Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
baserefreshstrategy.php
1<?php
2
4
17
18Main\Localization\Loc::loadMessages(__FILE__);
19
20abstract class BaseRefreshStrategy
21{
22 const REFRESH_FIELD = 'DATE_REFRESH';
23
24 protected $data;
25 protected $refreshGap;
26
27 public function __construct(array $data = null)
28 {
29 $this->data = $data;
30 }
31
32 protected function getBasketItemRefreshTimestamp(BasketItemBase $basketItem)
33 {
35 $refreshDate = $basketItem->getField(self::REFRESH_FIELD);
36 if ($refreshDate)
37 {
38 return $refreshDate->getTimestamp();
39 }
40
41 return 0;
42 }
43
44 protected function isBasketItemChanged(BasketItemBase $basketItem)
45 {
46 $changedValues = $basketItem->getFields()->getChangedValues();
47
48 // remove not meaningful field
49 unset($changedValues[self::REFRESH_FIELD]);
50
51 return !empty($changedValues);
52 }
53
54 protected function getBasketRefreshGapTime()
55 {
56 if (!isset($this->refreshGap))
57 {
58 $this->refreshGap = (int)Option::get('sale', 'basket_refresh_gap', 0);
59 }
60
61 return $this->refreshGap;
62 }
63
64 protected function getBasketIndexList(BasketBase $basket)
65 {
66 $basketIndexList = array();
67
69 foreach ($basket as $basketItem)
70 {
71 $providerName = $basketItem->getProviderName();
72
73 if (trim((string)$providerName) === '')
74 {
75 $callbackFunction = $basketItem->getCallbackFunction();
76 if (!empty($callbackFunction))
77 {
78 $providerName = $callbackFunction;
79 }
80 else
81 {
82 $providerName = null;
83 }
84 }
85
86 if (!empty($providerName) && $providerName[0] == "\\")
87 {
88 $providerName = ltrim($providerName, '\\');
89 }
90
91 $basketIndexList[$providerName][$basketItem->getProductId()][] = $basketItem;
92 }
93
94 return $basketIndexList;
95 }
96
97 protected function updateBasket(BasketBase $basket, array $productDataList)
98 {
99 $result = new Result();
100 $changedBasketItems = array();
101
102 $basketIndexList = $this->getBasketIndexList($basket);
103
104 foreach ($productDataList as $providerName => $productValueList)
105 {
106 foreach ($productValueList as $productId => $productData)
107 {
108 if (empty($basketIndexList[$providerName][$productId]))
109 {
110 $basketIndexList[$providerName][$productId][] = $basket->createItem($productData['MODULE_ID'], $productData['PRODUCT_ID']);
111 }
112
114 foreach ($basketIndexList[$providerName][$productId] as $item)
115 {
116 if ($item && isset($productData['DELETE']) && $productData['DELETE'])
117 {
118 $item->delete();
119 continue;
120 }
121
122 $r = $this->updateBasketItem($item, $productData);
123 if (!$r->isSuccess())
124 {
125 $result->addErrors($r->getErrors());
126 }
127
128 if ($this->isBasketItemChanged($item))
129 {
130 $changedBasketItems[] = $item->getBasketCode();
131 }
132 }
133 }
134 }
135
136 $result->addData(array(
137 'CHANGED_BASKET_ITEMS' => $changedBasketItems
138 ));
139
140 return $result;
141 }
142
143 protected function updateBasketItem(BasketItemBase $item, $data)
144 {
145 $result = new Result();
146
147 if (!empty($data))
148 {
149 $preparedData = $this->prepareData($item, $data);
150
151 if (!$preparedData)
152 {
153 return $result;
154 }
155
156 if (!$item->isCustomPrice() && isset($preparedData['DISCOUNT_PRICE']) && isset($preparedData['BASE_PRICE']))
157 {
158 $preparedData['PRICE'] = $preparedData['BASE_PRICE'] - $preparedData['DISCOUNT_PRICE'];
159 }
160
161 if (
162 empty($preparedData)
163 || (isset($preparedData['QUANTITY']) && $preparedData['QUANTITY'] <= 0)
164 || (isset($data['ACTIVE']) && $data['ACTIVE'] === 'N')
165 )
166 {
167 $preparedData['CAN_BUY'] = 'N';
168 unset($preparedData['QUANTITY']);
169 }
170
172 $event = new Main\Event('sale', EventActions::EVENT_ON_BASKET_ITEM_REFRESH_DATA, array(
173 'ENTITY' => $item,
174 'VALUES' => $data,
175 'PREPARED_VALUES' => $preparedData
176 ));
177 $event->send();
178
179 if ($event->getResults())
180 {
182 foreach ($event->getResults() as $eventResult)
183 {
184 if ($eventResult->getType() == Main\EventResult::ERROR)
185 {
186 $errorMsg = new ResultError(
187 Main\Localization\Loc::getMessage('SALE_EVENT_ON_BASKET_ITEM_REFRESH_DATA'),
188 'SALE_EVENT_ON_BASKET_ITEM_REFRESH_DATA'
189 );
190 if ($eventResultData = $eventResult->getParameters())
191 {
192 if (isset($eventResultData) && $eventResultData instanceof ResultError)
193 {
195 $errorMsg = $eventResultData;
196 }
197 }
198
199 $result->addError($errorMsg);
200 }
201 }
202 }
203
204 if ($this->getBasketRefreshGapTime() !== 0)
205 {
206 $item->setFieldNoDemand(self::REFRESH_FIELD, new DateTime());
207 }
208 }
209 else
210 {
211 $preparedData['CAN_BUY'] = 'N';
212 }
213
215 $r = $this->applyRefreshResult($item, $preparedData);
216 if (!$r->isSuccess())
217 {
218 $result->addErrors($r->getErrors());
219 }
220
221 return $result;
222 }
223
224 protected function prepareData(BasketItemBase $item, $data)
225 {
226 if (empty($data))
227 {
228 return false;
229 }
230
231 $preparedData = array();
232
235 $basketItemClassName = $registry->getBasketItemClassName();
236
237 if (!empty($data['PRICE_LIST']))
238 {
239 $basketItemCode = $item->getBasketCode();
240
241 if (!empty($data['PRICE_LIST'][$basketItemCode]))
242 {
243 $priceData = $data['PRICE_LIST'][$basketItemCode];
244
245 if (!isset($priceData['QUANTITY']) && isset($priceData['AVAILABLE_QUANTITY']))
246 {
247 $priceData['QUANTITY'] = $priceData['AVAILABLE_QUANTITY'];
248 }
249
250 $data = $priceData + $data;
251 if (isset($data['QUANTITY']))
252 {
253 $data['QUANTITY'] = $data['AVAILABLE_QUANTITY'] = static::getAvailableQuantityFromPool($item, $data['QUANTITY']);
254 }
255 }
256 else
257 {
258 return false;
259 }
260 }
261
262 $settableFields = $basketItemClassName::getSettableFieldsMap();
263 $roundFields = array_fill_keys($basketItemClassName::getRoundFields(), true);
264
265 foreach ($data as $key => $value)
266 {
267 if (isset($settableFields[$key]))
268 {
269 if (
270 $item->isMarkedFieldCustom($key)
271 ||
272 $key === 'DISCOUNT_PRICE' && $item->isMarkedFieldCustom('PRICE')
273 )
274 {
275 $value = $item->getField($key);
276 }
277
278 if (isset($roundFields[$key]))
279 {
280 $value = PriceMaths::roundPrecision($value);
281 }
282
283 $preparedData[$key] = $value;
284 }
285 }
286
287 return $preparedData;
288 }
289
290 protected static function getAvailableQuantityFromPool(BasketItemBase $item, $quantity)
291 {
292 $availableQuantity = $quantity;
294 $basket = $item->getCollection();
295 if (!$basket)
296 {
297 throw new Main\ObjectNotFoundException('Basket');
298 }
299
300 $order = $basket->getOrder();
301 if ($order && $order->getId() > 0)
302 {
303 $productId = $item->getProductId();
304
305 $poolQuantity = 0;
306
307 $pool = PoolQuantity::getInstance($order->getInternalId());
308 $reserveQuantityList = $pool->getQuantities(PoolQuantity::POOL_RESERVE_TYPE);
309 $quantityList = $pool->getQuantities(PoolQuantity::POOL_QUANTITY_TYPE);
310
311 if (isset($quantityList[$productId]))
312 {
313 $poolQuantity += $quantityList[$productId];
314 }
315
316 if (isset($reserveQuantityList[$productId]))
317 {
318 $poolQuantity += $reserveQuantityList[$productId];
319 }
320
321 if ($poolQuantity < 0)
322 {
323 $poolQuantity = abs($poolQuantity);
324 }
325
326 if (($quantity + $poolQuantity) >= $item->getQuantity())
327 {
328 $availableQuantity = $item->getQuantity();
329 }
330 }
331
332 return $availableQuantity;
333 }
334
335
336 protected function getProviderContext(BasketBase $basket)
337 {
338 return $basket->getContext();
339 }
340
341 protected function getBasketItemsToRefresh(BasketBase $basket, $quantity = 0)
342 {
343 $itemsToRefresh = array();
344 $currentItemsCount = 0;
345
346 $basketRefreshStart = time();
348
349 foreach ($basket as $basketItem)
350 {
351 if ($quantity > 0 && $currentItemsCount >= $quantity)
352 {
353 break;
354 }
355
356 $basketItemLastRefresh = $this->getBasketItemRefreshTimestamp($basketItem);
357 if ($basketRefreshStart - $basketItemLastRefresh >= $refreshGap)
358 {
359 $itemsToRefresh[] = $basketItem;
360 $currentItemsCount++;
361 }
362 }
363
364 return $itemsToRefresh;
365 }
366
373 protected function getProviderResult(BasketBase $basket, $itemsToRefresh = array())
374 {
375 if (!empty($itemsToRefresh))
376 {
377 $context = $this->getProviderContext($basket);
378 $result = Provider::getProductData($itemsToRefresh, $context);
379 }
380 else
381 {
382 $result = new Result();
383 $result->setData(array(
384 'PRODUCT_DATA_LIST' => array()
385 ));
386 }
387
388 return $result;
389 }
390
397 protected function applyRefreshResult(BasketItemBase $item, $fields)
398 {
399 return $item->setFields($fields);
400 }
401
407 abstract protected function getProductData(BasketBase $basket);
408
414 public function refresh(BasketBase $basket)
415 {
416 if (!$basket->isEmpty())
417 {
418 $result = $this->getProductData($basket);
419 if ($result->isSuccess())
420 {
421 $productData = $result->get('PRODUCT_DATA_LIST');
422 if (!empty($productData))
423 {
424 $r = $this->updateBasket($basket, $productData);
425 if ($r->isSuccess())
426 {
427 $result->addData($r->getData());
428 }
429 else
430 {
431 $result->addErrors($r->getErrors());
432 }
433 }
434 else
435 {
436 $result->addData(array(
437 'CHANGED_BASKET_ITEMS' => array()
438 ));
439 }
440 }
441 }
442 else
443 {
444 $result = new Result();
445 $result->setData(array(
446 'PRODUCT_DATA_LIST' => array(),
447 'CHANGED_BASKET_ITEMS' => array()
448 ));
449 }
450
451 return $result;
452 }
453}
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
isBasketItemChanged(BasketItemBase $basketItem)
getBasketItemsToRefresh(BasketBase $basket, $quantity=0)
getProviderResult(BasketBase $basket, $itemsToRefresh=array())
applyRefreshResult(BasketItemBase $item, $fields)
static roundPrecision($value)
static getProductData(BasketItemCollection $basketCollection, array $select=array(), BasketItem $refreshItem=null)
static getInstance($type)
Definition registry.php:183