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

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($key$logoutPath$csrfTokenId$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.      * @param string|null $key The firewall key or null to use the current firewall key
  52.      *
  53.      * @return string The logout path
  54.      */
  55.     public function getLogoutPath($key null)
  56.     {
  57.         return $this->generateLogoutUrl($keyUrlGeneratorInterface::ABSOLUTE_PATH);
  58.     }
  59.     /**
  60.      * Generates the absolute logout URL for the firewall.
  61.      *
  62.      * @param string|null $key The firewall key or null to use the current firewall key
  63.      *
  64.      * @return string The logout URL
  65.      */
  66.     public function getLogoutUrl($key null)
  67.     {
  68.         return $this->generateLogoutUrl($keyUrlGeneratorInterface::ABSOLUTE_URL);
  69.     }
  70.     /**
  71.      * @param string|null $key     The current firewall key
  72.      * @param string|null $context The current firewall context
  73.      */
  74.     public function setCurrentFirewall($key$context null)
  75.     {
  76.         $this->currentFirewall = [$key$context];
  77.     }
  78.     /**
  79.      * Generates the logout URL for the firewall.
  80.      *
  81.      * @return string The logout URL
  82.      */
  83.     private function generateLogoutUrl(?string $keyint $referenceType): string
  84.     {
  85.         [$logoutPath$csrfTokenId$csrfParameter$csrfTokenManager] = $this->getListener($key);
  86.         if (null === $logoutPath) {
  87.             throw new \LogicException('Unable to generate the logout URL without a path.');
  88.         }
  89.         $parameters null !== $csrfTokenManager ? [$csrfParameter => (string) $csrfTokenManager->getToken($csrfTokenId)] : [];
  90.         if ('/' === $logoutPath[0]) {
  91.             if (!$this->requestStack) {
  92.                 throw new \LogicException('Unable to generate the logout URL without a RequestStack.');
  93.             }
  94.             $request $this->requestStack->getCurrentRequest();
  95.             $url UrlGeneratorInterface::ABSOLUTE_URL === $referenceType $request->getUriForPath($logoutPath) : $request->getBaseUrl().$logoutPath;
  96.             if (!empty($parameters)) {
  97.                 $url .= '?'.http_build_query($parameters'''&');
  98.             }
  99.         } else {
  100.             if (!$this->router) {
  101.                 throw new \LogicException('Unable to generate the logout URL without a Router.');
  102.             }
  103.             $url $this->router->generate($logoutPath$parameters$referenceType);
  104.         }
  105.         return $url;
  106.     }
  107.     /**
  108.      * @throws \InvalidArgumentException if no LogoutListener is registered for the key or could not be found automatically
  109.      */
  110.     private function getListener(?string $key): array
  111.     {
  112.         if (null !== $key) {
  113.             if (isset($this->listeners[$key])) {
  114.                 return $this->listeners[$key];
  115.             }
  116.             throw new \InvalidArgumentException(sprintf('No LogoutListener found for firewall key "%s".'$key));
  117.         }
  118.         // Fetch the current provider key from token, if possible
  119.         if (null !== $this->tokenStorage) {
  120.             $token $this->tokenStorage->getToken();
  121.             if ($token instanceof AnonymousToken) {
  122.                 throw new \InvalidArgumentException('Unable to generate a logout url for an anonymous token.');
  123.             }
  124.             if (null !== $token && method_exists($token'getProviderKey')) {
  125.                 $key $token->getProviderKey();
  126.                 if (isset($this->listeners[$key])) {
  127.                     return $this->listeners[$key];
  128.                 }
  129.             }
  130.         }
  131.         // Fetch from injected current firewall information, if possible
  132.         [$key$context] = $this->currentFirewall;
  133.         if (isset($this->listeners[$key])) {
  134.             return $this->listeners[$key];
  135.         }
  136.         foreach ($this->listeners as $listener) {
  137.             if (isset($listener[4]) && $context === $listener[4]) {
  138.                 return $listener;
  139.             }
  140.         }
  141.         throw new \InvalidArgumentException('Unable to find the current firewall LogoutListener, please provide the provider key manually.');
  142.     }
  143. }