Passed
Push — 6.4.20.0 ( 4fc051...7c36c8 )
by Christian
12:10
created

SnippetService   F

Complexity

Total Complexity 72

Size/Duplication

Total Lines 610
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 245
dl 0
loc 610
rs 2.64
c 0
b 0
f 0
wmc 72

23 Methods

Rating   Name   Duplication   Size   Complexity  
A getRegionFilterItems() 0 34 6
A __construct() 0 18 1
A getAuthors() 0 25 4
A getList() 0 30 4
A getSnippetSet() 0 21 2
B sortSnippets() 0 40 11
A createIsoList() 0 9 2
A getUnusedThemes() 0 15 2
A mergeSnippetsComparison() 0 10 3
A fetchSnippetsFromDatabase() 0 8 1
A getSetMetaData() 0 12 2
A getSnippetFilesByIso() 0 8 2
A getUsedThemes() 0 17 3
A getStorefrontSnippets() 0 37 3
A fillBlankSnippets() 0 27 6
A flatten() 0 25 5
A getSnippetsFromFiles() 0 24 3
A getLocaleBySnippetSetId() 0 11 2
A findSnippetSetInDatabase() 0 3 1
A getSnippetsByLocale() 0 22 4
A getFileSnippets() 0 9 2
A databaseSnippetsToArray() 0 22 2
A findSnippetInDatabase() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like SnippetService often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use SnippetService, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
namespace Shopware\Core\System\Snippet;
4
5
use Doctrine\DBAL\Connection;
6
use Shopware\Core\Framework\Context;
7
use Shopware\Core\Framework\DataAbstractionLayer\Entity;
8
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
9
use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Bucket\TermsAggregation;
10
use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Bucket\TermsResult;
11
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
12
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
13
use Shopware\Core\Framework\Log\Package;
14
use Shopware\Core\Framework\Uuid\Uuid;
15
use Shopware\Core\System\SalesChannel\Aggregate\SalesChannelDomain\SalesChannelDomainEntity;
16
use Shopware\Core\System\Snippet\Aggregate\SnippetSet\SnippetSetEntity;
17
use Shopware\Core\System\Snippet\Files\AbstractSnippetFile;
18
use Shopware\Core\System\Snippet\Files\SnippetFileCollection;
19
use Shopware\Core\System\Snippet\Files\SnippetFileInterface;
20
use Shopware\Core\System\Snippet\Filter\SnippetFilterFactory;
21
use Shopware\Storefront\Theme\SalesChannelThemeLoader;
22
use Shopware\Storefront\Theme\StorefrontPluginConfiguration\StorefrontPluginConfiguration;
23
use Shopware\Storefront\Theme\StorefrontPluginRegistry;
24
use Symfony\Component\DependencyInjection\ContainerInterface;
25
use Symfony\Component\Translation\MessageCatalogueInterface;
26
27
#[Package('system-settings')]
28
class SnippetService
29
{
30
    private Connection $connection;
31
32
    private SnippetFileCollection $snippetFileCollection;
33
34
    private EntityRepositoryInterface $snippetRepository;
35
36
    private EntityRepositoryInterface $snippetSetRepository;
37
38
    private SnippetFilterFactory $snippetFilterFactory;
39
40
    private EntityRepositoryInterface $salesChannelDomain;
41
42
    private ?SalesChannelThemeLoader $salesChannelThemeLoader;
43
44
    /**
45
     * The "kernel" service is synthetic, it needs to be set at boot time before it can be used.
46
     * We need to get StorefrontPluginRegistry service from service_container lazily because it depends on kernel service.
47
     */
48
    private ContainerInterface $container;
49
50
    /**
51
     * @internal
52
     */
53
    public function __construct(
54
        Connection $connection,
55
        SnippetFileCollection $snippetFileCollection,
56
        EntityRepositoryInterface $snippetRepository,
57
        EntityRepositoryInterface $snippetSetRepository,
58
        EntityRepositoryInterface $salesChannelDomain,
59
        SnippetFilterFactory $snippetFilterFactory,
60
        ContainerInterface $container,
61
        ?SalesChannelThemeLoader $salesChannelThemeLoader = null
62
    ) {
63
        $this->connection = $connection;
64
        $this->snippetFileCollection = $snippetFileCollection;
65
        $this->snippetRepository = $snippetRepository;
66
        $this->snippetSetRepository = $snippetSetRepository;
67
        $this->snippetFilterFactory = $snippetFilterFactory;
68
        $this->salesChannelDomain = $salesChannelDomain;
69
        $this->container = $container;
70
        $this->salesChannelThemeLoader = $salesChannelThemeLoader;
71
    }
72
73
    /**
74
     * filters: [
75
     *      'isCustom' => bool,
76
     *      'isEmpty' => bool,
77
     *      'term' => string,
78
     *      'namespaces' => array,
79
     *      'authors' => array,
80
     *      'translationKeys' => array,
81
     * ]
82
     *
83
     * sort: [
84
     *      'column' => NULL || the string -> 'translationKey' || setId
85
     *      'direction' => 'ASC' || 'DESC'
86
     * ]
87
     *
88
     * @param int<1, max> $limit
89
     * @param array<string, bool|string|array<int, string>> $requestFilters
90
     * @param array<string, string> $sort
91
     *
92
     * @return array{total:int, data: array<string, array<int, array<string, string|null>>>}
93
     */
94
    public function getList(int $page, int $limit, Context $context, array $requestFilters, array $sort): array
95
    {
96
        --$page;
97
        /** @var array<string, array{iso: string, id: string}> $metaData */
98
        $metaData = $this->getSetMetaData($context);
99
100
        $isoList = $this->createIsoList($metaData);
101
        $languageFiles = $this->getSnippetFilesByIso($isoList);
102
103
        $fileSnippets = $this->getFileSnippets($languageFiles, $isoList);
104
        $dbSnippets = $this->databaseSnippetsToArray($this->findSnippetInDatabase(new Criteria(), $context), $fileSnippets);
105
106
        $snippets = array_replace_recursive($fileSnippets, $dbSnippets);
107
        $snippets = $this->fillBlankSnippets($snippets, $isoList);
108
109
        foreach ($requestFilters as $requestFilterName => $requestFilterValue) {
110
            $snippets = $this->snippetFilterFactory->getFilter($requestFilterName)->filter($snippets, $requestFilterValue);
111
        }
112
113
        $snippets = $this->sortSnippets($sort, $snippets);
114
115
        $total = 0;
116
        foreach ($snippets as &$set) {
117
            $total = $total > 0 ? $total : \count($set['snippets']);
118
            $set['snippets'] = array_chunk($set['snippets'], $limit, true)[$page] ?? [];
119
        }
120
121
        return [
122
            'total' => $total,
123
            'data' => $this->mergeSnippetsComparison($snippets),
124
        ];
125
    }
126
127
    /**
128
     * @return array<string, string>
129
     */
130
    public function getStorefrontSnippets(MessageCatalogueInterface $catalog, string $snippetSetId, ?string $fallbackLocale = null, ?string $salesChannelId = null): array
131
    {
132
        $locale = $this->getLocaleBySnippetSetId($snippetSetId);
133
134
        $snippets = [];
135
136
        $snippetFileCollection = clone $this->snippetFileCollection;
137
138
        $usingThemes = $this->getUsedThemes($salesChannelId);
139
        $unusedThemes = $this->getUnusedThemes($usingThemes);
140
        $snippetCollection = $snippetFileCollection->filter(function (AbstractSnippetFile $snippetFile) use ($unusedThemes) {
141
            return !\in_array($snippetFile->getTechnicalName(), $unusedThemes, true);
142
        });
143
144
        $fallbackSnippets = [];
145
146
        if ($fallbackLocale !== null) {
147
            // fallback has to be the base
148
            $snippets = $fallbackSnippets = $this->getSnippetsByLocale($snippetCollection, $fallbackLocale);
149
        }
150
151
        // now override fallback with defaults in catalog
152
        $snippets = array_replace_recursive(
153
            $snippets,
154
            $catalog->all('messages')
155
        );
156
157
        // after fallback and default catalog merged, overwrite them with current locale snippets
158
        $snippets = array_replace_recursive(
159
            $snippets,
160
            $locale === $fallbackLocale ? $fallbackSnippets : $this->getSnippetsByLocale($snippetCollection, $locale)
161
        );
162
163
        // at least overwrite the snippets with the database customer overwrites
164
        return array_replace_recursive(
165
            $snippets,
166
            $this->fetchSnippetsFromDatabase($snippetSetId, $unusedThemes)
167
        );
168
    }
169
170
    /**
171
     * @return array<int, string>
172
     */
173
    public function getRegionFilterItems(Context $context): array
174
    {
175
        /** @var array<string, array{iso: string, id: string}> $metaData */
176
        $metaData = $this->getSetMetaData($context);
177
        $isoList = $this->createIsoList($metaData);
178
        $snippetFiles = $this->getSnippetFilesByIso($isoList);
179
180
        $criteria = new Criteria();
181
        $dbSnippets = $this->findSnippetInDatabase($criteria, $context);
182
183
        $result = [];
184
        foreach ($snippetFiles as $files) {
185
            foreach ($this->getSnippetsFromFiles($files, '') as $namespace => $_value) {
186
                $region = explode('.', $namespace)[0];
187
                if (\in_array($region, $result, true)) {
188
                    continue;
189
                }
190
191
                $result[] = $region;
192
            }
193
        }
194
195
        /** @var SnippetEntity $snippet */
196
        foreach ($dbSnippets as $snippet) {
197
            $region = explode('.', $snippet->getTranslationKey())[0];
198
            if (\in_array($region, $result, true)) {
199
                continue;
200
            }
201
202
            $result[] = $region;
203
        }
204
        sort($result);
205
206
        return $result;
207
    }
208
209
    /**
210
     * @return array<int, int|string>
211
     */
212
    public function getAuthors(Context $context): array
213
    {
214
        $files = $this->snippetFileCollection->toArray();
215
216
        $criteria = new Criteria();
217
        $criteria->addAggregation(new TermsAggregation('distinct_author', 'author'));
218
219
        /** @var TermsResult|null $aggregation */
220
        $aggregation = $this->snippetRepository->aggregate($criteria, $context)
221
                ->get('distinct_author');
222
223
        if (!$aggregation || empty($aggregation->getBuckets())) {
0 ignored issues
show
introduced by
$aggregation is of type Shopware\Core\Framework\...sult\Bucket\TermsResult, thus it always evaluated to true.
Loading history...
224
            $result = [];
225
        } else {
226
            $result = $aggregation->getKeys();
227
        }
228
229
        $authors = array_flip($result);
230
        foreach ($files as $file) {
231
            $authors[$file['author']] = true;
232
        }
233
        $result = array_keys($authors);
234
        sort($result);
235
236
        return $result;
237
    }
238
239
    public function getSnippetSet(string $salesChannelId, string $languageId, string $locale, Context $context): ?SnippetSetEntity
240
    {
241
        $criteria = new Criteria();
242
        $criteria->addFilter(
243
            new EqualsFilter('salesChannelId', $salesChannelId),
244
            new EqualsFilter('languageId', $languageId)
245
        );
246
        $criteria->addAssociation('snippetSet');
247
248
        /** @var SalesChannelDomainEntity|null $salesChannelDomain */
249
        $salesChannelDomain = $this->salesChannelDomain->search($criteria, $context)->first();
250
251
        if ($salesChannelDomain === null) {
252
            $criteria = new Criteria();
253
            $criteria->addFilter(new EqualsFilter('iso', $locale));
254
            $snippetSet = $this->snippetSetRepository->search($criteria, $context)->first();
255
        } else {
256
            $snippetSet = $salesChannelDomain->getSnippetSet();
257
        }
258
259
        return $snippetSet;
260
    }
261
262
    /**
263
     * @param list<string> $usingThemes
0 ignored issues
show
Bug introduced by
The type Shopware\Core\System\Snippet\list 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...
264
     *
265
     * @return list<string>
266
     */
267
    protected function getUnusedThemes(array $usingThemes = []): array
268
    {
269
        if (!$this->container->has(StorefrontPluginRegistry::class)) {
270
            return [];
0 ignored issues
show
Bug Best Practice introduced by
The expression return array() returns the type array which is incompatible with the documented return type Shopware\Core\System\Snippet\list.
Loading history...
271
        }
272
273
        $themeRegistry = $this->container->get(StorefrontPluginRegistry::class);
274
275
        $unusedThemes = $themeRegistry->getConfigurations()->getThemes()->filter(function (StorefrontPluginConfiguration $theme) use ($usingThemes) {
276
            return !\in_array($theme->getTechnicalName(), $usingThemes, true);
277
        })->map(function (StorefrontPluginConfiguration $theme) {
278
            return $theme->getTechnicalName();
279
        });
280
281
        return array_values($unusedThemes);
0 ignored issues
show
Bug Best Practice introduced by
The expression return array_values($unusedThemes) returns the type array which is incompatible with the documented return type Shopware\Core\System\Snippet\list.
Loading history...
282
    }
283
284
    /**
285
     * Second parameter $unusedThemes is used for external dependencies
286
     *
287
     * @param list<string> $unusedThemes
288
     *
289
     * @return array<string, string>
290
     */
291
    protected function fetchSnippetsFromDatabase(string $snippetSetId, array $unusedThemes = []): array
292
    {
293
        /** @var array<string, string> $snippets */
294
        $snippets = $this->connection->fetchAllKeyValue('SELECT translation_key, value FROM snippet WHERE snippet_set_id = :snippetSetId', [
295
            'snippetSetId' => Uuid::fromHexToBytes($snippetSetId),
296
        ]);
297
298
        return $snippets;
299
    }
300
301
    /**
302
     * @return array<string, string>
303
     */
304
    private function getSnippetsByLocale(SnippetFileCollection $snippetFileCollection, string $locale): array
305
    {
306
        $files = $snippetFileCollection->getSnippetFilesByIso($locale);
307
        $snippets = [];
308
309
        foreach ($files as $file) {
310
            $json = json_decode(file_get_contents($file->getPath()) ?: '', true);
311
312
            $jsonError = json_last_error();
313
            if ($jsonError !== 0) {
314
                throw new \RuntimeException(sprintf('Invalid JSON in snippet file at path \'%s\' with code \'%d\'', $file->getPath(), $jsonError));
315
            }
316
317
            $flattenSnippetFileSnippets = $this->flatten($json);
318
319
            $snippets = array_replace_recursive(
320
                $snippets,
321
                $flattenSnippetFileSnippets
322
            );
323
        }
324
325
        return $snippets;
326
    }
327
328
    /**
329
     * @return list<string>
330
     */
331
    private function getUsedThemes(?string $salesChannelId = null): array
332
    {
333
        if (!$salesChannelId || $this->salesChannelThemeLoader === null) {
334
            return [StorefrontPluginRegistry::BASE_THEME_NAME];
0 ignored issues
show
Bug Best Practice introduced by
The expression return array(Shopware\St...istry::BASE_THEME_NAME) returns the type array<integer,string> which is incompatible with the documented return type Shopware\Core\System\Snippet\list.
Loading history...
335
        }
336
337
        $saleChannelThemes = $this->salesChannelThemeLoader->load($salesChannelId);
338
339
        $usedThemes = array_filter([
340
            $saleChannelThemes['themeName'] ?? null,
341
            $saleChannelThemes['parentThemeName'] ?? null,
342
        ]);
343
344
        /** @var list<string> */
345
        return array_values(array_unique([
0 ignored issues
show
Bug Best Practice introduced by
The expression return array_values(arra...try::BASE_THEME_NAME))) returns the type array which is incompatible with the documented return type Shopware\Core\System\Snippet\list.
Loading history...
346
            ...$usedThemes,
347
            StorefrontPluginRegistry::BASE_THEME_NAME, // Storefront snippets should always be loaded
348
        ]));
