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.
Completed
Push — master ( 940692...3386dd )
by SignpostMarv
03:16
created

AbstractDaftObject   B

Complexity

Total Complexity 41

Size/Duplication

Total Lines 275
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
dl 0
loc 275
ccs 98
cts 98
cp 1
rs 8.2769
c 0
b 0
f 0
wmc 41

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A __set() 0 3 1
A __unset() 0 3 1
A __get() 0 3 1
A DaftObjectProperties() 0 3 1
A DaftObjectJsonPropertyNames() 0 13 3
A ThrowIfNotDaftJson() 0 4 2
A HasPublicMethod() 0 15 3
A DaftObjectPublicGetters() 0 5 1
A __debugInfo() 0 12 4
A DaftObjectExportableProperties() 0 3 1
A DaftObjectPublicSetters() 0 5 1
A DaftObjectNullableProperties() 0 3 1
A DaftObjectJsonProperties() 0 5 1
B CheckTypeDefinesOwnIdProperties() 0 24 5
B CachePublicGettersAndSetters() 0 21 6
A DaftObjectMethodNameFromProperty() 0 5 2
A DoGetSet() 0 7 2
A MaybeThrowOnDoGetSet() 0 10 4

How to fix   Complexity   

Complex Class

Complex classes like AbstractDaftObject 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 AbstractDaftObject, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
* Base daft objects.
4
*
5
* @author SignpostMarv
6
*/
7
declare(strict_types=1);
8
9
namespace SignpostMarv\DaftObject;
10
11
use ReflectionClass;
12
use ReflectionMethod;
13
14
/**
15
* Base daft object.
16
*/
17
abstract class AbstractDaftObject implements DaftObject
18
{
19
    /**
20
    * List of properties that can be defined on an implementation.
21
    *
22
    * @var array<int, string>
23
    */
24
    const PROPERTIES = [];
25
26
    /**
27
    * List of nullable properties that can be defined on an implementation.
28
    *
29
    * @var array<int, string>
30
    */
31
    const NULLABLE_PROPERTIES = [];
32
33
    /**
34
    * List of exportable properties that can be defined on an implementation.
35
    *
36
    * @var array<int, string>
37
    */
38
    const EXPORTABLE_PROPERTIES = [];
39
40
    /**
41
    * import/export definition for DaftJson.
42
    *
43
    * @var array<int, string>
44
    */
45
    const JSON_PROPERTIES = [];
46
47
    /**
48
    * @var array<string, array<int, string>>
49
    */
50
    private static $publicGetters = [];
51
52
    /**
53
    * @var array<string, array<int, string>>
54
    */
55
    private static $publicSetters = [];
56
57
    /**
58
    * Does some sanity checking.
59
    *
60
    * @see DefinesOwnIdPropertiesInterface
61
    * @see self::CheckTypeDefinesOwnIdProperties()
62
    */
63 376
    public function __construct()
64
    {
65 376
        self::CheckTypeDefinesOwnIdProperties(
66 376
            static::class,
67 376
            ($this instanceof DefinesOwnIdPropertiesInterface)
68
        );
69 372
    }
70
71 82
    public function __get(string $property)
72
    {
73 82
        return $this->DoGetSet($property, false);
74
    }
75
76 158
    public function __set(string $property, $v)
77
    {
78 158
        return $this->DoGetSet($property, true, $v);
79
    }
80
81
    /**
82
    * @see static::NudgePropertyValue()
83
    */
84 40
    public function __unset(string $property) : void
85
    {
86 40
        $this->NudgePropertyValue($property, null);
87 36
    }
88
89
    /**
90
    * @return array<string, mixed>
91
    */
92 62
    public function __debugInfo() : array
93
    {
94 62
        $out = [];
95 62
        $publicGetters = static::DaftObjectPublicGetters();
96 62
        foreach (static::DaftObjectExportableProperties() as $prop) {
97 60
            $expectedMethod = 'Get' . ucfirst($prop);
98 60
            if ($this->__isset($prop) && in_array($prop, $publicGetters, true)) {
99 60
                $out[(string) $prop] = $this->$expectedMethod();
100
            }
101
        }
102
103 62
        return $out;
104
    }
105
106
    /**
107
    * List of properties that can be defined on an implementation.
108
    *
109
    * @return array<int, string>
110
    */
111 266
    final public static function DaftObjectProperties() : array
112
    {
113 266
        return static::PROPERTIES;
114
    }
115
116 92
    final public static function DaftObjectNullableProperties() : array
117
    {
118 92
        return static::NULLABLE_PROPERTIES;
119
    }
120
121 124
    final public static function DaftObjectExportableProperties() : array
122
    {
123 124
        return static::EXPORTABLE_PROPERTIES;
124
    }
125
126 108
    final public static function DaftObjectPublicGetters() : array
127
    {
128 108
        static::CachePublicGettersAndSetters();
129
130 108
        return self::$publicGetters[static::class];
131
    }
132
133 158
    final public static function DaftObjectPublicSetters() : array
134
    {
135 158
        static::CachePublicGettersAndSetters();
136
137 158
        return self::$publicSetters[static::class];
138
    }
139
140 68
    final public static function DaftObjectJsonProperties() : array
141
    {
142 68
        static::ThrowIfNotDaftJson();
143
144 36
        return static::JSON_PROPERTIES;
145
    }
146
147 36
    final public static function DaftObjectJsonPropertyNames() : array
148
    {
149 36
        $out = [];
150
151 36
        foreach (static::DaftObjectJsonProperties() as $k => $prop) {
152 36
            if (is_string($k)) {
153 24
                $prop = $k;
154
            }
155
156 36
            $out[] = $prop;
157
        }
158
159 36
        return $out;
160
    }
161
162 164
    protected static function ThrowIfNotDaftJson() : void
163
    {
164 164
        if (false === is_a(static::class, DaftJson::class, true)) {
165 128
            throw new DaftObjectNotDaftJsonBadMethodCallException(static::class);
166
        }
167 36
    }
168
169 26
    final protected static function HasPublicMethod(
170
        ReflectionClass $classReflection,
171
        string $method
172
    ) : bool {
173
        if (
174 26
            $classReflection->hasMethod($method)
175
        ) {
176 26
            $methodReflection = new ReflectionMethod(static::class, $method);
177
178
            return
179 26
                $methodReflection->isPublic() &&
180 26
                false === $methodReflection->isStatic();
181
        }
182
183 8
        return false;
184
    }
185
186 216
    final protected static function CachePublicGettersAndSetters() : void
187
    {
188 216
        if (false === isset(self::$publicGetters[static::class])) {
189 26
            self::$publicGetters[static::class] = [];
190 26
            self::$publicSetters[static::class] = [];
191
192 26
            if (is_a(static::class, DefinesOwnIdPropertiesInterface::class, true)) {
193 14
                self::$publicGetters[static::class][] = 'id';
194
            }
195
196 26
            $classReflection = new ReflectionClass(static::class);
197
198 26
            foreach (static::DaftObjectProperties() as $property) {
199 26
                $getter = static::DaftObjectMethodNameFromProperty($property);
200 26
                $setter = static::DaftObjectMethodNameFromProperty($property, true);
201 26
                if (static::HasPublicMethod($classReflection, $getter)) {
202 22
                    self::$publicGetters[static::class][] = $property;
203
                }
204
205 26
                if (static::HasPublicMethod($classReflection, $setter)) {
206 26
                    self::$publicSetters[static::class][] = $property;
207
                }
208
            }
209
        }
210 216
    }
211
212
    /**
213
    * Nudge the state of a given property, marking it as dirty.
214
    *
215
    * @param string $property property being nudged
216
    * @param mixed $value value to nudge property with
217
    *
218
    * @throws UndefinedPropertyException if $property is not in static::DaftObjectProperties()
219
    * @throws PropertyNotNullableException if $property is not in static::DaftObjectNullableProperties()
220
    * @throws PropertyNotRewriteableException if class is write-once read-many and $property was already changed
221
    */
222
    abstract protected function NudgePropertyValue(string $property, $value) : void;
223
224
    /**
225
    * Checks if a type correctly defines it's own id.
226
    *
227
    * @throws ClassDoesNotImplementClassException if $class is not an implementation of DefinesOwnIdPropertiesInterface
228
    * @throws ClassMethodReturnHasZeroArrayCountException if $class::DaftObjectIdProperties() does not contain at least one property
229
    * @throws ClassMethodReturnIsNotArrayOfStringsException if $class::DaftObjectIdProperties() is not string[]
230
    * @throws UndefinedPropertyException if an id property is not in $class::DaftObjectIdProperties()
231
    */
232 376
    final protected static function CheckTypeDefinesOwnIdProperties(
233
        string $class,
234
        bool $throwIfNotImplementation = false
235
    ) : void {
236 376
        $interfaceCheck = $class;
237
238 376
        if (is_a($interfaceCheck, DefinesOwnIdPropertiesInterface::class, true)) {
239 232
            $properties = $class::DaftObjectIdProperties();
240
241 232
            if (count($properties) < 1) {
242 2
                throw new ClassMethodReturnHasZeroArrayCountException(
243 2
                    $class,
244 2
                    'DaftObjectIdProperties'
245
                );
246 230
            } elseif (count($properties) !== count(array_filter($properties, 'is_string'))) {
247 2
                throw new ClassMethodReturnIsNotArrayOfStringsException(
248 2
                    $class,
249 230
                    'DaftObjectIdProperties'
250
                );
251
            }
252 150
        } elseif ($throwIfNotImplementation) {
253 2
            throw new ClassDoesNotImplementClassException(
254 2
                $class,
255 2
                DefinesOwnIdPropertiesInterface::class
256
            );
257
        }
258 372
    }
259
260 206
    protected static function DaftObjectMethodNameFromProperty(
261
        string $property,
262
        bool $SetNotGet = false
263
    ) : string {
264 206
        return ($SetNotGet ? 'Set' : 'Get') . ucfirst($property);
265
    }
266
267 216
    protected function MaybeThrowOnDoGetSet(string $property, bool $setter, array $props) : void
268
    {
269 216
        if (false === in_array($property, $props, true)) {
270 10
            if (false === in_array($property, static::DaftObjectProperties(), true)) {
271 6
                throw new UndefinedPropertyException(static::class, $property);
272 4
            } elseif ($setter) {
273 2
                throw new NotPublicSetterPropertyException(static::class, $property);
274
            }
275
276 2
            throw new NotPublicGetterPropertyException(static::class, $property);
277
        }
278 206
    }
279
280
    /**
281
    * @param mixed $v
282
    *
283
    * @return mixed
284
    */
285 216
    protected function DoGetSet(string $property, bool $setter, $v = null)
286
    {
287 216
        $props = $setter ? static::DaftObjectPublicSetters() : static::DaftObjectPublicGetters();
288
289 216
        $this->MaybeThrowOnDoGetSet($property, $setter, $props);
290
291 206
        return $this->{static::DaftObjectMethodNameFromProperty($property, $setter)}($v);
292
    }
293
}
294