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