custom/plugins/SwagPlatformSecurity/src/Fixes/NEXT23562/PatchedEntityTemplateLoader.php line 53

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Swag\Security\Fixes\NEXT23562;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Framework\Adapter\Twig\EntityTemplateLoader;
  5. use Shopware\Core\Framework\Feature;
  6. use Twig\Error\LoaderError;
  7. use Twig\Loader\LoaderInterface;
  8. use Twig\Source;
  9. class PatchedEntityTemplateLoader extends EntityTemplateLoader
  10. {
  11.     /**
  12.      * @var array<string, array<string, array{template: string, updatedAt: \DateTimeInterface|null}|null>>
  13.      */
  14.     private $databaseTemplateCache = [];
  15.     /**
  16.      * @var Connection
  17.      */
  18.     private $connection;
  19.     /**
  20.      * @var string
  21.      */
  22.     private $environment;
  23.     /**
  24.      * @var EntityTemplateLoader
  25.      */
  26.     private $original;
  27.     public function __construct(array $origArgsEntityTemplateLoader $originalConnection $connectionstring $environment)
  28.     {
  29.         parent::__construct(...$origArgs);
  30.         $this->original $original;
  31.         $this->connection $connection;
  32.         $this->environment $environment;
  33.     }
  34.     public function clearInternalCache(): void
  35.     {
  36.         Feature::triggerDeprecationOrThrow(
  37.             'v6.5.0.0',
  38.             Feature::deprecatedMethodMessage(__CLASS____METHOD__'v6.5.0.0''reset()')
  39.         );
  40.         $this->reset();
  41.     }
  42.     public function reset(): void
  43.     {
  44.         $this->databaseTemplateCache = [];
  45.     }
  46.     public function getSourceContext(/* string */ $name): Source
  47.     {
  48.         $template $this->findDatabaseTemplatePatched($name);
  49.         if (!$template) {
  50.             throw new LoaderError(sprintf('Template "%s" is not defined.'$name));
  51.         }
  52.         return new Source($template['template'], $name);
  53.     }
  54.     public function getCacheKey(/* string */ $name): string
  55.     {
  56.         return $name;
  57.     }
  58.     public function isFresh(/* string */ $name/* int */ $time): bool
  59.     {
  60.         $template $this->findDatabaseTemplatePatched($name);
  61.         if (!$template) {
  62.             return false;
  63.         }
  64.         return $template['updatedAt'] === null || $template['updatedAt']->getTimestamp() < $time;
  65.     }
  66.     /**
  67.      * @return bool
  68.      */
  69.     public function exists(/* string */ $name)
  70.     {
  71.         $template $this->findDatabaseTemplatePatched($name);
  72.         if (!$template) {
  73.             return false;
  74.         }
  75.         return true;
  76.     }
  77.     /**
  78.      * @return array{template: string, updatedAt: \DateTimeInterface|null}|null
  79.      */
  80.     private function findDatabaseTemplatePatched(string $name): ?array
  81.     {
  82.         if (isset($_ENV['DISABLE_EXTENSIONS']) && $_ENV['DISABLE_EXTENSIONS'] === false) {
  83.             return null;
  84.         }
  85.         /*
  86.          * In dev env app templates are directly loaded over the filesystem
  87.          * @see TwigLoaderConfigCompilerPass::addAppTemplatePaths()
  88.          */
  89.         if ($this->environment === 'dev') {
  90.             return null;
  91.         }
  92.         $templateName $this->splitTemplateName($name);
  93.         $namespace $templateName['namespace'];
  94.         $path $templateName['path'];
  95.         if (empty($this->databaseTemplateCache)) {
  96.             $query 'SELECT
  97.                         `app_template`.`path` AS `path`,
  98.                         `app_template`.`template` AS `template`,
  99.                         `app_template`.`updated_at` AS `updatedAt`,
  100.                         `app`.`name` AS `namespace`
  101.                     FROM `app_template`
  102.                     INNER JOIN `app` ON `app_template`.`app_id` = `app`.`id`
  103.                     WHERE `app_template`.`active` = 1 AND `app`.`active` = 1';
  104.             if (is_callable(
  105.                 [
  106.                     $this->connection,
  107.                     'fetchAllAssociative'
  108.                 ]
  109.             )) {
  110.                 /** @var array<array{path: string, template: string, updatedAt: string|null, namespace: string}> $templates */
  111.                 $templates $this->connection->fetchAllAssociative($query);
  112.             } else {
  113.                 $templates $this->connection->fetchAll($query);
  114.             }
  115.             foreach ($templates as $template) {
  116.                 $this->databaseTemplateCache[$template['path']][$template['namespace']] = [
  117.                     'template' => $template['template'],
  118.                     'updatedAt' => $template['updatedAt'] ? new \DateTimeImmutable($template['updatedAt']) : null,
  119.                 ];
  120.             }
  121.         }
  122.         if (\array_key_exists($path$this->databaseTemplateCache) && \array_key_exists($namespace$this->databaseTemplateCache[$path])) {
  123.             return $this->databaseTemplateCache[$path][$namespace];
  124.         }
  125.         /** @deprecated tag:v6.5.0 - only for intermediate backwards compatibility */
  126.         if (
  127.             \array_key_exists('../' $path$this->databaseTemplateCache)
  128.             && \array_key_exists($namespace$this->databaseTemplateCache['../' $path])
  129.         ) {
  130.             return $this->databaseTemplateCache['../' $path][$namespace];
  131.         }
  132.         // we have already loaded all DB templates
  133.         // if the namespace is not included return null
  134.         return $this->databaseTemplateCache[$path][$namespace] = null;
  135.     }
  136.     /**
  137.      * @return array{namespace: string, path: string}
  138.      */
  139.     private function splitTemplateName(string $template): array
  140.     {
  141.         // remove static template inheritance prefix
  142.         if (mb_strpos($template'@') !== 0) {
  143.             return ['path' => $template'namespace' => ''];
  144.         }
  145.         // remove "@"
  146.         $template mb_substr($template1);
  147.         $template explode('/'$template);
  148.         $namespace array_shift($template);
  149.         $template implode('/'$template);
  150.         return ['path' => $template'namespace' => $namespace];
  151.     }
  152. }