Formatter::hasBooleanValue()   B
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 26
rs 8.8571
cc 1
eloc 24
nc 1
nop 1
1
<?php
2
declare(strict_types=1);
3
4
namespace Crossjoin\Browscap\Formatter;
5
6
use Crossjoin\Browscap\PropertyFilter\PropertyFilterTrait;
7
8
/**
9
 * Class Formatter
10
 *
11
 * @package Crossjoin\Browscap\Formatter
12
 * @author Christoph Ziegenberg <[email protected]>
13
 * @link https://github.com/crossjoin/browscap
14
 */
15
class Formatter implements FormatterInterface
16
{
17
    use PropertyFilterTrait;
18
19
    const KEY_LOWER = 1;
20
    const KEY_UPPER = 2;
21
22
    const VALUE_TYPED = 4;
23
    const VALUE_UNKNOWN_TO_NULL = 8;
24
    const VALUE_BOOLEAN_TO_STRING = 16;
25
    const VALUE_REG_EXP_LOWER = 32;
26
27
    const RETURN_OBJECT = 64;
28
    const RETURN_ARRAY = 128;
29
30
    /**
31
     * @var int
32
     */
33
    protected $options;
34
35
    /**
36
     * Formatter constructor.
37
     *
38
     * @param int $options
39
     */
40
    public function __construct(int $options = 0)
41
    {
42
        $this->setOptions($options);
43
    }
44
45
    /**
46
     * @return int
47
     */
48
    protected function getOptions() : int
49
    {
50
        return $this->options;
51
    }
52
53
    /**
54
     * @param int $options
55
     */
56
    protected function setOptions(int $options)
57
    {
58
        $this->options = $options;
59
    }
60
61
    /**
62
     * @inheritdoc
63
     *
64
     * @return array|\stdClass
65
     */
66
    public function format(array $browscapData)
67
    {
68
        $data = new \stdClass();
69
70
        foreach ($browscapData as $key => $value) {
71
            if ($this->getPropertyFilter()->isFiltered($key)) {
72
                continue;
73
            }
74
            $key = $this->modifyKey($key);
75
            $value = $this->modifyValue($key, $value);
76
            $data->{$key} = $value;
77
        }
78
79
        if (($this->getOptions() & self::RETURN_ARRAY) > 0) {
80
            $data = (array)$data;
81
        }
82
83
        return $data;
84
    }
85
86
    /**
87
     * @param string $key
88
     *
89
     * @return string
90
     */
91
    protected function modifyKey(string $key)
92
    {
93
        $newKey = $key;
94
        if (($this->getOptions() & self::KEY_LOWER) > 0) {
95
            $newKey = strtolower($key);
96
        } elseif (($this->getOptions() & self::KEY_UPPER) > 0) {
97
            $newKey = strtoupper($key);
98
        }
99
100
        return $newKey;
101
    }
102
103
    /**
104
     * @param string $key
105
     * @param string $value
106
     *
107
     * @return mixed
108
     */
109
    protected function modifyValue(string $key, string $value)
110
    {
111
        $newValue = $value;
112
        if (($this->getOptions() & self::VALUE_TYPED) > 0) {
113
            if ($this->hasBooleanValue($key)) {
114
                $newValue = (strtolower($newValue) === 'true');
115
            } elseif ($this->hasIntegerValue($key)) {
116
                $newValue = (int)$newValue;
117
            } elseif ($this->hasFloatValue($key)) {
118
                $newValue = (float)$newValue;
119
            }
120
        }
121
122
        if (is_string($newValue) &&
123
            ($this->getOptions() & self::VALUE_UNKNOWN_TO_NULL) > 0 &&
124
            strtolower($newValue) === 'unknown'
125
        ) {
126
            $newValue = null;
127
        }
128
129
        if (($this->getOptions() & self::VALUE_BOOLEAN_TO_STRING) > 0 && $this->hasBooleanValue($key)) {
130
            $newValue = ($newValue === true || strtolower($newValue) === 'true');
131
            $newValue = ($newValue ? '1' : '');
132
        }
133
134
        if (strtolower($key) === 'browser_name_regex' && ($this->getOptions() & self::VALUE_REG_EXP_LOWER) > 0) {
135
            $newValue = strtolower($newValue);
136
        }
137
138
        return $newValue;
139
    }
140
141
    /**
142
     * @param string $key
143
     *
144
     * @return bool
145
     */
146
    protected function hasBooleanValue(string $key) : bool
147
    {
148
        return in_array(strtolower($key), [
149
            'activexcontrols',
150
            'alpha',
151
            'backgroundsounds',
152
            'beta',
153
            'cookies',
154
            'crawler',
155
            'frames',
156
            'iframes',
157
            'tables',
158
            'javaapplets',
159
            'javascript',
160
            'isanonymized',
161
            'isfake',
162
            'ismobiledevice',
163
            'ismodified',
164
            'issyndicationreader',
165
            'istablet',
166
            'vbscript',
167
            'win16',
168
            'win32',
169
            'win64',
170
        ], true);
171
    }
172
173
    /**
174
     * @param string $key
175
     *
176
     * @return bool
177
     */
178
    protected function hasIntegerValue(string $key) : bool
179
    {
180
        // Notes:
181
        // - "aolversion" is only contained in the default properties and never set
182
        // - "cssversion" is only set as integers in the browscap data, so version 2.1 should be returned as 2
183
        return in_array(strtolower($key), [
184
            'aolversion',
185
            'browser_bits',
186
            'cssversion',
187
            'majorver',
188
            'minorver',
189
            'platform_bits'
190
        ], true);
191
    }
192
193
    /**
194
     * @param string $key
195
     *
196
     * @return bool
197
     */
198
    protected function hasFloatValue(string $key) : bool
199
    {
200
        // Notes:
201
        // - "platform_version" is a float in most cases, but can also be "ME"
202
        // - "renderingengine_version" is a float in most cases, but also a version string like "1.9.2"
203
        return (strtolower($key) === 'version');
204
    }
205
}
206