vendor/symfony/framework-bundle/Routing/DelegatingLoader.php line 61

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\Bundle\FrameworkBundle\Routing;
  11. use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
  12. use Symfony\Component\Config\Exception\LoaderLoadException;
  13. use Symfony\Component\Config\Loader\DelegatingLoader as BaseDelegatingLoader;
  14. use Symfony\Component\Config\Loader\LoaderResolverInterface;
  15. /**
  16.  * DelegatingLoader delegates route loading to other loaders using a loader resolver.
  17.  *
  18.  * This implementation resolves the _controller attribute from the short notation
  19.  * to the fully-qualified form (from a:b:c to class::method).
  20.  *
  21.  * @author Fabien Potencier <fabien@symfony.com>
  22.  *
  23.  * @final since Symfony 4.4
  24.  */
  25. class DelegatingLoader extends BaseDelegatingLoader
  26. {
  27.     /**
  28.      * @deprecated since Symfony 4.4
  29.      */
  30.     protected $parser;
  31.     private $loading false;
  32.     private $defaultOptions;
  33.     /**
  34.      * @param LoaderResolverInterface $resolver
  35.      * @param array                   $defaultOptions
  36.      */
  37.     public function __construct($resolver$defaultOptions = [])
  38.     {
  39.         if ($resolver instanceof ControllerNameParser) {
  40.             @trigger_error(sprintf('Passing a "%s" instance as first argument to "%s()" is deprecated since Symfony 4.4, pass a "%s" instance instead.'ControllerNameParser::class, __METHOD__LoaderResolverInterface::class), \E_USER_DEPRECATED);
  41.             $this->parser $resolver;
  42.             $resolver $defaultOptions;
  43.             $defaultOptions < \func_num_args() ? func_get_arg(2) : [];
  44.         } elseif (< \func_num_args() && func_get_arg(2) instanceof ControllerNameParser) {
  45.             $this->parser func_get_arg(2);
  46.         }
  47.         $this->defaultOptions $defaultOptions;
  48.         parent::__construct($resolver);
  49.     }
  50.     /**
  51.      * {@inheritdoc}
  52.      */
  53.     public function load($resource$type null)
  54.     {
  55.         if ($this->loading) {
  56.             // This can happen if a fatal error occurs in parent::load().
  57.             // Here is the scenario:
  58.             // - while routes are being loaded by parent::load() below, a fatal error
  59.             //   occurs (e.g. parse error in a controller while loading annotations);
  60.             // - PHP abruptly empties the stack trace, bypassing all catch/finally blocks;
  61.             //   it then calls the registered shutdown functions;
  62.             // - the ErrorHandler catches the fatal error and re-injects it for rendering
  63.             //   thanks to HttpKernel->terminateWithException() (that calls handleException());
  64.             // - at this stage, if we try to load the routes again, we must prevent
  65.             //   the fatal error from occurring a second time,
  66.             //   otherwise the PHP process would be killed immediately;
  67.             // - while rendering the exception page, the router can be required
  68.             //   (by e.g. the web profiler that needs to generate an URL);
  69.             // - this handles the case and prevents the second fatal error
  70.             //   by triggering an exception beforehand.
  71.             throw new LoaderLoadException($resourcenull0null$type);
  72.         }
  73.         $this->loading true;
  74.         try {
  75.             $collection parent::load($resource$type);
  76.         } finally {
  77.             $this->loading false;
  78.         }
  79.         foreach ($collection->all() as $route) {
  80.             if ($this->defaultOptions) {
  81.                 $route->setOptions($route->getOptions() + $this->defaultOptions);
  82.             }
  83.             if (!\is_string($controller $route->getDefault('_controller'))) {
  84.                 continue;
  85.             }
  86.             if (str_contains($controller'::')) {
  87.                 continue;
  88.             }
  89.             if ($this->parser && === substr_count($controller':')) {
  90.                 $deprecatedNotation $controller;
  91.                 try {
  92.                     $controller $this->parser->parse($controllerfalse);
  93.                     @trigger_error(sprintf('Referencing controllers with %s is deprecated since Symfony 4.1, use "%s" instead.'$deprecatedNotation$controller), \E_USER_DEPRECATED);
  94.                 } catch (\InvalidArgumentException $e) {
  95.                     // unable to optimize unknown notation
  96.                 }
  97.             }
  98.             $route->setDefault('_controller'$controller);
  99.         }
  100.         return $collection;
  101.     }
  102. }