Fixed CacheResource implementation and tests

This commit is contained in:
Simon Wisselink
2023-01-03 17:10:02 +01:00
parent 32df4c6467
commit 3fccb54093
19 changed files with 215 additions and 213 deletions

View File

@@ -22,15 +22,9 @@ use Smarty\Template\Cached;
*/
abstract class Base
{
/**
* resource types provided by the core
*
* @var array
*/
protected static $sysplugins = ['file' => \Smarty\Cacheresource\File::class];
/**
* populate Cached Object with meta data from Resource
* populate Cached Object with metadata from Resource
*
* @param Cached $cached cached object
* @param Template $_template template object
@@ -52,7 +46,7 @@ abstract class Base
* Read the cached template and process header
*
* @param Template $_template template object
* @param Cached $cached cached object
* @param Cached|null $cached cached object
* @param boolean $update flag if called because cache update
*
* @return boolean true or false if the cached content does not exist
@@ -186,36 +180,4 @@ abstract class Base
// release lock
return true;
}
/**
* Load Cache Resource Handler
*
* @param Smarty $smarty Smarty object
* @param string $type name of the cache resource
*
* @return Base Cache Resource Handler
*/
public static function load(Smarty $smarty, $type = null)
{
if (!isset($type)) {
$type = $smarty->caching_type;
}
// try smarty's cache
if (isset($smarty->_cacheresource_handlers[ $type ])) {
return $smarty->_cacheresource_handlers[ $type ];
}
// try registered resource
if (isset($smarty->registered_cache_resources[ $type ])) {
// do not cache these instances as they may vary from instance to instance
return $smarty->_cacheresource_handlers[ $type ] = $smarty->registered_cache_resources[ $type ];
}
// try sysplugins dir
if (isset(self::$sysplugins[ $type ])) {
$cache_resource_class = self::$sysplugins[ $type ];
return $smarty->_cacheresource_handlers[ $type ] = new $cache_resource_class();
}
// try plugins dir
$cache_resource_class = 'Smarty_CacheResource_' . \smarty_ucfirst_ascii($type);
return $smarty->_cacheresource_handlers[ $type ] = new $cache_resource_class();
}
}

View File

