Passed
Push — master ( 42a16a...44846f )
by Andrea Marco
12:16 queued 14s
created

CasesCollection::sortDescBy()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
cc 2
nc 1
nop 1
crap 2

1 Method

Rating   Name   Duplication   Size   Complexity  
A CasesCollection::sortDesc() 0 3 1
1
<?php
2
3
namespace Cerbero\Enum;
4
5
use BackedEnum;
0 ignored issues
show
Bug introduced by
The type BackedEnum 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...
Bug introduced by
This use statement conflicts with another class in this namespace, Cerbero\Enum\BackedEnum. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
6
use Countable;
7
use IteratorAggregate;
8
use Traversable;
9
10
/**
11
 * The collection of enum cases.
12
 *
13
 * @template TKey of array-key
14
 * @template TValue
15
 *
16
 * @implements IteratorAggregate<TKey, TValue>
17
 */
18
class CasesCollection implements Countable, IteratorAggregate
19
{
20
    /**
21
     * Whether the cases belong to a backed enum.
22
     */
23
    protected readonly bool $enumIsBacked;
24
25
    /**
26
     * Instantiate the class.
27
     *
28
     * @param array<TKey, TValue> $cases
29
     */
30 64
    final public function __construct(protected array $cases)
31
    {
32 64
        $this->enumIsBacked = reset($cases) instanceof BackedEnum;
0 ignored issues
show
Bug introduced by
The property enumIsBacked is declared read-only in Cerbero\Enum\CasesCollection.
Loading history...
33
    }
34
35
    /**
36
     * Retrieve the count of cases.
37
     */
38 4
    public function count(): int
39
    {
40 4
        return count($this->cases);
41
    }
42
43
    /**
44
     * Retrieve the iterable cases.
45
     *
46
     * @return Traversable<TKey, TValue>
47
     */
48 10
    public function getIterator(): Traversable
49
    {
50 10
        yield from $this->cases;
51
    }
52
53
    /**
54
     * Retrieve all the cases as a plain array.
55
     *
56
     * @return array<TKey, TValue>
57
     */
58 73
    public function all(): array
59
    {
60 73
        return $this->cases;
61
    }
62
63
    /**
64
     * Retrieve all the cases as a plain array recursively.
65
     *
66
     * @return array<TKey, mixed>
67
     */
68 1
    public function toArray(): array
69
    {
70 1
        $array = [];
71
72 1
        foreach ($this->cases as $key => $value) {
73 1
            $array[$key] = $value instanceof self ? $value->toArray() : $value;
74
        }
75
76 1
        return $array;
77
    }
78
79
    /**
80
     * Retrieve the first case.
81
     *
82
     * @param (callable(TValue, TKey): bool)|null $callback
0 ignored issues
show
Documentation Bug introduced by
The doc comment (callable(TValue, TKey): bool)|null at position 1 could not be parsed: Expected ')' at position 1, but found 'callable'.
Loading history...
83
     * @return ?TValue
84
     */
85 5
    public function first(callable $callback = null): mixed
86
    {
87 5
        $callback ??= fn() => true;
88
89 5
        foreach ($this->cases as $key => $case) {
90 4
            if ($callback($case, $key)) {
91 4
                return $case;
92
            }
93
        }
94
95 1
        return null;
96
    }
97
98
    /**
99
     * Retrieve all the names of the cases.
100
     *
101
     * @return string[]
102
     */
103 2
    public function names(): array
104
    {
105 2
        return array_column($this->cases, 'name');
106
    }
107
108
    /**
109
     * Retrieve all the values of the backed cases.
110
     *
111
     * @return list<string|int>
0 ignored issues
show
Bug introduced by
The type Cerbero\Enum\list 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...
112
     */
113 3
    public function values(): array
114
    {
115 3
        return array_column($this->cases, 'value');
116
    }
117
118
    /**
119
     * Retrieve an array of values optionally keyed by the given key.
120
     *
121
     * @template TPluckValue
122
     *
123
     * @param (callable(TValue): TPluckValue)|string $value
0 ignored issues
show
Documentation Bug introduced by
The doc comment (callable(TValue): TPluckValue)|string at position 1 could not be parsed: Expected ')' at position 1, but found 'callable'.
Loading history...
124
     * @param (callable(TValue): array-key)|string|null $key
125
     * @return array<array-key, TPluckValue>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, TPluckValue> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, TPluckValue>.
Loading history...
126
     */
127 10
    public function pluck(callable|string $value, callable|string $key = null): array
128
    {
129 10
        $result = [];
130
131 10
        foreach ($this->cases as $case) {
132 10
            if ($key === null) {
133 6
                $result[] = $case->resolveItem($value);
134
            } else {
135 4
                $result[$case->resolveItem($key)] = $case->resolveItem($value);
136
            }
137
        }
138
139 10
        return $result;
140
    }
141
142
    /**
143
     * Retrieve the result of mapping over the cases.
144
     *
145
     * @template TMapValue
146
     *
147
     * @param callable(TValue, TKey): TMapValue $callback
148
     * @return array<TKey, TMapValue>
149
     */
150 3
    public function map(callable $callback): array
151
    {
152 3
        $keys = array_keys($this->cases);
153 3
        $values = array_map($callback, $this->cases, $keys);
154
155 3
        return array_combine($keys, $values);
156
    }
157
158
    /**
159
     * Retrieve the cases keyed by their own name.
160
     */
161 1
    public function keyByName(): static
162
    {
163 1
        return $this->keyBy('name');
164
    }
165
166
    /**
167
     * Retrieve the cases keyed by the given key.
168
     *
169
     * @param (callable(TValue): array-key)|string $key
0 ignored issues
show
Documentation Bug introduced by
The doc comment (callable(TValue): array-key)|string at position 1 could not be parsed: Expected ')' at position 1, but found 'callable'.
Loading history...
170
     */
171 4
    public function keyBy(callable|string $key): static
172
    {
173 4
        $keyed = [];
174
175 4
        foreach ($this->cases as $case) {
176 4
            $keyed[$case->resolveItem($key)] = $case;
177
        }
178
179 4
        return new static($keyed);
180
    }
181
182
    /**
183
     * Retrieve the cases keyed by their own value.
184
     */
185 2
    public function keyByValue(): static
186
    {
187 2
        return $this->enumIsBacked ? $this->keyBy('value') : new static([]);
188
    }
189
190
    /**
191
     * Retrieve the cases grouped by the given key.
192
     *
193
     * @param (callable(TValue): array-key)|string $key
0 ignored issues
show
Documentation Bug introduced by
The doc comment (callable(TValue): array-key)|string at position 1 could not be parsed: Expected ')' at position 1, but found 'callable'.
Loading history...
194
     */
195 6
    public function groupBy(callable|string $key): static
196
    {
197 6
        $grouped = [];
198
199 6
        foreach ($this->cases as $case) {
200 6
            $grouped[$case->resolveItem($key)][] = $case;
201
        }
202
203 6
        foreach ($grouped as $key => $cases) {
204 6
            $grouped[$key] = new static($cases);
205
        }
206
207 6
        return new static($grouped);
208
    }
209
210
    /**
211
     * Retrieve a new collection with the filtered cases.
212
     *
213
     * @param (callable(TValue): bool)|string $filter
0 ignored issues
show
Documentation Bug introduced by
The doc comment (callable(TValue): bool)|string at position 1 could not be parsed: Expected ')' at position 1, but found 'callable'.
Loading history...
214
     */
215 15
    public function filter(callable|string $filter): static
216
    {
217
        /** @phpstan-ignore method.nonObject */
218 15
        $callback = is_callable($filter) ? $filter : fn(mixed $case) => $case->resolveItem($filter) === true;
219
220 15
        return new static(array_filter($this->cases, $callback));
221
    }
222
223
    /**
224
     * Retrieve a new collection of cases having only the given names.
225
     */
226 2
    public function only(string ...$name): static
227
    {
228 2
        return $this->filter(fn(mixed $case) => in_array($case->name, $name));
229
    }
230
231
    /**
232
     * Retrieve a collection of cases not having the given names.
233
     */
234 2
    public function except(string ...$name): static
235
    {
236 2
        return $this->filter(fn(mixed $case) => !in_array($case->name, $name));
237
    }
238
239
    /**
240
     * Retrieve a new collection of backed cases having only the given values.
241
     */
242 3
    public function onlyValues(string|int ...$value): static
243
    {
244 3
        return $this->filter(fn(mixed $case) => $this->enumIsBacked && in_array($case->value, $value, true));
245
    }
246
247
    /**
248
     * Retrieve a new collection of backed cases not having the given values.
249
     */
250 3
    public function exceptValues(string|int ...$value): static
251
    {
252 3
        return $this->filter(fn(mixed $case) => $this->enumIsBacked && !in_array($case->value, $value, true));
253
    }
254
255
    /**
256
     * Retrieve a new collection of cases sorted by their own name ascending.
257
     */
258 2
    public function sort(): static
259
    {
260 2
        return $this->sortBy('name');
261
    }
262
263
    /**
264
     * Retrieve a new collection of cases sorted by the given key ascending.
265
     *
266
     * @param (callable(TValue): mixed)|string $key
0 ignored issues
show
Documentation Bug introduced by
The doc comment (callable(TValue): mixed)|string at position 1 could not be parsed: Expected ')' at position 1, but found 'callable'.
Loading history...
267
     */
268 6
    public function sortBy(callable|string $key): static
269
    {
270 6
        $cases = $this->cases;
271
272 6
        uasort($cases, fn(mixed $a, mixed $b) => $a->resolveItem($key) <=> $b->resolveItem($key));
273
274 6
        return new static($cases);
275
    }
276
277
    /**
278
     * Retrieve a new collection of cases sorted by their own value ascending.
279
     */
280 2
    public function sortByValue(): static
281
    {
282 2
        return $this->enumIsBacked ? $this->sortBy('value') : new static([]);
283
    }
284
285
    /**
286
     * Retrieve a new collection of cases sorted by their own name descending.
287
     */
288 2
    public function sortDesc(): static
289
    {
290 2
        return $this->sortByDesc('name');
291
    }
292
293
    /**
294
     * Retrieve a new collection of cases sorted by the given key descending.
295
     *
296
     * @param (callable(TValue): mixed)|string $key
0 ignored issues
show
Documentation Bug introduced by
The doc comment (callable(TValue): mixed)|string at position 1 could not be parsed: Expected ')' at position 1, but found 'callable'.
Loading history...
297
     */
298 6
    public function sortByDesc(callable|string $key): static
299
    {
300 6
        $cases = $this->cases;
301
302 6
        uasort($cases, fn(mixed $a, mixed $b) => $b->resolveItem($key) <=> $a->resolveItem($key));
303
304 6
        return new static($cases);
305
    }
306
307
    /**
308
     * Retrieve a new collection of cases sorted by their own value descending.
309
     */
310 2
    public function sortByDescValue(): static
311
    {
312 2
        return $this->enumIsBacked ? $this->sortByDesc('value') : new static([]);
313
    }
314
}
315