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
Pull Request — master (#4)
by Cees-Jan
07:33
created

Hydrator::preheat()   B

Complexity

Conditions 5
Paths 5

Size

Total Lines 28
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 12
cts 12
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 16
nc 5
nop 2
crap 5
1
<?php declare(strict_types=1);
2
3
namespace ApiClients\Foundation\Hydrator;
4
5
use Doctrine\Common\Annotations\AnnotationReader;
6
use Doctrine\Common\Annotations\CachedReader;
7
use Doctrine\Common\Annotations\Reader;
8
use Doctrine\Common\Cache\Cache;
9
use GeneratedHydrator\Configuration;
10
use ReflectionClass;
11
use RecursiveDirectoryIterator;
12
use RecursiveIteratorIterator;
13
use ApiClients\Foundation\Resource\ResourceInterface;
14
use ApiClients\Foundation\Resource\AbstractResource;
15
use Zend\Hydrator\HydratorInterface;
16
17
class Hydrator
18
{
19
    /**
20
     * @var array
21
     */
22
    protected $options;
23
24
    /**
25
     * @var array
26
     */
27
    protected $hydrators = [];
28
29
    /**
30
     * @var array
31
     */
32
    protected $annotations = [];
33
34
    /**
35
     * @var HandlerInterface[]
36
     */
37
    protected $annotationHandlers = [];
38
39
    /**
40
     * @var Reader
41
     */
42
    protected $annotationReader;
43
44
    /**
45 4
     * @param array $options
46
     */
47 4
    public function __construct(array $options)
48
    {
49 4
        $this->options = $options;
50 4
51 4
        $reader = new AnnotationReader();
52
        if (isset($this->options[Options::ANNOTATION_CACHE]) &&
53 1
            $this->options[Options::ANNOTATION_CACHE] instanceof Cache
54
        ) {
55 1
            $reader = new CachedReader(
56
                $reader,
57
                $this->options[Options::ANNOTATION_CACHE]
58 4
            );
59
        }
60 4
        $this->annotationReader = $reader;
61 4
62 4
        $this->setUpAnnotations();
63
        $this->addSelfToExtraProperties();
64 4
    }
65
66 4
    protected function setUpAnnotations()
67
    {
68
        if (!isset($this->options[Options::ANNOTATIONS])) {
69
            return;
70 4
        }
71 4
72
        foreach ($this->options[Options::ANNOTATIONS] as $annotationClass => $handler) {
73 4
            $this->annotationHandlers[$annotationClass] = new $handler($this);
74
        }
75 4
    }
76
77 4
    protected function addSelfToExtraProperties()
78 4
    {
79
        $this->options[Options::EXTRA_PROPERTIES]['hydrator'] = $this;
80
    }
81
82
    public function preheat(string $scanTarget, string $namespace)
83
    {
84
        $directory = new RecursiveDirectoryIterator($scanTarget);
85 4
        $directory = new RecursiveIteratorIterator($directory);
86
87 4
        foreach ($directory as $node) {
88 4
            if (!is_file($node->getPathname())) {
89
                continue;
90
            }
91 4
92 4
            $file = substr($node->getPathname(), strlen($scanTarget));
93
            $file = ltrim($file, DIRECTORY_SEPARATOR);
94
            $file = rtrim($file, '.php');
95 4
96
            $class = $namespace . '\\' . str_replace(DIRECTORY_SEPARATOR, '\\', $file);
97
98
            if (!class_exists($class)) {
99
                continue;
100
            }
101
102
            if (!is_subclass_of($class, ResourceInterface::class)) {
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...
103 4
                continue;
104
            }
105 4
106 4
            $this->getHydrator($class);
107 4
            $this->annotationReader->getClassAnnotations(new ReflectionClass($class));
108 4
        }
109 4
    }
110
111
    /**
112 4
     * @param string $class
113
     * @param array $json
114
     * @return ResourceInterface
115
     */
116 View Code Duplication
    public function hydrate(string $class, array $json): ResourceInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
117
    {
118
        $fullClassName = implode(
119
            '\\',
120 4
            [
121
                $this->options[Options::NAMESPACE],
122 4
                $this->options[Options::NAMESPACE_SUFFIX],
123 4
                $class,
124 4
            ]
125 4
        );
126
        return $this->hydrateFQCN($fullClassName, $json);
127
    }
128 4
129
    /**
130
     * @param string $class
131 4
     * @param array $json
132
     * @return ResourceInterface
133
     */
134
    public function hydrateFQCN(string $class, array $json): ResourceInterface
135
    {
136
        $hydrator = $this->getHydrator($class);
137
        $object = new $class();
138
        $json = $this->hydrateApplyAnnotations($json, $object);
139 2
        $resource = $hydrator->hydrate($json, $object);
140
        if ($resource instanceof AbstractResource) {
141 2
            $resource->setExtraProperties($this->options[Options::EXTRA_PROPERTIES]);
142 2
        }
143
        return $resource;
144
    }
145 2
146 2
    /**
147
     * @param array $json
148
     * @param ResourceInterface $object
149 2
     * @return array
150
     */
151 View Code Duplication
    protected function hydrateApplyAnnotations(array $json, ResourceInterface $object): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
152
    {
153
        foreach ($this->annotationHandlers as $annotationClass => $handler) {
154
            $annotation = $this->getAnnotation($object, $annotationClass);
155
            if ($annotation === null) {
156
                continue;
157
            }
158 2
159
            $json = $handler->hydrate($annotation, $json, $object);
160 2
        }
161 2
162 2
        return $json;
163
    }
164
165
    /**
166
     * @param string $class
167
     * @param ResourceInterface $object
168
     * @return array
169
     */
170 2 View Code Duplication
    public function extract(string $class, ResourceInterface $object): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
171
    {
172 2
        $fullClassName = implode(
173 2
            '\\',
174 2
            [
175 2
                $this->options[Options::NAMESPACE],
176
                $this->options[Options::NAMESPACE_SUFFIX],
177
                $class,
178 2
            ]
179
        );
180
        return $this->extractFQCN($fullClassName, $object);
181 2
    }
182
183
    /**
184
     * Takes a fully qualified class name and extracts the data for that class from the given $object
185
     * @param string $class
186
     * @param ResourceInterface $object
187
     * @return array
188
     */
189 4
    public function extractFQCN(string $class, ResourceInterface $object): array
190
    {
191 4
        $json = $this->getHydrator($class)->extract($object);
192 4
        $json = $this->extractApplyAnnotations($object, $json);
193 2
        return $json;
194
    }
195
196 4
    /**
197 4
     * @param array $json
198
     * @param ResourceInterface $object
199
     * @return array
200 4
     */
201 4 View Code Duplication
    protected function extractApplyAnnotations(ResourceInterface $object, array $json): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
202 4
    {
203
        foreach ($this->annotationHandlers as $annotationClass => $handler) {
204
            $annotation = $this->getAnnotation($object, $annotationClass);
205
            if ($annotation === null) {
206
                continue;
207 4
            }
208
209
            $json = $handler->extract($annotation, $object, $json);
210
        }
211 4
212 4
        return $json;
213 4
    }
214
215
    /**
216
     * @param ResourceInterface $object
217
     * @param string $annotationClass
218 4
     * @return null|AnnotationInterface
219
     */
220
    protected function getAnnotation(ResourceInterface $object, string $annotationClass)
221
    {
222
        $class = get_class($object);
223
        if (isset($this->annotations[$class][$annotationClass])) {
224
            return $this->annotations[$class][$annotationClass];
225
        }
226 1
227
        if (!isset($this->annotations[$class])) {
228 1
            $this->annotations[$class] = [];
229
        }
230 1
231
        $this->annotations[$class][$annotationClass] = $this->annotationReader
232
            ->getClassAnnotation(
233
                new ReflectionClass($object),
234
                $annotationClass
235
            )
236
        ;
237
238
        if (get_class($this->annotations[$class][$annotationClass]) === $annotationClass) {
239
            return $this->annotations[$class][$annotationClass];
240
        }
241 4
242
        $this->annotations[$class][$annotationClass] = $this->annotationReader
243 4
            ->getClassAnnotation(
244 4
                new ReflectionClass(get_parent_class($object)),
245
                $annotationClass
246
            )
247 4
        ;
248 4
249 4
        return $this->annotations[$class][$annotationClass];
250
    }
251 4
252 4
    /**
253
     * @param string $resource
254 4
     * @param ResourceInterface $object
255 4
     * @return ResourceInterface
256
     */
257 4
    public function buildAsyncFromSync(string $resource, ResourceInterface $object): ResourceInterface
258
    {
259
        return $this->hydrateFQCN(
260
            $this->options[Options::NAMESPACE] . '\\Async\\' . $resource,
261
            $this->extractFQCN(
262
                $this->options[Options::NAMESPACE] . '\\Sync\\' . $resource,
263
                $object
264
            )
265
        );
266
    }
267
268
    /**
269
     * @param string $class
270
     * @return HydratorInterface
271
     */
272
    protected function getHydrator(string $class): HydratorInterface
273
    {
274
        if (isset($this->hydrators[$class])) {
275
            return $this->hydrators[$class];
276
        }
277
278
        $config = new Configuration($class);
279
        if (isset($this->options[Options::RESOURCE_CACHE_DIR])) {
280
            $config->setGeneratedClassesTargetDir($this->options[Options::RESOURCE_CACHE_DIR]);
281
        }
282
        if (isset($this->options[Options::RESOURCE_NAMESPACE])) {
283
            $config->setGeneratedClassesNamespace($this->options[Options::RESOURCE_NAMESPACE]);
284
        }
285
        $hydrator = $config->createFactory()->getHydratorClass();
286
        $this->hydrators[$class] = new $hydrator;
287
288
        return $this->hydrators[$class];
289
    }
290
}
291