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\forms; |
||
12 | |||
13 | use hipanel\helpers\ArrayHelper; |
||
14 | use hipanel\modules\finance\behaviors\BillQuantity; |
||
15 | use hipanel\modules\finance\logic\bill\QuantityTrait; |
||
16 | use hipanel\modules\finance\models\Bill; |
||
17 | use hipanel\modules\finance\models\Charge; |
||
18 | use hipanel\modules\finance\models\Purse; |
||
19 | use hipanel\modules\finance\validation\BillChargesSumValidator; |
||
20 | use Yii; |
||
21 | use yii\base\Model; |
||
22 | |||
23 | class BillForm extends Model |
||
24 | { |
||
25 | use QuantityTrait; |
||
26 | |||
27 | const SCENARIO_CREATE = 'create'; |
||
28 | const SCENARIO_UPDATE = 'update'; |
||
29 | const SCENARIO_COPY = 'copy'; |
||
30 | |||
31 | const EVENT_SHOW_FORM = 'showForm'; |
||
32 | |||
33 | /** |
||
34 | * @var integer |
||
35 | */ |
||
36 | public $id; |
||
37 | |||
38 | /** |
||
39 | * @var integer |
||
40 | */ |
||
41 | public $client_id; |
||
42 | |||
43 | /** |
||
44 | * @var string |
||
45 | */ |
||
46 | public $currency; |
||
47 | |||
48 | /** |
||
49 | * @var float |
||
50 | */ |
||
51 | public $sum; |
||
52 | |||
53 | /** |
||
54 | * @var string |
||
55 | */ |
||
56 | public $time; |
||
57 | |||
58 | /** |
||
59 | * @var string |
||
60 | */ |
||
61 | public $type; |
||
62 | |||
63 | /** |
||
64 | * @var string |
||
65 | */ |
||
66 | public $gtype; |
||
67 | |||
68 | /** |
||
69 | * @var float |
||
70 | */ |
||
71 | public $quantity; |
||
72 | |||
73 | /** |
||
74 | * @var float |
||
75 | */ |
||
76 | public $unit; |
||
77 | |||
78 | /** |
||
79 | * @var float |
||
80 | */ |
||
81 | public $userQuantity; |
||
82 | |||
83 | /** |
||
84 | * @var string |
||
85 | */ |
||
86 | public $label; |
||
87 | |||
88 | /** |
||
89 | * @var integer |
||
90 | */ |
||
91 | public $object_id; |
||
92 | |||
93 | /** |
||
94 | * @var string |
||
95 | */ |
||
96 | public $object; |
||
97 | |||
98 | /** |
||
99 | * @var string |
||
100 | */ |
||
101 | public $class; |
||
102 | |||
103 | /** |
||
104 | * @var Charge[] |
||
105 | */ |
||
106 | public $charges = []; |
||
107 | |||
108 | public function behaviors() |
||
109 | { |
||
110 | return [ |
||
111 | [ |
||
112 | 'class' => BillQuantity::class, |
||
113 | ], |
||
114 | ]; |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * Creates [[BillForm]] from [[Bill]]. |
||
119 | * |
||
120 | * @param Bill $bill |
||
121 | * @param string $scenario |
||
122 | * @return BillForm |
||
123 | */ |
||
124 | public static function createFromBill($bill, $scenario) |
||
125 | { |
||
126 | $attributes = $bill->getAttributes([ |
||
127 | 'id', 'object_id', 'client_id', 'currency', 'type', |
||
128 | 'gtype', 'sum', 'time', 'quantity', 'unit', 'label', 'object', 'class', |
||
129 | ]); |
||
130 | |||
131 | $form = new self(['scenario' => $scenario]); |
||
132 | $form->setAttributes($attributes, false); |
||
133 | |||
134 | $form->charges = array_map(function ($model) use ($scenario) { |
||
135 | $model->scenario = $scenario; |
||
136 | |||
137 | return $model; |
||
138 | }, $bill->charges); |
||
139 | |||
140 | return $form; |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * @param Bill[] $bills |
||
145 | * @param string $scenario |
||
146 | * @return BillForm[] |
||
147 | */ |
||
148 | public static function createMultipleFromBills($bills, $scenario) |
||
149 | { |
||
150 | $result = []; |
||
151 | foreach ($bills as $bill) { |
||
152 | $result[] = self::createFromBill($bill, $scenario); |
||
153 | } |
||
154 | |||
155 | return $result; |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * {@inheritdoc} |
||
160 | */ |
||
161 | public function load($data, $formName = null) |
||
162 | { |
||
163 | $this->setAttributes($data); |
||
164 | $this->loadCharges($data['charges']); |
||
165 | |||
166 | return true; |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * @return Charge[] |
||
171 | */ |
||
172 | public function getCharges() |
||
173 | { |
||
174 | if (!empty($this->charges)) { |
||
175 | return $this->charges; |
||
176 | } |
||
177 | |||
178 | return [$this->newCharge()]; |
||
179 | } |
||
180 | |||
181 | /** |
||
182 | * Creates new charge. |
||
183 | * |
||
184 | * @return Charge |
||
185 | */ |
||
186 | public function newCharge() |
||
187 | { |
||
188 | return new Charge(['scenario' => Charge::SCENARIO_CREATE]); |
||
189 | } |
||
190 | |||
191 | /** |
||
192 | * @return array |
||
193 | */ |
||
194 | public function rules() |
||
195 | { |
||
196 | return [ |
||
197 | [['id', 'object_id'], 'integer', 'on' => [self::SCENARIO_UPDATE]], |
||
198 | [['sum', 'quantity'], 'number', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]], |
||
199 | [['time'], 'date', 'format' => 'php:Y-m-d H:i:s'], |
||
200 | [['label', 'currency', 'unit', 'type', 'object', 'class'], 'safe', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]], |
||
201 | [['sum'], BillChargesSumValidator::class], |
||
202 | [['unit'], 'default', 'value' => 'items', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]], // TODO: should be probably replaced with input on client side |
||
203 | [['object_id'], 'integer', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]], |
||
204 | [['currency'], 'filter', 'filter' => 'mb_strtolower'], |
||
205 | [['currency'], 'currencyValidate', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]], |
||
206 | [['id'], 'required', 'on' => [self::SCENARIO_UPDATE]], |
||
207 | [ |
||
208 | ['client_id', 'sum', 'quantity', 'unit', 'time', 'currency', 'type'], |
||
209 | 'required', |
||
210 | 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY], |
||
211 | ], |
||
212 | [['!charges'], 'safe', 'on' => [self::SCENARIO_CREATE, self::SCENARIO_UPDATE, self::SCENARIO_COPY]], |
||
213 | |||
214 | [['time', 'object_id', 'type'], function ($attribute) { |
||
215 | try { |
||
216 | Bill::perform('check-unique', $this->attributes); |
||
217 | } catch (\Exception $e) { |
||
218 | $this->addError($attribute, Yii::t('hipanel:finance', 'The bill is not unique')); |
||
219 | } |
||
220 | }, 'on' => self::SCENARIO_COPY], |
||
221 | ]; |
||
222 | } |
||
223 | |||
224 | public function currencyValidate($attribute, $params, $validator): void |
||
225 | { |
||
226 | if (empty($this->client_id)) { |
||
227 | return; |
||
228 | } |
||
229 | $clientCurrencies = Yii::$app->cache->getOrSet('clientCurrencies' . $this->client_id, function (): array { |
||
230 | $purses = Purse::find() |
||
231 | ->where(['client_id' => $this->client_id]) |
||
232 | ->all(); |
||
233 | return ArrayHelper::getColumn($purses, 'currency'); |
||
234 | }, 3600); |
||
235 | if (!in_array($this->currency, $clientCurrencies, true)) { |
||
236 | $this->addError($attribute, Yii::t('hipanel:finance', 'Client hasn\'t purse with this currency')); |
||
237 | } |
||
238 | } |
||
239 | |||
240 | View Code Duplication | public function attributeLabels() |
|
0 ignored issues
–
show
|
|||
241 | { |
||
242 | return [ |
||
243 | 'client_id' => Yii::t('hipanel', 'Client'), |
||
244 | 'time' => Yii::t('hipanel', 'Time'), |
||
245 | 'currency' => Yii::t('hipanel', 'Currency'), |
||
246 | 'sum' => Yii::t('hipanel:finance', 'Sum'), |
||
247 | 'label' => Yii::t('hipanel', 'Description'), |
||
248 | 'type' => Yii::t('hipanel', 'Type'), |
||
249 | 'quantity' => Yii::t('hipanel', 'Quantity'), |
||
250 | 'object_id' => Yii::t('hipanel', 'Object'), |
||
251 | ]; |
||
252 | } |
||
253 | |||
254 | public function getIsNewRecord() |
||
255 | { |
||
256 | return $this->id === null; |
||
257 | } |
||
258 | |||
259 | public function forceNewRecord(): void |
||
260 | { |
||
261 | $this->id = null; |
||
262 | $this->time = new \DateTime(); |
||
263 | } |
||
264 | |||
265 | private function getChargesAsArray() |
||
266 | { |
||
267 | return array_filter(array_map(function ($model) { |
||
268 | /** @var Charge $model */ |
||
269 | if ($model->validate()) { |
||
270 | return $model->toArray(); |
||
271 | } |
||
272 | |||
273 | return null; |
||
274 | }, $this->charges)); |
||
275 | } |
||
276 | |||
277 | public function fields() |
||
278 | { |
||
279 | return [ |
||
280 | 'id', |
||
281 | 'client_id', |
||
282 | 'object_id', |
||
283 | 'currency', |
||
284 | 'sum', |
||
285 | 'time', |
||
286 | 'type', |
||
287 | 'quantity', |
||
288 | 'label', |
||
289 | 'object', |
||
290 | 'class', |
||
291 | 'charges' => function () { |
||
292 | return $this->getChargesAsArray(); |
||
293 | }, |
||
294 | ]; |
||
295 | } |
||
296 | |||
297 | public function loadCharges($data) |
||
298 | { |
||
299 | $charges = []; |
||
300 | |||
301 | foreach ((array) $data as $datum) { |
||
302 | $charge = $this->newCharge(); |
||
303 | if ($charge->load($datum, '')) { |
||
304 | $charge->markAsNotNew(); |
||
305 | $charges[] = $charge; |
||
306 | } |
||
307 | } |
||
308 | |||
309 | $this->charges = $charges; |
||
310 | |||
311 | return true; |
||
312 | } |
||
313 | |||
314 | public function getPrimaryKey() |
||
315 | { |
||
316 | return $this->id; |
||
317 | } |
||
318 | |||
319 | public static function primaryKey() |
||
320 | { |
||
321 | return ['id']; |
||
322 | } |
||
323 | |||
324 | /** |
||
325 | * For compatibility with [[hiqdev\hiart\Collection]]. |
||
326 | * |
||
327 | * @param $defaultScenario |
||
328 | * @param array $data |
||
329 | * @param array $options |
||
330 | * @return mixed |
||
331 | */ |
||
332 | public function batchQuery($defaultScenario, $data = [], array $options = []) |
||
333 | { |
||
334 | $map = [ |
||
335 | 'create' => 'create', |
||
336 | 'update' => 'update', |
||
337 | ]; |
||
338 | $scenario = isset($map[$defaultScenario]) ? $map[$defaultScenario] : $defaultScenario; |
||
339 | |||
340 | return (new Bill())->batchQuery($scenario, $data, $options); |
||
341 | } |
||
342 | |||
343 | public function getOldAttribute($attribute) |
||
344 | { |
||
345 | return $this->$attribute; |
||
346 | } |
||
347 | |||
348 | public function setOldAttribute($attribute, $value) |
||
349 | { |
||
350 | return true; |
||
351 | } |
||
352 | |||
353 | public function setOldAttributes($values) |
||
354 | { |
||
355 | return true; |
||
356 | } |
||
357 | |||
358 | public function afterSave() |
||
359 | { |
||
360 | return true; |
||
361 | } |
||
362 | } |
||
363 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.