EcondaProductCollector::getSmallImageUrl()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
3
/**
4
 * MIT License
5
 * Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file.
6
 */
7
8
namespace SprykerEco\Zed\Econda\Business\Collector\File;
9
10
use Generated\Shared\Transfer\LocaleTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\LocaleTransfer 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...
11
use Generated\Shared\Transfer\StorageProductImageTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfe...ageProductImageTransfer 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...
12
use Orm\Zed\Category\Persistence\Map\SpyCategoryTableMap;
13
use Propel\Runtime\ActiveQuery\Criteria;
14
use Propel\Runtime\Collection\Collection;
15
use Propel\Runtime\Collection\ObjectCollection;
16
use Spryker\Shared\SqlCriteriaBuilder\CriteriaBuilder\CriteriaBuilderInterface;
17
use Spryker\Zed\ProductCategory\Persistence\ProductCategoryQueryContainerInterface;
18
use Spryker\Zed\ProductImage\Persistence\ProductImageQueryContainerInterface;
19
use SprykerEco\Zed\Econda\Business\Collector\AbstractDatabaseCollector;
20
use SprykerEco\Zed\Econda\Dependency\Facade\EcondaToPriceProductFacadeInterface;
21
use SprykerEco\Zed\Econda\EcondaConfig;
22
use SprykerEco\Zed\Econda\Persistence\Econda\AbstractEcondaPdoQuery;
23
24
class EcondaProductCollector extends AbstractDatabaseCollector
25
{
26
    // CSV File Columns
27
    protected const ID_COLUMN = 'ID';
28
    protected const NAME_COLUMN = 'Name';
29
    protected const DESCRIPTION_COLUMN = 'Description';
30
    protected const PRODUCT_URL_COLUMN = 'ProductURL';
31
    protected const IMAGE_URL_COLUMN = 'ImageURL';
32
    protected const PRICE_COLUMN = 'Price';
33
    protected const STOCK_COLUMN = 'Stock';
34
    protected const PRODUCT_CATEGORY_COLUMN = 'ProductCategory';
35
36
    // Internal Query Fields
37
    protected const ID_PRODUCT_ABSTRACT = 'id_product_abstract';
38
    protected const SKU = 'sku';
39
    protected const URL = 'url';
40
    protected const NAME = 'name';
41
    protected const DESCRIPTION = 'description';
42
    protected const META_DESCRIPTION = 'meta_description';
43
    protected const QUANTITY = 'quantity';
44
    protected const ID_PRODUCT_CONCRETE = 'id_product';
45
    protected const DEFAULT_QUERY_FIELD = 'default';
46
    protected const EXTERNAL_URL_SMALL_QUERY_FIELD = 'externalUrlSmall';
47
48
    protected const RESOURCE_TYPE = 'products';
49
50
    /**
51
     * @var \SprykerEco\Zed\Econda\EcondaConfig
52
     */
53
    protected $config;
54
55
    /**
56
     * @var \Spryker\Zed\ProductCategory\Persistence\ProductCategoryQueryContainerInterface
57
     */
58
    protected $productCategoryQueryContainer;
59
60
    /**
61
     * @var \SprykerEco\Zed\Econda\Dependency\Facade\EcondaToPriceProductFacadeInterface
62
     */
63
    protected $priceProductFacade;
64
65
    /**
66
     * @var \Propel\Runtime\Collection\Collection
67
     */
68
    protected $categoryCacheCollection;
69
70
    /**
71
     * @var \Spryker\Zed\ProductImage\Persistence\ProductImageQueryContainerInterface
72
     */
73
    protected $productImageQueryContainer;
74
75
    /**
76
     * @param \Spryker\Shared\SqlCriteriaBuilder\CriteriaBuilder\CriteriaBuilderInterface $criteria
77
     * @param \SprykerEco\Zed\Econda\Persistence\Econda\AbstractEcondaPdoQuery $econdaPdoQuery
78
     * @param \Spryker\Zed\ProductCategory\Persistence\ProductCategoryQueryContainerInterface $productCategoryQueryContainer
79
     * @param \Spryker\Zed\ProductImage\Persistence\ProductImageQueryContainerInterface $productImageQueryContainer
80
     * @param \SprykerEco\Zed\Econda\Dependency\Facade\EcondaToPriceProductFacadeInterface $priceProductFacade
81
     * @param \SprykerEco\Zed\Econda\EcondaConfig $config
82
     */
83
    public function __construct(
84
        CriteriaBuilderInterface $criteria,
85
        AbstractEcondaPdoQuery $econdaPdoQuery,
86
        ProductCategoryQueryContainerInterface $productCategoryQueryContainer,
87
        ProductImageQueryContainerInterface $productImageQueryContainer,
88
        EcondaToPriceProductFacadeInterface $priceProductFacade,
89
        EcondaConfig $config
90
    ) {
91
        parent::__construct($criteria, $econdaPdoQuery);
92
93
        $this->productCategoryQueryContainer = $productCategoryQueryContainer;
94
        $this->productImageQueryContainer = $productImageQueryContainer;
95
        $this->priceProductFacade = $priceProductFacade;
96
        $this->categoryCacheCollection = new Collection([]);
97
        $this->config = $config;
98
    }
99
100
    /**
101
     * @param array $collectedSet
102
     * @param \Generated\Shared\Transfer\LocaleTransfer $localeTransfer
103
     *
104
     * @return array
105
     */
106
    protected function collectData(array $collectedSet, LocaleTransfer $localeTransfer): array
107
    {
108
        $setToExport = [];
109
110
        foreach ($collectedSet as $collectedItemData) {
111
            $setToExport[] = $this->collectItem($collectedItemData);
112
        }
113
114
        return $setToExport;
115
    }
116
117
    /**
118
     * @param array $collectItemData
119
     *
120
     * @return array
121
     */
122
    protected function collectItem(array $collectItemData): array
123
    {
124
        $imageUrl = $this->getImageUrlFromItemData($collectItemData);
125
126
        return [
127
            static::ID_COLUMN => $collectItemData[static::SKU],
128
            static::NAME_COLUMN => $collectItemData[static::NAME],
129
            static::DESCRIPTION_COLUMN => $collectItemData[static::META_DESCRIPTION],
130
            static::PRODUCT_URL_COLUMN => $this->config->getHostYves() . $collectItemData[static::URL],
131
            static::IMAGE_URL_COLUMN => $imageUrl,
132
            static::PRICE_COLUMN => number_format($this->findPriceBySku($collectItemData[static::SKU]) / 100, 2),
133
            static::STOCK_COLUMN => (int)$collectItemData[static::QUANTITY],
134
            static::PRODUCT_CATEGORY_COLUMN => implode($this->config->getCsvCategoryDelimiter(), $this->generateCategories($collectItemData[static::ID_PRODUCT_ABSTRACT])),
135
        ];
136
    }
137
138
    /**
139
     * @return string
140
     */
141
    protected function collectResourceType(): string
142
    {
143
        return static::RESOURCE_TYPE;
144
    }
145
146
    /**
147
     * @param string $sku
148
     *
149
     * @return int
150
     */
151
    protected function findPriceBySku($sku): int
152
    {
153
        return $this->priceProductFacade->findPriceBySku($sku);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->priceProdu...e->findPriceBySku($sku) could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
154
    }
155
156
    /**
157
     * @param int $idProductAbstract
158
     *
159
     * @return array
160
     */
161
    protected function generateCategories($idProductAbstract): array
162
    {
163
        if ($this->categoryCacheCollection->offsetExists($idProductAbstract)) {
164
            return $this->categoryCacheCollection->get($idProductAbstract);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->categoryCa...get($idProductAbstract) could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
165
        }
166
167
        $productCategoryMappings = $this->getProductCategoryMappings($idProductAbstract);
168
169
        $categories = [];
170
        foreach ($productCategoryMappings as $mapping) {
171
            $categories[] = $mapping->getSpyCategory()->getIdCategory();
172
        }
173
174
        $this->categoryCacheCollection->set($idProductAbstract, $categories);
175
176
        return $categories;
177
    }
178
179
    /**
180
     * @param int $idProductAbstract
181
     *
182
     * @return \Orm\Zed\ProductCategory\Persistence\SpyProductCategory[]|\Propel\Runtime\Collection\ObjectCollection
183
     */
184
    protected function getProductCategoryMappings($idProductAbstract): ObjectCollection
185
    {
186
        $spyProductCategoryQuery = $this->productCategoryQueryContainer
187
            ->queryLocalizedProductCategoryMappingByIdProduct($idProductAbstract);
188
189
        $spyProductCategoryQuery->innerJoinSpyCategory()
190
            ->addAnd(
191
                SpyCategoryTableMap::COL_IS_ACTIVE,
192
                true,
193
                Criteria::EQUAL
194
            );
195
196
        return $spyProductCategoryQuery
197
            ->orderByProductOrder()
198
            ->find();
199
    }
200
201
    /**
202
     * @param int $idProductAbstract
203
     * @param int $idProductConcrete
204
     *
205
     * @return array
206
     */
207
    protected function generateProductConcreteImageSets($idProductAbstract, $idProductConcrete): array
208
    {
209
        $imageSets = $this->productImageQueryContainer
210
            ->queryProductImageSet()
211
            ->filterByFkProductAbstract($idProductAbstract)
212
            ->_or()
213
            ->filterByFkProduct($idProductConcrete)
214
            ->find();
215
216
        $result = [];
217
        foreach ($imageSets as $imageSetEntity) {
218
            $result[$imageSetEntity->getName()] = [];
219
            $productsToImages = $imageSetEntity->getSpyProductImageSetToProductImages(
220
                $this->productImageQueryContainer->queryProductImageSetToProductImage()
221
                    ->orderBySortOrder(Criteria::DESC)
222
            );
223
            foreach ($productsToImages as $productToImageEntity) {
224
                $imageEntity = $productToImageEntity->getSpyProductImage();
225
                $result[$imageSetEntity->getName()][] = [
226
                    StorageProductImageTransfer::ID_PRODUCT_IMAGE => $imageEntity->getIdProductImage(),
227
                    StorageProductImageTransfer::EXTERNAL_URL_LARGE => $imageEntity->getExternalUrlLarge(),
228
                    StorageProductImageTransfer::EXTERNAL_URL_SMALL => $imageEntity->getExternalUrlSmall(),
229
                ];
230
            }
231
        }
232
233
        return $result;
234
    }
235
236
    /**
237
     * @param array $collectItemData
238
     *
239
     * @return string
240
     */
241
    protected function getImageUrlFromItemData(array $collectItemData): string
242
    {
243
        $imageSet = $this->generateProductConcreteImageSets(
244
            $collectItemData[static::ID_PRODUCT_ABSTRACT],
245
            $collectItemData[static::ID_PRODUCT_CONCRETE]
246
        );
247
248
        return $this->getSmallPictureUrlFromDefaultImageSet($imageSet);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getSmallPi...aultImageSet($imageSet) could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
249
    }
250
251
    /**
252
     * @param array $imageSet
253
     *
254
     * @return string|null
255
     */
256
    protected function getSmallPictureUrlFromDefaultImageSet(array $imageSet): ?string
257
    {
258
        $defaultImageSet = $this->getDefaultImageSet($imageSet);
259
260
        if (is_array($defaultImageSet[0])) {
261
            return $this->getSmallImageUrl($defaultImageSet[0]);
262
        }
263
264
        return null;
265
    }
266
267
    /**
268
     * @param array $imageSet
269
     *
270
     * @return array
271
     */
272
    protected function getDefaultImageSet(array $imageSet): array
273
    {
274
        if (array_key_exists(static::DEFAULT_QUERY_FIELD, $imageSet) && is_array($imageSet[static::DEFAULT_QUERY_FIELD])) {
275
            return $imageSet[static::DEFAULT_QUERY_FIELD];
276
        }
277
278
        return [];
279
    }
280
281
    /**
282
     * @param array $imageArray
283
     *
284
     * @return string
285
     */
286
    protected function getSmallImageUrl(array $imageArray): string
287
    {
288
        if (array_key_exists(static::EXTERNAL_URL_SMALL_QUERY_FIELD, $imageArray)) {
289
            return $imageArray[static::EXTERNAL_URL_SMALL_QUERY_FIELD];
290
        }
291
292
        return '';
293
    }
294
}
295