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
|
/**
* Class CsvParser
* @package yii\multiparser
|
6215a30d
Mihail
add converter int...
|
12
|
* @todo - перевести на анг. яз.
|
474f35bf
Mihail
add DynamicFormHe...
|
13
|
*/
|
6215a30d
Mihail
add converter int...
|
14
|
class CsvParser extends Parser
|
999b9326
Mihail
add detectStartPo...
|
15
|
{
|
40ff24a1
Mihail
refactor CsvParse...
|
16
17
|
/** @var bool
имеет ли файл заголовок который будет установлен ключами возвращемого массива*/
|
e55d56cc
Mihail
add draft version...
|
18
|
public $hasHeaderRow = false;
|
40ff24a1
Mihail
refactor CsvParse...
|
19
20
|
/** @var array - массив с заголовком,
* если не указан и установлено свойство $hasHeaderRow - будет определен автоматически */
|
90ff40df
Mihail
fixed issue with ...
|
21
|
// public $keys; - определен в родительском классе
|
1e991822
Mihail
csv parser with e...
|
22
|
|
40ff24a1
Mihail
refactor CsvParse...
|
23
|
/** @var int - первая строка с которой начинать парсить */
|
e55d56cc
Mihail
add draft version...
|
24
|
public $first_line = 0;
|
1e991822
Mihail
csv parser with e...
|
25
|
|
40ff24a1
Mihail
refactor CsvParse...
|
26
27
28
29
30
|
/** @var int - последняя строка до которой парсить
* если не указана, то парсинг происходит до конца файла*/
public $last_line = 0;
/** @var int - первая колонка файла с которой начнется парсинг */
|
e55d56cc
Mihail
add draft version...
|
31
|
public $first_column = 0;
|
b13b1c83
Mihail
final version par...
|
32
|
|
40ff24a1
Mihail
refactor CsvParse...
|
33
|
/** @var string - разделитель csv */
|
e55d56cc
Mihail
add draft version...
|
34
|
public $delimiter = ';';
|
40ff24a1
Mihail
refactor CsvParse...
|
35
36
37
38
39
40
41
42
|
/** @var bool
нужно ли искать автоматически первоую значисмую строку (не пустая строка)
* иначе первая строка будет взята из аттрибута $first_line */
public $auto_detect_first_line = false;
/** @var int - количество значимых колонок, что бы определить первую значимую строку
* используется при автоопределении первой строки*/
|
e55d56cc
Mihail
add draft version...
|
43
|
public $min_column_quantity = 5;
|
dc10d651
Mihail
add value filter ...
|
44
|
|
6215a30d
Mihail
add converter int...
|
45
46
47
48
|
// /** @var array - конфигурация конвертера значений */
// public $converter_conf = [];
// /** @var array - конвертер созданный по конфигурации */
// public $converter = NULL;
|
d3cf6647
Mihail
add multiply pric...
|
49
50
|
/** @var int - текущая строка */
private $current_line = 0;
|
5c710262
Mihail
edit csv parser -...
|
51
|
|
474f35bf
Mihail
add DynamicFormHe...
|
52
|
|
40ff24a1
Mihail
refactor CsvParse...
|
53
|
/**
|
74072a2a
Mihail
add first version...
|
54
|
* метод устанвливает нужные настройки объекта SplFileObject, для работы с csv
|
40ff24a1
Mihail
refactor CsvParse...
|
55
|
*/
|
e55d56cc
Mihail
add draft version...
|
56
57
|
public function setup()
{
|
999b9326
Mihail
add detectStartPo...
|
58
59
60
|
$this->file->setCsvControl($this->delimiter);
$this->file->setFlags(\SplFileObject::READ_CSV);
$this->file->setFlags(\SplFileObject::SKIP_EMPTY);
|
aa518ad3
Mihail
finishing with co...
|
61
|
|
40ff24a1
Mihail
refactor CsvParse...
|
62
63
|
if ($this->auto_detect_first_line) {
$this->shiftToFirstValuableLine();
|
e55d56cc
Mihail
add draft version...
|
64
|
}
|
aa518ad3
Mihail
finishing with co...
|
65
|
|
6215a30d
Mihail
add converter int...
|
66
|
parent::setup();
|
74072a2a
Mihail
add first version...
|
67
|
|
6215a30d
Mihail
add converter int...
|
68
|
}
|
74072a2a
Mihail
add first version...
|
69
|
/**
|
40ff24a1
Mihail
refactor CsvParse...
|
70
71
72
73
74
75
|
* определяет первую значимую строку,
* считывается файл пока в нем не встретится строка с непустыми колонками
* в количестве указанном в атрибуте min_column_quantity
* в результате выполнения курсор ресурса будет находится на последней незначимой строке
*/
protected function shiftToFirstValuableLine()
|
e55d56cc
Mihail
add draft version...
|
76
|
{
|
e55d56cc
Mihail
add draft version...
|
77
|
|
40ff24a1
Mihail
refactor CsvParse...
|
78
|
$finish = false;
|
2cdc93f0
Mihail
add crud models f...
|
79
|
while (!$finish ) {
|
d3cf6647
Mihail
add multiply pric...
|
80
81
|
$this->current_line ++;
|
999b9326
Mihail
add detectStartPo...
|
82
|
$j = 0;
|
93e39994
Mihail
fixed parser and ...
|
83
|
$row = $this->file->fgetcsv();;
|
999b9326
Mihail
add detectStartPo...
|
84
85
|
if ($row === false) {
continue;
|
e55d56cc
Mihail
add draft version...
|
86
|
}
|
999b9326
Mihail
add detectStartPo...
|
87
|
|
999b9326
Mihail
add detectStartPo...
|
88
|
for ($i = 1; $i <= count($row); $i++) {
|
0084d336
Administrator
Importers CRUD
|
89
|
// CustomVarDamp::dump($row[$i]);
|
999b9326
Mihail
add detectStartPo...
|
90
91
92
93
94
95
|
if ($row[$i - 1] <> '') {
$j++;
}
if ($j >= $this->min_column_quantity) {
|
40ff24a1
Mihail
refactor CsvParse...
|
96
|
break 2;
|
999b9326
Mihail
add detectStartPo...
|
97
|
}
|
e55d56cc
Mihail
add draft version...
|
98
99
|
}
}
|
2cdc93f0
Mihail
add crud models f...
|
100
101
102
103
|
// @todo - сделать опционально
// код для того что бы парсить первую строку, закомментировано как предполагается что первая значимая строка это заголовок
// $this->current_line --;
// $this->file->seek( $this->current_line );
|
e55d56cc
Mihail
add draft version...
|
104
|
}
|
1e991822
Mihail
csv parser with e...
|
105
106
|
/**
|
40ff24a1
Mihail
refactor CsvParse...
|
107
108
|
* @return array - итоговый двумерный массив с результатом парсинга
* метод считывает с открытого файла данные построчно
|
1e991822
Mihail
csv parser with e...
|
109
110
111
|
*/
public function read()
{
|
aa518ad3
Mihail
finishing with co...
|
112
|
|
1e991822
Mihail
csv parser with e...
|
113
|
$return = [];
|
40ff24a1
Mihail
refactor CsvParse...
|
114
|
|
01746976
Mihail
fix errors with w...
|
115
116
117
118
|
// будем считать количество пустых строк подряд - при трех подряд - считаем что это конец файла и выходим
$empty_lines = 0;
while ( $empty_lines < 3 ) {
// прочтем строку из файла. Если там есть значения - то в ней массив, иначе - false
|
d3cf6647
Mihail
add multiply pric...
|
119
|
$row = $this->readRow( );
|
40ff24a1
Mihail
refactor CsvParse...
|
120
|
|
01746976
Mihail
fix errors with w...
|
121
122
123
124
125
126
|
if ($row === false) {
//счетчик пустых строк
$empty_lines++;
continue;
}
// строка не пустая, имеем прочитанный массив значений
|
d3cf6647
Mihail
add multiply pric...
|
127
|
$this->current_line++;
|
1e991822
Mihail
csv parser with e...
|
128
|
if ($this->hasHeaderRow) {
|
93e39994
Mihail
fixed parser and ...
|
129
|
// в файле есть заголовок, но он еще не назначен, назначим
|
dc10d651
Mihail
add value filter ...
|
130
131
|
if ($this->keys === NULL) {
$this->keys = array_values($row);
|
1e991822
Mihail
csv parser with e...
|
132
|
}
|
1e991822
Mihail
csv parser with e...
|
133
|
}
|
40ff24a1
Mihail
refactor CsvParse...
|
134
|
// если у нас установлен лимит, при его достижении прекращаем парсинг
|
d3cf6647
Mihail
add multiply pric...
|
135
|
if (($this->last_line) && ($this->current_line > $this->last_line)) {
|
999b9326
Mihail
add detectStartPo...
|
136
137
|
break;
}
|
01746976
Mihail
fix errors with w...
|
138
139
|
// обнуляем счетчик, так как считаюся пустые строки ПОДРЯД
$empty_lines = 0;
|
93e39994
Mihail
fixed parser and ...
|
140
141
|
$return[] = $row;
|
1e991822
Mihail
csv parser with e...
|
142
143
|
}
|
1e991822
Mihail
csv parser with e...
|
144
145
|
return $return;
}
|
95c167d6
Mihail
add managing with...
|
146
|
|
1e991822
Mihail
csv parser with e...
|
147
|
|
40ff24a1
Mihail
refactor CsvParse...
|
148
149
150
|
/**
* @return array - одномерный массив результата парсинга строки
*/
|
d3cf6647
Mihail
add multiply pric...
|
151
|
protected function readRow( )
|
1e991822
Mihail
csv parser with e...
|
152
|
{
|
999b9326
Mihail
add detectStartPo...
|
153
|
$row = $this->file->fgetcsv();
|
706a1491
Mihail
add form, model a...
|
154
|
|
74072a2a
Mihail
add first version...
|
155
|
if (is_array($row)) {
|
706a1491
Mihail
add form, model a...
|
156
157
158
159
|
// уберем нулевые колонки
$row = array_filter($row, function($val){
return $val <> '';
});
|
93e39994
Mihail
fixed parser and ...
|
160
161
162
163
|
// если есть заголовок, то перед конвертацией его нужно назначить
if ($this->hasHeaderRow && $this->keys !== NULL) {
if (count($this->keys) !== count($row)) {
|
95c167d6
Mihail
add managing with...
|
164
|
throw new \Exception("Ошибка парсинга файла в строке # {$this->current_line}. Не соответсвие числа ключевых колонок (заголовка) - числу колонок с данными", 0, 1, $this->file->getBasename(), $this->current_line);
|
93e39994
Mihail
fixed parser and ...
|
165
166
167
168
169
|
}
$row = array_combine($this->keys, $row);
}
// попытаемся конвертировать прочитанные значения согласно конфигурации котнвертера значений
|
74072a2a
Mihail
add first version...
|
170
|
$row = $this->convert($row);
|
93e39994
Mihail
fixed parser and ...
|
171
172
|
// обрежем массив к первой значимой колонке
if ( $this->first_column ) {
|
40ff24a1
Mihail
refactor CsvParse...
|
173
|
|
74072a2a
Mihail
add first version...
|
174
|
$row = array_slice($row, $this->first_column);
|
40ff24a1
Mihail
refactor CsvParse...
|
175
|
|
74072a2a
Mihail
add first version...
|
176
|
}
|
dfeb2d10
Mihail
edit universal cs...
|
177
|
}
|
999b9326
Mihail
add detectStartPo...
|
178
179
|
if (is_null($row))
$row = false;
|
dc10d651
Mihail
add value filter ...
|
180
|
|
dfeb2d10
Mihail
edit universal cs...
|
181
|
return $row;
|
1e991822
Mihail
csv parser with e...
|
182
183
184
|
}
|
1e991822
Mihail
csv parser with e...
|
185
186
|
}
|