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 hiqdev\hiart\ResponseErrorException; |
||
14 | use hiqdev\yii2\cart\ShoppingCart; |
||
15 | use Yii; |
||
16 | use yii\base\InvalidParamException; |
||
17 | use yii\web\User; |
||
18 | |||
19 | /** |
||
20 | * Class BatchPurchaseStrategy purchases positions in batch. |
||
21 | * |
||
22 | * @author Dmytro Naumenko <[email protected]> |
||
23 | */ |
||
24 | class BatchPurchaseStrategy implements PurchaseStrategyInterface |
||
25 | { |
||
26 | use PurchaseResultTrait; |
||
27 | |||
28 | /** |
||
29 | * @var AbstractCartPosition[] |
||
30 | */ |
||
31 | protected $positions = []; |
||
32 | |||
33 | /** |
||
34 | * @var ShoppingCart |
||
35 | */ |
||
36 | protected $cart; |
||
37 | |||
38 | /** |
||
39 | * @var AbstractPurchase[] |
||
40 | */ |
||
41 | protected $purchases; |
||
42 | /** |
||
43 | * @var User |
||
44 | */ |
||
45 | private $user; |
||
46 | |||
47 | /** |
||
48 | * BatchPurchaseStrategy constructor. |
||
49 | * |
||
50 | * @param ShoppingCart $cart |
||
51 | */ |
||
52 | public function __construct(ShoppingCart $cart, User $user) |
||
53 | { |
||
54 | $this->cart = $cart; |
||
55 | $this->user = $user; |
||
56 | } |
||
57 | |||
58 | /** {@inheritdoc} */ |
||
59 | public function addPosition(AbstractCartPosition $position) |
||
60 | { |
||
61 | $this->positions[$position->getId()] = $position; |
||
62 | $this->ensureConsistency(); |
||
63 | } |
||
64 | |||
65 | /** {@inheritdoc} */ |
||
66 | public function run() |
||
67 | { |
||
68 | $this->resetPurchaseResults(); |
||
69 | $this->createPurchaseObjects(); |
||
70 | if (empty($this->purchases)) { |
||
71 | return; |
||
72 | } |
||
73 | |||
74 | $samplePurchase = reset($this->purchases); |
||
75 | $operation = $samplePurchase::operation(); |
||
76 | |||
77 | try { |
||
78 | $response = $samplePurchase::perform($operation, $this->collectData(), ['batch' => true]); |
||
79 | $this->analyzeResponse($response); |
||
80 | } catch (ResponseErrorException $e) { |
||
81 | $this->extractResultsFromException($e); |
||
82 | } |
||
83 | } |
||
84 | |||
85 | private function createPurchaseObjects() |
||
86 | { |
||
87 | foreach ($this->positions as $id => $position) { |
||
88 | $this->purchases[$id] = $position->getPurchaseModel(); |
||
89 | } |
||
90 | } |
||
91 | |||
92 | private function collectData() |
||
93 | { |
||
94 | $result = []; |
||
95 | foreach ($this->purchases as $id => $purchase) { |
||
96 | if (!$purchase->validate()) { |
||
97 | Yii::error('Failed to validate purchase: ' . reset($purchase->getFirstErrors()), __METHOD__); |
||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
98 | $this->error[] = new ErrorPurchaseException('Failed to validate purchase. Contact support.', $purchase); |
||
99 | continue; |
||
100 | } |
||
101 | |||
102 | $result[$id] = $purchase->getAttributes(); |
||
103 | } |
||
104 | |||
105 | return $result; |
||
106 | } |
||
107 | |||
108 | private function extractResultsFromException(ResponseErrorException $e) |
||
109 | { |
||
110 | $data = $e->getResponse()->getData(); |
||
111 | |||
112 | if (!is_array($data)) { |
||
113 | Yii::error('Abnormal response during purchase', __METHOD__); |
||
114 | throw $e; |
||
115 | } |
||
116 | |||
117 | $this->analyzeResponse($data); |
||
118 | } |
||
119 | |||
120 | protected function analyzeResponse($response) |
||
121 | { |
||
122 | if ($response['_error'] === 'not enough money') { |
||
123 | foreach ($this->purchases as $key => $purchase) { |
||
124 | $error = Yii::t('hipanel:finance', 'Insufficient funds on the balance'); |
||
125 | if ($this->user->can('support')) { |
||
126 | $error = Yii::t('hipanel:finance', 'Insufficient funds. Maybe, your client does not have enough money on balance?'); |
||
127 | } |
||
128 | |||
129 | $this->error[] = new ErrorPurchaseException($error, $purchase); |
||
130 | } |
||
131 | } |
||
132 | |||
133 | foreach ($response as $key => $item) { |
||
134 | $this->analyzeResponseItem($key, $item); |
||
135 | } |
||
136 | } |
||
137 | |||
138 | protected function analyzeResponseItem($key, $data) |
||
139 | { |
||
140 | if (!isset($this->purchases[$key])) { |
||
141 | return; |
||
142 | } |
||
143 | |||
144 | $purchase = $this->purchases[$key]; |
||
145 | if ($error = $this->getPurchaseErrorFromResponse($purchase, $data)) { |
||
146 | $this->error[] = new ErrorPurchaseException($error, $purchase); |
||
147 | } elseif ($pendingMessage = $this->getPurchasePendingFromResponse($purchase, $data)) { |
||
148 | $this->pending[] = new PendingPurchaseException($pendingMessage, $purchase); |
||
149 | } else { |
||
150 | $this->success[] = $purchase; |
||
151 | } |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * @param AbstractPurchase $purchase |
||
156 | * @param array $data |
||
157 | * @return string|null Error message or `null` when no errors found |
||
158 | */ |
||
159 | protected function getPurchaseErrorFromResponse(AbstractPurchase $purchase, $data) |
||
160 | { |
||
161 | if (is_array($data) && array_key_exists('_error', $data)) { |
||
162 | return $data['_error']; |
||
163 | } |
||
164 | |||
165 | return null; |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Override this method to detect pending purchase result. |
||
170 | * |
||
171 | * @param AbstractPurchase $purchase |
||
172 | * @param array $data |
||
173 | * @return string|null Pending reason or `null` when no errors found |
||
174 | */ |
||
175 | protected function getPurchasePendingFromResponse(AbstractPurchase $purchase, $data) |
||
176 | { |
||
177 | return null; |
||
178 | } |
||
179 | |||
180 | protected function ensureConsistency() |
||
181 | { |
||
182 | $class = null; |
||
183 | foreach ($this->positions as $id => $position) { |
||
184 | if ($class === null) { |
||
185 | $class = get_class($position); |
||
186 | } |
||
187 | |||
188 | if (!$position instanceof $class) { |
||
189 | throw new InvalidParamException('Position "' . $id . '" is violates position class consistency policy'); |
||
0 ignored issues
–
show
The class
yii\base\InvalidParamException has been deprecated with message: since 2.0.14. Use [[InvalidArgumentException]] instead.
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.
Loading history...
|
|||
190 | } |
||
191 | } |
||
192 | } |
||
193 | } |
||
194 |