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 | |||
18 | /** |
||
19 | * Class BatchPurchaseStrategy purchases positions in batch. |
||
20 | * |
||
21 | * @author Dmytro Naumenko <[email protected]> |
||
22 | */ |
||
23 | class BatchPurchaseStrategy implements PurchaseStrategyInterface |
||
24 | { |
||
25 | use PurchaseResultTrait; |
||
26 | |||
27 | /** |
||
28 | * @var AbstractCartPosition[] |
||
29 | */ |
||
30 | protected $positions = []; |
||
31 | |||
32 | /** |
||
33 | * @var ShoppingCart |
||
34 | */ |
||
35 | protected $cart; |
||
36 | |||
37 | /** |
||
38 | * @var AbstractPurchase[] |
||
39 | */ |
||
40 | protected $purchases; |
||
41 | |||
42 | /** |
||
43 | * BatchPurchaseStrategy constructor. |
||
44 | * |
||
45 | * @param ShoppingCart $cart |
||
46 | */ |
||
47 | public function __construct(ShoppingCart $cart) |
||
48 | { |
||
49 | $this->cart = $cart; |
||
50 | } |
||
51 | |||
52 | /** {@inheritdoc} */ |
||
53 | public function addPosition(AbstractCartPosition $position) |
||
54 | { |
||
55 | $this->positions[$position->getId()] = $position; |
||
56 | $this->ensureConsistency(); |
||
57 | } |
||
58 | |||
59 | /** {@inheritdoc} */ |
||
60 | public function run() |
||
61 | { |
||
62 | $this->resetPurchaseResults(); |
||
63 | $this->createPurchaseObjects(); |
||
64 | if (empty($this->purchases)) { |
||
65 | return; |
||
66 | } |
||
67 | |||
68 | $samplePurchase = reset($this->purchases); |
||
69 | $operation = $samplePurchase::operation(); |
||
70 | |||
71 | try { |
||
72 | $response = $samplePurchase::perform($operation, $this->collectData(), ['batch' => true]); |
||
73 | $this->analyzeResponse($response); |
||
74 | } catch (ResponseErrorException $e) { |
||
75 | $this->extractResultsFromException($e); |
||
76 | } |
||
77 | } |
||
78 | |||
79 | private function createPurchaseObjects() |
||
80 | { |
||
81 | foreach ($this->positions as $id => $position) { |
||
82 | $this->purchases[$id] = $position->getPurchaseModel(); |
||
83 | } |
||
84 | } |
||
85 | |||
86 | private function collectData() |
||
87 | { |
||
88 | $result = []; |
||
89 | foreach ($this->purchases as $id => $purchase) { |
||
90 | if (!$purchase->validate()) { |
||
91 | Yii::error('Failed to validate purchase: ' . reset($purchase->getFirstErrors()), __METHOD__); |
||
92 | $this->error[] = new ErrorPurchaseException('Failed to validate purchase. Contact support.', $purchase); |
||
93 | continue; |
||
94 | } |
||
95 | |||
96 | $result[$id] = $purchase->getAttributes(); |
||
97 | } |
||
98 | |||
99 | return $result; |
||
100 | } |
||
101 | |||
102 | private function extractResultsFromException(ResponseErrorException $e) |
||
103 | { |
||
104 | $data = $e->getResponse()->getData(); |
||
105 | |||
106 | if (!is_array($data)) { |
||
107 | Yii::error('Abnormal response during purchase', __METHOD__); |
||
108 | throw $e; |
||
109 | } |
||
110 | |||
111 | $this->analyzeResponse($data); |
||
112 | } |
||
113 | |||
114 | protected function analyzeResponse($response) |
||
115 | { |
||
116 | foreach ($response as $key => $item) { |
||
117 | $this->analyzeResponseItem($key, $item); |
||
118 | } |
||
119 | } |
||
120 | |||
121 | protected function analyzeResponseItem($key, $data) |
||
122 | { |
||
123 | if (!isset($this->purchases[$key])) { |
||
124 | return; |
||
125 | } |
||
126 | |||
127 | $purchase = $this->purchases[$key]; |
||
128 | if ($error = $this->getPurchaseErrorFromResponse($purchase, $data)) { |
||
129 | $this->error[] = new ErrorPurchaseException($error, $purchase); |
||
130 | } elseif ($pendingMessage = $this->getPurchasePendingFromResponse($purchase, $data)) { |
||
131 | $this->pending[] = new PendingPurchaseException($pendingMessage, $purchase); |
||
132 | } else { |
||
133 | $this->success[] = $purchase; |
||
134 | } |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * @param AbstractPurchase $purchase |
||
139 | * @param array $data |
||
140 | * @return string|null Error message or `null` when no errors found |
||
141 | */ |
||
142 | protected function getPurchaseErrorFromResponse(AbstractPurchase $purchase, $data) |
||
0 ignored issues
–
show
|
|||
143 | { |
||
144 | if (is_array($data) && array_key_exists('_error', $data)) { |
||
145 | return $data['_error']; |
||
146 | } |
||
147 | |||
148 | return null; |
||
149 | } |
||
150 | |||
151 | /** |
||
152 | * Override this method to detect pending purchase result. |
||
153 | * |
||
154 | * @param AbstractPurchase $purchase |
||
155 | * @param array $data |
||
156 | * @return string|null Pending reason or `null` when no errors found |
||
157 | */ |
||
158 | protected function getPurchasePendingFromResponse(AbstractPurchase $purchase, $data) |
||
0 ignored issues
–
show
|
|||
159 | { |
||
160 | return null; |
||
161 | } |
||
162 | |||
163 | protected function ensureConsistency() |
||
164 | { |
||
165 | $class = null; |
||
166 | foreach ($this->positions as $id => $position) { |
||
167 | if ($class === null) { |
||
168 | $class = get_class($position); |
||
169 | } |
||
170 | |||
171 | if (!$position instanceof $class) { |
||
172 | throw new InvalidParamException('Position "' . $id . '" is violates position class consistency policy'); |
||
173 | } |
||
174 | } |
||
175 | } |
||
176 | } |
||
177 |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.