~ubuntu-branches/ubuntu/wily/php-doctrine-common/wily-proposed

« back to all changes in this revision

Viewing changes to lib/Doctrine/Common/Persistence/Mapping/Driver/AnnotationDriver.php

  • Committer: Package Import Robot
  • Author(s): David Prévot
  • Date: 2014-06-15 11:26:00 UTC
  • mfrom: (2.1.1 experimental)
  • Revision ID: package-import@ubuntu.com-20140615112600-sg4mgpwq9sfg4mre
Tags: 2.4.2-2
* Upload to unstable
* No tests if DEB_BUILD_OPTIONS contains nocheck

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/*
 
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.
 
14
 *
 
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>.
 
18
 */
 
19
 
 
20
namespace Doctrine\Common\Persistence\Mapping\Driver;
 
21
 
 
22
use Doctrine\Common\Annotations\AnnotationReader;
 
23
use Doctrine\Common\Annotations\AnnotationRegistry;
 
24
use Doctrine\Common\Persistence\Mapping\MappingException;
 
25
 
 
26
/**
 
27
 * The AnnotationDriver reads the mapping metadata from docblock annotations.
 
28
 *
 
29
 * @since  2.2
 
30
 * @author Benjamin Eberlei <kontakt@beberlei.de>
 
31
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 
32
 * @author Jonathan H. Wage <jonwage@gmail.com>
 
33
 * @author Roman Borschel <roman@code-factory.org>
 
34
 */
 
35
abstract class AnnotationDriver implements MappingDriver
 
