ParserController.php 9.19 KB
<?php
namespace backend\controllers;

use Yii;
use yii\filters\AccessControl;
use backend\components\base\BaseController;
use yii\filters\VerbFilter;
use backend\models\UploadFileParsingForm;
use yii\web\UploadedFile;
use yii\data\ArrayDataProvider;
use yii\multiparser\DynamicFormHelper;
use backend\components\parsers\CustomParserConfigurator;
use backend\models\Details;
use backend\models\ImporterFiles;
use backend\models\Importer;
use yii\base\ErrorException;

use common\components\CustomVarDamp;

/**
 * Parser controller
 */
class ParserController extends BaseController
{
    public $layout = "/column";

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'actions' => ['index', 'results', '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 UploadFileParsingForm();

        return $this->render('index', ['model' => $model]);
    }

    public function actionResults()
    {
        $model = new UploadFileParsingForm();
        $data = [];
        if ($model->load(Yii::$app->request->post())) {
            $model->file = UploadedFile::getInstance($model, 'file');
            // первый проход - валидируем, сохраняем файл, ложим в кеш отпарсенные данные и параметры модели (потом при записи в базу данных они пригодятся)
            if ($model->validate()) {
                $filePath = Yii::getAlias('@webroot') . '/uploads/' . $model->file->baseName . '.' . $model->file->extension;

                $model->file->saveAs($filePath);
                //запускаем парсинг
                $data = $model->readFile($filePath);
                // сохраняем в кеш отпарсенные даные
                Yii::$app->getCache()->set('parser_data', json_encode($data));
                // сохраняем в кеш модель - в ней настройки для дальнейшей обработки данных
                Yii::$app->getCache()->set('parser_configuration', serialize($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,
            ],
        ]);

        //формируем заголовок для пользователя, где он сможет выбрать соответсвие полей (выпадающий список)
        $header_model = DynamicFormHelper::CreateDynamicModel(count($data[0]));

        return $this->render('results',
            ['model' => $data,
                'header_model' => $header_model,
                // список колонок для выбора
                'basic_column' => Yii::$app->multiparser->getConfiguration('csv', 'basic_column'),
                '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(Yii::$app->multiparser->getConfiguration('csv', 'basic_column'))]);
        }

        // провалидируем выбранные колонки
        if ($model->validate()) {

            // валидация успешна у нас есть соответсвие колонок, преобразуем в массив данное соответсвие для дальнейшей работы
            $arr = $model->toArray();

            // получим данные из кеша
            if (Yii::$app->getCache()->get('parser_data') && Yii::$app->getCache()->get('parser_configuration')) {
                $data = json_decode(Yii::$app->getCache()->get('parser_data'), true);
                $configuration = unserialize(Yii::$app->getCache()->get('parser_configuration'));
            } else {
                CustomVarDamp::dumpAndDie('Ошибка кеша');
            }

            // соотнесем отпарсенные данные с соответсивем полученным от пользователя
            // для этого преобразуем массив отпарсенных данных - назначим ключи согласно соответствию
            $data = \Yii::$app->multiparser->convertToAssocArray($data, $arr, 'attr_');


            // 1. запишем дату старта в таблицу файлов поставщика (ImportersFiles)
            $files_model = new ImporterFiles();
            // id поставщика получим из конфигурации
            $files_model->load(['ImporterFiles' => $configuration->toArray()]);
            if ($files_model->validate()) {
                try {
                    $files_model->save();
                    $update_date = $files_model->find()
                        ->where(['importer_id' => $files_model->importer_id])
                        ->orderBy(['id' => SORT_DESC])
                        ->one()
                        ->upload_time;
                    $update_date = date('Y-m-d H:i:s',strtotime($update_date));
                   // CustomVarDamp::dumpAndDie(strtotime($update_date));
                } catch (ErrorException  $e) {
                    CustomVarDamp::dump($e->getMessage());
                }


                // 2. запишем полученные данные в таблицу товаров (Details)
                $details_model = new Details('web');
                // проверим все ли обязательные колонки были указаны пользователем
                $details_model->load(['Details' => $data[0]]);
                if ($details_model->validate()) {
                    // дополним данные значением импортера и даты обновления цены
                    $data = \Yii::$app->multiparser->addColumns( $data, ['IMPORT_ID' => $configuration['importer_id'],'timestamp' => $update_date] );

                    try {
                        //@todo add transaction
                        // попытаемся вставить данные в БД с апдейтом по ключам
                        $details_model->save($data);

                        // 3. зафиксируем дату конца загрузки в файлах поставщика
                        $files_model->time_end = date('Y-m-d H:i:s');
                       // CustomVarDamp::dumpAndDie($files_model);
                        $files_model->save();

                        // 4. зафиксируем дату загрузки в таблице поставщиков
                        $imp_model = Importer::findOne( $configuration['importer_id'] );
                        $imp_model->price_date_update = ''.strtotime($update_date);

                        if (!$imp_model->save()) {
                            CustomVarDamp::dumpAndDie( $imp_model->getErrors() );
                        }

                        // все прошло успешно - очищаем кеш
                        Yii::$app->getCache()->delete('parser_data');
                        Yii::$app->getCache()->delete('parser_configuration');
                        // @todo - Delete the file

                        CustomVarDamp::dumpAndDie('!!!');
                    } catch (ErrorException  $e) {
                        CustomVarDamp::dump($e->getMessage());
                    }
                }
                if ($details_model->hasErrors()) {
                    $errors_arr = $details_model->getErrors();
                    foreach ($errors_arr as $error) {
                        CustomVarDamp::dump(array_values($error));
                    }

                }


            }


        }

    }

}