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 (#11)
by Cees-Jan
10:32 queued 01:27
created

Hydrator::getHydrator()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 18
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 4

Importance

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