* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Routing\RequestContextAwareInterface; /** * Initializes the locale based on the current request. * * This listener works in 2 modes: * * * 2.3 compatibility mode where you must call setRequest whenever the Request changes. * * 2.4+ mode where you must pass a RequestStack instance in the constructor. * * @author Fabien Potencier */ class LocaleListener implements EventSubscriberInterface { private $router; private $defaultLocale; private $requestStack; /** * RequestStack will become required in 3.0. * * @param RequestStack $requestStack A RequestStack instance * @param string $defaultLocale The default locale * @param RequestContextAwareInterface|null $router The router * * @throws \InvalidArgumentException */ public function __construct($requestStack = null, $defaultLocale = 'en', $router = null) { if ((null !== $requestStack && !$requestStack instanceof RequestStack) || $defaultLocale instanceof RequestContextAwareInterface || $router instanceof RequestStack) { $tmp = $router; $router = \func_num_args() < 2 ? null : $defaultLocale; $defaultLocale = $requestStack; $requestStack = \func_num_args() < 3 ? null : $tmp; @trigger_error('The '.__METHOD__.' method now requires a RequestStack to be given as first argument as '.__CLASS__.'::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED); } elseif (!$requestStack instanceof RequestStack) { @trigger_error('The '.__METHOD__.' method now requires a RequestStack instance as '.__CLASS__.'::setRequest method will not be supported anymore in 3.0.', E_USER_DEPRECATED); } if (null !== $requestStack && !$requestStack instanceof RequestStack) { throw new \InvalidArgumentException('RequestStack instance expected.'); } if (null !== $router && !$router instanceof RequestContextAwareInterface) { throw new \InvalidArgumentException('Router must implement RequestContextAwareInterface.'); } $this->defaultLocale = $defaultLocale; $this->requestStack = $requestStack; $this->router = $router; } /** * Sets the current Request. * * This method was used to synchronize the Request, but as the HttpKernel * is doing that automatically now, you should never call it directly. * It is kept public for BC with the 2.3 version. * * @param Request|null $request A Request instance * * @deprecated since version 2.4, to be removed in 3.0. */ public function setRequest(Request $request = null) { @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.4 and will be removed in 3.0.', E_USER_DEPRECATED); if (null === $request) { return; } $this->setLocale($request); $this->setRouterContext($request); } public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); $request->setDefaultLocale($this->defaultLocale); $this->setLocale($request); $this->setRouterContext($request); } public function onKernelFinishRequest(FinishRequestEvent $event) { if (null === $this->requestStack) { return; // removed when requestStack is required } if (null !== $parentRequest = $this->requestStack->getParentRequest()) { $this->setRouterContext($parentRequest); } } private function setLocale(Request $request) { if ($locale = $request->attributes->get('_locale')) { $request->setLocale($locale); } } private function setRouterContext(Request $request) { if (null !== $this->router) { $this->router->getContext()->setParameter('_locale', $request->getLocale()); } } public static function getSubscribedEvents() { return array( // must be registered after the Router to have access to the _locale KernelEvents::REQUEST => array(array('onKernelRequest', 16)), KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)), ); } }