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 ( 4a7e81...ca99c5 )
by SignpostMarv
01:57
created

AbstractArrayBackedDaftObject   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 332
Duplicated Lines 3.01 %

Test Coverage

Coverage 86.43%

Importance

Changes 0
Metric Value
wmc 57
dl 10
loc 332
ccs 121
cts 140
cp 0.8643
rs 5.1724
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A MakePropertiesUnchanged() 0 4 2
A __isset() 0 5 2
A ChangedProperties() 0 8 1
A __construct() 0 11 4
A HasPropertyChanged() 0 5 2
B DaftObjectFromJsonType() 0 57 9
C DaftObjectFromJsonArray() 5 72 15
C NudgePropertyValue() 0 35 11
A DaftObjectFromJsonString() 5 9 2
B jsonSerialize() 0 29 5
A RetrievePropertyValueFromData() 0 14 4

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like AbstractArrayBackedDaftObject 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 AbstractArrayBackedDaftObject, 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
/**
12
* Array-backed daft objects.
13
*/
14
abstract class AbstractArrayBackedDaftObject extends AbstractDaftObject implements DaftObjectCreatedByArray
15
{
16
    /**
17
    * data for this instance.
18
    *
19
    * @var array
20
    */
21
    private $data = [];
22
23
    /**
24
    * List of changed properties.
25
    *
26
    * @var bool[]
27
    */
28
    private $changedProperties = [];
29
30
    /**
31
    * List of changed properties, for write-once read-many.
32
    *
33
    * @var bool[]
34
    */
35
    private $wormProperties = [];
36
37
    /**
38
    * {@inheritdoc}
39
    */
40 189
    public function __construct(array $data = [], bool $writeAll = false)
41
    {
42 189
        parent::__construct();
43
44 187
        if (true === $writeAll) {
45 60
            foreach ($data as $k => $v) {
46 60
                $this->__set($k, $v);
47
            }
48
        } else {
49 129
            foreach ($data as $k => $v) {
50 68
                $this->data[$k] = $v;
51
            }
52
        }
53 185
    }
54
55
    /**
56
    * {@inheritdoc}
57
    */
58 33
    public function __isset(string $property) : bool
59
    {
60
        return
61 33
            in_array($property, static::PROPERTIES, true) &&
62 33
            isset($this->data, $this->data[$property]);
63
    }
64
65
    /**
66
    * {@inheritdoc}
67
    */
68 29
    public function ChangedProperties() : array
69
    {
70
        /**
71
        * @var string[] $out
72
        */
73 29
        $out = array_keys($this->changedProperties);
74
75 29
        return $out;
76
    }
77
78
    /**
79
    * {@inheritdoc}
80
    */
81 33
    public function MakePropertiesUnchanged(string ...$properties) : void
82
    {
83 33
        foreach ($properties as $property) {
84 33
            unset($this->changedProperties[$property]);
85
        }
86 33
    }
87
88
    /**
89
    * {@inheritdoc}
90
    */
91 82
    public function HasPropertyChanged(string $property) : bool
92
    {
93
        return
94 82
            isset($this->changedProperties[$property]) &&
95 82
            true === $this->changedProperties[$property];
96
    }
97
98
    /**
99
    * {@inheritdoc}
100
    */
101 22
    public function jsonSerialize() : array
102
    {
103 22
        if (false === ($this instanceof DaftJson)) {
104 16
            throw new DaftObjectNotDaftJsonBadMethodCallException(
105 16
                static::class
106
            );
107
        }
108
109 6
        $out = [];
110
111 6
        foreach (static::DaftObjectJsonProperties() as $k => $v) {
112 6
            $property = $v;
113 6
            if (is_string($k)) {
114 3
                $property = $k;
115
            }
116
117 6
            $val = $this->DoGetSet(
118 6
                $property,
119 6
                'Get' . ucfirst($property),
120 6
                PropertyNotReadableException::class,
121 6
                NotPublicGetterPropertyException::class
122
            );
123
124 6
            if (false === is_null($val)) {
125 6
                $out[$property] = $val;
126
            }
127
        }
128
129 6
        return $out;
130
    }
131
132
    /**
133
    * {@inheritdoc}
134
    */
135 22
    final public static function DaftObjectFromJsonArray(
136
        array $array,
137
        bool $writeAll = false
138
    ) : DaftJson {
139 22 View Code Duplication
        if (false === is_a(static::class, DaftJson::class, true)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
140 16
            throw new DaftObjectNotDaftJsonBadMethodCallException(
141 16
                static::class
142
            );
143
        }
144
145 6
        $in = [];
146
147 6
        $props = static::DaftObjectJsonProperties();
148 6
        $jsonDef = static::DaftObjectJsonProperties();
149 6
        $nullableProps = static::DaftObjectNullableProperties();
150
151 6
        $jsonProps = [];
152
153 6
        foreach ($jsonDef as $k => $v) {
154 6
            if (is_string($k)) {
155 3
                $jsonProps[] = $k;
156
            } else {
157 6
                $jsonProps[] = $v;
158
            }
159
        }
160
161 6
        foreach ($jsonProps as $prop) {
162
            if (
163
                (
164 6
                    false === isset($array[$prop]) ||
165 6
                    is_null($array[$prop])
166
                ) &&
167 2
                false === in_array($prop, $nullableProps, true)
168
            ) {
169
                throw new PropertyNotNullableException(static::class, $prop);
170
            }
171
        }
172
173 6
        foreach (array_keys($array) as $prop) {
174
            if (
175 6
                false === in_array($prop, $props, true) &&
176 3
                false === isset($jsonDef[$prop])
177
            ) {
178
                throw new UndefinedPropertyException(static::class, $prop);
179
            } elseif (
180 6
                false === in_array($prop, $jsonProps, true)
181
            ) {
182
                throw new PropertyNotJsonDecodableException(
183
                    static::class,
184
                    $prop
185
                );
186 6
            } elseif (is_null($array[$prop])) {
187
                continue;
188 6
            } elseif (isset($jsonDef[$prop])) {
189 3
                $in[$prop] = static::DaftObjectFromJsonType(
190 3
                    $prop,
191 3
                    $jsonDef[$prop],
192 3
                    $array[$prop],
193 3
                    $writeAll
194
                );
195
            } else {
196 6
                $in[$prop] = $array[$prop];
197
            }
198
        }
199
200 6
        $out = new static($in, $writeAll);
201
202 6
        if ( ! ($out instanceof DaftJson)) { // here to trick phpstan
203
            exit;
204
        }
205
206 6
        return $out;
207
    }
208
209
    /**
210
    * @param mixed $propVal
211
    */
212 3
    protected static function DaftObjectFromJsonType(
213
        string $prop,
214
        string $jsonType,
215
        $propVal,
216
        bool $writeAll
217
    ) {
218 3
        $isArray = false;
219 3
        if ('[]' === mb_substr($jsonType, -2)) {
220 1
            $isArray = true;
221 1
            $jsonType = mb_substr($jsonType, 0, -2);
222
        }
223
224 3
        if ($isArray && false === is_array($propVal)) {
225
            throw new PropertyNotJsonDecodableShouldBeArrayException(
226
                static::class,
227
                $prop
228
            );
229 3
        } elseif (false === is_a($jsonType, DaftJson::class, true)) {
230
            throw new ClassDoesNotImplementClassException(
231
                $jsonType,
232
                DaftJson::class
233
            );
234
        }
235
236
        /**
237
        * @var DaftJson $jsonType
238
        */
239 3
        $jsonType = $jsonType;
240
241 3
        if ($isArray) {
242 1
            $out = [];
243
244 1
            foreach ($propVal as $i => $val) {
245 1
                if (is_array($val)) {
246 1
                    $out[] = $jsonType::DaftObjectFromJsonArray(
247 1
                        $val,
248 1
                        $writeAll
249
                    );
250
                } else {
251
                    throw new PropertyNotJsonDecodableShouldBeArrayException(
252
                        (string) $jsonType,
253
                        ($prop . '[' . $i . ']')
254
                    );
255
                }
256
            }
257
258 1
            return $out;
259 2
        } elseif (is_array($propVal)) {
260 2
            return $jsonType::DaftObjectFromJsonArray(
261 2
                $propVal,
262 2
                $writeAll
263
            );
264
        }
265
266
        throw new PropertyNotJsonDecodableShouldBeArrayException(
267
            (string) $jsonType,
268
            $prop
269
        );
270
    }
271
272 22
    public static function DaftObjectFromJsonString(string $string) : DaftJson
273
    {
274 22 View Code Duplication
        if (false === is_a(static::class, DaftJson::class, true)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
275 16
            throw new DaftObjectNotDaftJsonBadMethodCallException(
276 16
                static::class
277
            );
278
        }
279
280 6
        return static::DaftObjectFromJsonArray(json_decode($string, true));
281
    }
282
283
    /**
284
    * Retrieve a property from data.
285
    *
286
    * @param string $property the property being retrieved
287
    *
288
    * @throws PropertyNotNullableException if value is not set and $property is not listed as nullabe
289
    *
290
    * @return mixed the property value
291
    */
292 44
    protected function RetrievePropertyValueFromData(string $property)
293
    {
294
        if (
295 44
            false === array_key_exists($property, $this->data) &&
296 5
            false === in_array($property, static::NULLABLE_PROPERTIES, true)
297
        ) {
298 1
            throw new PropertyNotNullableException(static::class, $property);
299
        } elseif (
300 43
            in_array($property, static::NULLABLE_PROPERTIES, true)
301
        ) {
302 33
            return $this->data[$property] ?? null;
303
        }
304
305 43
        return $this->data[$property];
306
    }
307
308
    /**
309
    * {@inheritdoc}
310
    */
311 134
    protected function NudgePropertyValue(string $property, $value) : void
312
    {
313 134
        if (true !== in_array($property, static::PROPERTIES, true)) {
314 1
            throw new UndefinedPropertyException(static::class, $property);
315
        } elseif (
316 133
            true === is_null($value) &&
317 88
            true !== in_array($property, static::NULLABLE_PROPERTIES, true)
318
        ) {
319 58
            throw new PropertyNotNullableException(static::class, $property);
320
        } elseif (
321 75
            $this instanceof DaftObjectWorm &&
322
            (
323 50
                $this->HasPropertyChanged($property) ||
324
                (
325 50
                    isset($this->wormProperties[$property]) &&
0 ignored issues
show
Bug Best Practice introduced by
The property wormProperties does not exist on SignpostMarv\DaftObject\DaftObjectWorm. Since you implemented __get, consider adding a @property annotation.
Loading history...
326 2
                    true === $this->wormProperties[$property]
327
                )
328
            )
329
        ) {
330 50
            throw new PropertyNotRewriteableException(
331 50
                static::class,
332 50
                $property
333
            );
334
        }
335
336
        $isChanged = (
337 75
            false === array_key_exists($property, $this->data) ||
338 75
            $this->data[$property] !== $value
339
        );
340
341 75
        $this->data[$property] = $value;
342
343 75
        if ($isChanged && true !== isset($this->changedProperties[$property])) {
344 75
            $this->changedProperties[$property] = true;
345 75
            $this->wormProperties[$property] = true;
346
        }
347 75
    }
348
}
349