36
{
 
37
    /**
 
38
     * The AnnotationReader.
 
39
     *
 
40
     * @var AnnotationReader
 
41
     */
 
42
    protected $reader;
 
43
 
 
44
    /**
 
45
     * The paths where to look for mapping files.
 
46
     *
 
47
     * @var array
 
48
     */
 
49
    protected $paths = array();
 
50
 
 
51
    /**
 
52
     * The paths excluded from path where to look for mapping files.
 
53
     *
 
54
     * @var array
 
55
     */
 
56
    protected $excludePaths = array();
 
57
 
 
58
    /**
 
59
     * The file extension of mapping documents.
 
60
     *
 
61
     * @var string
 
62
     */
 
63
    protected $fileExtension = '.php';
 
64
 
 
65
    /**
 
66
     * Cache for AnnotationDriver#getAllClassNames().
 
67
     *
 
68
     * @var array|null
 
69
     */
 
70
    protected $classNames;
 
71
 
 
72
    /**
 
73
     * Name of the entity annotations as keys.
 
74
     *
 
75
     * @var array
 
76
     */
 
77
    protected $entityAnnotationClasses = array();
 
78
 
 
79
    /**
 
80
     * Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
 
81
     * docblock annotations.
 
82
     *
 
83
     * @param AnnotationReader  $reader The AnnotationReader to use, duck-typed.
 
84
     * @param string|array|null $paths  One or multiple paths where mapping classes can be found.
 
85
     */
 
86
    public function __construct($reader, $paths = null)
 
87
    {
 
88
        $this->reader = $reader;
 
89
        if ($paths) {
 
90
            $this->addPaths((array) $paths);
 
91
        }
 
92
    }
 
93
 
 
94
    /**
 
95
     * Appends lookup paths to metadata driver.
 
96
     *
 
97
     * @param array $paths
 
98
     *
 
99
     * @return void
 
100
     */
 
101
    public function addPaths(array $paths)
 
102
    {
 
103
        $this->paths = array_unique(array_merge($this->paths, $paths));
 
104
    }
 
105
 
 
106
    /**
 
107
     * Retrieves the defined metadata lookup paths.
 
108
     *
 
109
     * @return array
 
110
     */
 
111
    public function getPaths()
 
112
    {
 
113
        return $this->paths;
 
114
    }
 
115
 
 
116
    /**
 
117
     * Append exclude lookup paths to metadata driver.
 
118
     *
 
119
     * @param array $paths
 
120
     */
 
121
    public function addExcludePaths(array $paths)
 
122
    {
 
123
        $this->excludePaths = array_unique(array_merge($this->excludePaths, $paths));
 
124
    }
 
125
 
 
126
    /**
 
127
     * Retrieve the defined metadata lookup exclude paths.
 
128
     *
 
129
     * @return array
 
130
     */
 
131
    public function getExcludePaths()
 
132
    {
 
133
        return $this->excludePaths;
 
134
    }
 
135
 
 
136
    /**
 
137
     * Retrieve the current annotation reader
 
138
     *
 
139
     * @return AnnotationReader
 
140
     */
 
141
    public function getReader()
 
142
    {
 
143
        return $this->reader;
 
144
    }
 
145
 
 
146
    /**
 
147
     * Gets the file extension used to look for mapping files under.
 
148
     *
 
149
     * @return string
 
150
     */
 
151
    public function getFileExtension()
 
152
    {
 
153
        return $this->fileExtension;
 
154
    }
 
155
 
 
156
    /**
 
157
     * Sets the file extension used to look for mapping files under.
 
158
     *
 
159
     * @param string $fileExtension The file extension to set.
 
160
     *
 
161
     * @return void
 
162
     */
 
163
    public function setFileExtension($fileExtension)
 
164
    {
 
165
        $this->fileExtension = $fileExtension;
 
166
    }
 
167
 
 
168
    /**
 
169
     * Returns whether the class with the specified name is transient. Only non-transient
 
170
     * classes, that is entities and mapped superclasses, should have their metadata loaded.
 
171
     *
 
172
     * A class is non-transient if it is annotated with an annotation
 
173
     * from the {@see AnnotationDriver::entityAnnotationClasses}.
 
174
     *
 
175
     * @param string $className
 
176
     *
 
177
     * @return boolean
 
178
     */
 
179
    public function isTransient($className)
 
180
    {
 
181
        $classAnnotations = $this->reader->getClassAnnotations(new \ReflectionClass($className));
 
182
 
 
183
        foreach ($classAnnotations as $annot) {
 
184
            if (isset($this->entityAnnotationClasses[get_class($annot)])) {
 
185
                return false;
 
186
            }
 
187
        }
 
188
        return true;
 
189
    }
 
190
 
 
191
    /**
 
192
     * {@inheritDoc}
 
193
     */
 
194
    public function getAllClassNames()
 
195
    {
 
196
        if ($this->classNames !== null) {
 
197
            return $this->classNames;
 
198
        }
 
199
 
 
200
        if (!$this->paths) {
 
201
            throw MappingException::pathRequired();
 
202
        }
 
203
 
 
204
        $classes = array();
 
205
        $includedFiles = array();
 
206
 
 
207
        foreach ($this->paths as $path) {
 
208
            if ( ! is_dir($path)) {
 
209
                throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
 
210
            }
 
211
 
 
212
            $iterator = new \RegexIterator(
 
213
                new \RecursiveIteratorIterator(
 
214
                    new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS),
 
215
                    \RecursiveIteratorIterator::LEAVES_ONLY
 
216
                ),
 
217
                '/^.+' . preg_quote($this->fileExtension) . '$/i',
 
218
                \RecursiveRegexIterator::GET_MATCH
 
219
            );
 
220
 
 
221
            foreach ($iterator as $file) {
 
222
                $sourceFile = $file[0];
 
223
 
 
224
                if ( ! preg_match('(^phar:)i', $sourceFile)) {
 
225
                    $sourceFile = realpath($sourceFile);
 
226
                }
 
227
 
 
228
                foreach ($this->excludePaths as $excludePath) {
 
229
                    $exclude = str_replace('\\', '/', realpath($excludePath));
 
230
                    $current = str_replace('\\', '/', $sourceFile);
 
231
 
 
232
                    if (strpos($current, $exclude) !== false) {
 
233
                        continue 2;
 
234
                    }
 
235
                }
 
236
 
 
237
                require_once $sourceFile;
 
238
 
 
239
                $includedFiles[] = $sourceFile;
 
240
            }
 
241
        }
 
242
 
 
243
        $declared = get_declared_classes();
 
244
 
 
245
        foreach ($declared as $className) {
 
246
            $rc = new \ReflectionClass($className);
 
247
            $sourceFile = $rc->getFileName();
 
248
            if (in_array($sourceFile, $includedFiles) && ! $this->isTransient($className)) {
 
249
                $classes[] = $className;
 
250
            }
 
251
        }
 
252
 
 
253
        $this->classNames = $classes;
 
254
 
 
255
        return $classes;
 
256
    }
 
257
}