Test Failed
Push — master ( aebabc...cbd8ea )
by Sebastian
03:14
created

ArrayDataCollection::keyExists()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 1
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * @package Application Utils
4
 * @subpackage Collections
5
 * @see \AppUtils\ArrayDataCollection
6
 */
7
8
declare(strict_types=1);
9
10
namespace AppUtils;
11
12
use AppUtils\ArrayDataCollection\ArrayDataCollectionException;
13
use JsonException;
14
use testsuites\Traits\RenderableTests;
0 ignored issues
show
Bug introduced by
The type testsuites\Traits\RenderableTests was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
16
/**
17
 * Collection class used to work with associative arrays used to
18
 * store key => value pairs.
19
 *
20
 * Offers strict typed methods to access the available keys, to
21
 * remove the hassle of checking whether keys exist, and whether
22
 * they are of the expected type.
23
 *
24
 * @package Application Utils
25
 * @subpackage Collections
26
 * @author Sebastian Mordziol <[email protected]>
27
 */
28
class ArrayDataCollection
29
{
30
    public const ERROR_JSON_DECODE_FAILED = 116001;
31
32
    /**
33
     * @var array<string,mixed>
34
     */
35
    protected array $data;
36
37
    /**
38
     * @param array<string,mixed> $data
39
     */
40
    public function __construct(array $data=array())
41
    {
42
        $this->data = $data;
43
    }
44
45
    /**
46
     * @param ArrayDataCollection|array<string,mixed>|NULL $data
47
     * @return ArrayDataCollection
48
     */
49
    public static function create($data=array()) : ArrayDataCollection
50
    {
51
        if($data instanceof self) {
52
            return $data;
53
        }
54
55
        return new ArrayDataCollection($data);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type null; however, parameter $data of AppUtils\ArrayDataCollection::__construct() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

55
        return new ArrayDataCollection(/** @scrutinizer ignore-type */ $data);
Loading history...
56
    }
57
58
    /**
59
     * @return array<string,mixed>
60
     */
61
    public function getData() : array
62
    {
63
        return $this->data;
64
    }
65
66
    /**
67
     * @param array<string,mixed> $data
68
     * @return $this
69
     */
70
    public function setKeys(array $data) : self
71
    {
72
        foreach($data as $key => $value)
73
        {
74
            $this->setKey($key, $value);
75
        }
76
77
        return $this;
78
    }
79
80
    /**
81
     * @param string $name
82
     * @param mixed|NULL $value
83
     * @return $this
84
     */
85
    public function setKey(string $name, $value) : self
86
    {
87
        $this->data[$name] = $value;
88
        return $this;
89
    }
90
91
    /**
92
     * Merges the current collection's data with that of
93
     * the target collection, replacing existing values.
94
     *
95
     * @param ArrayDataCollection $collection
96
     * @return $this
97
     */
98
    public function mergeWith(ArrayDataCollection $collection) : self
99
    {
100
        return $this->setKeys($collection->getData());
101
    }
102
103
    /**
104
     * Combines the current collection's data with the
105
     * target collection, and returns a new collection
106
     * that contains the data of both collections.
107
     *
108
     * NOTE: The source collection's values are overwritten
109
     * by the target collection in the process.
110
     *
111
     * @param ArrayDataCollection $collection
112
     * @return ArrayDataCollection
113
     */
114
    public function combine(ArrayDataCollection $collection) : ArrayDataCollection
115
    {
116
        return self::create($this->data)->setKeys($collection->getData());
117
    }
118
119
    /**
120
     * @param string $name
121
     * @return mixed|null
122
     */
123
    public function getKey(string $name)
124
    {
125
        return $this->data[$name] ?? null;
126
    }
127
128
    /**
129
     * The stored value can be a string or a number.
130
     * All other types and values will return an empty
131
     * string.
132
     *
133
     * @param string $name
134
     * @return string
135
     */
136
    public function getString(string $name) : string
137
    {
138
        $value = $this->getKey($name);
139
140
        if(is_string($value)) {
141
            return $value;
142
        }
143
144
        if(is_numeric($value)) {
145
            return (string)$value;
146
        }
147
148
        return '';
149
    }
150
151
    /**
152
     * The stored value can be an integer or float,
153
     * or a string containing an integer or float.
154
     * All other types and values return <code>0</code>.
155
     *
156
     * @param string $name
157
     * @return int
158
     */
159
    public function getInt(string $name) : int
160
    {
161
        $value = $this->getKey($name);
162
163
        if(is_numeric($value)) {
164
            return (int)$value;
165
        }
166
167
        return 0;
168
    }
169
170
    /**
171
     * Attempts to decode the stored string as JSON.
172
     *
173
     * NOTE: Only JSON that decodes into an array is
174
     * accepted. Other values, like booleans or numbers,
175
     * will return an empty array.
176
     *
177
     * @param string $name
178
     * @return array<mixed>
179
     * @throws ArrayDataCollectionException
180
     */
181
    public function getJSONArray(string $name) : array
182
    {
183
        $value = $this->getString($name);
184
185
        if(empty($value)) {
186
            return array();
187
        }
188
189
        try
190
        {
191
            $value = json_decode($value, true, 512, JSON_THROW_ON_ERROR);
192
193
            if(is_array($value)) {
194
                return $value;
195
            }
196
197
            return array();
198
        }
199
        catch (JsonException $e)
200
        {
201
            throw new ArrayDataCollectionException(
202
                'Invalid JSON encountered in array data collection.',
203
                sprintf(
204
                    'The JSON string could not be decoded.'.PHP_EOL.
205
                    'Reason: %s'.PHP_EOL.
206
                    'Raw JSON given:'.PHP_EOL.
207
                    '---------------------------------------'.PHP_EOL.
208
                    '%s'.PHP_EOL.
209
                    '---------------------------------------'.PHP_EOL,
210
                    $e->getMessage(),
211
                    ConvertHelper::text_cut($value, 500)
212
                ),
213
                self::ERROR_JSON_DECODE_FAILED,
214
                $e
215
            );
216
        }
217
    }
218
219
    public function getArray(string $name) : array
220
    {
221
        $value = $this->getKey($name);
222
223
        if(is_array($value)) {
224
            return $value;
225
        }
226
227
        return array();
228
    }
229
230
    public function getBool(string $name) : bool
231
    {
232
        $value = $this->getKey($name);
233
234
        if(is_string($value)) {
235
            $value = strtolower($value);
236
        }
237
238
        return
239
            $value === true
240
            ||
241
            $value === 'true'
242
            ||
243
            $value === 'yes'
244
            ||
245
            $value === 1;
246
    }
247
248
    public function getFloat(string $name) : float
249
    {
250
        $value = $this->getKey($name);
251
252
        if(is_numeric($value)) {
253
            return (float)$value;
254
        }
255
256
        return 0.0;
257
    }
258
259
    /**
260
     * Whether the specified key exists in the data set,
261
     * even if its value is <code>NULL</code>.
262
     *
263
     * @param string $name
264
     * @return bool
265
     */
266
    public function keyExists(string $name) : bool
267
    {
268
        return array_key_exists($name, $this->data);
269
    }
270
271
    /**
272
     * Whether the specified key exists in the data set,
273
     * and has a non-<code>NULL</code> value.
274
     *
275
     * @param string $name
276
     * @return bool
277
     */
278
    public function keyHasValue(string $name) : bool
279
    {
280
        return isset($this->data[$name]);
281
    }
282
283
    /**
284
     * Removes the specified key from the data set, if it exists.
285
     *
286
     * @param string $name
287
     * @return $this
288
     */
289
    public function removeKey(string $name) : self
290
    {
291
        unset($this->data[$name]);
292
        return $this;
293
    }
294
}
295