Commit 90ff40df3f4c57aea54440ee58572c4fdbbf16e8
1 parent
df1a5df8
fixed issue with xml parser - redid in universul manner
Showing
7 changed files
with
104 additions
and
49 deletions
Show diff stats
backend/controllers/ParserController.php
@@ -52,6 +52,8 @@ class ParserController extends BaseController | @@ -52,6 +52,8 @@ class ParserController extends BaseController | ||
52 | 52 | ||
53 | public function actionIndex($mode = 0) | 53 | public function actionIndex($mode = 0) |
54 | { | 54 | { |
55 | +// $path = 'common\components\parsers\CustomConverter'; | ||
56 | +// CustomVarDamp::dumpAndDie(new $path()); | ||
55 | $model = new UploadFileParsingForm(); | 57 | $model = new UploadFileParsingForm(); |
56 | // установим режим, 0 - ручная загрузка, 1 - автозагрузка | 58 | // установим режим, 0 - ручная загрузка, 1 - автозагрузка |
57 | $model->mode = $mode; | 59 | $model->mode = $mode; |
@@ -81,7 +83,6 @@ class ParserController extends BaseController | @@ -81,7 +83,6 @@ class ParserController extends BaseController | ||
81 | try { | 83 | try { |
82 | $files_model->save(); | 84 | $files_model->save(); |
83 | } catch (ErrorException $e) { | 85 | } catch (ErrorException $e) { |
84 | - // CustomVarDamp::dump($e->getMessage()); | ||
85 | throw $e; | 86 | throw $e; |
86 | } | 87 | } |
87 | // получим id только что записанной записи - его запишем в название файла | 88 | // получим id только что записанной записи - его запишем в название файла |
backend/models/UploadFileParsingForm.php
@@ -71,12 +71,14 @@ class UploadFileParsingForm extends Model | @@ -71,12 +71,14 @@ class UploadFileParsingForm extends Model | ||
71 | public function readFile( $options = [] ){ | 71 | public function readFile( $options = [] ){ |
72 | 72 | ||
73 | $data = Yii::$app->multiparser->parse( $this->file_path, $options ); | 73 | $data = Yii::$app->multiparser->parse( $this->file_path, $options ); |
74 | - if( !is_array( $data ) ){ | 74 | + CustomVarDamp::dumpAndDie($data); |
75 | + if( !is_array( $data ) || count($data) == 0 ){ | ||
75 | throw new ErrorException("Ошибка чтения из файла прайса {$this->file_path}"); | 76 | throw new ErrorException("Ошибка чтения из файла прайса {$this->file_path}"); |
76 | } | 77 | } |
77 | // файл больше не нужен - данные прочитаны и сохранены в кеш | 78 | // файл больше не нужен - данные прочитаны и сохранены в кеш |
78 | -// if( file_exists($this->file_path) ) | ||
79 | -// unlink($this->file_path); | 79 | + if( file_exists($this->file_path) ) |
80 | + //@ todo - перестало работать - нет доступа на удалениев этом сеансе, в следующем - файл удаляется - разобраться | ||
81 | + //unlink( $this->file_path ); | ||
80 | 82 | ||
81 | return $data; | 83 | return $data; |
82 | } | 84 | } |
common/components/parsers/config.php
@@ -14,7 +14,6 @@ | @@ -14,7 +14,6 @@ | ||
14 | 'hasHeaderRow' => true, | 14 | 'hasHeaderRow' => true, |
15 | 'converter_conf' => [ | 15 | 'converter_conf' => [ |
16 | 'class' => ' common\components\parsers\CustomConverter', | 16 | 'class' => ' common\components\parsers\CustomConverter', |
17 | - 'hasKey' => 1, | ||
18 | 'configuration' => ["string" => 'DESCR', | 17 | 'configuration' => ["string" => 'DESCR', |
19 | "float" => 'PRICE', | 18 | "float" => 'PRICE', |
20 | "brand" => 'BRAND', | 19 | "brand" => 'BRAND', |
@@ -54,21 +53,40 @@ | @@ -54,21 +53,40 @@ | ||
54 | ['console' => | 53 | ['console' => |
55 | ['class' => 'yii\multiparser\XmlParser', | 54 | ['class' => 'yii\multiparser\XmlParser', |
56 | 'node' => 'Товар', | 55 | 'node' => 'Товар', |
56 | + 'hasHeaderRow' => true, | ||
57 | + 'keys' => [ | ||
58 | + "BRAND" => 'Производитель', | ||
59 | + "ARTICLE"=> 'Код', | ||
60 | + "PRICE" => 'Розница', | ||
61 | + "DESCR" => 'Наименование', | ||
62 | + "BOX" => 'Колво', | ||
63 | + "ADD_BOX"=> 'Ожидаемое', | ||
64 | + "GROUP" => 'Группа' | ||
65 | + ], | ||
57 | 'converter_conf' => [ | 66 | 'converter_conf' => [ |
58 | - 'class' => ' common\components\parsers\CustomConverter', | ||
59 | - 'hasKey' => 1, | 67 | + 'class' => 'common\components\parsers\CustomConverter', |
60 | 'configuration' => ["details" => [] | 68 | 'configuration' => ["details" => [] |
61 | ],], | 69 | ],], |
62 | ], | 70 | ], |
63 | - 'basic_column' => [ | ||
64 | - "BRAND" => 'Производитель', | ||
65 | - "ARTICLE"=> 'Код', | ||
66 | - "PRICE" => 'Розница', | ||
67 | - "DESCR" => 'Наименование', | ||
68 | - "BOX" => 'Колво', | ||
69 | - "ADD_BOX"=> 'Ожидаемое', | ||
70 | - "GROUP" => 'Группа' | ||
71 | - ], | 71 | + 'web' => |
72 | + ['class' => 'yii\multiparser\XmlParser', | ||
73 | + 'node' => 'Товар', | ||
74 | + 'hasHeaderRow' => true, | ||
75 | + 'keys' => [ | ||
76 | + "BRAND" => 'Производитель', | ||
77 | + "ARTICLE"=> 'Код', | ||
78 | + "PRICE" => 'Розница', | ||
79 | + "DESCR" => 'Наименование', | ||
80 | + "BOX" => 'Колво', | ||
81 | + "ADD_BOX"=> 'Ожидаемое', | ||
82 | + "GROUP" => 'Группа' | ||
83 | + ], | ||
84 | + 'converter_conf' => [ | ||
85 | + 'class' => 'common\components\parsers\CustomConverter', | ||
86 | + 'configuration' => ["details" => [] | ||
87 | + ],], | ||
88 | + ], | ||
72 | ], | 89 | ], |
90 | + | ||
73 | ]; | 91 | ]; |
74 | 92 |
vendor/yiisoft/multiparser/CsvParser.php
@@ -18,7 +18,7 @@ class CsvParser extends Parser | @@ -18,7 +18,7 @@ class CsvParser extends Parser | ||
18 | public $hasHeaderRow = false; | 18 | public $hasHeaderRow = false; |
19 | /** @var array - массив с заголовком, | 19 | /** @var array - массив с заголовком, |
20 | * если не указан и установлено свойство $hasHeaderRow - будет определен автоматически */ | 20 | * если не указан и установлено свойство $hasHeaderRow - будет определен автоматически */ |
21 | - public $keys; | 21 | + // public $keys; - определен в родительском классе |
22 | 22 | ||
23 | /** @var экземляр SplFileObject читаемого файла */ | 23 | /** @var экземляр SplFileObject читаемого файла */ |
24 | public $file; | 24 | public $file; |
@@ -66,11 +66,6 @@ class CsvParser extends Parser | @@ -66,11 +66,6 @@ class CsvParser extends Parser | ||
66 | $this->shiftToFirstValuableLine(); | 66 | $this->shiftToFirstValuableLine(); |
67 | } | 67 | } |
68 | 68 | ||
69 | - if ($this->hasHeaderRow) { | ||
70 | - // если у файла есть заголовок, то в результате имеем ассоциативный массив | ||
71 | - $this->converter_conf['hasKey'] = 1; | ||
72 | - } | ||
73 | - | ||
74 | parent::setup(); | 69 | parent::setup(); |
75 | 70 | ||
76 | } | 71 | } |
vendor/yiisoft/multiparser/ObjectCreator.php
@@ -14,7 +14,7 @@ use common\components\CustomVarDamp; | @@ -14,7 +14,7 @@ use common\components\CustomVarDamp; | ||
14 | class ObjectCreator { | 14 | class ObjectCreator { |
15 | public static function build( array $configuration ){ | 15 | public static function build( array $configuration ){ |
16 | if ( isset( $configuration['class'] ) ) { | 16 | if ( isset( $configuration['class'] ) ) { |
17 | - $class = $configuration['class']; | 17 | + $class = trim( $configuration['class'] ); |
18 | unset( $configuration['class'] ); | 18 | unset( $configuration['class'] ); |
19 | } else{ | 19 | } else{ |
20 | throw new \ErrorException('Error configuration - undefined class'); | 20 | throw new \ErrorException('Error configuration - undefined class'); |
vendor/yiisoft/multiparser/Parser.php
@@ -13,6 +13,11 @@ abstract class Parser | @@ -13,6 +13,11 @@ abstract class Parser | ||
13 | public $converter_conf = []; | 13 | public $converter_conf = []; |
14 | protected $converter = NULL; | 14 | protected $converter = NULL; |
15 | 15 | ||
16 | + /** @var array - массив с заголовком, | ||
17 | + * */ | ||
18 | + public $keys = NULL; | ||
19 | + public $hasHeaderRow = false; | ||
20 | + | ||
16 | public function setup() | 21 | public function setup() |
17 | { | 22 | { |
18 | $this->setupConverter(); | 23 | $this->setupConverter(); |
@@ -20,6 +25,11 @@ abstract class Parser | @@ -20,6 +25,11 @@ abstract class Parser | ||
20 | 25 | ||
21 | protected function setupConverter() | 26 | protected function setupConverter() |
22 | { | 27 | { |
28 | + if ($this->hasHeaderRow) { | ||
29 | + // если у файла есть заголовок, то в результате имеем ассоциативный массив | ||
30 | + $this->converter_conf['hasKey'] = 1; | ||
31 | + } | ||
32 | + | ||
23 | $converter = ObjectCreator::build( $this->converter_conf ); | 33 | $converter = ObjectCreator::build( $this->converter_conf ); |
24 | if ( $converter instanceof ConverterInterface ) { | 34 | if ( $converter instanceof ConverterInterface ) { |
25 | 35 |
vendor/yiisoft/multiparser/XmlParser.php
@@ -9,6 +9,9 @@ | @@ -9,6 +9,9 @@ | ||
9 | namespace yii\multiparser; | 9 | namespace yii\multiparser; |
10 | 10 | ||
11 | 11 | ||
12 | +use common\components\CustomVarDamp; | ||
13 | +use common\components\CustomArrayHelper; | ||
14 | + | ||
12 | class XmlParser extends Parser{ | 15 | class XmlParser extends Parser{ |
13 | /** @var экземляр SplFileObject читаемого файла */ | 16 | /** @var экземляр SplFileObject читаемого файла */ |
14 | public $file; | 17 | public $file; |
@@ -17,21 +20,13 @@ class XmlParser extends Parser{ | @@ -17,21 +20,13 @@ class XmlParser extends Parser{ | ||
17 | public function read() | 20 | public function read() |
18 | { | 21 | { |
19 | $file = $this->file; | 22 | $file = $this->file; |
20 | - $result = self::xmlToArray( $file->getPathname() ); | 23 | + $result = $this->xmlToArray( $file->getPathname() ); |
24 | + | ||
21 | if ( isset($this->node) ) { | 25 | if ( isset($this->node) ) { |
22 | - $result = $result[$this->node]; | ||
23 | - } | ||
24 | 26 | ||
25 | - //@todo переделать на универсальный способ, а для фрейма создать отдельный класс | ||
26 | -// $key_column = \Yii::$app->multiparser->getConfiguration('xml','basic_column'); | ||
27 | -// $key_column = array_flip($key_column); | ||
28 | -// | ||
29 | -// $result = \Yii::$app->multiparser->convertToAssocArray($result, $key_column); | ||
30 | -// foreach ( $result as &$value ) { | ||
31 | -// if (is_array($value)) { | ||
32 | -// $value = \Yii::$app->multiparser->convertByConfiguration( $value, $this->converter_conf ); | ||
33 | -// } | ||
34 | -// } | 27 | + $result = $result[ $this->node ]; |
28 | + | ||
29 | + } | ||
35 | 30 | ||
36 | return $result; | 31 | return $result; |
37 | } | 32 | } |
@@ -44,12 +39,12 @@ class XmlParser extends Parser{ | @@ -44,12 +39,12 @@ class XmlParser extends Parser{ | ||
44 | * @param string $file_path | 39 | * @param string $file_path |
45 | * @return array | 40 | * @return array |
46 | */ | 41 | */ |
47 | - protected static function xmlToArray( $file_path ) { | 42 | + protected function xmlToArray( $file_path ) { |
48 | 43 | ||
49 | try { | 44 | try { |
50 | $xml = new \SimpleXMLElement( $file_path, 0, true ); | 45 | $xml = new \SimpleXMLElement( $file_path, 0, true ); |
51 | //\common\components\CustomVarDamp::dumpAndDie($xml->children()->children()); | 46 | //\common\components\CustomVarDamp::dumpAndDie($xml->children()->children()); |
52 | - $result = self::recursiveXMLToArray( $xml ); | 47 | + $result = $this->recursiveXMLToArray( $xml ); |
53 | } catch(Exception $ex) { | 48 | } catch(Exception $ex) { |
54 | 49 | ||
55 | throw $ex; | 50 | throw $ex; |
@@ -66,26 +61,60 @@ class XmlParser extends Parser{ | @@ -66,26 +61,60 @@ class XmlParser extends Parser{ | ||
66 | * | 61 | * |
67 | * @return mixed | 62 | * @return mixed |
68 | */ | 63 | */ |
69 | - protected static function recursiveXMLToArray($xml) { | ||
70 | - if(is_object($xml) && get_class($xml) == 'SimpleXMLElement') { | 64 | + protected function recursiveXMLToArray($xml) { |
65 | + if( $xml instanceof \SimpleXMLElement ) { | ||
71 | $attributes = $xml->attributes(); | 66 | $attributes = $xml->attributes(); |
72 | - foreach($attributes as $k => $v) { | ||
73 | - if($v) $a[$k] = (string) $v; | 67 | + |
68 | + foreach( $attributes as $key => $value ) { | ||
69 | + if( $value ) { | ||
70 | + $attribute_array[$key] = (string) $value; | ||
71 | + } | ||
74 | } | 72 | } |
75 | - $x = $xml; | 73 | + $previous_xml = $xml; |
76 | $xml = get_object_vars($xml); | 74 | $xml = get_object_vars($xml); |
77 | } | 75 | } |
78 | 76 | ||
79 | - //\common\components\CustomVarDamp::dump($xml); | ||
80 | if(is_array($xml)) { | 77 | if(is_array($xml)) { |
81 | - if(count($xml) == 0) return (string) $x; // for CDATA | 78 | + |
79 | + if( count($xml) == 0 ) | ||
80 | + return (string) $previous_xml; // for CDATA | ||
81 | + | ||
82 | foreach($xml as $key => $value) { | 82 | foreach($xml as $key => $value) { |
83 | - $r[$key] = self::recursiveXMLToArray($value); | 83 | + $row[$key] = $this->recursiveXMLToArray($value); |
84 | + } | ||
85 | + if ( is_string($value) ) { | ||
86 | + // дошли до конца рекурсии | ||
87 | + // преобразуем ряд согласно конфигурации | ||
88 | + if ( $this->keys !== NULL ) { | ||
89 | + | ||
90 | + // назначим ключи из конфигурации, согласно массиву $keys | ||
91 | + $row = $this->compareArrayWithKeys( $row ); | ||
92 | + } | ||
93 | + $row = $this->convert( $row ); | ||
94 | + | ||
84 | } | 95 | } |
85 | - if(isset($a)) $r['@'] = $a; // Attributes | ||
86 | - return $r; | 96 | + |
97 | + | ||
98 | + if( isset( $attribute_array ) ) | ||
99 | + $row['@'] = $attribute_array; // Attributes | ||
100 | + | ||
101 | + return $row; | ||
87 | } | 102 | } |
88 | - //\common\components\CustomVarDamp::dumpAndDie($xml); | ||
89 | return (string) $xml; | 103 | return (string) $xml; |
90 | } | 104 | } |
105 | + | ||
106 | + /** | ||
107 | + * @param array $value_arr - текущий ряд, массив, которому нужно назначить конфигурационные ключи ($keys) | ||
108 | + * @return array | ||
109 | + */ | ||
110 | + protected function compareArrayWithKeys( array $value_arr ){ | ||
111 | + $res = $this->keys; | ||
112 | + foreach ( $this->keys as $key => $value ) { | ||
113 | + if ( array_key_exists( $value, $value_arr ) ) { | ||
114 | + $res[$key] = $value_arr[$value]; | ||
115 | + } | ||
116 | + } | ||
117 | + return $res; | ||
118 | + } | ||
119 | + | ||
91 | } | 120 | } |
92 | \ No newline at end of file | 121 | \ No newline at end of file |