349
    }
350
351
    /**
352
     * @param array<string, string> $isoList
353
     *
354
     * @return array<string, array<int, AbstractSnippetFile|SnippetFileInterface>>
355
     */
356
    private function getSnippetFilesByIso(array $isoList): array
357
    {
358
        $result = [];
359
        foreach ($isoList as $iso) {
360
            $result[$iso] = $this->snippetFileCollection->getSnippetFilesByIso($iso);
361
        }
362
363
        return $result;
364
    }
365
366
    /**
367
     * @param array<int, AbstractSnippetFile|SnippetFileInterface> $languageFiles
368
     *
369
     * @return array<string, array<string, string|null>>
370
     */
371
    private function getSnippetsFromFiles(array $languageFiles, string $setId): array
372
    {
373
        $result = [];
374
        foreach ($languageFiles as $snippetFile) {
375
            $json = json_decode((string) file_get_contents($snippetFile->getPath()), true);
376
377
            $jsonError = json_last_error();
378
            if ($jsonError !== 0) {
379
                throw new \RuntimeException(sprintf('Invalid JSON in snippet file at path \'%s\' with code \'%d\'', $snippetFile->getPath(), $jsonError));
380
            }
381
382
            $flattenSnippetFileSnippets = $this->flatten(
383
                $json,
384
                '',
385
                ['author' => $snippetFile->getAuthor(), 'id' => null, 'setId' => $setId]
386
            );
387
388
            $result = array_replace_recursive(
389
                $result,
390
                $flattenSnippetFileSnippets
391
            );
392
        }
393
394
        return $result;
395
    }
