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.

TypeUtilities   A
last analyzed

Complexity

Total Complexity 40

Size/Duplication

Total Lines 348
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 95
dl 0
loc 348
ccs 92
cts 92
cp 1
rs 9.2
c 0
b 0
f 0
wmc 40

15 Methods

Rating   Name   Duplication   Size   Complexity  
A DaftObjectPublicSetters() 0 5 1
A DaftObjectPublicOrProtectedGetters() 0 5 1
A MethodNameFromProperty() 0 15 4
A DaftObjectPublicGetters() 0 5 1
A CachePublicGettersAndSettersProperty() 0 17 4
A CachePublicGettersAndSettersProperties() 0 16 4
A MaybeThrowOnNudge() 0 22 4
A ExpectRetrievedValueIsString() 0 11 1
A HasMethod() 0 16 4
A ExpectRetrievedValueIsArray() 0 11 1
A MaybeThrowIfNotType() 0 20 2
A ExpectRetrievedValueIsIntish() 0 15 3
A CachePublicGettersAndSetters() 0 12 2
A ExpectRetrievedValueIsFloatish() 0 15 3
A ExpectRetrievedValueIsBoolish() 0 17 5

How to fix   Complexity   

Complex Class

Complex classes like TypeUtilities often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use TypeUtilities, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
* @author SignpostMarv
4
*/
5
declare(strict_types=1);
6
7
namespace SignpostMarv\DaftObject;
8
9
use ReflectionException;
10
use ReflectionMethod;
11
12
class TypeUtilities
13
{
14
    const BOOL_EXPECTING_NON_PUBLIC_METHOD = false;
15
16
    const BOOL_EXPECTING_GETTER = false;
17
18
    const BOOL_DEFAULT_THROWIFNOTIMPLEMENTATION = false;
19
20
    const BOOL_DEFAULT_EXPECTING_NON_PUBLIC_METHOD = true;
21
22
    const BOOL_METHOD_IS_PUBLIC = true;
23
24
    const BOOL_METHOD_IS_NON_PUBLIC = false;
25
26
    const BOOL_DEFAULT_SET_NOT_GET = false;
27
28
    const BOOL_DOES_NOT_HAVE_METHOD = false;
29
30
    const SUPPORTED_INVALID_LEADING_CHARACTERS = [
31
        '@',
32
    ];
33
34
    const BOOL_METHOD_IS_NOT_STATIC = false;
35
36
    /**
37
    * @var array<string, array<string, bool>>
38
    *
39
    * @psalm-var array<class-string<DaftObject>, array<string, bool>>
40
    */
41
    private static $Getters = [];
42
43
    /**
44
    * @var array<string, array<int, string>>
45
    *
46
    * @psalm-var array<class-string<DaftObject>, array<int, string>>
47
    */
48
    private static $publicSetters = [];
49
50
    /**
51
    * @psalm-param class-string<DaftObject> $class
52
    *
53
    * @return array<int, string>
54
    */
55 412
    public static function DaftObjectPublicGetters(string $class) : array
56
    {
57 412
        static::CachePublicGettersAndSetters($class);
58
59 412
        return array_keys(array_filter(self::$Getters[$class]));
60
    }
61
62
    /**
63
    * @psalm-param class-string<DaftObject> $class
64
    *
65
    * @return array<int, string>
66
    */
67 4
    public static function DaftObjectPublicOrProtectedGetters(string $class) : array
68
    {
69 4
        static::CachePublicGettersAndSetters($class);
70
71 4
        return array_keys(self::$Getters[$class]);
72
    }
73
74
    /**
75
    * @psalm-param class-string<DaftObject> $class
76
    */
77 320
    public static function DaftObjectPublicSetters(string $class) : array
78
    {
79 320
        static::CachePublicGettersAndSetters($class);
80
81 320
        return self::$publicSetters[$class];
82
    }
83
84 624
    public static function MethodNameFromProperty(
85
        string $prop,
86
        bool $SetNotGet = self::BOOL_DEFAULT_SET_NOT_GET
87
    ) : string {
88
        if (
89 624
            in_array(
90 624
                mb_substr($prop, 0, 1),
91 624
                self::SUPPORTED_INVALID_LEADING_CHARACTERS,
92 624
                DefinitionAssistant::IN_ARRAY_STRICT_MODE
93
            )
94
        ) {
95 40
            return ($SetNotGet ? 'Alter' : 'Obtain') . ucfirst(mb_substr($prop, 1));
96
        }
97
98 612
        return ($SetNotGet ? 'Set' : 'Get') . ucfirst($prop);
99
    }
100
101
    /**
102
    * @psalm-param class-string<DaftObject> $class
103
    */
104 120
    public static function HasMethod(
105
        string $class,
106
        string $property,
107
        bool $SetNotGet,
108
        bool $pub = self::BOOL_DEFAULT_EXPECTING_NON_PUBLIC_METHOD
109
    ) : bool {
110 120
        $method = static::MethodNameFromProperty($property, $SetNotGet);
111
112
        try {
113 120
            $ref = new ReflectionMethod($class, $method);
114
115
            return
116 16
                ($pub ? $ref->isPublic() : $ref->isProtected()) &&
117 16
                self::BOOL_METHOD_IS_NOT_STATIC === $ref->isStatic();
118 104
        } catch (ReflectionException $e) {
119 104
            return self::BOOL_DOES_NOT_HAVE_METHOD;
120
        }
121
    }
122
123
    /**
124
    * @template T as string
125
    *
126
    * @param scalar|array|object|null $value
127
    *
128
    * @psalm-param class-string<DaftObject> $class_name
129
    */
130 44
    public static function ExpectRetrievedValueIsString(
131
        string $property,
132
        $value,
133
        string $class_name
134
    ) : string {
135
        /**
136
        * @psalm-var T
137
        */
138 44
        $value = static::MaybeThrowIfNotType($property, $value, $class_name, 'string');
139
140 40
        return $value;
141
    }
142
143
    /**
144
    * @template T as array
145
    *
146
    * @param scalar|array|object|null $value
147
    *
148
    * @psalm-param class-string<DaftObject> $class_name
149
    */
150 8
    public static function ExpectRetrievedValueIsArray(
151
        string $property,
152
        $value,
153
        string $class_name
154
    ) : array {
155
        /**
156
        * @psalm-var T
157
        */
158 8
        $value = static::MaybeThrowIfNotType($property, $value, $class_name, 'array');
159
160 4
        return $value;
161
    }
162
163
    /**
164
    * @template T as int
165
    *
166
    * @param scalar|array|object|null $value
167
    *
168
    * @psalm-param class-string<DaftObject> $class_name
169
    */
170 16
    public static function ExpectRetrievedValueIsIntish(
171
        string $property,
172
        $value,
173
        string $class_name
174
    ) : int {
175 16
        if (is_string($value) && ctype_digit($value)) {
176 4
            $value = (int) $value;
177
        }
178
179
        /**
180
        * @psalm-var T
181
        */
182 16
        $value = static::MaybeThrowIfNotType($property, $value, $class_name, 'integer');
183
184 12
        return $value;
185
    }
186
187
    /**
188
    * @template T as float
189
    *
190
    * @param scalar|array|object|null $value
191
    *
192
    * @psalm-param class-string<DaftObject> $class_name
193
    */
194 12
    public static function ExpectRetrievedValueIsFloatish(
195
        string $property,
196
        $value,
197
        string $class_name
198
    ) : float {
199 12
        if (is_string($value) && is_numeric($value)) {
200 4
            $value = (float) $value;
201
        }
202
203
        /**
204
        * @psalm-var T
205
        */
206 12
        $value = static::MaybeThrowIfNotType($property, $value, $class_name, 'double');
207
208 8
        return $value;
209
    }
210
211
    /**
212
    * @template T as bool
213
    *
214
    * @param scalar|array|object|null $value
215
    *
216
    * @psalm-param class-string<DaftObject> $class_name
217
    */
218 28
    public static function ExpectRetrievedValueIsBoolish(
219
        string $property,
220
        $value,
221
        string $class_name
222
    ) : bool {
223 28
        if ('1' === $value || 1 === $value) {
224 8
            return true;
225 20
        } elseif ('0' === $value || 0 === $value) {
226 8
            return false;
227
        }
228
229
        /**
230
        * @psalm-var T
231
        */
232 12
        $value = static::MaybeThrowIfNotType($property, $value, $class_name, 'boolean');
233
234 8
        return $value;
235
    }
236
237
    /**
238
    * @psalm-param class-string<DaftObject> $class_name
239
    *
240
    * @param scalar|array|object|null $value
241
    */
242 528
    public static function MaybeThrowOnNudge(
243
        string $class_name,
244
        string $property,
245
        $value
246
    ) : void {
247
        if (
248 528
            ! in_array(
249 396
                $property,
250 528
                $class_name::DaftObjectProperties(),
251 528
                DefinitionAssistant::IN_ARRAY_STRICT_MODE
252
            )
253
        ) {
254 4
            throw Exceptions\Factory::UndefinedPropertyException($class_name, $property);
255
        } elseif (
256 524
            true === is_null($value) &&
257 292
            ! in_array(
258 219
                $property,
259 292
                $class_name::DaftObjectNullableProperties(),
260 466
                DefinitionAssistant::IN_ARRAY_STRICT_MODE
261
            )
262
        ) {
263 208
            throw Exceptions\Factory::PropertyNotNullableException($class_name, $property);
264
        }
265 316
    }
266
267
    /**
268
    * @template T
269
    *
270
    * @param scalar|array|object|null $value
271
    *
272
    * @psalm-return T
273
    *
274
    * @return mixed
275
    */
276 92
    protected static function MaybeThrowIfNotType(
277
        string $property,
278
        $value,
279
        string $class_name,
280
        string $type
281
    ) {
282 92
        if ($type !== gettype($value)) {
283 20
            throw Exceptions\Factory::PropertyValueNotOfExpectedTypeException(
284 15
                $class_name,
285 10
                $property,
286 10
                $type
287
            );
288
        }
289
290
        /**
291
        * @var T
292
        */
293 72
        $value = $value;
294
295 72
        return $value;
296
    }
297
298
    /**
299
    * @template T as DaftObject
300
    *
301
    * @psalm-param class-string<T> $class
302
    */
303 16
    protected static function CachePublicGettersAndSettersProperties(string $class) : void
304
    {
305
        if (
306 16
            is_a($class, AbstractDaftObject::class, true) &&
307 16
            DefinitionAssistant::IsTypeUnregistered($class)
308
        ) {
309
            /**
310
            * @psalm-var class-string<T>
311
            */
312 16
            $class = DefinitionAssistant::RegisterAbstractDaftObjectType($class);
313
        }
314
315
        foreach (
316 16
            DefinitionAssistant::ObtainExpectedProperties($class) as $prop
317
        ) {
318 16
            static::CachePublicGettersAndSettersProperty($class, $prop);
319
        }
320 16
    }
321
322
    /**
323
    * @psalm-param class-string<DaftObject> $class
324
    */
325 16
    protected static function CachePublicGettersAndSettersProperty(
326
        string $class,
327
        string $prop
328
    ) : void {
329 16
        if (static::HasMethod($class, $prop, self::BOOL_EXPECTING_GETTER)) {
330 12
            self::$Getters[$class][$prop] = self::BOOL_METHOD_IS_PUBLIC;
331 4
        } elseif (static::HasMethod(
332 3
            $class,
333 2
            $prop,
334 4
            self::BOOL_EXPECTING_GETTER,
335 4
            self::BOOL_EXPECTING_NON_PUBLIC_METHOD
336
        )) {
337 4
            self::$Getters[$class][$prop] = self::BOOL_METHOD_IS_NON_PUBLIC;
338
        }
339
340 16
        if (static::HasMethod($class, $prop, self::BOOL_METHOD_IS_PUBLIC)) {
341 16
            self::$publicSetters[$class][] = $prop;
342
        }
343 16
    }
344
345
    /**
346
    * @psalm-param class-string<DaftObject> $class
347
    */
348 660
    private static function CachePublicGettersAndSetters(string $class) : void
349
    {
350 660
        if (false === isset(self::$Getters[$class])) {
351 16
            self::$Getters[$class] = [];
352 16
            self::$publicSetters[$class] = [];
353
354
            /**
355
            * @psalm-var class-string<DaftObject>
356
            */
357 16
            $class = $class;
358
359 16
            static::CachePublicGettersAndSettersProperties($class);
360
        }
361 660
    }
362
}
363