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

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.     private ContaoFramework $framework;
  21.     private ScopeMatcher $scopeMatcher;
  22.     /**
  23.      * @internal Do not inherit from this class; decorate the "contao.model_argument_resolver" service instead
  24.      */
  25.     public function __construct(ContaoFramework $frameworkScopeMatcher $scopeMatcher)
  26.     {
  27.         $this->framework $framework;
  28.         $this->scopeMatcher $scopeMatcher;
  29.     }
  30.     public function supports(Request $requestArgumentMetadata $argument): bool
  31.     {
  32.         if (!$this->scopeMatcher->isContaoRequest($request)) {
  33.             return false;
  34.         }
  35.         $this->framework->initialize();
  36.         if (!is_a($argument->getType(), Model::class, true)) {
  37.             return false;
  38.         }
  39.         if (!$argument->isNullable() && null === $this->fetchModel($request$argument)) {
  40.             return false;
  41.         }
  42.         return true;
  43.     }
  44.     public function resolve(Request $requestArgumentMetadata $argument): \Generator
  45.     {
  46.         yield $this->fetchModel($request$argument);
  47.     }
  48.     private function fetchModel(Request $requestArgumentMetadata $argument): ?Model
  49.     {
  50.         $name $this->getArgumentName($request$argument);
  51.         if (null === $name) {
  52.             return null;
  53.         }
  54.         /** @var class-string<Model> $type */
  55.         $type $argument->getType();
  56.         $value $request->attributes->get($name);
  57.         if ($type && $value instanceof $type) {
  58.             return $value;
  59.         }
  60.         // Special handling for pageModel that could be globally registered
  61.         if (
  62.             isset($GLOBALS['objPage'])
  63.             && $GLOBALS['objPage'] instanceof PageModel
  64.             && (int) $GLOBALS['objPage']->id === (int) $value
  65.             && is_a($typePageModel::class, true)
  66.         ) {
  67.             return $GLOBALS['objPage'];
  68.         }
  69.         /** @var Model $model */
  70.         $model $this->framework->getAdapter($type);
  71.         return $model->findByPk((int) $value);
  72.     }
  73.     /**
  74.      * Returns the argument name from the model class.
  75.      */
  76.     private function getArgumentName(Request $requestArgumentMetadata $argument): ?string
  77.     {
  78.         if ($request->attributes->has($argument->getName())) {
  79.             return $argument->getName();
  80.         }
  81.         $className lcfirst($this->stripNamespace($argument->getType()));
  82.         if ($request->attributes->has($className)) {
  83.             return $className;
  84.         }
  85.         return null;
  86.     }
  87.     /**
  88.      * Strips the namespace from a class name.
  89.      */
  90.     private function stripNamespace(string $fqcn): string
  91.     {
  92.         if (false !== ($pos strrpos($fqcn'\\'))) {
  93.             return substr($fqcn$pos 1);
  94.         }
  95.         return $fqcn;
  96.     }
  97. }