GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Test Failed
Push — master ( 925ec5...ba350e )
by SignpostMarv
06:17
created

MaybeThrowIfValueArrayDoesNotMatchTypes()   A

Complexity

Conditions 5
Paths 2

Size

Total Lines 39
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
eloc 19
dl 0
loc 39
ccs 0
cts 0
cp 0
rs 9.3222
c 0
b 0
f 0
cc 5
nc 2
nop 2
crap 30
1
<?php
2
/**
3
* @author SignpostMarv
4
*/
5
declare(strict_types=1);
6
7
namespace SignpostMarv\DaftObject;
8
9
use Closure;
10
use InvalidArgumentException;
11
use SignpostMarv\DaftMagicPropertyAnalysis\DefinitionAssistant as Base;
12
13
/**
14
* @template-extends Base<DaftObject>
15
*/
16
class DefinitionAssistant extends Base
17
{
18
    const BOOL_EXPECTING_GETTER = false;
19
20
    const BOOL_EXPECTING_SETTER = true;
21
22
    const INT_ARRAY_INDEX_TYPE = 0;
23
24
    const INT_ARRAY_INDEX_GETTER = 1;
25
26
    const INT_ARRAY_INDEX_SETTER = 2;
27
28 46
    public static function IsTypeUnregistered(string $type) : bool
29
    {
30 46
        if ( ! is_a($type, DaftObject::class, true)) {
31 4
            throw new InvalidArgumentException(
32
                'Argument 1 passed to ' .
33
                __METHOD__ .
34
                '() must be an implementation of ' .
35
                DaftObject::class .
36
                ', ' .
37 4
                $type .
38 4
                ' given!'
39
            );
40
        }
41
42 42
        return parent::IsTypeUnregistered($type);
43
    }
44
45
    /**
46
    * @psalm-param class-string<AbstractDaftObject> $maybe
47
    */
48 36
    public static function RegisterAbstractDaftObjectType(string $maybe) : void
49
    {
50
        /**
51
        * @var array<int, string>
52
        */
53 36
        $props = TypeCertainty::EnsureArgumentIsArray($maybe::PROPERTIES);
54
55 36
        static::RegisterDaftObjectTypeFromTypeAndProps($maybe, ...$props);
56 36
    }
57
58 38
    public static function ObtainExpectedProperties($maybe) : array
59
    {
60 38
        $maybe = is_object($maybe) ? get_class($maybe) : $maybe;
61
62 38
        if (static::IsTypeUnregistered($maybe)) {
63 34
            if (TypeParanoia::IsThingStrings($maybe, AbstractDaftObject::class)) {
64 34
                static::RegisterAbstractDaftObjectType($maybe);
65
            }
66
        }
67
68 36
        $maybe = self::MaybeRegisterAdditionalTypes($maybe);
69
70 36
        return parent::ObtainExpectedProperties($maybe);
71
    }
72
73
    /**
74
    * @psalm-param class-string<DaftObject> $type
75
    */
76 4
    public static function AutoRegisterType(string $type, string ...$properties) : void
77
    {
78 4
        static::RegisterDaftObjectTypeFromTypeAndProps($type, ...$properties);
79 4
    }
80
81
    /**
82
    * @psalm-return Closure(string):?string
83
    */
84 38
    public static function SetterOrGetterClosure(
85
        string $type,
86
        bool $SetNotGet,
87
        string ...$props
88
    ) : Closure {
89
        return function (string $property) use ($type, $props, $SetNotGet) : ? string {
90 4
            if (in_array($property, $props, self::IN_ARRAY_STRICT_MODE)) {
91
                /**
92
                * @var string
93
                */
94 4
                $method = TypeUtilities::MethodNameFromProperty($property, $SetNotGet);
95
96 4
                if (method_exists($type, $method)) {
97 4
                    return $method;
98
                }
99
            }
100
101 2
            return null;
102 38
        };
103
    }
104
105
    /**
106
    * @param mixed $value
107
    *
108
    * @return array<int, mixed> filtered $value
109
    */
110 38
    public static function MaybeThrowIfValueDoesNotMatchMultiTypedArray(
111
        bool $autoTrimStrings,
112
        bool $throwIfNotUnique,
113
        $value,
114
        string ...$types
115
    ) : array {
116
        if ( ! is_array($value)) {
117 38
            throw new InvalidArgumentException(
118
                'Argument 3 passed to ' .
119 38
                __METHOD__ .
120 38
                ' must be an array, ' .
121 38
                (is_object($value) ? get_class($value) : gettype($value)) .
122
                ' given!'
123 38
            );
124
        }
125
126 38
        return static::MaybeThrowIfValueDoesNotMatchMultiTypedArrayValueArray(
127
            $autoTrimStrings,
128
            $throwIfNotUnique,
129
            $value,
130
            ...$types
131
        );
132 38
    }
133
134
    /**
135
    * @psalm-param class-string<DaftObject> $type
136 38
    *
137
    * @psalm-return array{0:class-string<DaftObject>, 1:null|Closure(string):?string, 2:null|Closure(string):?string, 4:string}
138
    */
139
    private static function TypeAndGetterAndSetterClosureWithProps(
140
        string $type,
141 38
        string ...$props
142
    ) : array {
143 38
        /**
144 38
        * @psalm-var array{0:class-string<DaftObject>, 1:null|Closure(string):?string, 2:null|Closure(string):?string, 4:string}
145 38
        */
146 38
        $out = array_merge(
147 19
            [
148
                $type,
149 38
                static::SetterOrGetterClosure($type, self::BOOL_EXPECTING_GETTER, ...$props),
150 38
                static::SetterOrGetterClosure($type, self::BOOL_EXPECTING_SETTER, ...$props),
151
            ],
152
            $props
153
        );
154
155
        return $out;
156
    }
157 38
158
    /**
159
    * @psalm-param class-string<DaftObject> $maybe
160
    */
161 38
    private static function RegisterDaftObjectTypeFromTypeAndProps(
162
        string $maybe,
163
        string ...$props
164
    ) : void {
165
        $args = static::TypeAndGetterAndSetterClosureWithProps($maybe, ...$props);
166 38
167 38
        /**
168
        * @var array<int, string>
169
        */
170
        $props = array_slice($args, 3);
171 38
172
        static::RegisterType(
173
            $args[self::INT_ARRAY_INDEX_TYPE],
174
            $args[self::INT_ARRAY_INDEX_GETTER],
175
            $args[self::INT_ARRAY_INDEX_SETTER],
176
            ...$props
177
        );
178
        self::MaybeRegisterAdditionalTypes($args[0]);
179
    }
180
181
    /**
182
    * @psalm-param class-string<DaftObject> $maybe
183
    *
184
    * @psalm-return class-string<DaftObject>
185
    */
186
    private static function MaybeRegisterAdditionalTypes(string $maybe) : string
187
    {
188
        foreach (
189
            [
190
                DefinesOwnArrayIdInterface::class,
191
                DefinesOwnIntegerIdInterface::class,
192
                DefinesOwnStringIdInterface::class,
193
            ] as $otherType
194
        ) {
195
            if ($otherType !== $maybe && self::IsTypeUnregistered($otherType)) {
196
                self::RegisterDaftObjectTypeFromTypeAndProps($otherType, 'id');
197
            }
198
        }
199
200
        return $maybe;
201
    }
202
203
    /**
204
    * @return array<int, mixed> filtered $value
205
    */
206
    private static function MaybeThrowIfValueDoesNotMatchMultiTypedArrayValueArray(
207
        bool $autoTrimStrings,
208
        bool $throwIfNotUnique,
209
        array $value,
210
        string ...$types
211
    ) : array {
212
        $value = static::MaybeThrowIfNotArrayIntKeys($value);
213
        $value = static::MaybeThrowIfValueArrayDoesNotMatchTypes($value, ...$types);
214
        $value = static::MaybeRemapStringsToTrimmedStrings($value, $autoTrimStrings, ...$types);
215
216
        $initialCount = count($value);
217
218
        $value = array_unique($value, SORT_REGULAR);
219
220
        if ($throwIfNotUnique && count($value) !== $initialCount) {
221
            throw new InvalidArgumentException(
222
                'Argument 3 passed to ' .
223
                __METHOD__ .
224
                ' contained non-unique values!'
225
            );
226
        }
227
228
        return array_values($value);
229
    }
230
231
    /**
232
    * @return array<int, mixed> filtered $value
233
    */
234
    private static function MaybeThrowIfNotArrayIntKeys(array $value) : array
235
    {
236
        $initialCount = count($value);
237
238
        /**
239
        * @var array<int, mixed>
240
        */
241
        $value = array_filter($value, 'is_int', ARRAY_FILTER_USE_KEY);
242
243
        if (count($value) !== $initialCount) {
244
            throw new InvalidArgumentException(
245
                'Argument 3 passed to ' .
246
                __METHOD__ .
247
                ' must be array<int, mixed>'
248
            );
249
        }
250
251
        return $value;
252
    }
253
254
    /**
255
    * @param array<int, mixed> $value
256
    *
257
    * @return array<int, mixed> filtered $value
258
    */
259
    private static function MaybeThrowIfValueArrayDoesNotMatchTypes(
260
        array $value,
261
        string ...$types
262
    ) : array {
263
        $initialCount = count($value);
264
265
        $value = array_filter(
266
            $value,
267
            /**
268
            * @param mixed $maybe
269
            */
270
            function ($maybe) use ($types) : bool {
271
                if (is_object($maybe)) {
272
                    foreach ($types as $maybeType) {
273
                        if (is_a($maybe, $maybeType)) {
274
                            return true;
275
                        }
276
                    }
277
278
                    return false;
279
                }
280
281
                return in_array(
282
                    gettype($maybe),
283
                    $types,
284
                    DefinitionAssistant::IN_ARRAY_STRICT_MODE
285
                );
286
            }
287
        );
288
289
        if (count($value) !== $initialCount) {
290
            throw new InvalidArgumentException(
291
                'Argument 3 passed to ' .
292
                __METHOD__ .
293
                ' contained values that did not match the provided types!'
294
            );
295
        }
296
297
        return $value;
298
    }
299
300
    /**
301
    * @param array<int, mixed> $value
302
    *
303
    * @return array<int, mixed>
304
    */
305
    private static function MaybeRemapStringsToTrimmedStrings(
306
        array $value,
307
        bool $autoTrimStrings,
308
        string ...$types
309
    ) : array {
310
        if (
311
            $autoTrimStrings &&
312
            in_array('string', $types, DefinitionAssistant::IN_ARRAY_STRICT_MODE)
313
        ) {
314
            $value = array_map(
315
                /**
316
                * @param mixed $maybe
317
                *
318
                * @return mixed
319
                */
320
                function ($maybe) {
321
                    return is_string($maybe) ? trim($maybe) : $maybe;
322
                },
323
                $value
324
            );
325
        }
326
327
        return $value;
328
    }
329
}
330