Test Failed
Branch v5 (12d602)
by Alexey
04:51
created

Cart   D

Complexity

Total Complexity 82

Size/Duplication

Total Lines 499
Duplicated Lines 5.21 %

Coupling/Cohesion

Components 2
Dependencies 8

Importance

Changes 0
Metric Value
dl 26
loc 499
rs 4.8717
c 0
b 0
f 0
wmc 82
lcom 2
cbo 8

17 Methods

Rating   Name   Duplication   Size   Complexity  
A indexes() 0 23 1
A relations() 0 61 1
B beforeDelete() 0 14 5
A itemName() 0 3 1
B availablePricesTypes() 0 16 6
C buildOrderInfo() 20 39 7
C checkStage() 0 29 12
B needDelivery() 0 8 6
C deliverySum() 0 28 12
A hasDiscount() 0 3 2
A discountSum() 0 7 3
A finalSum() 0 6 1
A itemsSum() 0 11 4
C addItem() 6 31 7
C removeItem() 0 27 7
A calc() 0 5 2
B availablePayTypes() 0 14 5

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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
2
3
/**
4
 * Cart
5
 *
6
 * @author Alexey Krupskiy <[email protected]>
7
 * @link http://inji.ru/
8
 * @copyright 2015 Alexey Krupskiy
9
 * @license https://github.com/injitools/cms-Inji/blob/master/LICENSE
10
 */
11
12
namespace Ecommerce;
13
/**
14
 * Class Cart
15
 *
16
 * @property int $id
17
 * @property int $user_id
18
 * @property int $cart_status_id
19
 * @property int $delivery_id
20
 * @property int $paytype_id
21
 * @property int $card_item_id
22
 * @property bool $warehouse_block
23
 * @property bool $payed
24
 * @property string $comment
25
 * @property bool $exported
26
 * @property string $complete_data
27
 * @property string $date_status
28
 * @property string $date_last_activ
29
 * @property string $date_create
30
 *
31
 * @property-read \Users\User $user
32
 * @property-read \Ecommerce\Cart\Item[] $cartItems
33
 * @property-read \Ecommerce\Cart\Event[] $events
34
 * @property-read \Ecommerce\Cart\Status $status
35
 * @property-read \Ecommerce\Delivery $delivery
36
 * @property-read \Ecommerce\PayType $payType
37
 * @property-read \Ecommerce\Cart\Info[] $infos
38
 * @property-read \Ecommerce\Cart\DeliveryInfo[] $deliveryInfos
39
 * @property-read \Ecommerce\Cart\Extra[] $extras
40
 * @property-read \Ecommerce\Card\Item $card
41
 * @property-read \Money\Pay[] $pays
42
 * @property-read \Ecommerce\Cart\Discount[] $discounts
43
 *
44
 * @method \Users\User user($options)($options)
45
 * @method \Ecommerce\Cart\Item[] cartItems($options)
46
 * @method \Ecommerce\Cart\Event[] events($options)
47
 * @method \Ecommerce\Cart\Status status($options)
48
 * @method \Ecommerce\Delivery delivery($options)
49
 * @method \Ecommerce\PayType payType($options)
50
 * @method \Ecommerce\Cart\Info[] infos($options)
51
 * @method \Ecommerce\Cart\DeliveryInfo[] deliveryInfos($options)
52
 * @method \Ecommerce\Cart\Extra[] extras($options)
53
 * @method \Ecommerce\Card\Item card($options)
54
 * @method \Money\Pay[] pays($options)
55
 * @method \Ecommerce\Cart\Discount[] discounts($options)
56
 */
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() {
149
        foreach ($this->cartItems as $cartItem) {
150
            $cartItem->delete();
151
        }
152
        foreach ($this->infos as $info) {
153
            $info->delete();
154
        }
155
        foreach ($this->extras as $extra) {
156
            $extra->delete();
157
        }
158
        foreach ($this->events as $event) {
159
            $event->delete();
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() {
320
        $types = \App::$cur->ecommerce->availablePricesTypes();
321
        if ($types === true) {
322
            return true;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return true; (boolean) is incompatible with the return type documented by Ecommerce\Cart::availablePricesTypes of type Ecommerce\true|array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
323
        }
324
        foreach (Card::getList() as $card) {
325
            foreach ($this->cartItems as $cartItem) {
326
                if ($cartItem->item_offer_price_id == $card->item_offer_price_id) {
327
                    foreach ($card->prices as $priceType) {
328
                        $types[$priceType->id] = $priceType->id;
329
                    }
330
                }
331
            }
332
        }
333
        return $types;
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 View Code Duplication
        if ($this->infos) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->infos of type Ecommerce\Cart\Info[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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 View Code Duplication
        if ($this->delivery) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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() {
416
        $sum = new \Money\Sums([0 => 0]);
417
        if ($this->delivery && $this->needDelivery()) {
418
            $sums = $this->itemsSum();
419
            $deliveryPrice = new \Money\Sums([$this->delivery->currency_id => $this->delivery->max_cart_price]);
420
            if ($this->delivery->max_cart_price && $sums->greater($deliveryPrice) || $sums->equal($deliveryPrice)) {
421
                $sum->sums = [$this->delivery->currency_id => 0];
422
            } else if ($this->delivery->prices) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->delivery->prices of type Ecommerce\Delivery\Price[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
423
                foreach ($this->delivery->prices(['order' => ['cart_price', 'asc']]) as $delPrice) {
424
                    $deliveryPrice = new \Money\Sums([$delPrice->currency_id => $delPrice->cart_price]);
425
                    if ($sums->greater($deliveryPrice) || $sums->equal($deliveryPrice)) {
426
                        $sum->sums = [$delPrice->currency_id => $delPrice->price];
427
                    }
428
                }
429
                if (!$sum->sums) {
430
                    $sum->sums = [$this->delivery->currency_id => $this->delivery->price];
431
                }
432
            } else {
433
                if (!$this->delivery->provider) {
434
                    $sum->sums = [$this->delivery->currency_id => $this->delivery->price];
435
                } else {
436
                    $className = 'Ecommerce\DeliveryProvider\\' . $this->delivery->provider->object;
437
                    $sum = $className::calcPrice($this);
438
                }
439
            }
440
        }
441
        return $sum;
442
    }
443
444
    public function hasDiscount() {
445
        return (bool) $this->card || $this->discounts;
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->discounts of type Ecommerce\Cart\Discount[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

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.

Loading history...
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 View Code Duplication
            foreach ($this->cartItems as $cartItem) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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() {
542
        if (!$this->delivery) {
543
            return \Ecommerce\PayType::getList(['order' => ['weight', 'ASC']]);
544
        }
545
        $providerHelper = $this->delivery->providerHelper();
546
        if (!$providerHelper) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $providerHelper of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
547
            return \Ecommerce\PayType::getList(['order' => ['weight', 'ASC']]);
548
        }
549
        $payTypeGroups = $providerHelper::availablePayTypeGroups($this);
550
        if (!$payTypeGroups || $payTypeGroups[0] === '*') {
551
            return \Ecommerce\PayType::getList(['order' => ['weight', 'ASC']]);
552
        }
553
        return \Ecommerce\PayType::getList(['where' => ['group', $payTypeGroups, 'IN'], 'order' => ['weight', 'ASC']]);
554
    }
555
}
556