@@ -181,6 +181,17 @@ class BCPluginsAdapter extends Base {
}
}
$type = 'cacheresource';
foreach (glob($path . $type . '.?*.php') as $filename) {
$pluginName = $this->getPluginNameFromFilename($filename);
if ($pluginName !== null) {
require_once $filename;
if (class_exists($className = 'smarty_' . $type . '_' . $pluginName)) {
$this->smarty->registerCacheResource($pluginName, new $className());
}
}
}
}
/**

View File

@@ -4,6 +4,7 @@ namespace Smarty;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Smarty\Cacheresource\File;
use Smarty\Extension\Base;
use Smarty\Extension\BCPluginsAdapter;
use Smarty\Extension\CoreExtension;
@@ -386,12 +387,12 @@ class Smarty extends \Smarty\TemplateBase
public $default_resource_type = 'file';
/**
* caching type
* Must be an element of $cache_resource_types.
* cache resource
* Must be a subclass of \Smarty\Cacheresource\Base
*
* @var string
* @var \Smarty\Cacheresource\Base
*/
public $caching_type = 'file';
private $cacheResource;
/**
* config type
@@ -446,8 +447,9 @@ class Smarty extends \Smarty\TemplateBase
* registered cache resources
*
* @var array
* @deprecated since 5.0
*/
public $registered_cache_resources = array();
private $registered_cache_resources = array();
/**
* default modifier
@@ -601,6 +603,8 @@ class Smarty extends \Smarty\TemplateBase
$this->extensions[] = new CoreExtension();
$this->extensions[] = new DefaultExtension();
$this->extensions[] = $this->BCPluginsAdapter;
$this->cacheResource = new File();
}
/**
@@ -1305,14 +1309,6 @@ class Smarty extends \Smarty\TemplateBase
$this->default_resource_type = $default_resource_type;
}
/**
* @param string $caching_type
*/
public function setCachingType($caching_type)
{
$this->caching_type = $caching_type;
}
/**
* Test install
*
@@ -1400,7 +1396,7 @@ class Smarty extends \Smarty\TemplateBase
*
* @return int number of cache files deleted
* @throws \Smarty\Exception
*@link https://www.smarty.net/docs/en/api.clear.cache.tpl
* @link https://www.smarty.net/docs/en/api.clear.cache.tpl
*
* @api Smarty::clearCache()
*/
@@ -1408,13 +1404,10 @@ class Smarty extends \Smarty\TemplateBase
$template_name,
$cache_id = null,
$compile_id = null,
$exp_time = null,
$type = null
$exp_time = null
) {
$this->_clearTemplateCache();
// load cache resource and call clear
$_cache_resource = \Smarty\Cacheresource\Base::load($this, $type);
return $_cache_resource->clear($this, $template_name, $cache_id, $compile_id, $exp_time);
return $this->getCacheResource()->clear($this, $template_name, $cache_id, $compile_id, $exp_time);
}
/**
@@ -1428,12 +1421,10 @@ class Smarty extends \Smarty\TemplateBase
*
* @return int number of cache files deleted
*/
public function clearAllCache($exp_time = null, $type = null)
public function clearAllCache($exp_time = null)
{
$this->_clearTemplateCache();
// load cache resource and call clearAll
$_cache_resource = \Smarty\Cacheresource\Base::load($this, $type);
return $_cache_resource->clearAll($this, $exp_time);
return $this->getCacheResource()->clearAll($this, $exp_time);
}
/**
@@ -2188,6 +2179,85 @@ class Smarty extends \Smarty\TemplateBase
return $this->unregisterFilter($type, $name);
}
private $_caching_type = 'file';
/**
* @param $type
*
* @return void
* @deprecated since 5.0
*/
public function setCachingType($type) {
trigger_error('Using Smarty::setCachingType() is deprecated and will be ' .
'removed in a future release. Use Smarty::setCacheResource() instead.', E_USER_DEPRECATED);
$this->_caching_type = $type;
$this->activateBCCacheResource();
}
/**
* @return string
* @deprecated since 5.0
*/
public function getCachingType(): string {
trigger_error('Using Smarty::getCachingType() is deprecated and will be ' .
'removed in a future release.', E_USER_DEPRECATED);
return $this->_caching_type;
}
/**
* Registers a resource to fetch a template
*
* @param string $name name of resource type
* @param Base $resource_handler
*
* @return Smarty
* @link https://www.smarty.net/docs/en/api.register.cacheresource.tpl
*
* @api Smarty::registerCacheResource()
*
* @deprecated since 5.0
*/
public function registerCacheResource($name, \Smarty\Cacheresource\Base $resource_handler) {
trigger_error('Using Smarty::registerCacheResource() is deprecated and will be ' .
'removed in a future release. Use Smarty::setCacheResource() instead.', E_USER_DEPRECATED);
$this->registered_cache_resources[$name] = $resource_handler;
$this->activateBCCacheResource();
return $this;
}
/**
* Unregisters a resource to fetch a template
*
* @param $name
*
* @return Smarty
* @api Smarty::unregisterCacheResource()
* @link https://www.smarty.net/docs/en/api.unregister.cacheresource.tpl
*
* @deprecated since 5.0
*
*/
public function unregisterCacheResource($name) {
trigger_error('Using Smarty::unregisterCacheResource() is deprecated and will be ' .
'removed in a future release.', E_USER_DEPRECATED);
if (isset($this->registered_cache_resources[$name])) {
unset($this->registered_cache_resources[$name]);
}
return $this;
}
private function activateBCCacheResource() {
if ($this->_caching_type == 'file') {
$this->setCacheResource(new File());
}
if (isset($this->registered_cache_resources[$this->_caching_type])) {
$this->setCacheResource($this->registered_cache_resources[$this->_caching_type]);
}
}
/**
* Registers a filter function
*
@@ -2339,5 +2409,19 @@ class Smarty extends \Smarty\TemplateBase
$this->allow_ambiguous_resources = $allow;
}
/**
* @return Cacheresource\Base
*/
public function getCacheResource(): Cacheresource\Base {
return $this->cacheResource;
}
/**
* @param Cacheresource\Base $cacheResource
*/
public function setCacheResource(Cacheresource\Base $cacheResource): void {
$this->cacheResource = $cacheResource;
}
}

View File

