Map::exists()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 1
crap 1
1
<?php
2
/**
3
 * Incoming
4
 *
5
 * @author    Trevor Suarez (Rican7)
6
 * @copyright (c) Trevor Suarez
7
 * @link      https://github.com/Rican7/incoming
8
 * @license   MIT
9
 */
10
11
declare(strict_types=1);
12
13
namespace Incoming\Structure;
14
15
use ArrayIterator;
16
use ArrayObject;
17
use Incoming\Structure\Exception\ReadOnlyException;
18
use Incoming\Structure\Iterator\ReadOnlyIterator;
19
use InvalidArgumentException;
20
use Iterator;
21
use Traversable;
22
23
/**
24
 * A key => value, read-only map data-structure.
25
 */
26
class Map implements Structure
27
{
28
29
    /**
30
     * Properties
31
     */
32
33
    /**
34
     * The underlying decorated data structure.
35
     *
36
     * @var ArrayObject
37
     */
38
    private $decorated;
39
40
41
    /**
42
     * Methods
43
     */
44
45
    /**
46
     * Constructor
47
     */
48 138
    public function __construct()
49
    {
50 138
        $this->decorated = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);
51 138
    }
52
53
    /**
54
     * Create from data in a Traversable instance.
55
     *
56
     * @param Traversable $data The data to create from.
57
     * @return static The resulting data-structure.
58
     * @throws InvalidArgumentException If the data contains non-scalar keys.
59
     */
60 108
    public static function fromTraversable(Traversable $data): self
61
    {
62 108
        $map = new static();
63
64 108
        foreach ($data as $key => $val) {
65 108
            if (!is_scalar($key)) {
66 3
                throw new InvalidArgumentException('Map keys must be scalar');
67
            }
68
69 105
            $map->decorated->offsetSet($key, $val);
70
        }
71
72 105
        return $map;
73
    }
74
75
    /**
76
     * Create from data in an array.
77
     *
78
     * @param array $data The data to create from.
79
     * @return static The resulting data-structure.
80
     */
81 66
    public static function fromArray(array $data): self
82
    {
83 66
        return static::fromTraversable(
84 66
            new ArrayIterator($data)
85
        );
86
    }
87
88
    /**
89
     * Check if a given key exists in the map.
90
     *
91
     * @param mixed $key The key to check for existence.
92
     * @return bool True if the key exists, false otherwise.
93
     */
94 36
    public function exists($key): bool
95
    {
96 36
        return $this->offsetExists($key);
97
    }
98
99
    /**
100
     * Get a value in the map by key.
101
     *
102
     * @param mixed $key The key to get the value for.
103
     * @param mixed $default_val The default value to return if the key does
104
     *  not exist.
105
     * @return mixed The resulting value.
106
     */
107 30
    public function get($key, $default_val = null)
108
    {
109 30
        if ($this->exists($key)) {
110 30
            return $this->offsetGet($key);
111
        }
112
113 3
        return $default_val;
114
    }
115
116
    /**
117
     * Check if the map is empty.
118
     *
119
     * @return bool True if the map is empty, false otherwise.
120
     */
121 3
    public function isEmpty(): bool
122
    {
123 3
        return ($this->count() === 0);
124
    }
125
126
    /**
127
     * Get an array list of all of the map's keys.
128
     *
129
     * @return array The list of the map's keys.
130
     */
131 3
    public function keys(): array
132
    {
133 3
        return array_keys(
134 3
            $this->toArray()
135
        );
136
    }
137
138
    /**
139
     * Get a representation of the map as an array.
140
     *
141
     * @return array The array representation of the map.
142
     */
143 6
    public function toArray(): array
144
    {
145 6
        return $this->decorated->getArrayCopy();
146
    }
147
148
    /**
149
     * Get the number of entries in the map.
150
     *
151
     * @return int The number of entries in the map.
152
     */
153 6
    public function count(): int
154
    {
155 6
        return count($this->decorated);
156
    }
157
158
    /**
159
     * Get an iterator instance over the underlying data.
160
     *
161
     * @return Iterator An iterator scoped to the map's data.
162
     */
163 30
    public function getIterator(): Iterator
164
    {
165 30
        return new ReadOnlyIterator(
166 30
            $this->decorated->getIterator()
167
        );
168
    }
169
170
    /**
171
     * Check whether an offset exists.
172
     *
173
     * @param mixed $offset The offset to check for.
174
     * @return bool True if the offset exists, false otherwise.
175
     */
176 39
    public function offsetExists($offset): bool
177
    {
178 39
        return $this->decorated->offsetExists($offset);
179
    }
180
181
    /**
182
     * Get the value at the given offset.
183
     *
184
     * @param mixed $offset The offset to get the value for.
185
     * @return mixed The resulting value.
186
     */
187 45
    public function offsetGet($offset)
188
    {
189 45
        return $this->decorated->offsetGet($offset);
190
    }
191
192
    /**
193
     * Set a value at the given offset.
194
     *
195
     * @internal
196
     *
197
     * @param mixed $offset The offset to set the value for.
198
     * @param mixed $value The value to set.
199
     * @throws ReadOnlyException External modification is not allowed.
200
     * @return void
201
     */
202 3
    public function offsetSet($offset, $value)
203
    {
204 3
        throw ReadOnlyException::forAttribute($offset, $value);
205
    }
206
207
    /**
208
     * Remove the item at the given offset.
209
     *
210
     * @internal
211
     *
212
     * @param mixed $offset The offset to unset.
213
     * @throws ReadOnlyException External modification is not allowed.
214
     * @return void
215
     */
216 3
    public function offsetUnset($offset)
217
    {
218 3
        throw ReadOnlyException::forAttribute($offset);
219
    }
220
221
    /**
222
     * Magic "__isset" method.
223
     *
224
     * Allows access to the map's values via object property/field syntax.
225
     *
226
     * @param string $key The key to check for.
227
     * @return bool True if the key exists, false otherwise.
228
     */
229 3
    public function __isset(string $key): bool
230
    {
231 3
        return $this->exists($key);
232
    }
233
234
    /**
235
     * Magic "__get" method.
236
     *
237
     * Allows access to the map's values via object property/field syntax.
238
     *
239
     * @param string $key The key to get the value for.
240
     * @return mixed The resulting value.
241
     */
242 3
    public function __get(string $key)
243
    {
244 3
        return $this->get($key);
245
    }
246
247
    /**
248
     * Magic "__set" method.
249
     *
250
     * @internal
251
     *
252
     * @param string $key The key to set the value for.
253
     * @param mixed $value The value to set.
254
     * @throws ReadOnlyException External modification is not allowed.
255
     * @return void
256
     */
257 3
    public function __set(string $key, $value)
258
    {
259 3
        throw ReadOnlyException::forAttribute($key, $value);
260
    }
261
262
    /**
263
     * Magic "__unset" method.
264
     *
265
     * @internal
266
     *
267
     * @param string $key The key to unset.
268
     * @throws ReadOnlyException External modification is not allowed.
269
     * @return void
270
     */
271 3
    public function __unset(string $key)
272
    {
273 3
        throw ReadOnlyException::forAttribute($key);
274
    }
275
}
276