vendor/symfony/security-http/Logout/LogoutUrlGenerator.php line 87

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\Security\Http\Logout;
  11. use Symfony\Component\HttpFoundation\RequestStack;
  12. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  13. use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
  14. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  15. use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
  16. /**
  17.  * Provides generator functions for the logout URL.
  18.  *
  19.  * @author Fabien Potencier <fabien@symfony.com>
  20.  * @author Jeremy Mikola <jmikola@gmail.com>
  21.  */
  22. class LogoutUrlGenerator
  23. {
  24.     private $requestStack;
  25.     private $router;
  26.     private $tokenStorage;
  27.     private $listeners = [];
  28.     /** @var string|null */
  29.     private $currentFirewallName;
  30.     /** @var string|null */
  31.     private $currentFirewallContext;
  32.     public function __construct(RequestStack $requestStack nullUrlGeneratorInterface $router nullTokenStorageInterface $tokenStorage null)
  33.     {
  34.         $this->requestStack $requestStack;
  35.         $this->router $router;
  36.         $this->tokenStorage $tokenStorage;
  37.     }
  38.     /**
  39.      * Registers a firewall's LogoutListener, allowing its URL to be generated.
  40.      *
  41.      * @param string      $key           The firewall key
  42.      * @param string      $logoutPath    The path that starts the logout process
  43.      * @param string|null $csrfTokenId   The ID of the CSRF token
  44.      * @param string|null $csrfParameter The CSRF token parameter name
  45.      * @param string|null $context       The listener context
  46.      */
  47.     public function registerListener(string $keystring $logoutPath, ?string $csrfTokenId, ?string $csrfParameterCsrfTokenManagerInterface $csrfTokenManager nullstring $context null)
  48.     {
  49.         $this->listeners[$key] = [$logoutPath$csrfTokenId$csrfParameter$csrfTokenManager$context];
  50.     }
  51.     /**
  52.      * Generates the absolute logout path for the firewall.
  53.      *
  54.      * @return string
  55.      */
  56.     public function getLogoutPath(string $key null)
  57.     {
  58.         return $this->generateLogoutUrl($keyUrlGeneratorInterface::ABSOLUTE_PATH);
  59.     }
  60.     /**
  61.      * Generates the absolute logout URL for the firewall.
  62.      *
  63.      * @return string
  64.      */
  65.     public function getLogoutUrl(string $key null)
  66.     {
  67.         return $this->generateLogoutUrl($keyUrlGeneratorInterface::ABSOLUTE_URL);
  68.     }
  69.     public function setCurrentFirewall(?string $keystring $context null)
  70.     {
  71.         $this->currentFirewallName $key;
  72.         $this->currentFirewallContext $context;
  73.     }
  74.     /**
  75.      * Generates the logout URL for the firewall.
  76.      */
  77.     private function generateLogoutUrl(?string $keyint $referenceType): string
  78.     {
  79.         [$logoutPath$csrfTokenId$csrfParameter$csrfTokenManager] = $this->getListener($key);
  80.         if (null === $logoutPath) {
  81.             throw new \LogicException('Unable to generate the logout URL without a path.');
  82.         }
  83.         $parameters null !== $csrfTokenManager ? [$csrfParameter => (string) $csrfTokenManager->getToken($csrfTokenId)] : [];
  84.         if ('/' === $logoutPath[0]) {
  85.             if (!$this->requestStack) {
  86.                 throw new \LogicException('Unable to generate the logout URL without a RequestStack.');
  87.             }
  88.             $request $this->requestStack->getCurrentRequest();
  89.             $url UrlGeneratorInterface::ABSOLUTE_URL === $referenceType $request->getUriForPath($logoutPath) : $request->getBaseUrl().$logoutPath;
  90.             if (!empty($parameters)) {
  91.                 $url .= '?'.http_build_query($parameters'''&');
  92.             }
  93.         } else {
  94.             if (!$this->router) {
  95.                 throw new \LogicException('Unable to generate the logout URL without a Router.');
  96.             }
  97.             $url $this->router->generate($logoutPath$parameters$referenceType);
  98.         }
  99.         return $url;
  100.     }
  101.     /**
  102.      * @throws \InvalidArgumentException if no LogoutListener is registered for the key or could not be found automatically
  103.      */
  104.     private function getListener(?string $key): array
  105.     {
  106.         if (null !== $key) {
  107.             if (isset($this->listeners[$key])) {
  108.                 return $this->listeners[$key];
  109.             }
  110.             throw new \InvalidArgumentException(sprintf('No LogoutListener found for firewall key "%s".'$key));
  111.         }
  112.         // Fetch the current provider key from token, if possible
  113.         if (null !== $this->tokenStorage) {
  114.             $token $this->tokenStorage->getToken();
  115.             // @deprecated since Symfony 5.4
  116.             if ($token instanceof AnonymousToken) {
  117.                 throw new \InvalidArgumentException('Unable to generate a logout url for an anonymous token.');
  118.             }
  119.             if (null !== $token) {
  120.                 if (method_exists($token'getFirewallName')) {
  121.                     $key $token->getFirewallName();
  122.                 } elseif (method_exists($token'getProviderKey')) {
  123.                     trigger_deprecation('symfony/security-http''5.2''Method "%s::getProviderKey()" has been deprecated, rename it to "getFirewallName()" instead.'\get_class($token));
  124.                     $key $token->getProviderKey();
  125.                 }
  126.                 if (isset($this->listeners[$key])) {
  127.                     return $this->listeners[$key];
  128.                 }
  129.             }
  130.         }
  131.         // Fetch from injected current firewall information, if possible
  132.         if (isset($this->listeners[$this->currentFirewallName])) {
  133.             return $this->listeners[$this->currentFirewallName];
  134.         }
  135.         foreach ($this->listeners as $listener) {
  136.             if (isset($listener[4]) && $this->currentFirewallContext === $listener[4]) {
  137.                 return $listener;
  138.             }
  139.         }
  140.         throw new \InvalidArgumentException('Unable to find the current firewall LogoutListener, please provide the provider key manually.');
  141.     }
  142. }