Passed
Push — trunk ( 5f7c6d...3ce3ae )
by Christian
18:14 queued 04:54
created

SalesChannelCmsPageLoader   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 52
dl 0
loc 126
rs 10
c 0
b 0
f 0
wmc 18

4 Methods

Rating   Name   Duplication   Size   Complexity  
B overwriteSlotConfig() 0 28 7
A __construct() 0 5 1
A loadSlotData() 0 11 2
B load() 0 60 8
1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\Content\Cms\SalesChannel;
4
5
use Shopware\Core\Content\Cms\Aggregate\CmsBlock\CmsBlockEntity;
0 ignored issues
show
Bug introduced by
The type Shopware\Core\Content\Cm...CmsBlock\CmsBlockEntity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Shopware\Core\Content\Cms\Aggregate\CmsSection\CmsSectionEntity;
0 ignored issues
show
Bug introduced by
The type Shopware\Core\Content\Cm...ection\CmsSectionEntity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
0 ignored issues
show
Bug introduced by
The type Shopware\Core\Content\Cm...e\CmsSlot\CmsSlotEntity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use Shopware\Core\Content\Cms\CmsPageCollection;
9
use Shopware\Core\Content\Cms\CmsPageEntity;
0 ignored issues
show
Bug introduced by
The type Shopware\Core\Content\Cms\CmsPageEntity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use Shopware\Core\Content\Cms\DataResolver\CmsSlotsDataResolver;
11
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
12
use Shopware\Core\Content\Cms\Events\CmsPageLoadedEvent;
13
use Shopware\Core\Content\Cms\Events\CmsPageLoaderCriteriaEvent;
14
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
15
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
16
use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
17
use Shopware\Core\Framework\Log\Package;
18
use Shopware\Core\System\SalesChannel\SalesChannelContext;
19
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
20
use Symfony\Component\HttpFoundation\Request;
21
22
#[Package('content')]
23
class SalesChannelCmsPageLoader implements SalesChannelCmsPageLoaderInterface
24
{
25
    /**
26
     * @internal
27
     *
28
     * @param EntityRepository<CmsPageCollection> $cmsPageRepository
29
     */
30
    public function __construct(
31
        private readonly EntityRepository $cmsPageRepository,
32
        private readonly CmsSlotsDataResolver $slotDataResolver,
33
        private readonly EventDispatcherInterface $eventDispatcher
34
    ) {
35
    }
36
37
    /**
38
     * @param array<string, mixed>|null $config
39
     *
40
     * @return EntitySearchResult<CmsPageCollection>
41
     */
42
    public function load(
43
        Request $request,
44
        Criteria $criteria,
45
        SalesChannelContext $context,
46
        ?array $config = null,
47
        ?ResolverContext $resolverContext = null
48
    ): EntitySearchResult {
49
        $this->eventDispatcher->dispatch(new CmsPageLoaderCriteriaEvent($request, $criteria, $context));
50
        $config ??= [];
51
52
        // ensure sections, blocks and slots are loaded, slots and blocks can be restricted by caller
53
        $criteria->addAssociation('sections.backgroundMedia');
54
        $criteria->addAssociation('sections.blocks.backgroundMedia');
55
        $criteria->addAssociation('sections.blocks.slots');
56
57
        // step 1, load cms pages with blocks and slots
58
        $result = $this->cmsPageRepository->search($criteria, $context->getContext());
59
        $pages = $result->getEntities();
60
61
        foreach ($pages as $page) {
62
            if ($page->getSections() === null) {
63
                continue;
64
            }
65
66
            $page->getSections()->sort(fn (CmsSectionEntity $a, CmsSectionEntity $b) => $a->getPosition() <=> $b->getPosition());
67
68
            if (!$resolverContext) {
69
                $resolverContext = new ResolverContext($context, $request);
70
            }
71
72
            // step 2, sort blocks into sectionPositions
73
            foreach ($page->getSections() as $section) {
74
                $blocks = $section->getBlocks();
75
                if ($blocks === null) {
76
                    continue;
77
                }
78
                $blocks->sort(fn (CmsBlockEntity $a, CmsBlockEntity $b) => $a->getPosition() <=> $b->getPosition());
79
80
                foreach ($blocks as $block) {
81
                    $slots = $block->getSlots();
82
                    if ($slots === null) {
83
                        continue;
84
                    }
85
                    $slots->sort(fn (CmsSlotEntity $a, CmsSlotEntity $b) => $a->getSlot() <=> $b->getSlot());
86
                }
87
            }
88
89
            // step 3, find config overwrite
90
            $overwrite = $config[$page->getId()] ?? $config;
91
92
            // step 4, overwrite slot config
93
            $this->overwriteSlotConfig($page, $overwrite);
94
95
            // step 5, resolve slot data
96
            $this->loadSlotData($page, $resolverContext);
97
        }
98
99
        $this->eventDispatcher->dispatch(new CmsPageLoadedEvent($request, $pages, $context));
100
101
        return $result;
102
    }
103
104
    private function loadSlotData(CmsPageEntity $page, ResolverContext $resolverContext): void
105
    {
106
        $sections = $page->getSections();
107
        if ($sections === null) {
108
            return;
109
        }
110
111
        $blocks = $sections->getBlocks();
112
        $slots = $this->slotDataResolver->resolve($blocks->getSlots(), $resolverContext);
113
114
        $blocks->setSlots($slots);
115
    }
116
117
    /**
118
     * @param array<string, mixed> $config
119
     */
120
    private function overwriteSlotConfig(CmsPageEntity $page, array $config): void
121
    {
122
        $sections = $page->getSections();
123
        if ($sections === null) {
124
            return;
125
        }
126
127
        foreach ($sections->getBlocks()->getSlots() as $slot) {
128
            if ($slot->getConfig() === null && $slot->getTranslation('config') !== null) {
129
                $slot->setConfig($slot->getTranslation('config'));
130
            }
131
132
            if (empty($config)) {
133
                continue;
134
            }
135
136
            if (!isset($config[$slot->getId()])) {
137
                continue;
138
            }
139
140
            $defaultConfig = $slot->getConfig() ?? [];
141
            $merged = array_replace_recursive(
142
                $defaultConfig,
143
                $config[$slot->getId()]
144
            );
145
146
            $slot->setConfig($merged);
147
            $slot->addTranslated('config', $merged);
148
        }
149
    }
150
}
151