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 ( 809eaf...99f0e2 )
by Cees-Jan
02:14
created

AbstractResourceTest::getAnnotation()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 0
cts 23
cp 0
rs 8.8571
c 0
b 0
f 0
nc 3
cc 3
eloc 15
nop 2
crap 12
1
<?php
2
declare(strict_types=1);
3
4
namespace ApiClients\Tools\ResourceTestUtilities;
5
6
use ApiClients\Foundation\Hydrator\AnnotationInterface;
7
use ApiClients\Foundation\Hydrator\Annotations\Rename;
8
use ApiClients\Foundation\Resource\ResourceInterface;
9
use Doctrine\Common\Annotations\AnnotationReader;
10
use Doctrine\Common\Inflector\Inflector;
11
use phpDocumentor\Reflection\DocBlock;
12
use phpDocumentor\Reflection\DocBlockFactory;
13
use ReflectionClass;
14
use ReflectionProperty;
15
use TypeError;
16
17
abstract class AbstractResourceTest extends TestCase
18
{
19
    abstract public function getSyncAsync(): string;
20
    abstract public function getClass(): string;
21
    abstract public function getNamespace(): string;
22
23
    public function provideProperties(): array
24
    {
25
        return $this->providePropertiesGenerator('compatible');
26
    }
27
28
    public function providePropertiesIncompatible(): array
29
    {
30
        return $this->providePropertiesGenerator('incompatible');
31
    }
32
33
    public function providePropertiesGenerator(string $typeMethod): array
34
    {
35
        $yield = [];
36
        $class = new ReflectionClass($this->getClass());
37
38
        $jsonTemplate = [];
39
        foreach ($class->getProperties() as $property) {
40
            $key = $property->getName();
41
            $renamed = self::GetAnnotation($property->getDeclaringClass()->getName(), Rename::class);
0 ignored issues
show
introduced by
Consider using $property->class. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
42
43
            if ($renamed instanceof Rename && $renamed->has($key)) {
44
                $key = $renamed->get($key);
45
            }
46
47
            $jsonTemplate[$key] = '';
48
        }
49
50
        foreach ($class->getProperties() as $property) {
51
            $method = Inflector::camelize($property->getName());
52
            $docBlock = $this->getDocBlock($property->getDocComment());
53
54
            $varTag = $docBlock->getTagsByName('var');
55
            if (count($varTag) !== 1) {
56
                continue;
57
            }
58
59
            $varTag = $varTag[0];
60
            $scalar = (string)$varTag->getType();
61
            if ($scalar === '') {
62
                continue;
63
            }
64
65
            if (!Types::has($scalar)) {
66
                continue;
67
            }
68
69
            $type = Types::get($scalar);
70
            $yield += $this->generateTypeValues($type, $property, $method, $typeMethod, $jsonTemplate);
71
        }
72
73
        return $yield;
74
    }
75
76
    protected function generateTypeValues(
77
        Type $type,
78
        ReflectionProperty $property,
79
        string $method,
80
        string $typeMethod,
81
        array $jsonTemplate
82
    ): array {
83
        $yield = [];
84
        $json = $jsonTemplate;
85
        foreach ($type->$typeMethod() as $typeClass) {
86
            $methodType = Types::get(constant($typeClass . '::SCALAR'));
87
            foreach ($methodType->generate(1) as $value) {
88
                $key = $property->getName();
89
90
                $renamed = self::GetAnnotation($property->getDeclaringClass()->getName(), Rename::class);
0 ignored issues
show
introduced by
Consider using $property->class. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
91
                if ($renamed instanceof Rename && $renamed->has($key)) {
92
                    $key = $renamed->get($key);
93
                }
94
95
                $json[$key] = $value;
96
97
                $yield[] = [
98
                    $property->getName(), // Name of the property to assign data to
99
                    $method,              // Method to call verifying that data
100
                    $type,                // The different types of data associated with this field
101
                    $json,                // JSON to use during testing
102
                    $value,               // Value to check against
103
                ];
104
            }
105
        }
106
107
        return $yield;
108
    }
109
110
    /**
111
     * @param $docBlockContents
112
     * @return DocBlock
113
     */
114
    protected function getDocBlock(string $docBlockContents): DocBlock
115
    {
116
        if (class_exists('phpDocumentor\Reflection\DocBlockFactory')) {
117
            return DocBlockFactory::createInstance()->create($docBlockContents);
118
        }
119
120
        return new DocBlock($docBlockContents);
121
    }
122
123
    /**
124
     * @param string $class
125
     * @param string $annotationClass
126
     * @return null|AnnotationInterface
127
     */
128
    protected static function getAnnotation(string $class, string $annotationClass)
129
    {
130
        $annotationReader = new AnnotationReader();
131
132
        $annotation = $annotationReader
133
            ->getClassAnnotation(
134
                new ReflectionClass($class),
135
                $annotationClass
136
            )
137
        ;
138
139
        if (get_class($annotation) === $annotationClass) {
140
            return $annotation;
141
        }
142
143
        $class = get_parent_class($class);
144
145
        if ($class === false) {
146
            return null;
147
        }
148
149
        return $annotationReader
150
            ->getClassAnnotation(
151
                new ReflectionClass($class),
152
                $annotationClass
153
            )
154
            ;
155
    }
156
157
    /**
158
     * @dataProvider provideProperties
159
     */
160
    public function testProperties(string $property, string $method, Type $type, array $json, $value)
0 ignored issues
show
Unused Code introduced by
The parameter $property is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
161
    {
162
        $class = $this->getClass();
163
        $resource = $this->hydrate(
164
            str_replace(
165
                $this->getNamespace(),
166
                $this->getNamespace() . '\\Async',
167
                $class
168
            ),
169
            $json,
170
            'Async'
171
        );
172
        $this->assertSame($value, $resource->{$method}());
173
        $this->assertInternalType($type->scalar(), $resource->{$method}());
174
    }
175
176
    /**
177
     * @dataProvider providePropertiesIncompatible
178
     * @expectedException TypeError
179
     */
180
    public function testPropertiesIncompatible(string $property, string $method, Type $type, array $json, $value)
0 ignored issues
show
Unused Code introduced by
The parameter $property is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $type is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
181
    {
182
        $class = $this->getClass();
183
        $resource = $this->hydrate(
184
            str_replace(
185
                $this->getNamespace(),
186
                $this->getNamespace() . '\\Async',
187
                $class
188
            ),
189
            $json,
190
            'Async'
191
        );
192
193
        if ($value !== $resource->{$method}()) {
194
            throw new TypeError();
195
        }
196
197
        $this->fail('We should not reach this');
198
    }
199
200
    public function testInterface()
201
    {
202
        $this->assertTrue(
203
            is_subclass_of(
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \ApiClients\Foundation\R...esourceInterface::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
204
                $this->getClass(),
205
                ResourceInterface::class
206
            )
207
        );
208
    }
209
}
210