vendor/pimcore/pimcore/bundles/AdminBundle/Session/Handler/AdminSessionHandler.php line 92

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Enterprise License (PEL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  * @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  * @license    http://www.pimcore.org/license     GPLv3 and PEL
  13.  */
  14. namespace Pimcore\Bundle\AdminBundle\Session\Handler;
  15. use Pimcore\Session\Attribute\LockableAttributeBagInterface;
  16. use Psr\Log\LoggerAwareInterface;
  17. use Psr\Log\LoggerAwareTrait;
  18. use Symfony\Component\HttpFoundation\Request;
  19. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
  20. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  21. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  22. class AdminSessionHandler implements LoggerAwareInterfaceAdminSessionHandlerInterface
  23. {
  24.     use LoggerAwareTrait;
  25.     /**
  26.      * Contains how many sessions are currently open, this is important, because writeClose() must not be called if
  27.      * there is still an open session, this is especially important if something doesn't use the method use() but get()
  28.      * so the session isn't closed automatically after the action is done
  29.      */
  30.     private $openedSessions 0;
  31.     /**
  32.      * @var SessionInterface
  33.      */
  34.     protected $session;
  35.     protected $readOnlySessionBagsCache = [];
  36.     public function __construct(SessionInterface $session)
  37.     {
  38.         $this->session $session;
  39.     }
  40.     /**
  41.      * @inheritdoc
  42.      */
  43.     public function getSessionId()
  44.     {
  45.         if (!$this->session->isStarted()) {
  46.             // this is just to initialize the session :)
  47.             $this->useSession(static function (SessionInterface $session) {
  48.                 return $session->getId();
  49.             });
  50.         }
  51.         return $this->session->getId();
  52.     }
  53.     /**
  54.      * @inheritdoc
  55.      */
  56.     public function getSessionName()
  57.     {
  58.         return $this->session->getName();
  59.     }
  60.     /**
  61.      * @inheritdoc
  62.      */
  63.     public function useSession(callable $callable)
  64.     {
  65.         $session $this->loadSession();
  66.         $result call_user_func_array($callable, [$session]);
  67.         $this->writeClose();
  68.         $this->readOnlySessionBagsCache = []; // clear cache if session was modified manually
  69.         return $result;
  70.     }
  71.     /**
  72.      * @inheritdoc
  73.      */
  74.     public function useSessionAttributeBag(callable $callablestring $name 'pimcore_admin')
  75.     {
  76.         $session $this->loadSession();
  77.         $attributeBag $this->loadAttributeBag($name$session);
  78.         $result call_user_func_array($callable, [$attributeBag$session]);
  79.         $this->writeClose();
  80.         return $result;
  81.     }
  82.     /**
  83.      * @inheritdoc
  84.      */
  85.     public function getReadOnlyAttributeBag(string $name 'pimcore_admin'): AttributeBagInterface
  86.     {
  87.         if (isset($this->readOnlySessionBagsCache[$name])) {
  88.             $bag $this->readOnlySessionBagsCache[$name];
  89.         } else {
  90.             $bag $this->useSessionAttributeBag(function (AttributeBagInterface $bag) {
  91.                 return $bag;
  92.             }, $name);
  93.         }
  94.         if ($bag instanceof LockableAttributeBagInterface) {
  95.             $bag->lock();
  96.         }
  97.         return $bag;
  98.     }
  99.     /**
  100.      * @inheritdoc
  101.      */
  102.     public function invalidate(int $lifetime null): bool
  103.     {
  104.         return $this->session->invalidate($lifetime);
  105.     }
  106.     /**
  107.      * @inheritdoc
  108.      */
  109.     public function regenerateId(): bool
  110.     {
  111.         return $this->useSession(static function (SessionInterface $session) {
  112.             return $session->migrate(true);
  113.         });
  114.     }
  115.     /**
  116.      * @inheritdoc
  117.      */
  118.     public function loadAttributeBag(string $nameSessionInterface $session null): SessionBagInterface
  119.     {
  120.         if (null === $session) {
  121.             $session $this->loadSession();
  122.         }
  123.         $attributeBag $session->getBag($name);
  124.         if ($attributeBag instanceof LockableAttributeBagInterface) {
  125.             $attributeBag->unlock();
  126.         }
  127.         $this->readOnlySessionBagsCache[$name] = $attributeBag;
  128.         return $attributeBag;
  129.     }
  130.     /**
  131.      * @inheritdoc
  132.      */
  133.     public function requestHasSessionId(Request $requestbool $checkRequestParams false): bool
  134.     {
  135.         $sessionName $this->getSessionName();
  136.         if (empty($sessionName)) {
  137.             return false;
  138.         }
  139.         $properties = ['cookies'];
  140.         if ($checkRequestParams) {
  141.             $properties[] = 'request';
  142.             $properties[] = 'query';
  143.         }
  144.         foreach ($properties as $property) {
  145.             if ($request->$property->has($sessionName) && !empty($request->$property->get($sessionName))) {
  146.                 return true;
  147.             }
  148.         }
  149.         return false;
  150.     }
  151.     /**
  152.      * @inheritdoc
  153.      */
  154.     public function getSessionIdFromRequest(Request $requestbool $checkRequestParams false): string
  155.     {
  156.         if ($this->requestHasSessionId($request$checkRequestParams)) {
  157.             $sessionName $this->getSessionName();
  158.             if ($sessionId $request->cookies->get($sessionName)) {
  159.                 return $sessionId;
  160.             }
  161.             if ($checkRequestParams) {
  162.                 if ($sessionId $request->request->get($sessionName)) {
  163.                     return $sessionId;
  164.                 }
  165.                 if ($sessionId $request->query->get($sessionName)) {
  166.                     return $sessionId;
  167.                 }
  168.             }
  169.         }
  170.         throw new \RuntimeException('Failed to get session ID from request');
  171.     }
  172.     /**
  173.      * @inheritdoc
  174.      */
  175.     public function loadSession(): SessionInterface
  176.     {
  177.         $sessionName $this->getSessionName();
  178.         $this->logger->debug('Opening admin session {name}', ['name' => $sessionName]);
  179.         if (!$this->session->isStarted()) {
  180.             $this->session->start();
  181.         }
  182.         $this->openedSessions++;
  183.         $this->logger->debug('Admin session {name} was successfully opened. Open admin sessions: {count}', [
  184.             'name' => $sessionName,
  185.             'count' => $this->openedSessions
  186.         ]);
  187.         return $this->session;
  188.     }
  189.     /**
  190.      * @inheritdoc
  191.      */
  192.     public function writeClose()
  193.     {
  194.         $this->openedSessions--;
  195.         if (=== $this->openedSessions) {
  196.             $this->session->save();
  197.             $this->logger->debug('Admin session {name} was written and closed', [
  198.                 'name' => $this->getSessionName()
  199.             ]);
  200.         } else {
  201.             $this->logger->debug('Not writing/closing session admin session {name} as there are still {count} open sessions', [
  202.                 'name' => $this->getSessionName(),
  203.                 'count' => $this->openedSessions
  204.             ]);
  205.         }
  206.     }
  207. }