vendor/contao/core-bundle/src/HttpKernel/ModelArgumentResolver.php line 44

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. /*
  4.  * This file is part of Contao.
  5.  *
  6.  * (c) Leo Feyer
  7.  *
  8.  * @license LGPL-3.0-or-later
  9.  */
  10. namespace Contao\CoreBundle\HttpKernel;
  11. use Contao\CoreBundle\Framework\ContaoFramework;
  12. use Contao\CoreBundle\Routing\ScopeMatcher;
  13. use Contao\Model;
  14. use Contao\PageModel;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
  17. use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
  18. class ModelArgumentResolver implements ArgumentValueResolverInterface
  19. {
  20.     /**
  21.      * @var ContaoFramework
  22.      */
  23.     private $framework;
  24.     /**
  25.      * @var ScopeMatcher
  26.      */
  27.     private $scopeMatcher;
  28.     /**
  29.      * @internal Do not inherit from this class; decorate the "contao.model_argument_resolver" service instead
  30.      */
  31.     public function __construct(ContaoFramework $frameworkScopeMatcher $scopeMatcher)
  32.     {
  33.         $this->framework $framework;
  34.         $this->scopeMatcher $scopeMatcher;
  35.     }
  36.     public function supports(Request $requestArgumentMetadata $argument): bool
  37.     {
  38.         if (!$this->scopeMatcher->isContaoRequest($request)) {
  39.             return false;
  40.         }
  41.         $this->framework->initialize();
  42.         if (!is_a($argument->getType(), Model::class, true)) {
  43.             return false;
  44.         }
  45.         if (!$argument->isNullable() && null === $this->fetchModel($request$argument)) {
  46.             return false;
  47.         }
  48.         return true;
  49.     }
  50.     public function resolve(Request $requestArgumentMetadata $argument): \Generator
  51.     {
  52.         yield $this->fetchModel($request$argument);
  53.     }
  54.     private function fetchModel(Request $requestArgumentMetadata $argument): ?Model
  55.     {
  56.         $name $this->getArgumentName($request$argument);
  57.         if (null === $name) {
  58.             return null;
  59.         }
  60.         $value $request->attributes->get($name);
  61.         $type $argument->getType();
  62.         if ($type && $value instanceof $type) {
  63.             return $value;
  64.         }
  65.         // Special handling for pageModel that could be globally registered
  66.         if (
  67.             isset($GLOBALS['objPage'])
  68.             && $GLOBALS['objPage'] instanceof PageModel
  69.             && (int) $GLOBALS['objPage']->id === (int) $value
  70.             && is_a($typePageModel::class, true)
  71.         ) {
  72.             return $GLOBALS['objPage'];
  73.         }
  74.         /** @var Model $model */
  75.         $model $this->framework->getAdapter($argument->getType());
  76.         return $model->findByPk((int) $value);
  77.     }
  78.     /**
  79.      * Returns the argument name from the model class.
  80.      */
  81.     private function getArgumentName(Request $requestArgumentMetadata $argument): ?string
  82.     {
  83.         if ($request->attributes->has($argument->getName())) {
  84.             return $argument->getName();
  85.         }
  86.         $className lcfirst($this->stripNamespace($argument->getType()));
  87.         if ($request->attributes->has($className)) {
  88.             return $className;
  89.         }
  90.         return null;
  91.     }
  92.     /**
  93.      * Strips the namespace from a class name.
  94.      */
  95.     private function stripNamespace(string $fqcn): string
  96.     {
  97.         if (false !== ($pos strrpos($fqcn'\\'))) {
  98.             return substr($fqcn$pos 1);
  99.         }
  100.         return $fqcn;
  101.     }
  102. }