1
|
|
|
<?php |
2
|
|
|
declare(strict_types = 1); |
3
|
|
|
|
4
|
|
|
namespace BrowscapPHP\Parser\Helper; |
5
|
|
|
|
6
|
|
|
use BrowscapPHP\Cache\BrowscapCacheInterface; |
7
|
|
|
use BrowscapPHP\Data\PropertyFormatter; |
8
|
|
|
use BrowscapPHP\Data\PropertyHolder; |
9
|
|
|
use BrowscapPHP\Helper\Quoter; |
10
|
|
|
use Psr\Log\LoggerInterface; |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* extracts the data and the data for theses pattern from the ini content, optimized for PHP 5.5+ |
14
|
|
|
*/ |
15
|
|
|
final class GetData implements GetDataInterface |
16
|
|
|
{ |
17
|
|
|
/** |
18
|
|
|
* The cache instance |
19
|
|
|
* |
20
|
|
|
* @var \BrowscapPHP\Cache\BrowscapCacheInterface |
21
|
|
|
*/ |
22
|
|
|
private $cache; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* a logger instance |
26
|
|
|
* |
27
|
|
|
* @var \Psr\Log\LoggerInterface |
28
|
|
|
*/ |
29
|
|
|
private $logger; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* @var \BrowscapPHP\Helper\Quoter |
33
|
|
|
*/ |
34
|
|
|
private $quoter; |
35
|
|
|
|
36
|
|
|
/** |
37
|
|
|
* class contsructor |
38
|
|
|
* |
39
|
|
|
* @param \BrowscapPHP\Cache\BrowscapCacheInterface $cache |
40
|
|
|
* @param \Psr\Log\LoggerInterface $logger |
41
|
|
|
* @param \BrowscapPHP\Helper\Quoter $quoter |
42
|
|
|
*/ |
43
|
1 |
|
public function __construct(BrowscapCacheInterface $cache, LoggerInterface $logger, Quoter $quoter) |
44
|
|
|
{ |
45
|
1 |
|
$this->cache = $cache; |
46
|
1 |
|
$this->logger = $logger; |
47
|
1 |
|
$this->quoter = $quoter; |
48
|
1 |
|
} |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* Gets the settings for a given pattern (method calls itself to |
52
|
|
|
* get the data from the parent patterns) |
53
|
|
|
* |
54
|
|
|
* @param string $pattern |
55
|
|
|
* @param array $settings |
56
|
|
|
* @return array |
57
|
|
|
*/ |
58
|
|
|
public function getSettings(string $pattern, array $settings = []) : array |
59
|
|
|
{ |
60
|
|
|
// The pattern has been pre-quoted on generation to speed up the pattern search, |
61
|
|
|
// but for this check we need the unquoted version |
62
|
|
|
$unquotedPattern = $this->quoter->pregUnQuote($pattern); |
63
|
|
|
|
64
|
|
|
// Try to get settings for the pattern |
65
|
|
|
$addedSettings = $this->getIniPart($unquotedPattern); |
66
|
|
|
|
67
|
|
|
// set some additional data |
68
|
|
|
if (count($settings) === 0) { |
69
|
|
|
// The optimization with replaced digits get can now result in setting searches, for which we |
70
|
|
|
// won't find a result - so only add the pattern information, is settings have been found. |
71
|
|
|
// |
72
|
|
|
// If not an empty array will be returned and the calling function can easily check if a pattern |
73
|
|
|
// has been found. |
74
|
|
|
if (count($addedSettings) > 0) { |
75
|
|
|
$settings['browser_name_regex'] = '/^' . $pattern . '$/'; |
76
|
|
|
$settings['browser_name_pattern'] = $unquotedPattern; |
77
|
|
|
} |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
// check if parent pattern set, only keep the first one |
81
|
|
|
$parentPattern = null; |
82
|
|
|
if (isset($addedSettings['Parent'])) { |
83
|
|
|
$parentPattern = $addedSettings['Parent']; |
84
|
|
|
|
85
|
|
|
if (isset($settings['Parent'])) { |
86
|
|
|
unset($addedSettings['Parent']); |
87
|
|
|
} |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
// merge settings |
91
|
|
|
$settings += $addedSettings; |
92
|
|
|
|
93
|
|
|
if ($parentPattern !== null) { |
94
|
|
|
return $this->getSettings($this->quoter->pregQuote($parentPattern), $settings); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return $settings; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Gets the relevant part (array of settings) of the ini file for a given pattern. |
102
|
|
|
* |
103
|
|
|
* @param string $pattern |
104
|
|
|
* @return array |
105
|
|
|
*/ |
106
|
|
|
private function getIniPart(string $pattern) : array |
107
|
|
|
{ |
108
|
|
|
$pattern = strtolower($pattern); |
109
|
|
|
$patternhash = Pattern::getHashForParts($pattern); |
110
|
|
|
$subkey = SubKey::getIniPartCacheSubKey($patternhash); |
111
|
|
|
|
112
|
|
View Code Duplication |
if (! $this->cache->hasItem('browscap.iniparts.' . $subkey, true)) { |
|
|
|
|
113
|
|
|
$this->logger->debug('cache key "browscap.iniparts.' . $subkey . '" not found'); |
114
|
|
|
|
115
|
|
|
return []; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
$success = null; |
119
|
|
|
$file = $this->cache->getItem('browscap.iniparts.' . $subkey, true, $success); |
120
|
|
|
|
121
|
|
|
if (! $success) { |
|
|
|
|
122
|
|
|
$this->logger->debug('cache key "browscap.iniparts.' . $subkey . '" not found'); |
123
|
|
|
|
124
|
|
|
return []; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
if (! is_array($file) || ! count($file)) { |
128
|
|
|
$this->logger->debug('cache key "browscap.iniparts.' . $subkey . '" was empty'); |
129
|
|
|
|
130
|
|
|
return []; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
$propertyFormatter = new PropertyFormatter(new PropertyHolder()); |
134
|
|
|
$return = []; |
135
|
|
|
|
136
|
|
|
foreach ($file as $buffer) { |
137
|
|
|
list($tmpBuffer, $patterns) = explode("\t", $buffer, 2); |
138
|
|
|
|
139
|
|
|
if ($tmpBuffer === $patternhash) { |
140
|
|
|
$return = json_decode($patterns, true); |
141
|
|
|
|
142
|
|
|
foreach (array_keys($return) as $property) { |
143
|
|
|
$return[$property] = $propertyFormatter->formatPropertyValue( |
144
|
|
|
$return[$property], |
145
|
|
|
$property |
146
|
|
|
); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
break; |
150
|
|
|
} |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
return $return; |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
|
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.