Passed
Push — trunk ( 6d115e...2fe92c )
by Christian
11:00 queued 15s
created

UnusedMediaSubscriber   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 45
dl 0
loc 110
rs 10
c 1
b 0
f 0
wmc 9

8 Methods

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