[+]: update composer.json (require min. php 7.0) + update "voku/simple-cache"
This commit is contained in:
@ -1,3 +1,15 @@
|
||||
# Changelog 4.0.1 (2019-03-03)
|
||||
|
||||
- hide "warning" about Zend OPcache API is restricted by "restrict_api"
|
||||
|
||||
|
||||
# Changelog 4.0.0 (2019-02-24)
|
||||
|
||||
- add "CacheAdapterAutoManager"
|
||||
- fix typos in "CachePsr16"
|
||||
- "iCache->setItemToDate()" now accepts DateTimeInterface instead of DateTime
|
||||
|
||||
|
||||
# Changelog 3.2.2 (2018-12-21)
|
||||
|
||||
- fix APC(u) detection for CLI usage
|
||||
|
@ -6,10 +6,10 @@
|
||||
[](https://packagist.org/packages/voku/simple-cache)
|
||||
[](https://packagist.org/packages/voku/simple-cache)
|
||||
[](https://packagist.org/packages/voku/simple-cache)
|
||||
[](https://www.paypal.me/moelleken)
|
||||
[](https://www.patreon.com/voku)
|
||||
|
||||
|
||||
:zap: Simple Cache Class
|
||||
===================
|
||||
# :zap: Simple Cache Class
|
||||
|
||||
This is a simple Cache Abstraction Layer for PHP >= 7.0 that provides a simple interaction
|
||||
with your cache-server. You can define the Adapter / Serializer in the "constructor" or the class will auto-detect you server-cache in this order:
|
||||
@ -21,27 +21,26 @@ with your cache-server. You can define the Adapter / Serializer in the "construc
|
||||
5. OpCache (via PHP-files)
|
||||
6. Static-PHP-Cache
|
||||
|
||||
## Get "Simple Cache"
|
||||
### Get "Simple Cache"
|
||||
|
||||
You can download it from here, or require it using [composer](https://packagist.org/packages/voku/simple-cache).
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"voku/simple-cache": "3.*"
|
||||
"voku/simple-cache": "4.*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Install via "composer require"
|
||||
### Install via "composer require"
|
||||
|
||||
```shell
|
||||
composer require voku/simple-cache
|
||||
composer require predis/predis # if you will use redis as cache, then add predis
|
||||
```
|
||||
|
||||
|
||||
## Quick Start
|
||||
### Quick Start
|
||||
|
||||
```php
|
||||
use voku\cache\Cache;
|
||||
@ -55,7 +54,7 @@ $bar = $cache->getItem('foo');
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
### Usage
|
||||
|
||||
```php
|
||||
use voku\cache\Cache;
|
||||
@ -100,6 +99,84 @@ If you use the parameter "$checkForUser" (=== true) in the constructor, then the
|
||||
|
||||
-> You can also overwrite the check for the user, if you add a global function named "checkForDev()".
|
||||
|
||||
## Overwrite the auto-connection option
|
||||
|
||||
## License
|
||||
You can overwrite the cache auto-detect via "CacheAdapterAutoManager" and the
|
||||
"$cacheAdapterManagerForAutoConnect" option in the "Cache"-constructor. Additional you can also
|
||||
activate the "$cacheAdapterManagerForAutoConnectOverwrite" option in the "Cache"-constructor, so that
|
||||
you can implement your own cache auto-detect logic.
|
||||
|
||||
```php
|
||||
|
||||
$cacheManager = new \voku\cache\CacheAdapterAutoManager();
|
||||
|
||||
// 1. check for "APCu" support first
|
||||
$cacheManager->addAdapter(
|
||||
\voku\cache\AdapterApcu::class
|
||||
);
|
||||
|
||||
// 2. check for "APC" support
|
||||
$cacheManager->addAdapter(
|
||||
\voku\cache\AdapterApcu::class
|
||||
);
|
||||
|
||||
// 3. try "OpCache"-Cache
|
||||
$cacheManager->addAdapter(
|
||||
\voku\cache\AdapterOpCache::class,
|
||||
static function () {
|
||||
$cacheDir = \realpath(\sys_get_temp_dir()) . '/simple_php_cache_opcache';
|
||||
|
||||
return $cacheDir;
|
||||
}
|
||||
);
|
||||
|
||||
// 4. try "File"-Cache
|
||||
$cacheManager->addAdapter(
|
||||
\voku\cache\AdapterFileSimple::class,
|
||||
static function () {
|
||||
$cacheDir = \realpath(\sys_get_temp_dir()) . '/simple_php_cache_file';
|
||||
|
||||
return $cacheDir;
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// 5. use Memory Cache as final fallback
|
||||
$cacheManager->addAdapter(
|
||||
\voku\cache\AdapterArray::class
|
||||
);
|
||||
|
||||
$cache = new \voku\cache\CachePsr16(
|
||||
null, // use auto-detection
|
||||
null, // use auto-detection
|
||||
false, // do not check for usage
|
||||
true, // enable the cache
|
||||
false, // do not check for admin session
|
||||
false, // do not check for dev
|
||||
false, // do not check for admin session
|
||||
false, // do not check for server vs. client ip
|
||||
'', // do not use "_GET"-parameter for disabling
|
||||
$cacheManager, // new auto-detection logic
|
||||
true // overwrite the auto-detection logic
|
||||
);
|
||||
```
|
||||
|
||||
### Support
|
||||
|
||||
For support and donations please visit [Github](https://github.com/voku/simple-cache/) | [Issues](https://github.com/voku/simple-cache/issues) | [PayPal](https://paypal.me/moelleken) | [Patreon](https://www.patreon.com/voku).
|
||||
|
||||
For status updates and release announcements please visit [Releases](https://github.com/voku/simple-cache/releases) | [Twitter](https://twitter.com/suckup_de) | [Patreon](https://www.patreon.com/voku/posts).
|
||||
|
||||
For professional support please contact [me](https://about.me/voku).
|
||||
|
||||
### Thanks
|
||||
|
||||
- Thanks to [GitHub](https://github.com) (Microsoft) for hosting the code and a good infrastructure including Issues-Managment, etc.
|
||||
- Thanks to [IntelliJ](https://www.jetbrains.com) as they make the best IDEs for PHP and they gave me an open source license for PhpStorm!
|
||||
- Thanks to [Travis CI](https://travis-ci.com/) for being the most awesome, easiest continous integration tool out there!
|
||||
- Thanks to [StyleCI](https://styleci.io/) for the simple but powerfull code style check.
|
||||
- Thanks to [PHPStan](https://github.com/phpstan/phpstan) && [Psalm](https://github.com/vimeo/psalm) for relly great Static analysis tools and for discover bugs in the code!
|
||||
|
||||
|
||||
### License
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fvoku%2Fsimple-cache?ref=badge_large)
|
||||
|
@ -25,7 +25,7 @@
|
||||
"psr/simple-cache": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~6.0"
|
||||
"phpunit/phpunit": "~6.0 || ~7.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
@ -85,7 +85,8 @@ class AdapterApc implements iAdapter
|
||||
* @param bool $limited - If $limited is TRUE, the return value will exclude the individual list of cache
|
||||
* entries. This is useful when trying to optimize calls for statistics gathering
|
||||
*
|
||||
* @return array|bool <p>Array of cached data (and meta-data) or FALSE on failure.</p>
|
||||
* @return array|false
|
||||
* <p>Array of cached data (and meta-data) or FALSE on failure.</p>
|
||||
*/
|
||||
public function cacheInfo(string $type = '', bool $limited = false): array
|
||||
{
|
||||
|
@ -84,7 +84,8 @@ class AdapterApcu implements iAdapter
|
||||
* @param bool $limited - If $limited is TRUE, the return value will exclude the individual list of cache
|
||||
* entries. This is useful when trying to optimize calls for statistics gathering
|
||||
*
|
||||
* @return array|bool <p>Array of cached data (and meta-data) or FALSE on failure.</p>
|
||||
* @return array|false
|
||||
* <p>Array of cached data (and meta-data) or FALSE on failure.</p>
|
||||
*/
|
||||
public function cacheInfo(bool $limited = false): array
|
||||
{
|
||||
|
@ -86,7 +86,9 @@ class AdapterFile extends AdapterFileAbstract
|
||||
\fflush($fp);
|
||||
\flock($fp, \LOCK_UN);
|
||||
}
|
||||
\fclose($fp);
|
||||
if ($fp !== false) {
|
||||
\fclose($fp);
|
||||
}
|
||||
|
||||
return $octetWritten !== false;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ abstract class AdapterFileAbstract implements iAdapter
|
||||
protected $fileMode = '0755';
|
||||
|
||||
/**
|
||||
* @param string|null $cacheDir
|
||||
* @param \callable|string|null $cacheDir
|
||||
*/
|
||||
public function __construct($cacheDir = null)
|
||||
{
|
||||
@ -44,9 +44,13 @@ abstract class AdapterFileAbstract implements iAdapter
|
||||
$cacheDir = \realpath(\sys_get_temp_dir()) . '/simple_php_cache';
|
||||
}
|
||||
|
||||
$this->cacheDir = (string) $cacheDir;
|
||||
if (\is_callable($cacheDir)) {
|
||||
$this->cacheDir = (string) \call_user_func($cacheDir);
|
||||
} else {
|
||||
$this->cacheDir = (string) $cacheDir;
|
||||
}
|
||||
|
||||
if ($this->createCacheDirectory($cacheDir) === true) {
|
||||
if ($this->createCacheDirectory($this->cacheDir) === true) {
|
||||
$this->installed = true;
|
||||
}
|
||||
}
|
||||
@ -106,14 +110,14 @@ abstract class AdapterFileAbstract implements iAdapter
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cacheFile
|
||||
* @param string $cacheFileWithPath
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function deleteFile($cacheFile): bool
|
||||
protected function deleteFile($cacheFileWithPath): bool
|
||||
{
|
||||
if (\is_file($cacheFile)) {
|
||||
return \unlink($cacheFile);
|
||||
if (\is_file($cacheFileWithPath)) {
|
||||
return \unlink($cacheFileWithPath);
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -199,7 +203,7 @@ abstract class AdapterFileAbstract implements iAdapter
|
||||
*
|
||||
* e.g. '0777', or '0755' ...
|
||||
*
|
||||
* @param $fileMode
|
||||
* @param string $fileMode
|
||||
*/
|
||||
public function setFileMode($fileMode)
|
||||
{
|
||||
@ -207,7 +211,7 @@ abstract class AdapterFileAbstract implements iAdapter
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $ttl
|
||||
* @param int $ttl
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -29,7 +29,12 @@ class AdapterOpCache extends AdapterFileSimple
|
||||
|
||||
if (self::$hasCompileFileFunction === null) {
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
self::$hasCompileFileFunction = \function_exists('opcache_compile_file') && !empty(\opcache_get_status());
|
||||
/** @noinspection PhpUsageOfSilenceOperatorInspection */
|
||||
self::$hasCompileFileFunction = (
|
||||
\function_exists('opcache_compile_file')
|
||||
&&
|
||||
!empty(@\opcache_get_status())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,27 @@ use voku\cache\Exception\InvalidArgumentException;
|
||||
class Cache implements iCache
|
||||
{
|
||||
/**
|
||||
* @var iAdapter
|
||||
* @var array
|
||||
*/
|
||||
protected static $STATIC_CACHE = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $STATIC_CACHE_EXPIRE = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $STATIC_CACHE_COUNTER = [];
|
||||
|
||||
/**
|
||||
* @var iAdapter|null
|
||||
*/
|
||||
protected $adapter;
|
||||
|
||||
/**
|
||||
* @var iSerializer
|
||||
* @var iSerializer|null
|
||||
*/
|
||||
protected $serializer;
|
||||
|
||||
@ -69,21 +84,6 @@ class Cache implements iCache
|
||||
*/
|
||||
protected $isAdminSession;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $STATIC_CACHE = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $STATIC_CACHE_EXPIRE = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $STATIC_CACHE_COUNTER = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
@ -92,19 +92,27 @@ class Cache implements iCache
|
||||
/**
|
||||
* __construct
|
||||
*
|
||||
* @param iAdapter|null $adapter
|
||||
* @param iSerializer|null $serializer
|
||||
* @param bool $checkForUsage <p>admin-session || server-ip == client-ip || check for
|
||||
* dev</p>
|
||||
* @param bool $cacheEnabled <p>false will disable the cache (use it e.g. for global
|
||||
* settings)</p>
|
||||
* @param bool|string $isAdminSession <p>set a admin-id, if the user is a admin (so we can
|
||||
* disable cache for this user)
|
||||
* @param bool $useCheckForAdminSession <p>use $isAdminSession flag or not</p>
|
||||
* @param bool $useCheckForDev <p>use checkForDev() or not</p>
|
||||
* @param bool $useCheckForServerIpIsClientIp <p>use check for server-ip == client-ip or not</p>
|
||||
* @param string $disableCacheGetParameter <p>set the _GET parameter for disabling the cache,
|
||||
* disable this check via empty string</p>
|
||||
* @param iAdapter|null $adapter
|
||||
* @param iSerializer|null $serializer
|
||||
* @param bool $checkForUsage <p>check for admin-session && check for
|
||||
* server-ip == client-ip
|
||||
* && check for dev</p>
|
||||
* @param bool $cacheEnabled <p>false === disable the cache (use it
|
||||
* e.g. for global settings)</p>
|
||||
* @param bool $isAdminSession <p>true === disable cache for this user
|
||||
* (use it e.g. for admin user settings)
|
||||
* @param bool $useCheckForAdminSession <p>use $isAdminSession flag or not</p>
|
||||
* @param bool $useCheckForDev <p>use checkForDev() or not</p>
|
||||
* @param bool $useCheckForServerIpIsClientIp <p>use check for server-ip == client-ip
|
||||
* or
|
||||
* not</p>
|
||||
* @param string $disableCacheGetParameter <p>set the _GET parameter for disabling
|
||||
* the cache, disable this check via empty
|
||||
* string</p>
|
||||
* @param CacheAdapterAutoManager $cacheAdapterManagerForAutoConnect <p>Overwrite some Adapters for the
|
||||
* auto-connect-function.</p>
|
||||
* @param bool $cacheAdapterManagerForAutoConnectOverwrite <p>true === Use only Adapters from your
|
||||
* "CacheAdapterManager".</p>
|
||||
*/
|
||||
public function __construct(
|
||||
iAdapter $adapter = null,
|
||||
@ -115,7 +123,9 @@ class Cache implements iCache
|
||||
bool $useCheckForDev = true,
|
||||
bool $useCheckForAdminSession = true,
|
||||
bool $useCheckForServerIpIsClientIp = true,
|
||||
string $disableCacheGetParameter = 'testWithoutCache'
|
||||
string $disableCacheGetParameter = 'testWithoutCache',
|
||||
CacheAdapterAutoManager $cacheAdapterManagerForAutoConnect = null,
|
||||
bool $cacheAdapterManagerForAutoConnectOverwrite = false
|
||||
) {
|
||||
$this->isAdminSession = $isAdminSession;
|
||||
|
||||
@ -128,19 +138,19 @@ class Cache implements iCache
|
||||
// First check if the cache is active at all.
|
||||
$this->isActive = $cacheEnabled;
|
||||
if (
|
||||
$this->isActive === true
|
||||
$this->isActive
|
||||
&&
|
||||
$checkForUsage === true
|
||||
$checkForUsage
|
||||
) {
|
||||
$this->setActive($this->isCacheActiveForTheCurrentUser());
|
||||
}
|
||||
|
||||
// If the cache is active, then try to auto-connect to the best possible cache-system.
|
||||
if ($this->isActive === true) {
|
||||
if ($this->isActive) {
|
||||
$this->setPrefix($this->getTheDefaultPrefix());
|
||||
|
||||
if ($adapter === null) {
|
||||
$adapter = $this->autoConnectToAvailableCacheSystem();
|
||||
$adapter = $this->autoConnectToAvailableCacheSystem($cacheAdapterManagerForAutoConnect, $cacheAdapterManagerForAutoConnectOverwrite);
|
||||
}
|
||||
|
||||
// INFO: Memcache(d) has his own "serializer", so don't use it twice
|
||||
@ -172,93 +182,81 @@ class Cache implements iCache
|
||||
}
|
||||
|
||||
/**
|
||||
* enable / disable the cache
|
||||
* Auto-connect to the available cache-system on the server.
|
||||
*
|
||||
* @param bool $isActive
|
||||
*/
|
||||
public function setActive(bool $isActive)
|
||||
{
|
||||
$this->isActive = $isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the current use is a admin || dev || server == client
|
||||
* @param CacheAdapterAutoManager $cacheAdapterManagerForAutoConnect <p>Overwrite some Adapters for the
|
||||
* auto-connect-function.</p>
|
||||
* @param bool $cacheAdapterManagerForAutoConnectOverwrite <p>true === Use only Adapters from your
|
||||
* "CacheAdapterManager".</p>
|
||||
*
|
||||
* @return bool
|
||||
* @return iAdapter
|
||||
*/
|
||||
public function isCacheActiveForTheCurrentUser(): bool
|
||||
{
|
||||
$active = true;
|
||||
protected function autoConnectToAvailableCacheSystem(
|
||||
CacheAdapterAutoManager $cacheAdapterManagerForAutoConnect = null,
|
||||
bool $cacheAdapterManagerForAutoConnectOverwrite = false
|
||||
): iAdapter {
|
||||
static $AUTO_ADAPTER_STATIC_CACHE = null;
|
||||
|
||||
// test the cache, with this GET-parameter
|
||||
if ($this->disableCacheGetParameter) {
|
||||
$testCache = isset($_GET[$this->disableCacheGetParameter]) ? (int) $_GET[$this->disableCacheGetParameter] : 0;
|
||||
} else {
|
||||
$testCache = 0;
|
||||
if (
|
||||
\is_object($AUTO_ADAPTER_STATIC_CACHE)
|
||||
&&
|
||||
$AUTO_ADAPTER_STATIC_CACHE instanceof iAdapter
|
||||
) {
|
||||
return $AUTO_ADAPTER_STATIC_CACHE;
|
||||
}
|
||||
|
||||
if ($testCache !== 1) {
|
||||
if (
|
||||
// admin session is active
|
||||
(
|
||||
$this->useCheckForAdminSession
|
||||
&&
|
||||
$this->isAdminSession
|
||||
)
|
||||
||
|
||||
// server == client
|
||||
(
|
||||
$this->useCheckForServerIpIsClientIp === true
|
||||
&&
|
||||
isset($_SERVER['SERVER_ADDR'])
|
||||
&&
|
||||
$_SERVER['SERVER_ADDR'] === $this->getClientIp()
|
||||
)
|
||||
||
|
||||
// user is a dev
|
||||
(
|
||||
$this->useCheckForDev === true
|
||||
&&
|
||||
$this->checkForDev() === true
|
||||
)
|
||||
) {
|
||||
$active = false;
|
||||
// init
|
||||
$adapter = null;
|
||||
|
||||
$cacheAdapterManagerDefault = CacheAdapterAutoManager::getDefaultsForAutoInit();
|
||||
|
||||
if ($cacheAdapterManagerForAutoConnect !== null) {
|
||||
if ($cacheAdapterManagerForAutoConnectOverwrite) {
|
||||
$cacheAdapterManagerDefault = $cacheAdapterManagerForAutoConnect;
|
||||
} else {
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$cacheAdapterManagerDefault->merge($cacheAdapterManagerForAutoConnect);
|
||||
}
|
||||
}
|
||||
|
||||
return $active;
|
||||
foreach ($cacheAdapterManagerDefault->getAdapters() as $adapterTmp => $callableFunctionTmp) {
|
||||
|
||||
/** @var iAdapter $adapterTest */
|
||||
if ($callableFunctionTmp !== null) {
|
||||
$adapterTest = new $adapterTmp($callableFunctionTmp);
|
||||
} else {
|
||||
$adapterTest = new $adapterTmp();
|
||||
}
|
||||
|
||||
if ($adapterTest->installed()) {
|
||||
$adapter = $adapterTest;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// save to static cache
|
||||
$AUTO_ADAPTER_STATIC_CACHE = $adapter;
|
||||
|
||||
return $adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the IP address of the client
|
||||
* Calculate store-key (prefix + $rawKey).
|
||||
*
|
||||
* @param bool $trust_proxy_headers <p>
|
||||
* Whether or not to trust the
|
||||
* proxy headers HTTP_CLIENT_IP
|
||||
* and HTTP_X_FORWARDED_FOR. ONLY
|
||||
* use if your $_SERVER is behind a
|
||||
* proxy that sets these values
|
||||
* </p>
|
||||
* @param string $rawKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getClientIp(bool $trust_proxy_headers = false): string
|
||||
protected function calculateStoreKey(string $rawKey): string
|
||||
{
|
||||
$remoteAddr = $_SERVER['REMOTE_ADDR'] ?? 'NO_REMOTE_ADDR';
|
||||
$str = $this->getPrefix() . $rawKey;
|
||||
|
||||
if ($trust_proxy_headers) {
|
||||
return $remoteAddr;
|
||||
if ($this->adapter instanceof AdapterFileAbstract) {
|
||||
$str = $this->cleanStoreKey($str);
|
||||
}
|
||||
|
||||
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
} else {
|
||||
$ip = $remoteAddr;
|
||||
}
|
||||
|
||||
return $ip;
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,182 +295,54 @@ class Cache implements iCache
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default-prefix via "SERVER"-var + "SESSION"-language.
|
||||
*/
|
||||
protected function getTheDefaultPrefix(): string
|
||||
{
|
||||
return ($_SERVER['SERVER_NAME'] ?? '') . '_' .
|
||||
($_SERVER['THEME'] ?? '') . '_' .
|
||||
($_SERVER['STAGE'] ?? '') . '_' .
|
||||
($_SESSION['language'] ?? '') . '_' .
|
||||
($_SESSION['language_extra'] ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-connect to the available cache-system on the server.
|
||||
*
|
||||
* @return iAdapter
|
||||
*/
|
||||
protected function autoConnectToAvailableCacheSystem(): iAdapter
|
||||
{
|
||||
static $adapterCache;
|
||||
|
||||
if (\is_object($adapterCache) && $adapterCache instanceof iAdapter) {
|
||||
return $adapterCache;
|
||||
}
|
||||
|
||||
$memcached = null;
|
||||
$isMemcachedAvailable = false;
|
||||
if (\extension_loaded('memcached')) {
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
$memcached = new \Memcached();
|
||||
/** @noinspection PhpUsageOfSilenceOperatorInspection */
|
||||
$isMemcachedAvailable = @$memcached->addServer('127.0.0.1', 11211);
|
||||
}
|
||||
|
||||
if ($isMemcachedAvailable === false) {
|
||||
$memcached = null;
|
||||
}
|
||||
|
||||
$adapterMemcached = new AdapterMemcached($memcached);
|
||||
if ($adapterMemcached->installed() === true) {
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// "Memcached"
|
||||
// -------------------------------------------------------------
|
||||
$adapter = $adapterMemcached;
|
||||
} else {
|
||||
$memcache = null;
|
||||
$isMemcacheAvailable = false;
|
||||
/** @noinspection ClassConstantCanBeUsedInspection */
|
||||
if (\class_exists('\Memcache')) {
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
$memcache = new \Memcache();
|
||||
/** @noinspection PhpUsageOfSilenceOperatorInspection */
|
||||
$isMemcacheAvailable = @$memcache->connect('127.0.0.1', 11211);
|
||||
}
|
||||
|
||||
if ($isMemcacheAvailable === false) {
|
||||
$memcache = null;
|
||||
}
|
||||
|
||||
$adapterMemcache = new AdapterMemcache($memcache);
|
||||
if ($adapterMemcache->installed() === true) {
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// "Memcache"
|
||||
// -------------------------------------------------------------
|
||||
$adapter = $adapterMemcache;
|
||||
} else {
|
||||
$redis = null;
|
||||
$isRedisAvailable = false;
|
||||
if (
|
||||
\extension_loaded('redis')
|
||||
&&
|
||||
\class_exists('\Predis\Client')
|
||||
) {
|
||||
/** @noinspection PhpUndefinedNamespaceInspection */
|
||||
/** @noinspection PhpUndefinedClassInspection */
|
||||
$redis = new \Predis\Client(
|
||||
[
|
||||
'scheme' => 'tcp',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'timeout' => '2.0',
|
||||
]
|
||||
);
|
||||
|
||||
try {
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$redis->connect();
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$isRedisAvailable = $redis->getConnection()->isConnected();
|
||||
} catch (\Exception $e) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
if ($isRedisAvailable === false) {
|
||||
$redis = null;
|
||||
}
|
||||
|
||||
$adapterRedis = new AdapterPredis($redis);
|
||||
if ($adapterRedis->installed() === true) {
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Redis
|
||||
// -------------------------------------------------------------
|
||||
$adapter = $adapterRedis;
|
||||
} else {
|
||||
$adapterXcache = new AdapterXcache();
|
||||
if ($adapterXcache->installed() === true) {
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// "Xcache"
|
||||
// -------------------------------------------------------------
|
||||
$adapter = $adapterXcache;
|
||||
} else {
|
||||
$adapterApcu = new AdapterApcu();
|
||||
if ($adapterApcu->installed() === true) {
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// "APCu"
|
||||
// -------------------------------------------------------------
|
||||
$adapter = $adapterApcu;
|
||||
} else {
|
||||
$adapterApc = new AdapterApc();
|
||||
if ($adapterApc->installed() === true) {
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// "APC"
|
||||
// -------------------------------------------------------------
|
||||
$adapter = $adapterApc;
|
||||
} else {
|
||||
$adapterObCache = new AdapterOpCache();
|
||||
if ($adapterObCache->installed() === true) {
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// OpCache (via PHP-files)
|
||||
// -------------------------------------------------------------
|
||||
$adapter = $adapterObCache;
|
||||
} else {
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Static-PHP-Cache
|
||||
// -------------------------------------------------------------
|
||||
$adapter = new AdapterArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save to static cache
|
||||
$adapterCache = $adapter;
|
||||
|
||||
return $adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set "isReady" state.
|
||||
*
|
||||
* @param bool $isReady
|
||||
*/
|
||||
protected function setCacheIsReady(bool $isReady)
|
||||
{
|
||||
$this->isReady = $isReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the "isReady" state.
|
||||
* @param string $storeKey
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getCacheIsReady(): bool
|
||||
protected function checkForStaticCache(string $storeKey): bool
|
||||
{
|
||||
return $this->isReady;
|
||||
return !empty(self::$STATIC_CACHE)
|
||||
&&
|
||||
\array_key_exists($storeKey, self::$STATIC_CACHE)
|
||||
&&
|
||||
\array_key_exists($storeKey, self::$STATIC_CACHE_EXPIRE)
|
||||
&&
|
||||
\time() <= self::$STATIC_CACHE_EXPIRE[$storeKey];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean store-key (required e.g. for the "File"-Adapter).
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function cleanStoreKey(string $str): string
|
||||
{
|
||||
return \md5($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if cached-item exists.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function existsItem(string $key): bool
|
||||
{
|
||||
if (!$this->adapter instanceof iAdapter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$storeKey = $this->calculateStoreKey($key);
|
||||
|
||||
// check static-cache
|
||||
if ($this->checkForStaticCache($storeKey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->adapter->exists($storeKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -503,21 +373,21 @@ class Cache implements iCache
|
||||
|
||||
// get from static-cache
|
||||
if (
|
||||
$useStaticCache === true
|
||||
$useStaticCache
|
||||
&&
|
||||
$this->checkForStaticCache($storeKey) === true
|
||||
$this->checkForStaticCache($storeKey)
|
||||
) {
|
||||
return self::$STATIC_CACHE[$storeKey];
|
||||
}
|
||||
|
||||
$serialized = $this->adapter->get($storeKey);
|
||||
$value = $serialized ? $this->serializer->unserialize($serialized) : null;
|
||||
$value = $serialized && $this->serializer ? $this->serializer->unserialize($serialized) : null;
|
||||
|
||||
self::$STATIC_CACHE_COUNTER[$storeKey]++;
|
||||
|
||||
// save into static-cache if needed
|
||||
if (
|
||||
$useStaticCache === true
|
||||
$useStaticCache
|
||||
&&
|
||||
(
|
||||
(
|
||||
@ -540,97 +410,55 @@ class Cache implements iCache
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate store-key (prefix + $rawKey).
|
||||
*
|
||||
* @param string $rawKey
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function calculateStoreKey(string $rawKey): string
|
||||
{
|
||||
$str = $this->getPrefix() . $rawKey;
|
||||
|
||||
if ($this->adapter instanceof AdapterFileAbstract) {
|
||||
$str = $this->cleanStoreKey($str);
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean store-key (required e.g. for the "File"-Adapter).
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function cleanStoreKey(string $str): string
|
||||
{
|
||||
return \md5($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the prefix.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPrefix(): string
|
||||
{
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* !!! Set the prefix. !!!
|
||||
*
|
||||
* WARNING: Do not use if you don't know what you do. Because this will overwrite the default prefix.
|
||||
*
|
||||
* @param string $prefix
|
||||
*/
|
||||
public function setPrefix(string $prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current value, when the static cache is used.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStaticCacheHitCounter(): int
|
||||
{
|
||||
return $this->staticCacheHitCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the static-hit-counter: Who often do we hit the cache, before we use static cache?
|
||||
*
|
||||
* @param int $staticCacheHitCounter
|
||||
*/
|
||||
public function setStaticCacheHitCounter(int $staticCacheHitCounter)
|
||||
{
|
||||
$this->staticCacheHitCounter = $staticCacheHitCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cache-item by key => value + date.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param \DateTime $date <p>If the date is in the past, we will remove the existing cache-item.</p>
|
||||
*
|
||||
* @throws InvalidArgumentException <p>If the $date is in the past.</p>
|
||||
* Remove all cached-items.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setItemToDate(string $key, $value, \DateTime $date): bool
|
||||
public function removeAll(): bool
|
||||
{
|
||||
$ttl = $date->getTimestamp() - \time();
|
||||
|
||||
if ($ttl <= 0) {
|
||||
throw new InvalidArgumentException('Date in the past.');
|
||||
if (!$this->adapter instanceof iAdapter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->setItem($key, $value, $ttl);
|
||||
// remove static-cache
|
||||
if (!empty(self::$STATIC_CACHE)) {
|
||||
self::$STATIC_CACHE = [];
|
||||
self::$STATIC_CACHE_COUNTER = [];
|
||||
self::$STATIC_CACHE_EXPIRE = [];
|
||||
}
|
||||
|
||||
return $this->adapter->removeAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached-item.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function removeItem(string $key): bool
|
||||
{
|
||||
if (!$this->adapter instanceof iAdapter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$storeKey = $this->calculateStoreKey($key);
|
||||
|
||||
// remove static-cache
|
||||
if (
|
||||
!empty(self::$STATIC_CACHE)
|
||||
&&
|
||||
\array_key_exists($storeKey, self::$STATIC_CACHE)
|
||||
) {
|
||||
unset(
|
||||
self::$STATIC_CACHE[$storeKey],
|
||||
self::$STATIC_CACHE_COUNTER[$storeKey],
|
||||
self::$STATIC_CACHE_EXPIRE[$storeKey]
|
||||
);
|
||||
}
|
||||
|
||||
return $this->adapter->remove($storeKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -658,15 +486,15 @@ class Cache implements iCache
|
||||
$serialized = $this->serializer->serialize($value);
|
||||
|
||||
// update static-cache, if it's exists
|
||||
if (\array_key_exists($storeKey, self::$STATIC_CACHE) === true) {
|
||||
if (\array_key_exists($storeKey, self::$STATIC_CACHE)) {
|
||||
self::$STATIC_CACHE[$storeKey] = $value;
|
||||
}
|
||||
|
||||
if ($ttl) {
|
||||
if ($ttl instanceof \DateInterval) {
|
||||
// Converting to a TTL in seconds
|
||||
$dateTimeNow = new \DateTime('now');
|
||||
$ttl = $dateTimeNow->add($ttl)->getTimestamp() - \time();
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$ttl = (new \DateTimeImmutable('now'))->add($ttl)->getTimestamp() - \time();
|
||||
}
|
||||
|
||||
// always cache the TTL time, maybe we need this later ...
|
||||
@ -679,91 +507,100 @@ class Cache implements iCache
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached-item.
|
||||
* Set cache-item by key => value + date.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param \DateTimeInterface $date <p>If the date is in the past, we will remove the existing cache-item.</p>
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* <p>If the $date is in the past.</p>
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function removeItem(string $key): bool
|
||||
public function setItemToDate(string $key, $value, \DateTimeInterface $date): bool
|
||||
{
|
||||
if (!$this->adapter instanceof iAdapter) {
|
||||
return false;
|
||||
$ttl = $date->getTimestamp() - \time();
|
||||
|
||||
if ($ttl <= 0) {
|
||||
throw new InvalidArgumentException('Date in the past.');
|
||||
}
|
||||
|
||||
$storeKey = $this->calculateStoreKey($key);
|
||||
|
||||
// remove static-cache
|
||||
if (
|
||||
!empty(self::$STATIC_CACHE)
|
||||
&&
|
||||
\array_key_exists($storeKey, self::$STATIC_CACHE) === true
|
||||
) {
|
||||
unset(self::$STATIC_CACHE[$storeKey], self::$STATIC_CACHE_COUNTER[$storeKey], self::$STATIC_CACHE_EXPIRE[$storeKey]
|
||||
);
|
||||
}
|
||||
|
||||
return $this->adapter->remove($storeKey);
|
||||
return $this->setItem($key, $value, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all cached-items.
|
||||
* Get the "isReady" state.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function removeAll(): bool
|
||||
public function getCacheIsReady(): bool
|
||||
{
|
||||
if (!$this->adapter instanceof iAdapter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove static-cache
|
||||
if (!empty(self::$STATIC_CACHE)) {
|
||||
self::$STATIC_CACHE = [];
|
||||
self::$STATIC_CACHE_COUNTER = [];
|
||||
self::$STATIC_CACHE_EXPIRE = [];
|
||||
}
|
||||
|
||||
return $this->adapter->removeAll();
|
||||
return $this->isReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if cached-item exists.
|
||||
* returns the IP address of the client
|
||||
*
|
||||
* @param string $key
|
||||
* @param bool $trust_proxy_headers <p>
|
||||
* Whether or not to trust the
|
||||
* proxy headers HTTP_CLIENT_IP
|
||||
* and HTTP_X_FORWARDED_FOR. ONLY
|
||||
* use if your $_SERVER is behind a
|
||||
* proxy that sets these values
|
||||
* </p>
|
||||
*
|
||||
* @return bool
|
||||
* @return string
|
||||
*/
|
||||
public function existsItem(string $key): bool
|
||||
protected function getClientIp(bool $trust_proxy_headers = false): string
|
||||
{
|
||||
if (!$this->adapter instanceof iAdapter) {
|
||||
return false;
|
||||
$remoteAddr = $_SERVER['REMOTE_ADDR'] ?? 'NO_REMOTE_ADDR';
|
||||
|
||||
if ($trust_proxy_headers) {
|
||||
return $remoteAddr;
|
||||
}
|
||||
|
||||
$storeKey = $this->calculateStoreKey($key);
|
||||
|
||||
// check static-cache
|
||||
if ($this->checkForStaticCache($storeKey) === true) {
|
||||
return true;
|
||||
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
|
||||
$ip = $_SERVER['HTTP_CLIENT_IP'];
|
||||
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
||||
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
|
||||
} else {
|
||||
$ip = $remoteAddr;
|
||||
}
|
||||
|
||||
return $this->adapter->exists($storeKey);
|
||||
return $ip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $storeKey
|
||||
* Get the prefix.
|
||||
*
|
||||
* @return bool
|
||||
* @return string
|
||||
*/
|
||||
protected function checkForStaticCache(string $storeKey): bool
|
||||
public function getPrefix(): string
|
||||
{
|
||||
return !empty(self::$STATIC_CACHE)
|
||||
&&
|
||||
\array_key_exists($storeKey, self::$STATIC_CACHE) === true
|
||||
&&
|
||||
\array_key_exists($storeKey, self::$STATIC_CACHE_EXPIRE) === true
|
||||
&&
|
||||
\time() <= self::$STATIC_CACHE_EXPIRE[$storeKey];
|
||||
return $this->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current value, when the static cache is used.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getStaticCacheHitCounter(): int
|
||||
{
|
||||
return $this->staticCacheHitCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default-prefix via "SERVER"-var + "SESSION"-language.
|
||||
*/
|
||||
protected function getTheDefaultPrefix(): string
|
||||
{
|
||||
return ($_SERVER['SERVER_NAME'] ?? '') . '_' .
|
||||
($_SERVER['THEME'] ?? '') . '_' .
|
||||
($_SERVER['STAGE'] ?? '') . '_' .
|
||||
($_SESSION['language'] ?? '') . '_' .
|
||||
($_SESSION['language_extra'] ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -795,4 +632,94 @@ class Cache implements iCache
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the current use is a admin || dev || server == client
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isCacheActiveForTheCurrentUser(): bool
|
||||
{
|
||||
$active = true;
|
||||
|
||||
// test the cache, with this GET-parameter
|
||||
if ($this->disableCacheGetParameter) {
|
||||
$testCache = isset($_GET[$this->disableCacheGetParameter]) ? (int) $_GET[$this->disableCacheGetParameter] : 0;
|
||||
} else {
|
||||
$testCache = 0;
|
||||
}
|
||||
|
||||
if ($testCache !== 1) {
|
||||
if (
|
||||
// admin session is active
|
||||
(
|
||||
$this->useCheckForAdminSession
|
||||
&&
|
||||
$this->isAdminSession
|
||||
)
|
||||
||
|
||||
// server == client
|
||||
(
|
||||
$this->useCheckForServerIpIsClientIp
|
||||
&&
|
||||
isset($_SERVER['SERVER_ADDR'])
|
||||
&&
|
||||
$_SERVER['SERVER_ADDR'] === $this->getClientIp()
|
||||
)
|
||||
||
|
||||
// user is a dev
|
||||
(
|
||||
$this->useCheckForDev
|
||||
&&
|
||||
$this->checkForDev()
|
||||
)
|
||||
) {
|
||||
$active = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $active;
|
||||
}
|
||||
|
||||
/**
|
||||
* enable / disable the cache
|
||||
*
|
||||
* @param bool $isActive
|
||||
*/
|
||||
public function setActive(bool $isActive)
|
||||
{
|
||||
$this->isActive = $isActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set "isReady" state.
|
||||
*
|
||||
* @param bool $isReady
|
||||
*/
|
||||
protected function setCacheIsReady(bool $isReady)
|
||||
{
|
||||
$this->isReady = $isReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* !!! Set the prefix. !!!
|
||||
*
|
||||
* WARNING: Do not use if you don't know what you do. Because this will overwrite the default prefix.
|
||||
*
|
||||
* @param string $prefix
|
||||
*/
|
||||
public function setPrefix(string $prefix)
|
||||
{
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the static-hit-counter: Who often do we hit the cache, before we use static cache?
|
||||
*
|
||||
* @param int $staticCacheHitCounter
|
||||
*/
|
||||
public function setStaticCacheHitCounter(int $staticCacheHitCounter)
|
||||
{
|
||||
$this->staticCacheHitCounter = $staticCacheHitCounter;
|
||||
}
|
||||
}
|
||||
|
230
bundled-libs/voku/simple-cache/src/voku/cache/CacheAdapterAutoManager.php
vendored
Normal file
230
bundled-libs/voku/simple-cache/src/voku/cache/CacheAdapterAutoManager.php
vendored
Normal file
@ -0,0 +1,230 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace voku\cache;
|
||||
|
||||
use voku\cache\Exception\InvalidArgumentException;
|
||||
|
||||
class CacheAdapterAutoManager
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $adapter = [];
|
||||
|
||||
/**
|
||||
* @var callable[]|null[]
|
||||
*/
|
||||
private $callableFunctions = [];
|
||||
|
||||
/**
|
||||
* @param string $adapter
|
||||
* @param callable|null $callableFunction
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addAdapter(
|
||||
string $adapter,
|
||||
callable $callableFunction = null
|
||||
): self
|
||||
{
|
||||
$this->validateAdapter($adapter);
|
||||
$this->validateCallable($callableFunction);
|
||||
|
||||
$this->adapter[] = $adapter;
|
||||
$this->callableFunctions[] = $callableFunction;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Generator|\Generator<string, callable>
|
||||
*/
|
||||
public function getAdapters(): \Generator
|
||||
{
|
||||
foreach ($this->adapter as $key => $value) {
|
||||
yield $this->adapter[$key] => $this->callableFunctions[$key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param self $adapterManager
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return CacheAdapterAutoManager
|
||||
*/
|
||||
public function merge(self $adapterManager): self
|
||||
{
|
||||
foreach ($adapterManager->getAdapters() as $adapterTmp => $callableFunctionTmp) {
|
||||
$this->validateAdapter($adapterTmp);
|
||||
$this->validateCallable($callableFunctionTmp);
|
||||
|
||||
$key = \array_search($adapterTmp, $this->adapter, true);
|
||||
|
||||
if ($key) {
|
||||
$this->adapter[$key] = $adapterTmp;
|
||||
$this->callableFunctions[$key] = $callableFunctionTmp;
|
||||
} else {
|
||||
$this->adapter[] = $adapterTmp;
|
||||
$this->callableFunctions[] = $callableFunctionTmp;
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $replaceAdapter
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function validateAdapter(string $replaceAdapter)
|
||||
{
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$interfaces = (new \ReflectionClass($replaceAdapter))->getInterfaces();
|
||||
if (!\array_key_exists(iAdapter::class, $interfaces)) {
|
||||
throw new InvalidArgumentException('"' . $replaceAdapter . '" did not implement the "iAdapter"-interface [' . \print_r($interfaces, true) . ']');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable $callableFunction
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function validateCallable(callable $callableFunction = null)
|
||||
{
|
||||
if (
|
||||
$callableFunction !== null
|
||||
&&
|
||||
!\is_callable($callableFunction)
|
||||
) {
|
||||
throw new InvalidArgumentException('$callableFunction is not callable');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CacheAdapterAutoManager
|
||||
*/
|
||||
public static function getDefaultsForAutoInit(): self
|
||||
{
|
||||
$cacheAdapterManager = new self();
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$cacheAdapterManager->addAdapter(
|
||||
AdapterMemcached::class,
|
||||
static function () {
|
||||
$memcached = null;
|
||||
$isMemcachedAvailable = false;
|
||||
if (\extension_loaded('memcached')) {
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
$memcached = new \Memcached();
|
||||
/** @noinspection PhpUsageOfSilenceOperatorInspection */
|
||||
$isMemcachedAvailable = @$memcached->addServer('127.0.0.1', 11211);
|
||||
}
|
||||
|
||||
if (!$isMemcachedAvailable) {
|
||||
$memcached = null;
|
||||
}
|
||||
|
||||
return $memcached;
|
||||
}
|
||||
);
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$cacheAdapterManager->addAdapter(
|
||||
AdapterMemcache::class,
|
||||
static function () {
|
||||
$memcache = null;
|
||||
$isMemcacheAvailable = false;
|
||||
/** @noinspection ClassConstantCanBeUsedInspection */
|
||||
if (\class_exists('\Memcache')) {
|
||||
/** @noinspection PhpComposerExtensionStubsInspection */
|
||||
$memcache = new \Memcache();
|
||||
/** @noinspection PhpUsageOfSilenceOperatorInspection */
|
||||
$isMemcacheAvailable = @$memcache->connect('127.0.0.1', 11211);
|
||||
}
|
||||
|
||||
if (!$isMemcacheAvailable) {
|
||||
$memcache = null;
|
||||
}
|
||||
|
||||
return $memcache;
|
||||
}
|
||||
);
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$cacheAdapterManager->addAdapter(
|
||||
AdapterPredis::class,
|
||||
static function () {
|
||||
$redis = null;
|
||||
$isRedisAvailable = false;
|
||||
if (
|
||||
\extension_loaded('redis')
|
||||
&&
|
||||
\class_exists('\Predis\Client')
|
||||
) {
|
||||
/** @noinspection PhpUndefinedNamespaceInspection */
|
||||
/** @noinspection PhpUndefinedClassInspection */
|
||||
$redis = new \Predis\Client(
|
||||
[
|
||||
'scheme' => 'tcp',
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
'timeout' => '2.0',
|
||||
]
|
||||
);
|
||||
|
||||
try {
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$redis->connect();
|
||||
/** @noinspection PhpUndefinedMethodInspection */
|
||||
$isRedisAvailable = $redis->getConnection()->isConnected();
|
||||
} catch (\Exception $e) {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
if ($isRedisAvailable === false) {
|
||||
$redis = null;
|
||||
}
|
||||
|
||||
return $redis;
|
||||
}
|
||||
);
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$cacheAdapterManager->addAdapter(
|
||||
AdapterXcache::class
|
||||
);
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$cacheAdapterManager->addAdapter(
|
||||
AdapterApcu::class
|
||||
);
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$cacheAdapterManager->addAdapter(
|
||||
AdapterApc::class
|
||||
);
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$cacheAdapterManager->addAdapter(
|
||||
AdapterOpCache::class,
|
||||
static function () {
|
||||
return \realpath(\sys_get_temp_dir()) . '/simple_php_cache';
|
||||
}
|
||||
);
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$cacheAdapterManager->addAdapter(
|
||||
AdapterArray::class
|
||||
);
|
||||
|
||||
return $cacheAdapterManager;
|
||||
}
|
||||
}
|
@ -4,9 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace voku\cache;
|
||||
|
||||
/**
|
||||
* CacheChain: global-cache-chain class
|
||||
*/
|
||||
class CacheChain implements iCache
|
||||
{
|
||||
/**
|
||||
@ -87,13 +84,13 @@ class CacheChain implements iCache
|
||||
$results[] = $cache->setItem($key, $value, $ttl);
|
||||
}
|
||||
|
||||
return \in_array(false, $results, true) === false;
|
||||
return !\in_array(false, $results, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setItemToDate(string $key, $value, \DateTime $date): bool
|
||||
public function setItemToDate(string $key, $value, \DateTimeInterface $date): bool
|
||||
{
|
||||
// init
|
||||
$results = [];
|
||||
@ -103,7 +100,7 @@ class CacheChain implements iCache
|
||||
$results[] = $cache->setItemToDate($key, $value, $date);
|
||||
}
|
||||
|
||||
return \in_array(false, $results, true) === false;
|
||||
return !\in_array(false, $results, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -118,7 +115,7 @@ class CacheChain implements iCache
|
||||
$results[] = $cache->removeItem($key);
|
||||
}
|
||||
|
||||
return \in_array(false, $results, true) === false;
|
||||
return !\in_array(false, $results, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,6 +144,6 @@ class CacheChain implements iCache
|
||||
$results[] = $cache->removeAll();
|
||||
}
|
||||
|
||||
return \in_array(false, $results, true) === false;
|
||||
return !\in_array(false, $results, true);
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ class CachePsr16 extends Cache implements CacheInterface
|
||||
/**
|
||||
* Deletes multiple cache items in a single operation.
|
||||
*
|
||||
* @param \iterable $keys a list of string-based keys to be deleted
|
||||
* @param iterable $keys a list of string-based keys to be deleted
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
@ -48,16 +48,20 @@ class CachePsr16 extends Cache implements CacheInterface
|
||||
*/
|
||||
public function deleteMultiple($keys): bool
|
||||
{
|
||||
if (!\is_array($keys) && !($keys instanceof \Traversable)) {
|
||||
if (
|
||||
!\is_array($keys)
|
||||
&&
|
||||
!($keys instanceof \Traversable)
|
||||
) {
|
||||
throw new InvalidArgumentException('$keys is not iterable:' . \print_r($keys, true));
|
||||
}
|
||||
|
||||
$results = [];
|
||||
foreach ((array) $keys as $key) {
|
||||
$results = $this->delete($key);
|
||||
$results[] = $this->delete($key);
|
||||
}
|
||||
|
||||
return \in_array(false, $results, true) === false;
|
||||
return !\in_array(false, $results, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,7 +76,7 @@ class CachePsr16 extends Cache implements CacheInterface
|
||||
*/
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
if ($this->has($key) === true) {
|
||||
if ($this->has($key)) {
|
||||
return $this->getItem($key);
|
||||
}
|
||||
|
||||
@ -82,17 +86,21 @@ class CachePsr16 extends Cache implements CacheInterface
|
||||
/**
|
||||
* Obtains multiple cache items by their unique keys.
|
||||
*
|
||||
* @param \iterable $keys a list of keys that can obtained in a single operation
|
||||
* @param mixed $default default value to return for keys that do not exist
|
||||
* @param iterable $keys a list of keys that can obtained in a single operation
|
||||
* @param mixed $default default value to return for keys that do not exist
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
* @return \iterable A list of key => value pairs. Cache keys that do not exist or are stale will have $default as
|
||||
* value.
|
||||
* @return iterable A list of key => value pairs. Cache keys that do not exist or are stale will have $default as
|
||||
* value.
|
||||
*/
|
||||
public function getMultiple($keys, $default = null)
|
||||
{
|
||||
if (!\is_array($keys) && !($keys instanceof \Traversable)) {
|
||||
if (
|
||||
!\is_array($keys)
|
||||
&&
|
||||
!($keys instanceof \Traversable)
|
||||
) {
|
||||
throw new InvalidArgumentException('$keys is not iterable:' . \print_r($keys, true));
|
||||
}
|
||||
|
||||
@ -152,7 +160,7 @@ class CachePsr16 extends Cache implements CacheInterface
|
||||
/**
|
||||
* Persists a set of key => value pairs in the cache, with an optional TTL.
|
||||
*
|
||||
* @param \iterable $values a list of key => value pairs for a multiple-set operation
|
||||
* @param iterable $values a list of key => value pairs for a multiple-set operation
|
||||
* @param \DateInterval|int|null $ttl Optional. The TTL value of this item. If no value is sent and
|
||||
* the driver supports TTL then the library may set a default value
|
||||
* for it or let the driver take care of that.
|
||||
@ -163,15 +171,19 @@ class CachePsr16 extends Cache implements CacheInterface
|
||||
*/
|
||||
public function setMultiple($values, $ttl = null): bool
|
||||
{
|
||||
if (!\is_array($values) && !($values instanceof \Traversable)) {
|
||||
if (
|
||||
!\is_array($values)
|
||||
&&
|
||||
!($values instanceof \Traversable)
|
||||
) {
|
||||
throw new InvalidArgumentException('$values is not iterable:' . \print_r($values, true));
|
||||
}
|
||||
|
||||
$results = [];
|
||||
foreach ((array) $values as $key => $value) {
|
||||
$results = $this->set($key, $value, $ttl);
|
||||
$results[] = $this->set($key, $value, $ttl);
|
||||
}
|
||||
|
||||
return \in_array(false, $results, true) === false;
|
||||
return !\in_array(false, $results, true);
|
||||
}
|
||||
}
|
||||
|
@ -32,13 +32,13 @@ interface iCache
|
||||
/**
|
||||
* set item a special expire-date
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param \DateTime $date
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param \DateTimeInterface $date
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setItemToDate(string $key, $value, \DateTime $date): bool;
|
||||
public function setItemToDate(string $key, $value, \DateTimeInterface $date): bool;
|
||||
|
||||
/**
|
||||
* remove item
|
||||
|
@ -12,18 +12,14 @@ interface iSerializer
|
||||
/**
|
||||
* serialize
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return mixed
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function serialize($value);
|
||||
|
||||
/**
|
||||
* unserialize
|
||||
*
|
||||
* @param $value
|
||||
*
|
||||
* @return mixed
|
||||
* @param string $value
|
||||
*/
|
||||
public function unserialize($value);
|
||||
}
|
||||
|
Reference in New Issue
Block a user