Blame view

lib/TableParser.php 8.1 KB
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
      /**
       * @var array - текущий отпарсенный ряд
a3b2aa93   Mihail   change meaning of...
18
19
20
       *если есть ключи, то колонки с пустыми значениями будут пропускаться (из ряда такие значения будут удаляться),
       * например если в файле вторая колонка пустая то она будет удалена
       * в остальных случаях парсятся все колонки (не проверяется - пустая ли колонка) и попадёт в итоговый массив
8e128526   Mihail   add xlsx parser
21
22
23
       */
      protected $row = [];
  
a3b2aa93   Mihail   change meaning of...
24
25
26
27
28
      /** @var int - первая строка с которой начинать парсить
       * эта строка будет считаться первой значимой строкой
       * если установлен аттрибут $has_header_row,
       * тогда следующая строка будет считаться заголовком и будет пропущена
       */
8e128526   Mihail   add xlsx parser
29
30
31
32
33
34
35
36
37
38
39
      public $first_line = 0;
  
      /** @var int - последняя строка до которой  парсить
       * если не указана, то парсинг происходит до конца файла*/
      public $last_line = 0;
  
      /** @var int - первая колонка файла с которой начнется парсинг */
      public $first_column = 0;
  
  
      /** @var bool
a3b2aa93   Mihail   change meaning of...
40
41
42
43
44
       * имеет ли файл заголовок в первой значимой строке
       * true - первая значимая строка будет пропущена
       */
      public $has_header_row = true;
  
8e128526   Mihail   add xlsx parser
45
46
47
48
49
  
      /** @var int - количество значимых колонок, что бы определить первую значимую строку
       * используется при автоопределении первой строки*/
      public $min_column_quantity = 5;
      /** @var int - количество пустых строк, что бы определить конец файла,
a684f314   Mihail   add adjustRowToKe...
50
       * такое количеество подряд пустых строк считается концом файла*/
8e128526   Mihail   add xlsx parser
51
52
53
54
55
56
57
      public $empty_lines_quantity = 3;
  
  
      /** @var int - номер текущей строки парсера */
      protected $current_row_number = 0;
  
  
8e128526   Mihail   add xlsx parser
58
59
60
61
      protected abstract function isEmptyColumn($column_value);
  
      protected abstract function readRow();
  
d1fac7a9   Mihail   add parsing sheet...
62
63
      protected abstract function setResult();
  
8e128526   Mihail   add xlsx parser
64
65
66
  
      public function read()
      {
61323a64   Mihail   redid read method...
67
          // первый проход
a3b2aa93   Mihail   change meaning of...
68
          $first_circle = true;
61323a64   Mihail   redid read method...
69
          $this->current_row_number = 1;
8e128526   Mihail   add xlsx parser
70
71
72
  
          // будем считать количество пустых строк подряд - при достижении $empty_lines_quantity - считаем что это конец файла и выходим
          $empty_lines = 0;
a684f314   Mihail   add adjustRowToKe...
73
          while ($empty_lines < $this->empty_lines_quantity) {
8e128526   Mihail   add xlsx parser
74
  
61323a64   Mihail   redid read method...
75
76
              $this->readRow();
              $this->current_row_number++;
a3b2aa93   Mihail   change meaning of...
77
  
58f734e6   Mihail   fixed issue with ...
78
              // уберем пустые колонки из ряда
61323a64   Mihail   redid read method...
79
              if ( $this->keys === NULL ) {
a684f314   Mihail   add adjustRowToKe...
80
81
82
                  $this->filterRow();
              }
  
61323a64   Mihail   redid read method...
83
              if ( $this->isEmptyRow() ) {
a3b2aa93   Mihail   change meaning of...
84
85
                  //счетчик пустых строк
                  $empty_lines++;
a3b2aa93   Mihail   change meaning of...
86
87
                  continue;
              }
58f734e6   Mihail   fixed issue with ...
88
  
61323a64   Mihail   redid read method...
89
90
91
92
93
94
95
96
              if ( $first_circle ) {
                  // при первом проходе нужно учесть настройки поп поиску первой строки
                  // такие как first_line и  has_header_row
                  $this->shiftToFirstValuableLine();
              }
  
              $first_circle = false;
  
a3b2aa93   Mihail   change meaning of...
97
              // запустим конвертирование
a684f314   Mihail   add adjustRowToKe...
98
              $this->adjustRowToSettings();
8e128526   Mihail   add xlsx parser
99
  
a3b2aa93   Mihail   change meaning of...
100
101
              // установим отпарсенную строку в итоговый массив результата
              $this->setResult();
8e128526   Mihail   add xlsx parser
102
  
8e128526   Mihail   add xlsx parser
103
              // если у нас установлен лимит, при  его достижении прекращаем парсинг
a684f314   Mihail   add adjustRowToKe...
104
              if ($this->isLastLine())
8e128526   Mihail   add xlsx parser
105
106
107
108
                  break;
  
              // обнуляем счетчик, так как считаюся пустые строки ПОДРЯД
              $empty_lines = 0;
8e128526   Mihail   add xlsx parser
109
          }
8e128526   Mihail   add xlsx parser
110
      }
