[ 'class' => AccessControl::className(), 'rules' => [ [ 'actions' => ['result', 'index', 'write'], 'allow' => true, 'roles' => ['@'], ], ], ], 'verbs' => [ 'class' => VerbFilter::className(), 'actions' => [ 'logout' => ['post'], ], ], ]; } /** * @inheritdoc */ public function actions() { return [ 'error' => [ 'class' => 'yii\web\ErrorAction', ], ]; } public function actionIndex() { $model = new UploadFileCrossingForm(); return $this->render('index', ['model' => $model]); } public function actionResult() { $model = new UploadFileCrossingForm(); $data = []; if ($model->load(Yii::$app->request->post())) { $model->file = UploadedFile::getInstance($model, 'file'); if ($model->validate()) { $file_name = $model->file->name; $model->file_path = Yii::getAlias('@temp_upload') . '/' . $file_name; $model->file->saveAs($model->file_path); //запускаем парсинг $data = $model->readFile(); // сохраняем в кеш отпарсенные даные $this->parserCacheHandler( 1, $data, $model ); } else if (Yii::$app->getCache()->get('parser_data')) { $data = json_decode(Yii::$app->getCache()->get('parser_data'), true); } $provider = new ArrayDataProvider([ 'allModels' => $data, 'pagination' => [ 'pageSize' => 10, ], ]); // создадим модель на столько реквизитов сколько колонок в отпарсенном файле $last_index = end(array_flip($data[0])); $header_counts = $last_index + 1; $header_model = DynamicFormHelper::CreateDynamicModel($header_counts); // соберем массив данных из которых будет пользователь выбирать значения в конструкторе (выпадающий список) $basicColumns = $this->getBasicColumns(); return $this->render('results', ['model' => $data, 'header_model' => $header_model, // список колонок для выбора 'basic_column' => $basicColumns, 'dataProvider' => $provider]); } } public function actionWrite() { //получим колонки которые выбрал пользователь $arr_attributes = Yii::$app->request->post()['DynamicModel']; //соберем модель по полученным данным $model = DynamicFormHelper::CreateDynamicModel($arr_attributes); //добавим правила валидации (колонки должны быть те что в модели) foreach ($arr_attributes as $key => $value) { $model->addRule($key, 'in', [ 'range' => array_keys( $this->getBasicColumns() ) ]); } // провалидируем выбранные колонки if ( $model->validate() ) { // валидация успешна у нас есть соответсвие колонок, преобразуем в массив данное соответсвие для дальнейшей работы $arr = $model->toArray(); // получим данные из кеша $this->parserCacheHandler( 0, $data, $configuration ); // соотнесем отпарсенные данные с соответствием полученным от пользователя // для этого преобразуем массив отпарсенных данных - назначим ключи согласно соответствию $data = CustomArrayHelper::createAssocArray($data, $arr, 'attr_'); // запустим конвертер над над данными $data = $this->convertDataByConfiguration( $data, $configuration ); // валидируем отпарсенные данные моделью в которую будем записывать $crosses_model = new DetailsCrosses(); $model_validator = new ModelArrayValidator( $crosses_model ); $data = $model_validator->validate( $data ); $msg = $model_validator->getMassage(); $type_msg = $model_validator->hasError() ? 'warning' : 'success'; $model_validator->close(); $data = $this->reverseCrosses( $data ); if ( $crosses_model->ManualInsertWithIgnore( $data ) ) { // очистим кеш $this->parserCacheHandler( 2 ); if ( file_exists($configuration['file_path']) ) unlink( $configuration['file_path'] ); Yii::$app->session->setFlash( $type_msg, $msg ); return $this->render('index', ['model' => $configuration]); } } else { // не прошла валидация формы загрузки файлов $errors_str = ''; foreach ($model->getErrors() as $error) { $errors_str .= implode(array_values($error)); } throw new \ErrorException($errors_str); } } protected function getBasicColumns() { $basicColumns_array = Yii::$app->multiparser->getConfiguration('csv', 'crosses'); if (isset($basicColumns_array['basic_column'])) { return $basicColumns_array['basic_column']; } else { throw new \ErrorException('Ошибка конфигурационного файла кроссов. Не указаны базовые колнки для пользовательской формы выбора.'); } } protected function convertDataByConfiguration( $data, $configuration ){ // доп. опции для парсера - удаление префикса в артикулах $options['mode'] = 'crosses'; $fields = []; if ($configuration['delete_prefix1']) { $fields[] = 'ARTICLE'; } if ($configuration['delete_prefix2']) { $fields[] = 'CROSS_ARTICLE'; } if ($fields) { $options ['converter_conf']['configuration'] = ["article" => $fields, "string" => ['ARTICLE', 'CROSS_ARTICLE'],]; } else { $options ['converter_conf']['configuration'] = ["string" => ['ARTICLE', 'CROSS_ARTICLE'],]; } // получим базовую конфигурацию и объеденим её с той что образовалась после выбора пользователем настроек $basic_options = Yii::$app->multiparser->getConfiguration( 'csv', 'crosses' ); $options = array_merge_recursive( $options, $basic_options ); foreach ( $data as &$row ) { $row = Yii::$app->converter->convertByConfiguration( $row, $options['converter_conf'] ); } return $data; } protected function reverseCrosses ( $data ) { // для доп массива обратных строк $i = count( $data ) - 1; $reverse_data = []; foreach ( $data as &$row ) { // нужно добавить обратную строку по кроссам $reverse_data[ $i ]['ARTICLE'] = $row['CROSS_ARTICLE']; $reverse_data[ $i ]['CROSS_ARTICLE'] = $row['ARTICLE']; $reverse_data[ $i ]['BRAND'] = $row['CROSS_BRAND']; $reverse_data[ $i ]['CROSS_BRAND'] = $row['BRAND']; $i++; } $data = array_merge( $data, $reverse_data ); return $data; } }