Security update for Core, with self-updated composer
[yaffs-website] / vendor / doctrine / annotations / lib / Doctrine / Common / Annotations / CachedReader.php
index e6dc59329a5fd2d2376b6417fde08e55b474b9b7..751c1b1b7f53a51f5a7d664e6674887c4e07515b 100644 (file)
@@ -20,6 +20,7 @@
 namespace Doctrine\Common\Annotations;
 
 use Doctrine\Common\Cache\Cache;
+use ReflectionClass;
 
 /**
  * A cache aware annotation reader.
@@ -29,11 +30,6 @@ use Doctrine\Common\Cache\Cache;
  */
 final class CachedReader implements Reader
 {
-    /**
-     * @var string
-     */
-    private static $CACHE_SALT = '@[Annot]';
-
     /**
      * @var Reader
      */
@@ -71,7 +67,7 @@ final class CachedReader implements Reader
     /**
      * {@inheritDoc}
      */
-    public function getClassAnnotations(\ReflectionClass $class)
+    public function getClassAnnotations(ReflectionClass $class)
     {
         $cacheKey = $class->getName();
 
@@ -90,7 +86,7 @@ final class CachedReader implements Reader
     /**
      * {@inheritDoc}
      */
-    public function getClassAnnotation(\ReflectionClass $class, $annotationName)
+    public function getClassAnnotation(ReflectionClass $class, $annotationName)
     {
         foreach ($this->getClassAnnotations($class) as $annot) {
             if ($annot instanceof $annotationName) {
@@ -182,14 +178,13 @@ final class CachedReader implements Reader
     /**
      * Fetches a value from the cache.
      *
-     * @param string           $rawCacheKey The cache key.
-     * @param \ReflectionClass $class       The related class.
+     * @param string          $cacheKey The cache key.
+     * @param ReflectionClass $class    The related class.
      *
      * @return mixed The cached value or false when the value is not in cache.
      */
-    private function fetchFromCache($rawCacheKey, \ReflectionClass $class)
+    private function fetchFromCache($cacheKey, ReflectionClass $class)
     {
-        $cacheKey = $rawCacheKey . self::$CACHE_SALT;
         if (($data = $this->cache->fetch($cacheKey)) !== false) {
             if (!$this->debug || $this->isCacheFresh($cacheKey, $class)) {
                 return $data;
@@ -202,14 +197,13 @@ final class CachedReader implements Reader
     /**
      * Saves a value to the cache.
      *
-     * @param string $rawCacheKey The cache key.
-     * @param mixed  $value       The value.
+     * @param string $cacheKey The cache key.
+     * @param mixed  $value    The value.
      *
      * @return void
      */
-    private function saveToCache($rawCacheKey, $value)
+    private function saveToCache($cacheKey, $value)
     {
-        $cacheKey = $rawCacheKey . self::$CACHE_SALT;
         $this->cache->save($cacheKey, $value);
         if ($this->debug) {
             $this->cache->save('[C]'.$cacheKey, time());
@@ -220,16 +214,49 @@ final class CachedReader implements Reader
      * Checks if the cache is fresh.
      *
      * @param string           $cacheKey
-     * @param \ReflectionClass $class
+     * @param ReflectionClass $class
      *
      * @return boolean
      */
-    private function isCacheFresh($cacheKey, \ReflectionClass $class)
+    private function isCacheFresh($cacheKey, ReflectionClass $class)
     {
-        if (false === $filename = $class->getFilename()) {
+        if (null === $lastModification = $this->getLastModification($class)) {
             return true;
         }
 
-        return $this->cache->fetch('[C]'.$cacheKey) >= filemtime($filename);
+        return $this->cache->fetch('[C]'.$cacheKey) >= $lastModification;
+    }
+
+    /**
+     * Returns the time the class was last modified, testing traits and parents
+     *
+     * @param ReflectionClass $class
+     * @return int
+     */
+    private function getLastModification(ReflectionClass $class)
+    {
+        $filename = $class->getFileName();
+        $parent   = $class->getParentClass();
+
+        return max(array_merge(
+            [$filename ? filemtime($filename) : 0],
+            array_map([$this, 'getTraitLastModificationTime'], $class->getTraits()),
+            array_map([$this, 'getLastModification'], $class->getInterfaces()),
+            $parent ? [$this->getLastModification($parent)] : []
+        ));
+    }
+
+    /**
+     * @param ReflectionClass $reflectionTrait
+     * @return int
+     */
+    private function getTraitLastModificationTime(ReflectionClass $reflectionTrait)
+    {
+        $fileName = $reflectionTrait->getFileName();
+
+        return max(array_merge(
+            [$fileName ? filemtime($fileName) : 0],
+            array_map([$this, 'getTraitLastModificationTime'], $reflectionTrait->getTraits())
+        ));
     }
 }