You've already forked joomla_test
first commit
This commit is contained in:
726
libraries/joomla/cache/cache.php
vendored
Normal file
726
libraries/joomla/cache/cache.php
vendored
Normal file
@ -0,0 +1,726 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Joomla! Cache base object
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCache
|
||||
{
|
||||
/**
|
||||
* @var object Storage handler
|
||||
* @since 11.1
|
||||
*/
|
||||
public static $_handler = array();
|
||||
|
||||
/**
|
||||
* @var array Options
|
||||
* @since 11.1
|
||||
*/
|
||||
public $_options;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options options
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __construct($options)
|
||||
{
|
||||
$conf = JFactory::getConfig();
|
||||
|
||||
$this->_options = array(
|
||||
'cachebase' => $conf->get('cache_path', JPATH_CACHE),
|
||||
'lifetime' => (int) $conf->get('cachetime'),
|
||||
'language' => $conf->get('language', 'en-GB'),
|
||||
'storage' => $conf->get('cache_handler', ''),
|
||||
'defaultgroup' => 'default',
|
||||
'locking' => true,
|
||||
'locktime' => 15,
|
||||
'checkTime' => true,
|
||||
'caching' => ($conf->get('caching') >= 1) ? true : false);
|
||||
|
||||
// Overwrite default options with given options
|
||||
foreach ($options as $option => $value)
|
||||
{
|
||||
if (isset($options[$option]) && $options[$option] !== '')
|
||||
{
|
||||
$this->_options[$option] = $options[$option];
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($this->_options['storage']))
|
||||
{
|
||||
$this->_options['caching'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a cache adapter object, always creating it
|
||||
*
|
||||
* @param string $type The cache object type to instantiate
|
||||
* @param array $options The array of options
|
||||
*
|
||||
* @return JCache A JCache object
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function getInstance($type = 'output', $options = array())
|
||||
{
|
||||
return JCacheController::getInstance($type, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the storage handlers
|
||||
*
|
||||
* @return array An array of available storage handlers
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function getStores()
|
||||
{
|
||||
$handlers = array();
|
||||
|
||||
// Get an iterator and loop trough the driver classes.
|
||||
$iterator = new DirectoryIterator(__DIR__ . '/storage');
|
||||
|
||||
foreach ($iterator as $file)
|
||||
{
|
||||
$fileName = $file->getFilename();
|
||||
|
||||
// Only load for php files.
|
||||
// Note: DirectoryIterator::getExtension only available PHP >= 5.3.6
|
||||
if (!$file->isFile()
|
||||
|| substr($fileName, strrpos($fileName, '.') + 1) != 'php'
|
||||
|| $fileName == 'helper.php')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Derive the class name from the type.
|
||||
$class = str_ireplace('.php', '', 'JCacheStorage' . ucfirst(trim($fileName)));
|
||||
|
||||
// If the class doesn't exist we have nothing left to do but look at the next type. We did our best.
|
||||
if (!class_exists($class))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sweet! Our class exists, so now we just need to know if it passes its test method.
|
||||
if ($class::isSupported())
|
||||
{
|
||||
// Connector names should not have file extensions.
|
||||
$handlers[] = str_ireplace('.php', '', $fileName);
|
||||
}
|
||||
}
|
||||
|
||||
return $handlers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set caching enabled state
|
||||
*
|
||||
* @param boolean $enabled True to enable caching
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function setCaching($enabled)
|
||||
{
|
||||
$this->_options['caching'] = $enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get caching state
|
||||
*
|
||||
* @return boolean Caching state
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function getCaching()
|
||||
{
|
||||
return $this->_options['caching'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cache lifetime
|
||||
*
|
||||
* @param integer $lt Cache lifetime
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function setLifeTime($lt)
|
||||
{
|
||||
$this->_options['lifetime'] = $lt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached data by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return mixed boolean False on failure or a cached data string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($id, $group = null)
|
||||
{
|
||||
// Get the default group
|
||||
$group = ($group) ? $group : $this->_options['defaultgroup'];
|
||||
|
||||
// Get the storage
|
||||
$handler = $this->_getStorage();
|
||||
if (!($handler instanceof Exception) && $this->_options['caching'])
|
||||
{
|
||||
return $handler->get($id, $group, $this->_options['checkTime']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all cached data
|
||||
*
|
||||
* @return mixed Boolean false on failure or an object with a list of cache groups and data
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
// Get the storage
|
||||
$handler = $this->_getStorage();
|
||||
if (!($handler instanceof Exception) && $this->_options['caching'])
|
||||
{
|
||||
return $handler->getAll();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the cached data by id and group
|
||||
*
|
||||
* @param mixed $data The data to store
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True if cache stored
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function store($data, $id, $group = null)
|
||||
{
|
||||
// Get the default group
|
||||
$group = ($group) ? $group : $this->_options['defaultgroup'];
|
||||
|
||||
// Get the storage and store the cached data
|
||||
$handler = $this->_getStorage();
|
||||
if (!($handler instanceof Exception) && $this->_options['caching'])
|
||||
{
|
||||
$handler->_lifetime = $this->_options['lifetime'];
|
||||
return $handler->store($id, $group, $data);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached data entry by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function remove($id, $group = null)
|
||||
{
|
||||
// Get the default group
|
||||
$group = ($group) ? $group : $this->_options['defaultgroup'];
|
||||
|
||||
// Get the storage
|
||||
$handler = $this->_getStorage();
|
||||
if (!($handler instanceof Exception))
|
||||
{
|
||||
return $handler->remove($id, $group);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean cache for a group given a mode.
|
||||
*
|
||||
* group mode : cleans all cache in the group
|
||||
* notgroup mode : cleans all cache not in the group
|
||||
*
|
||||
* @param string $group The cache data group
|
||||
* @param string $mode The mode for cleaning cache [group|notgroup]
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function clean($group = null, $mode = 'group')
|
||||
{
|
||||
// Get the default group
|
||||
$group = ($group) ? $group : $this->_options['defaultgroup'];
|
||||
|
||||
// Get the storage handler
|
||||
$handler = $this->_getStorage();
|
||||
if (!($handler instanceof Exception))
|
||||
{
|
||||
return $handler->clean($group, $mode);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collect expired cache data
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function gc()
|
||||
{
|
||||
// Get the storage handler
|
||||
$handler = $this->_getStorage();
|
||||
if (!($handler instanceof Exception))
|
||||
{
|
||||
return $handler->gc();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set lock flag on cached item
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param string $locktime The default locktime for locking the cache.
|
||||
*
|
||||
* @return object Properties are lock and locklooped
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function lock($id, $group = null, $locktime = null)
|
||||
{
|
||||
$returning = new stdClass;
|
||||
$returning->locklooped = false;
|
||||
|
||||
// Get the default group
|
||||
$group = ($group) ? $group : $this->_options['defaultgroup'];
|
||||
|
||||
// Get the default locktime
|
||||
$locktime = ($locktime) ? $locktime : $this->_options['locktime'];
|
||||
|
||||
// Allow storage handlers to perform locking on their own
|
||||
// NOTE drivers with lock need also unlock or unlocking will fail because of false $id
|
||||
$handler = $this->_getStorage();
|
||||
if (!($handler instanceof Exception) && $this->_options['locking'] == true && $this->_options['caching'] == true)
|
||||
{
|
||||
$locked = $handler->lock($id, $group, $locktime);
|
||||
if ($locked !== false)
|
||||
{
|
||||
return $locked;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
$curentlifetime = $this->_options['lifetime'];
|
||||
|
||||
// Set lifetime to locktime for storing in children
|
||||
$this->_options['lifetime'] = $locktime;
|
||||
|
||||
$looptime = $locktime * 10;
|
||||
$id2 = $id . '_lock';
|
||||
|
||||
if ($this->_options['locking'] == true && $this->_options['caching'] == true)
|
||||
{
|
||||
$data_lock = $this->get($id2, $group);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$data_lock = false;
|
||||
$returning->locked = false;
|
||||
}
|
||||
|
||||
if ($data_lock !== false)
|
||||
{
|
||||
$lock_counter = 0;
|
||||
|
||||
// Loop until you find that the lock has been released.
|
||||
// That implies that data get from other thread has finished
|
||||
while ($data_lock !== false)
|
||||
{
|
||||
|
||||
if ($lock_counter > $looptime)
|
||||
{
|
||||
$returning->locked = false;
|
||||
$returning->locklooped = true;
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
$data_lock = $this->get($id2, $group);
|
||||
$lock_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->_options['locking'] == true && $this->_options['caching'] == true)
|
||||
{
|
||||
$returning->locked = $this->store(1, $id2, $group);
|
||||
}
|
||||
|
||||
// Revert lifetime to previous one
|
||||
$this->_options['lifetime'] = $curentlifetime;
|
||||
|
||||
return $returning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset lock flag on cached item
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function unlock($id, $group = null)
|
||||
{
|
||||
$unlock = false;
|
||||
|
||||
// Get the default group
|
||||
$group = ($group) ? $group : $this->_options['defaultgroup'];
|
||||
|
||||
// Allow handlers to perform unlocking on their own
|
||||
$handler = $this->_getStorage();
|
||||
if (!($handler instanceof Exception) && $this->_options['caching'])
|
||||
{
|
||||
$unlocked = $handler->unlock($id, $group);
|
||||
if ($unlocked !== false)
|
||||
{
|
||||
return $unlocked;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
if ($this->_options['caching'])
|
||||
{
|
||||
$unlock = $this->remove($id . '_lock', $group);
|
||||
}
|
||||
|
||||
return $unlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cache storage handler
|
||||
*
|
||||
* @return JCacheStorage A JCacheStorage object
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function &_getStorage()
|
||||
{
|
||||
$hash = md5(serialize($this->_options));
|
||||
|
||||
if (isset(self::$_handler[$hash]))
|
||||
{
|
||||
return self::$_handler[$hash];
|
||||
}
|
||||
|
||||
self::$_handler[$hash] = JCacheStorage::getInstance($this->_options['storage'], $this->_options);
|
||||
return self::$_handler[$hash];
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform workarounds on retrieved cached data
|
||||
*
|
||||
* @param string $data Cached data
|
||||
* @param array $options Array of options
|
||||
*
|
||||
* @return string Body of cached data
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function getWorkarounds($data, $options = array())
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
$document = JFactory::getDocument();
|
||||
$body = null;
|
||||
|
||||
// Get the document head out of the cache.
|
||||
if (isset($options['mergehead']) && $options['mergehead'] == 1 && isset($data['head']) && !empty($data['head']))
|
||||
{
|
||||
$document->mergeHeadData($data['head']);
|
||||
}
|
||||
elseif (isset($data['head']) && method_exists($document, 'setHeadData'))
|
||||
{
|
||||
$document->setHeadData($data['head']);
|
||||
}
|
||||
|
||||
// If the pathway buffer is set in the cache data, get it.
|
||||
if (isset($data['pathway']) && is_array($data['pathway']))
|
||||
{
|
||||
// Push the pathway data into the pathway object.
|
||||
$pathway = $app->getPathWay();
|
||||
$pathway->setPathway($data['pathway']);
|
||||
}
|
||||
|
||||
// @todo check if the following is needed, seems like it should be in page cache
|
||||
// If a module buffer is set in the cache data, get it.
|
||||
if (isset($data['module']) && is_array($data['module']))
|
||||
{
|
||||
// Iterate through the module positions and push them into the document buffer.
|
||||
foreach ($data['module'] as $name => $contents)
|
||||
{
|
||||
$document->setBuffer($contents, 'module', $name);
|
||||
}
|
||||
}
|
||||
|
||||
// Set cached headers.
|
||||
if (isset($data['headers']) && $data['headers'])
|
||||
{
|
||||
foreach($data['headers'] as $header)
|
||||
{
|
||||
JResponse::setHeader($header['name'], $header['value']);
|
||||
}
|
||||
}
|
||||
|
||||
// The following code searches for a token in the cached page and replaces it with the
|
||||
// proper token.
|
||||
if (isset($data['body']))
|
||||
{
|
||||
$token = JSession::getFormToken();
|
||||
$search = '#<input type="hidden" name="[0-9a-f]{32}" value="1" />#';
|
||||
$replacement = '<input type="hidden" name="' . $token . '" value="1" />';
|
||||
|
||||
$data['body'] = preg_replace($search, $replacement, $data['body']);
|
||||
$body = $data['body'];
|
||||
}
|
||||
|
||||
// Get the document body out of the cache.
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create workarounded data to be cached
|
||||
*
|
||||
* @param string $data Cached data
|
||||
* @param array $options Array of options
|
||||
*
|
||||
* @return string Data to be cached
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function setWorkarounds($data, $options = array())
|
||||
{
|
||||
$loptions = array(
|
||||
'nopathway' => 0,
|
||||
'nohead' => 0,
|
||||
'nomodules' => 0,
|
||||
'modulemode' => 0,
|
||||
);
|
||||
|
||||
if (isset($options['nopathway']))
|
||||
{
|
||||
$loptions['nopathway'] = $options['nopathway'];
|
||||
}
|
||||
|
||||
if (isset($options['nohead']))
|
||||
{
|
||||
$loptions['nohead'] = $options['nohead'];
|
||||
}
|
||||
|
||||
if (isset($options['nomodules']))
|
||||
{
|
||||
$loptions['nomodules'] = $options['nomodules'];
|
||||
}
|
||||
|
||||
if (isset($options['modulemode']))
|
||||
{
|
||||
$loptions['modulemode'] = $options['modulemode'];
|
||||
}
|
||||
|
||||
$app = JFactory::getApplication();
|
||||
$document = JFactory::getDocument();
|
||||
|
||||
if ($loptions['nomodules'] != 1)
|
||||
{
|
||||
// Get the modules buffer before component execution.
|
||||
$buffer1 = $document->getBuffer();
|
||||
if (!is_array($buffer1))
|
||||
{
|
||||
$buffer1 = array();
|
||||
}
|
||||
|
||||
// Make sure the module buffer is an array.
|
||||
if (!isset($buffer1['module']) || !is_array($buffer1['module']))
|
||||
{
|
||||
$buffer1['module'] = array();
|
||||
}
|
||||
}
|
||||
|
||||
// View body data
|
||||
$cached['body'] = $data;
|
||||
|
||||
// Document head data
|
||||
if ($loptions['nohead'] != 1 && method_exists($document, 'getHeadData'))
|
||||
{
|
||||
|
||||
if ($loptions['modulemode'] == 1)
|
||||
{
|
||||
$headnow = $document->getHeadData();
|
||||
$unset = array('title', 'description', 'link', 'links', 'metaTags');
|
||||
|
||||
foreach ($unset as $un)
|
||||
{
|
||||
unset($headnow[$un]);
|
||||
unset($options['headerbefore'][$un]);
|
||||
}
|
||||
|
||||
$cached['head'] = array();
|
||||
|
||||
// Only store what this module has added
|
||||
foreach ($headnow as $now => $value)
|
||||
{
|
||||
if (isset($options['headerbefore'][$now]))
|
||||
{
|
||||
// We have to serialize the content of the arrays because the may contain other arrays which is a notice in PHP 5.4 and newer
|
||||
$nowvalue = array_map('serialize', $headnow[$now]);
|
||||
$beforevalue = array_map('serialize', $options['headerbefore'][$now]);
|
||||
$newvalue = array_diff_assoc($nowvalue, $beforevalue);
|
||||
$newvalue = array_map('unserialize', $newvalue);
|
||||
}
|
||||
else
|
||||
{
|
||||
$newvalue = $headnow[$now];
|
||||
}
|
||||
|
||||
if (!empty($newvalue))
|
||||
{
|
||||
$cached['head'][$now] = $newvalue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$cached['head'] = $document->getHeadData();
|
||||
}
|
||||
}
|
||||
|
||||
// Pathway data
|
||||
if ($app->isSite() && $loptions['nopathway'] != 1)
|
||||
{
|
||||
$pathway = $app->getPathWay();
|
||||
$cached['pathway'] = isset($data['pathway']) ? $data['pathway'] : $pathway->getPathway();
|
||||
}
|
||||
|
||||
if ($loptions['nomodules'] != 1)
|
||||
{
|
||||
// @todo Check if the following is needed, seems like it should be in page cache
|
||||
// Get the module buffer after component execution.
|
||||
$buffer2 = $document->getBuffer();
|
||||
if (!is_array($buffer2))
|
||||
{
|
||||
$buffer2 = array();
|
||||
}
|
||||
|
||||
// Make sure the module buffer is an array.
|
||||
if (!isset($buffer2['module']) || !is_array($buffer2['module']))
|
||||
{
|
||||
$buffer2['module'] = array();
|
||||
}
|
||||
|
||||
// Compare the second module buffer against the first buffer.
|
||||
$cached['module'] = array_diff_assoc($buffer2['module'], $buffer1['module']);
|
||||
}
|
||||
|
||||
// Headers data
|
||||
if (isset($options['headers']) && $options['headers'])
|
||||
{
|
||||
$cached['headers'] = JResponse::getHeaders();
|
||||
}
|
||||
|
||||
return $cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create safe id for cached data from url parameters set by plugins and framework
|
||||
*
|
||||
* @return string md5 encoded cacheid
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function makeId()
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
// Get url parameters set by plugins
|
||||
if (!empty($app->registeredurlparams))
|
||||
{
|
||||
$registeredurlparams = $app->registeredurlparams;
|
||||
}
|
||||
|
||||
// Platform defaults
|
||||
$registeredurlparams->format = 'WORD';
|
||||
$registeredurlparams->option = 'WORD';
|
||||
$registeredurlparams->view = 'WORD';
|
||||
$registeredurlparams->layout = 'WORD';
|
||||
$registeredurlparams->tpl = 'CMD';
|
||||
$registeredurlparams->id = 'INT';
|
||||
|
||||
$safeuriaddon = new stdClass;
|
||||
|
||||
foreach ($registeredurlparams as $key => $value)
|
||||
{
|
||||
$safeuriaddon->$key = $app->input->get($key, null, $value);
|
||||
}
|
||||
|
||||
return md5(serialize($safeuriaddon));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a directory where JCache should search for handlers. You may
|
||||
* either pass a string or an array of directories.
|
||||
*
|
||||
* @param string $path A path to search.
|
||||
*
|
||||
* @return array An array with directory elements
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function addIncludePath($path = '')
|
||||
{
|
||||
static $paths;
|
||||
|
||||
if (!isset($paths))
|
||||
{
|
||||
$paths = array();
|
||||
}
|
||||
if (!empty($path) && !in_array($path, $paths))
|
||||
{
|
||||
jimport('joomla.filesystem.path');
|
||||
array_unshift($paths, JPath::clean($path));
|
||||
}
|
||||
return $paths;
|
||||
}
|
||||
}
|
235
libraries/joomla/cache/controller.php
vendored
Normal file
235
libraries/joomla/cache/controller.php
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Public cache handler
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheController
|
||||
{
|
||||
/**
|
||||
* @var JCache
|
||||
* @since 11.1
|
||||
*/
|
||||
public $cache;
|
||||
|
||||
/**
|
||||
* @var array Array of options
|
||||
* @since 11.1
|
||||
*/
|
||||
public $options;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Array of options
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __construct($options)
|
||||
{
|
||||
$this->cache = new JCache($options);
|
||||
$this->options = & $this->cache->_options;
|
||||
|
||||
// Overwrite default options with given options
|
||||
foreach ($options as $option => $value)
|
||||
{
|
||||
if (isset($options[$option]))
|
||||
{
|
||||
$this->options[$option] = $options[$option];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic method to proxy JCacheControllerMethods
|
||||
*
|
||||
* @param string $name Name of the function
|
||||
* @param array $arguments Array of arguments for the function
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __call($name, $arguments)
|
||||
{
|
||||
$nazaj = call_user_func_array(array($this->cache, $name), $arguments);
|
||||
return $nazaj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a cache adapter object, always creating it
|
||||
*
|
||||
* @param string $type The cache object type to instantiate; default is output.
|
||||
* @param array $options Array of options
|
||||
*
|
||||
* @return JCache A JCache object
|
||||
*
|
||||
* @since 11.1
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function getInstance($type = 'output', $options = array())
|
||||
{
|
||||
self::addIncludePath(JPATH_PLATFORM . '/joomla/cache/controller');
|
||||
|
||||
$type = strtolower(preg_replace('/[^A-Z0-9_\.-]/i', '', $type));
|
||||
|
||||
$class = 'JCacheController' . ucfirst($type);
|
||||
|
||||
if (!class_exists($class))
|
||||
{
|
||||
// Search for the class file in the JCache include paths.
|
||||
jimport('joomla.filesystem.path');
|
||||
|
||||
if ($path = JPath::find(self::addIncludePath(), strtolower($type) . '.php'))
|
||||
{
|
||||
include_once $path;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException('Unable to load Cache Controller: ' . $type, 500);
|
||||
}
|
||||
}
|
||||
|
||||
return new $class($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set caching enabled state
|
||||
*
|
||||
* @param boolean $enabled True to enable caching
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function setCaching($enabled)
|
||||
{
|
||||
$this->cache->setCaching($enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cache lifetime
|
||||
*
|
||||
* @param integer $lt Cache lifetime
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function setLifeTime($lt)
|
||||
{
|
||||
$this->cache->setLifeTime($lt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a directory where JCache should search for controllers. You may
|
||||
* either pass a string or an array of directories.
|
||||
*
|
||||
* @param string $path A path to search.
|
||||
*
|
||||
* @return array An array with directory elements
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function addIncludePath($path = '')
|
||||
{
|
||||
static $paths;
|
||||
|
||||
if (!isset($paths))
|
||||
{
|
||||
$paths = array();
|
||||
}
|
||||
if (!empty($path) && !in_array($path, $paths))
|
||||
{
|
||||
jimport('joomla.filesystem.path');
|
||||
array_unshift($paths, JPath::clean($path));
|
||||
}
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get stored cached data by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return mixed False on no result, cached object otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($id, $group = null)
|
||||
{
|
||||
$data = $this->cache->get($id, $group);
|
||||
|
||||
if ($data === false)
|
||||
{
|
||||
$locktest = new stdClass;
|
||||
$locktest->locked = null;
|
||||
$locktest->locklooped = null;
|
||||
$locktest = $this->cache->lock($id, $group);
|
||||
if ($locktest->locked == true && $locktest->locklooped == true)
|
||||
{
|
||||
$data = $this->cache->get($id, $group);
|
||||
}
|
||||
if ($locktest->locked == true)
|
||||
{
|
||||
$this->cache->unlock($id, $group);
|
||||
}
|
||||
}
|
||||
|
||||
// Check again because we might get it from second attempt
|
||||
if ($data !== false)
|
||||
{
|
||||
// Trim to fix unserialize errors
|
||||
$data = unserialize(trim($data));
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store data to cache by id and group
|
||||
*
|
||||
* @param mixed $data The data to store
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param boolean $wrkarounds True to use wrkarounds
|
||||
*
|
||||
* @return boolean True if cache stored
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function store($data, $id, $group = null, $wrkarounds = true)
|
||||
{
|
||||
$locktest = new stdClass;
|
||||
$locktest->locked = null;
|
||||
$locktest->locklooped = null;
|
||||
|
||||
$locktest = $this->cache->lock($id, $group);
|
||||
|
||||
if ($locktest->locked == false && $locktest->locklooped == true)
|
||||
{
|
||||
$locktest = $this->cache->lock($id, $group);
|
||||
}
|
||||
|
||||
$sucess = $this->cache->store(serialize($data), $id, $group);
|
||||
|
||||
if ($locktest->locked == true)
|
||||
{
|
||||
$this->cache->unlock($id, $group);
|
||||
}
|
||||
|
||||
return $sucess;
|
||||
}
|
||||
}
|
205
libraries/joomla/cache/controller/callback.php
vendored
Normal file
205
libraries/joomla/cache/controller/callback.php
vendored
Normal file
@ -0,0 +1,205 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Joomla! Cache callback type object
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheControllerCallback extends JCacheController
|
||||
{
|
||||
/**
|
||||
* Executes a cacheable callback if not found in cache else returns cached output and result
|
||||
*
|
||||
* Since arguments to this function are read with func_get_args you can pass any number of
|
||||
* arguments to this method
|
||||
* as long as the first argument passed is the callback definition.
|
||||
*
|
||||
* The callback definition can be in several forms:
|
||||
* - Standard PHP Callback array see <http://php.net/callback> [recommended]
|
||||
* - Function name as a string eg. 'foo' for function foo()
|
||||
* - Static method name as a string eg. 'MyClass::myMethod' for method myMethod() of class MyClass
|
||||
*
|
||||
* @return mixed Result of the callback
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function call()
|
||||
{
|
||||
// Get callback and arguments
|
||||
$args = func_get_args();
|
||||
$callback = array_shift($args);
|
||||
|
||||
return $this->get($callback, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a cacheable callback if not found in cache else returns cached output and result
|
||||
*
|
||||
* @param mixed $callback Callback or string shorthand for a callback
|
||||
* @param array $args Callback arguments
|
||||
* @param string $id Cache id
|
||||
* @param boolean $wrkarounds True to use wrkarounds
|
||||
* @param array $woptions Workaround options
|
||||
*
|
||||
* @return mixed Result of the callback
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($callback, $args = array(), $id = false, $wrkarounds = false, $woptions = array())
|
||||
{
|
||||
|
||||
// Normalize callback
|
||||
if (is_array($callback))
|
||||
{
|
||||
// We have a standard php callback array -- do nothing
|
||||
}
|
||||
elseif (strstr($callback, '::'))
|
||||
{
|
||||
// This is shorthand for a static method callback classname::methodname
|
||||
list ($class, $method) = explode('::', $callback);
|
||||
$callback = array(trim($class), trim($method));
|
||||
}
|
||||
elseif (strstr($callback, '->'))
|
||||
{
|
||||
/*
|
||||
* This is a really not so smart way of doing this... we provide this for backward compatability but this
|
||||
* WILL! disappear in a future version. If you are using this syntax change your code to use the standard
|
||||
* PHP callback array syntax: <http://php.net/callback>
|
||||
*
|
||||
* We have to use some silly global notation to pull it off and this is very unreliable
|
||||
*/
|
||||
list ($object_123456789, $method) = explode('->', $callback);
|
||||
global $$object_123456789;
|
||||
$callback = array($$object_123456789, $method);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have just a standard function -- do nothing
|
||||
}
|
||||
|
||||
if (!$id)
|
||||
{
|
||||
// Generate an ID
|
||||
$id = $this->_makeId($callback, $args);
|
||||
}
|
||||
|
||||
$data = $this->cache->get($id);
|
||||
|
||||
$locktest = new stdClass;
|
||||
$locktest->locked = null;
|
||||
$locktest->locklooped = null;
|
||||
|
||||
if ($data === false)
|
||||
{
|
||||
$locktest = $this->cache->lock($id);
|
||||
if ($locktest->locked == true && $locktest->locklooped == true)
|
||||
{
|
||||
$data = $this->cache->get($id);
|
||||
}
|
||||
}
|
||||
|
||||
$coptions = array();
|
||||
|
||||
if ($data !== false)
|
||||
{
|
||||
|
||||
$cached = unserialize(trim($data));
|
||||
$coptions['mergehead'] = isset($woptions['mergehead']) ? $woptions['mergehead'] : 0;
|
||||
$output = ($wrkarounds == false) ? $cached['output'] : JCache::getWorkarounds($cached['output'], $coptions);
|
||||
$result = $cached['result'];
|
||||
if ($locktest->locked == true)
|
||||
{
|
||||
$this->cache->unlock($id);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (!is_array($args))
|
||||
{
|
||||
$Args = !empty($args) ? array(&$args) : array();
|
||||
}
|
||||
else
|
||||
{
|
||||
$Args = &$args;
|
||||
}
|
||||
|
||||
if ($locktest->locked == false)
|
||||
{
|
||||
$locktest = $this->cache->lock($id);
|
||||
}
|
||||
|
||||
if (isset($woptions['modulemode']) && $woptions['modulemode'] == 1)
|
||||
{
|
||||
$document = JFactory::getDocument();
|
||||
$coptions['modulemode'] = 1;
|
||||
$coptions['headerbefore'] = $document->getHeadData();
|
||||
}
|
||||
else
|
||||
{
|
||||
$coptions['modulemode'] = 0;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
$result = call_user_func_array($callback, $Args);
|
||||
$output = ob_get_contents();
|
||||
|
||||
ob_end_clean();
|
||||
|
||||
$cached = array();
|
||||
|
||||
$coptions['nopathway'] = isset($woptions['nopathway']) ? $woptions['nopathway'] : 1;
|
||||
$coptions['nohead'] = isset($woptions['nohead']) ? $woptions['nohead'] : 1;
|
||||
$coptions['nomodules'] = isset($woptions['nomodules']) ? $woptions['nomodules'] : 1;
|
||||
|
||||
$cached['output'] = ($wrkarounds == false) ? $output : JCache::setWorkarounds($output, $coptions);
|
||||
$cached['result'] = $result;
|
||||
|
||||
// Store the cache data
|
||||
$this->cache->store(serialize($cached), $id);
|
||||
if ($locktest->locked == true)
|
||||
{
|
||||
$this->cache->unlock($id);
|
||||
}
|
||||
}
|
||||
|
||||
echo $output;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a callback cache id
|
||||
*
|
||||
* @param callback $callback Callback to cache
|
||||
* @param array $args Arguments to the callback method to cache
|
||||
*
|
||||
* @return string MD5 Hash : function cache id
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _makeId($callback, $args)
|
||||
{
|
||||
if (is_array($callback) && is_object($callback[0]))
|
||||
{
|
||||
$vars = get_object_vars($callback[0]);
|
||||
$vars[] = strtolower(get_class($callback[0]));
|
||||
$callback[0] = $vars;
|
||||
}
|
||||
|
||||
return md5(serialize(array($callback, $args)));
|
||||
}
|
||||
}
|
1
libraries/joomla/cache/controller/index.html
vendored
Normal file
1
libraries/joomla/cache/controller/index.html
vendored
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
122
libraries/joomla/cache/controller/output.php
vendored
Normal file
122
libraries/joomla/cache/controller/output.php
vendored
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Joomla Cache output type object
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheControllerOutput extends JCacheController
|
||||
{
|
||||
/**
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $_id;
|
||||
|
||||
/**
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $_group;
|
||||
|
||||
/**
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $_locktest = null;
|
||||
|
||||
/**
|
||||
* Start the cache
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True if the cache is hit (false else)
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function start($id, $group = null)
|
||||
{
|
||||
// If we have data in cache use that.
|
||||
$data = $this->cache->get($id, $group);
|
||||
|
||||
$this->_locktest = new stdClass;
|
||||
$this->_locktest->locked = null;
|
||||
$this->_locktest->locklooped = null;
|
||||
|
||||
if ($data === false)
|
||||
{
|
||||
$this->_locktest = $this->cache->lock($id, $group);
|
||||
if ($this->_locktest->locked == true && $this->_locktest->locklooped == true)
|
||||
{
|
||||
$data = $this->cache->get($id, $group);
|
||||
}
|
||||
}
|
||||
|
||||
if ($data !== false)
|
||||
{
|
||||
$data = unserialize(trim($data));
|
||||
echo $data;
|
||||
if ($this->_locktest->locked == true)
|
||||
{
|
||||
$this->cache->unlock($id, $group);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing in cache... let's start the output buffer and start collecting data for next time.
|
||||
if ($this->_locktest->locked == false)
|
||||
{
|
||||
$this->_locktest = $this->cache->lock($id, $group);
|
||||
}
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
|
||||
// Set id and group placeholders
|
||||
$this->_id = $id;
|
||||
$this->_group = $group;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the cache buffer and store the cached data
|
||||
*
|
||||
* @return boolean True if cache stored
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function end()
|
||||
{
|
||||
// Get data from output buffer and echo it
|
||||
$data = ob_get_contents();
|
||||
ob_end_clean();
|
||||
echo $data;
|
||||
|
||||
// Get id and group and reset them placeholders
|
||||
$id = $this->_id;
|
||||
$group = $this->_group;
|
||||
$this->_id = null;
|
||||
$this->_group = null;
|
||||
|
||||
// Get the storage handler and store the cached data
|
||||
$ret = $this->cache->store(serialize($data), $id, $group);
|
||||
|
||||
if ($this->_locktest->locked == true)
|
||||
{
|
||||
$this->cache->unlock($id, $group);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
}
|
211
libraries/joomla/cache/controller/page.php
vendored
Normal file
211
libraries/joomla/cache/controller/page.php
vendored
Normal file
@ -0,0 +1,211 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Joomla! Cache page type object
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheControllerPage extends JCacheController
|
||||
{
|
||||
/**
|
||||
* @var integer ID property for the cache page object.
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $_id;
|
||||
|
||||
/**
|
||||
* @var string Cache group
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $_group;
|
||||
|
||||
/**
|
||||
* @var object Cache lock test
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $_locktest = null;
|
||||
|
||||
/**
|
||||
* Get the cached page data
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True if the cache is hit (false else)
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($id = false, $group = 'page')
|
||||
{
|
||||
// If an id is not given, generate it from the request
|
||||
if ($id == false)
|
||||
{
|
||||
$id = $this->_makeId();
|
||||
}
|
||||
|
||||
// If the etag matches the page id ... set a no change header and exit : utilize browser cache
|
||||
if (!headers_sent() && isset($_SERVER['HTTP_IF_NONE_MATCH']))
|
||||
{
|
||||
$etag = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']);
|
||||
if ($etag == $id)
|
||||
{
|
||||
$browserCache = isset($this->options['browsercache']) ? $this->options['browsercache'] : false;
|
||||
if ($browserCache)
|
||||
{
|
||||
$this->_noChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We got a cache hit... set the etag header and echo the page data
|
||||
$data = $this->cache->get($id, $group);
|
||||
|
||||
$this->_locktest = new stdClass;
|
||||
$this->_locktest->locked = null;
|
||||
$this->_locktest->locklooped = null;
|
||||
|
||||
if ($data === false)
|
||||
{
|
||||
$this->_locktest = $this->cache->lock($id, $group);
|
||||
if ($this->_locktest->locked == true && $this->_locktest->locklooped == true)
|
||||
{
|
||||
$data = $this->cache->get($id, $group);
|
||||
}
|
||||
}
|
||||
|
||||
if ($data !== false)
|
||||
{
|
||||
$data = unserialize(trim($data));
|
||||
|
||||
$data = JCache::getWorkarounds($data);
|
||||
|
||||
$this->_setEtag($id);
|
||||
if ($this->_locktest->locked == true)
|
||||
{
|
||||
$this->cache->unlock($id, $group);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
// Set id and group placeholders
|
||||
$this->_id = $id;
|
||||
$this->_group = $group;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the cache buffer and store the cached data
|
||||
*
|
||||
* @param mixed $data The data to store
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param boolean $wrkarounds True to use wrkarounds
|
||||
*
|
||||
* @return boolean True if cache stored
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function store($data, $id, $group = null, $wrkarounds = true)
|
||||
{
|
||||
// Get page data from JResponse
|
||||
if (empty($data))
|
||||
{
|
||||
$data = JResponse::getBody();
|
||||
}
|
||||
|
||||
// Get id and group and reset the placeholders
|
||||
if (empty($id))
|
||||
{
|
||||
$id = $this->_id;
|
||||
}
|
||||
if (empty($group))
|
||||
{
|
||||
$group = $this->_group;
|
||||
}
|
||||
|
||||
// Only attempt to store if page data exists
|
||||
if ($data)
|
||||
{
|
||||
if ($wrkarounds) {
|
||||
$data = JCache::setWorkarounds($data, array(
|
||||
'nopathway' => 1,
|
||||
'nohead' => 1,
|
||||
'nomodules' => 1,
|
||||
'headers' => true
|
||||
));
|
||||
}
|
||||
|
||||
if ($this->_locktest->locked == false)
|
||||
{
|
||||
$this->_locktest = $this->cache->lock($id, $group);
|
||||
}
|
||||
|
||||
$sucess = $this->cache->store(serialize($data), $id, $group);
|
||||
|
||||
if ($this->_locktest->locked == true)
|
||||
{
|
||||
$this->cache->unlock($id, $group);
|
||||
}
|
||||
|
||||
return $sucess;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a page cache id
|
||||
*
|
||||
* @return string MD5 Hash : page cache id
|
||||
*
|
||||
* @since 11.1
|
||||
* @todo Discuss whether this should be coupled to a data hash or a request
|
||||
* hash ... perhaps hashed with a serialized request
|
||||
*/
|
||||
protected function _makeId()
|
||||
{
|
||||
return JCache::makeId();
|
||||
}
|
||||
|
||||
/**
|
||||
* There is no change in page data so send an
|
||||
* unmodified header and die gracefully
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _noChange()
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
// Send not modified header and exit gracefully
|
||||
header('HTTP/1.x 304 Not Modified', true);
|
||||
$app->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ETag header in the response
|
||||
*
|
||||
* @param string $etag The entity tag (etag) to set
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _setEtag($etag)
|
||||
{
|
||||
JResponse::setHeader('ETag', $etag, true);
|
||||
}
|
||||
}
|
135
libraries/joomla/cache/controller/view.php
vendored
Normal file
135
libraries/joomla/cache/controller/view.php
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Joomla! Cache view type object
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheControllerView extends JCacheController
|
||||
{
|
||||
/**
|
||||
* Get the cached view data
|
||||
*
|
||||
* @param object &$view The view object to cache output for
|
||||
* @param string $method The method name of the view method to cache output for
|
||||
* @param string $id The cache data id
|
||||
* @param boolean $wrkarounds True to enable workarounds.
|
||||
*
|
||||
* @return boolean True if the cache is hit (false else)
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get( $view, $method = 'display' , $id = false, $wrkarounds = true )
|
||||
{
|
||||
// If an id is not given generate it from the request
|
||||
if ($id == false)
|
||||
{
|
||||
$id = $this->_makeId($view, $method);
|
||||
}
|
||||
|
||||
$data = $this->cache->get($id);
|
||||
|
||||
$locktest = new stdClass;
|
||||
$locktest->locked = null;
|
||||
$locktest->locklooped = null;
|
||||
|
||||
if ($data === false)
|
||||
{
|
||||
$locktest = $this->cache->lock($id, null);
|
||||
|
||||
// If the loop is completed and returned true it means the lock has been set.
|
||||
// If looped is true try to get the cached data again; it could exist now.
|
||||
if ($locktest->locked == true && $locktest->locklooped == true)
|
||||
{
|
||||
$data = $this->cache->get($id);
|
||||
}
|
||||
|
||||
// False means that locking is either turned off or maxtime has been exceeded.
|
||||
// Execute the view.
|
||||
}
|
||||
|
||||
if ($data !== false)
|
||||
{
|
||||
$data = unserialize(trim($data));
|
||||
|
||||
if ($wrkarounds === true)
|
||||
{
|
||||
echo JCache::getWorkarounds($data);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No workarounds, so all data is stored in one piece
|
||||
echo (isset($data)) ? $data : null;
|
||||
}
|
||||
|
||||
if ($locktest->locked == true)
|
||||
{
|
||||
$this->cache->unlock($id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* No hit so we have to execute the view
|
||||
*/
|
||||
if (method_exists($view, $method))
|
||||
{
|
||||
// If previous lock failed try again
|
||||
if ($locktest->locked == false)
|
||||
{
|
||||
$locktest = $this->cache->lock($id);
|
||||
}
|
||||
|
||||
// Capture and echo output
|
||||
ob_start();
|
||||
ob_implicit_flush(false);
|
||||
$view->$method();
|
||||
$data = ob_get_contents();
|
||||
ob_end_clean();
|
||||
echo $data;
|
||||
|
||||
/*
|
||||
* For a view we have a special case. We need to cache not only the output from the view, but the state
|
||||
* of the document head after the view has been rendered. This will allow us to properly cache any attached
|
||||
* scripts or stylesheets or links or any other modifications that the view has made to the document object
|
||||
*/
|
||||
$cached = $wrkarounds == true ? JCache::setWorkarounds($data) : $data;
|
||||
|
||||
// Store the cache data
|
||||
$this->cache->store(serialize($cached), $id);
|
||||
|
||||
if ($locktest->locked == true)
|
||||
{
|
||||
$this->cache->unlock($id);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a view cache id.
|
||||
*
|
||||
* @param object &$view The view object to cache output for
|
||||
* @param string $method The method name to cache for the view object
|
||||
*
|
||||
* @return string MD5 Hash : view cache id
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _makeId(&$view, $method)
|
||||
{
|
||||
return md5(serialize(array(JCache::makeId(), get_class($view), $method)));
|
||||
}
|
||||
}
|
1
libraries/joomla/cache/index.html
vendored
Normal file
1
libraries/joomla/cache/index.html
vendored
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
346
libraries/joomla/cache/storage.php
vendored
Normal file
346
libraries/joomla/cache/storage.php
vendored
Normal file
@ -0,0 +1,346 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Abstract cache storage handler
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheStorage
|
||||
{
|
||||
/**
|
||||
* @var string Rawname
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $rawname;
|
||||
|
||||
/**
|
||||
* @var datetime Now
|
||||
* @since 11.1
|
||||
*/
|
||||
public $_now;
|
||||
|
||||
/**
|
||||
* @var integer Cache lifetime
|
||||
* @since 11.1
|
||||
*/
|
||||
public $_lifetime;
|
||||
|
||||
/**
|
||||
* @var boolean Locking
|
||||
* @since 11.1
|
||||
*/
|
||||
public $_locking;
|
||||
|
||||
/**
|
||||
* @var string Language
|
||||
* @since 11.1
|
||||
*/
|
||||
public $_language;
|
||||
|
||||
/**
|
||||
* @var string Application name.
|
||||
* @since 11.1
|
||||
*/
|
||||
public $_application;
|
||||
|
||||
/**
|
||||
* @var string Hash
|
||||
* @since 11.1
|
||||
*/
|
||||
public $_hash;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Optional parameters
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __construct($options = array())
|
||||
{
|
||||
$config = JFactory::getConfig();
|
||||
$this->_hash = md5($config->get('secret'));
|
||||
$this->_application = (isset($options['application'])) ? $options['application'] : null;
|
||||
$this->_language = (isset($options['language'])) ? $options['language'] : 'en-GB';
|
||||
$this->_locking = (isset($options['locking'])) ? $options['locking'] : true;
|
||||
$this->_lifetime = (isset($options['lifetime'])) ? $options['lifetime'] * 60 : $config->get('cachetime') * 60;
|
||||
$this->_now = (isset($options['now'])) ? $options['now'] : time();
|
||||
|
||||
// Set time threshold value. If the lifetime is not set, default to 60 (0 is BAD)
|
||||
// _threshold is now available ONLY as a legacy (it's deprecated). It's no longer used in the core.
|
||||
if (empty($this->_lifetime))
|
||||
{
|
||||
$this->_threshold = $this->_now - 60;
|
||||
$this->_lifetime = 60;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->_threshold = $this->_now - $this->_lifetime;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cache storage handler object, only creating it
|
||||
* if it doesn't already exist.
|
||||
*
|
||||
* @param string $handler The cache storage handler to instantiate
|
||||
* @param array $options Array of handler options
|
||||
*
|
||||
* @return JCacheStorage A JCacheStorage instance
|
||||
*
|
||||
* @since 11.1
|
||||
* @throws UnexpectedValueException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public static function getInstance($handler = null, $options = array())
|
||||
{
|
||||
static $now = null;
|
||||
|
||||
self::addIncludePath(JPATH_PLATFORM . '/joomla/cache/storage');
|
||||
|
||||
if (!isset($handler))
|
||||
{
|
||||
$conf = JFactory::getConfig();
|
||||
$handler = $conf->get('cache_handler');
|
||||
if (empty($handler))
|
||||
{
|
||||
throw new UnexpectedValueException('Cache Storage Handler not set.');
|
||||
}
|
||||
}
|
||||
|
||||
if (is_null($now))
|
||||
{
|
||||
$now = time();
|
||||
}
|
||||
|
||||
$options['now'] = $now;
|
||||
|
||||
// We can't cache this since options may change...
|
||||
$handler = strtolower(preg_replace('/[^A-Z0-9_\.-]/i', '', $handler));
|
||||
|
||||
$class = 'JCacheStorage' . ucfirst($handler);
|
||||
if (!class_exists($class))
|
||||
{
|
||||
// Search for the class file in the JCacheStorage include paths.
|
||||
jimport('joomla.filesystem.path');
|
||||
if ($path = JPath::find(self::addIncludePath(), strtolower($handler) . '.php'))
|
||||
{
|
||||
include_once $path;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new RuntimeException(sprintf('Unable to load Cache Storage: %s', $handler));
|
||||
}
|
||||
}
|
||||
|
||||
return new $class($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached data by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param boolean $checkTime True to verify cache time expiration threshold
|
||||
*
|
||||
* @return mixed Boolean false on failure or a cached data object
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($id, $group, $checkTime = true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cached data
|
||||
*
|
||||
* @return mixed Boolean false on failure or a cached data object
|
||||
*
|
||||
* @since 11.1
|
||||
* @todo Review this method. The docblock doesn't fit what it actually does.
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
if (!class_exists('JCacheStorageHelper', false))
|
||||
{
|
||||
include_once JPATH_PLATFORM . '/joomla/cache/storage/helper.php';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data to cache by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param string $data The data to store in cache
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function store($id, $group, $data)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached data entry by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function remove($id, $group)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean cache for a group given a mode.
|
||||
*
|
||||
* @param string $group The cache data group
|
||||
* @param string $mode The mode for cleaning cache [group|notgroup]
|
||||
* group mode : cleans all cache in the group
|
||||
* notgroup mode : cleans all cache not in the group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function clean($group, $mode = null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collect expired cache data
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function gc()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the storage handler is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 12.1.
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the storage handler is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
* @deprecated 12.3 (Platform) & 4.0 (CMS)
|
||||
*/
|
||||
public static function test()
|
||||
{
|
||||
JLog::add('JCacheStorage::test() is deprecated. Use JCacheStorage::isSupported() instead.', JLog::WARNING, 'deprecated');
|
||||
|
||||
return static::isSupported();
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock cached item
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param integer $locktime Cached item max lock time
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function lock($id, $group, $locktime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock cached item
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function unlock($id, $group = null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cache_id string from an id/group pair
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return string The cache_id string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _getCacheId($id, $group)
|
||||
{
|
||||
$name = md5($this->_application . '-' . $id . '-' . $this->_language);
|
||||
$this->rawname = $this->_hash . '-' . $name;
|
||||
return $this->_hash . '-cache-' . $group . '-' . $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a directory where JCacheStorage should search for handlers. You may
|
||||
* either pass a string or an array of directories.
|
||||
*
|
||||
* @param string $path A path to search.
|
||||
*
|
||||
* @return array An array with directory elements
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public static function addIncludePath($path = '')
|
||||
{
|
||||
static $paths;
|
||||
|
||||
if (!isset($paths))
|
||||
{
|
||||
$paths = array();
|
||||
}
|
||||
|
||||
if (!empty($path) && !in_array($path, $paths))
|
||||
{
|
||||
jimport('joomla.filesystem.path');
|
||||
array_unshift($paths, JPath::clean($path));
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
}
|
248
libraries/joomla/cache/storage/apc.php
vendored
Normal file
248
libraries/joomla/cache/storage/apc.php
vendored
Normal file
@ -0,0 +1,248 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* APC cache storage handler
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @see http://php.net/manual/en/book.apc.php
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheStorageApc extends JCacheStorage
|
||||
{
|
||||
/**
|
||||
* Get cached data from APC by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param boolean $checkTime True to verify cache time expiration threshold
|
||||
*
|
||||
* @return mixed Boolean False on failure or a cached data string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($id, $group, $checkTime = true)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
return apc_fetch($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cached data
|
||||
*
|
||||
* @return array data
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
parent::getAll();
|
||||
|
||||
$allinfo = apc_cache_info('user');
|
||||
$keys = $allinfo['cache_list'];
|
||||
$secret = $this->_hash;
|
||||
|
||||
$data = array();
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
|
||||
$name = $key['info'];
|
||||
$namearr = explode('-', $name);
|
||||
|
||||
if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
|
||||
{
|
||||
$group = $namearr[2];
|
||||
|
||||
if (!isset($data[$group]))
|
||||
{
|
||||
$item = new JCacheStorageHelper($group);
|
||||
}
|
||||
else
|
||||
{
|
||||
$item = $data[$group];
|
||||
}
|
||||
|
||||
$item->updateSize($key['mem_size'] / 1024);
|
||||
|
||||
$data[$group] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data to APC by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param string $data The data to store in cache
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function store($id, $group, $data)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
return apc_store($cache_id, $data, $this->_lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached data entry by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function remove($id, $group)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
return apc_delete($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean cache for a group given a mode.
|
||||
*
|
||||
* group mode : cleans all cache in the group
|
||||
* notgroup mode : cleans all cache not in the group
|
||||
*
|
||||
* @param string $group The cache data group
|
||||
* @param string $mode The mode for cleaning cache [group|notgroup]
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function clean($group, $mode = null)
|
||||
{
|
||||
$allinfo = apc_cache_info('user');
|
||||
$keys = $allinfo['cache_list'];
|
||||
$secret = $this->_hash;
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
|
||||
if (strpos($key['info'], $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
|
||||
{
|
||||
apc_delete($key['info']);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force garbage collect expired cache data as items are removed only on fetch!
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function gc()
|
||||
{
|
||||
$allinfo = apc_cache_info('user');
|
||||
$keys = $allinfo['cache_list'];
|
||||
$secret = $this->_hash;
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if (strpos($key['info'], $secret . '-cache-'))
|
||||
{
|
||||
apc_fetch($key['info']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the cache storage is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
return extension_loaded('apc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock cached item - override parent as this is more efficient
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param integer $locktime Cached item max lock time
|
||||
*
|
||||
* @return object Properties are lock and locklooped
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function lock($id, $group, $locktime)
|
||||
{
|
||||
$returning = new stdClass;
|
||||
$returning->locklooped = false;
|
||||
|
||||
$looptime = $locktime * 10;
|
||||
|
||||
$cache_id = $this->_getCacheId($id, $group) . '_lock';
|
||||
|
||||
$data_lock = apc_add($cache_id, 1, $locktime);
|
||||
|
||||
if ($data_lock === false)
|
||||
{
|
||||
|
||||
$lock_counter = 0;
|
||||
|
||||
// Loop until you find that the lock has been released.
|
||||
// That implies that data get from other thread has finished
|
||||
while ($data_lock === false)
|
||||
{
|
||||
|
||||
if ($lock_counter > $looptime)
|
||||
{
|
||||
$returning->locked = false;
|
||||
$returning->locklooped = true;
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
$data_lock = apc_add($cache_id, 1, $locktime);
|
||||
$lock_counter++;
|
||||
}
|
||||
|
||||
}
|
||||
$returning->locked = $data_lock;
|
||||
|
||||
return $returning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock cached item - override parent for cacheid compatibility with lock
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function unlock($id, $group = null)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group) . '_lock';
|
||||
|
||||
$unlock = apc_delete($cache_id);
|
||||
return $unlock;
|
||||
}
|
||||
}
|
336
libraries/joomla/cache/storage/cachelite.php
vendored
Normal file
336
libraries/joomla/cache/storage/cachelite.php
vendored
Normal file
@ -0,0 +1,336 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Cache lite storage handler
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @see http://pear.php.net/package/Cache_Lite/
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheStorageCachelite extends JCacheStorage
|
||||
{
|
||||
/**
|
||||
* @var object
|
||||
* @since 11.1
|
||||
*/
|
||||
protected static $CacheLiteInstance = null;
|
||||
|
||||
/**
|
||||
* @var
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $_root;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Optional parameters.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __construct($options = array())
|
||||
{
|
||||
parent::__construct($options);
|
||||
|
||||
$this->_root = $options['cachebase'];
|
||||
|
||||
$cloptions = array(
|
||||
'cacheDir' => $this->_root . '/',
|
||||
'lifeTime' => $this->_lifetime,
|
||||
'fileLocking' => $this->_locking,
|
||||
'automaticCleaningFactor' => isset($options['autoclean']) ? $options['autoclean'] : 200,
|
||||
'fileNameProtection' => false,
|
||||
'hashedDirectoryLevel' => 0,
|
||||
'caching' => $options['caching']);
|
||||
|
||||
if (self::$CacheLiteInstance === null)
|
||||
{
|
||||
$this->initCache($cloptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates the appropriate CacheLite object.
|
||||
* Only initializes the engine if it does not already exist.
|
||||
* Note this is a protected method
|
||||
*
|
||||
* @param array $cloptions optional parameters
|
||||
*
|
||||
* @return object
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function initCache($cloptions)
|
||||
{
|
||||
require_once 'Cache/Lite.php';
|
||||
|
||||
self::$CacheLiteInstance = new Cache_Lite($cloptions);
|
||||
|
||||
return self::$CacheLiteInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached data from a file by id and group
|
||||
*
|
||||
* @param string $id The cache data id.
|
||||
* @param string $group The cache data group.
|
||||
* @param boolean $checkTime True to verify cache time expiration threshold.
|
||||
*
|
||||
* @return mixed Boolean false on failure or a cached data string.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($id, $group, $checkTime = true)
|
||||
{
|
||||
self::$CacheLiteInstance->setOption('cacheDir', $this->_root . '/' . $group . '/');
|
||||
$this->_getCacheId($id, $group);
|
||||
$data = self::$CacheLiteInstance->get($this->rawname, $group);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cached data
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
parent::getAll();
|
||||
|
||||
$path = $this->_root;
|
||||
$folders = new DirectoryIterator($path);
|
||||
$data = array();
|
||||
|
||||
foreach ($folders as $folder)
|
||||
{
|
||||
if (!$folder->isDir() || $folder->isDot())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$foldername = $folder->getFilename();
|
||||
|
||||
$files = new DirectoryIterator($path . '/' . $foldername);
|
||||
$item = new JCacheStorageHelper($foldername);
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
if (!$file->isFile())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$filename = $file->getFilename();
|
||||
|
||||
$item->updateSize(filesize($path . '/' . $foldername . '/' . $filename) / 1024);
|
||||
}
|
||||
|
||||
$data[$foldername] = $item;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data to a file by id and group
|
||||
*
|
||||
* @param string $id The cache data id.
|
||||
* @param string $group The cache data group.
|
||||
* @param string $data The data to store in cache.
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function store($id, $group, $data)
|
||||
{
|
||||
$dir = $this->_root . '/' . $group;
|
||||
|
||||
// If the folder doesn't exist try to create it
|
||||
if (!is_dir($dir))
|
||||
{
|
||||
// Make sure the index file is there
|
||||
$indexFile = $dir . '/index.html';
|
||||
@mkdir($dir) && file_put_contents($indexFile, '<!DOCTYPE html><title></title>');
|
||||
}
|
||||
|
||||
// Make sure the folder exists
|
||||
if (!is_dir($dir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$CacheLiteInstance->setOption('cacheDir', $this->_root . '/' . $group . '/');
|
||||
$this->_getCacheId($id, $group);
|
||||
$success = self::$CacheLiteInstance->save($data, $this->rawname, $group);
|
||||
|
||||
if ($success == true)
|
||||
{
|
||||
return $success;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached data file by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function remove($id, $group)
|
||||
{
|
||||
self::$CacheLiteInstance->setOption('cacheDir', $this->_root . '/' . $group . '/');
|
||||
$this->_getCacheId($id, $group);
|
||||
$success = self::$CacheLiteInstance->remove($this->rawname, $group);
|
||||
|
||||
if ($success == true)
|
||||
{
|
||||
return $success;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean cache for a group given a mode.
|
||||
*
|
||||
* @param string $group The cache data group.
|
||||
* @param string $mode The mode for cleaning cache [group|notgroup].
|
||||
* group mode : cleans all cache in the group
|
||||
* notgroup mode : cleans all cache not in the group
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function clean($group, $mode = null)
|
||||
{
|
||||
jimport('joomla.filesystem.folder');
|
||||
|
||||
switch ($mode)
|
||||
{
|
||||
case 'notgroup':
|
||||
$clmode = 'notingroup';
|
||||
$success = self::$CacheLiteInstance->clean($group, $clmode);
|
||||
break;
|
||||
|
||||
case 'group':
|
||||
if (is_dir($this->_root . '/' . $group))
|
||||
{
|
||||
$clmode = $group;
|
||||
self::$CacheLiteInstance->setOption('cacheDir', $this->_root . '/' . $group . '/');
|
||||
$success = self::$CacheLiteInstance->clean($group, $clmode);
|
||||
JFolder::delete($this->_root . '/' . $group);
|
||||
}
|
||||
else
|
||||
{
|
||||
$success = true;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (is_dir($this->_root . '/' . $group))
|
||||
{
|
||||
$clmode = $group;
|
||||
self::$CacheLiteInstance->setOption('cacheDir', $this->_root . '/' . $group . '/');
|
||||
$success = self::$CacheLiteInstance->clean($group, $clmode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$success = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($success == true)
|
||||
{
|
||||
return $success;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collect expired cache data
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function gc()
|
||||
{
|
||||
$result = true;
|
||||
self::$CacheLiteInstance->setOption('automaticCleaningFactor', 1);
|
||||
self::$CacheLiteInstance->setOption('hashedDirectoryLevel', 1);
|
||||
$success1 = self::$CacheLiteInstance->_cleanDir($this->_root . '/', false, 'old');
|
||||
|
||||
if (!($dh = opendir($this->_root . '/')))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while ($file = readdir($dh))
|
||||
{
|
||||
if (($file != '.') && ($file != '..') && ($file != '.svn'))
|
||||
{
|
||||
$file2 = $this->_root . '/' . $file;
|
||||
|
||||
if (is_dir($file2))
|
||||
{
|
||||
$result = ($result && (self::$CacheLiteInstance->_cleanDir($file2 . '/', false, 'old')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$success = ($success1 && $result);
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the cache storage is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
@include_once 'Cache/Lite.php';
|
||||
|
||||
if (class_exists('Cache_Lite'))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
689
libraries/joomla/cache/storage/file.php
vendored
Normal file
689
libraries/joomla/cache/storage/file.php
vendored
Normal file
@ -0,0 +1,689 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* File cache storage handler
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheStorageFile extends JCacheStorage
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $_root;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Optional parameters
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __construct($options = array())
|
||||
{
|
||||
parent::__construct($options);
|
||||
$this->_root = $options['cachebase'];
|
||||
}
|
||||
|
||||
// NOTE: raw php calls are up to 100 times faster than JFile or JFolder
|
||||
|
||||
/**
|
||||
* Get cached data from a file by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param boolean $checkTime True to verify cache time expiration threshold
|
||||
*
|
||||
* @return mixed Boolean false on failure or a cached data string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($id, $group, $checkTime = true)
|
||||
{
|
||||
$data = false;
|
||||
|
||||
$path = $this->_getFilePath($id, $group);
|
||||
|
||||
if ($checkTime == false || ($checkTime == true && $this->_checkExpire($id, $group) === true))
|
||||
{
|
||||
if (file_exists($path))
|
||||
{
|
||||
$data = file_get_contents($path);
|
||||
if ($data)
|
||||
{
|
||||
// Remove the initial die() statement
|
||||
$data = str_replace('<?php die("Access Denied"); ?>#x#', '', $data);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cached data
|
||||
*
|
||||
* @return array The cached data
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
parent::getAll();
|
||||
|
||||
$path = $this->_root;
|
||||
$folders = $this->_folders($path);
|
||||
$data = array();
|
||||
|
||||
foreach ($folders as $folder)
|
||||
{
|
||||
$files = $this->_filesInFolder($path . '/' . $folder);
|
||||
$item = new JCacheStorageHelper($folder);
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
$item->updateSize(filesize($path . '/' . $folder . '/' . $file) / 1024);
|
||||
}
|
||||
$data[$folder] = $item;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data to a file by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param string $data The data to store in cache
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function store($id, $group, $data)
|
||||
{
|
||||
$written = false;
|
||||
$path = $this->_getFilePath($id, $group);
|
||||
$die = '<?php die("Access Denied"); ?>#x#';
|
||||
|
||||
// Prepend a die string
|
||||
$data = $die . $data;
|
||||
|
||||
$_fileopen = @fopen($path, "wb");
|
||||
|
||||
if ($_fileopen)
|
||||
{
|
||||
$len = strlen($data);
|
||||
@fwrite($_fileopen, $data, $len);
|
||||
$written = true;
|
||||
}
|
||||
|
||||
// Data integrity check
|
||||
if ($written && ($data == file_get_contents($path)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached data file by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function remove($id, $group)
|
||||
{
|
||||
$path = $this->_getFilePath($id, $group);
|
||||
if (!@unlink($path))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean cache for a group given a mode.
|
||||
*
|
||||
* @param string $group The cache data group
|
||||
* @param string $mode The mode for cleaning cache [group|notgroup]
|
||||
* group mode : cleans all cache in the group
|
||||
* notgroup mode : cleans all cache not in the group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function clean($group, $mode = null)
|
||||
{
|
||||
$return = true;
|
||||
$folder = $group;
|
||||
|
||||
if (trim($folder) == '')
|
||||
{
|
||||
$mode = 'notgroup';
|
||||
}
|
||||
|
||||
switch ($mode)
|
||||
{
|
||||
case 'notgroup':
|
||||
$folders = $this->_folders($this->_root);
|
||||
for ($i = 0, $n = count($folders); $i < $n; $i++)
|
||||
{
|
||||
if ($folders[$i] != $folder)
|
||||
{
|
||||
$return |= $this->_deleteFolder($this->_root . '/' . $folders[$i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'group':
|
||||
default:
|
||||
if (is_dir($this->_root . '/' . $folder))
|
||||
{
|
||||
$return = $this->_deleteFolder($this->_root . '/' . $folder);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collect expired cache data
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function gc()
|
||||
{
|
||||
$result = true;
|
||||
|
||||
// Files older than lifeTime get deleted from cache
|
||||
$files = $this->_filesInFolder($this->_root, '', true, true, array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html'));
|
||||
foreach ($files as $file)
|
||||
{
|
||||
$time = @filemtime($file);
|
||||
if (($time + $this->_lifetime) < $this->_now || empty($time))
|
||||
{
|
||||
$result |= @unlink($file);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the cache storage is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
$conf = JFactory::getConfig();
|
||||
return is_writable($conf->get('cache_path', JPATH_CACHE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock cached item
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param integer $locktime Cached item max lock time
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function lock($id, $group, $locktime)
|
||||
{
|
||||
$returning = new stdClass;
|
||||
$returning->locklooped = false;
|
||||
|
||||
$looptime = $locktime * 10;
|
||||
$path = $this->_getFilePath($id, $group);
|
||||
|
||||
$_fileopen = @fopen($path, "r+b");
|
||||
|
||||
if ($_fileopen)
|
||||
{
|
||||
$data_lock = @flock($_fileopen, LOCK_EX);
|
||||
}
|
||||
else
|
||||
{
|
||||
$data_lock = false;
|
||||
}
|
||||
|
||||
if ($data_lock === false)
|
||||
{
|
||||
|
||||
$lock_counter = 0;
|
||||
|
||||
// Loop until you find that the lock has been released.
|
||||
// That implies that data get from other thread has finished
|
||||
while ($data_lock === false)
|
||||
{
|
||||
|
||||
if ($lock_counter > $looptime)
|
||||
{
|
||||
$returning->locked = false;
|
||||
$returning->locklooped = true;
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
$data_lock = @flock($_fileopen, LOCK_EX);
|
||||
$lock_counter++;
|
||||
}
|
||||
|
||||
}
|
||||
$returning->locked = $data_lock;
|
||||
|
||||
return $returning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock cached item
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function unlock($id, $group = null)
|
||||
{
|
||||
$path = $this->_getFilePath($id, $group);
|
||||
|
||||
$_fileopen = @fopen($path, "r+b");
|
||||
|
||||
if ($_fileopen)
|
||||
{
|
||||
$ret = @flock($_fileopen, LOCK_UN);
|
||||
@fclose($_fileopen);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to make sure cache is still valid, if not, delete it.
|
||||
*
|
||||
* @param string $id Cache key to expire.
|
||||
* @param string $group The cache data group.
|
||||
*
|
||||
* @return boolean False if not valid
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _checkExpire($id, $group)
|
||||
{
|
||||
$path = $this->_getFilePath($id, $group);
|
||||
|
||||
// Check prune period
|
||||
if (file_exists($path))
|
||||
{
|
||||
$time = @filemtime($path);
|
||||
if (($time + $this->_lifetime) < $this->_now || empty($time))
|
||||
{
|
||||
@unlink($path);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a cache file path from an id/group pair
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return string The cache file path
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _getFilePath($id, $group)
|
||||
{
|
||||
$name = $this->_getCacheId($id, $group);
|
||||
$dir = $this->_root . '/' . $group;
|
||||
|
||||
// If the folder doesn't exist try to create it
|
||||
if (!is_dir($dir))
|
||||
{
|
||||
|
||||
// Make sure the index file is there
|
||||
$indexFile = $dir . '/index.html';
|
||||
@ mkdir($dir) && file_put_contents($indexFile, '<!DOCTYPE html><title></title>');
|
||||
}
|
||||
|
||||
// Make sure the folder exists
|
||||
if (!is_dir($dir))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return $dir . '/' . $name . '.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Quickly delete a folder of files
|
||||
*
|
||||
* @param string $path The path to the folder to delete.
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _deleteFolder($path)
|
||||
{
|
||||
// Sanity check
|
||||
if (!$path || !is_dir($path) || empty($this->_root))
|
||||
{
|
||||
// Bad programmer! Bad Bad programmer!
|
||||
JLog::add('JCacheStorageFile::_deleteFolder ' . JText::_('JLIB_FILESYSTEM_ERROR_DELETE_BASE_DIRECTORY'), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
$path = $this->_cleanPath($path);
|
||||
|
||||
// Check to make sure path is inside cache folder, we do not want to delete Joomla root!
|
||||
$pos = strpos($path, $this->_cleanPath($this->_root));
|
||||
|
||||
if ($pos === false || $pos > 0)
|
||||
{
|
||||
JLog::add('JCacheStorageFile::_deleteFolder' . JText::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER', $path), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove all the files in folder if they exist; disable all filtering
|
||||
$files = $this->_filesInFolder($path, '.', false, true, array(), array());
|
||||
|
||||
if (!empty($files) && !is_array($files))
|
||||
{
|
||||
if (@unlink($files) !== true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
elseif (!empty($files) && is_array($files))
|
||||
{
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
$file = $this->_cleanPath($file);
|
||||
|
||||
// In case of restricted permissions we zap it one way or the other
|
||||
// as long as the owner is either the webserver or the ftp
|
||||
if (@unlink($file))
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
$filename = basename($file);
|
||||
JLog::add('JCacheStorageFile::_deleteFolder' . JText::sprintf('JLIB_FILESYSTEM_DELETE_FAILED', $filename), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove sub-folders of folder; disable all filtering
|
||||
$folders = $this->_folders($path, '.', false, true, array(), array());
|
||||
|
||||
foreach ($folders as $folder)
|
||||
{
|
||||
if (is_link($folder))
|
||||
{
|
||||
// Don't descend into linked directories, just delete the link.
|
||||
if (@unlink($folder) !== true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
elseif ($this->_deleteFolder($folder) !== true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// In case of restricted permissions we zap it one way or the other
|
||||
// as long as the owner is either the webserver or the ftp
|
||||
if (@rmdir($path))
|
||||
{
|
||||
$ret = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
JLog::add('JCacheStorageFile::_deleteFolder' . JText::sprintf('JLIB_FILESYSTEM_ERROR_FOLDER_DELETE', $path), JLog::WARNING, 'jerror');
|
||||
$ret = false;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to strip additional / or \ in a path name
|
||||
*
|
||||
* @param string $path The path to clean
|
||||
* @param string $ds Directory separator (optional)
|
||||
*
|
||||
* @return string The cleaned path
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _cleanPath($path, $ds = DIRECTORY_SEPARATOR)
|
||||
{
|
||||
$path = trim($path);
|
||||
|
||||
if (empty($path))
|
||||
{
|
||||
$path = $this->_root;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove double slashes and backslahses and convert all slashes and backslashes to DIRECTORY_SEPARATOR
|
||||
$path = preg_replace('#[/\\\\]+#', $ds, $path);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to quickly read the files in a folder.
|
||||
*
|
||||
* @param string $path The path of the folder to read.
|
||||
* @param string $filter A filter for file names.
|
||||
* @param mixed $recurse True to recursively search into sub-folders, or an
|
||||
* integer to specify the maximum depth.
|
||||
* @param boolean $fullpath True to return the full path to the file.
|
||||
* @param array $exclude Array with names of files which should not be shown in
|
||||
* the result.
|
||||
* @param array $excludefilter Array of folder names to exclude
|
||||
*
|
||||
* @return array Files in the given folder.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _filesInFolder($path, $filter = '.', $recurse = false, $fullpath = false
|
||||
, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'), $excludefilter = array('^\..*', '.*~'))
|
||||
{
|
||||
$arr = array();
|
||||
|
||||
// Check to make sure the path valid and clean
|
||||
$path = $this->_cleanPath($path);
|
||||
|
||||
// Is the path a folder?
|
||||
if (!is_dir($path))
|
||||
{
|
||||
JLog::add('JCacheStorageFile::_filesInFolder' . JText::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER', $path), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the source directory.
|
||||
if (!($handle = @opendir($path)))
|
||||
{
|
||||
return $arr;
|
||||
}
|
||||
|
||||
if (count($excludefilter))
|
||||
{
|
||||
$excludefilter = '/(' . implode('|', $excludefilter) . ')/';
|
||||
}
|
||||
else
|
||||
{
|
||||
$excludefilter = '';
|
||||
}
|
||||
while (($file = readdir($handle)) !== false)
|
||||
{
|
||||
if (($file != '.') && ($file != '..') && (!in_array($file, $exclude)) && (!$excludefilter || !preg_match($excludefilter, $file)))
|
||||
{
|
||||
$dir = $path . '/' . $file;
|
||||
$isDir = is_dir($dir);
|
||||
if ($isDir)
|
||||
{
|
||||
if ($recurse)
|
||||
{
|
||||
if (is_int($recurse))
|
||||
{
|
||||
$arr2 = $this->_filesInFolder($dir, $filter, $recurse - 1, $fullpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
$arr2 = $this->_filesInFolder($dir, $filter, $recurse, $fullpath);
|
||||
}
|
||||
|
||||
$arr = array_merge($arr, $arr2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (preg_match("/$filter/", $file))
|
||||
{
|
||||
if ($fullpath)
|
||||
{
|
||||
$arr[] = $path . '/' . $file;
|
||||
}
|
||||
else
|
||||
{
|
||||
$arr[] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
|
||||
return $arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to read the folders in a folder.
|
||||
*
|
||||
* @param string $path The path of the folder to read.
|
||||
* @param string $filter A filter for folder names.
|
||||
* @param mixed $recurse True to recursively search into sub-folders, or an integer to specify the maximum depth.
|
||||
* @param boolean $fullpath True to return the full path to the folders.
|
||||
* @param array $exclude Array with names of folders which should not be shown in the result.
|
||||
* @param array $excludefilter Array with regular expressions matching folders which should not be shown in the result.
|
||||
*
|
||||
* @return array Folders in the given folder.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function _folders($path, $filter = '.', $recurse = false, $fullpath = false
|
||||
, $exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX'), $excludefilter = array('^\..*'))
|
||||
{
|
||||
$arr = array();
|
||||
|
||||
// Check to make sure the path valid and clean
|
||||
$path = $this->_cleanPath($path);
|
||||
|
||||
// Is the path a folder?
|
||||
if (!is_dir($path))
|
||||
{
|
||||
JLog::add('JCacheStorageFile::_folders' . JText::sprintf('JLIB_FILESYSTEM_ERROR_PATH_IS_NOT_A_FOLDER', $path), JLog::WARNING, 'jerror');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the source directory
|
||||
if (!($handle = @opendir($path)))
|
||||
{
|
||||
return $arr;
|
||||
}
|
||||
|
||||
if (count($excludefilter))
|
||||
{
|
||||
$excludefilter_string = '/(' . implode('|', $excludefilter) . ')/';
|
||||
}
|
||||
else
|
||||
{
|
||||
$excludefilter_string = '';
|
||||
}
|
||||
while (($file = readdir($handle)) !== false)
|
||||
{
|
||||
if (($file != '.') && ($file != '..')
|
||||
&& (!in_array($file, $exclude))
|
||||
&& (empty($excludefilter_string) || !preg_match($excludefilter_string, $file)))
|
||||
{
|
||||
$dir = $path . '/' . $file;
|
||||
$isDir = is_dir($dir);
|
||||
if ($isDir)
|
||||
{
|
||||
// Removes filtered directories
|
||||
if (preg_match("/$filter/", $file))
|
||||
{
|
||||
if ($fullpath)
|
||||
{
|
||||
$arr[] = $dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
$arr[] = $file;
|
||||
}
|
||||
}
|
||||
if ($recurse)
|
||||
{
|
||||
if (is_int($recurse))
|
||||
{
|
||||
$arr2 = $this->_folders($dir, $filter, $recurse - 1, $fullpath, $exclude, $excludefilter);
|
||||
}
|
||||
else
|
||||
{
|
||||
$arr2 = $this->_folders($dir, $filter, $recurse, $fullpath, $exclude, $excludefilter);
|
||||
}
|
||||
|
||||
$arr = array_merge($arr, $arr2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
|
||||
return $arr;
|
||||
}
|
||||
}
|
71
libraries/joomla/cache/storage/helper.php
vendored
Normal file
71
libraries/joomla/cache/storage/helper.php
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Cache storage helper functions.
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheStorageHelper
|
||||
{
|
||||
/**
|
||||
* Cache data group
|
||||
*
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
public $group = '';
|
||||
|
||||
/**
|
||||
* Cached item size
|
||||
*
|
||||
* @var string
|
||||
* @since 11.1
|
||||
*/
|
||||
public $size = 0;
|
||||
|
||||
/**
|
||||
* Counter
|
||||
*
|
||||
* @var integer
|
||||
* @since 11.1
|
||||
*/
|
||||
public $count = 0;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __construct($group)
|
||||
{
|
||||
$this->group = $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase cache items count.
|
||||
*
|
||||
* @param string $size Cached item size
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function updateSize($size)
|
||||
{
|
||||
$this->size = number_format($this->size + $size, 2);
|
||||
$this->count++;
|
||||
}
|
||||
}
|
1
libraries/joomla/cache/storage/index.html
vendored
Normal file
1
libraries/joomla/cache/storage/index.html
vendored
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
485
libraries/joomla/cache/storage/memcache.php
vendored
Normal file
485
libraries/joomla/cache/storage/memcache.php
vendored
Normal file
@ -0,0 +1,485 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Memcache cache storage handler
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @see http://php.net/manual/en/book.memcache.php
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheStorageMemcache extends JCacheStorage
|
||||
{
|
||||
/**
|
||||
* @var Memcache
|
||||
* @since 11.1
|
||||
*/
|
||||
protected static $_db = null;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $_persistent = false;
|
||||
|
||||
/**
|
||||
* @var
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $_compress = 0;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Optional parameters.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __construct($options = array())
|
||||
{
|
||||
parent::__construct($options);
|
||||
if (self::$_db === null)
|
||||
{
|
||||
$this->getConnection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return memcache connection object
|
||||
*
|
||||
* @return object memcache connection object
|
||||
*
|
||||
* @since 11.1
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function getConnection()
|
||||
{
|
||||
if ((extension_loaded('memcache') && class_exists('Memcache')) != true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$config = JFactory::getConfig();
|
||||
$this->_persistent = $config->get('memcache_persist', true);
|
||||
$this->_compress = $config->get('memcache_compress', false) == false ? 0 : MEMCACHE_COMPRESSED;
|
||||
|
||||
/*
|
||||
* This will be an array of loveliness
|
||||
* @todo: multiple servers
|
||||
* $servers = (isset($params['servers'])) ? $params['servers'] : array();
|
||||
*/
|
||||
$server = array();
|
||||
$server['host'] = $config->get('memcache_server_host', 'localhost');
|
||||
$server['port'] = $config->get('memcache_server_port', 11211);
|
||||
|
||||
// Create the memcache connection
|
||||
self::$_db = new Memcache;
|
||||
self::$_db->addServer($server['host'], $server['port'], $this->_persistent);
|
||||
|
||||
$memcachetest = @self::$_db->connect($server['host'], $server['port']);
|
||||
if ($memcachetest == false)
|
||||
{
|
||||
throw new RuntimeException('Could not connect to memcache server', 404);
|
||||
}
|
||||
|
||||
// Memcahed has no list keys, we do our own accounting, initialise key index
|
||||
if (self::$_db->get($this->_hash . '-index') === false)
|
||||
{
|
||||
$empty = array();
|
||||
self::$_db->set($this->_hash . '-index', $empty, $this->_compress, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached data from memcache by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param boolean $checkTime True to verify cache time expiration threshold
|
||||
*
|
||||
* @return mixed Boolean false on failure or a cached data string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($id, $group, $checkTime = true)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
$back = self::$_db->get($cache_id);
|
||||
return $back;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cached data
|
||||
*
|
||||
* @return array data
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
parent::getAll();
|
||||
|
||||
$keys = self::$_db->get($this->_hash . '-index');
|
||||
$secret = $this->_hash;
|
||||
|
||||
$data = array();
|
||||
|
||||
if (!empty($keys))
|
||||
{
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if (empty($key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$namearr = explode('-', $key->name);
|
||||
|
||||
if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
|
||||
{
|
||||
|
||||
$group = $namearr[2];
|
||||
|
||||
if (!isset($data[$group]))
|
||||
{
|
||||
$item = new JCacheStorageHelper($group);
|
||||
}
|
||||
else
|
||||
{
|
||||
$item = $data[$group];
|
||||
}
|
||||
|
||||
$item->updateSize($key->size / 1024);
|
||||
|
||||
$data[$group] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data to memcache by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param string $data The data to store in cache
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function store($id, $group, $data)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
|
||||
if (!$this->lockindex())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$index = self::$_db->get($this->_hash . '-index');
|
||||
if ($index === false)
|
||||
{
|
||||
$index = array();
|
||||
}
|
||||
|
||||
$tmparr = new stdClass;
|
||||
$tmparr->name = $cache_id;
|
||||
$tmparr->size = strlen($data);
|
||||
|
||||
$config = JFactory::getConfig();
|
||||
$lifetime = (int) $config->get('cachetime', 15);
|
||||
if ($this->_lifetime == $lifetime)
|
||||
{
|
||||
$this->_lifetime = $lifetime * 60;
|
||||
}
|
||||
|
||||
$index[] = $tmparr;
|
||||
self::$_db->replace($this->_hash . '-index', $index, 0, 0);
|
||||
$this->unlockindex();
|
||||
|
||||
// Prevent double writes, write only if it doesn't exist else replace
|
||||
if (!self::$_db->replace($cache_id, $data, $this->_compress, $this->_lifetime))
|
||||
{
|
||||
self::$_db->set($cache_id, $data, $this->_compress, $this->_lifetime);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached data entry by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function remove($id, $group)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
|
||||
if (!$this->lockindex())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$index = self::$_db->get($this->_hash . '-index');
|
||||
if ($index === false)
|
||||
{
|
||||
$index = array();
|
||||
}
|
||||
|
||||
foreach ($index as $key => $value)
|
||||
{
|
||||
if ($value->name == $cache_id)
|
||||
{
|
||||
unset($index[$key]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
self::$_db->replace($this->_hash . '-index', $index, 0, 0);
|
||||
$this->unlockindex();
|
||||
|
||||
return self::$_db->delete($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean cache for a group given a mode.
|
||||
*
|
||||
* @param string $group The cache data group
|
||||
* @param string $mode The mode for cleaning cache [group|notgroup]
|
||||
* group mode : cleans all cache in the group
|
||||
* notgroup mode : cleans all cache not in the group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function clean($group, $mode = null)
|
||||
{
|
||||
if (!$this->lockindex())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$index = self::$_db->get($this->_hash . '-index');
|
||||
if ($index === false)
|
||||
{
|
||||
$index = array();
|
||||
}
|
||||
|
||||
$secret = $this->_hash;
|
||||
foreach ($index as $key => $value)
|
||||
{
|
||||
|
||||
if (strpos($value->name, $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
|
||||
{
|
||||
self::$_db->delete($value->name, 0);
|
||||
unset($index[$key]);
|
||||
}
|
||||
}
|
||||
self::$_db->replace($this->_hash . '-index', $index, 0, 0);
|
||||
$this->unlockindex();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the cache storage is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
if ((extension_loaded('memcache') && class_exists('Memcache')) != true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$config = JFactory::getConfig();
|
||||
$host = $config->get('memcache_server_host', 'localhost');
|
||||
$port = $config->get('memcache_server_port', 11211);
|
||||
|
||||
$memcache = new Memcache;
|
||||
$memcachetest = @$memcache->connect($host, $port);
|
||||
|
||||
if (!$memcachetest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock cached item - override parent as this is more efficient
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param integer $locktime Cached item max lock time
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function lock($id, $group, $locktime)
|
||||
{
|
||||
$returning = new stdClass;
|
||||
$returning->locklooped = false;
|
||||
|
||||
$looptime = $locktime * 10;
|
||||
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
|
||||
if (!$this->lockindex())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$index = self::$_db->get($this->_hash . '-index');
|
||||
if ($index === false)
|
||||
{
|
||||
$index = array();
|
||||
}
|
||||
|
||||
$tmparr = new stdClass;
|
||||
$tmparr->name = $cache_id;
|
||||
$tmparr->size = 1;
|
||||
$index[] = $tmparr;
|
||||
self::$_db->replace($this->_hash . '-index', $index, 0, 0);
|
||||
$this->unlockindex();
|
||||
|
||||
$data_lock = self::$_db->add($cache_id . '_lock', 1, false, $locktime);
|
||||
|
||||
if ($data_lock === false)
|
||||
{
|
||||
|
||||
$lock_counter = 0;
|
||||
|
||||
// Loop until you find that the lock has been released.
|
||||
// That implies that data get from other thread has finished
|
||||
while ($data_lock === false)
|
||||
{
|
||||
|
||||
if ($lock_counter > $looptime)
|
||||
{
|
||||
$returning->locked = false;
|
||||
$returning->locklooped = true;
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
$data_lock = self::$_db->add($cache_id . '_lock', 1, false, $locktime);
|
||||
$lock_counter++;
|
||||
}
|
||||
|
||||
}
|
||||
$returning->locked = $data_lock;
|
||||
|
||||
return $returning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock cached item - override parent for cacheid compatibility with lock
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function unlock($id, $group = null)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group) . '_lock';
|
||||
|
||||
if (!$this->lockindex())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$index = self::$_db->get($this->_hash . '-index');
|
||||
if ($index === false)
|
||||
{
|
||||
$index = array();
|
||||
}
|
||||
|
||||
foreach ($index as $key => $value)
|
||||
{
|
||||
if ($value->name == $cache_id)
|
||||
{
|
||||
unset($index[$key]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
self::$_db->replace($this->_hash . '-index', $index, 0, 0);
|
||||
$this->unlockindex();
|
||||
|
||||
return self::$_db->delete($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock cache index
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function lockindex()
|
||||
{
|
||||
$looptime = 300;
|
||||
$data_lock = self::$_db->add($this->_hash . '-index_lock', 1, false, 30);
|
||||
|
||||
if ($data_lock === false)
|
||||
{
|
||||
|
||||
$lock_counter = 0;
|
||||
|
||||
// Loop until you find that the lock has been released. that implies that data get from other thread has finished
|
||||
while ($data_lock === false)
|
||||
{
|
||||
if ($lock_counter > $looptime)
|
||||
{
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
$data_lock = self::$_db->add($this->_hash . '-index_lock', 1, false, 30);
|
||||
$lock_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock cache index
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function unlockindex()
|
||||
{
|
||||
return self::$_db->delete($this->_hash . '-index_lock');
|
||||
}
|
||||
}
|
489
libraries/joomla/cache/storage/memcached.php
vendored
Normal file
489
libraries/joomla/cache/storage/memcached.php
vendored
Normal file
@ -0,0 +1,489 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Memcached cache storage handler
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @see http://php.net/manual/en/book.memcached.php
|
||||
* @since 12.1
|
||||
*/
|
||||
class JCacheStorageMemcached extends JCacheStorage
|
||||
{
|
||||
/**
|
||||
* @var Memcached
|
||||
* @since 12.1
|
||||
*/
|
||||
protected static $_db = null;
|
||||
|
||||
/**
|
||||
* @var boolean
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $_persistent = false;
|
||||
|
||||
/**
|
||||
* @var
|
||||
* @since 12.1
|
||||
*/
|
||||
protected $_compress = 0;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Optional parameters.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function __construct($options = array())
|
||||
{
|
||||
parent::__construct($options);
|
||||
if (self::$_db === null)
|
||||
{
|
||||
$this->getConnection();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return memcached connection object
|
||||
*
|
||||
* @return object memcached connection object
|
||||
*
|
||||
* @since 12.1
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
protected function getConnection()
|
||||
{
|
||||
if ((extension_loaded('memcached') && class_exists('Memcached')) != true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$config = JFactory::getConfig();
|
||||
$this->_persistent = $config->get('memcache_persist', true);
|
||||
$this->_compress = $config->get('memcache_compress', false) == false ? 0 : Memcached::OPT_COMPRESSION;
|
||||
|
||||
/*
|
||||
* This will be an array of loveliness
|
||||
* @todo: multiple servers
|
||||
* $servers = (isset($params['servers'])) ? $params['servers'] : array();
|
||||
*/
|
||||
$server = array();
|
||||
$server['host'] = $config->get('memcache_server_host', 'localhost');
|
||||
$server['port'] = $config->get('memcache_server_port', 11211);
|
||||
|
||||
// Create the memcache connection
|
||||
if ($this->_persistent)
|
||||
{
|
||||
$session = JFactory::getSession();
|
||||
self::$_db = new Memcached($session->getId());
|
||||
}
|
||||
else
|
||||
{
|
||||
self::$_db = new Memcached;
|
||||
}
|
||||
$memcachedtest = self::$_db->addServer($server['host'], $server['port']);
|
||||
|
||||
if ($memcachedtest == false)
|
||||
{
|
||||
throw new RuntimeException('Could not connect to memcached server', 404);
|
||||
}
|
||||
|
||||
self::$_db->setOption(Memcached::OPT_COMPRESSION, $this->_compress);
|
||||
|
||||
// Memcached has no list keys, we do our own accounting, initialise key index
|
||||
if (self::$_db->get($this->_hash . '-index') === false)
|
||||
{
|
||||
$empty = array();
|
||||
self::$_db->set($this->_hash . '-index', $empty, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached data from memcached by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param boolean $checkTime True to verify cache time expiration threshold
|
||||
*
|
||||
* @return mixed Boolean false on failure or a cached data string
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function get($id, $group, $checkTime = true)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
$back = self::$_db->get($cache_id);
|
||||
return $back;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cached data
|
||||
*
|
||||
* @return array data
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
parent::getAll();
|
||||
|
||||
$keys = self::$_db->get($this->_hash . '-index');
|
||||
$secret = $this->_hash;
|
||||
|
||||
$data = array();
|
||||
|
||||
if (!empty($keys) && is_array($keys))
|
||||
{
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if (empty($key))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$namearr = explode('-', $key->name);
|
||||
|
||||
if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
|
||||
{
|
||||
|
||||
$group = $namearr[2];
|
||||
|
||||
if (!isset($data[$group]))
|
||||
{
|
||||
$item = new JCacheStorageHelper($group);
|
||||
}
|
||||
else
|
||||
{
|
||||
$item = $data[$group];
|
||||
}
|
||||
|
||||
$item->updateSize($key->size / 1024);
|
||||
|
||||
$data[$group] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data to memcached by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param string $data The data to store in cache
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function store($id, $group, $data)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
|
||||
if (!$this->lockindex())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$index = self::$_db->get($this->_hash . '-index');
|
||||
if ($index === false)
|
||||
{
|
||||
$index = array();
|
||||
}
|
||||
|
||||
$tmparr = new stdClass;
|
||||
$tmparr->name = $cache_id;
|
||||
$tmparr->size = strlen($data);
|
||||
$index[] = $tmparr;
|
||||
self::$_db->replace($this->_hash . '-index', $index, 0);
|
||||
$this->unlockindex();
|
||||
|
||||
// Prevent double writes, write only if it doesn't exist else replace
|
||||
if (!self::$_db->replace($cache_id, $data, $this->_lifetime))
|
||||
{
|
||||
self::$_db->set($cache_id, $data, $this->_lifetime);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached data entry by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function remove($id, $group)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
|
||||
if (!$this->lockindex())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$index = self::$_db->get($this->_hash . '-index');
|
||||
if ($index === false)
|
||||
{
|
||||
$index = array();
|
||||
}
|
||||
|
||||
foreach ($index as $key => $value)
|
||||
{
|
||||
if ($value->name == $cache_id)
|
||||
{
|
||||
unset($index[$key]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
self::$_db->replace($this->_hash . '-index', $index, 0);
|
||||
$this->unlockindex();
|
||||
|
||||
return self::$_db->delete($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean cache for a group given a mode.
|
||||
*
|
||||
* @param string $group The cache data group
|
||||
* @param string $mode The mode for cleaning cache [group|notgroup]
|
||||
* group mode : cleans all cache in the group
|
||||
* notgroup mode : cleans all cache not in the group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function clean($group, $mode = null)
|
||||
{
|
||||
if (!$this->lockindex())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$index = self::$_db->get($this->_hash . '-index');
|
||||
if ($index === false)
|
||||
{
|
||||
$index = array();
|
||||
}
|
||||
|
||||
$secret = $this->_hash;
|
||||
foreach ($index as $key => $value)
|
||||
{
|
||||
|
||||
if (strpos($value->name, $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
|
||||
{
|
||||
self::$_db->delete($value->name, 0);
|
||||
unset($index[$key]);
|
||||
}
|
||||
}
|
||||
self::$_db->replace($this->_hash . '-index', $index, 0);
|
||||
$this->unlockindex();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the cache storage is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
if ((extension_loaded('memcached') && class_exists('Memcached')) != true)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$config = JFactory::getConfig();
|
||||
$host = $config->get('memcache_server_host', 'localhost');
|
||||
$port = $config->get('memcache_server_port', 11211);
|
||||
|
||||
$memcached = new Memcached;
|
||||
$memcachedtest = @$memcached->addServer($host, $port);
|
||||
|
||||
if (!$memcachedtest)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock cached item - override parent as this is more efficient
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param integer $locktime Cached item max lock time
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function lock($id, $group, $locktime)
|
||||
{
|
||||
$returning = new stdClass;
|
||||
$returning->locklooped = false;
|
||||
|
||||
$looptime = $locktime * 10;
|
||||
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
|
||||
if (!$this->lockindex())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$index = self::$_db->get($this->_hash . '-index');
|
||||
if ($index === false)
|
||||
{
|
||||
$index = array();
|
||||
}
|
||||
|
||||
$tmparr = new stdClass;
|
||||
$tmparr->name = $cache_id;
|
||||
$tmparr->size = 1;
|
||||
|
||||
$index[] = $tmparr;
|
||||
self::$_db->replace($this->_hash . '-index', $index, 0);
|
||||
|
||||
$this->unlockindex();
|
||||
|
||||
$data_lock = self::$_db->add($cache_id . '_lock', 1, $locktime);
|
||||
|
||||
if ($data_lock === false)
|
||||
{
|
||||
|
||||
$lock_counter = 0;
|
||||
|
||||
// Loop until you find that the lock has been released.
|
||||
// That implies that data get from other thread has finished
|
||||
while ($data_lock === false)
|
||||
{
|
||||
|
||||
if ($lock_counter > $looptime)
|
||||
{
|
||||
$returning->locked = false;
|
||||
$returning->locklooped = true;
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
$data_lock = self::$_db->add($cache_id . '_lock', 1, $locktime);
|
||||
$lock_counter++;
|
||||
}
|
||||
|
||||
}
|
||||
$returning->locked = $data_lock;
|
||||
|
||||
return $returning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock cached item - override parent for cacheid compatibility with lock
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public function unlock($id, $group = null)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group) . '_lock';
|
||||
|
||||
if (!$this->lockindex())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$index = self::$_db->get($this->_hash . '-index');
|
||||
if ($index === false)
|
||||
{
|
||||
$index = array();
|
||||
}
|
||||
|
||||
foreach ($index as $key => $value)
|
||||
{
|
||||
if ($value->name == $cache_id)
|
||||
{
|
||||
unset($index[$key]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
self::$_db->replace($this->_hash . '-index', $index, 0);
|
||||
$this->unlockindex();
|
||||
|
||||
return self::$_db->delete($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock cache index
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected function lockindex()
|
||||
{
|
||||
$looptime = 300;
|
||||
$data_lock = self::$_db->add($this->_hash . '-index_lock', 1, 30);
|
||||
|
||||
if ($data_lock === false)
|
||||
{
|
||||
|
||||
$lock_counter = 0;
|
||||
|
||||
// Loop until you find that the lock has been released. that implies that data get from other thread has finished
|
||||
while ($data_lock === false)
|
||||
{
|
||||
if ($lock_counter > $looptime)
|
||||
{
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
usleep(100);
|
||||
$data_lock = self::$_db->add($this->_hash . '-index_lock', 1, 30);
|
||||
$lock_counter++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock cache index
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
protected function unlockindex()
|
||||
{
|
||||
return self::$_db->delete($this->_hash . '-index_lock');
|
||||
}
|
||||
}
|
194
libraries/joomla/cache/storage/wincache.php
vendored
Normal file
194
libraries/joomla/cache/storage/wincache.php
vendored
Normal file
@ -0,0 +1,194 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* WINCACHE cache storage handler
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @see http://php.net/manual/en/book.wincache.php
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheStorageWincache extends JCacheStorage
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $options Optional parameters.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function __construct($options = array())
|
||||
{
|
||||
parent::__construct($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached data from WINCACHE by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param boolean $checkTime True to verify cache time expiration threshold
|
||||
*
|
||||
* @return mixed Boolean false on failure or a cached data string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($id, $group, $checkTime = true)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
$cache_content = wincache_ucache_get($cache_id);
|
||||
return $cache_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cached data
|
||||
*
|
||||
* @return array data
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
parent::getAll();
|
||||
|
||||
$allinfo = wincache_ucache_info();
|
||||
$keys = $allinfo['cache_entries'];
|
||||
$secret = $this->_hash;
|
||||
$data = array();
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
$name = $key['key_name'];
|
||||
$namearr = explode('-', $name);
|
||||
if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
|
||||
{
|
||||
$group = $namearr[2];
|
||||
if (!isset($data[$group]))
|
||||
{
|
||||
$item = new JCacheStorageHelper($group);
|
||||
}
|
||||
else
|
||||
{
|
||||
$item = $data[$group];
|
||||
}
|
||||
if (isset($key['value_size']))
|
||||
{
|
||||
$item->updateSize($key['value_size'] / 1024);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dummy, WINCACHE version is too low.
|
||||
$item->updateSize(1);
|
||||
}
|
||||
$data[$group] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data to WINCACHE by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param string $data The data to store in cache
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function store($id, $group, $data)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
return wincache_ucache_set($cache_id, $data, $this->_lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached data entry by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function remove($id, $group)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
return wincache_ucache_delete($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean cache for a group given a mode.
|
||||
*
|
||||
* @param string $group The cache data group
|
||||
* @param string $mode The mode for cleaning cache [group|notgroup]
|
||||
* group mode : cleans all cache in the group
|
||||
* notgroup mode : cleans all cache not in the group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function clean($group, $mode = null)
|
||||
{
|
||||
$allinfo = wincache_ucache_info();
|
||||
$keys = $allinfo['cache_entries'];
|
||||
$secret = $this->_hash;
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if (strpos($key['key_name'], $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
|
||||
{
|
||||
wincache_ucache_delete($key['key_name']);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force garbage collect expired cache data as items are removed only on get/add/delete/info etc
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function gc()
|
||||
{
|
||||
$allinfo = wincache_ucache_info();
|
||||
$keys = $allinfo['cache_entries'];
|
||||
$secret = $this->_hash;
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if (strpos($key['key_name'], $secret . '-cache-'))
|
||||
{
|
||||
wincache_ucache_get($key['key_name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the cache storage is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
$test = extension_loaded('wincache') && function_exists('wincache_ucache_get') && !strcmp(ini_get('wincache.ucenabled'), '1');
|
||||
return $test;
|
||||
}
|
||||
}
|
209
libraries/joomla/cache/storage/xcache.php
vendored
Normal file
209
libraries/joomla/cache/storage/xcache.php
vendored
Normal file
@ -0,0 +1,209 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* XCache cache storage handler
|
||||
*
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Cache
|
||||
* @link http://xcache.lighttpd.net/
|
||||
* @since 11.1
|
||||
*/
|
||||
class JCacheStorageXcache extends JCacheStorage
|
||||
{
|
||||
/**
|
||||
* Get cached data by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param boolean $checkTime True to verify cache time expiration threshold
|
||||
*
|
||||
* @return mixed Boolean false on failure or a cached data string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function get($id, $group, $checkTime = true)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
$cache_content = xcache_get($cache_id);
|
||||
|
||||
if ($cache_content === null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $cache_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all cached data
|
||||
*
|
||||
* This requires the php.ini setting xcache.admin.enable_auth = Off.
|
||||
*
|
||||
* @return array data
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function getAll()
|
||||
{
|
||||
parent::getAll();
|
||||
|
||||
$allinfo = xcache_list(XC_TYPE_VAR, 0);
|
||||
$keys = $allinfo['cache_list'];
|
||||
$secret = $this->_hash;
|
||||
|
||||
$data = array();
|
||||
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
|
||||
$namearr = explode('-', $key['name']);
|
||||
|
||||
if ($namearr !== false && $namearr[0] == $secret && $namearr[1] == 'cache')
|
||||
{
|
||||
$group = $namearr[2];
|
||||
|
||||
if (!isset($data[$group]))
|
||||
{
|
||||
$item = new JCacheStorageHelper($group);
|
||||
}
|
||||
else
|
||||
{
|
||||
$item = $data[$group];
|
||||
}
|
||||
|
||||
$item->updateSize($key['size'] / 1024);
|
||||
|
||||
$data[$group] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the data by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
* @param string $data The data to store in cache
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function store($id, $group, $data)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
$store = xcache_set($cache_id, $data, $this->_lifetime);
|
||||
return $store;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a cached data entry by id and group
|
||||
*
|
||||
* @param string $id The cache data id
|
||||
* @param string $group The cache data group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function remove($id, $group)
|
||||
{
|
||||
$cache_id = $this->_getCacheId($id, $group);
|
||||
|
||||
if (!xcache_isset($cache_id))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return xcache_unset($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean cache for a group given a mode.
|
||||
*
|
||||
* This requires the php.ini setting xcache.admin.enable_auth = Off.
|
||||
*
|
||||
* @param string $group The cache data group
|
||||
* @param string $mode The mode for cleaning cache [group|notgroup]
|
||||
* group mode : cleans all cache in the group
|
||||
* notgroup mode : cleans all cache not in the group
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function clean($group, $mode = null)
|
||||
{
|
||||
$allinfo = xcache_list(XC_TYPE_VAR, 0);
|
||||
$keys = $allinfo['cache_list'];
|
||||
|
||||
$secret = $this->_hash;
|
||||
foreach ($keys as $key)
|
||||
{
|
||||
if (strpos($key['name'], $secret . '-cache-' . $group . '-') === 0 xor $mode != 'group')
|
||||
{
|
||||
xcache_unset($key['name']);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage collect expired cache data
|
||||
*
|
||||
* This is a dummy, since xcache has built in garbage collector, turn it
|
||||
* on in php.ini by changing default xcache.gc_interval setting from
|
||||
* 0 to 3600 (=1 hour)
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function gc()
|
||||
{
|
||||
/*
|
||||
$now = time();
|
||||
|
||||
$cachecount = xcache_count(XC_TYPE_VAR);
|
||||
|
||||
for ($i = 0; $i < $cachecount; $i ++) {
|
||||
|
||||
$allinfo = xcache_list(XC_TYPE_VAR, $i);
|
||||
$keys = $allinfo ['cache_list'];
|
||||
|
||||
foreach($keys as $key) {
|
||||
|
||||
if (strstr($key['name'], $this->_hash)) {
|
||||
if (($key['ctime'] + $this->_lifetime ) < $this->_now) xcache_unset($key['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to see if the cache storage is available.
|
||||
*
|
||||
* @return boolean True on success, false otherwise.
|
||||
*
|
||||
* @since 12.1
|
||||
*/
|
||||
public static function isSupported()
|
||||
{
|
||||
return (extension_loaded('xcache'));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user