1e991822
Mihail
csv parser with e...
|
1
2
|
<?php
/**
|
1e991822
Mihail
csv parser with e...
|
3
|
|
40ff24a1
Mihail
refactor CsvParse...
|
4
|
*/
|
036717a1
Mihail
add error excepti...
|
5
|
namespace yii\multiparser;
|
93e39994
Mihail
fixed parser and ...
|
6
|
use common\components\CustomVarDamp;
|
dc10d651
Mihail
add value filter ...
|
7
|
|
1e991822
Mihail
csv parser with e...
|
8
|
|
474f35bf
Mihail
add DynamicFormHe...
|
9
10
11
12
|
/**
* Class CsvParser
* @package yii\multiparser
*/
|
37656b1f
Mihail
add parser interf...
|
13
|
class CsvParser implements ParserInterface
|
999b9326
Mihail
add detectStartPo...
|
14
|
{
|
1e991822
Mihail
csv parser with e...
|
15
|
|
1e991822
Mihail
csv parser with e...
|
16
|
|
40ff24a1
Mihail
refactor CsvParse...
|
17
18
|
/** @var bool
имеет ли файл заголовок который будет установлен ключами возвращемого массива*/
|
e55d56cc
Mihail
add draft version...
|
19
|
public $hasHeaderRow = false;
|
40ff24a1
Mihail
refactor CsvParse...
|
20
21
22
|
/** @var array - массив с заголовком,
* если не указан и установлено свойство $hasHeaderRow - будет определен автоматически */
public $keys;
|
1e991822
Mihail
csv parser with e...
|
23
|
|
40ff24a1
Mihail
refactor CsvParse...
|
24
|
/** @var экземляр SplFileObject читаемого файла */
|
e55d56cc
Mihail
add draft version...
|
25
|
public $file;
|
1e991822
Mihail
csv parser with e...
|
26
|
|
40ff24a1
Mihail
refactor CsvParse...
|
27
|
/** @var int - первая строка с которой начинать парсить */
|
e55d56cc
Mihail
add draft version...
|
28
|
public $first_line = 0;
|
1e991822
Mihail
csv parser with e...
|
29
|
|
40ff24a1
Mihail
refactor CsvParse...
|
30
31
32
33
34
|
/** @var int - последняя строка до которой парсить
* если не указана, то парсинг происходит до конца файла*/
public $last_line = 0;
/** @var int - первая колонка файла с которой начнется парсинг */
|
e55d56cc
Mihail
add draft version...
|
35
|
public $first_column = 0;
|
b13b1c83
Mihail
final version par...
|
36
|
|
40ff24a1
Mihail
refactor CsvParse...
|
37
|
/** @var string - разделитель csv */
|
e55d56cc
Mihail
add draft version...
|
38
|
public $delimiter = ';';
|
40ff24a1
Mihail
refactor CsvParse...
|
39
40
41
42
43
44
45
46
|
/** @var bool
нужно ли искать автоматически первоую значисмую строку (не пустая строка)
* иначе первая строка будет взята из аттрибута $first_line */
public $auto_detect_first_line = false;
/** @var int - количество значимых колонок, что бы определить первую значимую строку
* используется при автоопределении первой строки*/
|
e55d56cc
Mihail
add draft version...
|
47
|
public $min_column_quantity = 5;
|
dc10d651
Mihail
add value filter ...
|
48
|
|
74072a2a
Mihail
add first version...
|
49
50
51
52
|
/** @var array - конфигурация конвертера значений */
public $converter_conf = [];
/** @var array - конвертер созданный по конфигурации */
public $converter = NULL;
|
5c710262
Mihail
edit csv parser -...
|
53
|
|
474f35bf
Mihail
add DynamicFormHe...
|
54
|
|
40ff24a1
Mihail
refactor CsvParse...
|
55
|
/**
|
74072a2a
Mihail
add first version...
|
56
|
* метод устанвливает нужные настройки объекта SplFileObject, для работы с csv
|
40ff24a1
Mihail
refactor CsvParse...
|
57
|
*/
|
e55d56cc
Mihail
add draft version...
|
58
59
|
public function setup()
{
|
999b9326
Mihail
add detectStartPo...
|
60
61
62
|
$this->file->setCsvControl($this->delimiter);
$this->file->setFlags(\SplFileObject::READ_CSV);
$this->file->setFlags(\SplFileObject::SKIP_EMPTY);
|
aa518ad3
Mihail
finishing with co...
|
63
|
|
40ff24a1
Mihail
refactor CsvParse...
|
64
65
|
if ($this->auto_detect_first_line) {
$this->shiftToFirstValuableLine();
|
e55d56cc
Mihail
add draft version...
|
66
|
}
|
74072a2a
Mihail
add first version...
|
67
68
|
$this->setupConverter();
|
1e991822
Mihail
csv parser with e...
|
69
70
|
}
|
40ff24a1
Mihail
refactor CsvParse...
|
71
|
/**
|
74072a2a
Mihail
add first version...
|
72
73
74
75
76
|
* устанавливает конвертер значений согласно конфигурационным настройкам
*/
public function setupConverter()
{
if (!count($this->converter_conf)) {
|
d21c5c5f
Mihail
XMLparser - read ...
|
77
|
$this->converter = new Converter();
|
74072a2a
Mihail
add first version...
|
78
79
80
81
|
if ($this->hasHeaderRow) {
// если у файла есть заголовок, то в результате имеем ассоциативный массив
$this->converter_conf['hasKey'] = 1;
}
|
8894c93a
Mihail
add Importers fil...
|
82
|
//$this->converter->configuration = $this->converter_conf;
|
aa518ad3
Mihail
finishing with co...
|
83
|
|
74072a2a
Mihail
add first version...
|
84
85
86
87
88
|
}
}
/**
|
40ff24a1
Mihail
refactor CsvParse...
|
89
90
91
92
93
94
|
* определяет первую значимую строку,
* считывается файл пока в нем не встретится строка с непустыми колонками
* в количестве указанном в атрибуте min_column_quantity
* в результате выполнения курсор ресурса будет находится на последней незначимой строке
*/
protected function shiftToFirstValuableLine()
|
e55d56cc
Mihail
add draft version...
|
95
|
{
|
e55d56cc
Mihail
add draft version...
|
96
|
|
40ff24a1
Mihail
refactor CsvParse...
|
97
98
99
|
$finish = false;
while (!$finish) {
|
999b9326
Mihail
add detectStartPo...
|
100
|
$j = 0;
|
93e39994
Mihail
fixed parser and ...
|
101
|
$row = $this->file->fgetcsv();;
|
999b9326
Mihail
add detectStartPo...
|
102
103
|
if ($row === false) {
continue;
|
e55d56cc
Mihail
add draft version...
|
104
|
}
|
999b9326
Mihail
add detectStartPo...
|
105
|
|
999b9326
Mihail
add detectStartPo...
|
106
107
108
109
110
111
112
|
for ($i = 1; $i <= count($row); $i++) {
if ($row[$i - 1] <> '') {
$j++;
}
if ($j >= $this->min_column_quantity) {
|
40ff24a1
Mihail
refactor CsvParse...
|
113
|
break 2;
|
999b9326
Mihail
add detectStartPo...
|
114
|
}
|
e55d56cc
Mihail
add draft version...
|
115
116
|
}
}
|
e55d56cc
Mihail
add draft version...
|
117
|
}
|
1e991822
Mihail
csv parser with e...
|
118
119
|
/**
|
40ff24a1
Mihail
refactor CsvParse...
|
120
121
|
* @return array - итоговый двумерный массив с результатом парсинга
* метод считывает с открытого файла данные построчно
|
1e991822
Mihail
csv parser with e...
|
122
123
124
|
*/
public function read()
{
|
aa518ad3
Mihail
finishing with co...
|
125
|
|
1e991822
Mihail
csv parser with e...
|
126
|
$return = [];
|
40ff24a1
Mihail
refactor CsvParse...
|
127
128
|
$current_line = 0;
|
01746976
Mihail
fix errors with w...
|
129
130
131
132
|
// будем считать количество пустых строк подряд - при трех подряд - считаем что это конец файла и выходим
$empty_lines = 0;
while ( $empty_lines < 3 ) {
// прочтем строку из файла. Если там есть значения - то в ней массив, иначе - false
|
93e39994
Mihail
fixed parser and ...
|
133
|
$row = $this->readRow( $current_line );
|
40ff24a1
Mihail
refactor CsvParse...
|
134
|
|
01746976
Mihail
fix errors with w...
|
135
136
137
138
139
140
|
if ($row === false) {
//счетчик пустых строк
$empty_lines++;
continue;
}
// строка не пустая, имеем прочитанный массив значений
|
40ff24a1
Mihail
refactor CsvParse...
|
141
|
$current_line++;
|
1e991822
Mihail
csv parser with e...
|
142
|
if ($this->hasHeaderRow) {
|
93e39994
Mihail
fixed parser and ...
|
143
|
// в файле есть заголовок, но он еще не назначен, назначим
|
dc10d651
Mihail
add value filter ...
|
144
145
|
if ($this->keys === NULL) {
$this->keys = array_values($row);
|
1e991822
Mihail
csv parser with e...
|
146
|
}
|
1e991822
Mihail
csv parser with e...
|
147
|
}
|
40ff24a1
Mihail
refactor CsvParse...
|
148
149
|
// если у нас установлен лимит, при его достижении прекращаем парсинг
if (($this->last_line) && ($current_line > $this->last_line)) {
|
999b9326
Mihail
add detectStartPo...
|
150
151
|
break;
}
|
01746976
Mihail
fix errors with w...
|
152
153
|
// обнуляем счетчик, так как считаюся пустые строки ПОДРЯД
$empty_lines = 0;
|
93e39994
Mihail
fixed parser and ...
|
154
155
|
$return[] = $row;
|
1e991822
Mihail
csv parser with e...
|
156
157
158
|
}
$this->closeHandler();
|
1e991822
Mihail
csv parser with e...
|
159
160
161
|
return $return;
}
|
2957209c
Mihail
csv parser - add ...
|
162
|
|
dfeb2d10
Mihail
edit universal cs...
|
163
|
protected function closeHandler()
|
1e991822
Mihail
csv parser with e...
|
164
|
{
|
2957209c
Mihail
csv parser - add ...
|
165
|
$this->file = NULL;
|
1e991822
Mihail
csv parser with e...
|
166
167
|
}
|
40ff24a1
Mihail
refactor CsvParse...
|
168
169
170
|
/**
* @return array - одномерный массив результата парсинга строки
*/
|
93e39994
Mihail
fixed parser and ...
|
171
|
protected function readRow( $current_line )
|
1e991822
Mihail
csv parser with e...
|
172
|
{
|
999b9326
Mihail
add detectStartPo...
|
173
|
$row = $this->file->fgetcsv();
|
74072a2a
Mihail
add first version...
|
174
|
if (is_array($row)) {
|
93e39994
Mihail
fixed parser and ...
|
175
176
177
178
179
180
181
182
183
184
185
|
// если есть заголовок, то перед конвертацией его нужно назначить
if ($this->hasHeaderRow && $this->keys !== NULL) {
if (count($this->keys) !== count($row)) {
//
throw new \ErrorException("Ошибка парсинга файла в строке # {$current_line}. Не соответсвие числа ключевых колонок (заголовка) - числу колонок с данными", 0, 1, $this->file->getBasename(), $current_line);
}
$row = array_combine($this->keys, $row);
}
// попытаемся конвертировать прочитанные значения согласно конфигурации котнвертера значений
|
74072a2a
Mihail
add first version...
|
186
|
$row = $this->convert($row);
|
93e39994
Mihail
fixed parser and ...
|
187
188
|
// обрежем массив к первой значимой колонке
if ( $this->first_column ) {
|
40ff24a1
Mihail
refactor CsvParse...
|
189
|
|
74072a2a
Mihail
add first version...
|
190
|
$row = array_slice($row, $this->first_column);
|
40ff24a1
Mihail
refactor CsvParse...
|
191
|
|
74072a2a
Mihail
add first version...
|
192
|
}
|
dfeb2d10
Mihail
edit universal cs...
|
193
|
}
|
999b9326
Mihail
add detectStartPo...
|
194
195
|
if (is_null($row))
$row = false;
|
dc10d651
Mihail
add value filter ...
|
196
|
|
dfeb2d10
Mihail
edit universal cs...
|
197
|
return $row;
|
1e991822
Mihail
csv parser with e...
|
198
199
200
|
}
|
74072a2a
Mihail
add first version...
|
201
202
203
204
205
206
207
208
209
210
|
/**
* @param $arr
* @return mixed
* преобразовует значения прочитанного массива в нужные типы, согласно конфигурации конвертера
*/
protected function convert($arr)
{
$result = $arr;
$converter = $this->converter;
|
74072a2a
Mihail
add first version...
|
211
212
|
if (!is_null($converter)) {
|
8894c93a
Mihail
add Importers fil...
|
213
|
$result = $converter->convertByConfiguration( $arr, $this->converter_conf );
|
74072a2a
Mihail
add first version...
|
214
215
216
217
218
219
220
|
}
return $result;
}
|
1e991822
Mihail
csv parser with e...
|
221
222
|
}
|