@@ -571,7 +571,7 @@ class Template extends TemplateBase {
*/
public function loadCached($force = false) {
if ($force || !isset($this->cached)) {
$this->cached = Cached::load($this);
$this->cached = Cached::create($this);
}
}

View File

@@ -90,7 +90,7 @@ class Cached extends ResourceBase {
$this->compile_id = $_template->compile_id;
$this->cache_id = $_template->cache_id;
$this->source = $_template->source;
$this->handler = \Smarty\Cacheresource\Base::load($_template->smarty);
$this->handler = $_template->smarty->getCacheResource();
}
/**
@@ -98,8 +98,8 @@ class Cached extends ResourceBase {
*
* @return Cached
*/
public static function load(Template $_template) {
$_template->cached = new Cached($_template);
public static function create(Template $_template) {
$_template->cached = new self($_template);
$_template->cached->handler->populate($_template->cached, $_template);
// caching enabled ?
if (!$_template->caching || $_template->source->handler->recompiled

View File

@@ -504,41 +504,6 @@ abstract class TemplateBase extends Data {
return $this;
}
/**
* Registers a resource to fetch a template
*
* @param string $name name of resource type
* @param Base $resource_handler
*
* @return TemplateBase
* @link https://www.smarty.net/docs/en/api.register.cacheresource.tpl
*
* @api Smarty::registerCacheResource()
*/
public function registerCacheResource($name, Base $resource_handler) {
$smarty = $this->_getSmartyObj();
$smarty->registered_cache_resources[$name] = $resource_handler;
return $this;
}
/**
* Unregisters a resource to fetch a template
*
* @param $name
*
* @return \Smarty|\Smarty\Template
* @api Smarty::unregisterCacheResource()
* @link https://www.smarty.net/docs/en/api.unregister.cacheresource.tpl
*
*/
public function unregisterCacheResource($name) {
$smarty = $this->_getSmartyObj();
if (isset($smarty->registered_cache_resources[$name])) {
unset($smarty->registered_cache_resources[$name]);
}
return $this;
}
/**
* Register config default handler
*

View File

@@ -564,7 +564,7 @@ KEY `name` (`name`)
public function buildCachedPath($tpl, $sub = true, $cache_id = null, $compile_id = null, $name = null, $type = null,
$dir = null, $cacheType = null)
{
$cacheType = isset($cacheType) ? $cacheType : $tpl->smarty->caching_type;
$cacheType = $cacheType ?? $tpl->smarty->getCachingType();
switch ($cacheType) {
case 'file':
case 'filetest':
@@ -594,7 +594,6 @@ KEY `name` (`name`)
$smarty = isset($tpl->smarty) ? $tpl->smarty : $tpl;
$_cache_dir = $smarty->getCacheDir();
return $_cache_dir . $_cache_id . $_compile_id . $_filepath . '.' . basename($sp) . '.php';
case 'mysql':
case 'mysqltest':
case 'pdo':
case 'foobar':
@@ -603,7 +602,6 @@ KEY `name` (`name`)
$_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null;
$_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null;
return sha1($uid . $_cache_id . $_compile_id);
case 'memcache':
case 'memcachetest':
case 'apc':
$sp = $this->buildSourcePath($tpl, $name, $type, $dir);

View File

@@ -7,7 +7,7 @@
*/
include_once __DIR__ . '/../_shared/CacheResourceTestCommon.php';
include_once __DIR__ . '/../_shared/PHPunitplugins/cacheresource.pdotest.php';
include_once __DIR__ . '/cacheresource.pdotest.php';
/**
* class for cache resource file tests
@@ -29,9 +29,6 @@ class CacheResourceCustomPDOTest extends CacheResourceTestCommon
}
$this->setUpSmarty(__DIR__);
parent::setUp();
$this->smarty->setCachingType('pdo');
$this->assertTrue(false !== $this->smarty->loadPlugin('Smarty_CacheResource_Pdotest'),
'loadPlugin() could not load PDO cache resource');
$this->smarty->registerCacheResource('pdo',
new Smarty_CacheResource_Pdotest($this->getPDO(), 'output_cache'));
}

View File

@@ -2,9 +2,9 @@
use Smarty\Template\Cached;
require_once __DIR__ . '/../../../__shared/cacheresources/cacheresource.pdo.php';
require_once __DIR__ . '/../../__shared/cacheresources/cacheresource.pdo.php';
class Smarty_CacheResource_Pdotest extends My_CacheResource_Pdo
class Smarty_CacheResource_Pdotest extends Smarty_CacheResource_Pdo
{
public $lockTime = 0;

View File

@@ -8,7 +8,7 @@
include_once __DIR__ . '/../_shared/CacheResourceTestCommon.php';
include_once __DIR__ . '/../_shared/PHPunitplugins/cacheresource.pdo_gziptest.php';
include_once __DIR__ . '/cacheresource.pdo_gziptest.php';
/**
* class for cache resource file tests

View File

@@ -2,9 +2,9 @@
use Smarty\Template\Cached;
require_once __DIR__ . '/../../../__shared/cacheresources/cacheresource.pdo_gzip.php';
require_once __DIR__ . '/../../__shared/cacheresources/cacheresource.pdo_gzip.php';
class Smarty_CacheResource_Pdo_Gziptest extends My_CacheResource_Pdo_Gzip
class Smarty_CacheResource_Pdo_Gziptest extends Smarty_CacheResource_Pdo_Gzip
{
public $lockTime = 0;

View File

@@ -6,7 +6,7 @@ use Smarty\Template\Cached;
require_once __DIR__ . '/../../../__shared/cacheresources/cacheresource.apc.php';
class Smarty_CacheResource_Apctest extends My_CacheResource_Apc
class Smarty_CacheResource_Apctest extends Smarty_CacheResource_Apc
{
public $lockTime = 0;

View File

@@ -9,7 +9,7 @@ class Smarty_CacheResource_Memcachetest extends Smarty_CacheResource_Memcache
{
public $lockTime = 0;
public function hasLock(Smarty $smarty, Cached $cached)
public function hasLock(\Smarty\Smarty $smarty, Cached $cached)
{
if ($this->lockTime) {
$this->lockTime--;

View File

@@ -9,19 +9,11 @@ class Smarty_CacheResource_Mysqltest extends Smarty_CacheResource_Mysql
{
public $lockTime = 0;
public function __construct() {
try {
$this->db = PHPUnit_Smarty::$pdo;
} catch (PDOException $e) {
throw new Exception('Mysql Resource failed: ' . $e->getMessage());
}
$this->fetch = $this->db->prepare('SELECT modified, content FROM output_cache WHERE id = :id');
$this->fetchTimestamp = $this->db->prepare('SELECT modified FROM output_cache WHERE id = :id');
$this->save = $this->db->prepare('REPLACE INTO output_cache (id, name, cache_id, compile_id, content)
VALUES (:id, :name, :cache_id, :compile_id, :content)');
protected function db(): PDO {
return PHPUnit_Smarty::$pdo;
}
public function hasLock(Smarty $smarty, Cached $cached)
public function hasLock(\Smarty\Smarty $smarty, Cached $cached)
{
if ($this->lockTime) {
$this->lockTime--;

View File

@@ -9,20 +9,8 @@
* @package CacheResource-examples
* @author Uwe Tews
*/
class My_CacheResource_Apc extends \Smarty\Cacheresource\KeyValueStore
class Smarty_CacheResource_Apc extends \Smarty\Cacheresource\KeyValueStore
{
/**
* Smarty_CacheResource_Apc constructor.
*
* @throws \Exception
*/
public function __construct()
{
// test if APC is present
if (!function_exists('apc_cache_info')) {
throw new Exception('APC Template Caching Error: APC is not installed');
}
}
/**
* Read values for a set of keys from cache

View File

@@ -10,7 +10,7 @@
* @package CacheResource-examples
* @author Rodney Rehm
*/
class My_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
{
/**
* memcache instance

View File

@@ -24,43 +24,47 @@ use Smarty\Exception;
* @package CacheResource-examples
* @author Rodney Rehm
*/
class My_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
class Smarty_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
{
/**
* @var \PDO
*/
protected $db;
/**
* @var \PDOStatement
* @return PDO
* @throws Exception
*/
protected $fetch;
/**
* @var \PDOStatement
*/
protected $fetchTimestamp;
/**
* @var \PDOStatement
*/
protected $save;
/**
* Smarty_CacheResource_Mysql constructor.
*
* @throws \Smarty\Exception
*/
public function __construct()
{
protected function db(): PDO {
static $dbConn = null;
try {
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty");
return $dbConn ?? ($dbConn = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty"));
} catch (PDOException $e) {
throw new Exception('Mysql Resource failed: ' . $e->getMessage());
}
$this->fetch = $this->db->prepare('SELECT modified, content FROM output_cache WHERE id = :id');
$this->fetchTimestamp = $this->db->prepare('SELECT modified FROM output_cache WHERE id = :id');
$this->save = $this->db->prepare(
}
/**
* @return false|PDOStatement
* @throws Exception
*/
protected function fetchQuery() {
static $query = null;
return $query ?? $query = $this->db()->prepare('SELECT modified, content FROM output_cache WHERE id = :id');
}
/**
* @return false|PDOStatement
* @throws Exception
*/
protected function fetchTimestampQuery() {
static $query = null;
return $query ?? $query = $this->db()->prepare('SELECT modified FROM output_cache WHERE id = :id');
}
/**
* @return false|PDOStatement
* @throws Exception
*/
protected function saveQuery() {
static $query = null;
return $query ?? $query = $this->db()->prepare(
'REPLACE INTO output_cache (id, name, cache_id, compile_id, content)
VALUES (:id, :name, :cache_id, :compile_id, :content)'
);
@@ -77,12 +81,13 @@ class My_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
* @param integer $mtime cache modification timestamp (epoch)
*
* @return void
* @throws Exception
*/
protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime)
{
$this->fetch->execute(array('id' => $id));
$row = $this->fetch->fetch();
$this->fetch->closeCursor();
$this->fetchQuery()->execute(array('id' => $id));
$row = $this->fetchQuery()->fetch();
$this->fetchQuery()->closeCursor();
if ($row) {
$content = $row[ 'content' ];
$mtime = strtotime($row[ 'modified' ]);
@@ -107,9 +112,9 @@ class My_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
*/
protected function fetchTimestamp($id, $name, $cache_id, $compile_id)
{
$this->fetchTimestamp->execute(array('id' => $id));
$mtime = strtotime($this->fetchTimestamp->fetchColumn());
$this->fetchTimestamp->closeCursor();
$this->fetchTimestampQuery()->execute(array('id' => $id));
$mtime = strtotime($this->fetchTimestampQuery()->fetchColumn());
$this->fetchTimestampQuery()->closeCursor();
return $mtime;
}
@@ -127,14 +132,14 @@ class My_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
*/
protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content)
{
$this->save->execute(
$this->saveQuery()->execute(
array('id' => $id,
'name' => $name,
'cache_id' => $cache_id,
'compile_id' => $compile_id,
'content' => $content,)
);
return !!$this->save->rowCount();
return !!$this->saveQuery()->rowCount();
}
/**
@@ -152,18 +157,18 @@ class My_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
// delete the whole cache
if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) {
// returning the number of deleted caches would require a second query to count them
$query = $this->db->query('TRUNCATE TABLE output_cache');
$query = $this->db()->query('TRUNCATE TABLE output_cache');
return -1;
}
// build the filter
$where = array();
// equal test name
if ($name !== null) {
$where[] = 'name = ' . $this->db->quote($name);
$where[] = 'name = ' . $this->db()->quote($name);
}
// equal test compile_id
if ($compile_id !== null) {
$where[] = 'compile_id = ' . $this->db->quote($compile_id);
$where[] = 'compile_id = ' . $this->db()->quote($compile_id);
}
// range test expiration time
if ($exp_time !== null) {
@@ -173,13 +178,13 @@ class My_CacheResource_Mysql extends \Smarty\Cacheresource\Custom
if ($cache_id !== null) {
$where[] =
'(cache_id = ' .
$this->db->quote($cache_id) .
$this->db()->quote($cache_id) .
' OR cache_id LIKE ' .
$this->db->quote($cache_id . '|%') .
$this->db()->quote($cache_id . '|%') .
')';
}
// run delete query
$query = $this->db->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where));
$query = $this->db()->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where));
return $query->rowCount();
}
}

View File

@@ -28,7 +28,7 @@ use Smarty\Exception;
*
* @author Beno!t POLASZEK - 2014
*/
class My_CacheResource_Pdo extends \Smarty\Cacheresource\Custom
class Smarty_CacheResource_Pdo extends \Smarty\Cacheresource\Custom
{
/**
* @var string[]

View File

@@ -12,7 +12,7 @@ require_once __DIR__ . '/cacheresource.pdo.php';
* @require Smarty_CacheResource_Pdo class
* @author Beno!t POLASZEK - 2014
*/
class My_CacheResource_Pdo_Gzip extends My_CacheResource_Pdo
class Smarty_CacheResource_Pdo_Gzip extends Smarty_CacheResource_Pdo
{
/**
* Encodes the content before saving to database