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\metadata\ClassMetadata; |
11
|
|
|
use samsonframework\container\resolver\Resolver; |
12
|
|
|
use samsonframework\filemanager\FileManagerInterface; |
13
|
|
|
|
14
|
|
|
/** |
15
|
|
|
* Class Container. |
16
|
|
|
*/ |
17
|
|
|
class MetadataBuilder |
18
|
|
|
{ |
19
|
|
|
/** Controller classes scope name */ |
20
|
|
|
const SCOPE_CONTROLLER = 'controllers'; |
21
|
|
|
|
22
|
|
|
/** Service classes scope name */ |
23
|
|
|
const SCOPE_SERVICES = 'services'; |
24
|
|
|
|
25
|
|
|
/** @var string[] Collection of available container scopes */ |
26
|
|
|
protected $scopes = [ |
27
|
|
|
self::SCOPE_CONTROLLER => [], |
28
|
|
|
self::SCOPE_SERVICES => [] |
29
|
|
|
]; |
30
|
|
|
|
31
|
|
|
/** @var ClassMetadata[string] Collection of classes metadata */ |
32
|
|
|
protected $classMetadata = []; |
33
|
|
|
|
34
|
|
|
/** @var FileManagerInterface */ |
35
|
|
|
protected $fileManger; |
36
|
|
|
|
37
|
|
|
/** @var Resolver */ |
38
|
|
|
protected $classResolver; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* Container constructor. |
42
|
|
|
* |
43
|
|
|
* @param FileManagerInterface $fileManger |
44
|
|
|
*/ |
45
|
4 |
|
public function __construct(FileManagerInterface $fileManger, Resolver $classResolver) |
46
|
|
|
{ |
47
|
4 |
|
$this->fileManger = $fileManger; |
48
|
4 |
|
$this->resolver = $classResolver; |
|
|
|
|
49
|
4 |
|
} |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* Load classes from paths. |
53
|
|
|
* |
54
|
|
|
* @param array $paths Paths for importing |
55
|
|
|
* |
56
|
|
|
* @return $this |
57
|
|
|
*/ |
58
|
1 |
|
public function loadFromPaths(array $paths) |
59
|
|
|
{ |
60
|
|
|
// Iterate all paths and get files |
61
|
1 |
|
foreach ($this->fileManger->scan($paths, ['php']) as $phpFile) { |
62
|
|
|
// Read all classes in given file |
63
|
1 |
|
$this->loadFromClassNames($this->getDefinedClasses(require_once($phpFile))); |
64
|
|
|
} |
65
|
|
|
|
66
|
1 |
|
return $this; |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Load classes from class names collection. |
71
|
|
|
* |
72
|
|
|
* @param string[] $classes Collection of class names for resolving |
73
|
|
|
* |
74
|
|
|
* @return $this |
75
|
|
|
*/ |
76
|
3 |
|
public function loadFromClassNames(array $classes) |
77
|
|
|
{ |
78
|
|
|
// Read all classes in given file |
79
|
3 |
|
foreach ($classes as $className) { |
80
|
|
|
// Resolve class metadata |
81
|
2 |
|
$this->classMetadata[$className] = $this->resolver->resolve(new \ReflectionClass($className)); |
|
|
|
|
82
|
|
|
// Store class in defined scopes |
83
|
2 |
|
foreach ($this->classMetadata[$className]->scopes as $scope) { |
84
|
2 |
|
$this->scopes[$scope][] = $className; |
85
|
|
|
} |
86
|
|
|
} |
87
|
|
|
|
88
|
3 |
|
return $this; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
/** |
92
|
|
|
* Find class names defined in PHP code. |
93
|
|
|
* |
94
|
|
|
* @param string $php PHP code for scanning |
95
|
|
|
* |
96
|
|
|
* @return string[] Collection of found class names in php code |
97
|
|
|
*/ |
98
|
2 |
|
protected function getDefinedClasses($php) : array |
99
|
|
|
{ |
100
|
2 |
|
$classes = array(); |
101
|
|
|
|
102
|
|
|
// Append php marker for parsing file |
103
|
2 |
|
$php = strpos(is_string($php) ? $php : '', '<?php') !== 0 ? '<?php ' . $php : $php; |
104
|
|
|
|
105
|
2 |
|
$tokens = token_get_all($php); |
106
|
|
|
|
107
|
2 |
|
for ($i = 2, $count = count($tokens); $i < $count; $i++) { |
108
|
1 |
|
if ($tokens[$i - 2][0] === T_CLASS |
109
|
1 |
|
&& $tokens[$i - 1][0] === T_WHITESPACE |
110
|
1 |
|
&& $tokens[$i][0] === T_STRING |
111
|
|
|
) { |
112
|
1 |
|
$classes[] = $tokens[$i][1]; |
113
|
|
|
} |
114
|
|
|
} |
115
|
|
|
|
116
|
2 |
|
return $classes; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
/** |
120
|
|
|
* Load classes from PHP code. |
121
|
|
|
* |
122
|
|
|
* @param string $php PHP code |
123
|
|
|
* |
124
|
|
|
* @return $this |
125
|
|
|
*/ |
126
|
1 |
|
public function loadFromCode($php) |
127
|
|
|
{ |
128
|
1 |
|
eval($php); |
129
|
1 |
|
$this->loadFromClassNames($this->getDefinedClasses($php)); |
130
|
|
|
|
131
|
1 |
|
return $this; |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
/** |
135
|
|
|
* Build container class. |
136
|
|
|
*/ |
137
|
1 |
|
public function build($containerClass) |
|
|
|
|
138
|
|
|
{ |
139
|
|
|
|
140
|
1 |
|
} |
141
|
|
|
} |
142
|
|
|
|
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.
If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.