396
397
    /**
398
     * @param array<string, array<string, array<string, array<string, string|null>>>> $sets
399
     *
400
     * @return array<string, array<int, array<string, string|null>>>
401
     */
402
    private function mergeSnippetsComparison(array $sets): array
403
    {
404
        $result = [];
405
        foreach ($sets as $snippetSet) {
406
            foreach ($snippetSet['snippets'] as $translationKey => $snippet) {
407
                $result[$translationKey][] = $snippet;
408
            }
409
        }
410
411
        return $result;
412
    }
413
414
    private function getLocaleBySnippetSetId(string $snippetSetId): string
415
    {
416
        $locale = $this->connection->fetchOne('SELECT iso FROM snippet_set WHERE id = :snippetSetId', [
417
            'snippetSetId' => Uuid::fromHexToBytes($snippetSetId),
418
        ]);
419
420
        if ($locale === false) {
421
            throw new \InvalidArgumentException(sprintf('No snippetSet with id "%s" found', $snippetSetId));
422
        }
423
424
        return (string) $locale;
425
    }
426
427
    /**
428
     * @param array<string, array<string, array<string, array<string, string|null>>>> $fileSnippets
429
     * @param array<string, string> $isoList
430
     *
431
     * @return array<string, array<string, array<string, array<string, string|null>>>>
432
     */
