Commit 40ff24a1aa0f48138c496b2cc58fa0c2b5b69a2a
1 parent
999b9326
refactor CsvParser, add CustomCsvParser
Showing
4 changed files
with
95 additions
and
72 deletions
Show diff stats
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 | ... | ... |
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 | } | ... | ... |