Completed
Push — master ( f9623f...c6d8a3 )
by Dmitry
13:53
created

ShoppingCart::trigger()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 0
cts 0
cp 0
rs 9.9666
c 0
b 0
f 0
cc 2
nc 2
nop 2
crap 6
1
<?php
2
3
/*
4
 * Cart module for Yii2
5
 *
6
 * @link      https://github.com/hiqdev/yii2-cart
7
 * @package   yii2-cart
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2015-2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hiqdev\yii2\cart;
13
14
use hipanel\modules\finance\cart\AbstractCartPosition;
15
use Yii;
16
use yii\base\Event;
17
use yz\shoppingcart\CartActionEvent;
18
19
/**
20
 * Class ShoppingCart.
21
 * @property AbstractCartPosition[] $positions
22
 */
23
class ShoppingCart extends \yz\shoppingcart\ShoppingCart
24
{
25
    /**
26
     * @var AbstractCartPosition[]
27
     * TODO make local AbstractCartPosition
28
     */
29
    protected $_positions = [];
30
31
    /**
32
     * The cart module.
33
     */
34
    public $module;
35
36
    /**
37
     * @return integer
38
     */
39 1
    public function getCount()
40
    {
41 1
        return count($this->_positions);
42
    }
43
44 1
    public function getQuantity()
45
    {
46 1
        $count = 0;
47 1
        foreach ($this->_positions as $position) {
48 1
            $count += $position->getQuantity();
49
        }
50
51 1
        return $count;
52
    }
53
54 2
    public function getSubtotal()
55
    {
56 2
        return $this->getCost(false);
57
    }
58
59 2
    public function getTotal()
60
    {
61 2
        return $this->getCost(true);
62
    }
63
64 1
    public function getDiscount()
65
    {
66 1
        return $this->getTotal() - $this->getSubtotal();
67
    }
68
69 1
    public function formatCurrency($sum, $currency = null)
70
    {
71 1
        return $sum !== null ? Yii::$app->formatter->format($sum, ['currency', $currency ?? $this->getCurrency()]) : '--';
72
    }
73
74
    /**
75
     * Sets cart from serialized string
76
     * @param string $serialized
77
     */
78
    public function setSerialized($serialized)
79
    {
80
        try {
81
            parent::setSerialized($serialized);
82
        } catch (\Exception $e) {
83
            Yii::error('Failed to unserlialize cart: ' . $e->getMessage(), __METHOD__);
84
            $this->_positions = [];
85
            $this->saveToSession();
86
        }
87
    }
88
89
    /**
90
     * Checks whether any of cart positions has error in `id` attribute.
91
     * @return boolean
92
     */
93
    public function hasErrors()
94
    {
95
        foreach ($this->_positions as $position) {
96
            if ($position->hasErrors('id')) {
97
                return true;
98
            }
99
        }
100
101
        return false;
102
    }
103
104
    /**
105
     * @param CartPositionInterface[] $positions
106
     */
107
    public function putPositions($positions)
108
    {
109
        foreach ($positions as $position) {
110
            if (isset($this->_positions[$position->getId()])) {
111
                if ($position instanceof DontIncrementQuantityWhenAlreadyInCart) {
112
                    continue;
113
                }
114
                $existingPosition = $this->_positions[$position->getId()];
115
                $existingPosition->setQuantity($existingPosition->getQuantity() + 1);
116
            } else {
117
                if ($position->getQuantity() <= 0) {
118
                    $position->setQuantity(1);
119
                }
120
                $this->_positions[$position->getId()] = $position;
121
            }
122
        }
123
124
        $this->trigger(self::EVENT_CART_CHANGE, new CartActionEvent([
125
            'action' => CartActionEvent::ACTION_POSITION_PUT,
126
        ]));
127
        if ($this->storeInSession)
128
            $this->saveToSession();
129
    }
130
131
    public function getCurrency(): ?string
132
    {
133
        if (!empty($this->_positions)) {
134
            return reset($this->_positions)->currency;
135
        }
136
137
        return Yii::$app->params['currency'];
138
    }
139
140
    /**
141
     * @return array
142
     */
143
    public function getAdditionalLinks(): array
144
    {
145
        $links = [];
146
        $positions = $this->_positions;
147
        if (empty($positions)) {
148
            return $links;
149
        }
150
151
        foreach ($positions as $position) {
152
            $additionalLinks = $position->getAdditionalLinks();
153
            if (!empty($additionalLinks)) {
154
                foreach ($additionalLinks as $link) {
155
                    [$url, $label] = $link;
0 ignored issues
show
Bug introduced by
The variable $url does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $label does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
156
                    if ($url && $label && !isset($links[$url])) {
157
                        $links[$url] = $label;
158
                    }
159
                }
160
            }
161
        }
162
163
        return $links;
164
    }
165
166
    /**
167
     * @var CartActionEvent[]|null
168
     */
169
    private $_accumulatedEvents;
170
    public function trigger($name, Event $event = null)
171
    {
172
        if (is_array($this->_accumulatedEvents)) {
173
            \Yii::info("Shopping cart accumulates event $name");
174
            $this->_accumulatedEvents[] = [$name, $event];
175
        } else {
176
            parent::trigger($name, $event);
177
        }
178
    }
179
180
    /**
181
     * Runs $closure and accumulates all events occurred during $closure run.
182
     * Events get released immediately after a success $closure run.
183
     *
184
     * The method can be used to prevent useless calculations that happen after
185
     * bunch of similar updates on a cart.
186
     *
187
     * @param \Closure $closure
188
     */
189
    public function accumulateEvents(\Closure $closure): void
190
    {
191
        $this->_accumulatedEvents = [];
192
        try {
193
            $closure();
194
            $events = $this->_accumulatedEvents;
195
            $this->_accumulatedEvents = null;
196
            foreach ($events as [$name, $event]) {
197
                \Yii::info("Releases event $name");
0 ignored issues
show
Bug introduced by
The variable $name does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
198
                $this->trigger($name, $event);
0 ignored issues
show
Bug introduced by
The variable $event does not exist. Did you mean $events?

This check looks for variables that are accessed but have not been defined. It raises an issue if it finds another variable that has a similar name.

The variable may have been renamed without also renaming all references.

Loading history...
199
            }
200
        } finally {
201
            $this->_accumulatedEvents = null;
202
        }
203
    }
204
}
205