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