Passed
Push — master ( 14eeeb...bf0e1b )
by SignpostMarv
02:49
created

DefinitionAssistant::ValidateClosure()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 55
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 36
nc 4
nop 3
dl 0
loc 55
ccs 34
cts 34
cp 1
crap 4
rs 9.344
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A DefinitionAssistant::MaybeRegisterTypeSetter() 0 12 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
* @author SignpostMarv
4
*/
5
declare(strict_types=1);
6
7
namespace SignpostMarv\DaftMagicPropertyAnalysis;
8
9
use Closure;
10
use InvalidArgumentException;
11
12
class DefinitionAssistant
13
{
14
    const ARG_INDEX_CLOSURE_GETTER = 2;
15
16
    const ARG_INDEX_CLOSURE_SETTER = 3;
17
18
    const IN_ARRAY_STRICT_MODE = true;
19
20
    const COUNT_EXPECTED_REQUIRED_PARAMETERS = 1;
21
22
    const PARAM_INDEX_FIRST = 0;
23
24
    const BOOL_IS_PARAM = true;
25
26
    const BOOL_IS_RETURN = false;
27
28
    /**
29
    * @var array<string, array<int, string>>
30
    *
31
    * @psalm-var array<class-string, array<int, string>>
32
    */
33
    protected static $properties = [];
34
35
    /**
36
    * @var array<string, Closure>
37
    *
38
    * @psalm-var array<class-string, Closure(string):?string>
39
    */
40
    protected static $getters = [];
41
42
    /**
43
    * @var array<string, Closure>
44
    *
45
    * @psalm-var array<class-string, Closure(string):?string>
46
    */
47
    protected static $setters = [];
48
49
    /**
50
    * @psalm-param class-string $type
51
    */
52 14
    public static function IsTypeUnregistered(string $type) : bool
53
    {
54 14
        return ! isset(static::$properties[$type]);
55
    }
56
57
    /**
58
    * @psalm-param class-string $type
59
    * @psalm-param null|Closure(string):?string $getter
60
    * @psalm-param null|Closure(string):?string $setter
61
    */
62 14
    public static function RegisterType(
63
        string $type,
64
        ? Closure $getter,
65
        ? Closure $setter,
66
        string $property,
67
        string ...$properties
68
    ) : void {
69 14
        if ( ! self::IsTypeUnregistered($type)) {
70 4
            throw new InvalidArgumentException(
71
                'Argument 1 passed to ' .
72
                __METHOD__ .
73 4
                '() has already been registered!'
74
            );
75 14
        } elseif (is_null($getter) && is_null($setter)) {
76 2
            throw new InvalidArgumentException(
77 2
                'One or both of arguments 2 and 3 must be specified!'
78
            );
79
        }
80
81 12
        array_unshift($properties, $property);
82
83 12
        static::MaybeRegisterTypeGetter($type, $getter);
84 10
        static::MaybeRegisterTypeSetter($type, $setter);
0 ignored issues
show
Bug introduced by
$type of type object is incompatible with the type string expected by parameter $type of SignpostMarv\DaftMagicPr...ybeRegisterTypeSetter(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

84
        static::MaybeRegisterTypeSetter(/** @scrutinizer ignore-type */ $type, $setter);
Loading history...
85
86 8
        static::$properties[$type] = $properties;
87 8
    }
88
89
    /**
90
    * @psalm-param class-string $type
91
    */
92 2
    public static function GetterMethodName(string $type, string $property) : ? string
93
    {
94
        if (
95 2
            in_array($property, static::$properties[$type] ?? [], self::IN_ARRAY_STRICT_MODE) &&
96 2
            isset(static::$getters[$type])
97
        ) {
98 2
            return static::$getters[$type]($property);
99
        }
100
101 2
        return self::CheckOtherTypes(self::$getters, $type, $property);
102
    }
103
104
    /**
105
    * @psalm-param class-string $type
106
    */
107 2
    public static function SetterMethodName(string $type, string $property) : ? string
108
    {
109
        if (
110 2
            in_array($property, static::$properties[$type] ?? [], self::IN_ARRAY_STRICT_MODE) &&
111 2
            isset(static::$setters[$type])
112
        ) {
113 2
            return static::$setters[$type]($property);
114
        }
115
116 2
        return self::CheckOtherTypes(self::$setters, $type, $property);
117
    }
118
119
    /**
120
    * @param mixed $maybe
121
    *
122
    * @psalm-param class-string|object $maybe
123
    *
124
    * @return array<int, string>
125
    */
126 4
    public static function ObtainExpectedProperties($maybe) : array
127
    {
128
        /**
129
        * @var array<int, string>
130
        */
131 4
        $out = array_values(array_unique(array_reduce(
132 4
            array_filter(
133 4
                static::$properties,
134
                function (string $type) use ($maybe) : bool {
135 4
                    return is_a($maybe, $type, is_string($maybe));
136 4
                },
137 4
                ARRAY_FILTER_USE_KEY
138
            ),
139 4
            'array_merge',
140 4
            []
141
        )));
142
143 4
        return $out;
144
    }
145
146
    /**
147
    * @param array<string, Closure> $otherTypes
148
    *
149
    * @psalm-param array<class-string, Closure(string):?string> $otherTypes
150
    * @psalm-param class-string $type
151
    */
152 4
    protected static function CheckOtherTypes(
153
        array $otherTypes,
154
        string $type,
155
        string $property
156
    ) : ? string {
157 4
        foreach ($otherTypes as $otherType => $getter) {
158
            if (
159 4
                $otherType !== $type &&
160 4
                isset(self::$properties[$otherType]) &&
161 4
                in_array($property, self::$properties[$otherType], self::IN_ARRAY_STRICT_MODE)
162
            ) {
163 4
                return $getter($property);
164
            }
165
        }
166
167 4
        return null;
168
    }
169
170
    /**
171
    * @psalm-param class-string $type
172
    * @psalm-param null|Closure(string):?string $getter
173
    */
174 12
    private static function MaybeRegisterTypeGetter(string $type, ? Closure $getter) : void
175
    {
176 12
        if ( ! is_null($getter)) {
177 10
            if ( ! method_exists($type, '__get')) {
178 2
                throw new InvalidArgumentException(
179
                    'Argument 1 passed to ' .
180
                    __CLASS__ .
181 2
                    '::RegisterType() must declare __get() !'
182
                );
183
            }
184
185 8
            self::$getters[$type] = $getter;
186
        }
187 10
    }
188
189
    /**
190
    * @psalm-param class-string $type
191
    * @psalm-param null|Closure(string):?string $setter
192
    */
193 10
    private static function MaybeRegisterTypeSetter(string $type, ? Closure $setter) : void
194
    {
195 10
        if ( ! is_null($setter)) {
196 10
            if ( ! method_exists($type, '__set')) {
197 2
                throw new InvalidArgumentException(
198
                    'Argument 1 passed to ' .
199
                    __CLASS__ .
200 2
                    '::RegisterType() must declare __set() !'
201
                );
202
            }
203
204 8
            self::$setters[$type] = $setter;
205
        }
206 8
    }
207
}
208