Total Complexity | 82 |
Total Lines | 497 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like Cart often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Cart, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
57 | class Cart extends \Model { |
||
58 | |||
59 | public static $logging = false; |
||
60 | public static $objectName = 'Корзины'; |
||
61 | |||
62 | public static function indexes() { |
||
63 | return [ |
||
64 | 'ecommerce_cartStatusBlock' => [ |
||
65 | 'type' => 'INDEX', |
||
66 | 'cols' => [ |
||
67 | 'cart_cart_status_id', |
||
68 | 'cart_warehouse_block' |
||
69 | ] |
||
70 | ], |
||
71 | 'ecommerce_cartStats' => [ |
||
72 | 'type' => 'INDEX', |
||
73 | 'cols' => [ |
||
74 | 'cart_cart_status_id', |
||
75 | ] |
||
76 | ], |
||
77 | 'ecommerce_cartBlock' => [ |
||
78 | 'type' => 'INDEX', |
||
79 | 'cols' => [ |
||
80 | 'cart_warehouse_block' |
||
81 | ] |
||
82 | ], |
||
83 | ]; |
||
84 | } |
||
85 | |||
86 | public static function relations() { |
||
87 | return [ |
||
88 | 'user' => [ |
||
89 | 'model' => 'Users\User', |
||
90 | 'col' => 'user_id' |
||
91 | ], |
||
92 | 'cartItems' => [ |
||
93 | 'type' => 'many', |
||
94 | 'model' => 'Ecommerce\Cart\Item', |
||
95 | 'col' => 'cart_id', |
||
96 | ], |
||
97 | 'events' => [ |
||
98 | 'type' => 'many', |
||
99 | 'model' => 'Ecommerce\Cart\Event', |
||
100 | 'col' => 'cart_id', |
||
101 | ], |
||
102 | 'status' => [ |
||
103 | 'model' => 'Ecommerce\Cart\Status', |
||
104 | 'col' => 'cart_status_id' |
||
105 | ], |
||
106 | 'delivery' => [ |
||
107 | 'model' => 'Ecommerce\Delivery', |
||
108 | 'col' => 'delivery_id' |
||
109 | ], |
||
110 | 'payType' => [ |
||
111 | 'model' => 'Ecommerce\PayType', |
||
112 | 'col' => 'paytype_id' |
||
113 | ], |
||
114 | 'infos' => [ |
||
115 | 'type' => 'many', |
||
116 | 'model' => 'Ecommerce\Cart\Info', |
||
117 | 'col' => 'cart_id', |
||
118 | 'resultKey' => 'useradds_field_id' |
||
119 | ], |
||
120 | 'deliveryInfos' => [ |
||
121 | 'type' => 'many', |
||
122 | 'model' => 'Ecommerce\Cart\DeliveryInfo', |
||
123 | 'col' => 'cart_id', |
||
124 | 'resultKey' => 'delivery_field_id' |
||
125 | ], |
||
126 | 'extras' => [ |
||
127 | 'type' => 'many', |
||
128 | 'model' => 'Ecommerce\Cart\Extra', |
||
129 | 'col' => 'cart_id' |
||
130 | ], |
||
131 | 'card' => [ |
||
132 | 'model' => 'Ecommerce\Card\Item', |
||
133 | 'col' => 'card_item_id' |
||
134 | ], |
||
135 | 'pays' => [ |
||
136 | 'type' => 'many', |
||
137 | 'model' => 'Money\Pay', |
||
138 | 'col' => 'data' |
||
139 | ], |
||
140 | 'discounts' => [ |
||
141 | 'type' => 'relModel', |
||
142 | 'relModel' => 'Ecommerce\Cart\Discount', |
||
143 | 'model' => 'Ecommerce\Discount', |
||
144 | ] |
||
145 | ]; |
||
146 | } |
||
147 | |||
148 | public function beforeDelete() { |
||
160 | } |
||
161 | } |
||
162 | |||
163 | public static $labels = [ |
||
164 | 'user_id' => 'Пользователь', |
||
165 | 'cart_status_id' => 'Статус', |
||
166 | 'delivery_id' => 'Доставка', |
||
167 | 'comment' => 'Комментарий', |
||
168 | 'bonus_used' => 'Выгодные рубли', |
||
169 | 'complete_data' => 'Время заказа', |
||
170 | 'info' => 'Информация', |
||
171 | 'items' => 'Товары', |
||
172 | 'paytype_id' => 'Способ оплаты', |
||
173 | 'payed' => 'Оплачен', |
||
174 | 'exported' => 'Выгружено', |
||
175 | 'warehouse_block' => 'Блокировка товаров', |
||
176 | 'extra' => 'Доп.', |
||
177 | 'card_item_id' => 'Дисконтная карта', |
||
178 | 'info' => 'Информация', |
||
179 | 'contacts' => 'Информация', |
||
180 | 'pay' => 'Счета', |
||
181 | 'sums' => 'Суммы', |
||
182 | 'deliveryInfo' => 'Для доставки', |
||
183 | 'discount' => 'Скидки', |
||
184 | ]; |
||
185 | public static $cols = [ |
||
186 | //Основные параметры |
||
187 | 'user_id' => ['type' => 'select', 'source' => 'relation', 'relation' => 'user'], |
||
188 | 'cart_status_id' => ['type' => 'select', 'source' => 'relation', 'relation' => 'status'], |
||
189 | 'delivery_id' => ['type' => 'select', 'source' => 'relation', 'relation' => 'delivery'], |
||
190 | 'paytype_id' => ['type' => 'select', 'source' => 'relation', 'relation' => 'payType'], |
||
191 | 'card_item_id' => ['type' => 'select', 'source' => 'relation', 'relation' => 'card'], |
||
192 | 'warehouse_block' => ['type' => 'bool'], |
||
193 | 'payed' => ['type' => 'bool'], |
||
194 | 'comment' => ['type' => 'textarea'], |
||
195 | //Системные |
||
196 | 'exported' => ['type' => 'bool'], |
||
197 | 'complete_data' => ['type' => 'dateTime', 'null' => true, 'emptyValue' => null], |
||
198 | 'date_status' => ['type' => 'dateTime', 'null' => true, 'emptyValue' => null], |
||
199 | 'date_last_activ' => ['type' => 'dateTime', 'null' => true, 'emptyValue' => null, 'logging' => false], |
||
200 | 'date_create' => ['type' => 'dateTime'], |
||
201 | //Виджеты |
||
202 | 'sums' => [ |
||
203 | 'type' => 'void', |
||
204 | 'view' => [ |
||
205 | 'type' => 'widget', |
||
206 | 'widget' => 'Ecommerce\adminSums', |
||
207 | ], |
||
208 | ], |
||
209 | 'contacts' => [ |
||
210 | 'type' => 'void', |
||
211 | 'view' => [ |
||
212 | 'type' => 'widget', |
||
213 | 'widget' => 'Ecommerce\admin/contacts', |
||
214 | ], |
||
215 | ], |
||
216 | //Менеджеры |
||
217 | 'extra' => ['type' => 'dataManager', 'relation' => 'extras'], |
||
218 | 'pay' => ['type' => 'dataManager', 'relation' => 'pays'], |
||
219 | 'items' => ['type' => 'dataManager', 'relation' => 'cartItems'], |
||
220 | 'info' => ['type' => 'dataManager', 'relation' => 'infos'], |
||
221 | 'deliveryInfo' => ['type' => 'dataManager', 'relation' => 'deliveryInfos'], |
||
222 | 'discount' => ['type' => 'dataManager', 'relation' => 'discounts'], |
||
223 | ]; |
||
224 | public static $dataManagers = [ |
||
225 | 'manager' => [ |
||
226 | 'cols' => [ |
||
227 | 'contacts', |
||
228 | 'items', |
||
229 | 'extra', |
||
230 | 'discount', |
||
231 | 'sums', |
||
232 | 'cart_status_id', |
||
233 | 'delivery_id', |
||
234 | 'deliveryInfo', |
||
235 | 'payed', |
||
236 | 'pay', |
||
237 | 'complete_data', |
||
238 | ], |
||
239 | 'sortable' => [ |
||
240 | 'cart_status_id', |
||
241 | 'delivery_id', |
||
242 | 'payed', |
||
243 | 'complete_data', |
||
244 | ], |
||
245 | 'filters' => [ |
||
246 | 'cart_status_id', |
||
247 | 'delivery_id', |
||
248 | 'payed', |
||
249 | 'complete_data', |
||
250 | ], |
||
251 | 'preSort' => [ |
||
252 | 'complete_data' => 'desc' |
||
253 | ], |
||
254 | 'actions' => [ |
||
255 | 'Ecommerce\CloseCartBtn', 'Open', 'Edit', 'Delete' |
||
256 | ] |
||
257 | ] |
||
258 | ]; |
||
259 | |||
260 | public static function itemName($item) { |
||
261 | return $item->pk() . '. ' . $item->name(); |
||
262 | } |
||
263 | |||
264 | public static $forms = [ |
||
265 | 'manager' => [ |
||
266 | 'inputs' => [ |
||
267 | 'userSearch' => [ |
||
268 | 'type' => 'search', |
||
269 | 'source' => 'relation', |
||
270 | 'relation' => 'user', |
||
271 | 'label' => 'Покупатель', |
||
272 | 'cols' => [ |
||
273 | 'info:first_name', |
||
274 | 'info:last_name', |
||
275 | 'info:middle_name', |
||
276 | 'mail' |
||
277 | ], |
||
278 | 'col' => 'user_id', |
||
279 | 'required' => true, |
||
280 | 'showCol' => [ |
||
281 | 'type' => 'staticMethod', |
||
282 | 'class' => 'Ecommerce\Cart', |
||
283 | 'method' => 'itemName', |
||
284 | ], |
||
285 | ], |
||
286 | 'cardSearch' => [ |
||
287 | 'type' => 'search', |
||
288 | 'source' => 'relation', |
||
289 | 'relation' => 'card', |
||
290 | 'label' => 'Дисконтная карта', |
||
291 | 'cols' => [ |
||
292 | 'code', |
||
293 | 'user:info:first_name', |
||
294 | 'user:info:last_name', |
||
295 | 'user:info:middle_name', |
||
296 | 'user:mail' |
||
297 | ], |
||
298 | 'col' => 'card_item_id', |
||
299 | ], |
||
300 | ], |
||
301 | 'map' => [ |
||
302 | ['userSearch', 'cart_status_id'], |
||
303 | ['paytype_id', 'delivery_id'], |
||
304 | ['cardSearch', 'comment'], |
||
305 | ['warehouse_block', 'complete_data'], |
||
306 | ['payed'], |
||
307 | ['items'], |
||
308 | ['extra'], |
||
309 | ['pay'], |
||
310 | ['info'], |
||
311 | ['deliveryInfo'] |
||
312 | ] |
||
313 | ], |
||
314 | ]; |
||
315 | |||
316 | /** |
||
317 | * @return true|array |
||
318 | */ |
||
319 | public function availablePricesTypes() { |
||
334 | } |
||
335 | |||
336 | public function buildOrderInfo() { |
||
337 | $orderInfo = '<h3>Товары</h3>'; |
||
338 | $orderInfo .= '<table cellspacing="2" border="1" cellpadding="5"><tr><th>Товар</th><th>Артикул</th><th>Кол-во</th><th>Цена</th><th>Сумма</th></tr>'; |
||
339 | foreach ($this->cartItems as $cartItem) { |
||
340 | $orderInfo .= "<tr>"; |
||
341 | $orderInfo .= "<td><a href='" . \App::$cur->getDomain() . "{$cartItem->item->getHref()}'>{$cartItem->name()}</a></td>"; |
||
342 | $orderInfo .= "<td>{$cartItem->price->offer->article}</td>"; |
||
343 | $orderInfo .= "<td>{$cartItem->count}</td>"; |
||
344 | $orderInfo .= "<td>{$cartItem->final_price}</td>"; |
||
345 | $orderInfo .= "<td>" . ($cartItem->final_price * $cartItem->count) . "</td>"; |
||
346 | $orderInfo .= "</tr>"; |
||
347 | } |
||
348 | $orderInfo .= '</table>'; |
||
349 | if ($this->infos) { |
||
|
|||
350 | $orderInfo .= '<h3>Контакты</h3>'; |
||
351 | $orderInfo .= '<table cellspacing="2" border="1" cellpadding="5">'; |
||
352 | $orderInfo .= "<tr><td>E-mail</td><td><b>{$this->user->mail}</b></td></tr>"; |
||
353 | foreach ($this->infos as $info) { |
||
354 | $value = \Model::resloveTypeValue($info, 'value'); |
||
355 | $orderInfo .= "<tr><td>{$info->name}</td><td><b>{$value}</b></td></tr>"; |
||
356 | } |
||
357 | $orderInfo .= '</table>'; |
||
358 | } |
||
359 | if ($this->delivery) { |
||
360 | $orderInfo .= '<h3>Информация о доставке</h3>'; |
||
361 | $orderInfo .= "<p><b>{$this->delivery->name}</b></p>"; |
||
362 | $orderInfo .= '<table cellspacing="2" border="1" cellpadding="5">'; |
||
363 | foreach ($this->deliveryInfos as $info) { |
||
364 | $value = \Model::resloveTypeValue($info, 'value'); |
||
365 | $orderInfo .= "<tr><td>{$info->name}</td><td><b>{$value}</b></td></tr>"; |
||
366 | } |
||
367 | $orderInfo .= '</table>'; |
||
368 | } |
||
369 | if ($this->payType) { |
||
370 | $orderInfo .= '<h3>Способ оплаты</h3>'; |
||
371 | $orderInfo .= "<p><b>{$this->payType->name}</b></p>"; |
||
372 | } |
||
373 | return $orderInfo; |
||
374 | } |
||
375 | |||
376 | public function checkStage() { |
||
377 | $sum = $this->itemsSum(); |
||
378 | $stages = Cart\Stage::getList(['order' => ['sum', 'asc']]); |
||
379 | $groups = []; |
||
380 | foreach ($stages as $stage) { |
||
381 | if ($sum->greater(new \Money\Sums([$stage->currency_id => $stage->sum])) || $sum->equal(new \Money\Sums([$stage->currency_id => $stage->sum]))) { |
||
382 | $groups[$stage->group] = $stage; |
||
383 | } |
||
384 | } |
||
385 | $discounts = Cart\Discount::getList(['where' => ['cart_id', $this->id]]); |
||
386 | foreach ($discounts as $discount) { |
||
387 | if (!isset($groups[$discount->group]) && $discount->auto) { |
||
388 | $discount->delete(); |
||
389 | } |
||
390 | if (isset($groups[$discount->group]) && $groups[$discount->group]->type == 'discount') { |
||
391 | $discount->discount_id = $groups[$discount->group]->value; |
||
392 | $discount->save(); |
||
393 | unset($groups[$discount->group]); |
||
394 | } |
||
395 | } |
||
396 | foreach ($groups as $group) { |
||
397 | if ($group && $group->type == 'discount') { |
||
398 | $rel = $this->addRelation('discounts', $group->value); |
||
399 | $rel->auto = true; |
||
400 | $rel->group = 'discount'; |
||
401 | $rel->save(); |
||
402 | } |
||
403 | } |
||
404 | } |
||
405 | |||
406 | public function needDelivery() { |
||
407 | foreach ($this->cartItems as $cartItem) { |
||
408 | if ((!$cartItem->item->type && !empty(\App::$cur->ecommerce->config['defaultNeedDelivery'])) || ($cartItem->item->type && $cartItem->item->type->delivery)) { |
||
409 | return true; |
||
410 | } |
||
411 | } |
||
412 | return false; |
||
413 | } |
||
414 | |||
415 | public function deliverySum() { |
||
442 | } |
||
443 | |||
444 | public function hasDiscount() { |
||
445 | return (bool) $this->card || $this->discounts; |
||
446 | } |
||
447 | |||
448 | public function discountSum() { |
||
449 | $sums = []; |
||
450 | foreach ($this->cartItems as $cartItem) { |
||
451 | $sums[$cartItem->price->currency_id] = isset($sums[$cartItem->price->currency_id]) ? $sums[$cartItem->price->currency_id] + $cartItem->discount() * $cartItem->count : $cartItem->discount() * $cartItem->count; |
||
452 | } |
||
453 | return new \Money\Sums($sums); |
||
454 | } |
||
455 | |||
456 | public function finalSum() { |
||
457 | $sums = $this->itemsSum(); |
||
458 | $sums = $sums->minus($this->discountSum()); |
||
459 | $sums = $sums->plus($this->deliverySum()); |
||
460 | return $sums; |
||
461 | } |
||
462 | |||
463 | public function itemsSum() { |
||
464 | $cart = Cart::get($this->id); |
||
465 | $sums = []; |
||
466 | foreach ($cart->cartItems as $cartItem) { |
||
467 | if (!$cartItem->price) { |
||
468 | continue; |
||
469 | } |
||
470 | $sums[$cartItem->price->currency_id] = isset($sums[$cartItem->price->currency_id]) ? $sums[$cartItem->price->currency_id] + $cartItem->price->price * $cartItem->count : $cartItem->price->price * $cartItem->count; |
||
471 | } |
||
472 | return new \Money\Sums($sums); |
||
473 | } |
||
474 | |||
475 | public function addItem($offer_price_id, $count = 1, $final_price = 0) { |
||
476 | $price = Item\Offer\Price::get((int) $offer_price_id); |
||
477 | |||
478 | if (!$price) { |
||
479 | return false; |
||
480 | } |
||
481 | |||
482 | if ($count <= 0) { |
||
483 | $count = 1; |
||
484 | } |
||
485 | |||
486 | $cartItem = new Cart\Item(); |
||
487 | $cartItem->cart_id = $this->id; |
||
488 | $cartItem->item_id = $price->offer->item->id; |
||
489 | $cartItem->count = $count; |
||
490 | $cartItem->item_offer_price_id = $price->id; |
||
491 | $cartItem->final_price = $final_price ? $final_price : $price->price; |
||
492 | $cartItem->save(); |
||
493 | $card = Card::get($price->item_offer_id, 'item_offer_id'); |
||
494 | if ($card && $card->prices) { |
||
495 | $this->loadRelation('cartItems'); |
||
496 | foreach ($this->cartItems as $cartItem) { |
||
497 | $price = $cartItem->price->offer->getPrice($this); |
||
498 | $cartItem->item_offer_price_id = $price->id; |
||
499 | $cartItem->final_price = $price->price; |
||
500 | $cartItem->save(); |
||
501 | } |
||
502 | $this->loadRelation('cartItems'); |
||
503 | } |
||
504 | return true; |
||
505 | } |
||
506 | |||
507 | public function removeItem($offer_price_id, $count = 1, $final_price = 0) { |
||
508 | $price = Item\Offer\Price::get((int) $offer_price_id); |
||
509 | |||
510 | if (!$price) { |
||
511 | return false; |
||
512 | } |
||
513 | |||
514 | if ($count <= 0) { |
||
515 | $count = 1; |
||
516 | } |
||
517 | |||
518 | $cartItem = new Cart\Item(); |
||
519 | $cartItem->cart_id = $this->id; |
||
520 | $cartItem->item_id = $price->offer->item->id; |
||
521 | $cartItem->count = $count; |
||
522 | $cartItem->item_offer_price_id = $price->id; |
||
523 | $cartItem->final_price = $final_price ? $final_price : $price->price; |
||
524 | $cartItem->save(); |
||
525 | $card = Card::get($price->item_offer_id, 'item_offer_id'); |
||
526 | if ($card && $card->prices) { |
||
527 | foreach ($this->cartItems as $cartItem) { |
||
528 | $cartItem->item_offer_price_id = $cartItem->price->offer->getPrice($this); |
||
529 | $cartItem->save(); |
||
530 | } |
||
531 | } |
||
532 | return true; |
||
533 | } |
||
534 | |||
535 | public function calc($save = true) { |
||
536 | if ($save) { |
||
537 | $this->save(); |
||
538 | } |
||
539 | } |
||
540 | |||
541 | public function availablePayTypes() { |
||
554 | } |
||
555 | } |
||
556 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.