Commit 40ff24a1aa0f48138c496b2cc58fa0c2b5b69a2a

Authored by Mihail
1 parent 999b9326

refactor CsvParser, add CustomCsvParser

backend/components/parsers/CsvParser.php
1 1 <?php
2 2 /**
3   - * Created by PhpStorm.
4   - * User: Cibermag
5   - * Date: 26.08.2015
6   - * Time: 17:00
7   - */
8 3  
  4 + */
  5 +//@ todo add exceptions
9 6 namespace backend\components\parsers;
10 7  
11 8  
... ... @@ -17,64 +14,70 @@ class CsvParser
17 14 {
18 15  
19 16  
20   - /** @var bool */
  17 + /** @var bool
  18 + имеет ли файл заголовок который будет установлен ключами возвращемого массива*/
21 19 public $hasHeaderRow = false;
  20 + /** @var array - массив с заголовком,
  21 + * если не указан и установлено свойство $hasHeaderRow - будет определен автоматически */
  22 + public $keys;
22 23  
23   - /** @var resource */
  24 + /** @var экземляр SplFileObject читаемого файла */
24 25 public $file;
25 26  
26   - /** @var out encoding charset */
27   - public $out_charset = 'UTF-8';
28   - /** @var out encoding charset */
29   - public $in_charset = 'windows-1251';
30   - /** @var int - first line for parsing */
  27 + /** @var int - первая строка с которой начинать парсить */
31 28 public $first_line = 0;
32   - public $last_line = 10;
33 29  
34   - /** @var int - first column for parsing */
  30 + /** @var int - последняя строка до которой парсить
  31 + * если не указана, то парсинг происходит до конца файла*/
  32 + public $last_line = 0;
  33 +
  34 + /** @var int - первая колонка файла с которой начнется парсинг */
35 35 public $first_column = 0;
36 36  
37   - /** @var array - array of headers values */
38   - public $keys;
  37 + /** @var string - разделитель csv */
39 38 public $delimiter = ';';
40   - public $auto_detect_start_position = false;
  39 +
  40 + /** @var bool
  41 + нужно ли искать автоматически первоую значисмую строку (не пустая строка)
  42 + * иначе первая строка будет взята из аттрибута $first_line */
  43 + public $auto_detect_first_line = false;
  44 +
  45 + /** @var int - количество значимых колонок, что бы определить первую значимую строку
  46 + * используется при автоопределении первой строки*/
41 47 public $min_column_quantity = 5;
42 48  
43 49  
  50 + /**
  51 + метод устанвливает нужные настройки объекта SplFileObject, для работы с csv
  52 + */
44 53 public function setup()
45 54 {
46   -
47 55 $this->file->setCsvControl($this->delimiter);
48 56 $this->file->setFlags(\SplFileObject::READ_CSV);
49 57 $this->file->setFlags(\SplFileObject::SKIP_EMPTY);
50   -// $this->file->setFlags(\SplFileObject::READ_AHEAD);
51   -
52   - if ($this->auto_detect_start_position) {
53   - $this->first_line = $this->detectStartPosition();
  58 + if ($this->auto_detect_first_line) {
  59 + $this->shiftToFirstValuableLine();
54 60 }
55   - // CustomVarDamp::dumpAndDie($this);
56   -// echo $this->file->key();
57   -// $this->file->seek($this->first_line + 1);
58   -// echo $this->file->key();
59   -
60   -
61 61 }
62 62  
63   -
64   - protected function detectStartPosition()
  63 + /**
  64 + * определяет первую значимую строку,
  65 + * считывается файл пока в нем не встретится строка с непустыми колонками
  66 + * в количестве указанном в атрибуте min_column_quantity
  67 + * в результате выполнения курсор ресурса будет находится на последней незначимой строке
  68 + */
  69 + protected function shiftToFirstValuableLine()
65 70 {
66   - $first_line = 0;
67   - $find = false;
68   - while (!$find) {
69 71  
  72 + $finish = false;
  73 +
  74 + while (!$finish) {
70 75 $j = 0;
71 76 $row = $this->readRow();
72   -
73 77 if ($row === false) {
74 78 continue;
75 79 }
76 80  
77   - $first_line++;
78 81 for ($i = 1; $i <= count($row); $i++) {
79 82  
80 83 if ($row[$i - 1] <> '') {
... ... @@ -82,30 +85,25 @@ class CsvParser
82 85 }
83 86  
84 87 if ($j >= $this->min_column_quantity) {
85   - $find = true;
86   - break;
  88 + break 2;
87 89 }
88 90 }
89 91 }
90   -
91   - return $first_line;
92   -
93 92 }
94 93  
95 94 /**
96   - * @return array
97   - * @throws InvalidFileException
  95 + * @return array - итоговый двумерный массив с результатом парсинга
  96 + * метод считывает с открытого файла данные построчно
98 97 */
99 98 public function read()
100 99 {
101   - // @todo add comments
102 100 $return = [];
103   - //CustomVarDamp::dump(debug_print_backtrace(1,2));
104   - $line = 0;
  101 +
  102 + $current_line = 0;
105 103 $this->keys = NULL;
106   - CustomVarDamp::dump($this->file->key());
  104 +
107 105 while (($row = $this->readRow()) !== FALSE) {
108   - $line++;
  106 + $current_line++;
109 107  
110 108 if ($this->hasHeaderRow) {
111 109 if ($this->keys === NULL) {
... ... @@ -114,25 +112,25 @@ class CsvParser
114 112  
115 113 if (count($this->keys) !== count($row)) {
116 114 //
117   - Yii::warning("Invalid columns detected on line #$line .");
  115 + Yii::warning("Invalid columns detected on line #$current_line .");
118 116 return $return;
119 117 }
120 118  
121 119 $return[] = array_combine($this->keys, $row);
122 120 }
123   - } else {
  121 + }
  122 + else
  123 + {
124 124 $return[] = $row;
125 125 }
126   - if(($this->last_line) && ($line > $this->last_line)){
127   -// CustomVarDamp::dump($this->last_line);
128   -// CustomVarDamp::dump($line);
  126 + // если у нас установлен лимит, при его достижении прекращаем парсинг
  127 + if (($this->last_line) && ($current_line > $this->last_line)) {
129 128 break;
130 129 }
131 130  
132 131 }
133 132  
134 133 $this->closeHandler();
135   - //CustomVarDamp::dumpAndDie($return);
136 134 return $return;
137 135 }
138 136  
... ... @@ -142,20 +140,20 @@ class CsvParser
142 140 $this->file = NULL;
143 141 }
144 142  
  143 + /**
  144 + * @return array - одномерный массив результата парсинга строки
  145 + */
145 146 protected function readRow()
146   - // @todo add comments
147 147 {
148 148  
149 149 $row = $this->file->fgetcsv();
150   - //
151   - if (is_array($row)) {
152   - // $row = array_slice( $row, $this->first_column );
153   - $row = Encoder::encodeArray($this->in_charset, $this->out_charset, $row);
  150 + if (is_array($row) && $this->first_column) {
  151 +
  152 + $row = array_slice($row, $this->first_column);
  153 +
154 154 }
155 155 if (is_null($row))
156 156 $row = false;
157   -// if ($this->keys !== NULL)
158   -// @$clear_arr[3] = ValueFilter::pricefilter($clear_arr[3]);{}{}{}
159 157  
160 158 return $row;
161 159  
... ...
backend/components/parsers/CustomCsvParser.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: Cibermag
  5 + * Date: 04.09.2015
  6 + * Time: 16:07
  7 + */
  8 +
  9 +namespace backend\components\parsers;
  10 +
  11 +
  12 +class CustomCsvParser extends CsvParser {
  13 +
  14 + protected function readRow()
  15 + {
  16 +
  17 + $row = parent::readRow();
  18 +
  19 + if (is_array($row)) {
  20 +
  21 + $row = Encoder::encodeArray( Encoder::$in_charset, Encoder::$out_charset, $row );
  22 + }
  23 +
  24 + return $row;
  25 +
  26 + }
  27 +
  28 +}
0 29 \ No newline at end of file
... ...
backend/components/parsers/Encoder.php
... ... @@ -11,9 +11,10 @@ namespace backend\components\parsers;
11 11 // @todo add comments
12 12 class Encoder
13 13 {
14   - public static $in_charset;
15   - public static $out_charset;
16   -
  14 + /** @var out encoding charset */
  15 + public static $out_charset = 'UTF-8';
  16 + /** @var out encoding charset */
  17 + public static $in_charset = 'windows-1251';
17 18  
18 19 public static function encodeFile($in_charset, $out_charset, $filePath)
19 20 {
... ...
backend/components/parsers/ParserHandler.php
... ... @@ -39,20 +39,16 @@ class ParserHandler {
39 39  
40 40 public function run(){
41 41 if ($this->extension = 'csv'){
42   - $first_line = isset( $this->options->first_line )? $this->options->first_line : 0;
43   - $first_column = isset( $this->options->first_column )? $this->options->first_column : 0;
44 42  
45 43 $csvParser = Yii::createObject([
46   - 'class' => 'backend\components\parsers\CsvParser',
  44 + 'class' => 'backend\components\parsers\CustomCsvParser',
47 45 'file' => $this->fileObject,
48   - 'auto_detect_start_position' => true,
  46 + 'auto_detect_first_line' => true,
49 47 ]);
50   - //CustomVarDamp::dumpAndDie($csvParser);
51   - // $csvParser = new CsvParser( );
52   - $csvParser->setup( );
53 48  
54   -// CustomVarDamp::dumpAndDie($data);
55   - return $csvParser->read();;//
  49 + $csvParser->setup();
  50 +
  51 + return $csvParser->read();
56 52 };
57 53 }
58 54 }
... ...