AnnotationLoader::loadDefinition()   B
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 30
ccs 16
cts 16
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 17
nc 5
nop 1
crap 5
1
<?php
2
3
namespace BrainExe\Core;
4
5
use BrainExe\Core\Annotations\Service;
6
use BrainExe\Core\Annotations\Builder\ServiceDefinition;
7
use Doctrine\Common\Annotations\AnnotationReader;
8
use Doctrine\Common\Annotations\AnnotationRegistry;
9
use Doctrine\Common\Annotations\IndexedReader;
10
use RecursiveDirectoryIterator;
11
use RecursiveIteratorIterator;
12
use ReflectionClass;
13
use SplFileInfo;
14
use Symfony\Component\Config\Loader\Loader as ConfigLoader;
15
use Symfony\Component\DependencyInjection\ContainerBuilder;
16
17
class AnnotationLoader extends ConfigLoader
18
{
19
    /**
20
     * @var ContainerBuilder
21
     */
22
    private $container;
23
24
    /**
25
     * @var AnnotationReader
26
     */
27
    private $reader;
28
29
    /**
30
     * @var ServiceDefinition[]
31
     */
32
    private $builders = [];
33
34
    /**
35
     * @param ContainerBuilder $container
36
     * @param ServiceDefinition[] $builders
37
     */
38 1
    public function __construct(ContainerBuilder $container, array $builders = [])
39
    {
40 1
        $this->container = $container;
41 1
        $this->builders  = $builders;
42 1
        $this->reader    = new IndexedReader(new AnnotationReader());
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Doctrine\Common\Ann...ons\AnnotationReader()) of type object<Doctrine\Common\Annotations\IndexedReader> is incompatible with the declared type object<Doctrine\Common\A...tions\AnnotationReader> of property $reader.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
43
44 1
        AnnotationRegistry::registerLoader(function ($class) {
45 1
            return class_exists($class);
46 1
        });
47 1
    }
48
49
    /**
50
     * {@inheritdoc}
51
     */
52 1
    public function load($path, $type = null)
53
    {
54 1
        $includedFiles = $this->includeFiles($path);
55 1
        $this->processFiles($includedFiles);
56 1
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function supports($resource, $type = null)
62
    {
63
        return is_dir($resource);
64
    }
65
66
    /**
67
     * @param ReflectionClass $reflection
68
     * @return array
69
     */
70 1
    private function loadDefinition(ReflectionClass $reflection) : array
71
    {
72 1
        $annotation = $this->reader->getClassAnnotation($reflection, Service::class);
73 1
        $definitions = [];
74
75
        /** @var ServiceDefinition $builder */
76 1
        if ($annotation) {
77 1
            $annotationClass = get_class($annotation);
78
79 1
            $class = $reflection->getName();
80 1
            $definition = $this->container->register($class, $class);
81
82 1
            if (isset($this->builders[$annotationClass])) {
83 1
                $builder = $this->builders[$annotationClass];
84
            } else {
85
                /** @var string|Service $annotationClass */
86 1
                $this->builders[$annotationClass] = $builder = $annotationClass::getBuilder(
87 1
                    $this->container,
88 1
                    $this->reader
89
                );
90
            }
91
92 1
            list($alias) = $builder->build($reflection, $annotation, $definition);
93 1
            if ($alias && $alias !== $class) {
94 1
                $this->container->setAlias($alias, $class);
95
            }
96
        }
97
98 1
        return $definitions;
99
    }
100
101
    /**
102
     * @param string $path
103
     * @return string[]
104
     */
105 1
    private function includeFiles(string $path) : array
106
    {
107 1
        $includedFiles = [];
108
109
        /** @var SplFileInfo[] $directoryIterator */
110 1
        $directoryIterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
111 1
        foreach ($directoryIterator as $fileInfo) {
112 1
            if ($fileInfo->getExtension() === 'php') {
113 1
                $included = $this->includeFile($fileInfo);
114 1
                $includedFiles[$included] = true;
115
            }
116
        }
117
118 1
        return $includedFiles;
119
    }
120
121
    /**
122
     * @param string[] $includedFiles
123
     */
124 1
    private function processFiles(array $includedFiles) : void
125
    {
126 1
        $declaredClasses = get_declared_classes();
127 1
        foreach ($declaredClasses as $className) {
128 1
            $reflection = new ReflectionClass($className);
129 1
            $filename   = $reflection->getFileName();
130
131 1
            if (isset($includedFiles[$filename])) {
132 1
                $this->loadDefinition($reflection);
133
            }
134
        }
135 1
    }
136
137
    /**
138
     * @param SplFileInfo $fileInfo
139
     * @return string
140
     */
141 1
    private function includeFile(SplFileInfo $fileInfo) : string
142
    {
143 1
        $sourceFile = $fileInfo->getRealPath();
144
145 1
        require_once $sourceFile;
146
147 1
        return $sourceFile;
148
    }
149
}
150