vendor/shopware/core/Framework/Script/Execution/ScriptLoader.php line 63

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\Script\Execution;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\DevOps\Environment\EnvironmentHelper;
  5. use Shopware\Core\Framework\Adapter\Cache\CacheCompressor;
  6. use Shopware\Core\Framework\App\Lifecycle\Persister\ScriptPersister;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Doctrine\FetchModeHelper;
  8. use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface;
  9. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  10. use Twig\Cache\FilesystemCache;
  11. /**
  12.  * @internal only for use by the app-system
  13.  */
  14. class ScriptLoader implements EventSubscriberInterface
  15. {
  16.     public const CACHE_KEY 'shopware-app-scripts';
  17.     private Connection $connection;
  18.     private string $cacheDir;
  19.     private ScriptPersister $scriptPersister;
  20.     private bool $debug;
  21.     private TagAwareAdapterInterface $cache;
  22.     public function __construct(Connection $connectionScriptPersister $scriptPersisterTagAwareAdapterInterface $cachestring $cacheDirbool $debug)
  23.     {
  24.         $this->connection $connection;
  25.         $this->cacheDir $cacheDir '/twig/scripts';
  26.         $this->scriptPersister $scriptPersister;
  27.         $this->debug $debug;
  28.         $this->cache $cache;
  29.     }
  30.     public static function getSubscribedEvents(): array
  31.     {
  32.         return ['script.written' => 'invalidateCache'];
  33.     }
  34.     /**
  35.      * @return Script[]
  36.      */
  37.     public function get(string $hook): array
  38.     {
  39.         $cacheItem $this->cache->getItem(self::CACHE_KEY);
  40.         if ($cacheItem->isHit() && $cacheItem->get() && !$this->debug) {
  41.             return CacheCompressor::uncompress($cacheItem)[$hook] ?? [];
  42.         }
  43.         $scripts $this->load();
  44.         $cacheItem CacheCompressor::compress($cacheItem$scripts);
  45.         $this->cache->save($cacheItem);
  46.         return $scripts[$hook] ?? [];
  47.     }
  48.     public function invalidateCache(): void
  49.     {
  50.         $this->cache->deleteItem(self::CACHE_KEY);
  51.     }
  52.     private function load(): array
  53.     {
  54.         if ($this->debug) {
  55.             $this->scriptPersister->refresh();
  56.         }
  57.         $scripts $this->connection->fetchAllAssociative("
  58.             SELECT LOWER(HEX(`script`.`app_id`)) as `app_id`,
  59.                    `script`.`name` AS scriptName,
  60.                    `script`.`script` AS script,
  61.                    `script`.`hook` AS hook,
  62.                    IFNULL(`script`.`updated_at`, `script`.`created_at`) AS lastModified,
  63.                    `app`.`name` AS appName,
  64.                    LOWER(HEX(`app`.`integration_id`)) AS integrationId,
  65.                    `app`.`version` AS appVersion,
  66.                    `script`.`active` AS active
  67.             FROM `script`
  68.             LEFT JOIN `app` ON `script`.`app_id` = `app`.`id`
  69.             WHERE `script`.`hook` != 'include'
  70.             ORDER BY `app`.`created_at`, `app`.`id`, `script`.`name`
  71.         ");
  72.         $includes $this->connection->fetchAllAssociative("
  73.             SELECT LOWER(HEX(`script`.`app_id`)) as `app_id`,
  74.                    `script`.`name` AS name,
  75.                    `script`.`script` AS script,
  76.                    `app`.`name` AS appName,
  77.                    LOWER(HEX(`app`.`integration_id`)) AS integrationId,
  78.                    IFNULL(`script`.`updated_at`, `script`.`created_at`) AS lastModified
  79.             FROM `script`
  80.             LEFT JOIN `app` ON `script`.`app_id` = `app`.`id`
  81.             WHERE `script`.`hook` = 'include'
  82.             ORDER BY `app`.`created_at`, `app`.`id`, `script`.`name`
  83.         ");
  84.         $allIncludes FetchModeHelper::group($includes);
  85.         $executableScripts = [];
  86.         /** @var array $script */
  87.         foreach ($scripts as $script) {
  88.             $appId $script['app_id'];
  89.             $includes $allIncludes[$appId] ?? [];
  90.             $dates array_merge([$script['lastModified']], array_column($includes'lastModified'));
  91.             /** @var \DateTimeInterface $lastModified */
  92.             $lastModified = new \DateTimeImmutable(max($dates));
  93.             /** @var string $cachePrefix */
  94.             $cachePrefix $script['appName'] ? md5($script['appName'] . $script['appVersion']) : EnvironmentHelper::getVariable('INSTANCE_ID''');
  95.             $includes array_map(function (array $script) use ($appId) {
  96.                 $script['app_id'] = $appId;
  97.                 return new Script(
  98.                     $script['name'],
  99.                     $script['script'],
  100.                     new \DateTimeImmutable($script['lastModified']),
  101.                     $this->getAppInfo($script)
  102.                 );
  103.             }, $includes);
  104.             $options = [];
  105.             if (!$this->debug) {
  106.                 $options['cache'] = new FilesystemCache($this->cacheDir '/' $cachePrefix);
  107.             } else {
  108.                 $options['debug'] = true;
  109.             }
  110.             $executableScripts[$script['hook']][] = new Script(
  111.                 $script['scriptName'],
  112.                 $script['script'],
  113.                 $lastModified,
  114.                 $this->getAppInfo($script),
  115.                 $options,
  116.                 $includes,
  117.                 (bool) $script['active']
  118.             );
  119.         }
  120.         return $executableScripts;
  121.     }
  122.     private function getAppInfo(array $script): ?ScriptAppInformation
  123.     {
  124.         if (!$script['app_id'] || !$script['appName'] || !$script['integrationId']) {
  125.             return null;
  126.         }
  127.         return new ScriptAppInformation(
  128.             $script['app_id'],
  129.             $script['appName'],
  130.             $script['integrationId']
  131.         );
  132.     }
  133. }