GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

CartController   F
last analyzed

Complexity

Total Complexity 87

Size/Duplication

Total Lines 559
Duplicated Lines 2.15 %

Coupling/Cohesion

Components 1
Dependencies 27

Importance

Changes 0
Metric Value
wmc 87
lcom 1
cbo 27
dl 12
loc 559
rs 2
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A behaviors() 0 9 1
A loadOrder() 0 8 3
A loadOrderItem() 0 12 6
F addProductsToOrder() 0 101 23
B actionAdd() 3 50 7
B actionChangeQuantity() 3 55 7
B actionDelete() 3 40 6
A actionClear() 3 36 4
A actionIndex() 0 29 5
B actionStage() 0 48 8
C actionStageLeaf() 0 44 12
A beforeAction() 0 18 3
A productsModelsToArray() 0 20 2

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 CartController 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 CartController, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace app\modules\shop\controllers;
3
4
use app\modules\core\behaviors\DisableRobotIndexBehavior;
5
use app\modules\core\helpers\EventTriggeringHelper;
6
use app\modules\core\models\Events;
7
use app\modules\shop\events\CartActionEvent;
8
use app\modules\shop\handlers\CartHandler;
9
use app\modules\shop\helpers\PriceHelper;
10
use app\modules\shop\events\OrderStageEvent;
11
use app\modules\shop\events\OrderStageLeafEvent;
12
use app\modules\shop\models\Addon;
13
use app\modules\shop\models\Order;
14
use app\modules\shop\models\OrderCode;
15
use app\modules\shop\models\OrderItem;
16
use app\modules\shop\models\OrderStage;
17
use app\modules\shop\models\OrderStageLeaf;
18
use app\modules\shop\models\Product;
19
use app\modules\shop\models\SpecialPriceList;
20
use app\modules\shop\ShopModule;
21
use yii\base\Event;
22
use yii\helpers\Url;
23
use Yii;
24
use yii\web\BadRequestHttpException;
25
use yii\web\Controller;
26
use yii\web\NotFoundHttpException;
27
use yii\web\Response;
28
use app\modules\shop\helpers\CurrencyHelper;
29
30
/**
31
 * Class CartController
32
 * @package app\modules\shop\controllers
33
 * @property ShopModule $module
34
 */
