+ Support Apcu and Yac cache driver.
This commit is contained in:
Vendored
+53
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* The cache library of zentaopms.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
|
||||
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Lu Fei <lufei@easycorp.ltd>
|
||||
* @package cache
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
|
||||
helper::import(dirname(__FILE__) . DS . 'simple-cache' . DS . 'CacheInterface.php');
|
||||
helper::import(dirname(__FILE__) . DS . 'simple-cache' . DS . 'CacheException.php');
|
||||
helper::import(dirname(__FILE__) . DS . 'simple-cache' . DS . 'InvalidArgumentException.php');
|
||||
helper::import(dirname(__FILE__) . DS . 'driver' . DS . 'ApcuDriver.php');
|
||||
helper::import(dirname(__FILE__) . DS . 'driver' . DS . 'YacDriver.php');
|
||||
|
||||
use ZenTao\Cache\SimpleCache\InvalidArgumentException;
|
||||
|
||||
class cache
|
||||
{
|
||||
/**
|
||||
* @var ZenTao\Cache\SimpleCache\CacheInterface
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
public function __construct($driver = 'Apcu', $namespace = '', $defaultLifetime = 0)
|
||||
{
|
||||
$driver = ucfirst(strtolower($driver));
|
||||
switch($driver)
|
||||
{
|
||||
case 'Apcu':
|
||||
$className = 'ZenTao\Cache\Driver\ApcuDriver';
|
||||
break;
|
||||
case 'Yac':
|
||||
$className = 'ZenTao\Cache\Driver\YacDriver';
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException("Driver {$driver} is not supported.");
|
||||
}
|
||||
|
||||
if(!extension_loaded($driver)) throw new InvalidArgumentException("Driver ext-{$driver} is not loaded.");
|
||||
|
||||
$this->client = new $className($namespace, $defaultLifetime);
|
||||
}
|
||||
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
if(!method_exists($this->client, $name)) throw new InvalidArgumentException("Method {$name} does not exist.");
|
||||
|
||||
return call_user_func_array(array($this->client, $name), $arguments);
|
||||
}
|
||||
}
|
||||
Vendored
+173
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
/**
|
||||
* The cache library of zentaopms.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
|
||||
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Lu Fei <lufei@easycorp.ltd>
|
||||
* @package cache
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace ZenTao\Cache\Driver;
|
||||
|
||||
use ZenTao\Cache\SimpleCache\CacheInterface;
|
||||
use ZenTao\Cache\SimpleCache\InvalidArgumentException;
|
||||
|
||||
class ApcuDriver implements CacheInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $namespace;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $defaultLifetime;
|
||||
|
||||
public function __construct($namespace = '', $defaultLifetime = 0)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
$this->defaultLifetime = $defaultLifetime;
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
$this->assertKeyName($key);
|
||||
$key = $this->buildKeyName($key);
|
||||
|
||||
$value = apcu_fetch($key, $success);
|
||||
|
||||
return $success === false ? $default : $value;
|
||||
}
|
||||
|
||||
public function set($key, $value, $ttl = null)
|
||||
{
|
||||
$this->assertKeyName($key);
|
||||
$key = $this->buildKeyName($key);
|
||||
|
||||
$ttl = is_null($ttl) ? $this->defaultLifetime : $ttl;
|
||||
|
||||
return apcu_store($key, $value, (int) $ttl);
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
$this->assertKeyName($key);
|
||||
$key = $this->buildKeyName($key);
|
||||
|
||||
return apcu_delete($key);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
return apcu_clear_cache();
|
||||
}
|
||||
|
||||
public function getMultiple($keys, $default = null)
|
||||
{
|
||||
$this->assertKeyNames($keys);
|
||||
$keys = $this->buildKeyNames($keys);
|
||||
|
||||
$result = apcu_fetch($keys);
|
||||
|
||||
if(!is_null($default) && is_array($result) && count($keys) > count($result))
|
||||
{
|
||||
$notFoundKeys = array_diff($keys, array_keys($result));
|
||||
$result = array_merge($result, array_fill_keys($notFoundKeys, $default));
|
||||
}
|
||||
|
||||
$mappedResult = array();
|
||||
|
||||
foreach($result as $key => $value)
|
||||
{
|
||||
$key = preg_replace("/^$this->namespace/", '', $key);
|
||||
|
||||
$mappedResult[$key] = $value;
|
||||
}
|
||||
|
||||
return $mappedResult;
|
||||
}
|
||||
|
||||
public function setMultiple($values, $ttl = null)
|
||||
{
|
||||
$this->assertKeyNames(array_keys($values));
|
||||
|
||||
$mappedByNamespaceValues = array();
|
||||
|
||||
foreach($values as $key => $value)
|
||||
{
|
||||
$mappedByNamespaceValues[$this->buildKeyName($key)] = $value;
|
||||
}
|
||||
|
||||
$ttl = is_null($ttl) ? $this->defaultLifetime : $ttl;
|
||||
|
||||
$result = apcu_store($mappedByNamespaceValues, (int) $ttl);
|
||||
|
||||
return $result === true ? true : (is_array($result) && count($result) == 0 ? true : false);
|
||||
}
|
||||
|
||||
public function deleteMultiple($keys)
|
||||
{
|
||||
$this->assertKeyNames($keys);
|
||||
$keys = $this->buildKeyNames($keys);
|
||||
|
||||
$result = apcu_delete($keys);
|
||||
|
||||
return count($result) === count($keys) ? false : true;
|
||||
}
|
||||
|
||||
public function has($key)
|
||||
{
|
||||
$this->assertKeyName($key);
|
||||
$key = $this->buildKeyName($key);
|
||||
|
||||
return (bool) apcu_exists($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function buildKeyName($key)
|
||||
{
|
||||
return $this->namespace . $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $keys
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function buildKeyNames(array $keys)
|
||||
{
|
||||
return array_map(function($key) {
|
||||
return $this->buildKeyName($key);
|
||||
}, $keys);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $key
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function assertKeyName($key)
|
||||
{
|
||||
if(!is_scalar($key) || is_bool($key)) throw new InvalidArgumentException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $keys
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function assertKeyNames(array $keys)
|
||||
{
|
||||
array_map(function ($value) {
|
||||
$this->assertKeyName($value);
|
||||
}, $keys);
|
||||
}
|
||||
}
|
||||
Vendored
+197
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
/**
|
||||
* The cache library of zentaopms.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
|
||||
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
|
||||
* @author Lu Fei <lufei@easycorp.ltd>
|
||||
* @package cache
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
|
||||
namespace ZenTao\Cache\Driver;
|
||||
|
||||
use ZenTao\Cache\SimpleCache\CacheInterface;
|
||||
use ZenTao\Cache\SimpleCache\InvalidArgumentException;
|
||||
|
||||
class YacDriver implements CacheInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $namespace;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $defaultLifetime;
|
||||
|
||||
/**
|
||||
* yac client
|
||||
*
|
||||
* @var \Yac
|
||||
*/
|
||||
protected $yac;
|
||||
|
||||
/**
|
||||
* if your key is longer than this, maybe you can use md5 result as the key
|
||||
*/
|
||||
const KEY_MAX_LEN = 48;
|
||||
|
||||
public function __construct($namespace = '', $defaultLifetime = 0)
|
||||
{
|
||||
$this->namespace = $namespace;
|
||||
$this->defaultLifetime = $defaultLifetime;
|
||||
$this->yac = new \Yac($namespace);
|
||||
}
|
||||
|
||||
public function get($key, $default = null)
|
||||
{
|
||||
$this->assertKeyName($key);
|
||||
$key = $this->buildKeyName($key);
|
||||
|
||||
return $this->yac->get($key) ?: $default;
|
||||
}
|
||||
|
||||
public function set($key, $value, $ttl = null)
|
||||
{
|
||||
$this->assertKeyName($key);
|
||||
$key = $this->buildKeyName($key);
|
||||
|
||||
$ttl = is_null($ttl) ? $this->defaultLifetime : $ttl;
|
||||
|
||||
return $this->yac->set($key, $value, (int)$ttl);
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
$this->assertKeyName($key);
|
||||
$key = $this->buildKeyName($key);
|
||||
|
||||
return $this->yac->delete($key);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
return $this->yac->flush();
|
||||
}
|
||||
|
||||
public function getMultiple($keys, $default = null)
|
||||
{
|
||||
if(!is_array($keys)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$hashKeyMap = array();
|
||||
foreach($keys as $index => $key)
|
||||
{
|
||||
$this->assertKeyName($key);
|
||||
if(strlen($key) > self::KEY_MAX_LEN)
|
||||
{
|
||||
$keys[$index] = $this->buildKeyName($key);
|
||||
$hashKeyMap[$keys[$index]] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
$results = $this->yac->get($keys);
|
||||
if($results !== false)
|
||||
{
|
||||
foreach($results as $key => $value)
|
||||
{
|
||||
if(isset($hashKeyMap[$key]))
|
||||
{
|
||||
$results[$hashKeyMap[$key]] = $value;
|
||||
unset($results[$key]);
|
||||
}
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
$results = array();
|
||||
foreach($keys as $key)
|
||||
{
|
||||
$results[$key] = $default;
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function setMultiple($values, $ttl = null)
|
||||
{
|
||||
if(!is_array($values)) return false;
|
||||
|
||||
foreach($values as $key => $value)
|
||||
{
|
||||
if(strlen($key) > self::KEY_MAX_LEN)
|
||||
{
|
||||
$values[$this->buildKeyName($key)] = $value;
|
||||
unset($values[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$ttl = is_null($ttl) ? $this->defaultLifetime : $ttl;
|
||||
|
||||
return $this->yac->set($values, $ttl);
|
||||
}
|
||||
|
||||
public function deleteMultiple($keys)
|
||||
{
|
||||
foreach($keys as $index => $key)
|
||||
{
|
||||
$keys[$index] = $this->buildKeyName($key);
|
||||
}
|
||||
return $this->yac->delete($keys);
|
||||
}
|
||||
|
||||
public function has($key)
|
||||
{
|
||||
return $this->get($key) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function buildKeyName($key)
|
||||
{
|
||||
if(strlen($key) > self::KEY_MAX_LEN)
|
||||
{
|
||||
$key = md5($key);
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $keys
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function buildKeyNames(array $keys)
|
||||
{
|
||||
return array_map(function ($key) {
|
||||
return $this->buildKeyName($key);
|
||||
}, $keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $key
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function assertKeyName($key)
|
||||
{
|
||||
if(!is_scalar($key) || is_bool($key)) throw new InvalidArgumentException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $keys
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function assertKeyNames(array $keys)
|
||||
{
|
||||
array_map(function ($value) {
|
||||
$this->assertKeyName($value);
|
||||
}, $keys);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace ZenTao\Cache\SimpleCache;
|
||||
|
||||
class CacheException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
namespace ZenTao\Cache\SimpleCache;
|
||||
|
||||
interface CacheInterface
|
||||
{
|
||||
/**
|
||||
* Fetches a value from the cache.
|
||||
*
|
||||
* @param string $key The unique key of this item in the cache.
|
||||
* @param mixed $default Default value to return if the key does not exist.
|
||||
*
|
||||
* @return mixed The value of the item from the cache, or $default in case of cache miss.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* MUST be thrown if the $key string is not a legal value.
|
||||
*/
|
||||
public function get($key, $default = null);
|
||||
|
||||
/**
|
||||
* Persists data in the cache, uniquely referenced by a key with an optional expiration TTL time.
|
||||
*
|
||||
* @param string $key The key of the item to store.
|
||||
* @param mixed $value The value of the item to store, must be serializable.
|
||||
* @param null|int|\DateInterval $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.
|
||||
*
|
||||
* @return bool True on success and false on failure.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* MUST be thrown if the $key string is not a legal value.
|
||||
*/
|
||||
public function set($key, $value, $ttl = null);
|
||||
|
||||
/**
|
||||
* Delete an item from the cache by its unique key.
|
||||
*
|
||||
* @param string $key The unique cache key of the item to delete.
|
||||
*
|
||||
* @return bool True if the item was successfully removed. False if there was an error.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* MUST be thrown if the $key string is not a legal value.
|
||||
*/
|
||||
public function delete($key);
|
||||
|
||||
/**
|
||||
* Wipes clean the entire cache's keys.
|
||||
*
|
||||
* @return bool True on success and false on failure.
|
||||
*/
|
||||
public function clear();
|
||||
|
||||
/**
|
||||
* Obtains multiple cache items by their unique keys.
|
||||
*
|
||||
* @param iterable<string> $keys A list of keys that can be obtained in a single operation.
|
||||
* @param mixed $default Default value to return for keys that do not exist.
|
||||
*
|
||||
* @return iterable<string, mixed> A list of key => value pairs. Cache keys that do not exist or are stale will have $default as value.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* MUST be thrown if $keys is neither an array nor a Traversable,
|
||||
* or if any of the $keys are not a legal value.
|
||||
*/
|
||||
public function getMultiple($keys, $default = null);
|
||||
|
||||
/**
|
||||
* 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 null|int|\DateInterval $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.
|
||||
*
|
||||
* @return bool True on success and false on failure.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* MUST be thrown if $values is neither an array nor a Traversable,
|
||||
* or if any of the $values are not a legal value.
|
||||
*/
|
||||
public function setMultiple($values, $ttl = null);
|
||||
|
||||
/**
|
||||
* Deletes multiple cache items in a single operation.
|
||||
*
|
||||
* @param iterable<string> $keys A list of string-based keys to be deleted.
|
||||
*
|
||||
* @return bool True if the items were successfully removed. False if there was an error.
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* MUST be thrown if $keys is neither an array nor a Traversable,
|
||||
* or if any of the $keys are not a legal value.
|
||||
*/
|
||||
public function deleteMultiple($keys);
|
||||
|
||||
/**
|
||||
* Determines whether an item is present in the cache.
|
||||
*
|
||||
* NOTE: It is recommended that has() is only to be used for cache warming type purposes
|
||||
* and not to be used within your live applications operations for get/set, as this method
|
||||
* is subject to a race condition where your has() will return true and immediately after,
|
||||
* another script can remove it making the state of your app out of date.
|
||||
*
|
||||
* @param string $key The cache item key.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* MUST be thrown if the $key string is not a legal value.
|
||||
*/
|
||||
public function has($key);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace ZenTao\Cache\SimpleCache;
|
||||
|
||||
class InvalidArgumentException extends CacheException
|
||||
{
|
||||
}
|
||||
Reference in New Issue
Block a user