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 ( c08372...94cdbd )
by SignpostMarv
02:00
created

AbstractDaftObject::__construct()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 5
nc 1
nop 0
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 3
rs 9.4285
c 0
b 0
f 0
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 ReflectionMethod;
12
13
/**
14
* Base daft object.
15
*/
16
abstract class AbstractDaftObject implements DaftObject
17
{
18
    /**
19
    * List of properties that can be defined on an implementation.
20
    *
21
    * @var string[]
22
    */
23
    const PROPERTIES = [];
24
25
    /**
26
    * List of nullable properties that can be defined on an implementation.
27
    *
28
    * @var string[]
29
    */
30
    const NULLABLE_PROPERTIES = [];
31
32
    /**
33
    * Index of checked types.
34
    *
35
    * @see self::CheckTypeDefinesOwnIdProperties()
36
    *
37
    * @var bool[]
38
    */
39
    private static $checkedTypes = [];
40
41
    /**
42
    * Does some sanity checking.
43
    *
44
    * @see DefinesOwnIdPropertiesInterface
45
    * @see self::CheckTypeDefinesOwnIdProperties()
46
    *
47
    * @throws AlreadyIncorrectlyImplementedTypeException if static::class was previously determined to be incorrectly implemented
48
    */
49 44
    public function __construct()
50
    {
51
        if (
52 44
            ($this instanceof DefinesOwnIdPropertiesInterface) &&
53 32
            false === self::CheckTypeDefinesOwnIdProperties($this)
54
        ) {
55 1
            throw new AlreadyIncorrectlyImplementedTypeException(
56 1
                get_class($this) // phpunit coverage does not pick up static::class here
57
            );
58
        }
59 41
    }
60
61
    /**
62
    * {@inheritdoc}
63
    */
64 28
    public function __get(string $property)
65
    {
66 28
        return $this->DoGetSet($property, true);
67
    }
68
69
    /**
70
    * {@inheritdoc}
71
    */
72 15
    public function __set(string $property, $v)
73
    {
74 15
        return $this->DoGetSet($property, false, $v);
75
    }
76
77
    /**
78
    * {@inheritdoc}
79
    *
80
    * @see static::NudgePropertyValue()
81
    */
82 8
    public function __unset(string $property) : void
83
    {
84 8
        $this->NudgePropertyValue($property, null);
85 6
    }
86
87
    /**
88
    * List of properties that can be defined on an implementation.
89
    *
90
    * @return string[]
91
    */
92 6
    final public static function DaftObjectProperties() : array
93
    {
94 6
        return static::PROPERTIES;
95
    }
96
97
    /**
98
    * {@inheritdoc}
99
    */
100 9
    final public static function DaftObjectNullableProperties() : array
101
    {
102 9
        return static::NULLABLE_PROPERTIES;
103
    }
104
105
    /**
106
    * Nudge the state of a given property, marking it as dirty.
107
    *
108
    * @param string $property property being nudged
109
    * @param mixed $value value to nudge property with
110
    *
111
    * @throws UndefinedPropertyException if $property is not in static::DaftObjectProperties()
112
    * @throws PropertyNotNullableException if $property is not in static::DaftObjectNullableProperties()
113
    * @throws PropertyNotRewriteableException if class is write-once read-many and $property was already changed
114
    */
115
    abstract protected function NudgePropertyValue(
116
        string $property,
117
        $value
118
    ) : void;
119
120
    /**
121
    * Checks if a type correctly defines it's own id.
122
    *
123
    * @param DaftObject $object
124
    *
125
    * @throws ClassDoesNotImplementClassException if $object is not an implementation of DefinesOwnIdPropertiesInterface
126
    * @throws ClassMethodReturnHasZeroArrayCountException if $object::DaftObjectIdProperties() does not contain at least one property
127
    * @throws ClassMethodReturnIsNotArrayOfStringsException if $object::DaftObjectIdProperties() is not string[]
128
    * @throws UndefinedPropertyException if an id property is not in $object::DaftObjectIdProperties()
129
    */
130 33
    final protected static function CheckTypeDefinesOwnIdProperties(
131
        DaftObject $object
132
    ) : bool {
133 33
        static $checkedTypes = [];
134
135 33
        if (false === isset($checkedTypes[get_class($object)])) {
136 8
            $checkedTypes[get_class($object)] = false;
137
138 8
            if (false === ($object instanceof DefinesOwnIdPropertiesInterface)) {
139 1
                throw new ClassDoesNotImplementClassException(
140 1
                    get_class($object),
141 1
                    DefinesOwnIdPropertiesInterface::class
142
                );
143
            }
144
145
            /**
146
            * @var DefinesOwnIdPropertiesInterface $object
147
            */
148 7
            $object = $object;
149
150 7
            $properties = $object::DaftObjectIdProperties();
151
152 7
            if (count($properties) < 1) {
153 1
                throw new ClassMethodReturnHasZeroArrayCountException(
154 1
                    get_class($object),
155 1
                    'DaftObjectIdProperties'
156
                );
157
            }
158
159 6
            foreach ($properties as $property) {
160 6
                if (false === is_string($property)) {
161 1
                    throw new ClassMethodReturnIsNotArrayOfStringsException(
162 1
                        get_class($object),
163 1
                        'DaftObjectIdProperties'
164
                    );
165
                } elseif (
166 5
                    false === in_array(
167 5
                        $property,
168 5
                        $object::DaftObjectProperties(),
169 5
                        true
170
                    )
171
                ) {
172
                    throw new UndefinedPropertyException(
173
                        get_class($object),
174
                        $property
175
                    );
176
                }
177
            }
178
179 5
            $checkedTypes[get_class($object)] = true;
180
        }
181
182 30
        return $checkedTypes[get_class($object)];
183
    }
184
185
    /**
186
    * @param mixed $v
187
    *
188
    * @return mixed
189
    */
190 37
    private function DoGetSet(
191
        string $property,
192
        bool $getNotSet,
193
        $v = null
194
    ) {
195 37
        static $scopes = [];
196 37
        $expectedMethod = ($getNotSet ? 'Get' : 'Set') . ucfirst($property);
197
198 37
        if ($getNotSet) {
199 28
            if (true !== method_exists($this, $expectedMethod)) {
200 1
                throw new UndefinedPropertyException(static::class, $property);
201 27
            } elseif (false === $this->CheckPublicScope($expectedMethod)) {
202 1
                throw new NotPublicGetterPropertyException(
203 1
                    static::class,
204 1
                    $property
205
                );
206
            }
207
208 26
            return $this->$expectedMethod();
209
        } elseif (
210 15
            true !== method_exists($this, $expectedMethod)
211
        ) {
212 1
            throw new PropertyNotWriteableException(
213 1
                static::class,
214 1
                $property
215
            );
216 14
        } elseif (false === $this->CheckPublicScope($expectedMethod)) {
217 1
            throw new NotPublicSetterPropertyException(
218 1
                static::class,
219 1
                $property
220
            );
221
        }
222
223 13
        return $this->$expectedMethod($v);
224
    }
225
226 35
    private function CheckPublicScope(string $expectedMethod) : bool
227
    {
228 35
        static $scopes = [];
229 35
        if (false === isset($scopes[$expectedMethod])) {
230 9
            $scopes[$expectedMethod] = (
231 9
                new ReflectionMethod(static::class, $expectedMethod)
232 9
            )->isPublic();
233
        }
234
235 35
        return $scopes[$expectedMethod];
236
    }
237
}
238