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