433
    private function fillBlankSnippets(array $fileSnippets, array $isoList): array
434
    {
435
        foreach ($isoList as $setId => $_iso) {
436
            foreach ($isoList as $currentSetId => $_currentIso) {
437
                if ($setId === $currentSetId) {
438
                    continue;
439
                }
440
441
                foreach ($fileSnippets[$setId]['snippets'] as $index => $_snippet) {
442
                    if (!isset($fileSnippets[$currentSetId]['snippets'][$index])) {
443
                        $fileSnippets[$currentSetId]['snippets'][$index] = [
444
                            'value' => '',
445
                            'translationKey' => $index,
446
                            'author' => '',
447
                            'origin' => '',
448
                            'resetTo' => '',
449
                            'setId' => $currentSetId,
450
                            'id' => null,
451
                        ];
452
                    }
453
                }
454
455
                ksort($fileSnippets[$currentSetId]['snippets']);
456
            }
457
        }
458
459
        return $fileSnippets;
460
    }
461
462
    /**
463
     * @param array<string, array<int, SnippetFileInterface|AbstractSnippetFile>> $languageFiles
464
     * @param array<string, string> $isoList
465
     *
466
     * @return array<string, array<string, array<string, array<string, string|null>>>>
467
     */
468
    private function getFileSnippets(array $languageFiles, array $isoList): array
