3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 * This software consists of voluntary contributions made by many individuals
16 * and is licensed under the MIT license. For more information, see
17 * <http://www.doctrine-project.org>.
20 namespace Doctrine\Common\Persistence\Mapping\Driver;
22 use Doctrine\Common\Cache\ArrayCache,
23 Doctrine\Common\Annotations\AnnotationReader,
24 Doctrine\Common\Annotations\AnnotationRegistry,
25 Doctrine\Common\Persistence\Mapping\MappingException;
28 * The AnnotationDriver reads the mapping metadata from docblock annotations.
31 * @author Benjamin Eberlei <kontakt@beberlei.de>
32 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
33 * @author Jonathan H. Wage <jonwage@gmail.com>
34 * @author Roman Borschel <roman@code-factory.org>
36 abstract class AnnotationDriver implements MappingDriver
39 * The AnnotationReader.
41 * @var AnnotationReader
46 * The paths where to look for mapping files.
50 protected $paths = array();
53 * The file extension of mapping documents.
57 protected $fileExtension = '.php';
60 * Cache for AnnotationDriver#getAllClassNames()
64 protected $classNames;
67 * Name of the entity annotations as keys
71 protected $entityAnnotationClasses = array();
74 * Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
75 * docblock annotations.
77 * @param AnnotationReader $reader The AnnotationReader to use, duck-typed.
78 * @param string|array $paths One or multiple paths where mapping classes can be found.
80 public function __construct($reader, $paths = null)
82 $this->reader = $reader;
84 $this->addPaths((array) $paths);
89 * Append lookup paths to metadata driver.
93 public function addPaths(array $paths)
95 $this->paths = array_unique(array_merge($this->paths, $paths));
99 * Retrieve the defined metadata lookup paths.
103 public function getPaths()
109 * Retrieve the current annotation reader
111 * @return AnnotationReader
113 public function getReader()
115 return $this->reader;
119 * Get the file extension used to look for mapping files under
123 public function getFileExtension()
125 return $this->fileExtension;
129 * Set the file extension used to look for mapping files under
131 * @param string $fileExtension The file extension to set
134 public function setFileExtension($fileExtension)
136 $this->fileExtension = $fileExtension;
140 * Whether the class with the specified name is transient. Only non-transient
141 * classes, that is entities and mapped superclasses, should have their metadata loaded.
143 * A class is non-transient if it is annotated with an annotation
144 * from the {@see AnnotationDriver::entityAnnotationClasses}.
146 * @param string $className
149 public function isTransient($className)
151 $classAnnotations = $this->reader->getClassAnnotations(new \ReflectionClass($className));
153 foreach ($classAnnotations as $annot) {
154 if (isset($this->entityAnnotationClasses[get_class($annot)])) {
164 public function getAllClassNames()
166 if ($this->classNames !== null) {
167 return $this->classNames;
171 throw MappingException::pathRequired();
175 $includedFiles = array();
177 foreach ($this->paths as $path) {
178 if ( ! is_dir($path)) {
179 throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
182 $iterator = new \RegexIterator(
183 new \RecursiveIteratorIterator(
184 new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS),
185 \RecursiveIteratorIterator::LEAVES_ONLY
187 '/^.+' . str_replace('.', '\.', $this->fileExtension) . '$/i',
188 \RecursiveRegexIterator::GET_MATCH
191 foreach ($iterator as $file) {
192 $sourceFile = realpath($file[0]);
194 require_once $sourceFile;
196 $includedFiles[] = $sourceFile;
200 $declared = get_declared_classes();
202 foreach ($declared as $className) {
203 $rc = new \ReflectionClass($className);
204 $sourceFile = $rc->getFileName();
205 if (in_array($sourceFile, $includedFiles) && ! $this->isTransient($className)) {
206 $classes[] = $className;
210 $this->classNames = $classes;