2015-08-17 17:00:26 -07:00
< ? php
namespace Drupal\Component\FileCache ;
/**
* Allows to cache data based on file modification dates .
*/
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 );
}
}
2015-10-08 11:40:12 -07:00
/**
* Resets the static cache .
*
* @ todo Replace this once https :// www . drupal . org / node / 2260187 is in .
*/
public static function reset () {
static :: $cached = [];
}
2015-08-17 17:00:26 -07:00
}