# MockArraySessionStorage

class MockArraySessionStorage implements SessionStorageInterface

MockArraySessionStorage mocks the session for unit tests.

No PHP session is actually started since a session can be initialized and shutdown only once per PHP execution cycle.

When doing functional testing, you should use MockFileSessionStorage instead.

## Properties

`protected string` | `$id` |  |
`protected string` | `$name` |  |
`protected bool` | `$started` |  |
`protected bool` | `$closed` |  |
`protected array` | `$data` |  |
`protected MetadataBag` | `$metadataBag` |  |
`protected array|SessionBagInterface[]` | `$bags` |  |

## Methods

`public` | `` | `__construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null)` | No description |
`public` | `` | `setSessionData(array $array)` | No description |
`public` | `bool` | `start()` | Starts the session. |
`public` | `bool` | `regenerate(bool $destroy = false, int $lifetime = null)` | Regenerates id that represents this storage. |
`public` | `string` | `getId()` | Returns the session ID. |
`public` | `` | `setId(string $id)` | Sets the session ID. |
`public` | `mixed` | `getName()` | Returns the session name. |
`public` | `` | `setName(string $name)` | Sets the session name. |
`public` | `` | `save()` | Force the session to be saved and closed. |
`public` | `` | `clear()` | Clear all session data in memory. |
`public` | `` | `registerBag(SessionBagInterface $bag)` | Registers a SessionBagInterface for use. |
`public` | `SessionBagInterface` | `getBag(string $name)` | Gets a SessionBagInterface by name. |
`public` | `bool` | `isStarted()` | Checks if the session is started. |
`public` | `` | `setMetadataBag(MetadataBag $bag = null)` | No description |
`public` | `MetadataBag` | `getMetadataBag()` | Gets the MetadataBag. |
`protected` | `string` | `generateId()` | Generates a session ID. |
`protected` | `` | `loadSession()` | No description |

## Details

at line 65

### `__construct()`

`public __construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null)`

#### Parameters

`string` | `$name` |
`MetadataBag` | `$metaBag` |

at line 71

### `setSessionData()`

`public setSessionData(array $array)`

#### Parameters

`array` | `$array` |

at line 79

### `start()`

`public bool start()`

Starts the session.

#### Return Value

`bool` | True if started

#### Exceptions

RuntimeException | if something goes wrong starting the session

at line 97

### `regenerate()`

`public bool regenerate(bool $destroy = false, int $lifetime = null)`

Regenerates id that represents this storage.

This method must invoke session_regenerate_id($destroy) unless this interface is used for a storage object designed for unit or functional testing where a real PHP session would interfere with testing.

Note regenerate+destroy should not clear the session data in memory only delete the session data from persistent storage.

Care: When regenerating the session ID no locking is involved in PHP's session design. See https://bugs.php.net/bug.php?id=61470 for a discussion. So you must make sure the regenerated session is saved BEFORE sending the headers with the new ID. Symfony's HttpKernel offers a listener for this. See Symfony\Component\HttpKernel\EventListener\SaveSessionListener. Otherwise session data could get lost again for concurrent requests with the new ID. One result could be that you get logged out after just logging in.

#### Parameters

`bool` | `$destroy` | Destroy session when regenerating?
`int` | `$lifetime` | Sets the cookie lifetime for the session cookie. A null value will leave the system settings unchanged, 0 sets the cookie to expire with browser session. Time is in seconds, and is not a Unix timestamp.

#### Return Value

`bool` | True if session regenerated, false if error

#### Exceptions

RuntimeException | If an error occurs while regenerating this storage

at line 112

### `getId()`

`public string getId()`

Returns the session ID.

#### Return Value

`string` | The session ID or empty

at line 120

### `setId()`

`public setId(string $id)`

Sets the session ID.

#### Parameters

`string` | `$id` |

at line 132

### `getName()`

`public mixed getName()`

Returns the session name.

#### Return Value

`mixed` | The session name

at line 140

### `setName()`

`public setName(string $name)`

Sets the session name.

#### Parameters

`string` | `$name` |

at line 148

### `save()`

`public save()`

Force the session to be saved and closed.

This method must invoke session_write_close() unless this interface is used for a storage object design for unit or functional testing where a real PHP session would interfere with testing, in which case it should actually persist the session data if required.

#### Exceptions

RuntimeException | if the session is saved without being started, or if the session is already closed

at line 161

### `clear()`

`public clear()`

Clear all session data in memory.

at line 178

### `registerBag()`

`public registerBag(SessionBagInterface $bag)`

Registers a SessionBagInterface for use.

#### Parameters

`SessionBagInterface` | `$bag` |

at line 186

### `getBag()`

`public SessionBagInterface getBag(string $name)`

Gets a SessionBagInterface by name.

#### Parameters

`string` | `$name` |

#### Return Value

`SessionBagInterface` |

#### Exceptions

InvalidArgumentException | If the bag does not exist

at line 202

### `isStarted()`

`public bool isStarted()`

Checks if the session is started.

#### Return Value

`bool` | True if started, false otherwise

