|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* This file is part of the browscap package. |
|
4
|
|
|
* |
|
5
|
|
|
* Copyright (c) 1998-2017, Browser Capabilities Project |
|
6
|
|
|
* |
|
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
|
8
|
|
|
* file that was distributed with this source code. |
|
9
|
|
|
*/ |
|
10
|
|
|
|
|
11
|
|
|
declare(strict_types = 1); |
|
12
|
|
|
namespace Browscap\Writer; |
|
13
|
|
|
|
|
14
|
|
|
use Browscap\Data\DataCollection; |
|
15
|
|
|
use Browscap\Filter\FilterInterface; |
|
16
|
|
|
use Browscap\Formatter\FormatterInterface; |
|
17
|
|
|
use Psr\Log\LoggerInterface; |
|
18
|
|
|
|
|
19
|
|
|
/** |
|
20
|
|
|
* Class CsvWriter |
|
21
|
|
|
* |
|
22
|
|
|
* @category Browscap |
|
23
|
|
|
* |
|
24
|
|
|
* @author Thomas Müller <[email protected]> |
|
25
|
|
|
*/ |
|
26
|
|
|
class CsvWriter implements WriterInterface |
|
27
|
|
|
{ |
|
28
|
|
|
/** |
|
29
|
|
|
* @var \Psr\Log\LoggerInterface |
|
30
|
|
|
*/ |
|
31
|
|
|
private $logger; |
|
32
|
|
|
|
|
33
|
|
|
/** |
|
34
|
|
|
* @var resource |
|
35
|
|
|
*/ |
|
36
|
|
|
private $file; |
|
37
|
|
|
|
|
38
|
|
|
/** |
|
39
|
|
|
* @var \Browscap\Formatter\FormatterInterface |
|
40
|
|
|
*/ |
|
41
|
|
|
private $formatter; |
|
42
|
|
|
|
|
43
|
|
|
/** |
|
44
|
|
|
* @var \Browscap\Filter\FilterInterface |
|
45
|
|
|
*/ |
|
46
|
|
|
private $filter; |
|
47
|
|
|
|
|
48
|
|
|
/** |
|
49
|
|
|
* @var bool |
|
50
|
|
|
*/ |
|
51
|
|
|
private $silent = false; |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* @var array |
|
55
|
|
|
*/ |
|
56
|
|
|
private $outputProperties = []; |
|
57
|
|
|
|
|
58
|
|
|
/** |
|
59
|
|
|
* @param string $file |
|
60
|
|
|
* @param \Psr\Log\LoggerInterface $logger |
|
61
|
|
|
*/ |
|
62
|
21 |
|
public function __construct(string $file, LoggerInterface $logger) |
|
63
|
|
|
{ |
|
64
|
21 |
|
$this->logger = $logger; |
|
65
|
21 |
|
$this->file = fopen($file, 'w'); |
|
66
|
21 |
|
} |
|
67
|
|
|
|
|
68
|
|
|
/** |
|
69
|
|
|
* returns the Type of the writer |
|
70
|
|
|
* |
|
71
|
|
|
* @return string |
|
72
|
|
|
*/ |
|
73
|
1 |
|
public function getType() : string |
|
74
|
|
|
{ |
|
75
|
1 |
|
return 'csv'; |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* closes the Writer and the written File |
|
80
|
|
|
*/ |
|
81
|
20 |
|
public function close() : void |
|
82
|
|
|
{ |
|
83
|
20 |
|
fclose($this->file); |
|
84
|
20 |
|
} |
|
85
|
|
|
|
|
86
|
|
|
/** |
|
87
|
|
|
* @param \Browscap\Formatter\FormatterInterface $formatter |
|
88
|
|
|
*/ |
|
89
|
4 |
|
public function setFormatter(FormatterInterface $formatter) : void |
|
90
|
|
|
{ |
|
91
|
4 |
|
$this->formatter = $formatter; |
|
92
|
4 |
|
} |
|
93
|
|
|
|
|
94
|
|
|
/** |
|
95
|
|
|
* @return \Browscap\Formatter\FormatterInterface |
|
96
|
|
|
*/ |
|
97
|
1 |
|
public function getFormatter() : FormatterInterface |
|
98
|
|
|
{ |
|
99
|
1 |
|
return $this->formatter; |
|
100
|
|
|
} |
|
101
|
|
|
|
|
102
|
|
|
/** |
|
103
|
|
|
* @param \Browscap\Filter\FilterInterface $filter |
|
104
|
|
|
*/ |
|
105
|
4 |
|
public function setFilter(FilterInterface $filter) : void |
|
106
|
|
|
{ |
|
107
|
4 |
|
$this->filter = $filter; |
|
108
|
4 |
|
$this->outputProperties = []; |
|
109
|
4 |
|
} |
|
110
|
|
|
|
|
111
|
|
|
/** |
|
112
|
|
|
* @return \Browscap\Filter\FilterInterface |
|
113
|
|
|
*/ |
|
114
|
1 |
|
public function getFilter() : FilterInterface |
|
115
|
|
|
{ |
|
116
|
1 |
|
return $this->filter; |
|
117
|
|
|
} |
|
118
|
|
|
|
|
119
|
|
|
/** |
|
120
|
|
|
* @param bool $silent |
|
121
|
|
|
*/ |
|
122
|
8 |
|
public function setSilent(bool $silent) : void |
|
123
|
|
|
{ |
|
124
|
8 |
|
$this->silent = $silent; |
|
125
|
8 |
|
} |
|
126
|
|
|
|
|
127
|
|
|
/** |
|
128
|
|
|
* @return bool |
|
129
|
|
|
*/ |
|
130
|
7 |
|
public function isSilent() : bool |
|
131
|
|
|
{ |
|
132
|
7 |
|
return $this->silent; |
|
133
|
|
|
} |
|
134
|
|
|
|
|
135
|
|
|
/** |
|
136
|
|
|
* Generates a start sequence for the output file |
|
137
|
|
|
*/ |
|
138
|
1 |
|
public function fileStart() : void |
|
139
|
|
|
{ |
|
140
|
|
|
// nothing to do here |
|
141
|
1 |
|
} |
|
142
|
|
|
|
|
143
|
|
|
/** |
|
144
|
|
|
* Generates a end sequence for the output file |
|
145
|
|
|
*/ |
|
146
|
1 |
|
public function fileEnd() : void |
|
147
|
|
|
{ |
|
148
|
|
|
// nothing to do here |
|
149
|
1 |
|
} |
|
150
|
|
|
|
|
151
|
|
|
/** |
|
152
|
|
|
* Generate the header |
|
153
|
|
|
* |
|
154
|
|
|
* @param string[] $comments |
|
155
|
|
|
*/ |
|
156
|
1 |
|
public function renderHeader(array $comments = []) : void |
|
157
|
|
|
{ |
|
158
|
|
|
// nothing to do here |
|
159
|
1 |
|
} |
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* renders the version information |
|
163
|
|
|
* |
|
164
|
|
|
* @param string[] $versionData |
|
165
|
|
|
*/ |
|
166
|
4 |
|
public function renderVersion(array $versionData = []) : void |
|
167
|
|
|
{ |
|
168
|
4 |
|
if ($this->isSilent()) { |
|
169
|
1 |
|
return; |
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
3 |
|
$this->logger->debug('rendering version information'); |
|
173
|
|
|
|
|
174
|
3 |
|
fwrite($this->file, '"GJK_Browscap_Version","GJK_Browscap_Version"' . PHP_EOL); |
|
175
|
|
|
|
|
176
|
3 |
|
if (!isset($versionData['version'])) { |
|
177
|
1 |
|
$versionData['version'] = '0'; |
|
178
|
|
|
} |
|
179
|
|
|
|
|
180
|
3 |
|
if (!isset($versionData['released'])) { |
|
181
|
1 |
|
$versionData['released'] = ''; |
|
182
|
|
|
} |
|
183
|
|
|
|
|
184
|
3 |
|
fwrite($this->file, '"' . $versionData['version'] . '","' . $versionData['released'] . '"' . PHP_EOL); |
|
185
|
3 |
|
} |
|
186
|
|
|
|
|
187
|
|
|
/** |
|
188
|
|
|
* renders the header for all divisions |
|
189
|
|
|
* |
|
190
|
|
|
* @param \Browscap\Data\DataCollection $collection |
|
191
|
|
|
*/ |
|
192
|
2 |
|
public function renderAllDivisionsHeader(DataCollection $collection) : void |
|
193
|
|
|
{ |
|
194
|
2 |
|
$division = $collection->getDefaultProperties(); |
|
195
|
2 |
|
$ua = $division->getUserAgents(); |
|
196
|
|
|
|
|
197
|
2 |
|
if (empty($ua[0]['properties']) || !is_array($ua[0]['properties'])) { |
|
198
|
1 |
|
return; |
|
199
|
|
|
} |
|
200
|
|
|
|
|
201
|
1 |
|
$defaultproperties = $ua[0]['properties']; |
|
202
|
1 |
|
$properties = array_merge( |
|
203
|
1 |
|
['PropertyName', 'MasterParent', 'LiteMode', 'Parent'], |
|
204
|
1 |
|
array_keys($defaultproperties) |
|
205
|
|
|
); |
|
206
|
|
|
|
|
207
|
1 |
|
$values = []; |
|
208
|
|
|
|
|
209
|
1 |
|
foreach ($properties as $property) { |
|
210
|
1 |
View Code Duplication |
if (!isset($this->outputProperties[$property])) { |
|
|
|
|
|
|
211
|
1 |
|
$this->outputProperties[$property] = $this->filter->isOutputProperty($property, $this); |
|
212
|
|
|
} |
|
213
|
|
|
|
|
214
|
1 |
|
if (!$this->outputProperties[$property]) { |
|
215
|
|
|
continue; |
|
216
|
|
|
} |
|
217
|
|
|
|
|
218
|
1 |
|
$values[] = $this->formatter->formatPropertyName($property); |
|
219
|
|
|
} |
|
220
|
|
|
|
|
221
|
1 |
|
fwrite($this->file, implode(',', $values) . PHP_EOL); |
|
222
|
1 |
|
} |
|
223
|
|
|
|
|
224
|
|
|
/** |
|
225
|
|
|
* renders the header for a division |
|
226
|
|
|
* |
|
227
|
|
|
* @param string $division |
|
228
|
|
|
* @param string $parent |
|
229
|
|
|
*/ |
|
230
|
1 |
|
public function renderDivisionHeader(string $division, string $parent = 'DefaultProperties') : void |
|
231
|
|
|
{ |
|
232
|
|
|
// nothing to do here |
|
233
|
1 |
|
} |
|
234
|
|
|
|
|
235
|
|
|
/** |
|
236
|
|
|
* renders the header for a section |
|
237
|
|
|
* |
|
238
|
|
|
* @param string $sectionName |
|
239
|
|
|
* |
|
240
|
|
|
* @return \Browscap\Writer\WriterInterface |
|
241
|
|
|
*/ |
|
242
|
1 |
|
public function renderSectionHeader(string $sectionName) : void |
|
243
|
|
|
{ |
|
244
|
|
|
// nothing to do here |
|
245
|
1 |
|
} |
|
246
|
|
|
|
|
247
|
|
|
/** |
|
248
|
|
|
* renders all found useragents into a string |
|
249
|
|
|
* |
|
250
|
|
|
* @param (int|string|true)[] $section |
|
251
|
|
|
* @param \Browscap\Data\DataCollection $collection |
|
252
|
|
|
* @param array[] $sections |
|
253
|
|
|
* @param string $sectionName |
|
254
|
|
|
* |
|
255
|
|
|
* @throws \InvalidArgumentException |
|
256
|
|
|
*/ |
|
257
|
2 |
|
public function renderSectionBody(array $section, DataCollection $collection, array $sections = [], string $sectionName = '') : void |
|
258
|
|
|
{ |
|
259
|
2 |
|
if ($this->isSilent()) { |
|
260
|
1 |
|
return; |
|
261
|
|
|
} |
|
262
|
|
|
|
|
263
|
1 |
|
$division = $collection->getDefaultProperties(); |
|
264
|
1 |
|
$ua = $division->getUserAgents(); |
|
265
|
1 |
|
$defaultproperties = $ua[0]['properties']; |
|
266
|
1 |
|
$properties = array_merge( |
|
267
|
1 |
|
['PropertyName', 'MasterParent', 'LiteMode', 'Parent'], |
|
268
|
1 |
|
array_keys($defaultproperties) |
|
269
|
|
|
); |
|
270
|
|
|
|
|
271
|
1 |
|
$section['PropertyName'] = $sectionName; |
|
272
|
1 |
|
$section['MasterParent'] = $this->detectMasterParent($sectionName, $section); |
|
|
|
|
|
|
273
|
|
|
|
|
274
|
1 |
|
if (in_array($sectionName, ['DefaultProperties', '*'])) { |
|
275
|
|
|
$section['LiteMode'] = 'true'; |
|
276
|
|
|
} else { |
|
277
|
1 |
|
$section['LiteMode'] = ((!isset($section['lite']) || !$section['lite']) ? 'false' : 'true'); |
|
278
|
|
|
} |
|
279
|
|
|
|
|
280
|
1 |
|
$values = []; |
|
281
|
|
|
|
|
282
|
1 |
|
foreach ($properties as $property) { |
|
283
|
1 |
View Code Duplication |
if (!isset($this->outputProperties[$property])) { |
|
|
|
|
|
|
284
|
1 |
|
$this->outputProperties[$property] = $this->filter->isOutputProperty($property, $this); |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
1 |
|
if (!$this->outputProperties[$property]) { |
|
288
|
|
|
continue; |
|
289
|
|
|
} |
|
290
|
|
|
|
|
291
|
1 |
|
if (isset($section[$property])) { |
|
292
|
1 |
|
$value = $section[$property]; |
|
293
|
|
|
} else { |
|
294
|
1 |
|
$value = ''; |
|
295
|
|
|
} |
|
296
|
|
|
|
|
297
|
1 |
|
$values[] = $this->formatter->formatPropertyValue($value, $property); |
|
298
|
|
|
} |
|
299
|
|
|
|
|
300
|
1 |
|
fwrite($this->file, implode(',', $values) . PHP_EOL); |
|
301
|
1 |
|
} |
|
302
|
|
|
|
|
303
|
|
|
/** |
|
304
|
|
|
* renders the footer for a section |
|
305
|
|
|
* |
|
306
|
|
|
* @param string $sectionName |
|
307
|
|
|
*/ |
|
308
|
1 |
|
public function renderSectionFooter(string $sectionName = '') : void |
|
309
|
|
|
{ |
|
310
|
|
|
// nothing to do here |
|
311
|
1 |
|
} |
|
312
|
|
|
|
|
313
|
|
|
/** |
|
314
|
|
|
* renders the footer for a division |
|
315
|
|
|
*/ |
|
316
|
1 |
|
public function renderDivisionFooter() : void |
|
317
|
|
|
{ |
|
318
|
|
|
// nothing to do here |
|
319
|
1 |
|
} |
|
320
|
|
|
|
|
321
|
|
|
/** |
|
322
|
|
|
* renders the footer for all divisions |
|
323
|
|
|
*/ |
|
324
|
1 |
|
public function renderAllDivisionsFooter() : void |
|
325
|
|
|
{ |
|
326
|
|
|
// nothing to do here |
|
327
|
1 |
|
} |
|
328
|
|
|
|
|
329
|
|
|
/** |
|
330
|
|
|
* @param string $key |
|
331
|
|
|
* @param string[] $properties |
|
332
|
|
|
* |
|
333
|
|
|
* @return string |
|
334
|
|
|
*/ |
|
335
|
1 |
|
private function detectMasterParent(string $key, array $properties) : string |
|
336
|
|
|
{ |
|
337
|
1 |
|
$this->logger->debug('check if the element can be marked as "MasterParent"'); |
|
338
|
|
|
|
|
339
|
1 |
|
if (in_array($key, ['DefaultProperties', '*']) |
|
340
|
1 |
|
|| empty($properties['Parent']) |
|
341
|
|
|
|| 'DefaultProperties' === $properties['Parent'] |
|
342
|
|
|
) { |
|
343
|
1 |
|
return 'true'; |
|
344
|
|
|
} |
|
345
|
|
|
|
|
346
|
|
|
return 'false'; |
|
347
|
|
|
} |
|
348
|
|
|
} |
|
349
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.