Passed
Push — trunk ( 13f525...a8cce2 )
by Christian
12:21 queued 14s
created

SnippetService::getUnusedThemes()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 13
nc 2
nop 0
dl 0
loc 23
rs 9.8333
c 0
b 0
f 0
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\Doctrine\FetchModeHelper;
8
use Shopware\Core\Framework\DataAbstractionLayer\Entity;
9
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
10
use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Bucket\TermsAggregation;
11
use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\Bucket\TermsResult;
12
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
13
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
14
use Shopware\Core\Framework\Uuid\Uuid;
15
use Shopware\Core\SalesChannelRequest;
16
use Shopware\Core\System\SalesChannel\Aggregate\SalesChannelDomain\SalesChannelDomainEntity;
17
use Shopware\Core\System\Snippet\Aggregate\SnippetSet\SnippetSetEntity;
18
use Shopware\Core\System\Snippet\Files\AbstractSnippetFile;
19
use Shopware\Core\System\Snippet\Files\SnippetFileCollection;
20
use Shopware\Core\System\Snippet\Files\SnippetFileInterface;
21
use Shopware\Core\System\Snippet\Filter\SnippetFilterFactory;
22
use Shopware\Storefront\Theme\StorefrontPluginConfiguration\StorefrontPluginConfiguration;
23
use Shopware\Storefront\Theme\StorefrontPluginRegistry;
24
use Symfony\Component\DependencyInjection\ContainerInterface;
25
use Symfony\Component\HttpFoundation\RequestStack;
26
use Symfony\Component\Translation\MessageCatalogueInterface;
27
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 RequestStack $requestStack;
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
        RequestStack $requestStack,
