MockFileSessionStorage

class MockFileSessionStorage extends MockArraySessionStorage

MockFileSessionStorage is used to mock sessions for functional testing when done in a single PHP process.

No PHP session is actually started since a session can be initialized and shutdown only once per PHP execution cycle and this class does not pollute any session related globals, including session_() functions or session. PHP ini directives.

Properties

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

Methods

public __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) No description
public setSessionData(array $array) No description from MockArraySessionStorage
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. from MockArraySessionStorage
public setId(string $id) Sets the session ID. from MockArraySessionStorage
public mixed getName() Returns the session name. from MockArraySessionStorage
public setName(string $name) Sets the session name. from MockArraySessionStorage
public save() Force the session to be saved and closed.
public clear() Clear all session data in memory. from MockArraySessionStorage
public registerBag(SessionBagInterface $bag) Registers a SessionBagInterface for use. from MockArraySessionStorage
public SessionBagInterface getBag(string $name) Gets a SessionBagInterface by name. from MockArraySessionStorage
public bool isStarted() Checks if the session is started. from MockArraySessionStorage
public setMetadataBag(MetadataBag $bag = null) No description from MockArraySessionStorage
public MetadataBag getMetadataBag() Gets the MetadataBag. from MockArraySessionStorage
protected string generateId() Generates a session ID. from MockArraySessionStorage
protected loadSession() No description from MockArraySessionStorage

Details

at line 34

__construct()

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

Parameters

string $savePath Path of directory to save session files
string $name
MetadataBag $metaBag
in MockArraySessionStorage at line 71

setSessionData()

public setSessionData(array $array)

Parameters

array $array
at line 52

start()

public bool start()

Starts the session.

Return Value

bool True if started

Exceptions

RuntimeException if something goes wrong starting the session
at line 72

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
in MockArraySessionStorage at line 112

getId()

public string getId()

Returns the session ID.

Return Value

string The session ID or empty
in MockArraySessionStorage at line 120

setId()

public setId(string $id)

Sets the session ID.

Parameters

string $id
in MockArraySessionStorage at line 132

getName()

public mixed getName()

Returns the session name.

Return Value

mixed The session name
in MockArraySessionStorage at line 140

setName()

public setName(string $name)

Sets the session name.

Parameters

string $name
at line 88

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
in MockArraySessionStorage at line 161

clear()

public clear()

Clear all session data in memory.

in MockArraySessionStorage at line 178

registerBag()

public registerBag(SessionBagInterface $bag)

Registers a SessionBagInterface for use.

Parameters

SessionBagInterface $bag
in MockArraySessionStorage 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
in MockArraySessionStorage at line 202

isStarted()

public bool isStarted()

Checks if the session is started.

Return Value

bool True if started, false otherwise
in MockArraySessionStorage at line 207

setMetadataBag()

public setMetadataBag(MetadataBag $bag = null)

Parameters

MetadataBag $bag
in MockArraySessionStorage at line 221

getMetadataBag()

public MetadataBag getMetadataBag()

Gets the MetadataBag.

Return Value

MetadataBag
in MockArraySessionStorage 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
in MockArraySessionStorage 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;

/**
 * MockFileSessionStorage is used to mock sessions for
 * functional testing when done in a single PHP process.
 *
 * No PHP session is actually started since a session can be initialized
 * and shutdown only once per PHP execution cycle and this class does
 * not pollute any session related globals, including session_*() functions
 * or session.* PHP ini directives.
 *
 * @author Drak <drak@zikula.org>
 */
class MockFileSessionStorage extends MockArraySessionStorage
{
    private $savePath;

    /**
     * @param string      $savePath Path of directory to save session files
     * @param string      $name     Session name
     * @param MetadataBag $metaBag  MetadataBag instance
     */
    public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null)
    {
        if (null === $savePath) {
            $savePath = sys_get_temp_dir();
        }

        if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) {
            throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $savePath));
        }

        $this->savePath = $savePath;

        parent::__construct($name, $metaBag);
    }

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

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

        $this->read();

        $this->started = true;

        return true;
    }

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

        if ($destroy) {
            $this->destroy();
        }

        return parent::regenerate($destroy, $lifetime);
    }

    /**
     * {@inheritdoc}
     */
    public function save()
    {
        if (!$this->started) {
            throw new \RuntimeException('Trying to save a session that was not started yet or was already closed');
        }

        $data = $this->data;

        foreach ($this->bags as $bag) {
            if (empty($data[$key = $bag->getStorageKey()])) {
                unset($data[$key]);
            }
        }
        if (array($key = $this->metadataBag->getStorageKey()) === array_keys($data)) {
            unset($data[$key]);
        }

        try {
            if ($data) {
                file_put_contents($this->getFilePath(), serialize($data));
            } else {
                $this->destroy();
            }
        } finally {
            $this->data = $data;
        }

        // this is needed for Silex, where the session object is re-used across requests
        // in functional tests. In Symfony, the container is rebooted, so we don't have
        // this issue
        $this->started = false;
    }

    /**
     * Deletes a session from persistent storage.
     * Deliberately leaves session data in memory intact.
     */
    private function destroy()
    {
        if (is_file($this->getFilePath())) {
            unlink($this->getFilePath());
        }
    }

    /**
     * Calculate path to file.
     *
     * @return string File path
     */
    private function getFilePath()
    {
        return $this->savePath.'/'.$this->id.'.mocksess';
    }

    /**
     * Reads session from storage and loads session.
     */
    private function read()
    {
        $filePath = $this->getFilePath();
        $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : array();

        $this->loadSession();
    }
}