Completed
Push — master ( 4bcb6e...27d771 )
by Vitaly
03:27
created

ContainerBuilder::loadFromClassNames()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 16
ccs 7
cts 7
cp 1
rs 9.4285
cc 3
eloc 7
nc 3
nop 1
crap 3
1
<?php declare(strict_types = 1);
2
/**
3
 * Created by PhpStorm.
4
 * User: root
5
 * Date: 02.08.16
6
 * Time: 0:46.
7
 */
8
namespace samsonframework\container;
9
10
use samsonframework\container\resolver\ResolverInterface;
11
use samsonframework\filemanager\FileManagerInterface;
12
use samsonphp\generator\Generator;
13
14
/**
15
 * Class Container.
16
 */
17
class ContainerBuilder extends Builder
18
{
19
    /**
20
     * @var FileManagerInterface
21
     * @Injectable
22
     */
23
    protected $fileManger;
24
25
    /**
26
     * @var ResolverInterface
27
     * @Injectable
28
     */
29
    protected $classResolver;
30
31
    /**
32
     * Container constructor.
33
     *
34
     * @param FileManagerInterface $fileManager
35
     * @param ResolverInterface    $classResolver
36
     * @param Generator            $generator
37
     */
38 11
    public function __construct(FileManagerInterface $fileManager, ResolverInterface $classResolver, Generator $generator)
39
    {
40 11
        $this->fileManger = $fileManager;
41 11
        $this->classResolver = $classResolver;
42
43 11
        parent::__construct($generator, $this->classMetadata);
44 11
    }
45
46
    /**
47
     * Load classes from paths.
48
     *
49
     * @param array $paths Paths for importing
50
     *
51
     * @return $this
52
     */
53 1
    public function loadFromPaths(array $paths)
54
    {
55
        // Iterate all paths and get files
56 1
        foreach ($this->fileManger->scan($paths, ['php']) as $phpFile) {
57 1
            require_once($phpFile);
58
            // Read all classes in given file
59 1
            $this->loadFromClassNames($this->getDefinedClasses(file_get_contents($phpFile)));
60
        }
61
62 1
        return $this;
63
    }
64
65
    /**
66
     * Load classes from class names collection.
67
     *
68
     * @param string[] $classes Collection of class names for resolving
69
     *
70
     * @return $this
71
     */
72 10
    public function loadFromClassNames(array $classes)
73
    {
74
        // Read all classes in given file
75 10
        foreach ($classes as $className) {
76
            // Resolve class metadata
77 10
            $this->classMetadata[$className] = $this->classResolver->resolve(new \ReflectionClass($className));
78
            // Store by metadata name as alias
79 10
            $this->classAliases[$this->classMetadata[$className]->name] = $className;
80
            // Store class in defined scopes
81 10
            foreach ($this->classMetadata[$className]->scopes as $scope) {
82 10
                $this->scopes[$scope][] = $className;
83
            }
84
        }
85
86 10
        return $this;
87
    }
88
89
    /**
90
     * Find class names defined in PHP code.
91
     *
92
     * @param string $php PHP code for scanning
93
     *
94
     * @return string[] Collection of found class names in php code
95
     */
96 2
    protected function getDefinedClasses(string $php) : array
97
    {
98 2
        $classes = [];
99 2
        $namespace = null;
100
101
        // Append php marker for parsing file
102 2
        $php = strpos(is_string($php) ? $php : '', '<?php') !== 0 ? '<?php ' . $php : $php;
103
104 2
        $tokens = token_get_all($php);
105
106 2
        for ($i = 2, $count = count($tokens); $i < $count; $i++) {
107 2
            if ($tokens[$i - 2][0] === T_CLASS
108 2
                && $tokens[$i - 1][0] === T_WHITESPACE
109 2
                && $tokens[$i][0] === T_STRING
110
            ) {
111 2
                $classes[] = $namespace ? $namespace . '\\' . $tokens[$i][1] : $tokens[$i][1];
112 2
            } elseif ($tokens[$i - 2][0] === T_NAMESPACE
113 2
                && $tokens[$i - 1][0] === T_WHITESPACE
114 2
                && $tokens[$i][0] === T_STRING
115
            ) {
116 1
                while (isset($tokens[$i]) && is_array($tokens[$i])) {
117 1
                    $namespace .= $tokens[$i++][1];
118
                }
119
            }
120
        }
121
122 2
        return $classes;
123
    }
124
125
    /**
126
     * Load classes from PHP c ode.
127
     *
128
     * @param string $php PHP code
129
     *
130
     * @return $this
131
     */
132 1
    public function loadFromCode($php)
133
    {
134 1
        if (count($classes = $this->getDefinedClasses($php))) {
135
            // TODO: Consider writing cache file and require it
136 1
            eval($php);
137 1
            $this->loadFromClassNames($classes);
138
        }
139
140 1
        return $this;
141
    }
142
}
143