Commit c2ef0939c007466c8265a903330db0ae61ae25b8
1 parent
9f082181
add array model validator and adjusted crosses upload form to it
Showing
8 changed files
with
180 additions
and
53 deletions
Show diff stats
backend/controllers/CrossingUploadController.php
... | ... | @@ -8,20 +8,16 @@ |
8 | 8 | |
9 | 9 | namespace backend\controllers; |
10 | 10 | |
11 | -use backend\components\base\BaseActiveRecord; | |
12 | 11 | use backend\components\base\BaseController; |
13 | 12 | use common\components\CustomArrayHelper; |
14 | -use common\components\CustomVarDamp; | |
15 | -use yii\base\ErrorException; | |
16 | -use yii\base\Model; | |
17 | 13 | use yii\data\ArrayDataProvider; |
18 | -use yii\db\ActiveRecord; | |
19 | 14 | use yii\filters\VerbFilter; |
20 | 15 | use yii\filters\AccessControl; |
21 | 16 | use backend\models\UploadFileCrossingForm; |
22 | 17 | use backend\models\DetailsCrosses; |
23 | 18 | use yii\multiparser\DynamicFormHelper; |
24 | 19 | use yii\web\UploadedFile; |
20 | +use common\components\ModelArrayValidator; | |
25 | 21 | use \Yii; |
26 | 22 | |
27 | 23 | class CrossingUploadController extends BaseController |
... | ... | @@ -141,11 +137,19 @@ class CrossingUploadController extends BaseController |
141 | 137 | // запустим конвертер над над данными |
142 | 138 | $data = $this->convertDataByConfiguration( $data, $configuration ); |
143 | 139 | |
140 | + // валидируем отпарсенные данные моделью в которую будем записывать | |
144 | 141 | $crosses_model = new DetailsCrosses(); |
142 | + $model_validator = new ModelArrayValidator( $crosses_model ); | |
143 | + $data = $model_validator->validate( $data ); | |
144 | + $msg = $model_validator->getMassage(); | |
145 | + $type_msg = $model_validator->hasError() ? 'warning' : 'success'; | |
146 | + $model_validator->close(); | |
147 | + | |
148 | + $data = $this->reverseCrosses( $data ); | |
145 | 149 | |
146 | 150 | if ( $crosses_model->ManualInsertWithIgnore( $data ) ) { |
147 | 151 | |
148 | - Yii::$app->session->setFlash('success', 'Файл кроссов успешно загружен'); | |
152 | + Yii::$app->session->setFlash( $type_msg, $msg ); | |
149 | 153 | |
150 | 154 | // очистим кеш |
151 | 155 | $this->cacheHandler( 2 ); |
... | ... | @@ -200,20 +204,10 @@ class CrossingUploadController extends BaseController |
200 | 204 | $basic_options = Yii::$app->multiparser->getConfiguration( 'csv', 'crosses' ); |
201 | 205 | $options = array_merge_recursive( $options, $basic_options ); |
202 | 206 | |
203 | - // для доп массива обратных строк | |
204 | - $i = count( $data ) - 1; | |
205 | - $reverse_data = []; | |
206 | 207 | foreach ( $data as &$row ) { |
207 | 208 | $row = Yii::$app->converter->convertByConfiguration( $row, $options['converter_conf'] ); |
208 | - // нужно добавить обратную строку по кроссам | |
209 | - $reverse_data[ $i ]['ARTICLE'] = $row['CROSS_ARTICLE']; | |
210 | - $reverse_data[ $i ]['CROSS_ARTICLE'] = $row['ARTICLE']; | |
211 | - $reverse_data[ $i ]['BRAND'] = $row['CROSS_BRAND']; | |
212 | - $reverse_data[ $i ]['CROSS_BRAND'] = $row['BRAND']; | |
213 | - $i++; | |
214 | 209 | } |
215 | 210 | |
216 | - $data = array_merge( $data, $reverse_data ); | |
217 | 211 | return $data; |
218 | 212 | |
219 | 213 | } |
... | ... | @@ -251,21 +245,22 @@ class CrossingUploadController extends BaseController |
251 | 245 | |
252 | 246 | } |
253 | 247 | |
254 | -// protected function validateModel( BaseActiveRecord $model, array $data ){ | |
255 | -// | |
256 | -// foreach ( $data as $row ) { | |
257 | -// // подготовим данные к валидации | |
258 | -// $validate_attr[$model->formName()] = $row; | |
259 | -// if( !$model->load( $validate_attr ) ){ | |
260 | -// // такой ситуации не должно быть, но на всякий случай | |
261 | -// throw new ErrorException('Незаполнены обязательные поля формы.'); | |
262 | -// } | |
263 | -// if ( !$model->validate( ) ) { | |
264 | -// $model->throwStringErrorException( key( $data ) ); | |
265 | -// }; | |
266 | -// } | |
267 | -// | |
268 | -// return true; | |
269 | -// | |
270 | -// } | |
248 | + protected function reverseCrosses ( $data ) | |
249 | + { | |
250 | + // для доп массива обратных строк | |
251 | + $i = count( $data ) - 1; | |
252 | + $reverse_data = []; | |
253 | + foreach ( $data as &$row ) { | |
254 | + // нужно добавить обратную строку по кроссам | |
255 | + $reverse_data[ $i ]['ARTICLE'] = $row['CROSS_ARTICLE']; | |
256 | + $reverse_data[ $i ]['CROSS_ARTICLE'] = $row['ARTICLE']; | |
257 | + $reverse_data[ $i ]['BRAND'] = $row['CROSS_BRAND']; | |
258 | + $reverse_data[ $i ]['CROSS_BRAND'] = $row['BRAND']; | |
259 | + $i++; | |
260 | + } | |
261 | + $data = array_merge( $data, $reverse_data ); | |
262 | + | |
263 | + return $data; | |
264 | + } | |
265 | + | |
271 | 266 | } |
272 | 267 | \ No newline at end of file | ... | ... |
backend/controllers/RgGrupController.php
... | ... | @@ -125,7 +125,7 @@ class RgGrupController extends BaseController |
125 | 125 | } |
126 | 126 | |
127 | 127 | // провалидируем выбранные колонки |
128 | - if ($model->validate()) { | |
128 | + if ( $model->validate() ) { | |
129 | 129 | |
130 | 130 | // валидация успешна у нас есть соответсвие колонок, преобразуем в массив данное соответсвие для дальнейшей работы |
131 | 131 | $arr = $model->toArray(); |
... | ... | @@ -147,7 +147,7 @@ class RgGrupController extends BaseController |
147 | 147 | $data = CustomArrayHelper::createAssocArray($data, $arr, 'attr_'); |
148 | 148 | |
149 | 149 | // в первой строке у нас заголовки - уберем |
150 | - unset($data[0]); | |
150 | + unset( $data[0] ); | |
151 | 151 | // подготовим данные для записи в таблицу w_margins_groups |
152 | 152 | $arr_values = []; |
153 | 153 | $group = ''; | ... | ... |
backend/views/crossing-upload/index.php
... | ... | @@ -8,9 +8,6 @@ use yii\helpers\ArrayHelper; |
8 | 8 | <div class="col-lg-5"> |
9 | 9 | <?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data',],'action'=>['crossing-upload/result']]); |
10 | 10 | |
11 | - if ($msg = \Yii::$app->session->getFlash('success')) { // вернулись после успешной загрузки данного файла | |
12 | - echo Html::tag('h3', $msg ,['class'=>'bg-success']); | |
13 | - } | |
14 | 11 | ?> |
15 | 12 | <h3>Кросс файлы</h3> |
16 | 13 | |
... | ... | @@ -22,7 +19,16 @@ use yii\helpers\ArrayHelper; |
22 | 19 | <?= Html::submitButton(Yii::t( 'app', 'Прочитать' ), ['class' => 'btn btn-primary']) ?> |
23 | 20 | </div> |
24 | 21 | |
25 | - <?php ActiveForm::end() ?> | |
22 | + <?php ActiveForm::end(); | |
23 | + Html::tag('br'); | |
24 | + if ($msg = \Yii::$app->session->getFlash('success')) | |
25 | + { | |
26 | + echo Html::tag('p', $msg ,['class'=>'bg-success']); | |
27 | + } elseif ($msg = \Yii::$app->session->getFlash('warning')) | |
28 | + { | |
29 | + echo Html::tag('p', $msg, ['class' => 'bg-warning']); | |
30 | + } | |
31 | + ?> | |
26 | 32 | </div> |
27 | 33 | </div> |
28 | 34 | ... | ... |
backend/views/currency/index.php
1 | +<?php | |
2 | +/** | |
3 | + * Created by PhpStorm. | |
4 | + * User: Tsurkanov | |
5 | + * Date: 26.11.2015 | |
6 | + * Time: 9:04 | |
7 | + */ | |
8 | + | |
9 | +namespace common\components; | |
10 | + | |
11 | +use yii\base\Model; | |
12 | + | |
13 | +/** | |
14 | + * Class ModelArrayValidator | |
15 | + * @package common\components | |
16 | + * Валидирует переданный массив, сохраняет отдельно ошибки, и возвращает отвалидированные данные | |
17 | + * также формирует сообщение на форму с количеством обработанных записей и количеством ошибок | |
18 | + * использовать когда нужно сохранить только отвалидированные данные, | |
19 | + * а ошибочные откинуть и показать пользователю в сообщении | |
20 | + */ | |
21 | +class ModelArrayValidator | |
22 | +{ | |
23 | + protected $arr_errors = []; | |
24 | + protected $model; | |
25 | + protected $valid_data = []; | |
26 | + protected $total_rows = 0; | |
27 | + | |
28 | + public function __construct( Model $model ) | |
29 | + { | |
30 | + $this->model = $model; | |
31 | + } | |
32 | + | |
33 | + /** | |
34 | + * @return array | |
35 | + */ | |
36 | + public function getErrors() | |
37 | + { | |
38 | + return $this->arr_errors; | |
39 | + } | |
40 | + | |
41 | + /** | |
42 | + * @return mixed | |
43 | + */ | |
44 | + public function getValidData() | |
45 | + { | |
46 | + return $this->valid_data; | |
47 | + } | |
48 | + | |
49 | + /** | |
50 | + * @return string - сообщение на форму с результатми обработки | |
51 | + */ | |
52 | + public function getMassage () | |
53 | + { | |
54 | + $total_count = $this->total_rows; | |
55 | + $success_count = $this->total_rows - count($this->arr_errors); | |
56 | + $error_count = count($this->arr_errors); | |
57 | + | |
58 | + $msg = "Обработано - {$total_count} строк.</br> | |
59 | + Успешно загрузились - {$success_count} строк.</br> | |
60 | + Найдено строк с ошибками - {$error_count}.</br>"; | |
61 | + | |
62 | + foreach ($this->arr_errors as $row => $error) { | |
63 | + $msg .= "Ошибка в строке {$row} </br> | |
64 | + Текст ошибки: {$error} </br>"; | |
65 | + } | |
66 | + | |
67 | + return $msg; | |
68 | + } | |
69 | + | |
70 | + /** | |
71 | + * @param $data | |
72 | + * @return array | |
73 | + * метод регистрирует ошибки, регистрирует "чистые данные" и возвращает их | |
74 | + */ | |
75 | + public function validate( $data ) | |
76 | + { | |
77 | + foreach ( $data as $row ) { | |
78 | + $this->total_rows++; | |
79 | + $validate_row[$this->model->formName()] = $row; | |
80 | + // clear previous loading | |
81 | + $this->clearModelAttributes(); | |
82 | + if ( $this->model->load( $validate_row ) && $this->model->validate() ) { | |
83 | + // everything OK, registred row to valid data | |
84 | + $this->valid_data[] = $row; | |
85 | + } else{ | |
86 | + // we have errors | |
87 | + $this->registredError( $this->total_rows ); | |
88 | + } | |
89 | + } | |
90 | + | |
91 | + return $this->valid_data; | |
92 | + } | |
93 | + | |
94 | + protected function registredError ($index) | |
95 | + { | |
96 | + $errors_str = ''; | |
97 | + foreach ($this->model->getErrors() as $error) { | |
98 | + $errors_str .= implode(array_values($error)); | |
99 | + } | |
100 | + | |
101 | + $this->arr_errors[$index] = $errors_str; | |
102 | + } | |
103 | + | |
104 | + | |
105 | + public function hasError () | |
106 | + { | |
107 | + return (bool) count($this->arr_errors); | |
108 | + } | |
109 | + | |
110 | + protected function clearModelAttributes() | |
111 | + { | |
112 | + $attributes = $this->model->safeAttributes(); | |
113 | + | |
114 | + foreach ( $attributes as $key => $value ) { | |
115 | + $this->model->$value = ''; | |
116 | + } | |
117 | + | |
118 | +} | |
119 | + | |
120 | + public function close(){ | |
121 | + | |
122 | + unset( $this->valid_data ); | |
123 | + unset( $this->arr_errors ); | |
124 | + unset( $this->model ); | |
125 | + | |
126 | + } | |
127 | +} | |
0 | 128 | \ No newline at end of file | ... | ... |
common/components/parsers/CustomConverter.php
... | ... | @@ -25,15 +25,17 @@ class CustomConverter extends Converter |
25 | 25 | |
26 | 26 | $details_model = new Details(); |
27 | 27 | // проверим все ли обязательные колонки были указаны пользователем |
28 | - $details_model->load(['Details' => $row]); | |
28 | +// $details_model->load(['Details' => $row]); | |
29 | +// | |
30 | +// if (!$details_model->validate()) { | |
31 | +// $errors = ''; | |
32 | +// foreach ($details_model->errors as $key => $arr_errors) { | |
33 | +// $errors .= "Аттрибут $key - " . implode(' , ', $arr_errors); | |
34 | +// } | |
35 | +// throw new \ErrorException($errors); | |
36 | +// } | |
37 | + | |
29 | 38 | |
30 | - if (!$details_model->validate()) { | |
31 | - $errors = ''; | |
32 | - foreach ($details_model->errors as $key => $arr_errors) { | |
33 | - $errors .= "Аттрибут $key - " . implode(' , ', $arr_errors); | |
34 | - } | |
35 | - throw new \ErrorException($errors); | |
36 | - } | |
37 | 39 | return $row; |
38 | 40 | } |
39 | 41 | |
... | ... | @@ -53,7 +55,7 @@ class CustomConverter extends Converter |
53 | 55 | return $row; |
54 | 56 | } |
55 | 57 | |
56 | - public function ConvertToMultiply(array $row) | |
58 | + public function ConvertToMultiply( array $row ) | |
57 | 59 | { |
58 | 60 | $PRICE = $row['PRICE']; |
59 | 61 | $sign = self::$sign; | ... | ... |
common/components/parsers/config.php
common/models/Currency.php
... | ... | @@ -30,9 +30,6 @@ class Currency extends \yii\db\ActiveRecord |
30 | 30 | { |
31 | 31 | return [ |
32 | 32 | [['name', 'rate'], 'required'], |
33 | -// [['rate'], 'filter','filter' => function($value){ | |
34 | -// return (float) str_replace( ',', '.', $value );} | |
35 | -// ], | |
36 | 33 | ['rate', \common\components\CommaNumberValidator::className()], |
37 | 34 | [['is_default'], 'integer'], |
38 | 35 | [['timestamp'], 'safe'], | ... | ... |