You are here

class FileCache in Drupal 9

Same name and namespace in other branches
  1. 8 core/lib/Drupal/Component/FileCache/FileCache.php \Drupal\Component\FileCache\FileCache

Allows to cache data based on file modification dates.

Hierarchy

Expanded class hierarchy of FileCache

3 files declare their use of FileCache
FileCacheFactoryTest.php in core/tests/Drupal/Tests/Component/FileCache/FileCacheFactoryTest.php
FileCacheTest.php in core/tests/Drupal/Tests/Component/FileCache/FileCacheTest.php
KernelTestBase.php in core/tests/Drupal/KernelTests/KernelTestBase.php

File

core/lib/Drupal/Component/FileCache/FileCache.php, line 8

Namespace

Drupal\Component\FileCache
View source
class FileCache implements FileCacheInterface {

  /**
   * Prefix that is used for cache entries.
   *
   * @var string
   */
  protected $prefix;

  /**
   * Static cache that contains already loaded cache entries.
   *
   * @var array
   */
  protected static $cached = [];

  /**
   * The collection identifier of this cache.
   *
   * @var string
   */
  protected $collection;

  /**
   * The cache backend backing this FileCache object.
   *
   * @var \Drupal\Component\FileCache\FileCacheBackendInterface
   */
  protected $cache;

  /**
   * Constructs a FileCache object.
   *
   * @param string $prefix
   *   The cache prefix.
   * @param string $collection
   *   A collection identifier to ensure that the same files could be cached for
   *   different purposes without clashing.
   * @param string|null $cache_backend_class
   *   (optional) The class that should be used as cache backend.
   * @param array $cache_backend_configuration
   *   (optional) The configuration for the backend class.
   */
  public function __construct($prefix, $collection, $cache_backend_class = NULL, array $cache_backend_configuration = []) {
    if (empty($prefix)) {
      throw new \InvalidArgumentException('Required prefix configuration is missing');
    }
    $this->prefix = $prefix;
    $this->collection = $collection;
    if (isset($cache_backend_class)) {
      $this->cache = new $cache_backend_class($cache_backend_configuration);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function get($filepath) {
    $filepaths = [
      $filepath,
    ];
    $cached = $this
      ->getMultiple($filepaths);
    return isset($cached[$filepath]) ? $cached[$filepath] : NULL;
  }

  /**
   * {@inheritdoc}
   */
  public function getMultiple(array $filepaths) {
    $file_data = [];
    $remaining_cids = [];

    // First load from the static cache what we can.
    foreach ($filepaths as $filepath) {
      if (!file_exists($filepath)) {
        continue;
      }
      $realpath = realpath($filepath);

      // If the file exists but realpath returns nothing, it is using a stream
      // wrapper, those are not supported.
      if (empty($realpath)) {
        continue;
      }
      $cid = $this->prefix . ':' . $this->collection . ':' . $realpath;
      if (isset(static::$cached[$cid]) && static::$cached[$cid]['mtime'] == filemtime($filepath)) {
        $file_data[$filepath] = static::$cached[$cid]['data'];
      }
      else {

        // Collect a list of cache IDs that we still need to fetch from cache
        // backend.
        $remaining_cids[$cid] = $filepath;
      }
    }

    // If there are any cache IDs left to fetch from the cache backend.
    if ($remaining_cids && $this->cache) {
      $cache_results = $this->cache
        ->fetch(array_keys($remaining_cids)) ?: [];
      foreach ($cache_results as $cid => $cached) {
        $filepath = $remaining_cids[$cid];
        if ($cached['mtime'] == filemtime($filepath)) {
          $file_data[$cached['filepath']] = $cached['data'];
          static::$cached[$cid] = $cached;
        }
      }
    }
    return $file_data;
  }

  /**
   * {@inheritdoc}
   */
  public function set($filepath, $data) {
    $realpath = realpath($filepath);
    $cached = [
      'mtime' => filemtime($filepath),
      'filepath' => $filepath,
      'data' => $data,
    ];
    $cid = $this->prefix . ':' . $this->collection . ':' . $realpath;
    static::$cached[$cid] = $cached;
    if ($this->cache) {
      $this->cache
        ->store($cid, $cached);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function delete($filepath) {
    $realpath = realpath($filepath);
    $cid = $this->prefix . ':' . $this->collection . ':' . $realpath;
    unset(static::$cached[$cid]);
    if ($this->cache) {
      $this->cache
        ->delete($cid);
    }
  }

  /**
   * Resets the static cache.
   *
   * @todo Replace this once https://www.drupal.org/node/2260187 is in.
   */
  public static function reset() {
    static::$cached = [];
  }

}

Members

Namesort descending Modifiers Type Description Overrides
FileCache::$cache protected property The cache backend backing this FileCache object.
FileCache::$cached protected static property Static cache that contains already loaded cache entries.
FileCache::$collection protected property The collection identifier of this cache.
FileCache::$prefix protected property Prefix that is used for cache entries.
FileCache::delete public function Deletes data from the cache. Overrides FileCacheInterface::delete
FileCache::get public function Gets data based on a filename. Overrides FileCacheInterface::get
FileCache::getMultiple public function Gets data based on filenames. Overrides FileCacheInterface::getMultiple
FileCache::reset public static function Resets the static cache.
FileCache::set public function Stores data based on a filename. Overrides FileCacheInterface::set
FileCache::__construct public function Constructs a FileCache object.