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,20 +8,16 @@ | ||
8 | 8 | ||
9 | namespace backend\controllers; | 9 | namespace backend\controllers; |
10 | 10 | ||
11 | -use backend\components\base\BaseActiveRecord; | ||
12 | use backend\components\base\BaseController; | 11 | use backend\components\base\BaseController; |
13 | use common\components\CustomArrayHelper; | 12 | use common\components\CustomArrayHelper; |
14 | -use common\components\CustomVarDamp; | ||
15 | -use yii\base\ErrorException; | ||
16 | -use yii\base\Model; | ||
17 | use yii\data\ArrayDataProvider; | 13 | use yii\data\ArrayDataProvider; |
18 | -use yii\db\ActiveRecord; | ||
19 | use yii\filters\VerbFilter; | 14 | use yii\filters\VerbFilter; |
20 | use yii\filters\AccessControl; | 15 | use yii\filters\AccessControl; |
21 | use backend\models\UploadFileCrossingForm; | 16 | use backend\models\UploadFileCrossingForm; |
22 | use backend\models\DetailsCrosses; | 17 | use backend\models\DetailsCrosses; |
23 | use yii\multiparser\DynamicFormHelper; | 18 | use yii\multiparser\DynamicFormHelper; |
24 | use yii\web\UploadedFile; | 19 | use yii\web\UploadedFile; |
20 | +use common\components\ModelArrayValidator; | ||
25 | use \Yii; | 21 | use \Yii; |
26 | 22 | ||
27 | class CrossingUploadController extends BaseController | 23 | class CrossingUploadController extends BaseController |
@@ -141,11 +137,19 @@ class CrossingUploadController extends BaseController | @@ -141,11 +137,19 @@ class CrossingUploadController extends BaseController | ||
141 | // запустим конвертер над над данными | 137 | // запустим конвертер над над данными |
142 | $data = $this->convertDataByConfiguration( $data, $configuration ); | 138 | $data = $this->convertDataByConfiguration( $data, $configuration ); |
143 | 139 | ||
140 | + // валидируем отпарсенные данные моделью в которую будем записывать | ||
144 | $crosses_model = new DetailsCrosses(); | 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 | if ( $crosses_model->ManualInsertWithIgnore( $data ) ) { | 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 | $this->cacheHandler( 2 ); | 155 | $this->cacheHandler( 2 ); |
@@ -200,20 +204,10 @@ class CrossingUploadController extends BaseController | @@ -200,20 +204,10 @@ class CrossingUploadController extends BaseController | ||
200 | $basic_options = Yii::$app->multiparser->getConfiguration( 'csv', 'crosses' ); | 204 | $basic_options = Yii::$app->multiparser->getConfiguration( 'csv', 'crosses' ); |
201 | $options = array_merge_recursive( $options, $basic_options ); | 205 | $options = array_merge_recursive( $options, $basic_options ); |
202 | 206 | ||
203 | - // для доп массива обратных строк | ||
204 | - $i = count( $data ) - 1; | ||
205 | - $reverse_data = []; | ||
206 | foreach ( $data as &$row ) { | 207 | foreach ( $data as &$row ) { |
207 | $row = Yii::$app->converter->convertByConfiguration( $row, $options['converter_conf'] ); | 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 | return $data; | 211 | return $data; |
218 | 212 | ||
219 | } | 213 | } |
@@ -251,21 +245,22 @@ class CrossingUploadController extends BaseController | @@ -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 | \ No newline at end of file | 267 | \ No newline at end of file |
backend/controllers/RgGrupController.php
@@ -125,7 +125,7 @@ class RgGrupController extends BaseController | @@ -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 | $arr = $model->toArray(); | 131 | $arr = $model->toArray(); |
@@ -147,7 +147,7 @@ class RgGrupController extends BaseController | @@ -147,7 +147,7 @@ class RgGrupController extends BaseController | ||
147 | $data = CustomArrayHelper::createAssocArray($data, $arr, 'attr_'); | 147 | $data = CustomArrayHelper::createAssocArray($data, $arr, 'attr_'); |
148 | 148 | ||
149 | // в первой строке у нас заголовки - уберем | 149 | // в первой строке у нас заголовки - уберем |
150 | - unset($data[0]); | 150 | + unset( $data[0] ); |
151 | // подготовим данные для записи в таблицу w_margins_groups | 151 | // подготовим данные для записи в таблицу w_margins_groups |
152 | $arr_values = []; | 152 | $arr_values = []; |
153 | $group = ''; | 153 | $group = ''; |
backend/views/crossing-upload/index.php
@@ -8,9 +8,6 @@ use yii\helpers\ArrayHelper; | @@ -8,9 +8,6 @@ use yii\helpers\ArrayHelper; | ||
8 | <div class="col-lg-5"> | 8 | <div class="col-lg-5"> |
9 | <?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data',],'action'=>['crossing-upload/result']]); | 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 | <h3>Кросс файлы</h3> | 12 | <h3>Кросс файлы</h3> |
16 | 13 | ||
@@ -22,7 +19,16 @@ use yii\helpers\ArrayHelper; | @@ -22,7 +19,16 @@ use yii\helpers\ArrayHelper; | ||
22 | <?= Html::submitButton(Yii::t( 'app', 'Прочитать' ), ['class' => 'btn btn-primary']) ?> | 19 | <?= Html::submitButton(Yii::t( 'app', 'Прочитать' ), ['class' => 'btn btn-primary']) ?> |
23 | </div> | 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 | </div> | 32 | </div> |
27 | </div> | 33 | </div> |
28 | 34 |
backend/views/currency/index.php
@@ -27,7 +27,7 @@ $this->params['breadcrumbs'][] = $this->title; | @@ -27,7 +27,7 @@ $this->params['breadcrumbs'][] = $this->title; | ||
27 | 'rate', | 27 | 'rate', |
28 | 'timestamp', | 28 | 'timestamp', |
29 | ['class' => 'yii\grid\ActionColumn', | 29 | ['class' => 'yii\grid\ActionColumn', |
30 | - 'template' => '{update}'], | 30 | + 'template' => '{update}{delete}'], |
31 | ], | 31 | ], |
32 | ]); ?> | 32 | ]); ?> |
33 | 33 |
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 | \ No newline at end of file | 128 | \ No newline at end of file |
common/components/parsers/CustomConverter.php
@@ -25,15 +25,17 @@ class CustomConverter extends Converter | @@ -25,15 +25,17 @@ class CustomConverter extends Converter | ||
25 | 25 | ||
26 | $details_model = new Details(); | 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 | return $row; | 39 | return $row; |
38 | } | 40 | } |
39 | 41 | ||
@@ -53,7 +55,7 @@ class CustomConverter extends Converter | @@ -53,7 +55,7 @@ class CustomConverter extends Converter | ||
53 | return $row; | 55 | return $row; |
54 | } | 56 | } |
55 | 57 | ||
56 | - public function ConvertToMultiply(array $row) | 58 | + public function ConvertToMultiply( array $row ) |
57 | { | 59 | { |
58 | $PRICE = $row['PRICE']; | 60 | $PRICE = $row['PRICE']; |
59 | $sign = self::$sign; | 61 | $sign = self::$sign; |
common/components/parsers/config.php
@@ -45,7 +45,7 @@ | @@ -45,7 +45,7 @@ | ||
45 | 'hasKey' => 1, | 45 | 'hasKey' => 1, |
46 | 'configuration' => [ | 46 | 'configuration' => [ |
47 | "brand" => ['BRAND', 'CROSS_BRAND'], | 47 | "brand" => ['BRAND', 'CROSS_BRAND'], |
48 | - "crosses" => [], | 48 | + // "crosses" => [], |
49 | ] | 49 | ] |
50 | ], | 50 | ], |
51 | 'basic_column' => [ | 51 | 'basic_column' => [ |
common/models/Currency.php
@@ -30,9 +30,6 @@ class Currency extends \yii\db\ActiveRecord | @@ -30,9 +30,6 @@ class Currency extends \yii\db\ActiveRecord | ||
30 | { | 30 | { |
31 | return [ | 31 | return [ |
32 | [['name', 'rate'], 'required'], | 32 | [['name', 'rate'], 'required'], |
33 | -// [['rate'], 'filter','filter' => function($value){ | ||
34 | -// return (float) str_replace( ',', '.', $value );} | ||
35 | -// ], | ||
36 | ['rate', \common\components\CommaNumberValidator::className()], | 33 | ['rate', \common\components\CommaNumberValidator::className()], |
37 | [['is_default'], 'integer'], | 34 | [['is_default'], 'integer'], |
38 | [['timestamp'], 'safe'], | 35 | [['timestamp'], 'safe'], |