35
class CartController extends Controller
36
{
37
    const EVENT_ACTION_ADD = 'shopCartActionAdd';
38
    const EVENT_ACTION_REMOVE = 'shopCartActionRemove';
39
    const EVENT_ACTION_QUANTITY = 'shopCartActionQuantity';
40
    const EVENT_ACTION_CLEAR = 'shopCartActionClear';
41
42
    /**
43
     * @inheritdoc
44
     */
45
    public function behaviors()
46
    {
47
        return [
48
            [
49
                'class' => DisableRobotIndexBehavior::className(),
0 ignored issues
show
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
50
                'setSameOrigin' => false
51
            ]
52
        ];
53
    }
54
55
    /**
56
     * Get Order.
57
     * @param bool $create Create order if it does not exist
58
     * @param bool $throwException Throw exception if it does not exist
59
     * @return null|Order
60
     * @throws NotFoundHttpException
61
     */
62
    protected function loadOrder($create = false, $throwException = true)
63
    {
64
        $model = Order::getOrder($create);
65
        if (is_null($model) && $throwException) {
66
            throw new NotFoundHttpException;
67
        }
68
        return $model;
69
    }
70
71
    /**
72
     * Get OrderItem.
73
     * @param int $id
74
     * @param bool $checkOrderAttachment
75
     * @return OrderItem
76
     * @throws NotFoundHttpException
77
     */
78
    protected function loadOrderItem($id, $checkOrderAttachment = true)
79
    {
80
        /** @var OrderItem $orderItemModel */
81
        $orderModel = $checkOrderAttachment ? $this->loadOrder() : null;
82
        $orderItemModel = OrderItem::findOne($id);
0 ignored issues
show
Bug Compatibility introduced by
The expression \app\modules\shop\models\OrderItem::findOne($id); of type yii\db\ActiveRecordInterface|array|null adds the type array to the return on line 88 which is incompatible with the return type documented by app\modules\shop\control...ntroller::loadOrderItem of type app\modules\shop\models\OrderItem.
Loading history...
83
        if (is_null($orderItemModel)
84
            || ($checkOrderAttachment && (is_null($orderModel) || $orderItemModel->order_id != $orderModel->id))
85
        ) {
86
            throw new NotFoundHttpException;
87
        }
88
        return $orderItemModel;
89
    }
90
91
    /**
92
     * @param Order $order
93
     * @param array $products
94
     * @param $result
95
     * @param int $parentId
96
     * @return mixed
97
     * @throws BadRequestHttpException
98
     * @throws NotFoundHttpException
99
     */
100
    protected function addProductsToOrder(Order $order, $products = [], $result, $parentId = 0)
101
    {
102
        $parentId = intval($parentId);
103
        if ($parentId !== 0) {
104
            // if parent id is set - order item should exist in this order!
105
            $parentOrderItem = OrderItem::findOne(['order_id' => $order->id, 'id' => $parentId]);
106
            if ($parentOrderItem === null) {
107
                throw new BadRequestHttpException;
108
            }
109
        }
110
111
        foreach ($products as $productArray) {
112
            $productModel = $addonModel = null;
113
114
            if (!isset($productArray['id'])) {
115
                if (isset($productArray['addon_id'])) {
116
                    $addonModel = Addon::findById($productArray['addon_id']);
117
                }
118
            } else {
119
                $product = Yii::$container->get(Product::class);
120
                $productModel = $product::findById($productArray['id']);
121
            }
122
123
            if ($addonModel === null && $productModel === null) {
124
                $result['errors'][] = Yii::t('app', 'Product not found.');
125
                continue;
126
            }
127
128
            /** @var Product $productModel */
129
            $quantity = isset($productArray['quantity']) && (double) $productArray['quantity'] > 0
130
                ? (double) $productArray['quantity']
131
                : 1;
132
133
            $condition = ['order_id' => $order->id, 'parent_id' => 0];
134
            if ($productModel !== null) {
135
                $condition['product_id'] = $productModel->id;
136
                $thisItemModel = $productModel;
137
                $quantity = $productModel->measure->ceilQuantity($quantity);
138
            } else {
139
                $condition['addon_id'] = $addonModel->id;
140
                $thisItemModel = $addonModel;
141
                if (!$addonModel->can_change_quantity) {
142
                    $quantity = 1;
143
                }
144
            }
145
146
            $orderItem = OrderItem::findOne($condition);
147
            if ($this->module->allowToAddSameProduct || null === $orderItem) {
148
                $orderItem = new OrderItem;
149
                $orderItem->attributes = [
150
                    'parent_id' => $parentId,
151
                    'order_id' => $order->id,
152
                    'quantity' => $quantity,
153
                    'price_per_pcs' => PriceHelper::getProductPrice(
154
                        $thisItemModel,
0 ignored issues
show
Compatibility introduced by
$thisItemModel of type object<yii\db\ActiveRecord> is not a sub-type of object<app\modules\shop\models\Product>. It seems like you assume a child class of the class yii\db\ActiveRecord to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
155
                        $order,
156
                        1,
157
                        SpecialPriceList::TYPE_CORE
158
                    ),
159
                ];
160
                if (empty($productArray['customName']) === false) {
161
                    $orderItem->custom_name = $productArray['customName'];
162
                }
163
                if ($productModel !== null) {
164
                    $orderItem->product_id = $thisItemModel->id;
165
                } else {
166
                    $orderItem->addon_id = $thisItemModel->id;
167
                }
168
            } else {
169
                /** @var OrderItem $orderItem */
170
                if ($addonModel !== null && !$addonModel->can_change_quantity) {
171
                    // quantity can not be changed
172
                    $quantity = 0;
173
                }
174
                if (null !== $orderItem) {
175
                    $orderItem->quantity += $quantity;
176
                }
177
            }
178
            if (false === $orderItem->save()) {
179
                $result['errors'][] = Yii::t('app', 'Cannot save order item.');
180
            } else {
181
                // refresh order
182
                Order::clearStaticOrder();
183
                $order = $this->loadOrder(false);
184
            }
185
186
            if (null !== $productModel) {
187
                $result['products'][] = [
188
                    'model' => $productModel,
189
                    'quantity' => $quantity,
190
                    'orderItem' => $orderItem,
191
                ];
192
            }
193
194
            if (isset($productArray['children']) && is_array($productArray['children'])) {
195
                $result = $this->addProductsToOrder($order, $productArray['children'], $result, $orderItem->id);
0 ignored issues
show
Bug introduced by
It seems like $order defined by $this->loadOrder(false) on line 183 can be null; however, app\modules\shop\control...r::addProductsToOrder() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
196
            }
197
        }
198
199
        return $result;
200
    }
201
202
    /**
203
     * @return array
204
     * @throws BadRequestHttpException
205
     * @throws NotFoundHttpException
206
     */
207
    public function actionAdd()
208
    {
209
        Yii::$app->response->format = Response::FORMAT_JSON;
210
211
        $products = Yii::$app->request->post('products', []);
212
213
        if (false === is_array($products) || true === empty($products)) {
214
            throw new BadRequestHttpException;
215
        }
216
217
        $order = $this->loadOrder(true);
218 View Code Duplication
        if (null === $order->stage || true === $order->getImmutability(Order::IMMUTABLE_USER)) {
219
            throw new BadRequestHttpException;
220
        }
221
222
        $result = [
223
            'products' => [],
224
            'errors' => [],
225
            'additional' => [],
226
        ];
227
228
        $result = $this->addProductsToOrder($order, $products, $result);
229
230
        $order = $this->loadOrder();
231
        $order->calculate(true);
232
233
        $userCurrency = CurrencyHelper::getUserCurrency();
234
235
        $result['success'] = count($products) > 0 && count($result['products']) > 0;
236
        $result['itemsCount'] = $order->items_count;
237
        $result['totalPrice'] = $userCurrency->format(
238
            CurrencyHelper::convertToUserCurrency($order->total_price, CurrencyHelper::getMainCurrency())
239
        );
240
241
        $event = new CartActionEvent($order, $result['products']);
242
        Event::trigger($this, self::EVENT_ACTION_ADD, $event);
243
244
        $result['additional'] = $event->getEventData();
245
246
        /**
247
         * Backward compatibility
248
         */
249
        $result['itemModalPreview'] = isset($result['additional']['bcItemModalPreview'])
250
            ? $result['additional']['bcItemModalPreview']
251
            : '';
252
253
        $result['products'] = $this->productsModelsToArray($result['products']);
254
255
        return $result;
256
    }
257
258
    /**
259
     * @return array
260
     * @throws BadRequestHttpException
261
     * @throws NotFoundHttpException
262
     */
263
    public function actionChangeQuantity()
264
    {
265
        Yii::$app->response->format = Response::FORMAT_JSON;
266
267
        $result = [];
268
269
        $id = Yii::$app->request->post('id');
270
        $quantity = floatval(Yii::$app->request->post('quantity', 0));
271
272
        if (null === $id || $quantity <= 0) {
273
            throw new BadRequestHttpException;
274
        }
275
276
        $orderItem = $this->loadOrderItem($id);
277
        $order = $this->loadOrder();
278
279 View Code Duplication
        if (null === $order->stage || true === $order->getImmutability(Order::IMMUTABLE_USER)) {
280
            throw new BadRequestHttpException;
281
        }
282
283
        $model = $orderItem->product;
284
        $product = [
285
            [
286
                'model' => $model,
287
                'quantity' => $model->measure->ceilQuantity($quantity) - $orderItem->quantity,
288
                'orderItem' => $orderItem,
289
            ]
290
        ];
291
292
        $orderItem->quantity = $orderItem->product->measure->ceilQuantity($quantity);
293
        // @todo Consider lock_product_price ?
294
        if ($orderItem->lock_product_price == 0) {
295
            $orderItem->price_per_pcs = PriceHelper::getProductPrice(
296
                $orderItem->product,
0 ignored issues
show
Bug introduced by
It seems like $orderItem->product can also be of type object<app\properties\HasProperties>; however, app\modules\shop\helpers...lper::getProductPrice() does only seem to accept object<app\modules\shop\models\Product>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
297
                $order,
298
                1,
299
                SpecialPriceList::TYPE_CORE
300
            );
301
        }
302
        $orderItem->save();
303
304
        $event = new CartActionEvent($order, $product);
305
        Event::trigger($this, self::EVENT_ACTION_QUANTITY, $event);
306
307
        $result['additional'] = $event->getEventData();
308
        $result['success'] = $order->calculate(true);
309
        $result['message'] = false === $result['success'] ? Yii::t('app', 'Cannot change quantity') : '';
310
        $result['itemsCount'] = $order->items_count;
311
        $result['itemPrice'] = CurrencyHelper::getMainCurrency()->format($orderItem->total_price);
312
        $result['totalPrice'] = CurrencyHelper::getMainCurrency()->format($order->total_price);
313
        $result['calculatedQuantity'] = $orderItem->quantity;
314
        $result['products'] = $this->productsModelsToArray($product);
315
316
        return $result;
317
    }
318
319
    /**
320
     * Delete OrderItem action.
321
     * @param int $id
322
     * @throws NotFoundHttpException
323
     * @throws \Exception
324
     * @return array
325
     */
326
    public function actionDelete($id)
327
    {
328
        Yii::$app->response->format = Response::FORMAT_JSON;
329
330
        $result = [];
331
332
        $order = $this->loadOrder();
333 View Code Duplication
        if (null === $order->stage || true === $order->getImmutability(Order::IMMUTABLE_USER)) {
334
            throw new BadRequestHttpException;
335
        }
336
337
        $orderItem = $this->loadOrderItem($id);
338
        $model = $orderItem->product;
339
340
        $product = [
341
            [
342
                'model' => $model,
343
                'quantity' => $orderItem->quantity,
344
                'orderItem' => $orderItem,
345
            ]
346
        ];
347
        $result['success'] = $orderItem->delete() && $order->calculate(true);
0 ignored issues
show
Bug Best Practice introduced by
The expression $orderItem->delete() of type false|integer is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

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

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
348
        $event = new CartActionEvent($order, $product);
349
        Event::trigger($this, self::EVENT_ACTION_REMOVE, $event);
350
351
        $result['additional'] = $event->getEventData();
352
353
        /**
354
         * Backward compatibility
355
         */
356
        $result['itemModalPreview'] = isset($result['additional']['bcItemModalPreview'])
357
            ? $result['additional']['bcItemModalPreview']
358
            : '';
359
        $result['products'] = $this->productsModelsToArray($product);
360
        $result['itemsCount'] = $order->items_count;
361
        $result['totalPrice'] = CurrencyHelper::getMainCurrency()->format($order->total_price);
362
        $result['message'] = false === $result['success'] ? Yii::t('app', 'Cannot change additional params') : '';
363
364
        return $result;
365
    }
366
367
    /**
368
     * @return array
369
     * @throws NotFoundHttpException
370
     * @throws \Exception
371
     */
372
    public function actionClear()
373
    {
374
        Yii::$app->response->format = Response::FORMAT_JSON;
375
376
        $result = [];
377
378
        $order = $this->loadOrder();
379 View Code Duplication
        if (null === $order->stage || true === $order->getImmutability(Order::IMMUTABLE_USER)) {
380
            throw new BadRequestHttpException;
381
        }
382
383
        $products = array_reduce($order->items, function($res, $item) {
384
            $res[] = [
385
                'model' => $item->product,
386
                'quantity' => $item->quantity,
387
                'orderItem' => $item,
388
            ];
389
            return $res;
390
        }, []);
391
392
        /** @var OrderItem $item */
393
        foreach ($order->items as $item) {
394
            $item->delete();
395
        }
396
        Order::clearStaticOrder();
397
        $order = $this->loadOrder();
398
        $result['success'] = $order->calculate(true);
399
400
        $event = new CartActionEvent($order, $products);
0 ignored issues
show
Bug introduced by
It seems like $order defined by $this->loadOrder() on line 397 can be null; however, app\modules\shop\events\...ionEvent::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
401
        Event::trigger($this, self::EVENT_ACTION_CLEAR, $event);
402
403
        $result['additional'] = $event->getEventData();
404
        $result['products'] = $this->productsModelsToArray($products);
405
406
        return $result;
407
    }
408
409
    /**
410
     * @return string
411
     * @throws NotFoundHttpException
412
     */
413
    public function actionIndex()
414
    {
415
        $model = $this->loadOrder(false, false);
416
        $orderCode = null;
417
        if (!is_null($model)) {
418
            $orderCode = OrderCode::find()
419
                ->where(
420
                    [
421
                        'order_id' => $model->id,
422
                        'status' => 1
423
                    ]
424
                )
425
                ->one();
426
427
            if ($orderCode === null) {
428
                $orderCode = new OrderCode();
429
430
                if (Yii::$app->request->isPost) {
431
                    $orderCode->load(Yii::$app->request->post());
432
                    $orderCode->order_id = $model->id;
433
                    if ($orderCode->save()) {
434
                        $this->refresh();
435
                    }
436
                }
437
            }
438
            $model->calculate();
439
        }
440
        return $this->render('index', ['model' => $model, 'orderCode' => $orderCode]);
441
    }
442
443
    /**
444
     * @return string|Response
445
     * @throws NotFoundHttpException
446
     */
447
    public function actionStage()
448
    {
449
        $order = $this->loadOrder(false, false);
450
        if (empty($order) || $order->getImmutability(Order::IMMUTABLE_USER)) {
451
            return $this->redirect(Url::to(['index']));
452
        }
453
454
        /** @var OrderStage $orderStage */
455
        $orderStage = $order->stage;
456
        $eventData = ['order' => $order];
457
458
        if (0 === intval($orderStage->is_in_cart)) {
459
            Yii::$app->session->remove('orderId');
460
            $order->in_cart = 0;
461
            $order->save();
462
            Order::clearStaticOrder();
463
        }
464
        if (1 === intval($orderStage->become_non_temporary)) {
465
            $order->temporary = 0;
466
            $order->save();
467
        }
468
469
//        if (null !== Yii::$app->session->get('OrderStageReach')) {
470
        /** @var Events $eventClass */
471
        $eventClass = Events::findByName($orderStage->event_name);
472
        if (!empty($eventClass) && is_subclass_of($eventClass->event_class_name, OrderStageEvent::className())) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \app\modules\shop\events...StageEvent::className() can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
473
            /** @var OrderStageEvent $event */
474
            $event = new $eventClass->event_class_name;
475
            $event->setEventData($eventData);
476
            EventTriggeringHelper::triggerSpecialEvent($event);
477
            $eventData = $event->eventData();
478
479
            if (!empty($eventData['__redirect'])) {
480
                return $this->redirect($eventData['__redirect']);
481
            }
482
        }
483
        Yii::$app->session->remove('OrderStageReach');
484
//        }
485
486
        return $this->render(
487
            'stage',
488
            [
489
                'order' => $order,
490
                'stage' => $orderStage,
491
                'eventData' => $eventData,
492
            ]
493
        );
494
    }
