Passed
Push — version-4 ( 84aff8...d98195 )
by Sebastian
02:28
created

MapTrait::toArray()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
1
<?php
2
declare(strict_types=1);
3
/*
4
 * Copyright (C) 2022 Sebastian Böttger <[email protected]>
5
 * You may use, distribute and modify this code under the
6
 * terms of the MIT license.
7
 *
8
 * You should have received a copy of the MIT license with
9
 * this file. If not, please visit: https://opensource.org/licenses/mit-license.php
10
 */
11
12
namespace Seboettg\Collection\Map;
13
14
use ArrayIterator;
15
use Iterator;
16
use ReflectionException;
17
use ReflectionFunction;
18
use Seboettg\Collection\Assert\Exception\NotApplicableCallableException;
19
use Seboettg\Collection\Lists\ListInterface;
20
use Seboettg\Collection\NativePhp\ArrayAccessTrait;
21
use function Seboettg\Collection\Assert\assertScalar;
22
use function Seboettg\Collection\Assert\assertType;
23
use function Seboettg\Collection\Assert\assertValidCallable;
24
use function Seboettg\Collection\Lists\emptyList;
25
use function Seboettg\Collection\Lists\listOf;
26
27
/**
28
 * @property array $array base array of this data structure
29
 */
30
trait MapTrait
31
{
32
    use ArrayAccessTrait;
33
34
    /**
35
     * @inheritDoc
36
     */
37 1
    public function getEntries(): ListInterface
38
    {
39
        return listOf(...array_map(function (string $key, $value) {
40 1
            return pair($key, $value);
41 1
        }, array_keys($this->array), $this->array));
42
43
    }
0 ignored issues
show
Coding Style introduced by
Function closing brace must go on the next line following the body; found 1 blank lines before brace
Loading history...
44
45
    /**
46
     * @inheritDoc
47
     */
48 2
    public function getKeys(): ListInterface
49
    {
50 2
        return listOf(...array_keys($this->array));
51
    }
52
53
    /**
54
     * @inheritDoc
55
     */
56 2
    public function values(): ListInterface
57
    {
58 2
        return listOf(...array_values($this->array));
59
    }
60
61
    /**
62
     * {@inheritDoc}
63
     */
64 16
    public function count(): int
65
    {
66 16
        return count($this->array);
67
    }
68
69
    /**
70
     * @inheritDoc
71
     */
72 1
    public function size(): int
73
    {
74 1
        return $this->count();
75
    }
76
77
    /**
78
     * @inheritDoc
79
     */
80
    public function clear(): void
81
    {
82
        unset($this->array);
83
        $this->array = [];
84
    }
85
86
    /**
87
     * @inheritDoc
88
     * @param scalar $key
89
     * @return bool
90
     */
91 6
    public function contains($key): bool
92
    {
93 6
        assertScalar($key, "Key must be a scalar value");
94 4
        return array_key_exists($key, $this->array);
95
    }
96
97
    /**
98
     * @inheritDoc
99
     * @param array $array
100
     */
101
    public function setArray(array $array): void
102
    {
103
        $this->array = $array;
104
    }
105
106
    /**
107
     * @inheritDoc
108
     * @param scalar
109
     * @return string
110
     */
111 1
    public function containsKey($key): bool
112
    {
113 1
        return $this->contains($key);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->contains($key) returns the type boolean which is incompatible with the documented return type string.
Loading history...
114
    }
115
116
    /**
117
     * @inheritDoc
118
     * @param mixed $value
119
     * @return bool
120
     */
121
    public function containsValue($value): bool
122
    {
123
        return in_array($value, $this->array, true) !== false;
124
    }
125
126
    /**
127
     * @inheritDoc
128
     * @return bool
129
     */
130 2
    public function isEmpty(): bool
131
    {
132 2
        return $this->count() === 0;
133
    }
134
135
    /**
136
     * @inheritDoc
137
     * @param scalar
138
     * @return mixed
139
     */
140 5
    public function get($key)
141
    {
142 5
        return $this->array[$key] ?? null;
143
    }
144
145
    /**
146
     * @inheritDoc
147
     * @param scalar $key
148
     * @param mixed $value
149
     */
150 36
    public function put($key, $value): void
151
    {
152 36
        assertScalar($key, "Key must be a scalar value");
153 36
        $this->array[$key] = $value;
154 36
    }
155
156
    /**
157
     * @param MapInterface<scalar, mixed> $map
158
     * @return void
159
     */
160 1
    public function putAll(MapInterface $map): void
161
    {
162 1
        foreach ($map as $key => $value) {
163 1
            $this->array[$key] = $value;
164
        }
165 1
    }
166
167
    /**
168
     * @inheritDoc
169
     * @param scalar $key
170
     * @return void
171
     */
172 1
    public function remove($key): void
173
    {
174 1
        unset($this->array[$key]);
175 1
    }
176
177
    /**
178
     * @inheritDoc
179
     * @param callable $predicate
180
     * @return bool
181
     */
182 1
    public function all(callable $predicate): bool
183
    {
184 1
        return $this->count() === $this->filter($predicate)->count();
185
    }
186
187
    /**
188
     * @inheritDoc
189
     * @param callable $predicate
190
     * @return bool
191
     */
192 1
    public function any(callable $predicate): bool
193
    {
194 1
        return $this->filter($predicate)->count() > 0;
195
    }
196
197
    /**
198
     * @inheritDoc
199
     * @param callable|null $predicate
200
     * @return MapInterface
201
     */
202 5
    public function filter(callable $predicate = null): MapInterface
203
    {
204 5
        $map = emptyMap();
205 5
        if ($predicate !== null) {
206
            try {
207 5
                $reflected = new ReflectionFunction($predicate);
208 5
                if (count($reflected->getParameters()) === 1) {
209 3
                    assertValidCallable($predicate, [Pair::class]);
210 3
                    foreach ($this->array as $key => $value) {
211 3
                        if ($predicate(pair($key, $value)) === true) {
212 3
                            $map->put($key, $value);
213
                        }
214
                    }
215
                } else {
216 2
                    if (count($reflected->getParameters()) === 2) {
217 2
                        assertValidCallable($predicate, ["scalar", "mixed"]);
218
                    }
219 5
                    foreach ($this->array as $key => $value) {
220 2
                        if ($predicate($key, $value) === true) {
221 2
                            $map->put($key, $value);
222
                        }
223
                    }
224
                }
225
            } catch (ReflectionException $ex) {
226 5
                throw new NotApplicableCallableException("Invalid callback.");
227
            }
228
        } else {
229
            $map->array = array_filter($this->array, $predicate);
0 ignored issues
show
Bug introduced by
The property array is declared private in anonymous//src/Map/Functions.php$0 and cannot be accessed from this context.
Loading history...
230
        }
231 5
        return $map;
232
    }
233
234
    /**
235
     * @inheritDoc
236
     * @param scalar $key
237
     * @param callable $default
238
     * @return mixed
239
     */
240 2
    public function getOrElse($key, callable $default)
241
    {
242 2
        return $this[$key] ?? $default($this);
243
    }
244
245
    /**
246
     * @inheritDoc
247
     * @param callable $transform
248
     * @return ListInterface
249
     */
250 2
    public function map(callable $transform): ListInterface
251
    {
252 2
        $list = emptyList();
253 2
        foreach ($this->array as $key => $value) {
254 2
            $list->add($transform(pair($key, $value)));
255
        }
256 2
        return $list;
257
    }
258
259
    /**
260
     * @inheritDoc
261
     * @param callable $transform
262
     * @return ListInterface
263
     */
264 1
    public function mapNotNull(callable $transform): ListInterface
265
    {
266 1
        return $this->map($transform)->filter(fn($item) => $item !== null);
267
    }
268
269
    /**
270
     * @inheritDoc
271
     * @param iterable<scalar> $keys
272
     * @param MapInterface
273
     */
274 2
    public function minus(iterable $keys): MapInterface
275
    {
276 2
        $newInstance = emptyMap();
277 2
        foreach ($this->array as $key => $value) {
278 2
            if (!$this->iterableContainsKey($key, $keys)) {
279 2
                $newInstance[$key] = $value;
280
            }
281
        }
282 2
        return $newInstance;
283
    }
284
285 2
    private function iterableContainsKey($key, iterable $keys): bool
286
    {
287 2
        foreach ($keys as $k) {
288 2
            if ($k === $key) {
289 2
                return true;
290
            }
291
        }
292 2
        return false;
293
    }
294
295
    /**
296
     * @inheritDoc
297
     * @param iterable<Pair<scalar, mixed>> $pairs
298
     * @return MapInterface<scalar, mixed>
299
     */
300 2
    public function plus(iterable $pairs): MapInterface
301
    {
302 2
        $map = emptyMap();
303 2
        $map->array = $this->array;
0 ignored issues
show
Bug introduced by
The property array is declared private in anonymous//src/Map/Functions.php$0 and cannot be accessed from this context.
Loading history...
304 2
        if ($pairs instanceof MapInterface) {
305 1
            foreach ($pairs as $key => $value) {
306 1
                $map[$key] = $value;
307
            }
308
        } else {
309 1
            foreach ($pairs as $pair) {
310 1
                assertType($pair, Pair::class,
311 1
                    sprintf(
312 1
                        "Expected object of type %s, object of type %s given",
313 1
                        Pair::class,
314 1
                        gettype($pair) === "object" ? get_class($pair) : gettype($pair)
315
                    )
316
                );
317 1
                $map[$pair->getKey()] = $pair->getValue();
318
            }
319
        }
320 2
        return $map;
321
    }
322
323
    /**
324
     * @inheritDoc
325
     * @param callable $action f(entry: Pair<scalar, mixed>) -> mixed|void
326
     * @return void
327
     */
328 1
    public function forEach(callable $action): void
329
    {
330 1
        foreach ($this->array as $key => $value) {
331 1
            $action(pair($key, $value));
332
        }
333 1
    }
334
335
    /**
336
     * @inheritDoc
337
     * @return ListInterface<Pair<scalar, mixed>>
338
     */
339 2
    public function toList(): ListInterface
340
    {
341 2
        $list = emptyList();
342 2
        foreach ($this->array as $key => $value) {
343 2
            $list->add(pair($key, $value));
344
        }
345 2
        return $list;
346
    }
347
348 1
    public function toMap(): MapInterface
349
    {
350 1
        return mapOf(...$this->toList());
351
    }
352
353
354 2
    public function getIterator(): Iterator
355
    {
356 2
        return new ArrayIterator($this->array);
357
    }
358
359
    /**
360
     * {@inheritDoc}
361
     */
362
    public function toArray(): array
363
    {
364
        return $this->array;
365
    }
366
}
367