61
        ContainerInterface $container
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->requestStack = $requestStack;
70
        $this->container = $container;
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): array
131
    {
132
        $locale = $this->getLocaleBySnippetSetId($snippetSetId);
133
134
        $snippets = [];
135
136
        $snippetFileCollection = clone $this->snippetFileCollection;
137
138
        $unusedThemes = $this->getUnusedThemes();
139
140
        $snippetCollection = $snippetFileCollection->filter(function (AbstractSnippetFile $snippetFile) use ($unusedThemes) {
141
            return !\in_array($snippetFile->getTechnicalName(), $unusedThemes, true);
142
        });
143
144
        if ($fallbackLocale !== null) {
145
            // fallback has to be the base
146
            $snippets = $this->getSnippetsByLocale($snippetCollection, $fallbackLocale);
147
        }
148
149
        // now override fallback with defaults in catalog
150
        $snippets = array_replace_recursive(
151
            $snippets,
152
            $catalog->all('messages')
153
        );
154
155
        // after fallback and default catalog merged, overwrite them with current locale snippets
156
        $snippets = array_replace_recursive(
157
            $snippets,
158
            $this->getSnippetsByLocale($snippetCollection, $locale)
159
        );
160
161
        // at least overwrite the snippets with the database customer overwrites
162
        $snippets = array_replace_recursive(
163
            $snippets,
164
            $this->fetchSnippetsFromDatabase($snippetSetId)
165
        );
166
167
        return $snippets;
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
     * @return array<int, string>
264
     */
265
    protected function getUnusedThemes(): array
266
    {
267
        if (!$this->container->has(StorefrontPluginRegistry::class)) {
268
            return [];
269
        }
270
271
        $themeRegistry = $this->container->get(StorefrontPluginRegistry::class);
272
273
        $request = $this->requestStack->getMainRequest();
274
275
        $usingThemes = array_filter(array_unique([
276
            $request ? $request->attributes->get(SalesChannelRequest::ATTRIBUTE_THEME_NAME) : null,
277
            $request ? $request->attributes->get(SalesChannelRequest::ATTRIBUTE_THEME_BASE_NAME) : null,
278
            StorefrontPluginRegistry::BASE_THEME_NAME, // Storefront snippets should always be loaded
279
        ]));
280
281
        $unusedThemes = $themeRegistry->getConfigurations()->getThemes()->filter(function (StorefrontPluginConfiguration $theme) use ($usingThemes) {
282
            return !\in_array($theme->getTechnicalName(), $usingThemes, true);
283
        })->map(function (StorefrontPluginConfiguration $theme) {
284
            return $theme->getTechnicalName();
285
        });
286
287
        return array_values($unusedThemes);
288
    }
289
290
    /**
291
     * @return array<string, string>
292
     */
293
    protected function fetchSnippetsFromDatabase(string $snippetSetId): array
294
    {
295
        $snippets = $this->connection->fetchAllAssociative('SELECT translation_key, value FROM snippet WHERE snippet_set_id = :snippetSetId', [
296
            'snippetSetId' => Uuid::fromHexToBytes($snippetSetId),
297
        ]);
298
299
        return FetchModeHelper::keyPair($snippets);
300
    }
301
302
    /**
303
     * @return array<string, string>
304
     */
305
    private function getSnippetsByLocale(SnippetFileCollection $snippetFileCollection, string $locale): array
306
    {
307
        $files = $snippetFileCollection->getSnippetFilesByIso($locale);
308
        $snippets = [];
309
310
        foreach ($files as $file) {
311
            $json = json_decode(file_get_contents($file->getPath()) ?: '', true);
312
313
            $jsonError = json_last_error();
314
            if ($jsonError !== 0) {
315
                throw new \RuntimeException(sprintf('Invalid JSON in snippet file at path \'%s\' with code \'%d\'', $file->getPath(), $jsonError));
316
            }
317
318
            $flattenSnippetFileSnippets = $this->flatten($json);
319
320
            $snippets = array_replace_recursive(
321
                $snippets,
322
                $flattenSnippetFileSnippets
323
            );
324
        }
325
326
        return $snippets;
327
    }
328
329
    /**
330
     * @param array<string, string> $isoList
331
     *
332
     * @return array<string, array<int, AbstractSnippetFile|SnippetFileInterface>>
333
     */
334
    private function getSnippetFilesByIso(array $isoList): array
335
    {
336
        $result = [];
337
        foreach ($isoList as $iso) {
338
            $result[$iso] = $this->snippetFileCollection->getSnippetFilesByIso($iso);
339
        }
340
341
        return $result;
342
    }
343
344
    /**
345
     * @param array<int, AbstractSnippetFile|SnippetFileInterface> $languageFiles
346
     *
347
     * @return array<string, array<string, string|null>>
348
     */
349
    private function getSnippetsFromFiles(array $languageFiles, string $setId): array
350
    {
351
        $result = [];
352
        foreach ($languageFiles as $snippetFile) {
353
            $json = json_decode((string) file_get_contents($snippetFile->getPath()), true);
354
355
            $jsonError = json_last_error();
356
            if ($jsonError !== 0) {
357
                throw new \RuntimeException(sprintf('Invalid JSON in snippet file at path \'%s\' with code \'%d\'', $snippetFile->getPath(), $jsonError));
358
            }
359
360
            $flattenSnippetFileSnippets = $this->flatten(
361
                $json,
362
                '',
363
                ['author' => $snippetFile->getAuthor(), 'id' => null, 'setId' => $setId]
364
            );
365
366
            $result = array_replace_recursive(
367
                $result,
368
                $flattenSnippetFileSnippets
369
            );
370
        }
371
372
        return $result;
373
    }
374
375
    /**
376
     * @param array<string, array<string, array<string, array<string, string|null>>>> $sets
377
     *
378
     * @return array<string, array<int, array<string, string|null>>>
379
     */
380
    private function mergeSnippetsComparison(array $sets): array
381
    {
382
        $result = [];
383
        foreach ($sets as $snippetSet) {
384
            foreach ($snippetSet['snippets'] as $translationKey => $snippet) {
385
                $result[$translationKey][] = $snippet;
386
            }
387
        }
388
389
        return $result;
390
    }
391
392
    private function getLocaleBySnippetSetId(string $snippetSetId): string
393
    {
394
        $locale = $this->connection->fetchOne('SELECT iso FROM snippet_set WHERE id = :snippetSetId', [
395
            'snippetSetId' => Uuid::fromHexToBytes($snippetSetId),
396
        ]);
397
398
        if ($locale === false) {
399
            throw new \InvalidArgumentException(sprintf('No snippetSet with id "%s" found', $snippetSetId));
400
        }
401
402
        return (string) $locale;
403
    }
404
405
    /**
406
     * @param array<string, array<string, array<string, array<string, string|null>>>> $fileSnippets
407
     * @param array<string, string> $isoList
408
     *
409
     * @return array<string, array<string, array<string, array<string, string|null>>>>
410
     */
411
    private function fillBlankSnippets(array $fileSnippets, array $isoList): array
412
    {
413
        foreach ($isoList as $setId => $_iso) {
414
            foreach ($isoList as $currentSetId => $_currentIso) {
415
                if ($setId === $currentSetId) {
416
                    continue;
417
                }
418
419
                foreach ($fileSnippets[$setId]['snippets'] as $index => $_snippet) {
420
                    if (!isset($fileSnippets[$currentSetId]['snippets'][$index])) {
421
                        $fileSnippets[$currentSetId]['snippets'][$index] = [
422
                            'value' => '',
423
                            'translationKey' => $index,
424
                            'author' => '',
425
                            'origin' => '',
426
                            'resetTo' => '',
427
                            'setId' => $currentSetId,
428
                            'id' => null,
429
                        ];
430
                    }
431
                }
432
433
                ksort($fileSnippets[$currentSetId]['snippets']);
434
            }
435
        }
436
437
        return $fileSnippets;
438
    }
439
440
    /**
441
     * @param array<string, array<int, SnippetFileInterface|AbstractSnippetFile>> $languageFiles
442
     * @param array<string, string> $isoList
443
     *
444
     * @return array<string, array<string, array<string, array<string, string|null>>>>
445
     */
446
    private function getFileSnippets(array $languageFiles, array $isoList): array
447
    {
448
        $fileSnippets = [];
449
450
        foreach ($isoList as $setId => $iso) {
451
            $fileSnippets[$setId]['snippets'] = $this->getSnippetsFromFiles($languageFiles[$iso], $setId);
452
        }
453
454
        return $fileSnippets;
455
    }
456
457
    /**
458
     * @param array<string, array{iso: string, id: string}> $metaData
459
     *
460
     * @return array<string, string>
461
     */
462
    private function createIsoList(array $metaData): array
463
    {
464
        $isoList = [];
465
466
        foreach ($metaData as $set) {
467
            $isoList[$set['id']] = $set['iso'];
468
        }
469
470
        return $isoList;
471
    }
472
473
    /**
474
     * @return array<string, array<mixed>>
475
     */
476
    private function getSetMetaData(Context $context): array
477
    {
478
        $queryResult = $this->findSnippetSetInDatabase(new Criteria(), $context);
479
480
        /** @var array<string, array{iso: string, id: string}> $result */
481
        $result = [];
482
        /** @var SnippetSetEntity $value */
483
        foreach ($queryResult as $key => $value) {
484
            $result[$key] = $value->jsonSerialize();
485
        }
486
487
        return $result;
488
    }
489
490
    /**
491
     * @param array<string, Entity> $queryResult
492
     * @param array<string, array<string, array<string, array<string, string|null>>>> $fileSnippets
493
     *
494
     * @return array<string, array<string, array<string, array<string, string|null>>>>
495
     */
496
    private function databaseSnippetsToArray(array $queryResult, array $fileSnippets): array
497
    {
498
        $result = [];
499
        /** @var SnippetEntity $snippet */
500
        foreach ($queryResult as $snippet) {
501
            $currentSnippet = array_intersect_key(
502
                $snippet->jsonSerialize(),
503
                array_flip([
504
                    'author',
505
                    'id',
506
                    'setId',
507
                    'translationKey',
508
                    'value',
509
                ])
510
            );
511
512
            $currentSnippet['origin'] = '';
513
            $currentSnippet['resetTo'] = $fileSnippets[$snippet->getSetId()]['snippets'][$snippet->getTranslationKey()]['origin'] ?? $snippet->getValue();
0 ignored issues
show
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

513
            $currentSnippet['resetTo'] = $fileSnippets[$snippet->getSetId()]['snippets'][$snippet->getTranslationKey()]['origin'] ?? $snippet->/** @scrutinizer ignore-call */ getValue();
Loading history...
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

513
            $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

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