/**
  * Pulls data out of cache.
  * Also, it checks all related tags for expiration/version-up.
  *
  * @see sfCache::get
  * @param string  $key
  * @param mixed   $default returned back if result is false
  * @return mixed
  */
 public function get($key, $default = null)
 {
     $cacheMetadata = new CacheMetadata($this->getCache()->get($key, $default));
     $data = $cacheMetadata->getData();
     if (null !== $data) {
         $fetchedCacheTags = $cacheMetadata->getTags();
         if (0 !== count($fetchedCacheTags)) {
             /**
              * speed up multi tag selection from backend
              */
             $tagKeys = array_keys($fetchedCacheTags);
             $storedTags = $this->getCache()->getMany($tagKeys);
             $hasExpired = false;
             /**
              * getMany returns keys with NULL value if some key is missing.
              * In case arrays are equal, cache is not expired
              */
             if ($fetchedCacheTags === $storedTags) {
                 $this->getLogger()->log('V', 'via equal compare');
                 # one tag is expired, no reasons to continue
                 # (should revalidate cache data)
             } else {
                 $extendedKeysWithCurrentVersions = array_combine(array_keys($storedTags), array_values($fetchedCacheTags));
                 # check for data tags is expired
                 foreach ($storedTags as $tagKey => $tagLatestVersion) {
                     $tagVersion = $extendedKeysWithCurrentVersions[$tagKey];
                     # tag is exprired or version is old
                     if (!$tagLatestVersion || $tagVersion < $tagLatestVersion) {
                         $this->getLogger()->log('v', sprintf('%s(%s=>%s)', $tagKey, $tagVersion, $tagLatestVersion));
                         # one tag is expired, no reasons to continue
                         # (should revalidate cache data)
                         $hasExpired = true;
                         break;
                     }
                     $this->getLogger()->log('V', sprintf('%s(%s)', $tagKey, $tagLatestVersion));
                 }
             }
             // some cache tags is invalidated
             if ($hasExpired) {
                 if ($this->isLocked($key)) {
                     # return old cache coz new data is writing to the current cache
                     $data = $cacheMetadata->getData();
                 } else {
                     # cache no locked, but cache is expired
                     $data = null;
                 }
             } else {
                 $data = $cacheMetadata->getData();
             }
         } else {
             $data = $cacheMetadata->getData();
         }
     }
     $this->getLogger()->log($data !== $default ? 'G' : 'g', $key);
     return $data;
 }
 /**
  * Listens to the 'view.cache.filter_content' event to decorate a chunk of HTML with cache information.
  *
  * Added info about linked tags
  *
  * @param sfEvent $event   A sfEvent instance
  * @param string  $content The HTML content
  *
  * @return string The decorated HTML string
  */
 public function decorateContentWithDebug(sfEvent $event, $content)
 {
     $updatedContent = parent::decorateContentWithDebug($event, $content);
     if ($content === $updatedContent) {
         return $content;
     }
     $cacheMetadata = new CacheMetadata($this->getCache()->get($this->generateCacheKey($event['uri'])));
     if (null === $cacheMetadata->getData()) {
         return $content;
     }
     $tags = $cacheMetadata->getTags();
     ksort($tags, SORT_ASC);
     $tagsCount = count($tags);
     $tagsContent = sprintf('[cache&nbsp;tags]&nbsp;count:&nbsp;%d', $tagsCount);
     if (0 != $tagsCount) {
         $tagsContent .= ',&nbsp;tags:';
         foreach ($tags as $name => $version) {
             $tagsContent .= sprintf(' <span title="%s">%s</span>,', htmlspecialchars($version, ENT_QUOTES, sfConfig::get('sf_charset')), htmlspecialchars($name, ENT_QUOTES, sfConfig::get('sf_charset')));
         }
         $tagsContent = substr($tagsContent, 0, -1) . '.';
     }
     $textToReplace = '&nbsp;<br />&nbsp;';
     return str_replace($textToReplace, $tagsContent, $updatedContent);
 }