123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- <?php
- /*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Symfony\Bundle\FrameworkBundle\Routing;
- use Psr\Log\LoggerInterface;
- use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
- use Symfony\Component\Config\Exception\FileLoaderLoadException;
- use Symfony\Component\Config\Loader\DelegatingLoader as BaseDelegatingLoader;
- use Symfony\Component\Config\Loader\LoaderResolverInterface;
- /**
- * DelegatingLoader delegates route loading to other loaders using a loader resolver.
- *
- * This implementation resolves the _controller attribute from the short notation
- * to the fully-qualified form (from a:b:c to class::method).
- *
- * @author Fabien Potencier <fabien@symfony.com>
- */
- class DelegatingLoader extends BaseDelegatingLoader
- {
- protected $parser;
- protected $logger;
- private $loading = false;
- /**
- * Ability to pass a LoggerInterface instance as second argument will be removed in 3.0.
- *
- * @param ControllerNameParser $parser A ControllerNameParser instance
- * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance
- */
- public function __construct(ControllerNameParser $parser, $resolver, $r = null)
- {
- $this->parser = $parser;
- if (!$resolver instanceof LoaderResolverInterface) {
- $this->logger = $resolver;
- $resolver = $r;
- @trigger_error('Passing a LoggerInterface instance as the second argument of the '.__METHOD__.' method is deprecated since Symfony 2.8 and will not be supported anymore in 3.0.', E_USER_DEPRECATED);
- }
- parent::__construct($resolver);
- }
- /**
- * {@inheritdoc}
- */
- public function load($resource, $type = null)
- {
- if ($this->loading) {
- // This can happen if a fatal error occurs in parent::load().
- // Here is the scenario:
- // - while routes are being loaded by parent::load() below, a fatal error
- // occurs (e.g. parse error in a controller while loading annotations);
- // - PHP abruptly empties the stack trace, bypassing all catch blocks;
- // it then calls the registered shutdown functions;
- // - the ErrorHandler catches the fatal error and re-injects it for rendering
- // thanks to HttpKernel->terminateWithException() (that calls handleException());
- // - at this stage, if we try to load the routes again, we must prevent
- // the fatal error from occurring a second time,
- // otherwise the PHP process would be killed immediately;
- // - while rendering the exception page, the router can be required
- // (by e.g. the web profiler that needs to generate an URL);
- // - this handles the case and prevents the second fatal error
- // by triggering an exception beforehand.
- throw new FileLoaderLoadException($resource);
- }
- $this->loading = true;
- try {
- $collection = parent::load($resource, $type);
- } catch (\Exception $e) {
- $this->loading = false;
- throw $e;
- } catch (\Throwable $e) {
- $this->loading = false;
- throw $e;
- }
- $this->loading = false;
- foreach ($collection->all() as $route) {
- if (!\is_string($controller = $route->getDefault('_controller')) || !$controller) {
- continue;
- }
- try {
- $controller = $this->parser->parse($controller);
- } catch (\InvalidArgumentException $e) {
- // unable to optimize unknown notation
- }
- $route->setDefault('_controller', $controller);
- }
- return $collection;
- }
- }
|