1
0
mirror of https://github.com/flextype/flextype.git synced 2025-08-08 22:26:46 +02:00

feat(cache): Move to PhpFastCache #457

This commit is contained in:
Awilum
2020-08-30 21:32:05 +03:00
parent e45bf89410
commit 5bd0b754ad
20 changed files with 20 additions and 838 deletions

View File

@@ -1,25 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Doctrine\Common\Cache\AcpuCache;
class AcpuCacheAdapter implements CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct()
{
}
public function getDriver() : object
{
return new AcpuCache();
}
}

View File

@@ -1,25 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Doctrine\Common\Cache\ArrayCache;
class ArrayCacheAdapter implements CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct()
{
}
public function getDriver() : object
{
return new ArrayCache();
}
}

View File

@@ -1,372 +0,0 @@
<?php
declare(strict_types=1);
/**
* Flextype (https://flextype.org)
* Founded by Sergey Romanenko and maintained by Flextype Community.
*/
namespace Flextype\App\Foundation\Cache;
use Flextype\Component\Filesystem\Filesystem;
use function clearstatcache;
use function error_reporting;
use function function_exists;
use function md5;
use function opcache_reset;
use function time;
class Cache
{
/**
* Unique cache key
*
* @var string Cache key.
*/
private $key;
/**
* Lifetime
*
* @var int Lifetime.
*/
private $lifetime;
/**
* Current time
*
* @var int Current time.
*/
private $now;
/**
* Cache Driver
*
* @var object
*/
private $driver;
/**
* Constructor
*
* @access public
*/
public function __construct()
{
// Create Cache Directory
! Filesystem::has(PATH['cache']) and Filesystem::createDir(PATH['cache']);
// Set current time
$this->now = time();
// Create cache key to allow invalidate all cache on configuration changes.
$cache_prefix = (flextype('registry')->get('flextype.settings.cache.prefix') ?? 'flextype');
$cache_unique_string = md5(PATH['project'] . flextype('registry')->get('flextype.manifest.version'));
$this->key = $cache_prefix . $cache_unique_string;
// Get Cache Driver
$this->driver = $this->getCacheDriver();
// Set the cache namespace to our unique key
$this->driver->setNamespace($this->key);
}
/**
* Get Cache Driver
*
* @access public
*/
public function getCacheDriver() : object
{
return flextype('cache_adapter')->getDriver();
}
/**
* Returns driver variable
*
* @access public
*/
public function driver() : object
{
return $this->driver;
}
/**
* Get cache key.
*
* @access public
*/
public function getKey() : string
{
return $this->key;
}
/**
* Fetches an entry from the cache.
*
* @param string $id The id of the cache entry to fetch.
*
* @return mixed|false The cached data or FALSE, if no cache entry exists for the given id.
*
* @access public
*/
public function fetch(string $id)
{
if (flextype('registry')->get('flextype.settings.cache.enabled')) {
return $this->driver->fetch($id);
}
return false;
}
/**
* Fetches multiplay items from the cache.
*
* @param array $keys Array of keys to retrieve from cache
*
* @return array Array of values retrieved for the given keys.
*/
public function fetchMultiple(array $keys) : array
{
if (flextype('registry')->get('flextype.settings.cache.enabled')) {
return $this->driver->fetchMultiple($keys);
}
return [];
}
/**
* Returns a boolean state of whether or not the item exists in the cache based on id key
*
* @param string $id the id of the cached data entry
*
* @return bool true if the cached items exists
*/
public function contains(string $id) : bool
{
if (flextype('registry')->get('flextype.settings.cache.enabled')) {
return $this->driver->contains($id);
}
return false;
}
/**
* Puts data into the cache.
*
* @param string $id The cache id.
* @param mixed $data The cache entry/data.
* @param int $lifetime The lifetime in number of seconds for this cache entry.
* If zero (the default), the entry never expires (although it may be deleted from the cache
* to make place for other items).
*
* @return bool TRUE if the operation was successful, FALSE if it wasn't.
*
* @access public
*/
public function save(string $id, $data, ?int $lifetime = null) : bool
{
if (! flextype('registry')->get('flextype.settings.cache.enabled')) {
return false;
}
if ($lifetime === null) {
$lifetime = $this->getLifetime();
}
return $this->driver->save($id, $data, $lifetime);
}
/**
* Puts multiple data into the cache.
*
* @param array $keysAndValues Array of keys and values to save in cache
* @param int $lifetime The lifetime. If != 0, sets a specific lifetime for these
* cache items (0 => infinite lifeTime).
*
* @return bool TRUE if the operation was successful, FALSE if it wasn't.
*/
public function saveMultiple(array $keysAndValues, int $lifetime = 0) : bool
{
if (! flextype('registry')->get('flextype.settings.cache.enabled')) {
return false;
}
return $this->saveMultiple($keysAndValues, $lifetime);
}
/**
* Delete item from the cache
*
* @param string $id The cache id.
*
* @return bool TRUE if the cache entry was successfully deleted, FALSE otherwise.
*/
public function delete(string $id) : bool
{
if (! flextype('registry')->get('flextype.settings.cache.enabled')) {
return false;
}
$this->driver->delete($id);
}
/**
* Delete multiple item from the cache.
*
* @param array $keys Array of keys to delete from cache
*
* @return bool TRUE if the operation was successful, FALSE if it wasn't
*/
public function deleteMultiple(array $keys) : bool
{
if (! flextype('registry')->get('flextype.settings.cache.enabled')) {
return false;
}
return $this->driver->deleteMultiple($keys);
}
/**
* Retrieves cached information from the data store.
*
* @return array|null An associative array with server's statistics if available, NULL otherwise.
*/
public function getStats() : ?array
{
if (! flextype('registry')->get('flextype.settings.cache.enabled')) {
return false;
}
return $this->driver->getStats();
}
/**
* Deletes all cache
*/
public function deleteAll() : bool
{
if (! flextype('registry')->get('flextype.settings.cache.enabled')) {
return false;
}
return $this->driver->deleteAll();
}
/**
* Flushes all cache items.
*
* @return bool TRUE if the cache items were successfully flushed, FALSE otherwise.
*/
public function flushAll() : bool
{
if (! flextype('registry')->get('flextype.settings.cache.enabled')) {
return false;
}
return $this->driver->flushAll();
}
/**
* Set the cache lifetime.
*
* @param int $future timestamp
*
* @access public
*/
public function setLifetime(int $future) : void
{
if (! $future) {
return;
}
$interval = $future-$this->now;
if ($interval <= 0 || $interval >= $this->getLifetime()) {
return;
}
$this->lifetime = $interval;
}
/**
* Retrieve the cache lifetime (in seconds)
*
* @return mixed
*
* @access public
*/
public function getLifetime()
{
if ($this->lifetime === null) {
$this->lifetime = flextype('registry')->get('flextype.settings.cache.lifetime') ?: 604800;
}
return $this->lifetime;
}
/**
* Purge specific cache directory
*
* @param $directory Directory to purge
*
* @access public
*/
public function purge(string $directory) : void
{
// Run event: onCacheBeforePurge
flextype('emitter')->emit('onCacheBeforePurge');
// Remove specific cache directory
Filesystem::deleteDir(PATH['cache'] . '/' . $directory);
// Save and Mute error_reporting
$errorReporting = error_reporting();
error_reporting(0);
// Clear stat cache
clearstatcache();
// Clear opcache
function_exists('opcache_reset') and opcache_reset();
// Restore error_reporting
error_reporting($errorReporting);
// Run event: onCacheAfterPurge
flextype('emitter')->emit('onCacheAfterPurge');
}
/**
* Purge ALL Cache directories
*
* @access public
*/
public function purgeAll() : void
{
// Run event: onCacheAfterPurgeAll
flextype('emitter')->emit('onCacheBeforePurgeAll');
// Remove cache directory
Filesystem::deleteDir(PATH['cache']);
// Save and Mute error_reporting
$errorReporting = error_reporting();
error_reporting(0);
// Clear stat cache
clearstatcache();
// Clear opcache
function_exists('opcache_reset') and opcache_reset();
// Restore error_reporting
error_reporting($errorReporting);
// Run event: onCacheAfterPurgeAll
flextype('emitter')->emit('onCacheAfterPurgeAll');
}
}