469
    {
470
        $fileSnippets = [];
471
472
        foreach ($isoList as $setId => $iso) {
473
            $fileSnippets[$setId]['snippets'] = $this->getSnippetsFromFiles($languageFiles[$iso], $setId);
474
        }
475
476
        return $fileSnippets;
477
    }
478
479
    /**
480
     * @param array<string, array{iso: string, id: string}> $metaData
481
     *
482
     * @return array<string, string>
483
     */
484
    private function createIsoList(array $metaData): array
485
    {
486
        $isoList = [];
487
488
        foreach ($metaData as $set) {
489
            $isoList[$set['id']] = $set['iso'];
490
        }
491
492
        return $isoList;
493
    }
494
495
    /**
496
     * @return array<string, array<mixed>>
497
     */
498
    private function getSetMetaData(Context $context): array
499
    {
500
        $queryResult = $this->findSnippetSetInDatabase(new Criteria(), $context);
501
502
        /** @var array<string, array{iso: string, id: string}> $result */
503
        $result = [];
504
        /** @var SnippetSetEntity $value */
505
        foreach ($queryResult as $key => $value) {
506
            $result[$key] = $value->jsonSerialize();
507
        }
508
509
        return $result;
510
    }
511
512
    /**
513
     * @param array<string, Entity> $queryResult
514
     * @param array<string, array<string, array<string, array<string, string|null>>>> $fileSnippets
515
     *
516
     * @return array<string, array<string, array<string, array<string, string|null>>>>
517
     */
