Commit 2d4b15147641ef1462f8460ffa608b5e03eb0245
1 parent
f32f4cbc
adapted xls parser
Showing
12 changed files
with
115 additions
and
226 deletions
Show diff stats
backend/controllers/CrossingUploadController.php
| @@ -73,7 +73,8 @@ class CrossingUploadController extends BaseController | @@ -73,7 +73,8 @@ class CrossingUploadController extends BaseController | ||
| 73 | $model->file_path = Yii::getAlias('@temp_upload') . '/' . $file_name; | 73 | $model->file_path = Yii::getAlias('@temp_upload') . '/' . $file_name; |
| 74 | $model->file->saveAs($model->file_path); | 74 | $model->file->saveAs($model->file_path); |
| 75 | //запускаем парсинг | 75 | //запускаем парсинг |
| 76 | - $data = $model->readFile(); | 76 | + $options['mode'] = 'crosses'; |
| 77 | + $data = $model->readFile($options); | ||
| 77 | // сохраняем в кеш отпарсенные даные | 78 | // сохраняем в кеш отпарсенные даные |
| 78 | $this->parserCacheHandler( 1, $data, $model ); | 79 | $this->parserCacheHandler( 1, $data, $model ); |
| 79 | } else { | 80 | } else { |
| @@ -170,7 +171,6 @@ class CrossingUploadController extends BaseController | @@ -170,7 +171,6 @@ class CrossingUploadController extends BaseController | ||
| 170 | 171 | ||
| 171 | protected function convertDataByConfiguration($data, $configuration) | 172 | protected function convertDataByConfiguration($data, $configuration) |
| 172 | { | 173 | { |
| 173 | - | ||
| 174 | // доп. опции для парсера - удаление префикса в артикулах | 174 | // доп. опции для парсера - удаление префикса в артикулах |
| 175 | $options['mode'] = 'crosses'; | 175 | $options['mode'] = 'crosses'; |
| 176 | $fields = []; | 176 | $fields = []; |
| @@ -196,7 +196,6 @@ class CrossingUploadController extends BaseController | @@ -196,7 +196,6 @@ class CrossingUploadController extends BaseController | ||
| 196 | } | 196 | } |
| 197 | 197 | ||
| 198 | return $data; | 198 | return $data; |
| 199 | - | ||
| 200 | } | 199 | } |
| 201 | 200 | ||
| 202 | protected function reverseCrosses($data) | 201 | protected function reverseCrosses($data) |
backend/controllers/ParserController.php
| 1 | <?php | 1 | <?php |
| 2 | namespace backend\controllers; | 2 | namespace backend\controllers; |
| 3 | 3 | ||
| 4 | +use common\components\CustomVarDamp; | ||
| 4 | use common\models\Details; | 5 | use common\models\Details; |
| 5 | use common\components\exceptions\CrossParsingException; | 6 | use common\components\exceptions\CrossParsingException; |
| 6 | use common\components\exceptions\OrdinaryActiveRecordException; | 7 | use common\components\exceptions\OrdinaryActiveRecordException; |
backend/controllers/RgGrupController.php
| @@ -71,7 +71,8 @@ class RgGrupController extends BaseController | @@ -71,7 +71,8 @@ class RgGrupController extends BaseController | ||
| 71 | $model->file_path = Yii::getAlias('@manual_upload') . '/' . $model->file->name; | 71 | $model->file_path = Yii::getAlias('@manual_upload') . '/' . $model->file->name; |
| 72 | $model->file->saveAs($model->file_path); | 72 | $model->file->saveAs($model->file_path); |
| 73 | //запускаем парсинг | 73 | //запускаем парсинг |
| 74 | - $data = $model->readFile(); | 74 | + $options['mode'] = 'rg'; |
| 75 | + $data = $model->readFile($options); | ||
| 75 | // сохраняем в кеш отпарсенные даные | 76 | // сохраняем в кеш отпарсенные даные |
| 76 | $this->parserCacheHandler(1, $data, $model); | 77 | $this->parserCacheHandler(1, $data, $model); |
| 77 | } else { | 78 | } else { |
| @@ -120,7 +121,7 @@ class RgGrupController extends BaseController | @@ -120,7 +121,7 @@ class RgGrupController extends BaseController | ||
| 120 | $data = CustomArrayHelper::createAssocArray($data, $arr, 'attr_'); | 121 | $data = CustomArrayHelper::createAssocArray($data, $arr, 'attr_'); |
| 121 | 122 | ||
| 122 | // в первой строке у нас заголовки - уберем | 123 | // в первой строке у нас заголовки - уберем |
| 123 | - unset($data[0]); | 124 | + unset($data[0]); //- закоментировать если в конфиге парсера указано о наличии заголовка |
| 124 | // подготовим данные для записи в таблицу w_margins_groups | 125 | // подготовим данные для записи в таблицу w_margins_groups |
| 125 | $data = $this->convertDataByConfiguration($data, $configuration); | 126 | $data = $this->convertDataByConfiguration($data, $configuration); |
| 126 | 127 |
common/components/parsers/CsvParser.php
| @@ -40,33 +40,6 @@ class CsvParser extends TableParser | @@ -40,33 +40,6 @@ class CsvParser extends TableParser | ||
| 40 | $this->row = fgetcsv( $this->file, 0, $this->delimiter ); | 40 | $this->row = fgetcsv( $this->file, 0, $this->delimiter ); |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | - protected function isEmptyRow(){ | ||
| 44 | - | ||
| 45 | - $is_empty = false; | ||
| 46 | - | ||
| 47 | - if ($this->row === false || $this->row === NULL ) { | ||
| 48 | - return true; | ||
| 49 | - } | ||
| 50 | - | ||
| 51 | - $j = 0; | ||
| 52 | - for ($i = 1; $i <= count( $this->row ); $i++) { | ||
| 53 | - | ||
| 54 | - if ( !isset( $this->row[ $i - 1 ] ) ) { | ||
| 55 | - continue; | ||
| 56 | - } | ||
| 57 | - | ||
| 58 | - if ( $this->isEmptyColumn( $this->row[$i - 1] ) ) { | ||
| 59 | - $j++; | ||
| 60 | - } | ||
| 61 | - | ||
| 62 | - if ( $j >= $this->min_column_quantity ) { | ||
| 63 | - $is_empty = true; | ||
| 64 | - break; | ||
| 65 | - } | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | - return $is_empty; | ||
| 69 | - } | ||
| 70 | 43 | ||
| 71 | protected function isEmptyColumn( $val ){ | 44 | protected function isEmptyColumn( $val ){ |
| 72 | return $val == ''; | 45 | return $val == ''; |
common/components/parsers/Parser.php
| @@ -9,8 +9,6 @@ | @@ -9,8 +9,6 @@ | ||
| 9 | namespace common\components\parsers; | 9 | namespace common\components\parsers; |
| 10 | 10 | ||
| 11 | //@todo - заменить read на parse | 11 | //@todo - заменить read на parse |
| 12 | -//@todo - xml - убрать из названий функций xml и array - это и так понятно | ||
| 13 | - | ||
| 14 | 12 | ||
| 15 | use common\components\CustomVarDamp; | 13 | use common\components\CustomVarDamp; |
| 16 | 14 | ||
| @@ -32,20 +30,8 @@ abstract class Parser | @@ -32,20 +30,8 @@ abstract class Parser | ||
| 32 | /** @var array - массив с заголовком, | 30 | /** @var array - массив с заголовком, |
| 33 | * */ | 31 | * */ |
| 34 | public $keys = NULL; | 32 | public $keys = NULL; |
| 35 | - /** @var bool | ||
| 36 | - имеет ли файл заголовок который будет установлен ключами возвращемого массива*/ | ||
| 37 | - public $has_header_row = false; | ||
| 38 | - /* | ||
| 39 | - *если есть ключи, то колонки с пустыми значениями будут пропускаться (из ряда такие значения будут удаляться), | ||
| 40 | - * например если в файле вторая колонка пустая то она будет удалена | ||
| 41 | - * если есть $has_header_row - то первая значимая строка становится ключами, но пустые колонки не удаляются из ряда | ||
| 42 | - * например если в файле вторая колонка пустая то ей будет назначен соответсвующий ключ (второй) из первой строки | ||
| 43 | - * все описаное выше реализуется в дочернем семействе классов TableParser в методе filterRow() | ||
| 44 | - * для xml происходит просто сопоставление переданных ключей с прочитанными | ||
| 45 | - */ | ||
| 46 | - | ||
| 47 | - | ||
| 48 | 33 | ||
| 34 | + public abstract function read(); | ||
| 49 | 35 | ||
| 50 | public function setup() | 36 | public function setup() |
| 51 | { | 37 | { |
| @@ -54,7 +40,7 @@ abstract class Parser | @@ -54,7 +40,7 @@ abstract class Parser | ||
| 54 | 40 | ||
| 55 | protected function setupConverter() | 41 | protected function setupConverter() |
| 56 | { | 42 | { |
| 57 | - if ( $this->has_header_row || $this->keys !== NULL ) { | 43 | + if ( !empty( $this->keys ) ) { |
| 58 | // если у файла есть заголовок, то в результате имеем ассоциативный массив | 44 | // если у файла есть заголовок, то в результате имеем ассоциативный массив |
| 59 | $this->converter_conf['hasKey'] = 1; | 45 | $this->converter_conf['hasKey'] = 1; |
| 60 | } | 46 | } |
| @@ -67,12 +53,8 @@ abstract class Parser | @@ -67,12 +53,8 @@ abstract class Parser | ||
| 67 | 53 | ||
| 68 | } | 54 | } |
| 69 | } | 55 | } |
| 70 | - | ||
| 71 | - | ||
| 72 | } | 56 | } |
| 73 | 57 | ||
| 74 | - public abstract function read(); | ||
| 75 | - | ||
| 76 | /** | 58 | /** |
| 77 | * @param $arr | 59 | * @param $arr |
| 78 | * @return mixed | 60 | * @return mixed |
| @@ -80,16 +62,12 @@ abstract class Parser | @@ -80,16 +62,12 @@ abstract class Parser | ||
| 80 | */ | 62 | */ |
| 81 | protected function convert( $arr ) | 63 | protected function convert( $arr ) |
| 82 | { | 64 | { |
| 83 | - | ||
| 84 | if ($this->converter !== NULL) { | 65 | if ($this->converter !== NULL) { |
| 85 | 66 | ||
| 86 | $arr = $this->converter->convertByConfiguration( $arr, $this->converter_conf ); | 67 | $arr = $this->converter->convertByConfiguration( $arr, $this->converter_conf ); |
| 87 | 68 | ||
| 88 | } | 69 | } |
| 89 | - | ||
| 90 | - | ||
| 91 | return $arr; | 70 | return $arr; |
| 92 | - | ||
| 93 | } | 71 | } |
| 94 | 72 | ||
| 95 | public final static function supportedExtension() | 73 | public final static function supportedExtension() |
| @@ -99,13 +77,9 @@ abstract class Parser | @@ -99,13 +77,9 @@ abstract class Parser | ||
| 99 | 77 | ||
| 100 | protected function cleanUp( ) | 78 | protected function cleanUp( ) |
| 101 | { | 79 | { |
| 102 | - | ||
| 103 | unset( $this->file ); | 80 | unset( $this->file ); |
| 104 | unset( $this->converter ); | 81 | unset( $this->converter ); |
| 105 | unset( $this->converter_conf ); | 82 | unset( $this->converter_conf ); |
| 106 | - | ||
| 107 | - | ||
| 108 | } | 83 | } |
| 109 | 84 | ||
| 110 | - | ||
| 111 | } | 85 | } |
| 112 | \ No newline at end of file | 86 | \ No newline at end of file |
common/components/parsers/TableParser.php
| @@ -13,14 +13,19 @@ use common\components\CustomVarDamp; | @@ -13,14 +13,19 @@ use common\components\CustomVarDamp; | ||
| 13 | 13 | ||
| 14 | abstract class TableParser extends Parser | 14 | abstract class TableParser extends Parser |
| 15 | { | 15 | { |
| 16 | - | ||
| 17 | - | ||
| 18 | /** | 16 | /** |
| 19 | * @var array - текущий отпарсенный ряд | 17 | * @var array - текущий отпарсенный ряд |
| 18 | + *если есть ключи, то колонки с пустыми значениями будут пропускаться (из ряда такие значения будут удаляться), | ||
| 19 | + * например если в файле вторая колонка пустая то она будет удалена | ||
| 20 | + * в остальных случаях парсятся все колонки (не проверяется - пустая ли колонка) и попадёт в итоговый массив | ||
| 20 | */ | 21 | */ |
| 21 | protected $row = []; | 22 | protected $row = []; |
| 22 | 23 | ||
| 23 | - /** @var int - первая строка с которой начинать парсить */ | 24 | + /** @var int - первая строка с которой начинать парсить |
| 25 | + * эта строка будет считаться первой значимой строкой | ||
| 26 | + * если установлен аттрибут $has_header_row, | ||
| 27 | + * тогда следующая строка будет считаться заголовком и будет пропущена | ||
| 28 | + */ | ||
| 24 | public $first_line = 0; | 29 | public $first_line = 0; |
| 25 | 30 | ||
| 26 | /** @var int - последняя строка до которой парсить | 31 | /** @var int - последняя строка до которой парсить |
| @@ -32,9 +37,11 @@ abstract class TableParser extends Parser | @@ -32,9 +37,11 @@ abstract class TableParser extends Parser | ||
| 32 | 37 | ||
| 33 | 38 | ||
| 34 | /** @var bool | 39 | /** @var bool |
| 35 | - нужно ли искать автоматически первоую значисмую строку (не пустая строка) | ||
| 36 | - * иначе первая строка будет взята из аттрибута $first_line */ | ||
| 37 | - public $auto_detect_first_line = false; | 40 | + * имеет ли файл заголовок в первой значимой строке |
| 41 | + * true - первая значимая строка будет пропущена | ||
| 42 | + */ | ||
| 43 | + public $has_header_row = true; | ||
| 44 | + | ||
| 38 | 45 | ||
| 39 | /** @var int - количество значимых колонок, что бы определить первую значимую строку | 46 | /** @var int - количество значимых колонок, что бы определить первую значимую строку |
| 40 | * используется при автоопределении первой строки*/ | 47 | * используется при автоопределении первой строки*/ |
| @@ -48,8 +55,6 @@ abstract class TableParser extends Parser | @@ -48,8 +55,6 @@ abstract class TableParser extends Parser | ||
| 48 | protected $current_row_number = 0; | 55 | protected $current_row_number = 0; |
| 49 | 56 | ||
| 50 | 57 | ||
| 51 | - protected abstract function isEmptyRow(); | ||
| 52 | - | ||
| 53 | protected abstract function isEmptyColumn($column_value); | 58 | protected abstract function isEmptyColumn($column_value); |
| 54 | 59 | ||
| 55 | protected abstract function readRow(); | 60 | protected abstract function readRow(); |
| @@ -59,69 +64,71 @@ abstract class TableParser extends Parser | @@ -59,69 +64,71 @@ abstract class TableParser extends Parser | ||
| 59 | 64 | ||
| 60 | public function read() | 65 | public function read() |
| 61 | { | 66 | { |
| 62 | - if ($this->auto_detect_first_line) { | ||
| 63 | - $this->shiftToFirstValuableLine(); | ||
| 64 | - } | 67 | + // получим первую значимую строку |
| 68 | + $this->shiftToFirstValuableLine(); | ||
| 69 | + | ||
| 70 | + // первый проход, строка прочитана в shiftToFirstValuableLine | ||
| 71 | + $first_circle = true; | ||
| 65 | 72 | ||
| 66 | // будем считать количество пустых строк подряд - при достижении $empty_lines_quantity - считаем что это конец файла и выходим | 73 | // будем считать количество пустых строк подряд - при достижении $empty_lines_quantity - считаем что это конец файла и выходим |
| 67 | $empty_lines = 0; | 74 | $empty_lines = 0; |
| 68 | while ($empty_lines < $this->empty_lines_quantity) { | 75 | while ($empty_lines < $this->empty_lines_quantity) { |
| 69 | - // прочтем строку из файла | ||
| 70 | - $this->readRow(); | ||
| 71 | 76 | ||
| 72 | - if ($this->isEmptyRow()) { | ||
| 73 | - //счетчик пустых строк | ||
| 74 | - $empty_lines++; | ||
| 75 | - $this->current_row_number++; | ||
| 76 | - continue; | 77 | + // прочтем строку из файла, если это не первый проход |
| 78 | + if (!$first_circle){ | ||
| 79 | + $this->readRow(); | ||
| 77 | } | 80 | } |
| 78 | 81 | ||
| 82 | + $first_circle = false; | ||
| 83 | + | ||
| 79 | // уберем пустые колонки из ряда | 84 | // уберем пустые колонки из ряда |
| 80 | if ($this->keys === NULL) { | 85 | if ($this->keys === NULL) { |
| 81 | $this->filterRow(); | 86 | $this->filterRow(); |
| 82 | } | 87 | } |
| 83 | 88 | ||
| 89 | + if ($this->isEmptyRow()) { | ||
| 90 | + //счетчик пустых строк | ||
| 91 | + $empty_lines++; | ||
| 92 | + $this->current_row_number++; | ||
| 93 | + continue; | ||
| 94 | + } | ||
| 84 | 95 | ||
| 96 | + // запустим конвертирование | ||
| 85 | $this->adjustRowToSettings(); | 97 | $this->adjustRowToSettings(); |
| 86 | 98 | ||
| 99 | + // установим отпарсенную строку в итоговый массив результата | ||
| 100 | + $this->setResult(); | ||
| 87 | // строка не пустая, имеем прочитанный массив значений | 101 | // строка не пустая, имеем прочитанный массив значений |
| 88 | $this->current_row_number++; | 102 | $this->current_row_number++; |
| 89 | 103 | ||
| 90 | - // для первой строки утановим ключи из заголовка | ||
| 91 | - if (!$this->setKeysFromHeader()) { | ||
| 92 | - $this->setResult(); | ||
| 93 | - } | ||
| 94 | - | ||
| 95 | - | ||
| 96 | // если у нас установлен лимит, при его достижении прекращаем парсинг | 104 | // если у нас установлен лимит, при его достижении прекращаем парсинг |
| 97 | if ($this->isLastLine()) | 105 | if ($this->isLastLine()) |
| 98 | break; | 106 | break; |
| 99 | 107 | ||
| 100 | // обнуляем счетчик, так как считаюся пустые строки ПОДРЯД | 108 | // обнуляем счетчик, так как считаюся пустые строки ПОДРЯД |
| 101 | $empty_lines = 0; | 109 | $empty_lines = 0; |
| 102 | - | ||
| 103 | } | 110 | } |
| 104 | } | 111 | } |
| 105 | 112 | ||
| 106 | /** | 113 | /** |
| 107 | * определяет первую значимую строку, | 114 | * определяет первую значимую строку, |
| 108 | * считывается файл пока в нем не встретится строка с непустыми колонками | 115 | * считывается файл пока в нем не встретится строка с непустыми колонками |
| 109 | - * в количестве указанном в атрибуте min_column_quantity | ||
| 110 | - * в результате выполнения $current_row_number будет находится на последней незначимой строке | 116 | + * или пока не дойдет до first_line |
| 117 | + * пропускает заголовок если он указан | ||
| 111 | */ | 118 | */ |
| 112 | protected function shiftToFirstValuableLine() | 119 | protected function shiftToFirstValuableLine() |
| 113 | { | 120 | { |
| 121 | + // читаем пока не встретим значимую строку, или пока не дойдем до first_line | ||
| 114 | do { | 122 | do { |
| 115 | - | ||
| 116 | $this->current_row_number++; | 123 | $this->current_row_number++; |
| 117 | $this->readRow(); | 124 | $this->readRow(); |
| 125 | + } while ( $this->isEmptyRow() && ( $this->first_line < $this->current_row_number ) ); | ||
| 118 | 126 | ||
| 119 | - } while ($this->isEmptyRow()); | ||
| 120 | - | ||
| 121 | - // @todo - сделать опционально | ||
| 122 | - // код для того что бы парсить первую строку, закомментировано как предполагается что первая значимая строка это заголовок | ||
| 123 | - // $this->current_row_number --; | ||
| 124 | -// $this->file->seek( $this->current_row_number ); | 127 | + // если указан заголовок, то его мы тоже пропускаем (читаем далее) |
| 128 | + if( $this->has_header_row ) { | ||
| 129 | + $this->current_row_number++; | ||
| 130 | + $this->readRow(); | ||
| 131 | + } | ||
| 125 | } | 132 | } |
| 126 | 133 | ||
| 127 | /** | 134 | /** |
| @@ -129,7 +136,6 @@ abstract class TableParser extends Parser | @@ -129,7 +136,6 @@ abstract class TableParser extends Parser | ||
| 129 | */ | 136 | */ |
| 130 | protected function adjustRowToSettings() | 137 | protected function adjustRowToSettings() |
| 131 | { | 138 | { |
| 132 | - | ||
| 133 | // если есть заголовок, то перед конвертацией его нужно назначить | 139 | // если есть заголовок, то перед конвертацией его нужно назначить |
| 134 | if ($this->keys !== NULL) { | 140 | if ($this->keys !== NULL) { |
| 135 | // adjust row to keys | 141 | // adjust row to keys |
| @@ -150,22 +156,43 @@ abstract class TableParser extends Parser | @@ -150,22 +156,43 @@ abstract class TableParser extends Parser | ||
| 150 | 156 | ||
| 151 | } | 157 | } |
| 152 | 158 | ||
| 153 | - protected function setKeysFromHeader() | ||
| 154 | - { | ||
| 155 | - if ($this->has_header_row) { | ||
| 156 | - // в файле есть заголовок, но он еще не назначен - назначим | ||
| 157 | - if ($this->keys === NULL) { | ||
| 158 | - $this->keys = array_values($this->row); | ||
| 159 | - return true; | 159 | + protected function isEmptyRow(){ |
| 160 | + | ||
| 161 | + $is_empty = false; | ||
| 162 | + | ||
| 163 | + if ( empty( $this->row ) ) { | ||
| 164 | + return true; | ||
| 165 | + } | ||
| 166 | + if ( count( $this->row ) < $this->min_column_quantity ) { | ||
| 167 | + return true; | ||
| 168 | + } | ||
| 169 | + | ||
| 170 | + $j = 0; | ||
| 171 | + for ($i = 1; $i <= count( $this->row ); $i++) { | ||
| 172 | + | ||
| 173 | + if ( !isset( $this->row[ $i - 1 ] ) ) { | ||
| 174 | + continue; | ||
| 175 | + } | ||
| 176 | + | ||
| 177 | + if ( $this->isEmptyColumn( $this->row[$i - 1] ) ) { | ||
| 178 | + $j++; | ||
| 179 | + } | ||
| 180 | + | ||
| 181 | + if ( $j >= $this->min_column_quantity ) { | ||
| 182 | + $is_empty = true; | ||
| 183 | + break; | ||
| 160 | } | 184 | } |
| 161 | } | 185 | } |
| 162 | - return false; | 186 | + |
| 187 | + return $is_empty; | ||
| 163 | } | 188 | } |
| 164 | 189 | ||
| 190 | + | ||
| 191 | + | ||
| 165 | protected function filterRow() | 192 | protected function filterRow() |
| 166 | { | 193 | { |
| 167 | - // если есть заголовок - все значения нужны, не фильтруем | ||
| 168 | - if ($this->has_header_row || !is_array($this->row)) { | 194 | + // нет строки - нет фильтрации |
| 195 | + if ( empty( $this->row ) ) { | ||
| 169 | return; | 196 | return; |
| 170 | } | 197 | } |
| 171 | $this->row = array_filter($this->row, function ($val) { | 198 | $this->row = array_filter($this->row, function ($val) { |
common/components/parsers/XlsParser.php
| @@ -66,36 +66,6 @@ class XlsParser extends TableParser | @@ -66,36 +66,6 @@ class XlsParser extends TableParser | ||
| 66 | } | 66 | } |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | - protected function isEmptyRow(){ | ||
| 70 | - | ||
| 71 | - $is_empty = false; | ||
| 72 | - | ||
| 73 | - if ( !$this->row ) { | ||
| 74 | - return true; | ||
| 75 | - } | ||
| 76 | - if ( count( $this->row ) < $this->min_column_quantity ) { | ||
| 77 | - return true; | ||
| 78 | - } | ||
| 79 | - | ||
| 80 | - $j = 0; | ||
| 81 | - for ($i = 1; $i <= count( $this->row ); $i++) { | ||
| 82 | - | ||
| 83 | - if ( !isset( $this->row[ $i - 1 ] ) ) { | ||
| 84 | - continue; | ||
| 85 | - } | ||
| 86 | - | ||
| 87 | - if ( $this->isEmptyColumn( $this->row[$i - 1] ) ) { | ||
| 88 | - $j++; | ||
| 89 | - } | ||
| 90 | - | ||
| 91 | - if ( $j >= $this->min_column_quantity ) { | ||
| 92 | - $is_empty = true; | ||
| 93 | - break; | ||
| 94 | - } | ||
| 95 | - } | ||
| 96 | - | ||
| 97 | - return $is_empty; | ||
| 98 | - } | ||
| 99 | 69 | ||
| 100 | protected function isEmptyColumn( $val ){ | 70 | protected function isEmptyColumn( $val ){ |
| 101 | return $val == ''; | 71 | return $val == ''; |
common/components/parsers/XlsxParser.php
| @@ -175,58 +175,17 @@ class XlsxParser extends TableParser | @@ -175,58 +175,17 @@ class XlsxParser extends TableParser | ||
| 175 | $value = (string)round( $value, $this->float_precision ); | 175 | $value = (string)round( $value, $this->float_precision ); |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | - | ||
| 179 | } else { | 178 | } else { |
| 180 | $value = ''; | 179 | $value = ''; |
| 181 | } | 180 | } |
| 182 | - | ||
| 183 | // set | 181 | // set |
| 184 | $this->row[$i] = $value; | 182 | $this->row[$i] = $value; |
| 185 | - | ||
| 186 | } | 183 | } |
| 187 | -// // fill the row by empty values for keys that we are missed in previous step | ||
| 188 | - // only for 'has_header_row = true' mode | ||
| 189 | - if ( $this->has_header_row && $this->keys !== Null ) { | ||
| 190 | - $extra_column = count( $this->keys ) - count( $this->row ); | ||
| 191 | - if ( $extra_column ) { | ||
| 192 | - foreach ( $this->keys as $key => $key ) { | ||
| 193 | - | ||
| 194 | - if ( isset( $this->row[$key] ) ) { | ||
| 195 | - continue; | ||
| 196 | - } | ||
| 197 | - $this->row[$key] = ''; | ||
| 198 | - } | ||
| 199 | - } | ||
| 200 | 184 | ||
| 201 | - } | ||
| 202 | ksort( $this->row ); | 185 | ksort( $this->row ); |
| 203 | $this->current_node->next(); | 186 | $this->current_node->next(); |
| 204 | } | 187 | } |
| 205 | 188 | ||
| 206 | - protected function isEmptyRow() | ||
| 207 | - { | ||
| 208 | - | ||
| 209 | - $is_empty = false; | ||
| 210 | - | ||
| 211 | - if (!count($this->row)) { | ||
| 212 | - return true; | ||
| 213 | - } | ||
| 214 | - | ||
| 215 | - $j = 0; | ||
| 216 | - for ($i = 1; $i <= count($this->row); $i++) { | ||
| 217 | - | ||
| 218 | - if (isset($this->row[$i - 1]) && $this->isEmptyColumn($this->row[$i - 1])) { | ||
| 219 | - $j++; | ||
| 220 | - } | ||
| 221 | - | ||
| 222 | - if ($j >= $this->min_column_quantity) { | ||
| 223 | - $is_empty = true; | ||
| 224 | - break; | ||
| 225 | - } | ||
| 226 | - } | ||
| 227 | - | ||
| 228 | - return $is_empty; | ||
| 229 | - } | ||
| 230 | 189 | ||
| 231 | protected function isEmptyColumn($val) | 190 | protected function isEmptyColumn($val) |
| 232 | { | 191 | { |
| @@ -261,7 +220,6 @@ class XlsxParser extends TableParser | @@ -261,7 +220,6 @@ class XlsxParser extends TableParser | ||
| 261 | } | 220 | } |
| 262 | } | 221 | } |
| 263 | 222 | ||
| 264 | - | ||
| 265 | /** | 223 | /** |
| 266 | * @param $cell_address - string with address like A1, B1 ... | 224 | * @param $cell_address - string with address like A1, B1 ... |
| 267 | * @return int - integer index | 225 | * @return int - integer index |
| @@ -281,17 +239,7 @@ class XlsxParser extends TableParser | @@ -281,17 +239,7 @@ class XlsxParser extends TableParser | ||
| 281 | return $index; | 239 | return $index; |
| 282 | 240 | ||
| 283 | } | 241 | } |
| 284 | -// @todo - переписать родительский метод в универсальной манере а не переопределять его | ||
| 285 | - protected function setKeysFromHeader(){ | ||
| 286 | - if ( $this->has_header_row ) { | ||
| 287 | 242 | ||
| 288 | - if ($this->keys === NULL) { | ||
| 289 | - $this->keys = $this->row; | ||
| 290 | - return true; | ||
| 291 | - } | ||
| 292 | - } | ||
| 293 | - return false; | ||
| 294 | - } | ||
| 295 | protected function cleanUp() | 243 | protected function cleanUp() |
| 296 | { | 244 | { |
| 297 | parent::cleanUp(); | 245 | parent::cleanUp(); |
common/components/parsers/XmlParser.php
| @@ -15,15 +15,13 @@ class XmlParser extends Parser{ | @@ -15,15 +15,13 @@ class XmlParser extends Parser{ | ||
| 15 | 15 | ||
| 16 | public function read() | 16 | public function read() |
| 17 | { | 17 | { |
| 18 | - //$file = $this->file; | ||
| 19 | - $result = $this->xmlToArray( ); | 18 | + $result = $this->parseToArray( ); |
| 20 | 19 | ||
| 21 | if ( isset($this->node) ) { | 20 | if ( isset($this->node) ) { |
| 22 | 21 | ||
| 23 | $result = $result[ $this->node ]; | 22 | $result = $result[ $this->node ]; |
| 24 | 23 | ||
| 25 | } | 24 | } |
| 26 | - | ||
| 27 | $this->cleanUp(); | 25 | $this->cleanUp(); |
| 28 | return $result; | 26 | return $result; |
| 29 | } | 27 | } |
| @@ -36,17 +34,15 @@ class XmlParser extends Parser{ | @@ -36,17 +34,15 @@ class XmlParser extends Parser{ | ||
| 36 | * @throws Exception | 34 | * @throws Exception |
| 37 | * @throws \Exception | 35 | * @throws \Exception |
| 38 | */ | 36 | */ |
| 39 | - protected function xmlToArray( ) { | ||
| 40 | - | 37 | + protected function parseToArray( ) { |
| 41 | try { | 38 | try { |
| 42 | $xml = new \SimpleXMLElement( $this->file_path, 0, true ); | 39 | $xml = new \SimpleXMLElement( $this->file_path, 0, true ); |
| 43 | //\common\components\CustomVarDamp::dumpAndDie($xml->children()->children()); | 40 | //\common\components\CustomVarDamp::dumpAndDie($xml->children()->children()); |
| 44 | - $result = $this->recursiveXMLToArray( $xml ); | 41 | + $result = $this->recursiveParseToArray( $xml ); |
| 45 | } catch(\Exception $ex) { | 42 | } catch(\Exception $ex) { |
| 46 | 43 | ||
| 47 | throw $ex; | 44 | throw $ex; |
| 48 | } | 45 | } |
| 49 | - | ||
| 50 | return $result; | 46 | return $result; |
| 51 | } | 47 | } |
| 52 | 48 | ||
| @@ -58,7 +54,7 @@ class XmlParser extends Parser{ | @@ -58,7 +54,7 @@ class XmlParser extends Parser{ | ||
| 58 | * | 54 | * |
| 59 | * @return mixed | 55 | * @return mixed |
| 60 | */ | 56 | */ |
| 61 | - protected function recursiveXMLToArray($xml) { | 57 | + protected function recursiveParseToArray($xml) { |
| 62 | if( $xml instanceof \SimpleXMLElement ) { | 58 | if( $xml instanceof \SimpleXMLElement ) { |
| 63 | $attributes = $xml->attributes(); | 59 | $attributes = $xml->attributes(); |
| 64 | 60 | ||
| @@ -77,7 +73,7 @@ class XmlParser extends Parser{ | @@ -77,7 +73,7 @@ class XmlParser extends Parser{ | ||
| 77 | return (string) $previous_xml; // for CDATA | 73 | return (string) $previous_xml; // for CDATA |
| 78 | 74 | ||
| 79 | foreach($xml as $key => $value) { | 75 | foreach($xml as $key => $value) { |
| 80 | - $row[$key] = $this->recursiveXMLToArray($value); | 76 | + $row[$key] = $this->recursiveParseToArray($value); |
| 81 | } | 77 | } |
| 82 | if ( is_string($value) ) { | 78 | if ( is_string($value) ) { |
| 83 | // дошли до конца рекурсии | 79 | // дошли до конца рекурсии |
| @@ -90,7 +86,6 @@ class XmlParser extends Parser{ | @@ -90,7 +86,6 @@ class XmlParser extends Parser{ | ||
| 90 | 86 | ||
| 91 | } | 87 | } |
| 92 | 88 | ||
| 93 | - | ||
| 94 | if( isset( $attribute_array ) ) | 89 | if( isset( $attribute_array ) ) |
| 95 | $row['@'] = $attribute_array; // Attributes | 90 | $row['@'] = $attribute_array; // Attributes |
| 96 | 91 |
common/components/parsers/config.php
| @@ -3,7 +3,6 @@ return [ | @@ -3,7 +3,6 @@ return [ | ||
| 3 | 'csv' => | 3 | 'csv' => |
| 4 | ['web' => | 4 | ['web' => |
| 5 | ['class' => 'common\components\parsers\CustomCsvParser', | 5 | ['class' => 'common\components\parsers\CustomCsvParser', |
| 6 | - 'auto_detect_first_line' => true, | ||
| 7 | 'converter_conf' => [ | 6 | 'converter_conf' => [ |
| 8 | 'class' => 'common\components\parsers\CustomConverter', | 7 | 'class' => 'common\components\parsers\CustomConverter', |
| 9 | 'configuration' => ["encode" => 'DESCR'], | 8 | 'configuration' => ["encode" => 'DESCR'], |
| @@ -11,7 +10,6 @@ return [ | @@ -11,7 +10,6 @@ return [ | ||
| 11 | ], | 10 | ], |
| 12 | 'console' => | 11 | 'console' => |
| 13 | ['class' => 'common\components\parsers\CustomCsvParser', | 12 | ['class' => 'common\components\parsers\CustomCsvParser', |
| 14 | - 'auto_detect_first_line' => true, | ||
| 15 | 'converter_conf' => [ | 13 | 'converter_conf' => [ |
| 16 | 'class' => ' common\components\parsers\CustomConverter', | 14 | 'class' => ' common\components\parsers\CustomConverter', |
| 17 | 'configuration' => ["encode" => 'DESCR', | 15 | 'configuration' => ["encode" => 'DESCR', |
| @@ -22,7 +20,6 @@ return [ | @@ -22,7 +20,6 @@ return [ | ||
| 22 | "multiply" => [], | 20 | "multiply" => [], |
| 23 | "article" => [], | 21 | "article" => [], |
| 24 | "details" => [] | 22 | "details" => [] |
| 25 | - | ||
| 26 | ] | 23 | ] |
| 27 | ],], | 24 | ],], |
| 28 | 25 | ||
| @@ -36,9 +33,7 @@ return [ | @@ -36,9 +33,7 @@ return [ | ||
| 36 | "ADD_BOX" => 'В пути', | 33 | "ADD_BOX" => 'В пути', |
| 37 | "GROUP" => 'Группа RG' | 34 | "GROUP" => 'Группа RG' |
| 38 | ], | 35 | ], |
| 39 | - | ||
| 40 | 'crosses' => ['class' => 'common\components\parsers\CustomCsvParser', | 36 | 'crosses' => ['class' => 'common\components\parsers\CustomCsvParser', |
| 41 | - 'auto_detect_first_line' => true, | ||
| 42 | 'min_column_quantity' => 4, | 37 | 'min_column_quantity' => 4, |
| 43 | 'converter_conf' => [ | 38 | 'converter_conf' => [ |
| 44 | 'class' => ' common\components\parsers\CustomConverter', | 39 | 'class' => ' common\components\parsers\CustomConverter', |
| @@ -60,7 +55,6 @@ return [ | @@ -60,7 +55,6 @@ return [ | ||
| 60 | ['console' => | 55 | ['console' => |
| 61 | ['class' => 'common\components\parsers\XmlParser', | 56 | ['class' => 'common\components\parsers\XmlParser', |
| 62 | 'node' => 'Товар', | 57 | 'node' => 'Товар', |
| 63 | - 'has_header_row' => true, | ||
| 64 | 'keys' => [ | 58 | 'keys' => [ |
| 65 | "BRAND" => 'Производитель', | 59 | "BRAND" => 'Производитель', |
| 66 | "ARTICLE" => 'Код', | 60 | "ARTICLE" => 'Код', |
| @@ -80,20 +74,29 @@ return [ | @@ -80,20 +74,29 @@ return [ | ||
| 80 | ['web' => | 74 | ['web' => |
| 81 | ['class' => 'common\components\parsers\XlsxParser', | 75 | ['class' => 'common\components\parsers\XlsxParser', |
| 82 | 'path_for_extract_files' => \Yii::getAlias('@temp_upload') . '/xlsx/', | 76 | 'path_for_extract_files' => \Yii::getAlias('@temp_upload') . '/xlsx/', |
| 83 | - //'auto_detect_first_line' => true, | ||
| 84 | - //'has_header_row' => true, | 77 | + 'min_column_quantity' => 5, |
| 85 | 'active_sheet' => 1, | 78 | 'active_sheet' => 1, |
| 86 | 'converter_conf' => [ | 79 | 'converter_conf' => [ |
| 87 | 'class' => 'common\components\parsers\CustomConverter', | 80 | 'class' => 'common\components\parsers\CustomConverter', |
| 88 | 'configuration' => ["string" => []], | 81 | 'configuration' => ["string" => []], |
| 89 | ] | 82 | ] |
| 90 | ], | 83 | ], |
| 84 | + 'rg' => | ||
| 85 | + ['class' => 'common\components\parsers\XlsxParser', | ||
| 86 | + 'path_for_extract_files' => \Yii::getAlias('@temp_upload') . '/xlsx/', | ||
| 87 | + 'min_column_quantity' => 4, | ||
| 88 | + 'has_header_row' => false, // заголовок есть, но мы его выводим пользователю для наглядности (так у них на сайте было) и принудительно удаляем первую строку при записи | ||
| 89 | + 'active_sheet' => 1, | ||
| 90 | + 'converter_conf' => [ | ||
| 91 | + 'class' => 'common\components\parsers\CustomConverter', | ||
| 92 | + 'configuration' => ["string" => []], | ||
| 93 | + ] | ||
| 94 | + ], | ||
| 91 | 'console' => | 95 | 'console' => |
| 92 | ['class' => 'common\components\parsers\XlsxParser', | 96 | ['class' => 'common\components\parsers\XlsxParser', |
| 93 | 'path_for_extract_files' => \Yii::getAlias('@temp_upload') . '/xlsx/', | 97 | 'path_for_extract_files' => \Yii::getAlias('@temp_upload') . '/xlsx/', |
| 94 | - 'auto_detect_first_line' => true, | ||
| 95 | 'active_sheet' => 1, | 98 | 'active_sheet' => 1, |
| 96 | - 'min_column_quantity' => 3, | 99 | + 'min_column_quantity' => 5, |
| 97 | 'converter_conf' => [ | 100 | 'converter_conf' => [ |
| 98 | 'class' => ' common\components\parsers\CustomConverter', | 101 | 'class' => ' common\components\parsers\CustomConverter', |
| 99 | 'configuration' => ["encode" => 'DESCR', | 102 | 'configuration' => ["encode" => 'DESCR', |
| @@ -108,9 +111,8 @@ return [ | @@ -108,9 +111,8 @@ return [ | ||
| 108 | ],], | 111 | ],], |
| 109 | ], | 112 | ], |
| 110 | 'txt' => | 113 | 'txt' => |
| 111 | - [ 'web' => | 114 | + ['web' => |
| 112 | ['class' => 'common\components\parsers\CustomCsvParser', | 115 | ['class' => 'common\components\parsers\CustomCsvParser', |
| 113 | - 'auto_detect_first_line' => true, | ||
| 114 | 'delimiter' => "\t", | 116 | 'delimiter' => "\t", |
| 115 | 'converter_conf' => [ | 117 | 'converter_conf' => [ |
| 116 | 'class' => 'common\components\parsers\CustomConverter', | 118 | 'class' => 'common\components\parsers\CustomConverter', |
| @@ -118,22 +120,21 @@ return [ | @@ -118,22 +120,21 @@ return [ | ||
| 118 | ] | 120 | ] |
| 119 | ], | 121 | ], |
| 120 | 'console' => | 122 | 'console' => |
| 121 | - ['class' => 'common\components\parsers\CustomCsvParser', | ||
| 122 | - 'auto_detect_first_line' => true, | ||
| 123 | - 'delimiter' => "\t", | ||
| 124 | - 'converter_conf' => [ | ||
| 125 | - 'class' => ' common\components\parsers\CustomConverter', | ||
| 126 | - 'configuration' => ["encode" => 'DESCR', | ||
| 127 | - "string" => 'DESCR', | ||
| 128 | - "float" => 'PRICE', | ||
| 129 | - "brand" => 'BRAND', | ||
| 130 | - "integer" => ['BOX', 'ADD_BOX'], | ||
| 131 | - "multiply" => [], | ||
| 132 | - "article" => [], | ||
| 133 | - "details" => [] | ||
| 134 | - ] | 123 | + ['class' => 'common\components\parsers\CustomCsvParser', |
| 124 | + 'delimiter' => "\t", | ||
| 125 | + 'converter_conf' => [ | ||
| 126 | + 'class' => ' common\components\parsers\CustomConverter', | ||
| 127 | + 'configuration' => ["encode" => 'DESCR', | ||
| 128 | + "string" => 'DESCR', | ||
| 129 | + "float" => 'PRICE', | ||
| 130 | + "brand" => 'BRAND', | ||
| 131 | + "integer" => ['BOX', 'ADD_BOX'], | ||
| 132 | + "multiply" => [], | ||
| 133 | + "article" => [], | ||
| 134 | + "details" => [] | ||
| 135 | + ] | ||
| 136 | + ], | ||
| 135 | ], | 137 | ], |
| 136 | - ], | ||
| 137 | 'basic_column' => [ | 138 | 'basic_column' => [ |
| 138 | Null => 'Пусто', | 139 | Null => 'Пусто', |
| 139 | "BRAND" => 'Бренд', | 140 | "BRAND" => 'Бренд', |
| @@ -148,7 +149,6 @@ return [ | @@ -148,7 +149,6 @@ return [ | ||
| 148 | 'xls' => | 149 | 'xls' => |
| 149 | ['web' => | 150 | ['web' => |
| 150 | ['class' => 'common\components\parsers\XlsParser', | 151 | ['class' => 'common\components\parsers\XlsParser', |
| 151 | - 'auto_detect_first_line' => true, | ||
| 152 | 'converter_conf' => [ | 152 | 'converter_conf' => [ |
| 153 | 'class' => 'common\components\parsers\CustomConverter', | 153 | 'class' => 'common\components\parsers\CustomConverter', |
| 154 | 'configuration' => ["encode" => 'DESCR'], | 154 | 'configuration' => ["encode" => 'DESCR'], |
| @@ -156,7 +156,6 @@ return [ | @@ -156,7 +156,6 @@ return [ | ||
| 156 | ], | 156 | ], |
| 157 | 'console' => | 157 | 'console' => |
| 158 | ['class' => 'common\components\parsers\XlsParser', | 158 | ['class' => 'common\components\parsers\XlsParser', |
| 159 | - 'auto_detect_first_line' => true, | ||
| 160 | 'converter_conf' => [ | 159 | 'converter_conf' => [ |
| 161 | 'class' => ' common\components\parsers\CustomConverter', | 160 | 'class' => ' common\components\parsers\CustomConverter', |
| 162 | 'configuration' => ["encode" => 'DESCR', | 161 | 'configuration' => ["encode" => 'DESCR', |