View File

@@ -1,20 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
interface CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct();
/**
* Returns the cache driver object
*/
public function getDriver() : object;
}

View File

@@ -1,32 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Doctrine\Common\Cache\FilesystemCache;
use Flextype\Component\Filesystem\Filesystem;
class FilesystemCacheAdapter implements CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct()
{
}
public function getDriver() : object
{
$cache_directory = PATH['cache'] . '/doctrine/';
if (! Filesystem::has($cache_directory)) {
Filesystem::createDir($cache_directory);
}
return new FilesystemCache($cache_directory);
}
}

View File

@@ -1,35 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Doctrine\Common\Cache\MemcachedCache;
use Memecached;
class MemcachedCacheAdapter implements CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct()
{
}
public function getDriver() : object
{
$memcached = new Memecached();
$memcached->addServer(
flextype('registry')->get('flextype.settings.cache.memcached.server', 'localhost'),
flextype('registry')->get('flextype.settings.cache.memcache.port', 11211)
);
$driver = new MemcachedCache();
$driver->setMemcached($memcached);
return $driver;
}
}

View File

@@ -1,113 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Doctrine\Common\Cache\FileCache;
use function restore_error_handler;
use function set_error_handler;
use function sprintf;
use function time;
use function var_export;
/**
* Php file cache driver.
*/
class PhpArrayFileCache extends FileCache
{
public const EXTENSION = '.doctrineacache.php';
/**
* @var callable
*
* This is cached in a local static variable to avoid instantiating a closure each time we need an empty handler
*/
private static $emptyErrorHandler;
/**
* {@inheritdoc}
*/
public function __construct($directory, $extension = self::EXTENSION, $umask = 0002)
{
parent::__construct($directory, $extension, $umask);
self::$emptyErrorHandler = static function () : void {
};
}
/**
* {@inheritdoc}
*/
protected function doFetch($id)
{
$value = $this->includeFileForId($id);
if ($value === null) {
return false;
}
if ($value['lifetime'] !== 0 && $value['lifetime'] < time()) {
return false;
}
return $value['data'];
}
/**
* {@inheritdoc}
*/
protected function doContains($id)
{
$value = $this->includeFileForId($id);
if ($value === null) {
return false;
}
return $value['lifetime'] === 0 || $value['lifetime'] > time();
}
/**
* {@inheritdoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
if ($lifeTime > 0) {
$lifeTime = time() + $lifeTime;
}
$filename = $this->getFilename($id);
$value = [
'lifetime' => $lifeTime,
'data' => $data,
];
$value = var_export($value, true);
$code = sprintf('<?php return %s;', $value);
return $this->writeFile($filename, $code);
}
/**
* @return array|null
*/
private function includeFileForId(string $id) : ?array
{
$fileName = $this->getFilename($id);
// note: error suppression is still faster than `file_exists`, `is_file` and `is_readable`
set_error_handler(self::$emptyErrorHandler);
$value = include $fileName;
restore_error_handler();
if (! isset($value['lifetime'])) {
return null;
}
return $value;
}
}