495
496
    /**
497
     * @param null $id
498
     * @return Response
499
     * @throws NotFoundHttpException
500
     * @throws \yii\base\Exception
501
     */
502
    public function actionStageLeaf($id = null)
503
    {
504
        if (empty($id)) {
505
            return $this->redirect(Url::to(['stage']));
506
        }
507
        /** @var OrderStageLeaf $orderStageLeaf */
508
        $orderStageLeaf = OrderStageLeaf::findOne(['id' => $id]);
509
        if (empty($orderStageLeaf)) {
510
            return $this->redirect(Url::to(['stage']));
511
        }
512
513
        $order = $this->loadOrder(false, false);
514
        if (empty($order)) {
515
            return $this->redirect(Url::to(['index']));
516
        }
517
518
        $orderStage = $order->stage;
519
        if ($orderStage->id !== $orderStageLeaf->stage_from_id && $orderStage->id !== $orderStageLeaf->stage_to_id) {
520
            return $this->redirect(Url::to(['stage']));
521
        }
522
523
        if (null !== Yii::$app->request->get('previous') && 1 !== intval($orderStageLeaf->stageFrom->immutable_by_user)) {
524
            $order->order_stage_id = $orderStageLeaf->stageFrom->id;
525
            $order->save();
526
        } else {
527
            /** @var Events $eventClassName */
528
            $eventClassName = Events::findByName($orderStageLeaf->event_name);
529
            if (!empty($eventClassName) && is_subclass_of($eventClassName->event_class_name, OrderStageLeafEvent::className())) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \app\modules\shop\events...eLeafEvent::className() can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
530
                /** @var OrderStageLeafEvent $event */
531
                $event = new $eventClassName->event_class_name;
532
                EventTriggeringHelper::triggerSpecialEvent($event);
533
                if ($event->getStatus()) {
534
                    $order->order_stage_id = $order->order_stage_id == $orderStageLeaf->stage_to_id
535
                        ? $orderStageLeaf->stage_from_id
536
                        : $orderStageLeaf->stage_to_id;
537
                    $order->save();
538
539
                    Yii::$app->session->set('OrderStageReach', true);
540
                }
541
            }
542
        }
