summaryrefslogtreecommitdiff
path: root/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php')
-rw-r--r--vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php212
1 files changed, 212 insertions, 0 deletions
diff --git a/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php
new file mode 100644
index 0000000..e85ba70
--- /dev/null
+++ b/vendor/doctrine/persistence/src/Persistence/Mapping/Driver/ColocatedMappingDriver.php
@@ -0,0 +1,212 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Doctrine\Persistence\Mapping\Driver;
6
7use Doctrine\Persistence\Mapping\MappingException;
8use FilesystemIterator;
9use RecursiveDirectoryIterator;
10use RecursiveIteratorIterator;
11use RecursiveRegexIterator;
12use ReflectionClass;
13use RegexIterator;
14
15use function array_merge;
16use function array_unique;
17use function assert;
18use function get_declared_classes;
19use function in_array;
20use function is_dir;
21use function preg_match;
22use function preg_quote;
23use function realpath;
24use function str_replace;
25use function strpos;
26
27/**
28 * The ColocatedMappingDriver reads the mapping metadata located near the code.
29 */
30trait ColocatedMappingDriver
31{
32 /**
33 * The paths where to look for mapping files.
34 *
35 * @var array<int, string>
36 */
37 protected $paths = [];
38
39 /**
40 * The paths excluded from path where to look for mapping files.
41 *
42 * @var array<int, string>
43 */
44 protected $excludePaths = [];
45
46 /**
47 * The file extension of mapping documents.
48 *
49 * @var string
50 */
51 protected $fileExtension = '.php';
52
53 /**
54 * Cache for getAllClassNames().
55 *
56 * @var array<int, string>|null
57 * @psalm-var list<class-string>|null
58 */
59 protected $classNames;
60
61 /**
62 * Appends lookup paths to metadata driver.
63 *
64 * @param array<int, string> $paths
65 *
66 * @return void
67 */
68 public function addPaths(array $paths)
69 {
70 $this->paths = array_unique(array_merge($this->paths, $paths));
71 }
72
73 /**
74 * Retrieves the defined metadata lookup paths.
75 *
76 * @return array<int, string>
77 */
78 public function getPaths()
79 {
80 return $this->paths;
81 }
82
83 /**
84 * Append exclude lookup paths to metadata driver.
85 *
86 * @param string[] $paths
87 *
88 * @return void
89 */
90 public function addExcludePaths(array $paths)
91 {
92 $this->excludePaths = array_unique(array_merge($this->excludePaths, $paths));
93 }
94
95 /**
96 * Retrieve the defined metadata lookup exclude paths.
97 *
98 * @return array<int, string>
99 */
100 public function getExcludePaths()
101 {
102 return $this->excludePaths;
103 }
104
105 /**
106 * Gets the file extension used to look for mapping files under.
107 *
108 * @return string
109 */
110 public function getFileExtension()
111 {
112 return $this->fileExtension;
113 }
114
115 /**
116 * Sets the file extension used to look for mapping files under.
117 *
118 * @return void
119 */
120 public function setFileExtension(string $fileExtension)
121 {
122 $this->fileExtension = $fileExtension;
123 }
124
125 /**
126 * {@inheritDoc}
127 *
128 * Returns whether the class with the specified name is transient. Only non-transient
129 * classes, that is entities and mapped superclasses, should have their metadata loaded.
130 *
131 * @psalm-param class-string $className
132 *
133 * @return bool
134 */
135 abstract public function isTransient(string $className);
136
137 /**
138 * Gets the names of all mapped classes known to this driver.
139 *
140 * @return string[] The names of all mapped classes known to this driver.
141 * @psalm-return list<class-string>
142 */
143 public function getAllClassNames()
144 {
145 if ($this->classNames !== null) {
146 return $this->classNames;
147 }
148
149 if ($this->paths === []) {
150 throw MappingException::pathRequiredForDriver(static::class);
151 }
152
153 $classes = [];
154 $includedFiles = [];
155
156 foreach ($this->paths as $path) {
157 if (! is_dir($path)) {
158 throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
159 }
160
161 $iterator = new RegexIterator(
162 new RecursiveIteratorIterator(
163 new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
164 RecursiveIteratorIterator::LEAVES_ONLY
165 ),
166 '/^.+' . preg_quote($this->fileExtension) . '$/i',
167 RecursiveRegexIterator::GET_MATCH
168 );
169
170 foreach ($iterator as $file) {
171 $sourceFile = $file[0];
172
173 if (preg_match('(^phar:)i', $sourceFile) === 0) {
174 $sourceFile = realpath($sourceFile);
175 }
176
177 foreach ($this->excludePaths as $excludePath) {
178 $realExcludePath = realpath($excludePath);
179 assert($realExcludePath !== false);
180 $exclude = str_replace('\\', '/', $realExcludePath);
181 $current = str_replace('\\', '/', $sourceFile);
182
183 if (strpos($current, $exclude) !== false) {
184 continue 2;
185 }
186 }
187
188 require_once $sourceFile;
189
190 $includedFiles[] = $sourceFile;
191 }
192 }
193
194 $declared = get_declared_classes();
195
196 foreach ($declared as $className) {
197 $rc = new ReflectionClass($className);
198
199 $sourceFile = $rc->getFileName();
200
201 if (! in_array($sourceFile, $includedFiles, true) || $this->isTransient($className)) {
202 continue;
203 }
204
205 $classes[] = $className;
206 }
207
208 $this->classNames = $classes;
209
210 return $classes;
211 }
212}