Upgrade CakePHP from 2.2.5 to 2.9.5

This commit is contained in:
Brm Ko 2017-02-26 15:29:44 +01:00
parent 5a580df460
commit 235a541597
793 changed files with 60746 additions and 23753 deletions

View file

@ -1,16 +1,17 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.Cache
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
App::uses('Inflector', 'Utility');
@ -19,22 +20,22 @@ App::uses('CacheEngine', 'Cache');
/**
* Cache provides a consistent interface to Caching in your application. It allows you
* to use several different Cache engines, without coupling your application to a specific
* implementation. It also allows you to change out cache storage or configuration without effecting
* implementation. It also allows you to change out cache storage or configuration without effecting
* the rest of your application.
*
* You can configure Cache engines in your application's `bootstrap.php` file. A sample configuration would
* You can configure Cache engines in your application's `bootstrap.php` file. A sample configuration would
* be
*
* {{{
* ```
* Cache::config('shared', array(
* 'engine' => 'Apc',
* 'prefix' => 'my_app_'
* ));
* }}}
* ```
*
* This would configure an APC cache engine to the 'shared' alias. You could then read and write
* to that cache alias by using it for the `$config` parameter in the various Cache methods. In
* general all Cache operations are supported by all cache engines. However, Cache::increment() and
* This would configure an APC cache engine to the 'shared' alias. You could then read and write
* to that cache alias by using it for the `$config` parameter in the various Cache methods. In
* general all Cache operations are supported by all cache engines. However, Cache::increment() and
* Cache::decrement() are not supported by File caching.
*
* @package Cake.Cache
@ -50,6 +51,13 @@ class Cache {
*/
protected static $_config = array();
/**
* Group to Config mapping
*
* @var array
*/
protected static $_groups = array();
/**
* Whether to reset the settings with the next call to Cache::set();
*
@ -65,7 +73,7 @@ class Cache {
protected static $_engines = array();
/**
* Set the cache configuration to use. config() can
* Set the cache configuration to use. config() can
* both create new configurations, return the settings for already configured
* configurations.
*
@ -95,21 +103,21 @@ class Cache {
* handy for deleting a complete group from cache.
* - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace
* with either another cache config or another application.
* - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable
* - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable
* cache::gc from ever being called automatically.
* - `servers' Used by memcache. Give the address of the memcached servers to use.
* - `compress` Used by memcache. Enables memcache's compressed format.
* - `serialize` Used by FileCache. Should cache objects be serialized first.
* - `path` Used by FileCache. Path to where cachefiles should be saved.
* - `lock` Used by FileCache. Should files be locked before writing to them?
* - `user` Used by Xcache. Username for XCache
* - `password` Used by Xcache. Password for XCache
* - `compress` Used by memcache. Enables memcache's compressed format.
* - `serialize` Used by FileCache. Should cache objects be serialized first.
* - `path` Used by FileCache. Path to where cachefiles should be saved.
* - `lock` Used by FileCache. Should files be locked before writing to them?
* - `user` Used by Xcache. Username for XCache
* - `password` Used by Xcache/Redis. Password for XCache/Redis
*
* @see app/Config/core.php for configuration settings
* @param string $name Name of the configuration
* @param array $settings Optional associative array of settings passed to the engine
* @return array(engine, settings) on success, false on failure
* @return array array(engine, settings) on success, false on failure
* @throws CacheException
* @see app/Config/core.php for configuration settings
*/
public static function config($name = null, $settings = array()) {
if (is_array($name)) {
@ -117,25 +125,33 @@ class Cache {
}
$current = array();
if (isset(self::$_config[$name])) {
$current = self::$_config[$name];
if (isset(static::$_config[$name])) {
$current = static::$_config[$name];
}
if (!empty($settings)) {
self::$_config[$name] = array_merge($current, $settings);
static::$_config[$name] = $settings + $current;
}
if (empty(self::$_config[$name]['engine'])) {
if (empty(static::$_config[$name]['engine'])) {
return false;
}
$engine = self::$_config[$name]['engine'];
if (!empty(static::$_config[$name]['groups'])) {
foreach (static::$_config[$name]['groups'] as $group) {
static::$_groups[$group][] = $name;
sort(static::$_groups[$group]);
static::$_groups[$group] = array_unique(static::$_groups[$group]);
}
}
if (!isset(self::$_engines[$name])) {
self::_buildEngine($name);
$settings = self::$_config[$name] = self::settings($name);
} elseif ($settings = self::set(self::$_config[$name], null, $name)) {
self::$_config[$name] = $settings;
$engine = static::$_config[$name]['engine'];
if (!isset(static::$_engines[$name])) {
static::_buildEngine($name);
$settings = static::$_config[$name] = static::settings($name);
} elseif ($settings = static::set(static::$_config[$name], null, $name)) {
static::$_config[$name] = $settings;
}
return compact('engine', 'settings');
}
@ -144,30 +160,35 @@ class Cache {
* Finds and builds the instance of the required engine class.
*
* @param string $name Name of the config array that needs an engine instance built
* @return boolean
* @return bool
* @throws CacheException
*/
protected static function _buildEngine($name) {
$config = self::$_config[$name];
$config = static::$_config[$name];
list($plugin, $class) = pluginSplit($config['engine'], true);
$cacheClass = $class . 'Engine';
App::uses($cacheClass, $plugin . 'Cache/Engine');
if (!class_exists($cacheClass)) {
return false;
throw new CacheException(__d('cake_dev', 'Cache engine %s is not available.', $name));
}
$cacheClass = $class . 'Engine';
if (!is_subclass_of($cacheClass, 'CacheEngine')) {
throw new CacheException(__d('cake_dev', 'Cache engines must use CacheEngine as a base class.'));
throw new CacheException(__d('cake_dev', 'Cache engines must use %s as a base class.', 'CacheEngine'));
}
self::$_engines[$name] = new $cacheClass();
if (self::$_engines[$name]->init($config)) {
if (self::$_engines[$name]->settings['probability'] && time() % self::$_engines[$name]->settings['probability'] === 0) {
self::$_engines[$name]->gc();
}
return true;
static::$_engines[$name] = new $cacheClass();
if (!static::$_engines[$name]->init($config)) {
$msg = __d(
'cake_dev',
'Cache engine "%s" is not properly configured. Ensure required extensions are installed, and credentials/permissions are correct',
$name
);
throw new CacheException($msg);
}
return false;
if (static::$_engines[$name]->settings['probability'] && time() % static::$_engines[$name]->settings['probability'] === 0) {
static::$_engines[$name]->gc();
}
return true;
}
/**
@ -176,27 +197,27 @@ class Cache {
* @return array Array of configured Cache config names.
*/
public static function configured() {
return array_keys(self::$_config);
return array_keys(static::$_config);
}
/**
* Drops a cache engine. Deletes the cache configuration information
* If the deleted configuration is the last configuration using an certain engine,
* Drops a cache engine. Deletes the cache configuration information
* If the deleted configuration is the last configuration using a certain engine,
* the Engine instance is also unset.
*
* @param string $name A currently configured cache config you wish to remove.
* @return boolean success of the removal, returns false when the config does not exist.
* @return bool success of the removal, returns false when the config does not exist.
*/
public static function drop($name) {
if (!isset(self::$_config[$name])) {
if (!isset(static::$_config[$name])) {
return false;
}
unset(self::$_config[$name], self::$_engines[$name]);
unset(static::$_config[$name], static::$_engines[$name]);
return true;
}
/**
* Temporarily change the settings on a cache config. The settings will persist for the next write
* Temporarily change the settings on a cache config. The settings will persist for the next write
* operation (write, decrement, increment, clear). Any reads that are done before the write, will
* use the modified settings. If `$settings` is empty, the settings will be reset to the
* original configuration.
@ -222,29 +243,29 @@ class Cache {
if (is_array($settings) && $value !== null) {
$config = $value;
}
if (!isset(self::$_config[$config]) || !isset(self::$_engines[$config])) {
if (!isset(static::$_config[$config]) || !isset(static::$_engines[$config])) {
return false;
}
if (!empty($settings)) {
self::$_reset = true;
static::$_reset = true;
}
if (self::$_reset === true) {
if (static::$_reset === true) {
if (empty($settings)) {
self::$_reset = false;
$settings = self::$_config[$config];
static::$_reset = false;
$settings = static::$_config[$config];
} else {
if (is_string($settings) && $value !== null) {
$settings = array($settings => $value);
}
$settings = array_merge(self::$_config[$config], $settings);
$settings += static::$_config[$config];
if (isset($settings['duration']) && !is_numeric($settings['duration'])) {
$settings['duration'] = strtotime($settings['duration']) - time();
}
}
self::$_engines[$config]->settings = $settings;
static::$_engines[$config]->settings = $settings;
}
return self::settings($config);
return static::settings($config);
}
/**
@ -253,17 +274,15 @@ class Cache {
* Permanently remove all expired and deleted data
*
* @param string $config [optional] The config name you wish to have garbage collected. Defaults to 'default'
* @param integer $expires [optional] An expires timestamp. Defaults to NULL
* @return void
* @param int $expires [optional] An expires timestamp. Defaults to NULL
* @return bool
*/
public static function gc($config = 'default', $expires = null) {
self::$_engines[$config]->gc($expires);
return static::$_engines[$config]->gc($expires);
}
/**
* Write data for key into cache. Will automatically use the currently
* active cache configuration. To set the currently active configuration use
* Cache::config()
* Write data for key into a cache engine.
*
* ### Usage:
*
@ -278,32 +297,32 @@ class Cache {
* @param string $key Identifier for the data
* @param mixed $value Data to be cached - anything except a resource
* @param string $config Optional string configuration name to write to. Defaults to 'default'
* @return boolean True if the data was successfully cached, false on failure
* @return bool True if the data was successfully cached, false on failure
*/
public static function write($key, $value, $config = 'default') {
$settings = self::settings($config);
$settings = static::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
$key = static::$_engines[$config]->key($key);
if (!$key || is_resource($value)) {
return false;
}
$success = self::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']);
self::set(null, $config);
$success = static::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']);
static::set(null, $config);
if ($success === false && $value !== '') {
trigger_error(
__d('cake_dev',
"%s cache was unable to write '%s' to %s cache",
$config,
$key,
self::$_engines[$config]->settings['engine']
static::$_engines[$config]->settings['engine']
),
E_USER_WARNING
);
@ -312,9 +331,7 @@ class Cache {
}
/**
* Read a key from the cache. Will automatically use the currently
* active cache configuration. To set the currently active configuration use
* Cache::config()
* Read a key from a cache config.
*
* ### Usage:
*
@ -331,46 +348,46 @@ class Cache {
* @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
*/
public static function read($key, $config = 'default') {
$settings = self::settings($config);
$settings = static::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
$key = static::$_engines[$config]->key($key);
if (!$key) {
return false;
}
return self::$_engines[$config]->read($settings['prefix'] . $key);
return static::$_engines[$config]->read($settings['prefix'] . $key);
}
/**
* Increment a number under the key and return incremented value.
*
* @param string $key Identifier for the data
* @param integer $offset How much to add
* @param int $offset How much to add
* @param string $config Optional string configuration name. Defaults to 'default'
* @return mixed new value, or false if the data doesn't exist, is not integer,
* or if there was an error fetching it.
*/
public static function increment($key, $offset = 1, $config = 'default') {
$settings = self::settings($config);
$settings = static::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
$key = static::$_engines[$config]->key($key);
if (!$key || !is_integer($offset) || $offset < 0) {
if (!$key || !is_int($offset) || $offset < 0) {
return false;
}
$success = self::$_engines[$config]->increment($settings['prefix'] . $key, $offset);
self::set(null, $config);
$success = static::$_engines[$config]->increment($settings['prefix'] . $key, $offset);
static::set(null, $config);
return $success;
}
@ -378,27 +395,27 @@ class Cache {
* Decrement a number under the key and return decremented value.
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @param string $config Optional string configuration name. Defaults to 'default'
* @return mixed new value, or false if the data doesn't exist, is not integer,
* or if there was an error fetching it
*/
public static function decrement($key, $offset = 1, $config = 'default') {
$settings = self::settings($config);
$settings = static::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
$key = static::$_engines[$config]->key($key);
if (!$key || !is_integer($offset) || $offset < 0) {
if (!$key || !is_int($offset) || $offset < 0) {
return false;
}
$success = self::$_engines[$config]->decrement($settings['prefix'] . $key, $offset);
self::set(null, $config);
$success = static::$_engines[$config]->decrement($settings['prefix'] . $key, $offset);
static::set(null, $config);
return $success;
}
@ -417,40 +434,40 @@ class Cache {
*
* @param string $key Identifier for the data
* @param string $config name of the configuration to use. Defaults to 'default'
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public static function delete($key, $config = 'default') {
$settings = self::settings($config);
$settings = static::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
$key = static::$_engines[$config]->key($key);
if (!$key) {
return false;
}
$success = self::$_engines[$config]->delete($settings['prefix'] . $key);
self::set(null, $config);
$success = static::$_engines[$config]->delete($settings['prefix'] . $key);
static::set(null, $config);
return $success;
}
/**
* Delete all keys from the cache.
*
* @param boolean $check if true will check expiration, otherwise delete all
* @param bool $check if true will check expiration, otherwise delete all
* @param string $config name of the configuration to use. Defaults to 'default'
* @return boolean True if the cache was successfully cleared, false otherwise
* @return bool True if the cache was successfully cleared, false otherwise
*/
public static function clear($check = false, $config = 'default') {
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$success = self::$_engines[$config]->clear($check);
self::set(null, $config);
$success = static::$_engines[$config]->clear($check);
static::set(null, $config);
return $success;
}
@ -459,14 +476,14 @@ class Cache {
*
* @param string $group name of the group to be cleared
* @param string $config name of the configuration to use. Defaults to 'default'
* @return boolean True if the cache group was successfully cleared, false otherwise
* @return bool True if the cache group was successfully cleared, false otherwise
*/
public static function clearGroup($group, $config = 'default') {
if (!self::isInitialized($config)) {
if (!static::isInitialized($config)) {
return false;
}
$success = self::$_engines[$config]->clearGroup($group);
self::set(null, $config);
$success = static::$_engines[$config]->clearGroup($group);
static::set(null, $config);
return $success;
}
@ -474,13 +491,13 @@ class Cache {
* Check if Cache has initialized a working config for the given name.
*
* @param string $config name of the configuration to use. Defaults to 'default'
* @return boolean Whether or not the config name has been initialized.
* @return bool Whether or not the config name has been initialized.
*/
public static function isInitialized($config = 'default') {
if (Configure::read('Cache.disable')) {
return false;
}
return isset(self::$_engines[$config]);
return isset(static::$_engines[$config]);
}
/**
@ -491,11 +508,126 @@ class Cache {
* @see Cache::config()
*/
public static function settings($name = 'default') {
if (!empty(self::$_engines[$name])) {
return self::$_engines[$name]->settings();
if (!empty(static::$_engines[$name])) {
return static::$_engines[$name]->settings();
}
return array();
}
}
/**
* Retrieve group names to config mapping.
*
* ```
* Cache::config('daily', array(
* 'duration' => '1 day', 'groups' => array('posts')
* ));
* Cache::config('weekly', array(
* 'duration' => '1 week', 'groups' => array('posts', 'archive')
* ));
* $configs = Cache::groupConfigs('posts');
* ```
*
* $config will equal to `array('posts' => array('daily', 'weekly'))`
*
* @param string $group group name or null to retrieve all group mappings
* @return array map of group and all configuration that has the same group
* @throws CacheException
*/
public static function groupConfigs($group = null) {
if ($group === null) {
return static::$_groups;
}
if (isset(static::$_groups[$group])) {
return array($group => static::$_groups[$group]);
}
throw new CacheException(__d('cake_dev', 'Invalid cache group %s', $group));
}
/**
* Provides the ability to easily do read-through caching.
*
* When called if the $key is not set in $config, the $callable function
* will be invoked. The results will then be stored into the cache config
* at key.
*
* Examples:
*
* Using a Closure to provide data, assume $this is a Model:
*
* ```
* $model = $this;
* $results = Cache::remember('all_articles', function() use ($model) {
* return $model->find('all');
* });
* ```
*
* @param string $key The cache key to read/store data at.
* @param callable $callable The callable that provides data in the case when
* the cache key is empty. Can be any callable type supported by your PHP.
* @param string $config The cache configuration to use for this operation.
* Defaults to default.
* @return mixed The results of the callable or unserialized results.
*/
public static function remember($key, $callable, $config = 'default') {
$existing = static::read($key, $config);
if ($existing !== false) {
return $existing;
}
$results = call_user_func($callable);
static::write($key, $results, $config);
return $results;
}
/**
* Write data for key into a cache engine if it doesn't exist already.
*
* ### Usage:
*
* Writing to the active cache config:
*
* `Cache::add('cached_data', $data);`
*
* Writing to a specific cache config:
*
* `Cache::add('cached_data', $data, 'long_term');`
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached - anything except a resource.
* @param string $config Optional string configuration name to write to. Defaults to 'default'.
* @return bool True if the data was successfully cached, false on failure.
* Or if the key existed already.
*/
public static function add($key, $value, $config = 'default') {
$settings = self::settings($config);
if (empty($settings)) {
return false;
}
if (!self::isInitialized($config)) {
return false;
}
$key = self::$_engines[$config]->key($key);
if (!$key || is_resource($value)) {
return false;
}
$success = self::$_engines[$config]->add($settings['prefix'] . $key, $value, $settings['duration']);
self::set(null, $config);
return $success;
}
/**
* Fetch the engine attached to a specific configuration name.
*
* @param string $config Optional string configuration name to get an engine for. Defaults to 'default'.
* @return null|CacheEngine Null if the engine has not been initialized or the engine.
*/
public static function engine($config = 'default') {
if (self::isInitialized($config)) {
return self::$_engines[$config];
}
return null;
}
}

View file

@ -1,16 +1,17 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.Cache
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -29,10 +30,10 @@ abstract class CacheEngine {
/**
* Contains the compiled string with all groups
* prefixes to be prepeded to every key in this cache engine
* prefixes to be prepended to every key in this cache engine
*
* @var string
**/
*/
protected $_groupPrefix = null;
/**
@ -41,7 +42,7 @@ abstract class CacheEngine {
* Called automatically by the cache frontend
*
* @param array $settings Associative array of parameters for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
$settings += $this->settings + array(
@ -66,7 +67,7 @@ abstract class CacheEngine {
*
* Permanently remove all expired and deleted data
*
* @param integer $expires [optional] An expires timestamp, invalidataing all data before.
* @param int $expires [optional] An expires timestamp, invalidating all data before.
* @return void
*/
public function gc($expires = null) {
@ -77,11 +78,22 @@ abstract class CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache for.
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache for.
* @return bool True if the data was successfully cached, false on failure
*/
abstract public function write($key, $value, $duration);
/**
* Write value for a key into cache if it doesn't already exist
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param int $duration How long to cache for.
* @return bool True if the data was successfully cached, false on failure
*/
public function add($key, $value, $duration) {
}
/**
* Read a key from the cache
*
@ -94,7 +106,7 @@ abstract class CacheEngine {
* Increment a number under the key and return incremented value
*
* @param string $key Identifier for the data
* @param integer $offset How much to add
* @param int $offset How much to add
* @return New incremented value, false otherwise
*/
abstract public function increment($key, $offset = 1);
@ -103,7 +115,7 @@ abstract class CacheEngine {
* Decrement a number under the key and return decremented value
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New incremented value, false otherwise
*/
abstract public function decrement($key, $offset = 1);
@ -112,25 +124,25 @@ abstract class CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
abstract public function delete($key);
/**
* Delete all keys from the cache
*
* @param boolean $check if true will check expiration, otherwise delete all
* @return boolean True if the cache was successfully cleared, false otherwise
* @param bool $check if true will check expiration, otherwise delete all
* @return bool True if the cache was successfully cleared, false otherwise
*/
abstract public function clear($check);
/**
* Clears all values belonging to a group. Is upt to the implementing engine
* to decide whether actually deete the keys or just simulate it to acheive
* Clears all values belonging to a group. Is up to the implementing engine
* to decide whether actually delete the keys or just simulate it to achieve
* the same result.
*
* @param string $groups name of the group to be cleared
* @return boolean
* @param string $group name of the group to be cleared
* @return bool
*/
public function clearGroup($group) {
return false;
@ -175,5 +187,4 @@ abstract class CacheEngine {
$key = preg_replace('/[\s]+/', '_', strtolower(trim(str_replace(array(DS, '/', '.'), '_', strval($key)))));
return $prefix . $key;
}
}

View file

@ -2,20 +2,18 @@
/**
* APC storage engine for cache.
*
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.Cache.Engine
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -27,12 +25,19 @@ class ApcEngine extends CacheEngine {
/**
* Contains the compiled group names
* (prefixed witht the global configuration prefix)
* (prefixed with the global configuration prefix)
*
* @var array
**/
*/
protected $_compiledGroupNames = array();
/**
* APC or APCu extension
*
* @var string
*/
protected $_apcExtension = 'apc';
/**
* Initialize the Cache Engine
*
@ -40,7 +45,7 @@ class ApcEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
* @see CacheEngine::__defaults
*/
public function init($settings = array()) {
@ -49,6 +54,10 @@ class ApcEngine extends CacheEngine {
}
$settings += array('engine' => 'Apc');
parent::init($settings);
if (function_exists('apcu_dec')) {
$this->_apcExtension = 'apcu';
return true;
}
return function_exists('apc_dec');
}
@ -57,17 +66,17 @@ class ApcEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
if ($duration == 0) {
$expires = 0;
} else {
$expires = 0;
if ($duration) {
$expires = time() + $duration;
}
apc_store($key . '_expires', $expires, $duration);
return apc_store($key, $value, $duration);
$func = $this->_apcExtension . '_store';
$func($key . '_expires', $expires, $duration);
return $func($key, $value, $duration);
}
/**
@ -78,62 +87,74 @@ class ApcEngine extends CacheEngine {
*/
public function read($key) {
$time = time();
$cachetime = intval(apc_fetch($key . '_expires'));
$func = $this->_apcExtension . '_fetch';
$cachetime = (int)$func($key . '_expires');
if ($cachetime !== 0 && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) {
return false;
}
return apc_fetch($key);
return $func($key);
}
/**
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to increment
* @param int $offset How much to increment
* @return New incremented value, false otherwise
*/
public function increment($key, $offset = 1) {
return apc_inc($key, $offset);
$func = $this->_apcExtension . '_inc';
return $func($key, $offset);
}
/**
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
*/
public function decrement($key, $offset = 1) {
return apc_dec($key, $offset);
$func = $this->_apcExtension . '_dec';
return $func($key, $offset);
}
/**
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return apc_delete($key);
$func = $this->_apcExtension . '_delete';
return $func($key);
}
/**
* Delete all keys from the cache. This will clear every cache config using APC.
* Delete all keys from the cache. This will clear every cache config using APC.
*
* @param boolean $check If true, nothing will be cleared, as entries are removed
* from APC as they expired. This flag is really only used by FileEngine.
* @return boolean True Returns true.
* @param bool $check If true, nothing will be cleared, as entries are removed
* from APC as they expired. This flag is really only used by FileEngine.
* @return bool True Returns true.
*/
public function clear($check) {
if ($check) {
return true;
}
$info = apc_cache_info('user');
$cacheKeys = $info['cache_list'];
unset($info);
foreach ($cacheKeys as $key) {
$func = $this->_apcExtension . '_delete';
if (class_exists('APCIterator', false)) {
$iterator = new APCIterator(
'user',
'/^' . preg_quote($this->settings['prefix'], '/') . '/',
APC_ITER_NONE
);
$func($iterator);
return true;
}
$cache = $this->_apcExtension === 'apc' ? apc_cache_info('user') : apcu_cache_info();
foreach ($cache['cache_list'] as $key) {
if (strpos($key['info'], $this->settings['prefix']) === 0) {
apc_delete($key['info']);
$func($key['info']);
}
}
return true;
@ -145,7 +166,7 @@ class ApcEngine extends CacheEngine {
* the group accordingly.
*
* @return array
**/
*/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
@ -153,11 +174,13 @@ class ApcEngine extends CacheEngine {
}
}
$groups = apc_fetch($this->_compiledGroupNames);
$fetchFunc = $this->_apcExtension . '_fetch';
$storeFunc = $this->_apcExtension . '_store';
$groups = $fetchFunc($this->_compiledGroupNames);
if (count($groups) !== count($this->settings['groups'])) {
foreach ($this->_compiledGroupNames as $group) {
if (!isset($groups[$group])) {
apc_store($group, 1);
$storeFunc($group, 1);
$groups[$group] = 1;
}
}
@ -176,11 +199,32 @@ class ApcEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
apc_inc($this->settings['prefix'] . $group, 1, $success);
$func = $this->_apcExtension . '_inc';
$func($this->settings['prefix'] . $group, 1, $success);
return $success;
}
/**
* Write data for key into cache if it doesn't exist already.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
* @link http://php.net/manual/en/function.apc-add.php
*/
public function add($key, $value, $duration) {
$expires = 0;
if ($duration) {
$expires = time() + $duration;
}
$func = $this->_apcExtension . '_add';
$func($key . '_expires', $expires, $duration);
return $func($key, $value, $duration);
}
}

View file

@ -1,28 +1,27 @@
<?php
/**
* File Storage engine for cache. Filestorage is the slowest cache storage
* to read and write. However, it is good for servers that don't have other storage
* File Storage engine for cache. Filestorage is the slowest cache storage
* to read and write. However, it is good for servers that don't have other storage
* engine available, or have content which is not performance sensitive.
*
* You can configure a FileEngine cache, using Cache::config()
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* File Storage engine for cache. Filestorage is the slowest cache storage
* to read and write. However, it is good for servers that don't have other storage
* File Storage engine for cache. Filestorage is the slowest cache storage
* to read and write. However, it is good for servers that don't have other storage
* engine available, or have content which is not performance sensitive.
*
* You can configure a FileEngine cache, using Cache::config()
@ -43,7 +42,7 @@ class FileEngine extends CacheEngine {
*
* - path = absolute path to cache directory, default => CACHE
* - prefix = string prefix for filename, default => cake_
* - lock = enable file locking on write, default => false
* - lock = enable file locking on write, default => true
* - serialize = serialize the data, default => true
*
* @var array
@ -54,7 +53,7 @@ class FileEngine extends CacheEngine {
/**
* True unless FileEngine::__active(); fails
*
* @var boolean
* @var bool
*/
protected $_init = true;
@ -65,7 +64,7 @@ class FileEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
$settings += array(
@ -94,8 +93,8 @@ class FileEngine extends CacheEngine {
/**
* Garbage collection. Permanently remove all expired and deleted data
*
* @param integer $expires [optional] An expires timestamp, invalidataing all data before.
* @return boolean True if garbage collection was successful, false on failure
* @param int $expires [optional] An expires timestamp, invalidating all data before.
* @return bool True if garbage collection was successful, false on failure
*/
public function gc($expires = null) {
return $this->clear(true);
@ -106,11 +105,11 @@ class FileEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $data Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $data, $duration) {
if ($data === '' || !$this->_init) {
if (!$this->_init) {
return false;
}
@ -133,7 +132,7 @@ class FileEngine extends CacheEngine {
}
$expires = time() + $duration;
$contents = $expires . $lineBreak . $data . $lineBreak;
$contents = implode(array($expires, $lineBreak, $data, $lineBreak));
if ($this->settings['lock']) {
$this->_File->flock(LOCK_EX);
@ -166,7 +165,7 @@ class FileEngine extends CacheEngine {
$this->_File->rewind();
$time = time();
$cachetime = intval($this->_File->current());
$cachetime = (int)$this->_File->current();
if ($cachetime !== false && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) {
if ($this->settings['lock']) {
@ -201,7 +200,7 @@ class FileEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
if ($this->_setKey($key) === false || !$this->_init) {
@ -209,60 +208,104 @@ class FileEngine extends CacheEngine {
}
$path = $this->_File->getRealPath();
$this->_File = null;
return unlink($path);
//@codingStandardsIgnoreStart
return @unlink($path);
//@codingStandardsIgnoreEnd
}
/**
* Delete all values from the cache
*
* @param boolean $check Optional - only delete expired cache items
* @return boolean True if the cache was successfully cleared, false otherwise
* @param bool $check Optional - only delete expired cache items
* @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
if (!$this->_init) {
return false;
}
$dir = dir($this->settings['path']);
$this->_File = null;
$threshold = $now = false;
if ($check) {
$now = time();
$threshold = $now - $this->settings['duration'];
}
$this->_clearDirectory($this->settings['path'], $now, $threshold);
$directory = new RecursiveDirectoryIterator($this->settings['path']);
$contents = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST);
$cleared = array();
foreach ($contents as $path) {
if ($path->isFile()) {
continue;
}
$path = $path->getRealPath() . DS;
if (!in_array($path, $cleared)) {
$this->_clearDirectory($path, $now, $threshold);
$cleared[] = $path;
}
}
return true;
}
/**
* Used to clear a directory of matching files.
*
* @param string $path The path to search.
* @param int $now The current timestamp
* @param int $threshold Any file not modified after this value will be deleted.
* @return void
*/
protected function _clearDirectory($path, $now, $threshold) {
$prefixLength = strlen($this->settings['prefix']);
if (!is_dir($path)) {
return;
}
$dir = dir($path);
while (($entry = $dir->read()) !== false) {
if (substr($entry, 0, $prefixLength) !== $this->settings['prefix']) {
continue;
}
if ($this->_setKey($entry) === false) {
try {
$file = new SplFileObject($path . $entry, 'r');
} catch (Exception $e) {
continue;
}
if ($check) {
$mtime = $this->_File->getMTime();
if ($threshold) {
$mtime = $file->getMTime();
if ($mtime > $threshold) {
continue;
}
$expires = (int)$this->_File->current();
$expires = (int)$file->current();
if ($expires > $now) {
continue;
}
}
$path = $this->_File->getRealPath();
$this->_File = null;
if (file_exists($path)) {
unlink($path);
if ($file->isFile()) {
$filePath = $file->getRealPath();
$file = null;
//@codingStandardsIgnoreStart
@unlink($filePath);
//@codingStandardsIgnoreEnd
}
}
$dir->close();
return true;
}
/**
* Not implemented
*
* @param string $key
* @param integer $offset
* @param string $key The key to decrement
* @param int $offset The number to offset
* @return void
* @throws CacheException
*/
@ -273,8 +316,8 @@ class FileEngine extends CacheEngine {
/**
* Not implemented
*
* @param string $key
* @param integer $offset
* @param string $key The key to decrement
* @param int $offset The number to offset
* @return void
* @throws CacheException
*/
@ -287,8 +330,8 @@ class FileEngine extends CacheEngine {
* for the cache file the key is referring to.
*
* @param string $key The key
* @param boolean $createKey Whether the key should be created if it doesn't exists, or not
* @return boolean true if the cache key could be set, false otherwise
* @param bool $createKey Whether the key should be created if it doesn't exists, or not
* @return bool true if the cache key could be set, false otherwise
*/
protected function _setKey($key, $createKey = false) {
$groups = null;
@ -298,7 +341,7 @@ class FileEngine extends CacheEngine {
$dir = $this->settings['path'] . $groups;
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
mkdir($dir, 0775, true);
}
$path = new SplFileInfo($dir . $key);
@ -327,10 +370,16 @@ class FileEngine extends CacheEngine {
/**
* Determine is cache directory is writable
*
* @return boolean
* @return bool
*/
protected function _active() {
$dir = new SplFileInfo($this->settings['path']);
if (Configure::read('debug')) {
$path = $dir->getPathname();
if (!is_dir($path)) {
mkdir($path, 0775, true);
}
}
if ($this->_init && !($dir->isDir() && $dir->isWritable())) {
$this->_init = false;
trigger_error(__d('cake_dev', '%s is not writable', $this->settings['path']), E_USER_WARNING);
@ -350,24 +399,51 @@ class FileEngine extends CacheEngine {
return false;
}
$key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
$key = Inflector::underscore(str_replace(array(DS, '/', '.', '<', '>', '?', ':', '|', '*', '"'), '_', strval($key)));
return $key;
}
/**
* Recursively deletes all files under any directory named as $group
*
* @return boolean success
**/
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
$this->_File = null;
$directoryIterator = new RecursiveDirectoryIterator($this->settings['path']);
$contents = new RecursiveIteratorIterator($directoryIterator, RecursiveIteratorIterator::CHILD_FIRST);
foreach ($contents as $object) {
$containsGroup = strpos($object->getPathName(), DS . $group . DS) !== false;
if ($object->isFile() && $containsGroup) {
unlink($object->getPathName());
$hasPrefix = true;
if (strlen($this->settings['prefix']) !== 0) {
$hasPrefix = strpos($object->getBaseName(), $this->settings['prefix']) === 0;
}
if ($object->isFile() && $containsGroup && $hasPrefix) {
$path = $object->getPathName();
$object = null;
//@codingStandardsIgnoreStart
@unlink($path);
//@codingStandardsIgnoreEnd
}
}
return true;
}
/**
* Write data for key into cache if it doesn't exist already.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
*/
public function add($key, $value, $duration) {
$cachedValue = $this->read($key);
if ($cachedValue === false) {
return $this->write($key, $value, $duration);
}
return false;
}
}

View file

@ -2,37 +2,36 @@
/**
* Memcache storage engine for cache
*
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.Cache.Engine
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Memcache storage engine for cache. Memcache has some limitations in the amount of
* control you have over expire times far in the future. See MemcacheEngine::write() for
* Memcache storage engine for cache. Memcache has some limitations in the amount of
* control you have over expire times far in the future. See MemcacheEngine::write() for
* more information.
*
* @package Cake.Cache.Engine
* @package Cake.Cache.Engine
* @deprecated 3.0.0 You should use the Memcached adapter instead.
*/
class MemcacheEngine extends CacheEngine {
/**
* Contains the compiled group names
* (prefixed witht the global configuration prefix)
* (prefixed with the global configuration prefix)
*
* @var array
**/
*/
protected $_compiledGroupNames = array();
/**
@ -60,7 +59,7 @@ class MemcacheEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
if (!class_exists('Memcache')) {
@ -98,17 +97,17 @@ class MemcacheEngine extends CacheEngine {
}
/**
* Parses the server address into the host/port. Handles both IPv6 and IPv4
* Parses the server address into the host/port. Handles both IPv6 and IPv4
* addresses and Unix sockets
*
* @param string $server The server address string.
* @return array Array containing host, port
*/
protected function _parseServerString($server) {
if ($server[0] == 'u') {
if (strpos($server, 'unix://') === 0) {
return array($server, 0);
}
if (substr($server, 0, 1) == '[') {
if (substr($server, 0, 1) === '[') {
$position = strpos($server, ']:');
if ($position !== false) {
$position++;
@ -126,14 +125,14 @@ class MemcacheEngine extends CacheEngine {
}
/**
* Write data for key into cache. When using memcache as your cache engine
* Write data for key into cache. When using memcache as your cache engine
* remember that the Memcache pecl extension does not support cache expiry times greater
* than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
* @see http://php.net/manual/en/memcache.set.php
*/
public function write($key, $value, $duration) {
@ -157,14 +156,14 @@ class MemcacheEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to increment
* @param int $offset How much to increment
* @return New incremented value, false otherwise
* @throws CacheException when you try to increment with compress = true
*/
public function increment($key, $offset = 1) {
if ($this->settings['compress']) {
throw new CacheException(
__d('cake_dev', 'Method increment() not implemented for compressed cache in %s', __CLASS__)
__d('cake_dev', 'Method %s not implemented for compressed cache in %s', 'increment()', __CLASS__)
);
}
return $this->_Memcache->increment($key, $offset);
@ -174,14 +173,14 @@ class MemcacheEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
* @throws CacheException when you try to decrement with compress = true
*/
public function decrement($key, $offset = 1) {
if ($this->settings['compress']) {
throw new CacheException(
__d('cake_dev', 'Method decrement() not implemented for compressed cache in %s', __CLASS__)
__d('cake_dev', 'Method %s not implemented for compressed cache in %s', 'decrement()', __CLASS__)
);
}
return $this->_Memcache->decrement($key, $offset);
@ -191,7 +190,7 @@ class MemcacheEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return $this->_Memcache->delete($key);
@ -200,20 +199,21 @@ class MemcacheEngine extends CacheEngine {
/**
* Delete all keys from the cache
*
* @param boolean $check
* @return boolean True if the cache was successfully cleared, false otherwise
* @param bool $check If true no deletes will occur and instead CakePHP will rely
* on key TTL values.
* @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
if ($check) {
return true;
}
foreach ($this->_Memcache->getExtendedStats('slabs') as $slabs) {
foreach ($this->_Memcache->getExtendedStats('slabs', 0) as $slabs) {
foreach (array_keys($slabs) as $slabId) {
if (!is_numeric($slabId)) {
continue;
}
foreach ($this->_Memcache->getExtendedStats('cachedump', $slabId) as $stats) {
foreach ($this->_Memcache->getExtendedStats('cachedump', $slabId, 0) as $stats) {
if (!is_array($stats)) {
continue;
}
@ -232,8 +232,8 @@ class MemcacheEngine extends CacheEngine {
* Connects to a server in connection pool
*
* @param string $host host ip address or name
* @param integer $port Server port
* @return boolean True if memcache server was connected
* @param int $port Server port
* @return bool True if memcache server was connected
*/
public function connect($host, $port = 11211) {
if ($this->_Memcache->getServerStatus($host, $port) === 0) {
@ -251,7 +251,7 @@ class MemcacheEngine extends CacheEngine {
* the group accordingly.
*
* @return array
**/
*/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
@ -283,9 +283,30 @@ class MemcacheEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
return (bool)$this->_Memcache->increment($this->settings['prefix'] . $group);
}
/**
* Write data for key into cache if it doesn't exist already. When using memcached as your cache engine
* remember that the Memcached PECL extension does not support cache expiry times greater
* than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
* @link http://php.net/manual/en/memcache.add.php
*/
public function add($key, $value, $duration) {
if ($duration > 30 * DAY) {
$duration = 0;
}
return $this->_Memcache->add($key, $value, $this->settings['compress'], $duration);
}
}

View file

@ -0,0 +1,365 @@
<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since CakePHP(tm) v 2.5.0
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* Memcached storage engine for cache. Memcached has some limitations in the amount of
* control you have over expire times far in the future. See MemcachedEngine::write() for
* more information.
*
* Main advantage of this Memcached engine over the memcached engine is
* support of binary protocol, and igbibnary serialization
* (if memcached extension compiled with --enable-igbinary)
* Compressed keys can also be incremented/decremented
*
* This cache engine requires at least ext/memcached version 2.0
*
* @package Cake.Cache.Engine
*/
class MemcachedEngine extends CacheEngine {
/**
* memcached wrapper.
*
* @var Memcache
*/
protected $_Memcached = null;
/**
* Settings
*
* - servers = string or array of memcached servers, default => 127.0.0.1. If an
* array MemcacheEngine will use them as a pool.
* - compress = boolean, default => false
* - persistent = string The name of the persistent connection. All configurations using
* the same persistent value will share a single underlying connection.
* - serialize = string, default => php. The serializer engine used to serialize data.
* Available engines are php, igbinary and json. Beside php, the memcached extension
* must be compiled with the appropriate serializer support.
* - options - Additional options for the memcached client. Should be an array of option => value.
* Use the Memcached::OPT_* constants as keys.
*
* @var array
*/
public $settings = array();
/**
* List of available serializer engines
*
* Memcached must be compiled with json and igbinary support to use these engines
*
* @var array
*/
protected $_serializers = array(
'igbinary' => Memcached::SERIALIZER_IGBINARY,
'json' => Memcached::SERIALIZER_JSON,
'php' => Memcached::SERIALIZER_PHP
);
/**
* Initialize the Cache Engine
*
* Called automatically by the cache frontend
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return bool True if the engine has been successfully initialized, false if not
* @throws CacheException when you try use authentication without Memcached compiled with SASL support
*/
public function init($settings = array()) {
if (!class_exists('Memcached')) {
return false;
}
if (!isset($settings['prefix'])) {
$settings['prefix'] = Inflector::slug(APP_DIR) . '_';
}
if (defined('Memcached::HAVE_MSGPACK') && Memcached::HAVE_MSGPACK) {
$this->_serializers['msgpack'] = Memcached::SERIALIZER_MSGPACK;
}
$settings += array(
'engine' => 'Memcached',
'servers' => array('127.0.0.1'),
'compress' => false,
'persistent' => false,
'login' => null,
'password' => null,
'serialize' => 'php',
'options' => array()
);
parent::init($settings);
if (!is_array($this->settings['servers'])) {
$this->settings['servers'] = array($this->settings['servers']);
}
if (isset($this->_Memcached)) {
return true;
}
if (!$this->settings['persistent']) {
$this->_Memcached = new Memcached();
} else {
$this->_Memcached = new Memcached((string)$this->settings['persistent']);
}
$this->_setOptions();
if (count($this->_Memcached->getServerList())) {
return true;
}
$servers = array();
foreach ($this->settings['servers'] as $server) {
$servers[] = $this->_parseServerString($server);
}
if (!$this->_Memcached->addServers($servers)) {
return false;
}
if ($this->settings['login'] !== null && $this->settings['password'] !== null) {
if (!method_exists($this->_Memcached, 'setSaslAuthData')) {
throw new CacheException(
__d('cake_dev', 'Memcached extension is not build with SASL support')
);
}
$this->_Memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
$this->_Memcached->setSaslAuthData($this->settings['login'], $this->settings['password']);
}
if (is_array($this->settings['options'])) {
foreach ($this->settings['options'] as $opt => $value) {
$this->_Memcached->setOption($opt, $value);
}
}
return true;
}
/**
* Settings the memcached instance
*
* @throws CacheException when the Memcached extension is not built with the desired serializer engine
* @return void
*/
protected function _setOptions() {
$this->_Memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
$serializer = strtolower($this->settings['serialize']);
if (!isset($this->_serializers[$serializer])) {
throw new CacheException(
__d('cake_dev', '%s is not a valid serializer engine for Memcached', $serializer)
);
}
if ($serializer !== 'php' && !constant('Memcached::HAVE_' . strtoupper($serializer))) {
throw new CacheException(
__d('cake_dev', 'Memcached extension is not compiled with %s support', $serializer)
);
}
$this->_Memcached->setOption(Memcached::OPT_SERIALIZER, $this->_serializers[$serializer]);
// Check for Amazon ElastiCache instance
if (defined('Memcached::OPT_CLIENT_MODE') && defined('Memcached::DYNAMIC_CLIENT_MODE')) {
$this->_Memcached->setOption(Memcached::OPT_CLIENT_MODE, Memcached::DYNAMIC_CLIENT_MODE);
}
$this->_Memcached->setOption(Memcached::OPT_COMPRESSION, (bool)$this->settings['compress']);
}
/**
* Parses the server address into the host/port. Handles both IPv6 and IPv4
* addresses and Unix sockets
*
* @param string $server The server address string.
* @return array Array containing host, port
*/
protected function _parseServerString($server) {
$socketTransport = 'unix://';
if (strpos($server, $socketTransport) === 0) {
return array(substr($server, strlen($socketTransport)), 0);
}
if (substr($server, 0, 1) === '[') {
$position = strpos($server, ']:');
if ($position !== false) {
$position++;
}
} else {
$position = strpos($server, ':');
}
$port = 11211;
$host = $server;
if ($position !== false) {
$host = substr($server, 0, $position);
$port = substr($server, $position + 1);
}
return array($host, (int)$port);
}
/**
* Write data for key into cache. When using memcached as your cache engine
* remember that the Memcached PECL extension does not support cache expiry times greater
* than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
* @see http://php.net/manual/en/memcache.set.php
*/
public function write($key, $value, $duration) {
if ($duration > 30 * DAY) {
$duration = 0;
}
return $this->_Memcached->set($key, $value, $duration);
}
/**
* Read a key from the cache
*
* @param string $key Identifier for the data
* @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
*/
public function read($key) {
return $this->_Memcached->get($key);
}
/**
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
* @param int $offset How much to increment
* @return New incremented value, false otherwise
* @throws CacheException when you try to increment with compress = true
*/
public function increment($key, $offset = 1) {
return $this->_Memcached->increment($key, $offset);
}
/**
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
* @throws CacheException when you try to decrement with compress = true
*/
public function decrement($key, $offset = 1) {
return $this->_Memcached->decrement($key, $offset);
}
/**
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return $this->_Memcached->delete($key);
}
/**
* Delete all keys from the cache
*
* @param bool $check If true no deletes will occur and instead CakePHP will rely
* on key TTL values.
* @return bool True if the cache was successfully cleared, false otherwise. Will
* also return false if you are using a binary protocol.
*/
public function clear($check) {
if ($check) {
return true;
}
$keys = $this->_Memcached->getAllKeys();
if ($keys === false) {
return false;
}
foreach ($keys as $key) {
if (strpos($key, $this->settings['prefix']) === 0) {
$this->_Memcached->delete($key);
}
}
return true;
}
/**
* Returns the `group value` for each of the configured groups
* If the group initial value was not found, then it initializes
* the group accordingly.
*
* @return array
*/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
$this->_compiledGroupNames[] = $this->settings['prefix'] . $group;
}
}
$groups = $this->_Memcached->getMulti($this->_compiledGroupNames);
if (count($groups) !== count($this->settings['groups'])) {
foreach ($this->_compiledGroupNames as $group) {
if (!isset($groups[$group])) {
$this->_Memcached->set($group, 1, 0);
$groups[$group] = 1;
}
}
ksort($groups);
}
$result = array();
$groups = array_values($groups);
foreach ($this->settings['groups'] as $i => $group) {
$result[] = $group . $groups[$i];
}
return $result;
}
/**
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
return (bool)$this->_Memcached->increment($this->settings['prefix'] . $group);
}
/**
* Write data for key into cache if it doesn't exist already. When using memcached as your cache engine
* remember that the Memcached pecl extension does not support cache expiry times greater
* than 30 days in the future. Any duration greater than 30 days will be treated as never expiring.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
* @link http://php.net/manual/en/memcached.add.php
*/
public function add($key, $value, $duration) {
if ($duration > 30 * DAY) {
$duration = 0;
}
return $this->_Memcached->add($key, $value, $duration);
}
}

View file

@ -2,20 +2,18 @@
/**
* Redis storage engine for cache
*
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.Cache.Engine
* @since CakePHP(tm) v 2.2
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -35,10 +33,12 @@ class RedisEngine extends CacheEngine {
/**
* Settings
*
* - server = string url or ip to the Redis server host
* - server = string URL or ip to the Redis server host
* - database = integer database number to use for connection
* - port = integer port number to the Redis server (default: 6379)
* - timeout = float timeout in seconds (default: 0)
* - persistent = bool Connects to the Redis server with a persistent connection (default: true)
* - persistent = boolean Connects to the Redis server with a persistent connection (default: true)
* - unix_socket = path to the unix socket file (default: false)
*
* @var array
*/
@ -51,7 +51,7 @@ class RedisEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
if (!class_exists('Redis')) {
@ -59,11 +59,14 @@ class RedisEngine extends CacheEngine {
}
parent::init(array_merge(array(
'engine' => 'Redis',
'prefix' => null,
'prefix' => Inflector::slug(APP_DIR) . '_',
'server' => '127.0.0.1',
'database' => 0,
'port' => 6379,
'password' => false,
'timeout' => 0,
'persistent' => true
'persistent' => true,
'unix_socket' => false
), $settings)
);
@ -73,21 +76,29 @@ class RedisEngine extends CacheEngine {
/**
* Connects to a Redis server
*
* @return boolean True if Redis server was connected
* @return bool True if Redis server was connected
*/
protected function _connect() {
$return = false;
try {
$this->_Redis = new Redis();
if (empty($this->settings['persistent'])) {
if (!empty($this->settings['unix_socket'])) {
$return = $this->_Redis->connect($this->settings['unix_socket']);
} elseif (empty($this->settings['persistent'])) {
$return = $this->_Redis->connect($this->settings['server'], $this->settings['port'], $this->settings['timeout']);
} else {
$return = $this->_Redis->pconnect($this->settings['server'], $this->settings['port'], $this->settings['timeout']);
$persistentId = $this->settings['port'] . $this->settings['timeout'] . $this->settings['database'];
$return = $this->_Redis->pconnect($this->settings['server'], $this->settings['port'], $this->settings['timeout'], $persistentId);
}
} catch (RedisException $e) {
$return = false;
}
if (!$return) {
return false;
}
return $return;
if ($this->settings['password'] && !$this->_Redis->auth($this->settings['password'])) {
return false;
}
return $this->_Redis->select($this->settings['database']);
}
/**
@ -95,13 +106,18 @@ class RedisEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
if (!is_int($value)) {
$value = serialize($value);
}
if (!$this->_Redis->isConnected()) {
$this->_connect();
}
if ($duration === 0) {
return $this->_Redis->set($key, $value);
}
@ -117,11 +133,11 @@ class RedisEngine extends CacheEngine {
*/
public function read($key) {
$value = $this->_Redis->get($key);
if (ctype_digit($value)) {
$value = (int)$value;
if (preg_match('/^[-]?\d+$/', $value)) {
return (int)$value;
}
if ($value !== false && is_string($value)) {
$value = unserialize($value);
return unserialize($value);
}
return $value;
}
@ -130,7 +146,7 @@ class RedisEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to increment
* @param int $offset How much to increment
* @return New incremented value, false otherwise
* @throws CacheException when you try to increment with compress = true
*/
@ -142,7 +158,7 @@ class RedisEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
* @throws CacheException when you try to decrement with compress = true
*/
@ -154,7 +170,7 @@ class RedisEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return $this->_Redis->delete($key) > 0;
@ -163,8 +179,9 @@ class RedisEngine extends CacheEngine {
/**
* Delete all keys from the cache
*
* @param boolean $check
* @return boolean True if the cache was successfully cleared, false otherwise
* @param bool $check Whether or not expiration keys should be checked. If
* true, no keys will be removed as cache will rely on redis TTL's.
* @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
if ($check) {
@ -182,7 +199,7 @@ class RedisEngine extends CacheEngine {
* the group accordingly.
*
* @return array
**/
*/
public function groups() {
$result = array();
foreach ($this->settings['groups'] as $group) {
@ -200,20 +217,42 @@ class RedisEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
* @param string $group The group name to clear.
* @return bool success
*/
public function clearGroup($group) {
return (bool)$this->_Redis->incr($this->settings['prefix'] . $group);
}
/**
* Disconnects from the redis server
*
* @return voind
**/
*/
public function __destruct() {
if (!$this->settings['persistent']) {
$this->_Redis->close();
}
}
/**
* Write data for key into cache if it doesn't exist already.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
* @link https://github.com/phpredis/phpredis#setnx
*/
public function add($key, $value, $duration) {
if (!is_int($value)) {
$value = serialize($value);
}
$result = $this->_Redis->setnx($key, $value);
// setnx() doesn't have an expiry option, so overwrite the key with one
if ($result) {
return $this->_Redis->setex($key, $duration, $value);
}
return false;
}
}

View file

@ -4,19 +4,18 @@
*
* Supports wincache 1.1.0 and higher.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.Cache.Engine
* @since CakePHP(tm) v 1.2.0.4933
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -28,10 +27,10 @@ class WincacheEngine extends CacheEngine {
/**
* Contains the compiled group names
* (prefixed witht the global configuration prefix)
* (prefixed with the global configuration prefix)
*
* @var array
**/
*/
protected $_compiledGroupNames = array();
/**
@ -41,7 +40,7 @@ class WincacheEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
* @see CacheEngine::__defaults
*/
public function init($settings = array()) {
@ -58,8 +57,8 @@ class WincacheEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
$expires = time() + $duration;
@ -81,7 +80,7 @@ class WincacheEngine extends CacheEngine {
*/
public function read($key) {
$time = time();
$cachetime = intval(wincache_ucache_get($key . '_expires'));
$cachetime = (int)wincache_ucache_get($key . '_expires');
if ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime) {
return false;
}
@ -92,7 +91,7 @@ class WincacheEngine extends CacheEngine {
* Increments the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to increment
* @param int $offset How much to increment
* @return New incremented value, false otherwise
*/
public function increment($key, $offset = 1) {
@ -103,7 +102,7 @@ class WincacheEngine extends CacheEngine {
* Decrements the value of an integer cached key
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
*/
public function decrement($key, $offset = 1) {
@ -114,19 +113,19 @@ class WincacheEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return wincache_ucache_delete($key);
}
/**
* Delete all keys from the cache. This will clear every
* Delete all keys from the cache. This will clear every
* item in the cache matching the cache config prefix.
*
* @param boolean $check If true, nothing will be cleared, as entries will
* @param bool $check If true, nothing will be cleared, as entries will
* naturally expire in wincache..
* @return boolean True Returns true.
* @return bool True Returns true.
*/
public function clear($check) {
if ($check) {
@ -149,7 +148,7 @@ class WincacheEngine extends CacheEngine {
* the group accordingly.
*
* @return array
**/
*/
public function groups() {
if (empty($this->_compiledGroupNames)) {
foreach ($this->settings['groups'] as $group) {
@ -180,12 +179,29 @@ class WincacheEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
$success = null;
wincache_ucache_inc($this->settings['prefix'] . $group, 1, $success);
return $success;
}
/**
* Write data for key into cache if it doesn't exist already.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
*/
public function add($key, $value, $duration) {
$cachedValue = $this->read($key);
if ($cachedValue === false) {
return $this->write($key, $value, $duration);
}
return false;
}
}

View file

@ -2,19 +2,18 @@
/**
* Xcache storage engine for cache.
*
* PHP 5
*
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @package Cake.Cache.Engine
* @since CakePHP(tm) v 1.2.0.4947
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
@ -42,10 +41,10 @@ class XcacheEngine extends CacheEngine {
* To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array());
*
* @param array $settings array of setting for the engine
* @return boolean True if the engine has been successfully initialized, false if not
* @return bool True if the engine has been successfully initialized, false if not
*/
public function init($settings = array()) {
if (php_sapi_name() !== 'cli') {
if (PHP_SAPI !== 'cli') {
parent::init(array_merge(array(
'engine' => 'Xcache',
'prefix' => Inflector::slug(APP_DIR) . '_',
@ -63,8 +62,8 @@ class XcacheEngine extends CacheEngine {
*
* @param string $key Identifier for the data
* @param mixed $value Data to be cached
* @param integer $duration How long to cache the data, in seconds
* @return boolean True if the data was successfully cached, false on failure
* @param int $duration How long to cache the data, in seconds
* @return bool True if the data was successfully cached, false on failure
*/
public function write($key, $value, $duration) {
$expires = time() + $duration;
@ -81,7 +80,7 @@ class XcacheEngine extends CacheEngine {
public function read($key) {
if (xcache_isset($key)) {
$time = time();
$cachetime = intval(xcache_get($key . '_expires'));
$cachetime = (int)xcache_get($key . '_expires');
if ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime) {
return false;
}
@ -95,7 +94,7 @@ class XcacheEngine extends CacheEngine {
* If the cache key is not an integer it will be treated as 0
*
* @param string $key Identifier for the data
* @param integer $offset How much to increment
* @param int $offset How much to increment
* @return New incremented value, false otherwise
*/
public function increment($key, $offset = 1) {
@ -107,7 +106,7 @@ class XcacheEngine extends CacheEngine {
* If the cache key is not an integer it will be treated as 0
*
* @param string $key Identifier for the data
* @param integer $offset How much to subtract
* @param int $offset How much to subtract
* @return New decremented value, false otherwise
*/
public function decrement($key, $offset = 1) {
@ -118,7 +117,7 @@ class XcacheEngine extends CacheEngine {
* Delete a key from the cache
*
* @param string $key Identifier for the data
* @return boolean True if the value was successfully deleted, false if it didn't exist or couldn't be removed
* @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
*/
public function delete($key) {
return xcache_unset($key);
@ -127,8 +126,9 @@ class XcacheEngine extends CacheEngine {
/**
* Delete all keys from the cache
*
* @param boolean $check
* @return boolean True if the cache was successfully cleared, false otherwise
* @param bool $check If true no deletes will occur and instead CakePHP will rely
* on key TTL values.
* @return bool True if the cache was successfully cleared, false otherwise
*/
public function clear($check) {
$this->_auth();
@ -146,7 +146,7 @@ class XcacheEngine extends CacheEngine {
* the group accordingly.
*
* @return array
**/
*/
public function groups() {
$result = array();
foreach ($this->settings['groups'] as $group) {
@ -164,8 +164,9 @@ class XcacheEngine extends CacheEngine {
* Increments the group value to simulate deletion of all keys under a group
* old values will remain in storage until they expire.
*
* @return boolean success
**/
* @param string $group The group to clear.
* @return bool success
*/
public function clearGroup($group) {
return (bool)xcache_inc($this->settings['prefix'] . $group, 1);
}
@ -177,7 +178,7 @@ class XcacheEngine extends CacheEngine {
* This has to be done because xcache_clear_cache() needs to pass Basic Http Auth
* (see xcache.admin configuration settings)
*
* @param boolean $reverse Revert changes
* @param bool $reverse Revert changes
* @return void
*/
protected function _auth($reverse = false) {
@ -206,4 +207,21 @@ class XcacheEngine extends CacheEngine {
}
}
}
/**
* Write data for key into cache if it doesn't exist already.
* If it already exists, it fails and returns false.
*
* @param string $key Identifier for the data.
* @param mixed $value Data to be cached.
* @param int $duration How long to cache the data, in seconds.
* @return bool True if the data was successfully cached, false on failure.
*/
public function add($key, $value, $duration) {
$cachedValue = $this->read($key);
if ($cachedValue === false) {
return $this->write($key, $value, $duration);
}
return false;
}
}