ProductAbstractPagePublisher::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 10
dl 0
loc 12
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
/**
4
 * Copyright © 2016-present Spryker Systems GmbH. All rights reserved.
5
 * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
6
 */
7
8
namespace Spryker\Zed\ProductPageSearch\Business\Publisher;
9
10
use Generated\Shared\Transfer\ProductPageLoadTransfer;
11
use Generated\Shared\Transfer\ProductPageSearchTransfer;
12
use Generated\Shared\Transfer\ProductPayloadTransfer;
13
use Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch;
14
use Spryker\Shared\ProductPageSearch\ProductPageSearchConfig as SharedProductPageSearchConfig;
15
use Spryker\Zed\Kernel\Persistence\EntityManager\InstancePoolingTrait;
16
use Spryker\Zed\ProductPageSearch\Business\Exception\PluginNotFoundException;
17
use Spryker\Zed\ProductPageSearch\Business\Mapper\ProductPageSearchMapperInterface;
18
use Spryker\Zed\ProductPageSearch\Business\Model\ProductPageSearchWriterInterface;
19
use Spryker\Zed\ProductPageSearch\Business\Reader\AddToCartSkuReaderInterface;
20
use Spryker\Zed\ProductPageSearch\Dependency\Facade\ProductPageSearchToStoreFacadeInterface;
21
use Spryker\Zed\ProductPageSearch\Persistence\ProductPageSearchQueryContainerInterface;
22
use Spryker\Zed\ProductPageSearch\Persistence\ProductPageSearchRepositoryInterface;
23
use Spryker\Zed\ProductPageSearch\ProductPageSearchConfig;
24
25
class ProductAbstractPagePublisher implements ProductAbstractPagePublisherInterface
26
{
27
    use InstancePoolingTrait;
28
29
    /**
30
     * @var array<int>
31
     */
32
    protected static array $publishedProductAbstractIds = [];
33
34
    /**
35
     * @var array<int>
36
     */
37
    protected static array $unpublishedProductAbstractIds = [];
38
39
    /**
40
     * @var string
41
     */
42
    public const PRODUCT_ABSTRACT_LOCALIZED_ENTITY = 'PRODUCT_ABSTRACT_LOCALIZED_ENTITY';
43
44
    /**
45
     * @var string
46
     */
47
    public const PRODUCT_ABSTRACT_PAGE_SEARCH_ENTITY = 'PRODUCT_ABSTRACT_PAGE_SEARCH_ENTITY';
48
49
    /**
50
     * @var string
51
     */
52
    public const STORE_NAME = 'STORE_NAME';
53
54
    /**
55
     * @var string
56
     */
57
    public const LOCALE_NAME = 'LOCALE_NAME';
58
59
    /**
60
     * @var array<int, array<string>>
61
     */
62
    protected static $localesByIdStoreMap;
63
64
    /**
65
     * @var array<int, int>
66
     */
67
    protected array $productAbstractIdTimestampMapToSave = [];
68
69
    /**
70
     * @param \Spryker\Zed\ProductPageSearch\Persistence\ProductPageSearchRepositoryInterface $repository
71
     * @param \Spryker\Zed\ProductPageSearch\Persistence\ProductPageSearchQueryContainerInterface $queryContainer
72
     * @param array<\Spryker\Zed\ProductPageSearch\Dependency\Plugin\ProductPageDataExpanderInterface> $pageDataExpanderPlugins
73
     * @param array<\Spryker\Zed\ProductPageSearchExtension\Dependency\Plugin\ProductPageDataLoaderPluginInterface> $productPageDataLoaderPlugins
74
     * @param array<\Spryker\Zed\ProductPageSearchExtension\Dependency\Plugin\ProductPageSearchCollectionFilterPluginInterface> $productPageSearchCollectionFilterPlugins
75
     * @param \Spryker\Zed\ProductPageSearch\Business\Mapper\ProductPageSearchMapperInterface $productPageSearchMapper
76
     * @param \Spryker\Zed\ProductPageSearch\Business\Model\ProductPageSearchWriterInterface $productPageSearchWriter
77
     * @param \Spryker\Zed\ProductPageSearch\ProductPageSearchConfig $productPageSearchConfig
78
     * @param \Spryker\Zed\ProductPageSearch\Dependency\Facade\ProductPageSearchToStoreFacadeInterface $storeFacade
79
     * @param \Spryker\Zed\ProductPageSearch\Business\Reader\AddToCartSkuReaderInterface $addToCartSkuReader
80
     */
81
    public function __construct(
82
        protected ProductPageSearchRepositoryInterface $repository,
83
        protected ProductPageSearchQueryContainerInterface $queryContainer,
84
        protected array $pageDataExpanderPlugins,
85
        protected array $productPageDataLoaderPlugins,
86
        protected array $productPageSearchCollectionFilterPlugins,
87
        protected ProductPageSearchMapperInterface $productPageSearchMapper,
88
        protected ProductPageSearchWriterInterface $productPageSearchWriter,
89
        protected ProductPageSearchConfig $productPageSearchConfig,
90
        protected ProductPageSearchToStoreFacadeInterface $storeFacade,
91
        protected AddToCartSkuReaderInterface $addToCartSkuReader
92
    ) {
93
    }
94
95
    /**
96
     * @param array<int, int> $productAbstractIdTimestampMap
97
     *
98
     * @return void
99
     */
100
    public function publishWithTimestamps(array $productAbstractIdTimestampMap): void
101
    {
102
        // Filters IDs if it had been processed in the current process
103
        $productAbstractIds = array_values(array_unique(array_diff(array_keys($productAbstractIdTimestampMap), static::$publishedProductAbstractIds)));
104
        // Exclude IDs if they were processed in current process
105
        $productAbstractIdTimestampMap = array_intersect_key($productAbstractIdTimestampMap, array_flip($productAbstractIds));
106
        // Filters IDs if it had been processed in parallel processes
107
        $this->productAbstractIdTimestampMapToSave = $this->repository->getRelevantProductAbstractIdsToUpdate($productAbstractIdTimestampMap);
108
109
        if ($this->productAbstractIdTimestampMapToSave) {
110
            $this->publish(array_keys($this->productAbstractIdTimestampMapToSave));
111
        }
112
113
        static::$publishedProductAbstractIds = array_merge(static::$publishedProductAbstractIds, $productAbstractIds);
114
    }
115
116
    /**
117
     * @param array<int> $productAbstractIds
118
     *
119
     * @return void
120
     */
121
    public function publish(array $productAbstractIds)
122
    {
123
        $productAbstractIdsChunks = array_chunk(
124
            $productAbstractIds,
125
            $this->productPageSearchConfig->getProductAbstractPagePublishChunkSize(),
126
        );
127
128
        foreach ($productAbstractIdsChunks as $productAbstractIdsChunk) {
129
            $this->publishEntities($productAbstractIdsChunk, [], false);
130
        }
131
    }
132
133
    /**
134
     * @param array<int> $productAbstractIds
135
     * @param array<string> $pageDataExpanderPluginNames
136
     *
137
     * @return void
138
     */
139
    public function refresh(array $productAbstractIds, array $pageDataExpanderPluginNames = [])
140
    {
141
        $isPoolingStateChanged = $this->disableInstancePooling();
142
143
        $productAbstractIdsChunks = array_chunk(
144
            array_unique($productAbstractIds),
145
            $this->productPageSearchConfig->getProductAbstractPagePublishChunkSize(),
146
        );
147
148
        foreach ($productAbstractIdsChunks as $productAbstractIdsChunk) {
149
            $this->publishEntities($productAbstractIdsChunk, $pageDataExpanderPluginNames, true);
150
        }
151
152
        if ($isPoolingStateChanged) {
153
            $this->enableInstancePooling();
154
        }
155
    }
156
157
    /**
158
     * @param array<int, int> $productAbstractIdTimestampMap
159
     *
160
     * @return void
161
     */
162
    public function unpublishWithTimestamps(array $productAbstractIdTimestampMap)
163
    {
164
        $productAbstractIds = array_values(array_unique(array_diff(array_keys($productAbstractIdTimestampMap), static::$unpublishedProductAbstractIds)));
165
        if ($productAbstractIds) {
166
            $this->unpublish($productAbstractIds);
167
        }
168
        static::$unpublishedProductAbstractIds = array_merge(static::$unpublishedProductAbstractIds, $productAbstractIds);
169
    }
170
171
    /**
172
     * @param array<int> $productAbstractIds
173
     *
174
     * @return void
175
     */
176
    public function unpublish(array $productAbstractIds)
177
    {
178
        $productAbstractPageSearchEntities = $this->findProductAbstractPageSearchEntities($productAbstractIds);
179
        $this->productPageSearchWriter->deleteProductAbstractPageSearchEntities($productAbstractPageSearchEntities);
180
        $this->productPageSearchWriter->commitRemaining();
181
    }
182
183
    /**
184
     * @param array<int> $productAbstractIds
185
     * @param array<string> $pageDataExpanderPluginNames
186
     * @param bool $isRefresh
187
     *
188
     * @return void
189
     */
190
    protected function publishEntities(array $productAbstractIds, array $pageDataExpanderPluginNames, $isRefresh = false)
191
    {
192
        $pageDataExpanderPlugins = $this->getPageDataExpanderPlugins($pageDataExpanderPluginNames);
193
194
        $payloadTransfers = [];
195
        foreach ($productAbstractIds as $productAbstractId) {
196
            $payloadTransfers[$productAbstractId] = (new ProductPayloadTransfer())->setIdProductAbstract($productAbstractId);
197
        }
198
199
        $productPageLoadTransfer = (new ProductPageLoadTransfer())
200
            ->setProductAbstractIds($productAbstractIds)
201
            ->setPayloadTransfers($payloadTransfers);
202
203
        foreach ($this->productPageDataLoaderPlugins as $productPageDataLoaderPlugin) {
204
            $productPageLoadTransfer = $productPageDataLoaderPlugin->expandProductPageDataTransfer($productPageLoadTransfer);
205
        }
206
207
        $productAbstractLocalizedEntities = $this->findProductAbstractLocalizedEntities($productAbstractIds);
208
        $productCategories = $this->getProductCategoriesByProductAbstractIds($productAbstractIds);
209
        $productAbstractLocalizedEntities = $this->hydrateProductAbstractLocalizedEntitiesWithProductCategories($productCategories, $productAbstractLocalizedEntities);
210
211
        $productAbstractPageSearchEntities = $this->findProductAbstractPageSearchEntities($productAbstractIds);
212
        if (!$productAbstractLocalizedEntities) {
213
            $this->productPageSearchWriter->deleteProductAbstractPageSearchEntities($productAbstractPageSearchEntities);
214
            $this->productPageSearchWriter->commitRemaining();
215
216
            return;
217
        }
218
219
        if ($this->productPageSearchConfig->isProductAbstractAddToCartEnabled()) {
220
            $productAbstractLocalizedEntities = $this->hydrateProductAbstractLocalizedEntitiesWithProductAbstractAddToCartSku(
221
                $productAbstractLocalizedEntities,
222
                $productAbstractIds,
223
            );
224
        }
225
226
        $this->storeData(
227
            $productAbstractLocalizedEntities,
228
            $productAbstractPageSearchEntities,
229
            $pageDataExpanderPlugins,
230
            $productPageLoadTransfer,
231
            $isRefresh,
232
        );
233
234
        $this->productPageSearchWriter->commitRemaining();
235
    }
236
237
    /**
238
     * @param array<array<string, mixed>> $productAbstractLocalizedEntities
239
     * @param array<\Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch> $productAbstractPageSearchEntities
240
     * @param array<\Spryker\Zed\ProductPageSearch\Dependency\Plugin\ProductPageDataExpanderInterface> $pageDataExpanderPlugins
241
     * @param \Generated\Shared\Transfer\ProductPageLoadTransfer $productPageLoadTransfer
242
     * @param bool $isRefresh
243
     *
244
     * @return void
245
     */
246
    protected function storeData(
247
        array $productAbstractLocalizedEntities,
248
        array $productAbstractPageSearchEntities,
249
        array $pageDataExpanderPlugins,
250
        ProductPageLoadTransfer $productPageLoadTransfer,
251
        $isRefresh = false
252
    ) {
253
        $pairedEntities = $this->pairProductAbstractLocalizedEntitiesWithProductAbstractPageSearchEntities(
254
            $productAbstractLocalizedEntities,
255
            $productAbstractPageSearchEntities,
256
            $productPageLoadTransfer,
257
        );
258
259
        $productPageSearchTransfers = $this->mapPairedEntitiesToProductPageSearchTransfers(
260
            $pairedEntities,
261
            $isRefresh,
262
        );
263
        $productPageSearchTransfers = $this->executeProductPageSearchCollectionFilterPlugins($productPageSearchTransfers);
264
        $productPageSearchTransfersIndexedByLocaleAndIdProductAbstract = $this->getProductPageSearchTransfersIndexedByLocaleAndIdProductAbstract(
265
            $productPageSearchTransfers,
266
        );
267
268
        foreach ($pairedEntities as $pairedEntity) {
269
            /** @var array|null $productAbstractLocalizedEntity */
270
            $productAbstractLocalizedEntity = $pairedEntity[static::PRODUCT_ABSTRACT_LOCALIZED_ENTITY];
271
            /** @var \Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch $productAbstractPageSearchEntity */
272
            $productAbstractPageSearchEntity = $pairedEntity[static::PRODUCT_ABSTRACT_PAGE_SEARCH_ENTITY];
273
            $store = $pairedEntity[static::STORE_NAME];
274
            $locale = $pairedEntity[static::LOCALE_NAME];
275
276
            if ($productAbstractLocalizedEntity === null || !$this->isActual($productAbstractLocalizedEntity)) {
277
                $this->deleteProductAbstractPageSearchEntity($productAbstractPageSearchEntity);
278
279
                continue;
280
            }
281
282
            $idProductAbstract = $productAbstractLocalizedEntity['fk_product_abstract'];
283
            $productPageSearchTransfer = $this->findProductPageSearchTransferFromIndexedList(
284
                $productPageSearchTransfersIndexedByLocaleAndIdProductAbstract,
285
                $idProductAbstract,
286
                $locale,
287
                $store,
288
            );
289
290
            if ($productPageSearchTransfer === null) {
291
                $this->deleteProductAbstractPageSearchEntity($productAbstractPageSearchEntity);
292
293
                continue;
294
            }
295
296
            $this->storeProductAbstractPageSearchEntity(
297
                $productAbstractLocalizedEntity,
298
                $productAbstractPageSearchEntity,
299
                $productPageSearchTransfer,
300
                $store,
301
                $locale,
302
                $pageDataExpanderPlugins,
303
            );
304
        }
305
    }
306
307
    /**
308
     * @param \Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch $productAbstractPageSearchEntity
309
     *
310
     * @return void
311
     */
312
    protected function deleteProductAbstractPageSearchEntity(SpyProductAbstractPageSearch $productAbstractPageSearchEntity)
313
    {
314
        if (!$productAbstractPageSearchEntity->isNew()) {
315
            $productAbstractPageSearchEntity->delete();
316
        }
317
    }
318
319
    /**
320
     * @param array $productAbstractLocalizedEntity
321
     * @param \Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch $productAbstractPageSearchEntity
322
     * @param \Generated\Shared\Transfer\ProductPageSearchTransfer $productPageSearchTransfer
323
     * @param string $storeName
324
     * @param string $localeName
325
     * @param array<\Spryker\Zed\ProductPageSearch\Dependency\Plugin\ProductPageDataExpanderInterface> $pageDataExpanderPlugins
326
     *
327
     * @return void
328
     */
329
    protected function storeProductAbstractPageSearchEntity(
330
        array $productAbstractLocalizedEntity,
331
        SpyProductAbstractPageSearch $productAbstractPageSearchEntity,
332
        ProductPageSearchTransfer $productPageSearchTransfer,
333
        string $storeName,
334
        string $localeName,
335
        array $pageDataExpanderPlugins
336
    ) {
337
        if (!empty($this->productAbstractIdTimestampMapToSave[$productAbstractPageSearchEntity->getFkProductAbstract()])) {
338
            $productPageSearchTransfer->setTimestamp($this->productAbstractIdTimestampMapToSave[$productAbstractPageSearchEntity->getFkProductAbstract()]);
339
        }
340
        $productPageSearchTransfer->setStore($storeName);
341
        $productPageSearchTransfer->setLocale($localeName);
342
343
        $this->expandPageSearchTransferWithPlugins($pageDataExpanderPlugins, $productAbstractLocalizedEntity, $productPageSearchTransfer);
344
345
        $searchDocument = $this->productPageSearchMapper->mapToSearchData($productPageSearchTransfer);
346
347
        $this->productPageSearchWriter->save($productPageSearchTransfer, $searchDocument, $productAbstractPageSearchEntity);
348
    }
349
350
    /**
351
     * @param array $productAbstractLocalizedEntity
352
     *
353
     * @return bool
354
     */
355
    protected function isActual(array $productAbstractLocalizedEntity): bool
356
    {
357
        foreach ($productAbstractLocalizedEntity['SpyProductAbstract']['SpyProducts'] as $spyProduct) {
358
            if ($spyProduct['is_active'] && $this->isSearchable($spyProduct, $productAbstractLocalizedEntity['fk_locale'])) {
359
                return true;
360
            }
361
        }
362
363
        return false;
364
    }
365
366
    /**
367
     * @param array $spyProduct
368
     * @param int $idLocale
369
     *
370
     * @return bool
371
     */
372
    protected function isSearchable(array $spyProduct, int $idLocale): bool
373
    {
374
        foreach ($spyProduct['SpyProductSearches'] as $spyProductSearch) {
375
            if ($spyProductSearch['fk_locale'] === $idLocale && $spyProductSearch['is_searchable'] === true) {
376
                return true;
377
            }
378
        }
379
380
        return false;
381
    }
382
383
    /**
384
     * Retrieves the ProductPageSearchTransfer from the storage entity (if it existed already) or populates it from the localized entity.
385
     *
386
     * @param array $productAbstractLocalizedEntity
387
     * @param \Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch $productAbstractPageSearchEntity
388
     * @param bool $isRefresh
389
     *
390
     * @return \Generated\Shared\Transfer\ProductPageSearchTransfer
391
     */
392
    protected function getProductPageSearchTransfer(
393
        array $productAbstractLocalizedEntity,
394
        SpyProductAbstractPageSearch $productAbstractPageSearchEntity,
395
        $isRefresh = false
396
    ): ProductPageSearchTransfer {
397
        if ($isRefresh && !$productAbstractPageSearchEntity->isNew()) {
398
            return $this->refreshProductPageSearchTransfer($productAbstractPageSearchEntity);
399
        }
400
401
        return $this->productPageSearchMapper->mapToProductPageSearchTransfer($productAbstractLocalizedEntity);
402
    }
403
404
    /**
405
     * @param \Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch $productAbstractPageSearchEntity
406
     *
407
     * @return \Generated\Shared\Transfer\ProductPageSearchTransfer
408
     */
409
    protected function refreshProductPageSearchTransfer(
410
        SpyProductAbstractPageSearch $productAbstractPageSearchEntity
411
    ): ProductPageSearchTransfer {
412
        return $this->productPageSearchMapper->mapToProductPageSearchTransferFromJson($productAbstractPageSearchEntity->getStructuredData());
413
    }
414
415
    /**
416
     * @param array<string> $pageDataExpanderPluginNames
417
     *
418
     * @return array<\Spryker\Zed\ProductPageSearch\Dependency\Plugin\ProductPageDataExpanderInterface>
419
     */
420
    protected function getPageDataExpanderPlugins(array $pageDataExpanderPluginNames)
421
    {
422
        if (!$pageDataExpanderPluginNames) {
423
            return $this->pageDataExpanderPlugins;
424
        }
425
426
        $selectedExpanderPlugins = [];
427
        foreach ($pageDataExpanderPluginNames as $pageDataExpanderPluginName) {
428
            $this->assertPageDataExpanderPluginName($pageDataExpanderPluginName);
429
430
            $selectedExpanderPlugins[] = $this->pageDataExpanderPlugins[$pageDataExpanderPluginName];
431
        }
432
433
        return $selectedExpanderPlugins;
434
    }
435
436
    /**
437
     * @param string $pageDataExpanderPluginName
438
     *
439
     * @throws \Spryker\Zed\ProductPageSearch\Business\Exception\PluginNotFoundException
440
     *
441
     * @return void
442
     */
443
    protected function assertPageDataExpanderPluginName($pageDataExpanderPluginName)
444
    {
445
        if (!isset($this->pageDataExpanderPlugins[$pageDataExpanderPluginName])) {
446
            throw new PluginNotFoundException(sprintf('The plugin with this name: %s is not found', $pageDataExpanderPluginName));
447
        }
448
    }
449
450
    /**
451
     * @param array<\Spryker\Zed\ProductPageSearch\Dependency\Plugin\ProductPageDataExpanderInterface> $pageDataExpanderPlugins
452
     * @param array<string, mixed> $productAbstractLocalizedEntity
453
     * @param \Generated\Shared\Transfer\ProductPageSearchTransfer $productPageSearchTransfer
454
     *
455
     * @return void
456
     */
457
    protected function expandPageSearchTransferWithPlugins(
458
        array $pageDataExpanderPlugins,
459
        array $productAbstractLocalizedEntity,
460
        ProductPageSearchTransfer $productPageSearchTransfer
461
    ) {
462
        foreach ($pageDataExpanderPlugins as $pageDataExpanderPlugin) {
463
            $pageDataExpanderPlugin->expandProductPageData($productAbstractLocalizedEntity, $productPageSearchTransfer);
464
        }
465
    }
466
467
    /**
468
     * - Returns a paired array with all provided entities.
469
     * - ProductAbstractLocalizedEntities without ProductAbstractPageSearchEntity are paired with a newly created ProductAbstractPageSearchEntity.
470
     * - ProductAbstractPageSearchEntity without ProductAbstractLocalizedEntities (left outs) are paired with NULL.
471
     * - ProductAbstractLocalizedEntities are paired multiple times per store.
472
     *
473
     * @param array<array<string, mixed>> $productAbstractLocalizedEntities
474
     * @param array<\Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch> $productAbstractPageSearchEntities
475
     * @param \Generated\Shared\Transfer\ProductPageLoadTransfer $productPageLoadTransfer
476
     *
477
     * @return array
478
     */
479
    protected function pairProductAbstractLocalizedEntitiesWithProductAbstractPageSearchEntities(
480
        array $productAbstractLocalizedEntities,
481
        array $productAbstractPageSearchEntities,
482
        ProductPageLoadTransfer $productPageLoadTransfer
483
    ) {
484
        $mappedProductAbstractPageSearchEntities = $this->mapProductAbstractPageSearchEntities($productAbstractPageSearchEntities);
485
486
        $pairs = [];
487
        $productPayloadTransfers = $productPageLoadTransfer->getPayloadTransfers();
488
        foreach ($productAbstractLocalizedEntities as $productAbstractLocalizedEntity) {
489
            [$pairs, $mappedProductAbstractPageSearchEntities] = $this->pairProductAbstractLocalizedEntityWithProductAbstractPageSearchEntityByStoresAndLocale(
490
                $productAbstractLocalizedEntity['fk_product_abstract'],
491
                $productAbstractLocalizedEntity['Locale']['locale_name'],
492
                $productPayloadTransfers[$productAbstractLocalizedEntity['fk_product_abstract']],
493
                $productAbstractLocalizedEntity['SpyProductAbstract']['SpyProductAbstractStores'],
494
                $productAbstractLocalizedEntity,
495
                $mappedProductAbstractPageSearchEntities,
496
                $pairs,
497
            );
498
        }
499
500
        $pairs = $this->pairRemainingProductAbstractPageSearchEntities($mappedProductAbstractPageSearchEntities, $pairs);
501
502
        return $pairs;
503
    }
504
505
    /**
506
     * @param array<int> $productAbstractIds
507
     *
508
     * @return array
509
     */
510
    protected function findProductAbstractLocalizedEntities(array $productAbstractIds)
511
    {
512
        $localesByIdStoreMap = $this->getLocalesByIdStoreMap();
513
        /** @var array<int> $allStoreIds */
514
        $allStoreIds = array_keys($localesByIdStoreMap);
515
        $allLocaleIsoCodes = array_merge(...array_values($localesByIdStoreMap));
516
517
        $productAbstractLocalizedAttributeDataCollection = $this
518
            ->queryContainer
519
            ->queryProductAbstractLocalizedAttributesByProductAbstractIdsAndStoreIdsAndLocaleIds(
520
                $productAbstractIds,
521
                $allStoreIds,
522
                $allLocaleIsoCodes,
523
            )
524
            ->find()
525
            ->getData();
526
527
        $productConcreteEntities = $this->queryContainer
528
            ->queryProductConcretesByAbstractProductIdsAndLocaleIsoCodes($productAbstractIds, $allLocaleIsoCodes)
529
            ->find()
530
            ->getData();
531
532
        $productConcreteIds = array_column($productConcreteEntities, 'id_product');
533
534
        $productSearchEntities = $this->queryContainer
535
            ->queryProductSearchByProductConcreteIdsAndLocaleIsoCodes($productConcreteIds, $allLocaleIsoCodes)
536
            ->find()
537
            ->getData();
538
539
        $productConcreteEntities = $this->hydrateProductConcreteEntitiesWithProductSearchEntities(
540
            $productSearchEntities,
541
            $productConcreteEntities,
542
        );
543
544
        return $this->hydrateProductAbstractLocalizedEntitiesWithProductConcreteEntities(
545
            $productConcreteEntities,
546
            $productAbstractLocalizedAttributeDataCollection,
547
        );
548
    }
549
550
    /**
551
     * @param array $productSearchEntities
552
     * @param array $productConcreteEntities
553
     *
554
     * @return array
555
     */
556
    protected function hydrateProductConcreteEntitiesWithProductSearchEntities(array $productSearchEntities, array $productConcreteEntities): array
557
    {
558
        $productSearchByProductConcreteId = [];
559
560
        foreach ($productSearchEntities as $productSearch) {
561
            $productSearchByProductConcreteId[$productSearch['fk_product']][] = $productSearch;
562
        }
563
564
        foreach ($productConcreteEntities as $key => $productConcreteEntity) {
565
            $productConcreteId = (int)$productConcreteEntity['id_product'];
566
            $productConcreteEntities[$key]['SpyProductSearches'] = $productSearchByProductConcreteId[$productConcreteId] ?? [];
567
        }
568
569
        return $productConcreteEntities;
570
    }
571
572
    /**
573
     * @param array $productCategories
574
     * @param array $productAbstractLocalizedEntities
575
     *
576
     * @return array
577
     */
578
    protected function hydrateProductAbstractLocalizedEntitiesWithProductCategories(array $productCategories, array $productAbstractLocalizedEntities)
579
    {
580
        $productCategoriesByProductAbstractId = [];
581
582
        foreach ($productCategories as $productCategory) {
583
            $productCategoriesByProductAbstractId[$productCategory['fk_product_abstract']][] = $productCategory;
584
        }
585
586
        foreach ($productAbstractLocalizedEntities as $key => $productAbstractLocalizedEntity) {
587
            $productAbstractId = (int)$productAbstractLocalizedEntity['fk_product_abstract'];
588
            $productAbstractLocalizedEntities[$key]['SpyProductAbstract']['SpyProductCategories']
589
                = $productCategoriesByProductAbstractId[$productAbstractId] ?? [];
590
        }
591
592
        return $productAbstractLocalizedEntities;
593
    }
594
595
    /**
596
     * @param array $productConcreteData
597
     * @param array $productAbstractLocalizedEntities
598
     *
599
     * @return array
600
     */
601
    protected function hydrateProductAbstractLocalizedEntitiesWithProductConcreteEntities(
602
        array $productConcreteData,
603
        array $productAbstractLocalizedEntities
604
    ): array {
605
        $productConcretesByProductAbstractId = [];
606
        foreach ($productConcreteData as $productConcrete) {
607
            $productConcretesByProductAbstractId[$productConcrete['fk_product_abstract']][] = $productConcrete;
608
        }
609
610
        foreach ($productAbstractLocalizedEntities as $key => $productAbstractLocalizedEntity) {
611
            $productAbstractId = (int)$productAbstractLocalizedEntity['fk_product_abstract'];
612
            $productAbstractLocalizedEntities[$key]['SpyProductAbstract']['SpyProducts'] = $productConcretesByProductAbstractId[$productAbstractId] ?? [];
613
        }
614
615
        return $productAbstractLocalizedEntities;
616
    }
617
618
    /**
619
     * @param array<int> $productAbstractIds
620
     *
621
     * @return array
622
     */
623
    protected function getProductCategoriesByProductAbstractIds(array $productAbstractIds)
624
    {
625
        return $this->queryContainer->queryAllProductCategories($productAbstractIds)->find()->getData();
626
    }
627
628
    /**
629
     * @param array<int> $productAbstractIds
630
     *
631
     * @return array<\Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch>
632
     */
633
    protected function findProductAbstractPageSearchEntities(array $productAbstractIds)
634
    {
635
        return $this->queryContainer->queryProductAbstractSearchPageByIds($productAbstractIds)->find()->getArrayCopy();
636
    }
637
638
    /**
639
     * @param array<\Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch> $productAbstractPageSearchEntities
640
     *
641
     * @return array
642
     */
643
    protected function mapProductAbstractPageSearchEntities(array $productAbstractPageSearchEntities)
644
    {
645
        $mappedProductAbstractPageSearchEntities = [];
646
        foreach ($productAbstractPageSearchEntities as $entity) {
647
            $mappedProductAbstractPageSearchEntities[$entity->getFkProductAbstract()][$entity->getStore()][$entity->getLocale()] = $entity;
648
        }
649
650
        return $mappedProductAbstractPageSearchEntities;
651
    }
652
653
    /**
654
     * @param array $mappedProductAbstractPageSearchEntities
655
     * @param array $pairs
656
     *
657
     * @return array
658
     */
659
    protected function pairRemainingProductAbstractPageSearchEntities(array $mappedProductAbstractPageSearchEntities, array $pairs)
660
    {
661
        array_walk_recursive($mappedProductAbstractPageSearchEntities, function (SpyProductAbstractPageSearch $productAbstractPageSearchEntity) use (&$pairs) {
662
            $pairs[] = [
663
                static::PRODUCT_ABSTRACT_LOCALIZED_ENTITY => null,
664
                static::PRODUCT_ABSTRACT_PAGE_SEARCH_ENTITY => $productAbstractPageSearchEntity,
665
                static::LOCALE_NAME => $productAbstractPageSearchEntity->getLocale(),
666
                static::STORE_NAME => $productAbstractPageSearchEntity->getStore(),
667
            ];
668
        });
669
670
        return $pairs;
671
    }
672
673
    /**
674
     * @param int $idProductAbstract
675
     * @param string $localeName
676
     * @param \Generated\Shared\Transfer\ProductPayloadTransfer $productPayloadTransfer
677
     * @param array $productAbstractStores
678
     * @param array $productAbstractLocalizedEntity
679
     * @param array $mappedProductAbstractPageSearchEntities
680
     * @param array $pairs
681
     *
682
     * @return array
683
     */
684
    protected function pairProductAbstractLocalizedEntityWithProductAbstractPageSearchEntityByStoresAndLocale(
685
        $idProductAbstract,
686
        $localeName,
687
        ProductPayloadTransfer $productPayloadTransfer,
688
        array $productAbstractStores,
689
        array $productAbstractLocalizedEntity,
690
        array $mappedProductAbstractPageSearchEntities,
691
        array $pairs
692
    ) {
693
        $localesByIdStoreMap = $this->getLocalesByIdStoreMap();
694
695
        foreach ($productAbstractStores as $productAbstractStore) {
696
            $idStore = $productAbstractStore['fk_store'];
697
            $storeName = $productAbstractStore['SpyStore']['name'];
698
699
            if (!in_array($localeName, $localesByIdStoreMap[$idStore])) {
700
                continue;
701
            }
702
703
            $productAbstractLocalizedEntity[SharedProductPageSearchConfig::PRODUCT_ABSTRACT_PAGE_LOAD_DATA] = $productPayloadTransfer;
704
705
            $searchEntity = $mappedProductAbstractPageSearchEntities[$idProductAbstract][$storeName][$localeName] ??
706
                new SpyProductAbstractPageSearch();
707
708
            unset($mappedProductAbstractPageSearchEntities[$idProductAbstract][$storeName][$localeName]);
709
710
            $pairs[] = [
711
                static::PRODUCT_ABSTRACT_LOCALIZED_ENTITY => $productAbstractLocalizedEntity,
712
                static::PRODUCT_ABSTRACT_PAGE_SEARCH_ENTITY => $searchEntity,
713
                static::LOCALE_NAME => $localeName,
714
                static::STORE_NAME => $storeName,
715
            ];
716
        }
717
718
        return [$pairs, $mappedProductAbstractPageSearchEntities];
719
    }
720
721
    /**
722
     * @param array $productAbstractLocalizedEntities
723
     * @param array<int> $productAbstractIds
724
     *
725
     * @return array
726
     */
727
    protected function hydrateProductAbstractLocalizedEntitiesWithProductAbstractAddToCartSku(
728
        array $productAbstractLocalizedEntities,
729
        array $productAbstractIds
730
    ): array {
731
        $productAbstractStoreIds = [];
732
        foreach ($productAbstractLocalizedEntities as $productAbstractLocalizedEntity) {
733
            $productAbstractId = (int)$productAbstractLocalizedEntity['fk_product_abstract'];
734
            foreach ($productAbstractLocalizedEntity['SpyProductAbstract']['SpyProductAbstractStores'] as $productAbstractStoreData) {
735
                $storeId = (int)$productAbstractStoreData['SpyStore']['id_store'];
736
                $productAbstractStoreIds[$productAbstractId][] = $storeId;
737
            }
738
        }
739
740
        $productConcreteSkuMapByIdProductAbstract = $this->addToCartSkuReader->getProductAbstractAddToCartSkus($productAbstractIds, $productAbstractStoreIds);
741
742
        foreach ($productAbstractLocalizedEntities as &$productAbstractLocalizedEntity) {
743
            $productAbstractId = (int)$productAbstractLocalizedEntity['fk_product_abstract'];
744
            $productAbstractLocalizedEntity[ProductPageSearchTransfer::ADD_TO_CART_SKU] = $productConcreteSkuMapByIdProductAbstract[$productAbstractId] ?? null;
745
        }
746
747
        return $productAbstractLocalizedEntities;
748
    }
749
750
    /**
751
     * @param array $pairedEntities
752
     * @param bool $isRefresh
753
     *
754
     * @return array
755
     */
756
    protected function mapPairedEntitiesToProductPageSearchTransfers(
757
        array $pairedEntities,
758
        bool $isRefresh
759
    ): array {
760
        $productAbstractPageSearchTransfers = [];
761
762
        foreach ($pairedEntities as $pairedEntity) {
763
            /** @var array|null $productAbstractLocalizedEntity */
764
            $productAbstractLocalizedEntity = $pairedEntity[static::PRODUCT_ABSTRACT_LOCALIZED_ENTITY] ?? null;
765
            /** @var \Orm\Zed\ProductPageSearch\Persistence\SpyProductAbstractPageSearch $productAbstractPageSearchEntity */
766
            $productAbstractPageSearchEntity = $pairedEntity[static::PRODUCT_ABSTRACT_PAGE_SEARCH_ENTITY];
767
768
            if (!$productAbstractLocalizedEntity) {
769
                continue;
770
            }
771
772
            $productAbstractPageSearchTransfers[] = $this->getProductPageSearchTransfer(
773
                $productAbstractLocalizedEntity,
774
                $productAbstractPageSearchEntity,
775
                $isRefresh,
776
            );
777
        }
778
779
        return $productAbstractPageSearchTransfers;
780
    }
781
782
    /**
783
     * @param array<\Generated\Shared\Transfer\ProductPageSearchTransfer> $productPageSearchTransfers
784
     *
785
     * @return array<\Generated\Shared\Transfer\ProductPageSearchTransfer>
786
     */
787
    protected function executeProductPageSearchCollectionFilterPlugins(array $productPageSearchTransfers): array
788
    {
789
        foreach ($this->productPageSearchCollectionFilterPlugins as $productPageSearchCollectionFilterPlugin) {
790
            $productPageSearchTransfers = $productPageSearchCollectionFilterPlugin->filter($productPageSearchTransfers);
791
        }
792
793
        return $productPageSearchTransfers;
794
    }
795
796
    /**
797
     * @param array<\Generated\Shared\Transfer\ProductPageSearchTransfer> $productPageSearchTransfers
798
     *
799
     * @return array<string, array<int, list<\Generated\Shared\Transfer\ProductPageSearchTransfer>>>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, array<int,...ctPageSearchTransfer>>> at position 8 could not be parsed: Expected '>' at position 8, but found 'list'.
Loading history...
800
     */
801
    protected function getProductPageSearchTransfersIndexedByLocaleAndIdProductAbstract(array $productPageSearchTransfers): array
802
    {
803
        $productPageSearchTransfersIndexedByLocaleAndIdProductAbstract = [];
804
        foreach ($productPageSearchTransfers as $productPageSearchTransfer) {
805
            $idProductAbstract = $productPageSearchTransfer->getIdProductAbstractOrFail();
806
            $locale = $productPageSearchTransfer->getLocaleOrFail();
807
            $productPageSearchTransfersIndexedByLocaleAndIdProductAbstract[$locale][$idProductAbstract][] = $productPageSearchTransfer;
808
        }
809
810
        return $productPageSearchTransfersIndexedByLocaleAndIdProductAbstract;
811
    }
812
813
    /**
814
     * @param array<string, array<int, list<\Generated\Shared\Transfer\ProductPageSearchTransfer>>> $productPageSearchTransfersIndexedByLocaleAndIdProductAbstract
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<string, array<int,...ctPageSearchTransfer>>> at position 8 could not be parsed: Expected '>' at position 8, but found 'list'.
Loading history...
815
     * @param int $idProductAbstract
816
     * @param string $locale
817
     * @param string $storeName
818
     *
819
     * @return \Generated\Shared\Transfer\ProductPageSearchTransfer|null
820
     */
821
    protected function findProductPageSearchTransferFromIndexedList(
822
        array $productPageSearchTransfersIndexedByLocaleAndIdProductAbstract,
823
        int $idProductAbstract,
824
        string $locale,
825
        string $storeName
826
    ): ?ProductPageSearchTransfer {
827
        if (!isset($productPageSearchTransfersIndexedByLocaleAndIdProductAbstract[$locale][$idProductAbstract])) {
828
            return null;
829
        }
830
831
        $productPageSearchTransfers = $productPageSearchTransfersIndexedByLocaleAndIdProductAbstract[$locale][$idProductAbstract];
832
        foreach ($productPageSearchTransfers as $productPageSearchTransfer) {
833
            if ($productPageSearchTransfer->getStore() === $storeName) {
834
                return $productPageSearchTransfer;
835
            }
836
        }
837
838
        return $productPageSearchTransfers[0] ?? null;
839
    }
840
841
    /**
842
     * @return array<int, array<string>>
843
     */
844
    protected function getLocalesByIdStoreMap(): array
845
    {
846
        if (static::$localesByIdStoreMap === null) {
0 ignored issues
show
introduced by
The condition static::localesByIdStoreMap === null is always false.
Loading history...
847
            static::$localesByIdStoreMap = [];
848
849
            foreach ($this->storeFacade->getAllStores() as $storeTransfer) {
850
                static::$localesByIdStoreMap[(int)$storeTransfer->getIdStore()] = $storeTransfer->getAvailableLocaleIsoCodes();
851
            }
852
        }
853
854
        return static::$localesByIdStoreMap;
855
    }
856
}
857