View File

@@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Flextype\Component\Filesystem\Filesystem;
class PhpArrayFileCacheAdapter implements CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct()
{
}
public function getDriver() : object
{
$cache_directory = PATH['cache'] . '/doctrine/';
if (! Filesystem::has($cache_directory)) {
Filesystem::createDir($cache_directory);
}
return new PhpArrayFileCache($cache_directory);
}
}

View File

@@ -1,32 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Doctrine\Common\Cache\PhpFileCache;
use Flextype\Component\Filesystem\Filesystem;
class PhpFileCacheAdapter implements CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct()
{
}
public function getDriver() : object
{
$cache_directory = PATH['cache'] . '/doctrine/';
if (! Filesystem::has($cache_directory)) {
Filesystem::createDir($cache_directory);
}
return new PhpFileCache($cache_directory);
}
}

View File

@@ -1,48 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Doctrine\Common\Cache\RedisCache;
use Redis;
use RedisException;
class RedisCacheAdapter implements CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct()
{
}
public function getDriver() : object
{
$redis = new Redis();
$socket = flextype('registry')->get('flextype.settings.cache.redis.socket', false);
$password = flextype('registry')->get('flextype.settings.cache.redis.password', false);
if ($socket) {
$redis->connect($socket);
} else {
$redis->connect(
flextype('registry')->get('flextype.settings.cache.redis.server', 'localhost'),
flextype('registry')->get('flextype.settings.cache.redis.port', 6379)
);
}
// Authenticate with password if set
if ($password && ! $redis->auth($password)) {
throw new RedisException('Redis authentication failed');
}
$driver = new RedisCache();
$driver->setRedis($redis);
return $driver;
}
}

View File

@@ -1,35 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Doctrine\Common\Cache\SQLite3Cache;
use Flextype\Component\Filesystem\Filesystem;
use SQLite3;
class SQLite3CacheAdapter implements CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct()
{
}
public function getDriver() : object
{
$cache_directory = PATH['cache'] . '/doctrine/';
if (! Filesystem::has($cache_directory)) {
Filesystem::createDir($cache_directory);
}
$db = new SQLite3($cache_directory . flextype('registry')->get('flextype.settings.cache.sqlite3.database', 'flextype') . '.db');
return new SQLite3Cache($db, flextype('registry')->get('flextype.settings.cache.sqlite3.table', 'flextype'));
}
}

View File

@@ -1,25 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Doctrine\Common\Cache\WinCacheCache;
class WinCacheCacheAdapter implements CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct()
{
}
public function getDriver() : object
{
return new WinCacheCache();
}
}

View File

@@ -1,25 +0,0 @@
<?php
declare(strict_types=1);
namespace Flextype\App\Foundation\Cache;
use Doctrine\Common\Cache\ZendDataCache;
class ZendDataCacheCacheAdapter implements CacheAdapterInterface
{
/**
* Constructor
*
* @access public
*/
public function __construct()
{
}
public function getDriver() : object
{
return new ZendDataCache();
}
}