543
544
        return $this->redirect(Url::to(['stage']));
545
    }
546
547
    /**
548
     * @inheritdoc
549
     */
550
    public function beforeAction($action)
551
    {
552
        if (false === parent::beforeAction($action)) {
553
            return false;
554
        }
555
556
        $_renderCartPreview = [
557
            self::EVENT_ACTION_ADD,
558
            self::EVENT_ACTION_REMOVE,
559
            self::EVENT_ACTION_QUANTITY,
560
            self::EVENT_ACTION_CLEAR,
561
        ];
562
        foreach ($_renderCartPreview as $_eventName) {
563
            Event::on(self::className(), $_eventName, [CartHandler::className(), 'renderCartPreview']);
0 ignored issues
show
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
564
        }
565
566
        return true;
567
    }
568
569
    /**
570
     * @param array $products
571
     * @return array
572
     */
573
    private function productsModelsToArray($products)
574
    {
575
        return array_reduce($products, function($res, $item) {
576
            /** @var Product $model */
577
            $model = $item['model'];
578
579
            $i = [
580
                'id' => $model->id,
581
                'name' => $model->name,
582
                'price' => CurrencyHelper::convertToMainCurrency($model->price, $model->currency),
583
                'currency' => CurrencyHelper::getMainCurrency()->iso_code,
584
            ];
585
            if (isset($item['quantity'])) {
586
                $i['quantity'] = $item['quantity'];
587
            }
588
589
            $res[] = $i;
590
            return $res;
591
        }, []);
592
    }
593
}
594