a684f314   Mihail   add adjustRowToKe...
111
  
8e128526   Mihail   add xlsx parser
112
      /**
61323a64   Mihail   redid read method...
113
114
       * определяет первую значимую строку согласно first_line и has_header_row,
       * считывается пока не дойдет до first_line
a3b2aa93   Mihail   change meaning of...
115
       * пропускает заголовок если он указан
8e128526   Mihail   add xlsx parser
116
117
118
       */
      protected function shiftToFirstValuableLine()
      {
61323a64   Mihail   redid read method...
119
120
          // читаем пока не дойдем до first_line
          while ( $this->first_line > $this->current_row_number ) {
8e128526   Mihail   add xlsx parser
121
              $this->readRow();
61323a64   Mihail   redid read method...
122
123
              $this->current_row_number++;
          }
a3b2aa93   Mihail   change meaning of...
124
125
          // если указан заголовок, то его мы тоже пропускаем (читаем далее)
          if( $this->has_header_row ) {
a3b2aa93   Mihail   change meaning of...
126
              $this->readRow();
61323a64   Mihail   redid read method...
127
              $this->current_row_number++;
a3b2aa93   Mihail   change meaning of...
128
          }
8e128526   Mihail   add xlsx parser
129
130
131
132
133
      }
  
      /**
       * @return array - одномерный массив результата парсинга строки
       */
a684f314   Mihail   add adjustRowToKe...
134
      protected function adjustRowToSettings()
8e128526   Mihail   add xlsx parser
135
      {
a684f314   Mihail   add adjustRowToKe...
136
137
138
139
140
141
142
          // если есть заголовок, то перед конвертацией его нужно назначить
          if ($this->keys !== NULL) {
              // adjust row to keys
              $this->adjustRowToKeys();
              // назначим заголовок
              $this->row = array_combine($this->keys, $this->row);
          }
8e128526   Mihail   add xlsx parser
143
  
a684f314   Mihail   add adjustRowToKe...
144
145
          // попытаемся конвертировать прочитанные значения согласно конфигурации котнвертера значений
          $this->row = $this->convert($this->row);
8e128526   Mihail   add xlsx parser
146
  
a684f314   Mihail   add adjustRowToKe...
147
148
          // обрежем массив к первой значимой колонке
          if ($this->first_column) {
8e128526   Mihail   add xlsx parser
149
  
a684f314   Mihail   add adjustRowToKe...
150
              $this->row = array_slice($this->row, $this->first_column);
8e128526   Mihail   add xlsx parser
151
  
a684f314   Mihail   add adjustRowToKe...
152
          }
8e128526   Mihail   add xlsx parser
153
154
155
  
      }
  
a3b2aa93   Mihail   change meaning of...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
      protected  function isEmptyRow(){
  
          $is_empty = false;
  
          if ( empty( $this->row ) ) {
              return true;
          }
          if (  count( $this->row ) < $this->min_column_quantity ) {
              return true;
          }
  
          $j = 0;
          for ($i = 1; $i <= count( $this->row ); $i++) {
  
              if ( !isset( $this->row[ $i - 1 ] ) ) {
                  continue;
              }
  
              if ( $this->isEmptyColumn( $this->row[$i - 1] ) ) {
                  $j++;
              }
  
              if ( $j >= $this->min_column_quantity ) {
                  $is_empty = true;
                  break;
8e128526   Mihail   add xlsx parser
181
182
              }
          }
a3b2aa93   Mihail   change meaning of...
183
184
  
          return $is_empty;
8e128526   Mihail   add xlsx parser
185
186
      }
  
a3b2aa93   Mihail   change meaning of...
187
188
  
  
a684f314   Mihail   add adjustRowToKe...
189
190
      protected function filterRow()
      {
a3b2aa93   Mihail   change meaning of...
191
192
          // нет строки - нет фильтрации
          if ( empty( $this->row ) ) {
d1fac7a9   Mihail   add parsing sheet...
193
194
              return;
          }
a684f314   Mihail   add adjustRowToKe...
195
          $this->row = array_filter($this->row, function ($val) {
8e128526   Mihail   add xlsx parser
196
197
              return !$this->isEmptyColumn($val);
          });
8e128526   Mihail   add xlsx parser
198
199
      }
  
a684f314   Mihail   add adjustRowToKe...
200
201
      protected function isLastLine()
      {
8e128526   Mihail   add xlsx parser
202
  
a684f314   Mihail   add adjustRowToKe...
203
          if (($this->last_line) && ($this->current_row_number > $this->last_line)) {
8e128526   Mihail   add xlsx parser
204
205
206
207
208
              return true;
          }
          return false;
      }
  
a684f314   Mihail   add adjustRowToKe...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
      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
226
  }