diff --git a/common/components/parsers/config.php b/common/components/parsers/config.php index 7e25bdf..cbf1acc 100644 --- a/common/components/parsers/config.php +++ b/common/components/parsers/config.php @@ -11,7 +11,6 @@ 'console' => ['class' => 'common\components\parsers\CustomCsvParser', 'auto_detect_first_line' => true, - 'hasHeaderRow' => true, 'converter_conf' => [ 'class' => ' common\components\parsers\CustomConverter', 'configuration' => ["string" => 'DESCR', @@ -38,11 +37,9 @@ 'crosses' => ['class' => 'common\components\parsers\CustomCsvParser', 'auto_detect_first_line' => true, 'min_column_quantity' => 4, - 'hasHeaderRow' => true, 'keys' =>['ARTICLE', 'CROSS_ARTICLE', 'BRAND', 'CROSS_BRAND'], 'converter_conf' => [ 'class' => ' common\components\parsers\CustomConverter', - 'hasKey' => 1, 'configuration' => [ "brand" => ['BRAND', 'CROSS_BRAND'], "crosses" => [], diff --git a/vendor/yiisoft/multiparser/CsvParser.php b/vendor/yiisoft/multiparser/CsvParser.php index 81a6ff3..7ca1b88 100644 --- a/vendor/yiisoft/multiparser/CsvParser.php +++ b/vendor/yiisoft/multiparser/CsvParser.php @@ -11,43 +11,11 @@ use common\components\CustomVarDamp; * @package yii\multiparser * @todo - перевести на анг. яз. */ -class CsvParser extends Parser +class CsvParser extends TableParser { - /** @var bool - имеет ли файл заголовок который будет установлен ключами возвращемого массива*/ - public $hasHeaderRow = false; - /** @var array - массив с заголовком, - * если не указан и установлено свойство $hasHeaderRow - будет определен автоматически */ - // public $keys; - определен в родительском классе - - /** @var int - первая строка с которой начинать парсить */ - public $first_line = 0; - - /** @var int - последняя строка до которой парсить - * если не указана, то парсинг происходит до конца файла*/ - public $last_line = 0; - - /** @var int - первая колонка файла с которой начнется парсинг */ - public $first_column = 0; - /** @var string - разделитель csv */ public $delimiter = ';'; - /** @var bool - нужно ли искать автоматически первоую значисмую строку (не пустая строка) - * иначе первая строка будет взята из аттрибута $first_line */ - public $auto_detect_first_line = false; - - /** @var int - количество значимых колонок, что бы определить первую значимую строку - * используется при автоопределении первой строки*/ - public $min_column_quantity = 5; - -// /** @var array - конфигурация конвертера значений */ -// public $converter_conf = []; -// /** @var array - конвертер созданный по конфигурации */ -// public $converter = NULL; - /** @var int - текущая строка */ - private $current_line = 0; /** @@ -55,132 +23,53 @@ class CsvParser extends Parser */ public function setup() { + $this->file->setCsvControl($this->delimiter); $this->file->setFlags(\SplFileObject::READ_CSV); $this->file->setFlags(\SplFileObject::SKIP_EMPTY); - if ($this->auto_detect_first_line) { - $this->shiftToFirstValuableLine(); - } - parent::setup(); } - /** - * определяет первую значимую строку, - * считывается файл пока в нем не встретится строка с непустыми колонками - * в количестве указанном в атрибуте min_column_quantity - * в результате выполнения курсор ресурса будет находится на последней незначимой строке - */ - protected function shiftToFirstValuableLine() - { - - $finish = false; - while (!$finish ) { - $this->current_line ++; - - $j = 0; - $row = $this->file->fgetcsv();; - if ($row === false) { - continue; - } - - for ($i = 1; $i <= count($row); $i++) { - // CustomVarDamp::dump($row[$i]); - - if ($row[$i - 1] <> '') { - $j++; - } - - if ($j >= $this->min_column_quantity) { - break 2; - } - } - } - // @todo - сделать опционально - // код для того что бы парсить первую строку, закомментировано как предполагается что первая значимая строка это заголовок - // $this->current_line --; -// $this->file->seek( $this->current_line ); - } - /** - * @return array - итоговый двумерный массив с результатом парсинга - * метод считывает с открытого файла данные построчно - */ public function read() { + parent::read(); - $return = []; - - // будем считать количество пустых строк подряд - при трех подряд - считаем что это конец файла и выходим - $empty_lines = 0; - while ( $empty_lines < 3 ) { - // прочтем строку из файла. Если там есть значения - то в ней массив, иначе - false - $row = $this->readRow( ); - - if ($row === false) { - //счетчик пустых строк - $empty_lines++; - continue; - } - // строка не пустая, имеем прочитанный массив значений - $this->current_line++; - if ($this->hasHeaderRow) { - // в файле есть заголовок, но он еще не назначен, назначим - if ($this->keys === NULL) { - $this->keys = array_values($row); - } - } - // если у нас установлен лимит, при его достижении прекращаем парсинг - if (($this->last_line) && ($this->current_line > $this->last_line)) { - break; - } - // обнуляем счетчик, так как считаюся пустые строки ПОДРЯД - $empty_lines = 0; - - $return[] = $row; - } - - return $return; + return $this->result; } - - /** - * @return array - одномерный массив результата парсинга строки - */ + protected function readRow( ) { - $row = $this->file->fgetcsv(); + $this->row = $this->file->fgetcsv(); + } - if (is_array($row)) { - // уберем нулевые колонки - $row = array_filter($row, function($val){ - return $val <> ''; - }); - // если есть заголовок, то перед конвертацией его нужно назначить - if ($this->hasHeaderRow && $this->keys !== NULL) { + protected function isEmptyRow(){ - if (count($this->keys) !== count($row)) { - throw new \Exception("Ошибка парсинга файла в строке # {$this->current_line}. Не соответсвие числа ключевых колонок (заголовка) - числу колонок с данными", 0, 1, $this->file->getBasename(), $this->current_line); - } + $is_empty = false; - $row = array_combine($this->keys, $row); - } - // попытаемся конвертировать прочитанные значения согласно конфигурации котнвертера значений - $row = $this->convert($row); - // обрежем массив к первой значимой колонке - if ( $this->first_column ) { + if ($this->row === false || $this->row === NULL ) { + return true; + } - $row = array_slice($row, $this->first_column); + $j = 0; + for ($i = 1; $i <= count( $this->row ); $i++) { + if ( $this->isEmptyColumn( $this->row[$i - 1] ) ) { + $j++; } - } - if (is_null($row)) - $row = false; - return $row; + if ( $j >= $this->min_column_quantity ) { + $is_empty = true; + break; + } + } + return $is_empty; } - + protected function isEmptyColumn( $val ){ + return $val == ''; + } } \ No newline at end of file diff --git a/vendor/yiisoft/multiparser/Parser.php b/vendor/yiisoft/multiparser/Parser.php index b07b93b..0b60829 100644 --- a/vendor/yiisoft/multiparser/Parser.php +++ b/vendor/yiisoft/multiparser/Parser.php @@ -8,27 +8,44 @@ namespace yii\multiparser; +//@todo - заменить read на parse +//@todo - xml - убрать из названий функций xml и array - это и так понятно + + +use common\components\CustomVarDamp; + abstract class Parser { public $converter_conf = []; protected $converter = NULL; + /** + * @var array - результирующий массив с отпарсенными значениями + */ + protected $result = []; + /** @var array - массив с заголовком, * */ public $keys = NULL; - public $hasHeaderRow = false; + /** @var bool + имеет ли файл заголовок который будет установлен ключами возвращемого массива*/ + public $has_header_row = false; /** @var экземляр SplFileObject читаемого файла */ public $file; + + public function setup() { + $this->setupConverter(); + } protected function setupConverter() { - if ($this->hasHeaderRow) { + if ( $this->has_header_row || $this->keys !== NULL ) { // если у файла есть заголовок, то в результате имеем ассоциативный массив $this->converter_conf['hasKey'] = 1; } diff --git a/vendor/yiisoft/multiparser/TableParser.php b/vendor/yiisoft/multiparser/TableParser.php new file mode 100644 index 0000000..c20b3b1 --- /dev/null +++ b/vendor/yiisoft/multiparser/TableParser.php @@ -0,0 +1,171 @@ +auto_detect_first_line) { + $this->shiftToFirstValuableLine(); + } + + // будем считать количество пустых строк подряд - при достижении $empty_lines_quantity - считаем что это конец файла и выходим + $empty_lines = 0; + while ( $empty_lines < $this->empty_lines_quantity ) { + // прочтем строку из файла + $this->readRow(); + + + + if ( $this->isEmptyRow() ) { + //счетчик пустых строк + $empty_lines++; + continue; + } + // уберем пустые колонки из ряда + $this->filterRow(); + + + $this->adjustRowToSettings( ); + + // строка не пустая, имеем прочитанный массив значений + $this->current_row_number++; + + // для первой строки утановим ключи из заголовка + $this->setKeysFromHeader(); + + // если у нас установлен лимит, при его достижении прекращаем парсинг + if ( $this->isLastLine() ) + break; + + // обнуляем счетчик, так как считаюся пустые строки ПОДРЯД + $empty_lines = 0; + + $this->result[] = $this->row; + } + + + } + + + /** + * определяет первую значимую строку, + * считывается файл пока в нем не встретится строка с непустыми колонками + * в количестве указанном в атрибуте min_column_quantity + * в результате выполнения $current_row_number будет находится на последней незначимой строке + */ + protected function shiftToFirstValuableLine() + { + do { + + $this->current_row_number ++; + $this->readRow(); + + } while( $this->isEmptyRow() ); + + // @todo - сделать опционально + // код для того что бы парсить первую строку, закомментировано как предполагается что первая значимая строка это заголовок + // $this->current_row_number --; +// $this->file->seek( $this->current_row_number ); + } + + /** + * @return array - одномерный массив результата парсинга строки + */ + protected function adjustRowToSettings( ) + { + // если есть заголовок, то перед конвертацией его нужно назначить + if ( $this->keys !== NULL ) { + + if (count($this->keys) !== count($this->row)) { + throw new \Exception("Ошибка парсинга файла в строке # {$this->current_row_number}. Не соответсвие числа ключевых колонок (заголовка) - числу колонок с данными", 0, 1, $this->file->getBasename(), $this->current_row_number); + } + + $this->row = array_combine($this->keys, $this->row); + } + + // попытаемся конвертировать прочитанные значения согласно конфигурации котнвертера значений + $this->row = $this->convert($this->row); + + // обрежем массив к первой значимой колонке + if ( $this->first_column ) { + + $this->row = array_slice($this->row, $this->first_column); + + } + + } + + protected function setKeysFromHeader(){ + if ( $this->has_header_row ) { + // в файле есть заголовок, но он еще не назначен - назначим + if ($this->keys === NULL) { + $this->keys = array_values( $this->row ); + } + } + } + protected function filterRow(){ + $this->row = array_filter( $this->row, function($val){ + return !$this->isEmptyColumn($val); + }); + } + protected function isLastLine(){ + + if ( ( $this->last_line ) && ( $this->current_row_number > $this->last_line ) ) { + return true; + } + return false; + } + +} \ No newline at end of file -- libgit2 0.21.4