Passed
Push — 6.5.0.0 ( 8c3841...8f0d50 )
by Christian
11:34 queued 14s
created

SnippetService::getUsedThemes()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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