View File

@@ -108,9 +108,9 @@ class Entries
$entry_cache_id = $this->getCacheID($this->entry_id);
// Try to get current requested entry from cache
if (flextype('cache')->contains($entry_cache_id)) {
if (flextype('cache')->has($entry_cache_id)) {
// Fetch entry from cache
$this->entry = flextype('cache')->fetch($entry_cache_id);
$this->entry = flextype('cache')->get($entry_cache_id);
// Run event: onEntryAfterCacheInitialized
flextype('emitter')->emit('onEntryAfterCacheInitialized');
@@ -142,7 +142,7 @@ class Entries
// Save entry data to cache
if ($cache) {
flextype('cache')->save($entry_cache_id, $this->entry);
flextype('cache')->set($entry_cache_id, $this->entry);
}
// Return entry data

View File

@@ -78,15 +78,15 @@ class Plugins
}
// Get plugins from cache or scan plugins folder and create new plugins cache item
if (flextype('cache')->contains($plugins_cache_id)) {
flextype('registry')->set('plugins', flextype('cache')->fetch($plugins_cache_id));
if (flextype('cache')->has($plugins_cache_id)) {
flextype('registry')->set('plugins', flextype('cache')->get($plugins_cache_id));
if (flextype('cache')->contains($locale)) {
I18n::add(flextype('cache')->fetch($locale), $locale);
if (flextype('cache')->has($locale)) {
I18n::add(flextype('cache')->get($locale), $locale);
} else {
// Save plugins dictionary
$dictionary = $this->getPluginsDictionary($plugins_list, $locale);
flextype('cache')->save($locale, $dictionary[$locale]);
flextype('cache')->set($locale, $dictionary[$locale]);
}
} else {
// Init plugin configs
@@ -167,11 +167,11 @@ class Plugins
// Save plugins list
flextype('registry')->set('plugins', $plugins);
flextype('cache')->save($plugins_cache_id, $plugins);
flextype('cache')->set($plugins_cache_id, $plugins);
// Save plugins dictionary
$dictionary = $this->getPluginsDictionary($plugins_list, $locale);
flextype('cache')->save($locale, $dictionary[$locale]);
flextype('cache')->set($locale, $dictionary[$locale]);
}
$this->includeEnabledPlugins();

View File

@@ -41,12 +41,12 @@ class Markdown
if ($cache === true && flextype('registry')->get('flextype.settings.cache.enabled') === true) {
$key = $this->getCacheID($input);
if ($data_from_cache = flextype('cache')->fetch($key)) {
if ($data_from_cache = flextype('cache')->get($key)) {
return $data_from_cache;
}
$data = $this->_parse($input);
flextype('cache')->save($key, $data);
flextype('cache')->set($key, $data);
return $data;
}

View File

@@ -89,12 +89,12 @@ class Shortcode
if ($cache === true && flextype('registry')->get('flextype.settings.cache.enabled') === true) {
$key = $this->getCacheID($input);
if ($data_from_cache = flextype('cache')->fetch($key)) {
if ($data_from_cache = flextype('cache')->get($key)) {
return $data_from_cache;
}
$data = $this->shortcode->process($input);
flextype('cache')->save($key, $data);
flextype('cache')->set($key, $data);
return $data;
}

View File

@@ -47,12 +47,12 @@ class Frontmatter
if ($cache === true && flextype('registry')->get('flextype.settings.cache.enabled') === true) {
$key = $this->getCacheID($input);
if ($data_from_cache = flextype('cache')->fetch($key)) {
if ($data_from_cache = flextype('cache')->get($key)) {
return $data_from_cache;
}
$data = $this->_decode($input);
flextype('cache')->save($key, $data);
flextype('cache')->set($key, $data);
return $data;
}

View File

@@ -59,12 +59,12 @@ class Json
if ($cache === true && flextype('registry')->get('flextype.settings.cache.enabled') === true) {
$key = $this->getCacheID($input);
if ($data_from_cache = flextype('cache')->fetch($key)) {
if ($data_from_cache = flextype('cache')->get($key)) {
return $data_from_cache;
}
$data = $this->_decode($input, $assoc, $depth, $flags);
flextype('cache')->save($key, $data);
flextype('cache')->set($key, $data);
return $data;
}

View File

@@ -76,12 +76,12 @@ class Yaml
if ($cache === true && flextype('registry')->get('flextype.settings.cache.enabled') === true) {
$key = $this->getCacheID($input);
if ($data_from_cache = flextype('cache')->fetch($key)) {
if ($data_from_cache = flextype('cache')->get($key)) {
return $data_from_cache;
}
$data = $this->_decode($input, $flags);
flextype('cache')->save($key, $data);
flextype('cache')->set($key, $data);
return $data;
}