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\Annotations;
22
use Doctrine\Common\Cache\Cache;
25
* A cache aware annotation reader.
27
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
28
* @author Benjamin Eberlei <kontakt@beberlei.de>
30
final class CachedReader implements Reader
35
private static $CACHE_SALT = '@[Annot]';
55
private $loadedAnnotations;
60
* @param Reader $reader
64
public function __construct(Reader $reader, Cache $cache, $debug = false)
66
$this->delegate = $reader;
67
$this->cache = $cache;
68
$this->debug = (Boolean) $debug;
72
* Get annotations for class
74
* @param \ReflectionClass $class
77
public function getClassAnnotations(\ReflectionClass $class)
79
$cacheKey = $class->getName();
81
if (isset($this->loadedAnnotations[$cacheKey])) {
82
return $this->loadedAnnotations[$cacheKey];
85
if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) {
86
$annots = $this->delegate->getClassAnnotations($class);
87
$this->saveToCache($cacheKey, $annots);
90
return $this->loadedAnnotations[$cacheKey] = $annots;
94
* Get selected annotation for class
96
* @param \ReflectionClass $class
97
* @param string $annotationName
100
public function getClassAnnotation(\ReflectionClass $class, $annotationName)
102
foreach ($this->getClassAnnotations($class) as $annot) {
103
if ($annot instanceof $annotationName) {
112
* Get annotations for property
114
* @param \ReflectionProperty $property
117
public function getPropertyAnnotations(\ReflectionProperty $property)
119
$class = $property->getDeclaringClass();
120
$cacheKey = $class->getName().'$'.$property->getName();
122
if (isset($this->loadedAnnotations[$cacheKey])) {
123
return $this->loadedAnnotations[$cacheKey];
126
if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) {
127
$annots = $this->delegate->getPropertyAnnotations($property);
128
$this->saveToCache($cacheKey, $annots);
131
return $this->loadedAnnotations[$cacheKey] = $annots;
135
* Get selected annotation for property
137
* @param \ReflectionProperty $property
138
* @param string $annotationName
141
public function getPropertyAnnotation(\ReflectionProperty $property, $annotationName)
143
foreach ($this->getPropertyAnnotations($property) as $annot) {
144
if ($annot instanceof $annotationName) {
153
* Get method annotations
155
* @param \ReflectionMethod $method
158
public function getMethodAnnotations(\ReflectionMethod $method)
160
$class = $method->getDeclaringClass();
161
$cacheKey = $class->getName().'#'.$method->getName();
163
if (isset($this->loadedAnnotations[$cacheKey])) {
164
return $this->loadedAnnotations[$cacheKey];
167
if (false === ($annots = $this->fetchFromCache($cacheKey, $class))) {
168
$annots = $this->delegate->getMethodAnnotations($method);
169
$this->saveToCache($cacheKey, $annots);
172
return $this->loadedAnnotations[$cacheKey] = $annots;
176
* Get selected method annotation
178
* @param \ReflectionMethod $method
179
* @param string $annotationName
182
public function getMethodAnnotation(\ReflectionMethod $method, $annotationName)
184
foreach ($this->getMethodAnnotations($method) as $annot) {
185
if ($annot instanceof $annotationName) {
194
* Clear loaded annotations
196
public function clearLoadedAnnotations()
198
$this->loadedAnnotations = array();
202
* Fetches a value from the cache.
204
* @param string $rawCacheKey The cache key.
205
* @param \ReflectionClass $class The related class.
206
* @return mixed|boolean The cached value or false when the value is not in cache.
208
private function fetchFromCache($rawCacheKey, \ReflectionClass $class)
210
$cacheKey = $rawCacheKey . self::$CACHE_SALT;
211
if (($data = $this->cache->fetch($cacheKey)) !== false) {
212
if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) {
221
* Saves a value to the cache
223
* @param string $rawCacheKey The cache key.
224
* @param mixed $value The value.
226
private function saveToCache($rawCacheKey, $value)
228
$cacheKey = $rawCacheKey . self::$CACHE_SALT;
229
$this->cache->save($cacheKey, $value);
231
$this->cache->save('[C]'.$cacheKey, time());
236
* Check if cache is fresh
238
* @param string $cacheKey
239
* @param \ReflectionClass $class
242
private function isCacheFresh($cacheKey, \ReflectionClass $class)
244
if (false === $filename = $class->getFilename()) {
248
return $this->cache->fetch('[C]'.$cacheKey) >= filemtime($filename);