Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\HttpFoundation\Session\Storage; Chris@0: Chris@0: /** Chris@0: * MockFileSessionStorage is used to mock sessions for Chris@0: * functional testing when done in a single PHP process. Chris@0: * Chris@0: * No PHP session is actually started since a session can be initialized Chris@0: * and shutdown only once per PHP execution cycle and this class does Chris@0: * not pollute any session related globals, including session_*() functions Chris@0: * or session.* PHP ini directives. Chris@0: * Chris@0: * @author Drak Chris@0: */ Chris@0: class MockFileSessionStorage extends MockArraySessionStorage Chris@0: { Chris@0: private $savePath; Chris@0: Chris@0: /** Chris@0: * @param string $savePath Path of directory to save session files Chris@0: * @param string $name Session name Chris@0: * @param MetadataBag $metaBag MetadataBag instance Chris@0: */ Chris@0: public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null) Chris@0: { Chris@0: if (null === $savePath) { Chris@0: $savePath = sys_get_temp_dir(); Chris@0: } Chris@0: Chris@0: if (!is_dir($savePath) && !@mkdir($savePath, 0777, true) && !is_dir($savePath)) { Chris@0: throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"', $savePath)); Chris@0: } Chris@0: Chris@0: $this->savePath = $savePath; Chris@0: Chris@0: parent::__construct($name, $metaBag); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function start() Chris@0: { Chris@0: if ($this->started) { Chris@0: return true; Chris@0: } Chris@0: Chris@0: if (!$this->id) { Chris@0: $this->id = $this->generateId(); Chris@0: } Chris@0: Chris@0: $this->read(); Chris@0: Chris@0: $this->started = true; Chris@0: Chris@0: return true; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function regenerate($destroy = false, $lifetime = null) Chris@0: { Chris@0: if (!$this->started) { Chris@0: $this->start(); Chris@0: } Chris@0: Chris@0: if ($destroy) { Chris@0: $this->destroy(); Chris@0: } Chris@0: Chris@0: return parent::regenerate($destroy, $lifetime); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function save() Chris@0: { Chris@0: if (!$this->started) { Chris@0: throw new \RuntimeException('Trying to save a session that was not started yet or was already closed'); Chris@0: } Chris@0: Chris@14: $data = $this->data; Chris@14: Chris@14: foreach ($this->bags as $bag) { Chris@14: if (empty($data[$key = $bag->getStorageKey()])) { Chris@14: unset($data[$key]); Chris@14: } Chris@14: } Chris@17: if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) { Chris@14: unset($data[$key]); Chris@14: } Chris@14: Chris@14: try { Chris@14: if ($data) { Chris@14: file_put_contents($this->getFilePath(), serialize($data)); Chris@14: } else { Chris@14: $this->destroy(); Chris@14: } Chris@14: } finally { Chris@14: $this->data = $data; Chris@14: } Chris@0: Chris@0: // this is needed for Silex, where the session object is re-used across requests Chris@0: // in functional tests. In Symfony, the container is rebooted, so we don't have Chris@0: // this issue Chris@0: $this->started = false; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Deletes a session from persistent storage. Chris@0: * Deliberately leaves session data in memory intact. Chris@0: */ Chris@0: private function destroy() Chris@0: { Chris@0: if (is_file($this->getFilePath())) { Chris@0: unlink($this->getFilePath()); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Calculate path to file. Chris@0: * Chris@0: * @return string File path Chris@0: */ Chris@0: private function getFilePath() Chris@0: { Chris@0: return $this->savePath.'/'.$this->id.'.mocksess'; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Reads session from storage and loads session. Chris@0: */ Chris@0: private function read() Chris@0: { Chris@0: $filePath = $this->getFilePath(); Chris@17: $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : []; Chris@0: Chris@0: $this->loadSession(); Chris@0: } Chris@0: }