diff --git a/backend/components/parsers/CustomCsvParser.php b/backend/components/parsers/CustomCsvParser.php index 5c45f7a..190fd91 100644 --- a/backend/components/parsers/CustomCsvParser.php +++ b/backend/components/parsers/CustomCsvParser.php @@ -14,20 +14,19 @@ class CustomCsvParser extends \yii\multiparser\CsvParser { //public $last_line = 10; //public $hasHeaderRow = true; // public $keys = ['first','second', 'third', 'forth', 'fifth']; - - - protected function readRow() + public function setupConverter() { - $row = parent::readRow(); - if (is_array($row)) { - - $row = Encoder::encodeArray( Encoder::$in_charset, Encoder::$out_charset, $row ); + if ($this->hasHeaderRow) { + // если у файла есть заголовок, то в результате имеем ассоциативный массив + $this->converter_conf['hasKey'] = 1; } - return $row; + $this->converter = \Yii::createObject($this->converter_conf); + \common\components\CustomVarDamp::dumpAndDie($this); } + } \ No newline at end of file diff --git a/backend/components/parsers/CustomParserConfigurator.php b/backend/components/parsers/CustomParserConfigurator.php deleted file mode 100644 index 18b08e8..0000000 --- a/backend/components/parsers/CustomParserConfigurator.php +++ /dev/null @@ -1,28 +0,0 @@ - - ['web' => - ['class' => 'backend\components\parsers\CustomCsvParser', - 'auto_detect_first_line' => true,]]]; - - - - public static $basic_column = [ - "BRAND" => 'Бренд', - "ARTICLE"=> 'Артикул', - "PRICE" => 'Цена', - "DESCR" => 'Наименование', - "BOX" => 'Колво', - "ADD_BOX"=> 'В пути', - "GROUP" => 'Группа RG' - ]; - - -} \ No newline at end of file diff --git a/backend/components/parsers/DynamicFormHelper.php b/backend/components/parsers/DynamicFormHelper.php deleted file mode 100644 index 675a0fb..0000000 --- a/backend/components/parsers/DynamicFormHelper.php +++ /dev/null @@ -1,73 +0,0 @@ - $i) { - $arr_keys[] = "attr_{$i}"; - $i++; - } - array_flip($arr_keys); - - } - - $model = new DynamicModel($arr_keys); - - return $model; - } - - // @todo - rewrite on two functions, add comments - public static function CreateDynamicGridViewWithDropDownListHeader( $dataProvider, $form, $header_model, $arr_header_values ) - { - $columns_config = [['class' => SerialColumn::className()]]; - $i = 0; - foreach( $header_model as $key => $value ) { - - $columns_config[] = ['header' => $form->field($header_model, $key, ['inputOptions' => ['label' => '']])->dropDownList($arr_header_values), 'attribute' => $i]; - $i++; - } - - //\common\components\CustomVarDamp::dumpAndDie($columns_config); - - $dynamic_grid_view = GridView::widget( ['dataProvider' => $dataProvider, - 'columns' => $columns_config ] ); - - return $dynamic_grid_view; - - } - - - -} \ No newline at end of file diff --git a/backend/components/parsers/Encoder.php b/backend/components/parsers/Encoder.php deleted file mode 100644 index ca2b467..0000000 --- a/backend/components/parsers/Encoder.php +++ /dev/null @@ -1,51 +0,0 @@ - + ['web' => + ['class' => 'backend\components\parsers\CustomCsvParser', + 'auto_detect_first_line' => true, + 'converter_conf' => ['class' => 'yii\multiparser\CsvConverter', + 'configuration' => [ + "string" => 'DESCR' + ] + ,]], + + 'basic_column' => [ + "BRAND" => 'Бренд', + "ARTICLE"=> 'Артикул', + "PRICE" => 'Цена', + "DESCR" => 'Наименование', + "BOX" => 'Колво', + "ADD_BOX"=> 'В пути', + "GROUP" => 'Группа RG' + ], + ]]; + + +//[ +// "float" => 'PRICE', +// "integer" => ['BOX' , 'ADD_BOX' ], +// "prefix" => 'ARTICLE' +//] \ No newline at end of file diff --git a/backend/config/main.php b/backend/config/main.php index fcac464..386e300 100644 --- a/backend/config/main.php +++ b/backend/config/main.php @@ -5,6 +5,7 @@ $params = array_merge( require(__DIR__ . '/params.php'), require(__DIR__ . '/params-local.php') ); +$mp_configuration = require( __DIR__ . '/../components/parsers/config.php'); return [ 'id' => 'app-backend', @@ -41,6 +42,7 @@ return [ 'multiparser'=>[ 'class' => 'yii\multiparser\YiiMultiparser', + 'configuration' => $mp_configuration, ], ], diff --git a/backend/controllers/ParserController.php b/backend/controllers/ParserController.php index 310c228..4b86f2a 100644 --- a/backend/controllers/ParserController.php +++ b/backend/controllers/ParserController.php @@ -8,7 +8,7 @@ use yii\filters\VerbFilter; use backend\models\UploadFileParsingForm; use yii\web\UploadedFile; use yii\data\ArrayDataProvider; -use backend\components\parsers\DynamicFormHelper; +use yii\multiparser\DynamicFormHelper; use backend\components\parsers\CustomParserConfigurator; use common\components\CustomVarDamp; @@ -96,13 +96,14 @@ class ParserController extends BaseController ], ]); + // CustomVarDamp::dumpAndDie($data); $header_model = DynamicFormHelper::CreateDynamicModel( count( $data[0] ) ); - //CustomVarDamp::dumpAndDie($header_model); + // CustomVarDamp::dumpAndDie(Yii::$app->multiparser->getConfiguration('csv','basic_column')); return $this->render('results', ['model' => $data, 'header_model' => $header_model, - 'basic_column' => CustomParserConfigurator::$basic_column, + 'basic_column' => Yii::$app->multiparser->getConfiguration('csv','basic_column'), 'dataProvider' => $provider]); } @@ -113,7 +114,7 @@ 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( CustomParserConfigurator::$basic_column )]); + $model->addRule($key, 'in', ['range' => array_keys( Yii::$app->multiparser->getConfiguration('csv','basic_column') )]); } //CustomVarDamp::dumpAndDie($model); diff --git a/backend/views/parser/results.php b/backend/views/parser/results.php index 2f3c7d0..e0c6460 100644 --- a/backend/views/parser/results.php +++ b/backend/views/parser/results.php @@ -1,7 +1,7 @@ params['breadcrumbs'][] = $this->title; $form = ActiveForm::begin(['action' => 'write']); ?> - +
'btn btn-primary']) ?> diff --git a/vendor/yiisoft/multiparser/CSVConverter.php b/vendor/yiisoft/multiparser/CSVConverter.php new file mode 100644 index 0000000..dbbe6a2 --- /dev/null +++ b/vendor/yiisoft/multiparser/CSVConverter.php @@ -0,0 +1,131 @@ + $value ) { + + if ( $hasKey ){ + // у нас ассоциативный массив, и мы можем конвертировать каждое значение в отдельности + if ( is_array( $value ) ) { + foreach ($value as $sub_value) { + if (isset($arr[$sub_value])) { + // конвертируем только те ячейки которые сопоставлены в прочитанном массиве с колонками в конфигурационном файле + $result[$arr[$sub_value]] = self::$key( $arr[$sub_value] ); + } + + } + } else { + + if (isset($arr[$value])) { + // конвертируем только те ячейки которые сопоставлены в прочитанном массиве с колонками в конфигурационном файле + $result[$arr[$value]] = self::$key( $arr[$value] ); + } + + } + + } else { + // нет заголовка - мы можем конвертировать только с року в целом + $result = self::$key( $arr ); + } + + } + + return $result; + } + + +} \ No newline at end of file diff --git a/vendor/yiisoft/multiparser/CsvParser.php b/vendor/yiisoft/multiparser/CsvParser.php index cde4650..284a789 100644 --- a/vendor/yiisoft/multiparser/CsvParser.php +++ b/vendor/yiisoft/multiparser/CsvParser.php @@ -45,10 +45,14 @@ class CsvParser implements ParserInterface * используется при автоопределении первой строки*/ public $min_column_quantity = 5; + /** @var array - конфигурация конвертера значений */ + public $converter_conf = []; + /** @var array - конвертер созданный по конфигурации */ + public $converter = NULL; /** - метод устанвливает нужные настройки объекта SplFileObject, для работы с csv + * метод устанвливает нужные настройки объекта SplFileObject, для работы с csv */ public function setup() { @@ -58,9 +62,27 @@ class CsvParser implements ParserInterface if ($this->auto_detect_first_line) { $this->shiftToFirstValuableLine(); } + $this->setupConverter(); + } /** + * устанавливает конвертер значений согласно конфигурационным настройкам + */ + public function setupConverter() + { + if (!count($this->converter_conf)) { + $this->converter = new CSVConverter(); + if ($this->hasHeaderRow) { + // если у файла есть заголовок, то в результате имеем ассоциативный массив + $this->converter_conf['hasKey'] = 1; + } + $this->converter->configuration = $this->converter_conf; + } + } + + + /** * определяет первую значимую строку, * считывается файл пока в нем не встретится строка с непустыми колонками * в количестве указанном в атрибуте min_column_quantity @@ -112,14 +134,12 @@ class CsvParser implements ParserInterface if (count($this->keys) !== count($row)) { // - throw new \ErrorException( "Invalid columns detected on line # {$current_line}", 0, 1, $this->file->getBasename(), $current_line); + throw new \ErrorException("Invalid columns detected on line # {$current_line}", 0, 1, $this->file->getBasename(), $current_line); } $return[] = array_combine($this->keys, $row); } - } - else - { + } else { $return[] = $row; } // если у нас установлен лимит, при его достижении прекращаем парсинг @@ -134,7 +154,6 @@ class CsvParser implements ParserInterface } - protected function closeHandler() { $this->file = NULL; @@ -147,10 +166,15 @@ class CsvParser implements ParserInterface { $row = $this->file->fgetcsv(); - if (is_array($row) && $this->first_column) { + if (is_array($row)) { + // попытаемся конвертировать прочитанные занчения согдасно конфигурации котнвертера значений + $row = $this->convert($row); + + if ($this->first_column) { - $row = array_slice($row, $this->first_column); + $row = array_slice($row, $this->first_column); + } } if (is_null($row)) $row = false; @@ -159,5 +183,27 @@ class CsvParser implements ParserInterface } + /** + * @param $arr + * @return mixed + * преобразовует значения прочитанного массива в нужные типы, согласно конфигурации конвертера + */ + protected function convert($arr) + { + $result = $arr; + $converter = $this->converter; + + //\common\components\CustomVarDamp::dumpAndDie($this); + + if (!is_null($converter)) { + + $result = $converter::convertByConfiguration($arr); + + } + + return $result; + + } + } \ No newline at end of file diff --git a/vendor/yiisoft/multiparser/DynamicFormHelper.php b/vendor/yiisoft/multiparser/DynamicFormHelper.php new file mode 100644 index 0000000..249aaeb --- /dev/null +++ b/vendor/yiisoft/multiparser/DynamicFormHelper.php @@ -0,0 +1,71 @@ + $i) { + $arr_keys[] = "attr_{$i}"; + $i++; + } + array_flip($arr_keys); + + } + + $model = new DynamicModel($arr_keys); + + return $model; + } + + // @todo add comments + public static function CreateGridWithDropDownListHeader( $dataProvider, $form, $header_model, $arr_header_values ) + { + $columns_config = [['class' => SerialColumn::className()]]; + $i = 0; + foreach( $header_model as $key => $value ) { + + $columns_config[] = ['header' => $form->field($header_model, $key, ['inputOptions' => ['label' => '']])->dropDownList($arr_header_values), 'attribute' => $i]; + $i++; + } + + $dynamic_grid_view = GridView::widget( ['dataProvider' => $dataProvider, + 'columns' => $columns_config ] ); + + return $dynamic_grid_view; + + } + + + +} \ No newline at end of file diff --git a/vendor/yiisoft/multiparser/Encoder.php b/vendor/yiisoft/multiparser/Encoder.php new file mode 100644 index 0000000..7661b6a --- /dev/null +++ b/vendor/yiisoft/multiparser/Encoder.php @@ -0,0 +1,59 @@ + - ['web' => - ['class' => 'backend\components\parsers\CustomCsvParser', - 'auto_detect_first_line' => true,]]]; + protected static $configuration; - - public static function getConfiguration($extension, $mode) + public static function getConfiguration($extension, $parameter) { + self::setConfiguration(); + if (!isset( self::$configuration[$extension] )){ throw new \ErrorException( "Parser do not maintain file with extension {$extension}"); } - if (!isset( self::$configuration[$extension][$mode] )){ - throw new \ErrorException( "Parser configurator do not have settings for {$mode} mode"); + if (!isset( self::$configuration[$extension][$parameter] )){ + throw new \ErrorException( "Parser configurator do not have settings for {$parameter} parameter"); } - return self::$configuration[$extension][$mode]; + return self::$configuration[$extension][$parameter]; } + protected static function setConfiguration() + { + + self::$configuration = require(__DIR__ . '/config.php'); + + } + + + } \ No newline at end of file diff --git a/vendor/yiisoft/multiparser/XmlParser.php b/vendor/yiisoft/multiparser/XmlParser.php new file mode 100644 index 0000000..77cd03c --- /dev/null +++ b/vendor/yiisoft/multiparser/XmlParser.php @@ -0,0 +1,82 @@ +/', $val)) { + throw new InvalidArgumentException('XML Doctype parsing disabled'); + } + + // Disable external entity loading + if($disableExternals) $oldVal = libxml_disable_entity_loader($disableExternals); + try { + $xml = new SimpleXMLElement($val); + $result = self::recursiveXMLToArray($xml); + } catch(Exception $ex) { + if($disableExternals) libxml_disable_entity_loader($oldVal); + throw $ex; + } + if($disableExternals) libxml_disable_entity_loader($oldVal); + return $result; + } + + /** + * Convert a XML string to a PHP array recursively. Do not + * call this function directly, Please use {@link Convert::xml2array()} + * + * @param SimpleXMLElement + * + * @return mixed + */ + protected static function recursiveXMLToArray($xml) { + if(is_object($xml) && get_class($xml) == 'SimpleXMLElement') { + $attributes = $xml->attributes(); + foreach($attributes as $k => $v) { + if($v) $a[$k] = (string) $v; + } + $x = $xml; + $xml = get_object_vars($xml); + } + if(is_array($xml)) { + if(count($xml) == 0) return (string) $x; // for CDATA + foreach($xml as $key => $value) { + $r[$key] = self::recursiveXMLToArray($value); + } + if(isset($a)) $r['@'] = $a; // Attributes + return $r; + } + + return (string) $xml; + } +} \ No newline at end of file diff --git a/vendor/yiisoft/multiparser/YiiMultiparser.php b/vendor/yiisoft/multiparser/YiiMultiparser.php index 0308387..0abf73e 100644 --- a/vendor/yiisoft/multiparser/YiiMultiparser.php +++ b/vendor/yiisoft/multiparser/YiiMultiparser.php @@ -11,8 +11,26 @@ namespace yii\multiparser; use yii\base\Component; + + class YiiMultiparser extends Component{ +public $configuration; + + public function getConfiguration($extension, $conf_parameter){ + + if (!isset( $this->configuration[$extension] )){ + throw new \ErrorException( "Parser do not maintain file with extension {$extension}"); + } + if (!isset( $this->configuration[$extension][$conf_parameter] )){ + throw new \ErrorException( "Parser configurator do not have settings for {$conf_parameter} parameter"); + } + + return $this->configuration[$extension][$conf_parameter]; + + } + + public function parse( $filePath, $options = [] ){ $parser = new YiiParserHandler( $filePath, $options ); diff --git a/vendor/yiisoft/multiparser/YiiParserHandler.php b/vendor/yiisoft/multiparser/YiiParserHandler.php index fddd3d4..eb3cb4f 100644 --- a/vendor/yiisoft/multiparser/YiiParserHandler.php +++ b/vendor/yiisoft/multiparser/YiiParserHandler.php @@ -12,4 +12,72 @@ namespace yii\multiparser; class YiiParserHandler extends ParserHandler{ + /** + * @param $filePath + * @param array $options + * проверяет читабенльность переданного файла, а также наличие настроек парсера в конфигурационном файле для данного типа файла + */ + public function __construct($filePath, $options = []) + { + $this->filePath = $filePath; + if (isset($options['mode'])) { + + $this->mode = $options['mode']; + unset($options['mode']); + + } else { + + $this->mode = self::DEFAULT_MODE; + + } + + $this->options = $options; + + try { + $this->fileObject = new \SplFileObject($this->filePath, 'r'); + } catch (\ErrorException $e) { + // Yii::warning("Ошибка открытия файла {$this->filePath}"); + echo "Ошибка открытия файла {$this->filePath}"; + return []; + } + + $options['file'] = $this->fileObject; + $this->extension = $this->fileObject->getExtension(); + + try { + $this->configuration = \Yii::$app->multiparser->getConfiguration($this->extension, $this->mode); + $this->configuration = array_merge($this->configuration, $options); + + } catch (\ErrorException $e) { + echo $e->getMessage(); + return []; + } + + } + + public function run() + { + + $result = []; + + // \common\components\CustomVarDamp::dumpAndDie($this); + if (count($this->configuration)) { + $parser = \Yii::createObject($this->configuration); + + try { + + $parser->setup(); + $result = $parser->read(); + + } catch (\ErrorException $e) { + + echo $e->getMessage(); + + } + + } + + return $result; + } + } \ No newline at end of file diff --git a/vendor/yiisoft/multiparser/config.php b/vendor/yiisoft/multiparser/config.php new file mode 100644 index 0000000..950efaa --- /dev/null +++ b/vendor/yiisoft/multiparser/config.php @@ -0,0 +1,20 @@ + + ['web' => + ['class' => 'yii\multiparser\CsvParser', + 'auto_detect_first_line' => true, + 'converter_conf' => [ + "float" => 'PRICE', + "integer" => 'QUANTITY', + "string" => 'DESCR' + ]], + 'basic_column' => [ + "ARTICLE" => 'Артикул', + "PRICE" => 'Цена', + "DESCR" => 'Наименование', + "QUANTITY" => 'Колво' + + ], + ]]; -- libgit2 0.21.4