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.
Passed
Push — master ( 2fb392...923b97 )
by SignpostMarv
04:18
created

PropertyReflectionExtension::getType()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
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\PHPStan;
10
11
use BadMethodCallException;
12
use InvalidArgumentException;
13
use PHPStan\Broker\Broker;
14
use PHPStan\Reflection\ClassReflection;
15
use PHPStan\Reflection\PropertyReflection;
16
use PHPStan\Type\MixedType;
17
use PHPStan\Type\Type;
18
use PHPStan\Type\TypehintHelper;
19
use ReflectionMethod;
20
use SignpostMarv\DaftObject\DaftObject;
21
use SignpostMarv\DaftObject\DefinesOwnIdPropertiesInterface;
22
use SignpostMarv\DaftObject\TypeParanoia;
23
use SignpostMarv\DaftObject\TypeUtilities;
24
25
class PropertyReflectionExtension implements PropertyReflection
26
{
27
    const REF_PARAM_INDEX = 0;
28
29
    const BOOL_IS_WRITEABLE = true;
30
31
    const BOOL_IS_READABLE = true;
32
33
    const BOOL_SETNOTGET_SETTER = true;
34
35
    const BOOL_SETNOTGET_GETTER = false;
36
37
    const BOOL_CLASS_NOT_DAFTOBJECT = false;
38
39
    const BOOL_REFLECTION_NO_FILE = false;
40
41
    const BOOL_NOT_VARIADIC = false;
42
43
    const BOOL_IS_STATIC = false;
44
45
    /**
46
    * @var Type
47
    */
48
    protected $type;
49
50
    /**
51
    * @var Broker
52
    */
53
    protected $broker;
54
55
    /**
56
    * @var bool
57
    */
58
    protected $readable = false;
59
60
    /**
61
    * @var bool
62
    */
63
    protected $writeable = false;
64
65
    /**
66
    * @var bool
67
    */
68
    protected $public;
69
70
    /**
71
    * @var ClassReflection|null
72
    */
73
    protected $readableReflection;
74
75
    /**
76
    * @var ClassReflection|null
77
    */
78
    protected $writeableReflection;
79
80
    public function __construct(ClassReflection $classReflection, Broker $broker, string $property)
81
    {
82
        if ( ! TypeParanoia::IsThingStrings($classReflection->getName(), DaftObject::class)) {
83
            throw new InvalidArgumentException(sprintf('%s is not an implementation of %s',
84
                $classReflection->getName(),
85
                DaftObject::class
86
            ));
87
        }
88
89
        $this->broker = $broker;
90
91
        $this->public = static::PropertyIsPublic($classReflection->getName(), $property);
92
93
        $this->type = new MixedType();
94
95
        $this->SetupReflections($classReflection, $property);
96
    }
97
98
    public function getType() : Type
99
    {
100
        return $this->type;
101
    }
102
103
    public function isReadable() : bool
104
    {
105
        return $this->readable;
106
    }
107
108
    public function isWritable() : bool
109
    {
110
        return $this->writeable;
111
    }
112
113
    public function isPublic() : bool
114
    {
115
        return $this->public;
116
    }
117
118
    public function isPrivate() : bool
119
    {
120
        return ! $this->isPublic();
121
    }
122
123
    public function isStatic() : bool
124
    {
125
        return self::BOOL_IS_STATIC;
126
    }
127
128
    public function getDeclaringClass() : ClassReflection
129
    {
130
        $reflection = $this->readable ? $this->readableReflection : $this->writeableReflection;
131
132
        if ( ! ($reflection instanceof ClassReflection)) {
133
            throw new BadMethodCallException(
134
                static::class .
135
                '::SetupReflections() was not called before ' .
136
                __METHOD__ .
137
                ' was called!'
138
            );
139
        }
140
141
        return $reflection;
142
    }
143
144
    protected static function DetermineDeclaringClass(
145
        Broker $broker,
146
        ReflectionMethod $refMethod
147
    ) : ClassReflection {
148
        $reflectionClass = $refMethod->getDeclaringClass();
149
150
        $filename = null;
151
        if (self::BOOL_REFLECTION_NO_FILE !== $reflectionClass->getFileName()) {
152
            $filename = $reflectionClass->getFileName();
153
        }
154
155
        return $broker->getClassFromReflection(
156
            $reflectionClass,
157
            $reflectionClass->getName(),
158
            $reflectionClass->isAnonymous() ? $filename : null
159
        );
160
    }
161
162
    /**
163
    * @psalm-suppress InvalidStringClass
164
    * @psalm-suppress MixedMethodCall
165
    */
166
    protected static function PropertyIsPublic(string $className, string $property) : bool
167
    {
168
        if ( ! TypeParanoia::IsSubThingStrings($className, DaftObject::class)) {
169
            return self::BOOL_CLASS_NOT_DAFTOBJECT;
170
        }
171
172
        return
173
            (
174
                TypeParanoia::IsThingStrings(
175
                    $className,
176
                    DefinesOwnIdPropertiesInterface::class
177
                ) &&
178
                'id' === $property
179
            ) ||
180
            TypeParanoia::MaybeInMaybeArray($property, $className::DaftObjectPublicGetters()) ||
181
            TypeParanoia::MaybeInMaybeArray($property, $className::DaftObjectPublicSetters());
182
    }
183
184
    private function SetupReflections(ClassReflection $classReflection, string $property) : void
185
    {
186
        $class = $classReflection->getName();
187
        $get = TypeUtilities::MethodNameFromProperty($property, self::BOOL_SETNOTGET_GETTER);
188
        $set = TypeUtilities::MethodNameFromProperty($property, self::BOOL_SETNOTGET_SETTER);
189
190
        $this->writeableReflection = $this->readableReflection = $classReflection;
191
192
        if ($classReflection->getNativeReflection()->hasMethod($get)) {
193
            $this->readableReflection = $this->SetGetterProps(new ReflectionMethod($class, $get));
194
        }
195
196
        if ($classReflection->getNativeReflection()->hasMethod($set)) {
197
            $this->writeableReflection = $this->SetSetterProps($class, $set);
198
        }
199
    }
200
201
    private function SetGetterProps(ReflectionMethod $refMethod) : ClassReflection
202
    {
203
        $this->readable = self::BOOL_IS_READABLE;
204
205
        if ($refMethod->isStatic()) {
206
            throw new InvalidArgumentException(
207
                'Implementations of ' .
208
                DaftObject::class .
209
                ' must not contain static getters.'
210
            );
211
        }
212
213
        if ($refMethod->hasReturnType()) {
214
            $this->type = TypehintHelper::decideTypeFromReflection($refMethod->getReturnType());
215
        }
216
217
        return static::DetermineDeclaringClass($this->broker, $refMethod);
218
    }
219
220
    private function SetSetterProps(string $class, string $set) : ClassReflection
221
    {
222
        $refMethod = new ReflectionMethod($class, $set);
223
        $this->writeable = self::BOOL_IS_WRITEABLE;
224
225
        $refParam = $refMethod->getParameters()[self::REF_PARAM_INDEX];
226
227
        if ($refParam->hasType()) {
228
            $this->type = TypehintHelper::decideTypeFromReflection(
229
                $refParam->getType(),
230
                null,
231
                $class,
232
                self::BOOL_NOT_VARIADIC
233
            );
234
        }
235
236
        return static::DetermineDeclaringClass($this->broker, $refMethod);
237
    }
238
}
239