This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Finance module for HiPanel |
||
4 | * |
||
5 | * @link https://github.com/hiqdev/hipanel-module-finance |
||
6 | * @package hipanel-module-finance |
||
7 | * @license BSD-3-Clause |
||
8 | * @copyright Copyright (c) 2015-2019, HiQDev (http://hiqdev.com/) |
||
9 | */ |
||
10 | |||
11 | namespace hipanel\modules\finance\cart; |
||
12 | |||
13 | use hipanel\modules\finance\models\Bill; |
||
14 | use hiqdev\yii2\cart\NotPurchasableException; |
||
15 | use hiqdev\yii2\cart\ShoppingCart; |
||
16 | use Yii; |
||
17 | use yii\base\BaseObject; |
||
18 | use yii\web\User; |
||
19 | |||
20 | class CartFinisher extends BaseObject |
||
21 | { |
||
22 | /** |
||
23 | * @var ShoppingCart |
||
24 | */ |
||
25 | public $cart; |
||
26 | |||
27 | /** |
||
28 | * @var string|null |
||
29 | */ |
||
30 | public $exchangeFromCurrency; |
||
31 | |||
32 | /** |
||
33 | * @var User |
||
34 | */ |
||
35 | public $user; |
||
36 | |||
37 | /** |
||
38 | * @var PurchaseStrategyInterface[] |
||
39 | */ |
||
40 | protected $purchasers = []; |
||
41 | |||
42 | /** |
||
43 | * @var AbstractPurchase[] array of successful purchases |
||
44 | */ |
||
45 | protected $_success = []; |
||
46 | |||
47 | /** |
||
48 | * @var ErrorPurchaseException[] array of failed purchases |
||
49 | */ |
||
50 | protected $_error = []; |
||
51 | |||
52 | /** |
||
53 | * @var PendingPurchaseException[] array of purchases that are pending |
||
54 | */ |
||
55 | protected $_pending = []; |
||
56 | |||
57 | /** |
||
58 | * Getter for array of successful purchases. |
||
59 | * @return AbstractPurchase[] |
||
60 | */ |
||
61 | public function getSuccess() |
||
62 | { |
||
63 | return $this->_success; |
||
64 | } |
||
65 | |||
66 | /** |
||
67 | * Getter for array of failed purchases. |
||
68 | * @return ErrorPurchaseException[] |
||
69 | */ |
||
70 | public function getError() |
||
71 | { |
||
72 | return $this->_error; |
||
73 | } |
||
74 | |||
75 | /** |
||
76 | * Getter for array of failed purchases. |
||
77 | * @return PendingPurchaseException[] |
||
78 | */ |
||
79 | public function getPending() |
||
80 | { |
||
81 | return $this->_pending; |
||
82 | } |
||
83 | |||
84 | /** |
||
85 | * Runs the purchase. |
||
86 | * Purchases the positions in the [[cart]]. |
||
87 | */ |
||
88 | public function run() |
||
89 | { |
||
90 | if ($this->cart->isEmpty) { |
||
91 | return; |
||
92 | } |
||
93 | |||
94 | $this->ensureCanBeFinished(); |
||
95 | $this->createPurchasers(); |
||
96 | $this->exchangeMoney(); |
||
97 | |||
98 | foreach ($this->purchasers as $purchaser) { |
||
99 | $purchaser->run(); |
||
100 | |||
101 | $this->cart->accumulateEvents(function () use ($purchaser) { |
||
102 | $this->_success = array_merge($this->_success, $purchaser->getSuccessPurchases()); |
||
103 | foreach ($purchaser->getSuccessPurchases() as $purchase) { |
||
104 | $this->cart->remove($purchase->position); |
||
105 | } |
||
106 | $this->_pending = array_merge($this->_pending, $purchaser->getPendingPurchaseExceptions()); |
||
107 | foreach ($purchaser->getPendingPurchaseExceptions() as $exception) { |
||
108 | $this->cart->remove($exception->position); |
||
109 | } |
||
110 | }); |
||
111 | $this->_error = array_merge($this->_error, $purchaser->getErrorPurchaseExceptions()); |
||
112 | } |
||
113 | } |
||
114 | |||
115 | protected function ensureCanBeFinished() |
||
116 | { |
||
117 | /** @var PositionPurchasabilityValidatorInterface[] $validators */ |
||
118 | $validators = []; |
||
119 | |||
120 | foreach ($this->cart->positions as $position) { |
||
121 | $purchase = $position->getPurchaseModel(); |
||
0 ignored issues
–
show
|
|||
122 | |||
123 | foreach ($purchase->getPurchasabilityRules() as $validator) { |
||
124 | if (!isset($validators[$validator])) { |
||
125 | $validators[$validator] = Yii::createObject($validator); |
||
126 | } |
||
127 | } |
||
128 | } |
||
129 | |||
130 | try { |
||
131 | foreach ($validators as $validator) { |
||
132 | $validator->validate($this->cart->positions); |
||
133 | } |
||
134 | } catch (NotPurchasableException $e) { |
||
135 | $e->resolve(); |
||
136 | } |
||
137 | } |
||
138 | |||
139 | protected function createPurchasers() |
||
140 | { |
||
141 | foreach ($this->cart->positions as $position) { |
||
142 | if ($position instanceof BatchPurchasablePositionInterface) { |
||
143 | $purchaser = $this->getPurchaser(get_class($position), $position->getBatchPurchaseStrategyClass()); |
||
144 | } else { |
||
145 | $purchaser = $this->getPurchaser(get_class($position), OneByOnePurchaseStrategy::class); |
||
146 | } |
||
147 | |||
148 | $purchaser->addPosition($position); |
||
0 ignored issues
–
show
$position of type object<hiqdev\yii2\cart\CartPositionInterface> is not a sub-type of object<hipanel\modules\f...t\AbstractCartPosition> . It seems like you assume a concrete implementation of the interface hiqdev\yii2\cart\CartPositionInterface 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...
|
|||
149 | } |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * @param string $positionClass |
||
154 | * @param string $purchaserClass |
||
155 | * @return PurchaseStrategyInterface |
||
156 | */ |
||
157 | protected function getPurchaser($positionClass, $purchaserClass) |
||
158 | { |
||
159 | if (!isset($this->purchasers[$positionClass])) { |
||
160 | $this->purchasers[$positionClass] = new $purchaserClass($this->cart, $this->user); |
||
161 | } |
||
162 | |||
163 | return $this->purchasers[$positionClass]; |
||
164 | } |
||
165 | |||
166 | private function exchangeMoney(): void |
||
167 | { |
||
168 | if ($this->exchangeFromCurrency === null) { |
||
169 | return; |
||
170 | } |
||
171 | |||
172 | Bill::perform('create-exchange', [ |
||
173 | 'from' => $this->exchangeFromCurrency, |
||
174 | 'to' => $this->cart->getCurrency(), |
||
175 | 'buySum' => $this->cart->getTotal(), |
||
176 | ]); |
||
177 | } |
||
178 | } |
||
179 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the interface: