vendor/symfony/framework-bundle/Controller/ControllerNameParser.php line 82

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\Controller;
  11. use Symfony\Component\HttpKernel\Bundle\BundleInterface;
  12. use Symfony\Component\HttpKernel\KernelInterface;
  13. /**
  14.  * ControllerNameParser converts controller from the short notation a:b:c
  15.  * (BlogBundle:Post:index) to a fully-qualified class::method string
  16.  * (Bundle\BlogBundle\Controller\PostController::indexAction).
  17.  *
  18.  * @author Fabien Potencier <fabien@symfony.com>
  19.  *
  20.  * @deprecated since Symfony 4.1
  21.  */
  22. class ControllerNameParser
  23. {
  24.     protected $kernel;
  25.     public function __construct(KernelInterface $kernelbool $triggerDeprecation true)
  26.     {
  27.         $this->kernel $kernel;
  28.         if ($triggerDeprecation) {
  29.             @trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.1.'__CLASS__), E_USER_DEPRECATED);
  30.         }
  31.     }
  32.     /**
  33.      * Converts a short notation a:b:c to a class::method.
  34.      *
  35.      * @param string $controller A short notation controller (a:b:c)
  36.      *
  37.      * @return string A string in the class::method notation
  38.      *
  39.      * @throws \InvalidArgumentException when the specified bundle is not enabled
  40.      *                                   or the controller cannot be found
  41.      */
  42.     public function parse($controller)
  43.     {
  44.         if (> \func_num_args() || func_get_arg(1)) {
  45.             @trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.1.'__CLASS__), E_USER_DEPRECATED);
  46.         }
  47.         $parts explode(':'$controller);
  48.         if (!== \count($parts) || \in_array(''$partstrue)) {
  49.             throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "a:b:c" controller string.'$controller));
  50.         }
  51.         $originalController $controller;
  52.         list($bundleName$controller$action) = $parts;
  53.         $controller str_replace('/''\\'$controller);
  54.         try {
  55.             // this throws an exception if there is no such bundle
  56.             $bundle $this->kernel->getBundle($bundleName);
  57.         } catch (\InvalidArgumentException $e) {
  58.             $message sprintf(
  59.                 'The "%s" (from the _controller value "%s") does not exist or is not enabled in your kernel!',
  60.                 $bundleName,
  61.                 $originalController
  62.             );
  63.             if ($alternative $this->findAlternative($bundleName)) {
  64.                 $message .= sprintf(' Did you mean "%s:%s:%s"?'$alternative$controller$action);
  65.             }
  66.             throw new \InvalidArgumentException($message0$e);
  67.         }
  68.         $try $bundle->getNamespace().'\\Controller\\'.$controller.'Controller';
  69.         if (class_exists($try)) {
  70.             return $try.'::'.$action.'Action';
  71.         }
  72.         throw new \InvalidArgumentException(sprintf('The _controller value "%s:%s:%s" maps to a "%s" class, but this class was not found. Create this class or check the spelling of the class and its namespace.'$bundleName$controller$action$try));
  73.     }
  74.     /**
  75.      * Converts a class::method notation to a short one (a:b:c).
  76.      *
  77.      * @param string $controller A string in the class::method notation
  78.      *
  79.      * @return string A short notation controller (a:b:c)
  80.      *
  81.      * @throws \InvalidArgumentException when the controller is not valid or cannot be found in any bundle
  82.      */
  83.     public function build($controller)
  84.     {
  85.         @trigger_error(sprintf('The %s class is deprecated since Symfony 4.1.'__CLASS__), E_USER_DEPRECATED);
  86.         if (=== preg_match('#^(.*?\\\\Controller\\\\(.+)Controller)::(.+)Action$#'$controller$match)) {
  87.             throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "class::method" string.'$controller));
  88.         }
  89.         $className $match[1];
  90.         $controllerName $match[2];
  91.         $actionName $match[3];
  92.         foreach ($this->kernel->getBundles() as $name => $bundle) {
  93.             if (!== strpos($className$bundle->getNamespace())) {
  94.                 continue;
  95.             }
  96.             return sprintf('%s:%s:%s'$name$controllerName$actionName);
  97.         }
  98.         throw new \InvalidArgumentException(sprintf('Unable to find a bundle that defines controller "%s".'$controller));
  99.     }
  100.     /**
  101.      * Attempts to find a bundle that is *similar* to the given bundle name.
  102.      */
  103.     private function findAlternative(string $nonExistentBundleName): ?string
  104.     {
  105.         $bundleNames array_map(function (BundleInterface $b) {
  106.             return $b->getName();
  107.         }, $this->kernel->getBundles());
  108.         $alternative null;
  109.         $shortest null;
  110.         foreach ($bundleNames as $bundleName) {
  111.             // if there's a partial match, return it immediately
  112.             if (false !== strpos($bundleName$nonExistentBundleName)) {
  113.                 return $bundleName;
  114.             }
  115.             $lev levenshtein($nonExistentBundleName$bundleName);
  116.             if ($lev <= \strlen($nonExistentBundleName) / && (null === $alternative || $lev $shortest)) {
  117.                 $alternative $bundleName;
  118.                 $shortest $lev;
  119.             }
  120.         }
  121.         return $alternative;
  122.     }
  123. }