vendor/shopware/core/Content/Cms/Subscriber/UnusedMediaSubscriber.php line 30

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Cms\Subscriber;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Content\Media\Event\UnusedMediaSearchEvent;
  5. use Shopware\Core\Framework\Log\Package;
  6. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  7. /**
  8.  * @internal
  9.  *
  10.  * @codeCoverageIgnore This would be useless as a unit test. It is integration tested here: \Shopware\Tests\Integration\Core\Content\Cms\Subscriber\UnusedMediaSubscriberTest
  11.  */
  12. #[Package('content')]
  13. class UnusedMediaSubscriber implements EventSubscriberInterface
  14. {
  15.     public function __construct(
  16.         private readonly Connection $connection
  17.     ) {
  18.     }
  19.     public static function getSubscribedEvents(): array
  20.     {
  21.         return [
  22.             UnusedMediaSearchEvent::class => 'removeUsedMedia',
  23.         ];
  24.     }
  25.     public function removeUsedMedia(UnusedMediaSearchEvent $event): void
  26.     {
  27.         $event->markAsUsed($this->findMediaIdsInImageGalleries($event));
  28.         $event->markAsUsed($this->findMediaIdsInImages($event));
  29.         foreach (['category_translation''product_translation'] as $table) {
  30.             $event->markAsUsed($this->findMediaIdsInImageGalleriesInOverridesTable($table$event));
  31.             $event->markAsUsed($this->findMediaIdsInImagesInOverridesTable($table$event));
  32.         }
  33.     }
  34.     /**
  35.      * @return array<string>
  36.      */
  37.     private function findMediaIdsInImageGalleriesInOverridesTable(string $tableUnusedMediaSearchEvent $event): array
  38.     {
  39.         $sql = <<<SQL
  40.         SELECT JSON_EXTRACT(slot_config, "$.*.sliderItems.value[*].mediaId") as mediaId
  41.         FROM $table
  42.         WHERE JSON_OVERLAPS(
  43.             JSON_EXTRACT(slot_config, "$.*.sliderItems.value[*].mediaId"),
  44.             JSON_ARRAY(%s)
  45.         );
  46.         SQL;
  47.         return $this->executeQueryWithIds($sql$event);
  48.     }
  49.     /**
  50.      * @return array<string>
  51.      */
  52.     private function findMediaIdsInImagesInOverridesTable(string $tableUnusedMediaSearchEvent $event): array
  53.     {
  54.         $sql = <<<SQL
  55.         SELECT JSON_EXTRACT(slot_config, "$.*.media.value") as mediaId
  56.         FROM $table
  57.         WHERE JSON_OVERLAPS(
  58.             JSON_EXTRACT(slot_config, "$.*.media.value"),
  59.             JSON_ARRAY(%s)
  60.         );
  61.         SQL;
  62.         return $this->executeQueryWithIds($sql$event);
  63.     }
  64.     /**
  65.      * @return array<string>
  66.      */
  67.     private function findMediaIdsInImageGalleries(UnusedMediaSearchEvent $event): array
  68.     {
  69.         $sql = <<<SQL
  70.         SELECT JSON_EXTRACT(config, "$.sliderItems.value[*].mediaId") as mediaId
  71.         FROM cms_slot_translation
  72.         INNER JOIN cms_slot ON (cms_slot_translation.cms_slot_id = cms_slot.id)
  73.         WHERE (cms_slot.type = 'image-slider' OR cms_slot.type = 'image-gallery')
  74.         AND JSON_OVERLAPS(
  75.             JSON_EXTRACT(config, "$.sliderItems.value[*].mediaId"),
  76.             JSON_ARRAY(%s)
  77.         );
  78.         SQL;
  79.         return $this->executeQueryWithIds($sql$event);
  80.     }
  81.     /**
  82.      * @return array<string>
  83.      */
  84.     private function findMediaIdsInImages(UnusedMediaSearchEvent $event): array
  85.     {
  86.         $sql = <<<SQL
  87.         SELECT JSON_ARRAY(JSON_EXTRACT(config, "$.media.value")) as mediaId
  88.         FROM cms_slot_translation
  89.         INNER JOIN cms_slot ON (cms_slot_translation.cms_slot_id = cms_slot.id)
  90.         WHERE cms_slot.type = 'image'
  91.         AND JSON_OVERLAPS(
  92.             JSON_EXTRACT(config, "$.media.value"),
  93.             JSON_ARRAY(%s)
  94.         );
  95.         SQL;
  96.         return $this->executeQueryWithIds($sql$event);
  97.     }
  98.     /**
  99.      * @return array<string>
  100.      */
  101.     private function executeQueryWithIds(string $sqlUnusedMediaSearchEvent $event): array
  102.     {
  103.         $result $this->connection->fetchFirstColumn(
  104.             sprintf($sqlimplode(','array_map(fn (string $id) => sprintf('"%s"'$id), $event->getUnusedIds())))
  105.         );
  106.         //json_decode each row and flatten the result to an array of ids
  107.         return array_merge(
  108.             ...array_map(fn (string $ids) => json_decode($idstrue\JSON_THROW_ON_ERROR), $result)
  109.         );
  110.     }
  111. }