shiftToFirstValuableLine(); // первый проход, строка прочитана в shiftToFirstValuableLine $first_circle = true; // будем считать количество пустых строк подряд - при достижении $empty_lines_quantity - считаем что это конец файла и выходим $empty_lines = 0; while ($empty_lines < $this->empty_lines_quantity) { // прочтем строку из файла, если это не первый проход if (!$first_circle){ $this->readRow(); } $first_circle = false; // уберем пустые колонки из ряда if ($this->keys === NULL) { $this->filterRow(); } if ($this->isEmptyRow()) { //счетчик пустых строк $empty_lines++; $this->current_row_number++; continue; } // запустим конвертирование $this->adjustRowToSettings(); // установим отпарсенную строку в итоговый массив результата $this->setResult(); // строка не пустая, имеем прочитанный массив значений $this->current_row_number++; // если у нас установлен лимит, при его достижении прекращаем парсинг if ($this->isLastLine()) break; // обнуляем счетчик, так как считаюся пустые строки ПОДРЯД $empty_lines = 0; } } /** * определяет первую значимую строку, * считывается файл пока в нем не встретится строка с непустыми колонками * или пока не дойдет до first_line * пропускает заголовок если он указан */ protected function shiftToFirstValuableLine() { // читаем пока не встретим значимую строку, или пока не дойдем до first_line do { $this->current_row_number++; $this->readRow(); } while ( $this->isEmptyRow() && ( $this->first_line < $this->current_row_number ) ); // если указан заголовок, то его мы тоже пропускаем (читаем далее) if( $this->has_header_row ) { $this->current_row_number++; $this->readRow(); } } /** * @return array - одномерный массив результата парсинга строки */ protected function adjustRowToSettings() { // если есть заголовок, то перед конвертацией его нужно назначить if ($this->keys !== NULL) { // adjust row to keys $this->adjustRowToKeys(); // назначим заголовок $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 isEmptyRow(){ $is_empty = false; if ( empty( $this->row ) ) { return true; } if ( count( $this->row ) < $this->min_column_quantity ) { return true; } $j = 0; for ($i = 1; $i <= count( $this->row ); $i++) { if ( !isset( $this->row[ $i - 1 ] ) ) { continue; } if ( $this->isEmptyColumn( $this->row[$i - 1] ) ) { $j++; } if ( $j >= $this->min_column_quantity ) { $is_empty = true; break; } } return $is_empty; } protected function filterRow() { // нет строки - нет фильтрации if ( empty( $this->row ) ) { return; } $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; } protected function adjustRowToKeys() { //уберем из ряда те колонки которых нет в ключах $this->row = array_intersect_key($this->row, $this->keys); $keys_count = count($this->keys); $column_count = count($this->row); if ($keys_count != $column_count) { // найдем колонки которых нет в ряде но есть ключах $arr_diff = array_diff_key($this->keys, $this->row); foreach ($arr_diff as $key => $value) { // колонки которых нет в ряде но есть ключах, добавим их с пустым значением $this->row[$key] = ''; } } } }