6
6
use Doctrine \Common \Persistence \Mapping \Driver \MappingDriver ;
7
7
use Doctrine \ORM \Mapping \Builder \ClassMetadataBuilder ;
8
8
use Doctrine \ORM \Mapping \MappingException ;
9
+ use FilesystemIterator ;
9
10
use InvalidArgumentException ;
10
11
use LaravelDoctrine \Fluent \Builders \Builder ;
11
12
use LaravelDoctrine \Fluent \Mappers \MapperSet ;
13
+ use RecursiveDirectoryIterator ;
14
+ use RecursiveIteratorIterator ;
15
+ use RecursiveRegexIterator ;
16
+ use ReflectionClass ;
17
+ use RegexIterator ;
12
18
13
19
class FluentDriver implements MappingDriver
14
20
{
@@ -22,20 +28,37 @@ class FluentDriver implements MappingDriver
22
28
*/
23
29
protected $ fluentFactory ;
24
30
31
+ /**
32
+ * The file extension of mapping documents.
33
+ *
34
+ * @var string
35
+ */
36
+ protected $ fileExtension = '.php ' ;
37
+
25
38
/**
26
39
* Initializes a new FileDriver that looks in the given path(s) for mapping
27
40
* documents and operates in the specified operating mode.
28
41
*
29
42
* @param string[] $mappings
43
+ * @param array $paths
44
+ *
45
+ * @throws MappingException
30
46
*/
31
- public function __construct (array $ mappings = [])
47
+ public function __construct (array $ mappings = [], array $ paths = [] )
32
48
{
33
49
$ this ->fluentFactory = function (ClassMetadata $ metadata ) {
34
50
return new Builder (new ClassMetadataBuilder ($ metadata ));
35
51
};
36
52
37
53
$ this ->mappers = new MapperSet ();
38
- $ this ->addMappings ($ mappings );
54
+
55
+ if (!empty ($ paths )) {
56
+ $ this ->loadPaths ($ paths );
57
+ }
58
+
59
+ if (!empty ($ mappings )) {
60
+ $ this ->addMappings ($ mappings );
61
+ }
39
62
}
40
63
41
64
/**
@@ -78,8 +101,75 @@ public function isTransient($className)
78
101
$ this ->mappers ->getMapperFor ($ className )->isTransient ();
79
102
}
80
103
104
+ /**
105
+ * @param array $paths
106
+ *
107
+ * @throws MappingException
108
+ */
109
+ public function loadPaths (array $ paths )
110
+ {
111
+ $ classes = [];
112
+ $ includedFiles = [];
113
+
114
+ foreach ($ paths as $ path ) {
115
+ if (!is_dir ($ path )) {
116
+ throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath ($ path );
117
+ }
118
+
119
+ $ iterator = new RegexIterator (
120
+ new RecursiveIteratorIterator (
121
+ new RecursiveDirectoryIterator ($ path , FilesystemIterator::SKIP_DOTS ),
122
+ RecursiveIteratorIterator::LEAVES_ONLY
123
+ ),
124
+ '/^.+ ' .preg_quote ($ this ->fileExtension ).'$/i ' ,
125
+ RecursiveRegexIterator::GET_MATCH
126
+ );
127
+
128
+ foreach ($ iterator as $ file ) {
129
+ $ sourceFile = $ file [0 ];
130
+
131
+ if (!preg_match ('(^phar:)i ' , $ sourceFile )) {
132
+ $ sourceFile = realpath ($ sourceFile );
133
+ }
134
+
135
+ require_once $ sourceFile ;
136
+
137
+ $ includedFiles [] = $ sourceFile ;
138
+ }
139
+
140
+ $ declared = get_declared_classes ();
141
+
142
+ foreach ($ declared as $ className ) {
143
+ $ rc = new ReflectionClass ($ className );
144
+ $ sourceFile = $ rc ->getFileName ();
145
+
146
+ if (!in_array ($ sourceFile , $ includedFiles )) {
147
+ continue ;
148
+ }
149
+
150
+ if ($ rc ->isAbstract () || $ rc ->isInterface ()) {
151
+ continue ;
152
+ }
153
+
154
+ if (!$ rc ->implementsInterface (Mapping::class)) {
155
+ continue ;
156
+ }
157
+
158
+ if ($ this ->isTransient ($ className )) {
159
+
160
+ /** @var Mapping $mapping */
161
+ $ mapping = $ rc ->newInstanceWithoutConstructor ();
162
+
163
+ $ this ->addMapping ($ mapping );
164
+ }
165
+ }
166
+ }
167
+ }
168
+
81
169
/**
82
170
* @param string[] $mappings
171
+ *
172
+ * @throws InvalidArgumentException
83
173
*/
84
174
public function addMappings (array $ mappings = [])
85
175
{
0 commit comments