518
    private function databaseSnippetsToArray(array $queryResult, array $fileSnippets): array
519
    {
520
        $result = [];
521
        /** @var SnippetEntity $snippet */
522
        foreach ($queryResult as $snippet) {
523
            $currentSnippet = array_intersect_key(
524
                $snippet->jsonSerialize(),
525
                array_flip([
526
                    'author',
527
                    'id',
528
                    'setId',
529
                    'translationKey',
530
                    'value',
531
                ])
532
            );
533
534
            $currentSnippet['origin'] = '';
535
            $currentSnippet['resetTo'] = $fileSnippets[$snippet->getSetId()]['snippets'][$snippet->getTranslationKey()]['origin'] ?? $snippet->getValue();
0 ignored issues
show
Bug introduced by
The method getTranslationKey() does not exist on Shopware\Core\Framework\...AbstractionLayer\Entity. Did you maybe mean getTranslation()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

535
            $currentSnippet['resetTo'] = $fileSnippets[$snippet->getSetId()]['snippets'][$snippet->/** @scrutinizer ignore-call */ getTranslationKey()]['origin'] ?? $snippet->getValue();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getSetId() does not exist on Shopware\Core\Framework\...AbstractionLayer\Entity. It seems like you code against a sub-type of Shopware\Core\Framework\...AbstractionLayer\Entity such as Shopware\Core\System\Snippet\SnippetEntity. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

535
            $currentSnippet['resetTo'] = $fileSnippets[$snippet->/** @scrutinizer ignore-call */ getSetId()]['snippets'][$snippet->getTranslationKey()]['origin'] ?? $snippet->getValue();
Loading history...
Bug introduced by
The method getValue() does not exist on Shopware\Core\Framework\...AbstractionLayer\Entity. It seems like you code against a sub-type of Shopware\Core\Framework\...AbstractionLayer\Entity such as Shopware\Core\Content\Pr...oductStreamFilterEntity or Shopware\Administration\...nistrationSnippetEntity or Shopware\Core\System\Snippet\SnippetEntity or Shopware\Core\System\Use...Config\UserConfigEntity or Shopware\Core\Content\Ru...ion\RuleConditionEntity or Shopware\Core\Checkout\P...PromotionDiscountEntity or Shopware\Core\Checkout\P...PromotionSetGroupEntity. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

535
            $currentSnippet['resetTo'] = $fileSnippets[$snippet->getSetId()]['snippets'][$snippet->getTranslationKey()]['origin'] ?? $snippet->/** @scrutinizer ignore-call */ getValue();
Loading history...
536
            $result[$snippet->getSetId()]['snippets'][$snippet->getTranslationKey()] = $currentSnippet;
537
        }
538
539
        return $result;
540
    }
