8e128526
Mihail
add xlsx parser
|
1
2
3
4
5
6
7
8
|
<?php
/**
* Created by PhpStorm.
* User: Tsurkanov
* Date: 22.10.2015
* Time: 15:53
*/
|
d0261fd1
Mihail
fixed namespace i...
|
9
|
namespace yii\multiparser;
|
8e128526
Mihail
add xlsx parser
|
10
11
|
|
a684f314
Mihail
add adjustRowToKe...
|
12
13
|
abstract class TableParser extends Parser
{
|
8e128526
Mihail
add xlsx parser
|
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
/**
* @var array - текущий отпарсенный ряд
*/
protected $row = [];
/** @var int - первая строка с которой начинать парсить */
public $first_line = 0;
/** @var int - последняя строка до которой парсить
* если не указана, то парсинг происходит до конца файла*/
public $last_line = 0;
/** @var int - первая колонка файла с которой начнется парсинг */
public $first_column = 0;
/** @var bool
нужно ли искать автоматически первоую значисмую строку (не пустая строка)
* иначе первая строка будет взята из аттрибута $first_line */
public $auto_detect_first_line = false;
/** @var int - количество значимых колонок, что бы определить первую значимую строку
* используется при автоопределении первой строки*/
public $min_column_quantity = 5;
/** @var int - количество пустых строк, что бы определить конец файла,
|
a684f314
Mihail
add adjustRowToKe...
|
41
|
* такое количеество подряд пустых строк считается концом файла*/
|
8e128526
Mihail
add xlsx parser
|
42
43
44
45
46
47
48
49
50
51
52
53
54
|
public $empty_lines_quantity = 3;
/** @var int - номер текущей строки парсера */
protected $current_row_number = 0;
protected abstract function isEmptyRow();
protected abstract function isEmptyColumn($column_value);
protected abstract function readRow();
|
d1fac7a9
Mihail
add parsing sheet...
|
55
56
|
protected abstract function setResult();
|
8e128526
Mihail
add xlsx parser
|
57
58
59
60
61
62
63
64
65
|
public function read()
{
if ($this->auto_detect_first_line) {
$this->shiftToFirstValuableLine();
}
// будем считать количество пустых строк подряд - при достижении $empty_lines_quantity - считаем что это конец файла и выходим
$empty_lines = 0;
|
a684f314
Mihail
add adjustRowToKe...
|
66
|
while ($empty_lines < $this->empty_lines_quantity) {
|
8e128526
Mihail
add xlsx parser
|
67
68
69
|
// прочтем строку из файла
$this->readRow();
|
a684f314
Mihail
add adjustRowToKe...
|
70
|
if ($this->isEmptyRow()) {
|
8e128526
Mihail
add xlsx parser
|
71
|
//счетчик пустых строк
|
d1fac7a9
Mihail
add parsing sheet...
|
72
|
//CustomVarDamp::dump($this->current_row_number);
|
8e128526
Mihail
add xlsx parser
|
73
74
75
76
|
$empty_lines++;
continue;
}
|
58f734e6
Mihail
fixed issue with ...
|
77
|
// уберем пустые колонки из ряда
|
a684f314
Mihail
add adjustRowToKe...
|
78
79
80
81
|
if ($this->keys === NULL) {
$this->filterRow();
}
|
58f734e6
Mihail
fixed issue with ...
|
82
|
|
a684f314
Mihail
add adjustRowToKe...
|
83
|
$this->adjustRowToSettings();
|
8e128526
Mihail
add xlsx parser
|
84
85
86
87
88
|
// строка не пустая, имеем прочитанный массив значений
$this->current_row_number++;
// для первой строки утановим ключи из заголовка
|
a684f314
Mihail
add adjustRowToKe...
|
89
|
if (!$this->setKeysFromHeader()) {
|
d1fac7a9
Mihail
add parsing sheet...
|
90
91
92
|
$this->setResult();
}
|
8e128526
Mihail
add xlsx parser
|
93
94
|
// если у нас установлен лимит, при его достижении прекращаем парсинг
|
a684f314
Mihail
add adjustRowToKe...
|
95
|
if ($this->isLastLine())
|
8e128526
Mihail
add xlsx parser
|
96
97
98
99
100
|
break;
// обнуляем счетчик, так как считаюся пустые строки ПОДРЯД
$empty_lines = 0;
|
8e128526
Mihail
add xlsx parser
|
101
102
|
}
|
8e128526
Mihail
add xlsx parser
|
103
|
}
|
a684f314
Mihail
add adjustRowToKe...
|
104
|
|
8e128526
Mihail
add xlsx parser
|
105
106
107
108
109
110
111
112
|
/**
* определяет первую значимую строку,
* считывается файл пока в нем не встретится строка с непустыми колонками
* в количестве указанном в атрибуте min_column_quantity
* в результате выполнения $current_row_number будет находится на последней незначимой строке
*/
protected function shiftToFirstValuableLine()
{
|
a684f314
Mihail
add adjustRowToKe...
|
113
|
do {
|
8e128526
Mihail
add xlsx parser
|
114
|
|
f6e54131
Mihail
fixed keys and he...
|
115
|
$this->current_row_number++;
|
8e128526
Mihail
add xlsx parser
|
116
117
|
$this->readRow();
|
a684f314
Mihail
add adjustRowToKe...
|
118
|
} while ($this->isEmptyRow());
|
8e128526
Mihail
add xlsx parser
|
119
120
121
122
123
124
125
126
127
128
|
// @todo - сделать опционально
// код для того что бы парсить первую строку, закомментировано как предполагается что первая значимая строка это заголовок
// $this->current_row_number --;
// $this->file->seek( $this->current_row_number );
}
/**
* @return array - одномерный массив результата парсинга строки
*/
|
a684f314
Mihail
add adjustRowToKe...
|
129
|
protected function adjustRowToSettings()
|
8e128526
Mihail
add xlsx parser
|
130
131
|
{
|
a684f314
Mihail
add adjustRowToKe...
|
132
133
134
135
136
137
138
|
// если есть заголовок, то перед конвертацией его нужно назначить
if ($this->keys !== NULL) {
// adjust row to keys
$this->adjustRowToKeys();
// назначим заголовок
$this->row = array_combine($this->keys, $this->row);
}
|
8e128526
Mihail
add xlsx parser
|
139
|
|
a684f314
Mihail
add adjustRowToKe...
|
140
141
|
// попытаемся конвертировать прочитанные значения согласно конфигурации котнвертера значений
$this->row = $this->convert($this->row);
|
8e128526
Mihail
add xlsx parser
|
142
|
|
a684f314
Mihail
add adjustRowToKe...
|
143
144
|
// обрежем массив к первой значимой колонке
if ($this->first_column) {
|
8e128526
Mihail
add xlsx parser
|
145
|
|
a684f314
Mihail
add adjustRowToKe...
|
146
|
$this->row = array_slice($this->row, $this->first_column);
|
8e128526
Mihail
add xlsx parser
|
147
|
|
a684f314
Mihail
add adjustRowToKe...
|
148
|
}
|
8e128526
Mihail
add xlsx parser
|
149
150
151
|
}
|
a684f314
Mihail
add adjustRowToKe...
|
152
153
154
|
protected function setKeysFromHeader()
{
if ($this->has_header_row) {
|
8e128526
Mihail
add xlsx parser
|
155
156
|
// в файле есть заголовок, но он еще не назначен - назначим
if ($this->keys === NULL) {
|
a684f314
Mihail
add adjustRowToKe...
|
157
|
$this->keys = array_values($this->row);
|
d1fac7a9
Mihail
add parsing sheet...
|
158
|
return true;
|
8e128526
Mihail
add xlsx parser
|
159
160
|
}
}
|
d1fac7a9
Mihail
add parsing sheet...
|
161
|
return false;
|
8e128526
Mihail
add xlsx parser
|
162
163
|
}
|
a684f314
Mihail
add adjustRowToKe...
|
164
165
|
protected function filterRow()
{
|
cd8b9f70
Mihail
add cleanUp metho...
|
166
|
// если есть заголовок - все значения нужны, не фильтруем
|
a684f314
Mihail
add adjustRowToKe...
|
167
|
if ($this->has_header_row || !is_array($this->row)) {
|
d1fac7a9
Mihail
add parsing sheet...
|
168
169
|
return;
}
|
a684f314
Mihail
add adjustRowToKe...
|
170
|
$this->row = array_filter($this->row, function ($val) {
|
8e128526
Mihail
add xlsx parser
|
171
172
|
return !$this->isEmptyColumn($val);
});
|
8e128526
Mihail
add xlsx parser
|
173
174
|
}
|
a684f314
Mihail
add adjustRowToKe...
|
175
176
|
protected function isLastLine()
{
|
8e128526
Mihail
add xlsx parser
|
177
|
|
a684f314
Mihail
add adjustRowToKe...
|
178
|
if (($this->last_line) && ($this->current_row_number > $this->last_line)) {
|
8e128526
Mihail
add xlsx parser
|
179
180
181
182
183
|
return true;
}
return false;
}
|
a684f314
Mihail
add adjustRowToKe...
|
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
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] = '';
}
}
}
|
8e128526
Mihail
add xlsx parser
|
201
|
}
|