Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
csvreader.php
1<?
12
13use Bitrix\Main;
14
15include_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/csv_data.php");
16
17final class CSVReader extends \CCSVData
18{
19 const FILE_ENCODING = 'UTF-8';
20
21 private $header = array();
22 private $useHeader = false;
23 private $legacy = false;
24
25 private $convertCharset = true;
26 private $callbacks = array();
27
28 public function __construct($fields_type = "R", $convertCharset = true)
29 {
30 parent::__construct($fields_type = "R", false);
31 $this->convertCharset = $convertCharset;
32 }
33
34 public function LoadFile($filename, $firstHeader = true)
35 {
36 parent::LoadFile($filename);
37
38 $this->SetFieldsType("R");
39 if($firstHeader)
40 $this->SetFirstHeader();
41 $this->SetDelimiter(";");
42 }
43
44 public function SetFirstHeader($first_header = false)
45 {
46 $this->useHeader = true;
47 $this->header = $this->ReadHeader();
48 }
49
50 public function ReadHeader()
51 {
52 if(!$this->useHeader || !$this->__file)
53 return false;
54
55 if($this->cFieldsType == 'F')
56 return false; // sorry, not implemented for that
57
58 $fPos = ftell($this->__file);
59 fseek($this->__file, $this->__hasBOM ? 3 : 0);
60
61 $h = fgets($this->__file);
62
63 fseek($this->__file, $fPos);
64
65 return explode($this->cDelimiter, $h);
66 }
67
68 public function FetchAssoc()
69 {
70 if(!($line = $this->Fetch()))
71 return false;
72
73 if(!$this->useHeader || $this->legacy)
74 return $line;
75
76 $header = $this->header;
77
78 $result = array();
79 $colCount = count($line);
80 $langFields = array();
81 for($k = 0; $k < $colCount; $k++)
82 {
83 $fld = trim(array_shift($header));
84
85 if(!$fld) // column grid appeared shorter than data field
86 break;
87
88 $resLine = array();
89 $prev =& $resLine;
90 $subFields = explode('.', $fld);
91
92 foreach($subFields as $subfld)
93 {
94 $subfld = trim($subfld);
95
96 $prev[$subfld] = array();
97 $prev =& $prev[$subfld];
98 }
99
100 $prev = trim($line[$k]);
101
102 // keep for charset conversion
103 if(mb_strpos($fld, 'NAME') !== false)
104 $langFields[] = &$prev;
105
106 $result = array_merge_recursive($result, $resLine);
107 }
108
109 if (is_callable($this->callbacks['AFTER_ASSOC_LINE_READ'] ?? ''))
110 {
111 call_user_func_array(
112 $this->callbacks['AFTER_ASSOC_LINE_READ'],
113 [&$result]
114 );
115 }
116
117 // character conversion
118 if($this->convertCharset && self::FILE_ENCODING != SITE_CHARSET)
119 {
120 foreach($langFields as &$value)
121 {
122 $value = \CharsetConverter::ConvertCharset($value, self::FILE_ENCODING, SITE_CHARSET);
123 }
124 }
125
126 return $result;
127 }
128
129 // this function should not be here
130 public function CheckFileIsLegacy()
131 {
132 return $this->legacy;
133 }
134
135 public function ReadBlockLowLevel(&$bytesRead = false, $lineLimit = false)
136 {
137 if(trim($this->header[0]) == 'en' && !isset($this->header[1]))
138 {
139 $this->legacy = true;
140 $this->SetDelimiter(",");
141 }
142
143 if($bytesRead !== false)
144 $this->SetPos($bytesRead);
145
146 $result = array();
147 $i = -1;
148 while ($line = $this->FetchAssoc())
149 {
150 $i++;
151
152 if($lineLimit !== false && $lineLimit + 1 == $i)
153 break;
154
155 if(!$i && !$bytesRead)
156 {
157 continue; // header, skip
158 }
159
160 $result[] = $line;
161
162 if($bytesRead !== false)
163 $bytesRead = $this->GetPos();
164 }
165
166 return $result;
167 }
168
169 public function ReadBlock($file, &$bytesRead = false, $lineLimit = false)
170 {
171 if(mb_strpos($file, $_SERVER['DOCUMENT_ROOT']) != 0) // not found or somwhere else
172 $file = $_SERVER['DOCUMENT_ROOT'].$file;
173
174 if(!file_exists($file) || !is_readable($file))
175 throw new Main\SystemException('Cannot open file '.$file.' for reading');
176
177 $this->LoadFile($file);
178
179 return $this->ReadBlockLowLevel($bytesRead, $lineLimit);
180 }
181
182 public function GetFileSize()
183 {
184 return $this->iFileLength;
185 }
186
187 public function GetHeaderAssoc()
188 {
189 return $this->GetAssocLineByHeader($this->header, $this->header);
190 }
191
192 public function SetCharsetConvert($switch)
193 {
194 $this->convertCharset = !!$switch;
195 }
196
197 public function AddEventCallback($event, $callback)
198 {
199 if((string) $event != '' && is_callable($callback))
200 $this->callbacks[$event] = $callback;
201 }
202
203 private function GetAssocLineByHeader($line, $header)
204 {
205 $result = array();
206 $lineLen = count($line);
207 for($k = 0; $k < $lineLen; $k++)
208 {
209 $fld = array_shift($header);
210
211 if(!$fld) // column grid appeared shorter than data field
212 break;
213
214 $resLine = array();
215 $prev =& $resLine;
216 $subFields = explode('.', $fld);
217
218 foreach($subFields as $subfld)
219 {
220 $subfld = trim($subfld);
221
222 $prev[$subfld] = array();
223 $prev =& $prev[$subfld];
224 }
225
226 $prev = trim($line[$k]);
227
228 $result = array_merge_recursive($result, $resLine);
229 }
230
231 return $result;
232 }
233}
__construct($fields_type="R", $convertCharset=true)
Definition csvreader.php:28
ReadBlockLowLevel(&$bytesRead=false, $lineLimit=false)
ReadBlock($file, &$bytesRead=false, $lineLimit=false)
AddEventCallback($event, $callback)
LoadFile($filename, $firstHeader=true)
Definition csvreader.php:34
SetFirstHeader($first_header=false)
Definition csvreader.php:44