Passed
Branch feature/first-release (051e8a)
by Andrea Marco
02:29
created

CasesCollection::keyByName()   A

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
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 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 UnitEnum;
0 ignored issues
show
Bug introduced by
The type UnitEnum 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...
7
8
/**
9
 * The collection of enum cases.
10
 *
11
 */
12
class CasesCollection
13
{
14
    /**
15
     * Whether the cases belong to a backed enum
16
     *
17
     * @var bool
18
     */
19
    protected bool $enumIsBacked;
20
21
    /**
22
     * Instantiate the class
23
     *
24
     * @param array $cases
25
     */
26 14
    public function __construct(protected array $cases)
27
    {
28 14
        $this->enumIsBacked = $this->first() instanceof BackedEnum;
29
    }
30
31
    /**
32
     * Retrieve the cases
33
     *
34
     * @return array
35
     */
36 70
    public function cases(): array
37
    {
38 70
        return $this->cases;
39
    }
40
41
    /**
42
     * Retrieve the count of cases
43
     *
44
     * @return int
45
     */
46 1
    public function count(): int
47
    {
48 1
        return count($this->cases);
49
    }
50
51
    /**
52
     * Retrieve the first case
53
     *
54
     * @param callable|null $callback
55
     * @return mixed
56
     */
57 21
    public function first(callable $callback = null): mixed
58
    {
59 21
        $callback ??= fn () => true;
60
61 21
        foreach ($this->cases as $case) {
62 20
            if ($callback($case)) {
63 20
                return $case;
64
            }
65
        }
66
67 1
        return null;
68
    }
69
70
    /**
71
     * Retrieve the cases keyed by name
72
     *
73
     * @return array<string, mixed>
74
     */
75 1
    public function keyByName(): array
76
    {
77 1
        return $this->keyBy('name');
78
    }
79
80
    /**
81
     * Retrieve the cases keyed by the given key
82
     *
83
     * @param callable|string $key
84
     * @return array<string, mixed>
85
     */
86 4
    public function keyBy(callable|string $key): array
87
    {
88 4
        $result = [];
89
90 4
        foreach ($this->cases as $case) {
91 4
            $result[$case->get($key)] = $case;
92
        }
93
94 4
        return $result;
95
    }
96
97
    /**
98
     * Retrieve the cases keyed by value
99
     *
100
     * @return array<string, mixed>
101
     */
102 2
    public function keyByValue(): array
103
    {
104 2
        return $this->enumIsBacked ? $this->keyBy('value') : [];
105
    }
106
107
    /**
108
     * Retrieve all the names of the cases
109
     *
110
     * @return array<int, string>
111
     */
112 1
    public function names(): array
113
    {
114 1
        return array_column($this->cases, 'name');
115
    }
116
117
    /**
118
     * Retrieve all the values of the backed cases
119
     *
120
     * @return array<int, string|int>
121
     */
122 2
    public function values(): array
123
    {
124 2
        return array_column($this->cases, 'value');
125
    }
126
127
    /**
128
     * Retrieve all the keys of the cases
129
     *
130
     * @param callable|string $key
131
     * @return array
132
     */
133 4
    public function keys(callable|string $key): array
134
    {
135 4
        return $this->pluck($key);
136
    }
137
138
    /**
139
     * Retrieve an array of values optionally keyed by the given key
140
     *
141
     * @param callable|string|null $value
142
     * @param callable|string|null $key
143
     * @return array
144
     */
145 10
    public function pluck(callable|string $value = null, callable|string $key = null): array
146
    {
147 10
        $result = [];
148 10
        $value ??= $this->enumIsBacked ? 'value' : 'name';
149
150 10
        foreach ($this->cases as $case) {
151 10
            if ($key === null) {
152 8
                $result[] = $case->get($value);
153
            } else {
154 2
                $result[$case->get($key)] = $case->get($value);
155
            }
156
        }
157
158 8
        return $result;
159
    }
160
161
    /**
162
     * Retrieve a collection with the filtered cases
163
     *
164
     * @param callable $callback
165
     * @return static
166
     */
167
    public function filter(callable $callback): static
168
    {
169
        $cases = array_filter($this->cases, $callback);
170
171
        return new static(array_values($cases));
172
    }
173
174
    /**
175
     * Retrieve a collection of cases having the given names
176
     *
177
     * @param string ...$name
178
     * @return static
179
     */
180
    public function only(string ...$name): static
181
    {
182
        return $this->filter(fn (UnitEnum $enum) => in_array($enum->name, $name));
183
    }
184
185
    /**
186
     * Retrieve a collection of cases not having the given names
187
     *
188
     * @param string ...$name
189
     * @return static
190
     */
191
    public function except(string ...$name): static
192
    {
193
        return $this->filter(fn (UnitEnum $enum) => !in_array($enum->name, $name));
194
    }
195
196
    /**
197
     * Retrieve a collection of backed cases having the given values
198
     *
199
     * @param string|int ...$value
200
     * @return static
201
     */
202
    public function onlyValues(string|int ...$value): static
203
    {
204
        return $this->filter(fn (UnitEnum $enum) => $this->enumIsBacked && in_array($enum->value, $value, true));
205
    }
206
207
    /**
208
     * Retrieve a collection of backed cases not having the given values
209
     *
210
     * @param string|int ...$value
211
     * @return static
212
     */
213
    public function exceptValues(string|int ...$value): static
214
    {
215
        return $this->filter(fn (UnitEnum $enum) => $this->enumIsBacked && !in_array($enum->value, $value, true));
216
    }
217
218
    /**
219
     * Retrieve a collection of cases sorted by name ascending
220
     *
221
     * @return static
222
     */
223
    public function sort(): static
224
    {
225
        return $this->sortBy('name');
226
    }
227
228
    /**
229
     * Retrieve a collection of cases sorted by name descending
230
     *
231
     * @return static
232
     */
233
    public function sortDesc(): static
234
    {
235
        return $this->sortDescBy('name');
236
    }
237
238
    /**
239
     * Retrieve a collection of cases sorted by the given key ascending
240
     *
241
     * @param callable|string $key
242
     * @return static
243
     */
244
    public function sortBy(callable|string $key): static
245
    {
246
        $cases = $this->cases;
247
248
        usort($cases, fn ($a, $b) => $a->get($key) <=> $b->get($key));
249
250
        return new static($cases);
251
    }
252
253
    /**
254
     * Retrieve a collection of cases sorted by the given key descending
255
     *
256
     * @param callable|string $key
257
     * @return static
258
     */
259
    public function sortDescBy(callable|string $key): static
260
    {
261
        $cases = $this->cases;
262
263
        usort($cases, fn ($a, $b) => $a->get($key) > $b->get($key) ? -1 : 1);
264
265
        return new static($cases);
266
    }
267
268
    /**
269
     * Retrieve a collection of cases sorted by value ascending
270
     *
271
     * @return static
272
     */
273
    public function sortByValue(): static
274
    {
275
        return $this->enumIsBacked ? $this->sortBy('value') : new static([]);
276
    }
277
278
    /**
279
     * Retrieve a collection of cases sorted by value descending
280
     *
281
     * @return static
282
     */
283
    public function sortDescByValue(): static
284
    {
285
        return $this->enumIsBacked ? $this->sortDescBy('value') : new static([]);
286
    }
287
}
288