src/Core/Framework/App/Lifecycle/Persister/ScriptPersister.php line 27

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\App\Lifecycle\Persister;
  3. use Shopware\Core\Framework\App\AppEntity;
  4. use Shopware\Core\Framework\App\Lifecycle\ScriptFileReaderInterface;
  5. use Shopware\Core\Framework\Context;
  6. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  9. use Shopware\Core\Framework\Log\Package;
  10. use Shopware\Core\Framework\Script\ScriptCollection;
  11. use Shopware\Core\Framework\Script\ScriptEntity;
  12. /**
  13.  * @internal only for use by the app-system
  14.  */
  15. #[Package('core')]
  16. class ScriptPersister
  17. {
  18.     public function __construct(private readonly ScriptFileReaderInterface $scriptReader, private readonly EntityRepository $scriptRepository, private readonly EntityRepository $appRepository)
  19.     {
  20.     }
  21.     public function updateScripts(string $appIdContext $context): void
  22.     {
  23.         $app $this->getAppWithExistingScripts($appId$context);
  24.         /** @var ScriptCollection $existingScripts */
  25.         $existingScripts $app->getScripts();
  26.         $scriptPaths $this->scriptReader->getScriptPathsForApp($app->getPath());
  27.         $upserts = [];
  28.         foreach ($scriptPaths as $scriptPath) {
  29.             $payload = [
  30.                 'script' => $this->scriptReader->getScriptContent($scriptPath$app->getPath()),
  31.             ];
  32.             /** @var ScriptEntity|null $existing */
  33.             $existing $existingScripts->filterByProperty('name'$scriptPath)->first();
  34.             if ($existing) {
  35.                 $existingScripts->remove($existing->getId());
  36.                 if ($existing->getScript() === $payload['script']) {
  37.                     // Don't update DB when content is identical
  38.                     continue;
  39.                 }
  40.                 $payload['id'] = $existing->getId();
  41.             } else {
  42.                 $payload['appId'] = $appId;
  43.                 $payload['active'] = $app->isActive();
  44.                 $payload['name'] = $scriptPath;
  45.                 $payload['hook'] = explode('/'$scriptPath)[0];
  46.             }
  47.             $upserts[] = $payload;
  48.         }
  49.         if (!empty($upserts)) {
  50.             $this->scriptRepository->upsert($upserts$context);
  51.         }
  52.         $this->deleteOldScripts($existingScripts$context);
  53.     }
  54.     public function activateAppScripts(string $appIdContext $context): void
  55.     {
  56.         $criteria = new Criteria();
  57.         $criteria->setTitle('app-scripts::activate');
  58.         $criteria->addFilter(new EqualsFilter('appId'$appId));
  59.         $criteria->addFilter(new EqualsFilter('active'false));
  60.         /** @var array<string> $scripts */
  61.         $scripts $this->scriptRepository->searchIds($criteria$context)->getIds();
  62.         $updateSet array_map(fn (string $id) => ['id' => $id'active' => true], $scripts);
  63.         $this->scriptRepository->update($updateSet$context);
  64.     }
  65.     public function deactivateAppScripts(string $appIdContext $context): void
  66.     {
  67.         $criteria = new Criteria();
  68.         $criteria->setTitle('app-scripts::deactivate');
  69.         $criteria->addFilter(new EqualsFilter('appId'$appId));
  70.         $criteria->addFilter(new EqualsFilter('active'true));
  71.         /** @var array<string> $scripts */
  72.         $scripts $this->scriptRepository->searchIds($criteria$context)->getIds();
  73.         $updateSet array_map(fn (string $id) => ['id' => $id'active' => false], $scripts);
  74.         $this->scriptRepository->update($updateSet$context);
  75.     }
  76.     public function refresh(): void
  77.     {
  78.         $criteria = new Criteria();
  79.         $criteria->setTitle('app-scripts::refresh');
  80.         $criteria->addFilter(new EqualsFilter('active'true));
  81.         $apps $this->appRepository->search($criteriaContext::createDefaultContext())->getEntities();
  82.         /** @var AppEntity $app */
  83.         foreach ($apps as $app) {
  84.             $this->updateScripts($app->getId(), Context::createDefaultContext());
  85.         }
  86.     }
  87.     private function deleteOldScripts(ScriptCollection $toBeRemovedContext $context): void
  88.     {
  89.         /** @var array<string> $ids */
  90.         $ids $toBeRemoved->getIds();
  91.         if (!empty($ids)) {
  92.             $ids array_map(static fn (string $id): array => ['id' => $id], array_values($ids));
  93.             $this->scriptRepository->delete($ids$context);
  94.         }
  95.     }
  96.     private function getAppWithExistingScripts(string $appIdContext $context): AppEntity
  97.     {
  98.         $criteria = new Criteria([$appId]);
  99.         $criteria->addAssociation('scripts');
  100.         /** @var AppEntity $app */
  101.         $app $this->appRepository->search($criteria$context)->first();
  102.         return $app;
  103.     }
  104. }