541
542
    /**
543
     * @return array<string, Entity>
544
     */
545
    private function findSnippetInDatabase(Criteria $criteria, Context $context): array
546
    {
547
        return $this->snippetRepository->search($criteria, $context)->getEntities()->getElements();
548
    }
549
550
    /**
551
     * @return array<string, Entity>
552
     */
553
    private function findSnippetSetInDatabase(Criteria $criteria, Context $context): array
554
    {
555
        return $this->snippetSetRepository->search($criteria, $context)->getEntities()->getElements();
556
    }
557
558
    /**
559
     * @param array<string, string> $sort
560
     * @param array<string, array<string, array<string, array<string, string|null>>>> $snippets
561
     *
562
     * @return array<string, array<string, array<string, array<string, string|null>>>>
563
     */
564
    private function sortSnippets(array $sort, array $snippets): array
565
    {
566
        if (!isset($sort['sortBy'], $sort['sortDirection'])) {
567
            return $snippets;
568
        }
569
570
        if ($sort['sortBy'] === 'translationKey' || $sort['sortBy'] === 'id') {
571
            foreach ($snippets as &$set) {
572
                if ($sort['sortDirection'] === 'ASC') {
573
                    ksort($set['snippets']);
574
                } elseif ($sort['sortDirection'] === 'DESC') {
575
                    krsort($set['snippets']);
576
                }
577
            }
578
579
            return $snippets;
580
        }
581
582
        if (!isset($snippets[$sort['sortBy']])) {
583
            return $snippets;
584
        }
585
586
        $mainSet = $snippets[$sort['sortBy']];
587
        unset($snippets[$sort['sortBy']]);
588
589
        uasort($mainSet['snippets'], static function ($a, $b) use ($sort) {
590
            $a = mb_strtolower((string) $a['value']);
591
            $b = mb_strtolower((string) $b['value']);
592
593
            return $sort['sortDirection'] !== 'DESC' ? $a <=> $b : $b <=> $a;
594
        });
595
596
        $result = [$sort['sortBy'] => $mainSet];
597
        foreach ($snippets as $setId => $set) {
598
            foreach ($mainSet['snippets'] as $currentKey => $_value) {
599
                $result[$setId]['snippets'][$currentKey] = $set['snippets'][$currentKey];
600
            }
601
        }
602
603
        return $result;
604
    }
605
606
    /**
607
     * @param array<string, string|array<string, mixed>> $array
608
     * @param array<string, string|null>|null $additionalParameters
609
     *
610
     * @return array<string, string|array<string, mixed>>
611
     */
612
    private function flatten(array $array, string $prefix = '', ?array $additionalParameters = null): array
613
    {
614
        $result = [];
615
        foreach ($array as $index => $value) {
616
            $newIndex = $prefix . (empty($prefix) ? '' : '.') . $index;
617
618
            if (\is_array($value)) {
619
                $result = array_merge($result, $this->flatten($value, $newIndex, $additionalParameters));
620
            } else {
621
                if (!empty($additionalParameters)) {
622
                    $result[$newIndex] = array_merge([
623
                        'value' => $value,
624
                        'origin' => $value,
625
                        'resetTo' => $value,
626
                        'translationKey' => $newIndex,
627
                    ], $additionalParameters);
628
629
                    continue;
630
                }
631
632
                $result[$newIndex] = $value;
633
            }
634
        }
635
636
        return $result;
637
    }
638
}
639