at line 207

### `setMetadataBag()`

`public setMetadataBag(MetadataBag $bag = null)`

#### Parameters

`MetadataBag` | `$bag` |

at line 221

### `getMetadataBag()`

`public MetadataBag getMetadataBag()`

Gets the MetadataBag.

#### Return Value

`MetadataBag` |

at line 234

### `generateId()`

`protected string generateId()`

Generates a session ID.

This doesn't need to be particularly cryptographically secure since this is just a mock.

#### Return Value

`string` |

at line 239

### `loadSession()`

`protected loadSession()`

## Source code

    <?php

    /*
     * This file is part of the Symfony package.
     *
     * (c) Fabien Potencier <fabien@symfony.com>
     *
     * For the full copyright and license information, please view the LICENSE
     * file that was distributed with this source code.
     */

    namespace Symfony\Component\HttpFoundation\Session\Storage;

    use Symfony\Component\HttpFoundation\Session\SessionBagInterface;

    /**
     * MockArraySessionStorage mocks the session for unit tests.
     *
     * No PHP session is actually started since a session can be initialized
     * and shutdown only once per PHP execution cycle.
     *
     * When doing functional testing, you should use MockFileSessionStorage instead.
     *
     * @author Fabien Potencier <fabien@symfony.com>
     * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
     * @author Drak <drak@zikula.org>
     */
    class MockArraySessionStorage implements SessionStorageInterface
    {
        /**
         * @var string
         */
        protected $id = '';

        /**
         * @var string
         */
        protected $name;

        /**
         * @var bool
         */
        protected $started = false;

        /**
         * @var bool
         */
        protected $closed = false;

        /**
         * @var array
         */
        protected $data = array();

        /**
         * @var MetadataBag
         */
        protected $metadataBag;

        /**
         * @var array|SessionBagInterface[]
         */
        protected $bags = array();

        public function __construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null)
        {
            $this->name = $name;
            $this->setMetadataBag($metaBag);
        }

        public function setSessionData(array $array)
        {
            $this->data = $array;
        }

        /**
         * {@inheritdoc}
         */
        public function start()
        {
            if ($this->started) {
                return true;
            }

            if (empty($this->id)) {
                $this->id = $this->generateId();
            }

            $this->loadSession();

            return true;
        }

        /**
         * {@inheritdoc}
         */
        public function regenerate($destroy = false, $lifetime = null)
        {
            if (!$this->started) {
                $this->start();
            }

            $this->metadataBag->stampNew($lifetime);
            $this->id = $this->generateId();

            return true;
        }

        /**
         * {@inheritdoc}
         */
        public function getId()
        {
            return $this->id;
        }

        /**
         * {@inheritdoc}
         */
        public function setId($id)
        {
            if ($this->started) {
                throw new \LogicException('Cannot set session ID after the session has started.');
            }

            $this->id = $id;
        }

        /**
         * {@inheritdoc}
         */
        public function getName()
        {
            return $this->name;
        }

        /**
         * {@inheritdoc}
         */
        public function setName($name)
        {
            $this->name = $name;
        }

        /**
         * {@inheritdoc}
         */
        public function save()
        {
            if (!$this->started || $this->closed) {
                throw new \RuntimeException('Trying to save a session that was not started yet or was already closed');
            }
            // nothing to do since we don't persist the session data
            $this->closed = false;
            $this->started = false;
        }

        /**
         * {@inheritdoc}
         */
        public function clear()
        {
            // clear out the bags
            foreach ($this->bags as $bag) {
                $bag->clear();
            }

            // clear out the session
            $this->data = array();

            // reconnect the bags to the session
            $this->loadSession();
        }

        /**
         * {@inheritdoc}
         */
        public function registerBag(SessionBagInterface $bag)
        {
            $this->bags[$bag->getName()] = $bag;
        }

        /**
         * {@inheritdoc}
         */
        public function getBag($name)
        {
            if (!isset($this->bags[$name])) {
                throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
            }

            if (!$this->started) {
                $this->start();
            }

            return $this->bags[$name];
        }

        /**
         * {@inheritdoc}
         */
        public function isStarted()
        {
            return $this->started;
        }

        public function setMetadataBag(MetadataBag $bag = null)
        {
            if (null === $bag) {
                $bag = new MetadataBag();
            }

            $this->metadataBag = $bag;
        }

        /**
         * Gets the MetadataBag.
         *
         * @return MetadataBag
         */
        public function getMetadataBag()
        {
            return $this->metadataBag;
        }

        /**
         * Generates a session ID.
         *
         * This doesn't need to be particularly cryptographically secure since this is just
         * a mock.
         *
         * @return string
         */
        protected function generateId()
        {
            return hash('sha256', uniqid('ss_mock_', true));
        }

        protected function loadSession()
        {
            $bags = array_merge($this->bags, array($this->metadataBag));

            foreach ($bags as $bag) {
                $key = $bag->getStorageKey();
                $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array();
                $bag->initialize($this->data[$key]);
            }

            $this->started = true;
            $this->closed = false;
        }
    }