vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php line 85

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\HttpFoundation\Session\Storage\Handler;
  11. use Symfony\Component\HttpFoundation\Session\SessionUtils;
  12. /**
  13.  * This abstract session handler provides a generic implementation
  14.  * of the PHP 7.0 SessionUpdateTimestampHandlerInterface,
  15.  * enabling strict and lazy session handling.
  16.  *
  17.  * @author Nicolas Grekas <p@tchwork.com>
  18.  */
  19. abstract class AbstractSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface
  20. {
  21.     private $sessionName;
  22.     private $prefetchId;
  23.     private $prefetchData;
  24.     private $newSessionId;
  25.     private $igbinaryEmptyData;
  26.     /**
  27.      * @return bool
  28.      */
  29.     #[\ReturnTypeWillChange]
  30.     public function open($savePath$sessionName)
  31.     {
  32.         $this->sessionName $sessionName;
  33.         if (!headers_sent() && !\ini_get('session.cache_limiter') && '0' !== \ini_get('session.cache_limiter')) {
  34.             header(sprintf('Cache-Control: max-age=%d, private, must-revalidate'60 * (int) \ini_get('session.cache_expire')));
  35.         }
  36.         return true;
  37.     }
  38.     /**
  39.      * @return string
  40.      */
  41.     abstract protected function doRead(string $sessionId);
  42.     /**
  43.      * @return bool
  44.      */
  45.     abstract protected function doWrite(string $sessionIdstring $data);
  46.     /**
  47.      * @return bool
  48.      */
  49.     abstract protected function doDestroy(string $sessionId);
  50.     /**
  51.      * @return bool
  52.      */
  53.     #[\ReturnTypeWillChange]
  54.     public function validateId($sessionId)
  55.     {
  56.         $this->prefetchData $this->read($sessionId);
  57.         $this->prefetchId $sessionId;
  58.         if (\PHP_VERSION_ID 70317 || (70400 <= \PHP_VERSION_ID && \PHP_VERSION_ID 70405)) {
  59.             // work around https://bugs.php.net/79413
  60.             foreach (debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) {
  61.                 if (!isset($frame['class']) && isset($frame['function']) && \in_array($frame['function'], ['session_regenerate_id''session_create_id'], true)) {
  62.                     return '' === $this->prefetchData;
  63.                 }
  64.             }
  65.         }
  66.         return '' !== $this->prefetchData;
  67.     }
  68.     /**
  69.      * @return string
  70.      */
  71.     #[\ReturnTypeWillChange]
  72.     public function read($sessionId)
  73.     {
  74.         if (null !== $this->prefetchId) {
  75.             $prefetchId $this->prefetchId;
  76.             $prefetchData $this->prefetchData;
  77.             $this->prefetchId $this->prefetchData null;
  78.             if ($prefetchId === $sessionId || '' === $prefetchData) {
  79.                 $this->newSessionId '' === $prefetchData $sessionId null;
  80.                 return $prefetchData;
  81.             }
  82.         }
  83.         $data $this->doRead($sessionId);
  84.         $this->newSessionId '' === $data $sessionId null;
  85.         return $data;
  86.     }
  87.     /**
  88.      * @return bool
  89.      */
  90.     #[\ReturnTypeWillChange]
  91.     public function write($sessionId$data)
  92.     {
  93.         if (null === $this->igbinaryEmptyData) {
  94.             // see https://github.com/igbinary/igbinary/issues/146
  95.             $this->igbinaryEmptyData = \function_exists('igbinary_serialize') ? igbinary_serialize([]) : '';
  96.         }
  97.         if ('' === $data || $this->igbinaryEmptyData === $data) {
  98.             return $this->destroy($sessionId);
  99.         }
  100.         $this->newSessionId null;
  101.         return $this->doWrite($sessionId$data);
  102.     }
  103.     /**
  104.      * @return bool
  105.      */
  106.     #[\ReturnTypeWillChange]
  107.     public function destroy($sessionId)
  108.     {
  109.         if (!headers_sent() && filter_var(\ini_get('session.use_cookies'), \FILTER_VALIDATE_BOOLEAN)) {
  110.             if (!$this->sessionName) {
  111.                 throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', static::class));
  112.             }
  113.             $cookie SessionUtils::popSessionCookie($this->sessionName$sessionId);
  114.             /*
  115.              * We send an invalidation Set-Cookie header (zero lifetime)
  116.              * when either the session was started or a cookie with
  117.              * the session name was sent by the client (in which case
  118.              * we know it's invalid as a valid session cookie would've
  119.              * started the session).
  120.              */
  121.             if (null === $cookie || isset($_COOKIE[$this->sessionName])) {
  122.                 if (\PHP_VERSION_ID 70300) {
  123.                     setcookie($this->sessionName''0, \ini_get('session.cookie_path'), \ini_get('session.cookie_domain'), filter_var(\ini_get('session.cookie_secure'), \FILTER_VALIDATE_BOOLEAN), filter_var(\ini_get('session.cookie_httponly'), \FILTER_VALIDATE_BOOLEAN));
  124.                 } else {
  125.                     $params session_get_cookie_params();
  126.                     unset($params['lifetime']);
  127.                     setcookie($this->sessionName''$params);
  128.                 }
  129.             }
  130.         }
  131.         return $this->newSessionId === $sessionId || $this->doDestroy($sessionId);
  132.     }
  133. }