Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
SkuRepository.php
1<?php
2
4
14
24{
26 protected $factory;
31
40 public function __construct(
45 )
46 {
47 parent::__construct($factory, $iblockInfo);
48 $this->productRepository = $productRepository;
49 $this->propertyRepository = $propertyRepository;
50 }
51
57 {
58 $callback = function (array $params) use ($product) {
59 yield from $this->getSkuIteratorForProduct($product, $params);
60 };
61
62 return $this->factory
63 ->createCollection()
64 ->setIteratorCallback($callback)
65 ;
66 }
67
76 public function getEntitiesByProduct(BaseProduct $product, array $params): \Generator
77 {
78 return $this->getSkuIteratorForProduct($product, $params);
79 }
80
86 {
87 $callback = function (array $params) use ($product) {
88 yield from $this->getSkuIteratorEagerLoading($product, $params);
89 };
90
91 return $this->factory
92 ->createCollection()
93 ->setIteratorCallback($callback)
94 ;
95 }
96
97 public function getEntitiesBy($params): array
98 {
99 $sku = parent::getEntitiesBy($params);
100
101 if (!empty($sku))
102 {
103 $this->loadParentProducts(...$sku);
104 }
105
106 return $sku;
107 }
108
109 protected function getAdditionalFilter(): array
110 {
111 $filter = parent::getAdditionalFilter();
112 $filter['IBLOCK_ID'] = $this->iblockInfo->getSkuIblockId();
113
114 return $filter;
115 }
116
117 protected function getAdditionalProductFilter(): array
118 {
119 $filter = parent::getAdditionalProductFilter();
120
121 $filter['=TYPE'] = [
125 ];
126
127 return $filter;
128 }
129
130 protected function makeEntity(array $fields = []): BaseIblockElementEntity
131 {
132 $type = (int)($fields['TYPE'] ?? 0);
133
135 {
136 $entityClass = $this->factory::SKU;
137 }
138 else
139 {
140 $entityClass = $this->factory::SIMPLE_SKU;
141 }
142
143 return $this->factory->createEntity($entityClass);
144 }
145
146 private function loadParentProducts(BaseSku ...$skuItems): void
147 {
148 $skuByProductMap = $this->getSkuByProductMap($skuItems);
149
150 if (!empty($skuByProductMap))
151 {
152 $products = $this->productRepository->getEntitiesBy([
153 'filter' => [
154 '=ID' => array_keys($skuByProductMap),
155 ],
156 ]);
157
159 foreach ($products as $product)
160 {
161 $productSkuItems = $skuByProductMap[$product->getId()] ?? [];
162 $skuCollection = $this->getCollectionByProduct($product)
163 ->setParent($product)
164 ->add(...$productSkuItems)
165 ;
166 $product->setSkuCollection($skuCollection);
167 }
168 }
169 }
170
171 private function getSkuByProductMap(array $skuItems): array
172 {
173 $skuByProductMap = [];
174
175 $skuMap = [];
177 foreach ($skuItems as $sku)
178 {
179 if ($sku->getParent() === null)
180 {
181 $skuMap[$sku->getId()] = $sku;
182 }
183 }
184
185 if (!empty($skuMap))
186 {
187 $skuPropertyId = $this->iblockInfo->getSkuPropertyId();
188 $propertyValuesIterator = \CIBlockElement::GetPropertyValues(
189 $this->iblockInfo->getSkuIblockId(),
190 ['ID' => array_keys($skuMap)],
191 false,
192 ['ID' => $skuPropertyId]
193 );
194
195 while ($propertyValues = $propertyValuesIterator->fetch())
196 {
197 $productId = $propertyValues[$skuPropertyId];
198 $sku = $skuMap[$propertyValues['IBLOCK_ELEMENT_ID']];
199
200 $skuByProductMap[$productId][] = $sku;
201 }
202 }
203
204 return $skuByProductMap;
205 }
206
207 private function getSkuIteratorForProduct(BaseProduct $product, array $params = []): \Generator
208 {
209 if ($product->isSimple())
210 {
211 if ($product->getSkuCollection()->isEmpty())
212 {
213 yield $this->createEntity();
214 }
215 }
216 elseif (!$product->isNew())
217 {
218 $params['filter']['PROPERTY_' . $this->iblockInfo->getSkuPropertyId()] = $product->getId();
219 $params['order']['ID'] ??= 'DESC';
220
221 foreach ($this->getList($params) as $item)
222 {
223 yield $this->createEntity($item);
224 }
225 }
226 }
227
228 private function getSkuIteratorEagerLoading(BaseProduct $product, array $params = []): \Generator
229 {
230 if ($product->isSimple())
231 {
232 if ($product->getSkuCollection()->isEmpty())
233 {
234 yield $this->createEntity();
235 }
236 }
237 elseif (!$product->isNew())
238 {
239 $params['filter']['PROPERTY_' . $this->iblockInfo->getSkuPropertyId()] = $product->getId();
240 $params['order']['ID'] = 'DESC';
241
242 $items = [];
243 foreach ($this->getList($params) as $item)
244 {
245 $items[$item['ID']] = $item;
246 }
247
248 $skuIds = array_keys($items);
249
250 $propertySettings = $this->propertyRepository->getPropertiesSettingsByFilter([
251 '=IBLOCK_ID' => $this->iblockInfo->getSkuIblockId(),
252 ]);
253
254 $propertyElementMap = $this->getPropertyMapBySkuIds($skuIds, $propertySettings);
255
256 foreach ($items as $skuId => $item)
257 {
258 $propertyCollection = $this->propertyRepository->createCollection();
259
260 foreach ($propertySettings as $setting)
261 {
262 if (isset($propertyElementMap[$skuId][$setting['ID']]))
263 {
264 $propertyItem = $propertyElementMap[$skuId][$setting['ID']];
265 }
266 else
267 {
268 $propertyItem = $this->propertyRepository->createEntity([], $setting);
269 }
270
271 if ($propertyItem)
272 {
273 $propertyCollection->add($propertyItem);
274 }
275 }
276
277 yield $this->createEntity($item, $propertyCollection);
278 }
279 }
280 }
281
287 private function getPropertyMapBySkuIds(array $skuIds, array $propertySettings): array
288 {
289 $skuPropertyFilter = [
290 'filter' => [
291 'IBLOCK_ID' => $this->iblockInfo->getSkuIblockId(),
292 'ID' => $skuIds,
293 ],
294 ];
295
296 $properties = $this->propertyRepository->getEntitiesBy($skuPropertyFilter, $propertySettings);
297 $propertyElementMap = [];
298
300 foreach ($properties as $property)
301 {
302 $elementId = $property->getSetting('IBLOCK_ELEMENT_ID');
303
304 if ($elementId > 0)
305 {
306 $propertyElementMap[$elementId] = $propertyElementMap[$elementId] ?? [];
307 $propertyElementMap[$elementId][$property->getSetting('ID')] = $property;
308 }
309 }
310
311 return $propertyElementMap;
312 }
313
314 protected function createEntity(array $fields = [], PropertyCollection $propertyCollection = null): BaseIblockElementEntity
315 {
316 $entity = parent::createEntity($fields);
317
318 if ($propertyCollection)
319 {
320 $entity->setPropertyCollection($propertyCollection);
321 }
322
323 return $entity;
324 }
325
326 public function setDetailUrlTemplate(?string $template): BaseIblockElementRepository
327 {
328 if (isset($this->productRepository))
329 {
330 if ($this->productRepository->getDetailUrlTemplate() === null)
331 {
332 $this->productRepository->setDetailUrlTemplate($template);
333 $this->productRepository->setAutoloadDetailUrl($template !== null);
334 }
335 }
336
337 return parent::setDetailUrlTemplate($template);
338 }
339
341 {
342 if (isset($this->productRepository))
343 {
344 $this->productRepository->setAutoloadDetailUrl($state);
345 }
346
347 return parent::setAutoloadDetailUrl($state);
348 }
349
350 public function getCountByProductId(int $productId): int
351 {
352 $filter = [
353 'PROPERTY_' . $this->iblockInfo->getSkuPropertyId() => $productId,
354 ];
355
356 return \CIBlockElement::GetList(
357 [],
358 array_merge(
359 [
360 // 'ACTIVE' => 'Y',
361 // 'ACTIVE_DATE' => 'Y',
362 ],
363 $filter,
364 $this->getAdditionalFilter()
365 ),
366 []
367 );
368 }
369}
__construct(SkuFactory $factory, IblockInfo $iblockInfo, ProductRepositoryContract $productRepository, PropertyRepositoryContract $propertyRepository)
loadEagerCollectionByProduct(BaseProduct $product)
getEntitiesByProduct(BaseProduct $product, array $params)
createEntity(array $fields=[], PropertyCollection $propertyCollection=null)
getCollectionByProduct(BaseProduct $product)