diff options
Diffstat (limited to 'tests/UnitTests/__shared')
13 files changed, 873 insertions, 49 deletions
diff --git a/tests/UnitTests/__shared/PHPunitplugins/block.dummyblock.php b/tests/UnitTests/__shared/PHPunitplugins/block.dummyblock.php index 7de4fa09..b20ca8ec 100644 --- a/tests/UnitTests/__shared/PHPunitplugins/block.dummyblock.php +++ b/tests/UnitTests/__shared/PHPunitplugins/block.dummyblock.php @@ -2,8 +2,8 @@ /** * Smarty block plugin dummy for testing plugin functionallity * - * @package Smarty - * @subpackage PHPunitPlugin + + */ /** * Smarty {dummyblock} {/dummyblock} diff --git a/tests/UnitTests/__shared/PHPunitplugins/compiler.getparamsshort.php b/tests/UnitTests/__shared/PHPunitplugins/compiler.getparamsshort.php index e5907eb1..368b4a91 100644 --- a/tests/UnitTests/__shared/PHPunitplugins/compiler.getparamsshort.php +++ b/tests/UnitTests/__shared/PHPunitplugins/compiler.getparamsshort.php @@ -2,10 +2,12 @@ /** * Smarty plugin params * - * @package Smarty - * @subpackage PHPunitPlugin + + */ +use Smarty\Compile\Base; + /** * Smarty {getparams} * @@ -14,13 +16,13 @@ * * @return string */ -class smarty_compiler_getparamsshort extends Smarty_Internal_CompileBase +class smarty_compiler_getparamsshort extends Base { /** * Attribute definition: Overwrites base class. * * @var array - * @see Smarty_Internal_CompileBase + * @see Base */ public $required_attributes = array(); @@ -28,18 +30,18 @@ class smarty_compiler_getparamsshort extends Smarty_Internal_CompileBase * Attribute definition: Overwrites base class. * * @var array - * @see Smarty_Internal_CompileBase + * @see Base */ public $optional_attributes = array('_any'); /** * Attribute definition: Overwrites base class. * * @var array - * @see Smarty_Internal_CompileBase + * @see Base */ public $shorttag_order = array('s1', 's2', 's3'); - public function compile($args, $compiler) + public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) { $_attr = $this->getAttributes($compiler, $args); $output = '<?php echo "array('; diff --git a/tests/UnitTests/__shared/PHPunitplugins/function.checkconfigvar.php b/tests/UnitTests/__shared/PHPunitplugins/function.checkconfigvar.php index c026793b..94fcc2c9 100644 --- a/tests/UnitTests/__shared/PHPunitplugins/function.checkconfigvar.php +++ b/tests/UnitTests/__shared/PHPunitplugins/function.checkconfigvar.php @@ -2,10 +2,12 @@ /** * Smarty plugin for testing scopes in config vars * - * @package Smarty - * @subpackage PHPunitPlugin + + */ +use Smarty\Template; + /** * Smarty {checkconfigvar} * @@ -17,29 +19,29 @@ function smarty_function_checkconfigvar($params, $template) { $output = ''; - $types = array('template', 'data', 'smarty'); + $types = array('template', 'data', 'global'); if (isset($params['types'])) { $types = (array)$params['types']; } $var = $params['var']; $ptr = $template; while ($ptr) { - if (in_array('template', $types) && $ptr instanceof Smarty_Internal_Template) { - $output .= "#{$ptr->source->name}:\${$var} ="; - $output .= isset($ptr->config_vars[$var]) ? preg_replace('/\s/', '', var_export($ptr->config_vars[$var], true)) : 'null'; + if (in_array('template', $types) && $ptr instanceof Template) { + $output .= "#{$ptr->getSource()->name}:\${$var} ="; + $output .= $ptr->hasConfigVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getConfigVariable($var), true)) : 'null'; $ptr = $ptr->parent; - } elseif (in_array('data', $types) && $ptr instanceof Smarty_Data) { + } elseif (in_array('data', $types) && !($ptr instanceof Template || $ptr instanceof \Smarty\Smarty)) { $output .= "#data:\${$var} ="; - $output .= isset($ptr->config_vars[$var]) ? preg_replace('/\s/', '', var_export($ptr->config_vars[$var], true)) : 'null'; + $output .= $ptr->hasConfigVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getConfigVariable($var), true)) : 'null'; $ptr = $ptr->parent; } else { $ptr = null; } } - if (in_array('smarty', $types)) { - $output .= "#Smarty:\${$var} ="; - $output .= isset($template->smarty->config_vars[ $var ]) ? - preg_replace('/\s/', '', var_export($template->smarty->config_vars[ $var ], true)) : 'null'; + if (in_array('global', $types)) { + $output .= "#global:\${$var} ="; + $output .= $template->getSmarty()->hasConfigVariable($var) ? + preg_replace('/\s/', '', var_export($template->getSmarty()->getConfigVariable($var), true)) : 'null'; } return $output; } diff --git a/tests/UnitTests/__shared/PHPunitplugins/function.checkvar.php b/tests/UnitTests/__shared/PHPunitplugins/function.checkvar.php index 5d549c8b..62a4e674 100644 --- a/tests/UnitTests/__shared/PHPunitplugins/function.checkvar.php +++ b/tests/UnitTests/__shared/PHPunitplugins/function.checkvar.php @@ -2,55 +2,52 @@ /** * Smarty plugin for testing scopes * - * @package Smarty - * @subpackage PHPunitPlugin + + */ +use Smarty\Template; + /** * Smarty {checkvar} * * @param array $params parameter array - * @param object $template template object + * @param Template $template template object * * @return string */ -function smarty_function_checkvar($params, $template) +function smarty_function_checkvar($params, \Smarty\Template $template) { $output = ''; - $types = array('template', 'data', 'smarty', 'global'); + $types = ['template', 'data', 'global']; if (isset($params['types'])) { $types = (array)$params['types']; } $var = $params['var']; $ptr = $template; while ($ptr) { - if (in_array('template', $types) && $ptr instanceof Smarty_Internal_Template) { - $output .= "#{$ptr->source->name}:\${$var} ="; - $output .= isset($ptr->tpl_vars[$var]) ? preg_replace('/\s/', '', var_export($ptr->tpl_vars[$var]->value, true)) : '>unassigned<'; + if (in_array('template', $types) && $ptr instanceof Template) { + $output .= "#{$ptr->getSource()->name}:\${$var} ="; + $output .= $ptr->hasVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getValue($var), true)) : '>unassigned<'; $i = 0; - while (isset($ptr->_cache[ 'varStack' ][ $i ])) { - $output .= "#{$ptr->_cache[ 'varStack' ][ $i ]['name']} = "; - $output .= isset($ptr->_cache[ 'varStack' ][ $i ][ 'tpl' ][$var]) ? preg_replace('/\s/', '', var_export($ptr->_cache[ 'varStack' ][ $i ][ 'tpl' ][$var]->value, true)) : '>unassigned<'; + while (isset($ptr->_var_stack[ $i ])) { + $output .= "#{$ptr->_var_stack[ $i ]['name']} = "; + $output .= isset($ptr->_var_stack[ $i ][ 'tpl' ][$var]) ? preg_replace('/\s/', '', var_export($ptr->_var_stack[ $i ][ 'tpl' ][$var]->value, true)) : '>unassigned<'; $i ++; } $ptr = $ptr->parent; - } elseif (in_array('data', $types) && $ptr instanceof Smarty_Data) { + } elseif (in_array('data', $types) && !($ptr instanceof Template || $ptr instanceof \Smarty\Smarty)) { $output .= "#data:\${$var} ="; - $output .= isset($ptr->tpl_vars[$var]) ? preg_replace('/\s/', '', var_export($ptr->tpl_vars[$var]->value, true)) : '>unassigned<'; + $output .= $ptr->hasVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getValue($var), true)) : '>unassigned<'; $ptr = $ptr->parent; } else { $ptr = null; } } - if (in_array('smarty', $types)) { - $output .= "#Smarty:\${$var} ="; - $output .= isset($template->smarty->tpl_vars[ $var ]) ? - preg_replace('/\s/', '', var_export($template->smarty->tpl_vars[ $var ]->value, true)) : '>unassigned<'; - } if (in_array('global', $types)) { $output .= "#global:\${$var} ="; - $output .= isset(Smarty::$global_tpl_vars[ $var ]) ? - preg_replace('/\s/', '', var_export(Smarty::$global_tpl_vars[ $var ]->value, true)) : '>unassigned<'; + $output .= $template->getSmarty()->hasVariable($var) ? + preg_replace('/\s/', '', var_export($template->getSmarty()->getValue($var), true)) : '>unassigned<'; } return $output; } diff --git a/tests/UnitTests/__shared/PHPunitplugins/function.getparams.php b/tests/UnitTests/__shared/PHPunitplugins/function.getparams.php index be1c26ab..41075800 100644 --- a/tests/UnitTests/__shared/PHPunitplugins/function.getparams.php +++ b/tests/UnitTests/__shared/PHPunitplugins/function.getparams.php @@ -2,10 +2,12 @@ /** * Smarty plugin params * - * @package Smarty - * @subpackage PHPunitPlugin + + */ +use Smarty\Template; + /** * Smarty {gatparams} * @@ -14,7 +16,7 @@ * * @return string */ -function smarty_function_getparams($params, Smarty_Internal_Template $template) +function smarty_function_getparams($params, Template $template) { return var_export($params, true); } diff --git a/tests/UnitTests/__shared/PHPunitplugins/function.getvar.php b/tests/UnitTests/__shared/PHPunitplugins/function.getvar.php index 2b78fbbb..c1b0756b 100644 --- a/tests/UnitTests/__shared/PHPunitplugins/function.getvar.php +++ b/tests/UnitTests/__shared/PHPunitplugins/function.getvar.php @@ -2,10 +2,12 @@ /** * Smarty plugin getvar * - * @package Smarty - * @subpackage PHPunitPlugin + + */ +use Smarty\Template; + /** * Smarty {getvar} * @@ -14,7 +16,7 @@ * * @return string */ -function smarty_function_getvar($params, Smarty_Internal_Template $template) +function smarty_function_getvar($params, Template $template) { if (isset($params[ 'assign' ])) { $template->assign($params[ 'assign' ], $template->getTemplateVars($params[ 'var' ])); diff --git a/tests/UnitTests/__shared/PHPunitplugins/function.pluginassign.php b/tests/UnitTests/__shared/PHPunitplugins/function.pluginassign.php index 111d9d05..7786b742 100644 --- a/tests/UnitTests/__shared/PHPunitplugins/function.pluginassign.php +++ b/tests/UnitTests/__shared/PHPunitplugins/function.pluginassign.php @@ -2,8 +2,8 @@ /** * Smarty plugin for assign * - * @package Smarty - * @subpackage PHPunitPlugin + + */ /** diff --git a/tests/UnitTests/__shared/cacheresources/cacheresource.apc.php b/tests/UnitTests/__shared/cacheresources/cacheresource.apc.php new file mode 100644 index 00000000..3f437888 --- /dev/null +++ b/tests/UnitTests/__shared/cacheresources/cacheresource.apc.php @@ -0,0 +1,73 @@ +<?php + +/** + * APC CacheResource + * CacheResource Implementation based on the KeyValueStore API to use + * memcache as the storage resource for Smarty's output caching. + * * + * + + * @author Uwe Tews + */ +class Smarty_CacheResource_Apc extends \Smarty\Cacheresource\KeyValueStore +{ + + /** + * Read values for a set of keys from cache + * + * @param array $keys list of keys to fetch + * + * @return array list of values with the given keys used as indexes + * @return boolean true on success, false on failure + */ + protected function read(array $keys) + { + $_res = array(); + $res = apc_fetch($keys); + foreach ($res as $k => $v) { + $_res[ $k ] = $v; + } + return $_res; + } + + /** + * Save values for a set of keys to cache + * + * @param array $keys list of values to save + * @param int $expire expiration time + * + * @return boolean true on success, false on failure + */ + protected function write(array $keys, $expire = null) + { + foreach ($keys as $k => $v) { + apc_store($k, $v, $expire); + } + return true; + } + + /** + * Remove values from cache + * + * @param array $keys list of keys to delete + * + * @return boolean true on success, false on failure + */ + protected function delete(array $keys) + { + foreach ($keys as $k) { + apc_delete($k); + } + return true; + } + + /** + * Remove *all* values from cache + * + * @return boolean true on success, false on failure + */ + protected function purge() + { + return apc_clear_cache('user'); + } +} diff --git a/tests/UnitTests/__shared/cacheresources/cacheresource.memcache.php b/tests/UnitTests/__shared/cacheresources/cacheresource.memcache.php new file mode 100644 index 00000000..bc212a82 --- /dev/null +++ b/tests/UnitTests/__shared/cacheresources/cacheresource.memcache.php @@ -0,0 +1,101 @@ +<?php + +/** + * Memcache CacheResource + * CacheResource Implementation based on the KeyValueStore API to use + * memcache as the storage resource for Smarty's output caching. + * Note that memcache has a limitation of 256 characters per cache-key. + * To avoid complications all cache-keys are translated to a sha1 hash. + * + + * @author Rodney Rehm + */ +class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore +{ + /** + * memcache instance + * + * @var Memcache + */ + private $memcache = null; + + /** + * @return Memcache|Memcached + */ + public function getMemcache() { + if ($this->memcache === null) { + if (class_exists('Memcached')) { + $this->memcache = new Memcached(); + } else { + $this->memcache = new Memcache(); + } + $this->memcache->addServer('127.0.0.1', 11211); + } + return $this->memcache; + } + + /** + * Read values for a set of keys from cache + * + * @param array $keys list of keys to fetch + * + * @return array list of values with the given keys used as indexes + * @return boolean true on success, false on failure + */ + protected function read(array $keys) + { + $res = array(); + foreach ($keys as $key) { + $k = sha1($key); + $res[$key] = $this->getMemcache()->get($k); + } + return $res; + } + + /** + * Save values for a set of keys to cache + * + * @param array $keys list of values to save + * @param int $expire expiration time + * + * @return boolean true on success, false on failure + */ + protected function write(array $keys, $expire = null) + { + foreach ($keys as $k => $v) { + $k = sha1($k); + if (class_exists('Memcached')) { + $this->getMemcache()->set($k, $v, $expire); + } else { + $this->getMemcache()->set($k, $v, 0, $expire); + } + } + return true; + } + + /** + * Remove values from cache + * + * @param array $keys list of keys to delete + * + * @return boolean true on success, false on failure + */ + protected function delete(array $keys) + { + foreach ($keys as $k) { + $k = sha1($k); + $this->getMemcache()->delete($k); + } + return true; + } + + /** + * Remove *all* values from cache + * + * @return boolean true on success, false on failure + */ + protected function purge() + { + return $this->getMemcache()->flush(); + } +} diff --git a/tests/UnitTests/__shared/cacheresources/cacheresource.mysql.php b/tests/UnitTests/__shared/cacheresources/cacheresource.mysql.php new file mode 100644 index 00000000..9b51c272 --- /dev/null +++ b/tests/UnitTests/__shared/cacheresources/cacheresource.mysql.php @@ -0,0 +1,190 @@ +<?php + +use Smarty\Exception; + +/** + * MySQL CacheResource + * CacheResource Implementation based on the Custom API to use + * MySQL as the storage resource for Smarty's output caching. + * Table definition: + * <pre>CREATE TABLE IF NOT EXISTS `output_cache` ( + * `id` CHAR(40) NOT NULL COMMENT 'sha1 hash', + * `name` VARCHAR(250) NOT NULL, + * `cache_id` VARCHAR(250) NULL DEFAULT NULL, + * `compile_id` VARCHAR(250) NULL DEFAULT NULL, + * `modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + * `content` LONGTEXT NOT NULL, + * PRIMARY KEY (`id`), + * INDEX(`name`), + * INDEX(`cache_id`), + * INDEX(`compile_id`), + * INDEX(`modified`) + * ) ENGINE = InnoDB;</pre> + * + + * @author Rodney Rehm + */ +class Smarty_CacheResource_Mysql extends \Smarty\Cacheresource\Custom +{ + + /** + * @return PDO + * @throws Exception + */ + protected function db(): PDO { + static $dbConn = null; + try { + 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()); + } + } + + /** + * @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)' + ); + } + + /** + * fetch cached content and its modification time from data source + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param string $content cached content + * @param integer $mtime cache modification timestamp (epoch) + * + * @return void + * @throws Exception + */ + protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime) + { + $this->fetchQuery()->execute(array('id' => $id)); + $row = $this->fetchQuery()->fetch(); + $this->fetchQuery()->closeCursor(); + if ($row) { + $content = $row[ 'content' ]; + $mtime = strtotime($row[ 'modified' ]); + } else { + $content = null; + $mtime = null; + } + } + + /** + * Fetch cached content's modification timestamp from data source + * + * @note implementing this method is optional. Only implement it if modification times can be accessed faster than + * loading the complete cached content. + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * + * @return integer|boolean timestamp (epoch) the template was modified, or false if not found + */ + protected function fetchTimestamp($id, $name, $cache_id, $compile_id) + { + $this->fetchTimestampQuery()->execute(array('id' => $id)); + $mtime = strtotime($this->fetchTimestampQuery()->fetchColumn()); + $this->fetchTimestampQuery()->closeCursor(); + return $mtime; + } + + /** + * Save content to cache + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param integer|null $exp_time seconds till expiration time in seconds or null + * @param string $content content to cache + * + * @return boolean success + */ + protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content) + { + $this->saveQuery()->execute( + array('id' => $id, + 'name' => $name, + 'cache_id' => $cache_id, + 'compile_id' => $compile_id, + 'content' => $content,) + ); + return !!$this->saveQuery()->rowCount(); + } + + /** + * Delete content from cache + * + * @param string $name template name + * @param string $cache_id cache id + * @param string $compile_id compile id + * @param integer|null $exp_time seconds till expiration or null + * + * @return integer number of deleted caches + */ + protected function delete($name, $cache_id, $compile_id, $exp_time) + { + // 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'); + return -1; + } + // build the filter + $where = array(); + // equal test name + if ($name !== null) { + $where[] = 'name = ' . $this->db()->quote($name); + } + // equal test compile_id + if ($compile_id !== null) { + $where[] = 'compile_id = ' . $this->db()->quote($compile_id); + } + // range test expiration time + if ($exp_time !== null) { + $where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)'; + } + // equal test cache_id and match sub-groups + if ($cache_id !== null) { + $where[] = + '(cache_id = ' . + $this->db()->quote($cache_id) . + ' OR cache_id LIKE ' . + $this->db()->quote($cache_id . '|%') . + ')'; + } + // run delete query + $query = $this->db()->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where)); + return $query->rowCount(); + } +} diff --git a/tests/UnitTests/__shared/cacheresources/cacheresource.pdo.php b/tests/UnitTests/__shared/cacheresources/cacheresource.pdo.php new file mode 100644 index 00000000..8be18ec9 --- /dev/null +++ b/tests/UnitTests/__shared/cacheresources/cacheresource.pdo.php @@ -0,0 +1,347 @@ +<?php + +use Smarty\Exception; + +/** + * PDO Cache Handler + * Allows you to store Smarty Cache files into your db. + * Example table : + * CREATE TABLE `smarty_cache` ( + * `id` char(40) NOT NULL COMMENT 'sha1 hash', + * `name` varchar(250) NOT NULL, + * `cache_id` varchar(250) DEFAULT NULL, + * `compile_id` varchar(250) DEFAULT NULL, + * `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + * `expire` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + * `content` mediumblob NOT NULL, + * PRIMARY KEY (`id`), + * KEY `name` (`name`), + * KEY `cache_id` (`cache_id`), + * KEY `compile_id` (`compile_id`), + * KEY `modified` (`modified`), + * KEY `expire` (`expire`) + * ) ENGINE=InnoDB + * Example usage : + * $cnx = new PDO("mysql:host=localhost;dbname=mydb", "username", "password"); + * $smarty->setCachingType('pdo'); + * $smarty->registerCacheResource('pdo', new Smarty_CacheResource_Pdo($cnx, 'smarty_cache')); + * + * @author Beno!t POLASZEK - 2014 + */ +class Smarty_CacheResource_Pdo extends \Smarty\Cacheresource\Custom +{ + /** + * @var string[] + */ + protected $fetchStatements = array('default' => 'SELECT %2$s + FROM %1$s + WHERE 1 + AND id = :id + AND cache_id IS NULL + AND compile_id IS NULL', + 'withCacheId' => 'SELECT %2$s + FROM %1$s + WHERE 1 + AND id = :id + AND cache_id = :cache_id + AND compile_id IS NULL', + 'withCompileId' => 'SELECT %2$s + FROM %1$s + WHERE 1 + AND id = :id + AND compile_id = :compile_id + AND cache_id IS NULL', + 'withCacheIdAndCompileId' => 'SELECT %2$s + FROM %1$s + WHERE 1 + AND id = :id + AND cache_id = :cache_id + AND compile_id = :compile_id'); + + /** + * @var string + */ + protected $insertStatement = 'INSERT INTO %s + + SET id = :id, + name = :name, + cache_id = :cache_id, + compile_id = :compile_id, + modified = CURRENT_TIMESTAMP, + expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND), + content = :content + + ON DUPLICATE KEY UPDATE + name = :name, + cache_id = :cache_id, + compile_id = :compile_id, + modified = CURRENT_TIMESTAMP, + expire = DATE_ADD(CURRENT_TIMESTAMP, INTERVAL :expire SECOND), + content = :content'; + + /** + * @var string + */ + protected $deleteStatement = 'DELETE FROM %1$s WHERE %2$s'; + + /** + * @var string + */ + protected $truncateStatement = 'TRUNCATE TABLE %s'; + + /** + * @var string + */ + protected $fetchColumns = 'modified, content'; + + /** + * @var string + */ + protected $fetchTimestampColumns = 'modified'; + + /** + * @var \PDO + */ + protected $pdo; + + /** + * @var + */ + protected $table; + + /** + * @var null + */ + protected $database; + + /** + * Constructor + * + * @param PDO $pdo PDO : active connection + * @param string $table : table (or view) name + * @param string $database : optional - if table is located in another db + * + * @throws \Smarty\Exception + */ + public function __construct(PDO $pdo, $table, $database = null) + { + if (is_null($table)) { + throw new Exception("Table name for caching can't be null"); + } + $this->pdo = $pdo; + $this->table = $table; + $this->database = $database; + $this->fillStatementsWithTableName(); + } + + /** + * Fills the table name into the statements. + * + * @return $this Current Instance + * @access protected + */ + protected function fillStatementsWithTableName() + { + foreach ($this->fetchStatements as &$statement) { + $statement = sprintf($statement, $this->getTableName(), '%s'); + } + $this->insertStatement = sprintf($this->insertStatement, $this->getTableName()); + $this->deleteStatement = sprintf($this->deleteStatement, $this->getTableName(), '%s'); + $this->truncateStatement = sprintf($this->truncateStatement, $this->getTableName()); + return $this; + } + + /** + * Gets the fetch statement, depending on what you specify + * + * @param string $columns : the column(s) name(s) you want to retrieve from the database + * @param string $id unique cache content identifier + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * + * @access protected + * @return \PDOStatement + */ + protected function getFetchStatement($columns, $id, $cache_id = null, $compile_id = null) + { + $args = array(); + if (!is_null($cache_id) && !is_null($compile_id)) { + $query = $this->fetchStatements[ 'withCacheIdAndCompileId' ] and + $args = array('id' => $id, 'cache_id' => $cache_id, 'compile_id' => $compile_id); + } elseif (is_null($cache_id) && !is_null($compile_id)) { + $query = $this->fetchStatements[ 'withCompileId' ] and + $args = array('id' => $id, 'compile_id' => $compile_id); + } elseif (!is_null($cache_id) && is_null($compile_id)) { + $query = $this->fetchStatements[ 'withCacheId' ] and $args = array('id' => $id, 'cache_id' => $cache_id); + } else { + $query = $this->fetchStatements[ 'default' ] and $args = array('id' => $id); + } + $query = sprintf($query, $columns); + $stmt = $this->pdo->prepare($query); + foreach ($args as $key => $value) { + $stmt->bindValue($key, $value); + } + return $stmt; + } + + /** + * fetch cached content and its modification time from data source + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * @param string $content cached content + * @param integer $mtime cache modification timestamp (epoch) + * + * @return void + * @access protected + */ + protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime) + { + $stmt = $this->getFetchStatement($this->fetchColumns, $id, $cache_id, $compile_id); + $stmt->execute(); + $row = $stmt->fetch(); + $stmt->closeCursor(); + if ($row) { + $content = $this->outputContent($row[ 'content' ]); + $mtime = strtotime($row[ 'modified' ]); + } else { + $content = null; + $mtime = null; + } + } + + /** + * Fetch cached content's modification timestamp from data source + * {@internal implementing this method is optional. + * Only implement it if modification times can be accessed faster than loading the complete cached content.}} + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * + * @return integer|boolean timestamp (epoch) the template was modified, or false if not found + * @access protected + */ + // protected function fetchTimestamp($id, $name, $cache_id = null, $compile_id = null) { + // $stmt = $this->getFetchStatement($this->fetchTimestampColumns, $id, $cache_id, $compile_id); + // $stmt -> execute(); + // $mtime = strtotime($stmt->fetchColumn()); + // $stmt -> closeCursor(); + // return $mtime; + // } + /** + * Save content to cache + * + * @param string $id unique cache content identifier + * @param string $name template name + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * @param integer|null $exp_time seconds till expiration time in seconds or null + * @param string $content content to cache + * + * @return boolean success + * @access protected + */ + protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content) + { + $stmt = $this->pdo->prepare($this->insertStatement); + $stmt->bindValue('id', $id); + $stmt->bindValue('name', $name); + $stmt->bindValue('cache_id', $cache_id, (is_null($cache_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR); + $stmt->bindValue('compile_id', $compile_id, (is_null($compile_id)) ? PDO::PARAM_NULL : PDO::PARAM_STR); + $stmt->bindValue('expire', (int)$exp_time, PDO::PARAM_INT); + $stmt->bindValue('content', $this->inputContent($content)); + $stmt->execute(); + return !!$stmt->rowCount(); + } + + /** + * Encodes the content before saving to database + * + * @param string $content + * + * @return string $content + * @access protected + */ + protected function inputContent($content) + { + return $content; + } + + /** + * Decodes the content before saving to database + * + * @param string $content + * + * @return string $content + * @access protected + */ + protected function outputContent($content) + { + return $content; + } + + /** + * Delete content from cache + * + * @param string|null $name template name + * @param string|null $cache_id cache id + * @param string|null $compile_id compile id + * @param integer|null|-1 $exp_time seconds till expiration or null + * + * @return integer number of deleted caches + * @access protected + */ + protected function delete($name = null, $cache_id = null, $compile_id = null, $exp_time = null) + { + // 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 + $this->pdo->query($this->truncateStatement); + return -1; + } + // build the filter + $where = array(); + // equal test name + if ($name !== null) { + $where[] = 'name = ' . $this->pdo->quote($name); + } + // equal test cache_id and match sub-groups + if ($cache_id !== null) { + $where[] = + '(cache_id = ' . + $this->pdo->quote($cache_id) . + ' OR cache_id LIKE ' . + $this->pdo->quote($cache_id . '|%') . + ')'; + } + // equal test compile_id + if ($compile_id !== null) { + $where[] = 'compile_id = ' . $this->pdo->quote($compile_id); + } + // for clearing expired caches + if ($exp_time === \Smarty\Smarty::CLEAR_EXPIRED) { + $where[] = 'expire < CURRENT_TIMESTAMP'; + } // range test expiration time + elseif ($exp_time !== null) { + $where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)'; + } + // run delete query + $query = $this->pdo->query(sprintf($this->deleteStatement, join(' AND ', $where))); + return $query->rowCount(); + } + + /** + * Gets the formatted table name + * + * @return string + * @access protected + */ + protected function getTableName() + { + return (is_null($this->database)) ? "`{$this->table}`" : "`{$this->database}`.`{$this->table}`"; + } +} diff --git a/tests/UnitTests/__shared/cacheresources/cacheresource.pdo_gzip.php b/tests/UnitTests/__shared/cacheresources/cacheresource.pdo_gzip.php new file mode 100644 index 00000000..89818abb --- /dev/null +++ b/tests/UnitTests/__shared/cacheresources/cacheresource.pdo_gzip.php @@ -0,0 +1,42 @@ +<?php + +require_once __DIR__ . '/cacheresource.pdo.php'; + +/** + * PDO Cache Handler with GZIP support + * Example usage : + * $cnx = new PDO("mysql:host=localhost;dbname=mydb", "username", "password"); + * $smarty->setCachingType('pdo_gzip'); + * $smarty->registerCacheResource('pdo_gzip', new Smarty_CacheResource_Pdo_Gzip($cnx, 'smarty_cache')); + * + * @require Smarty_CacheResource_Pdo class + * @author Beno!t POLASZEK - 2014 + */ +class Smarty_CacheResource_Pdo_Gzip extends Smarty_CacheResource_Pdo +{ + /** + * Encodes the content before saving to database + * + * @param string $content + * + * @return string $content + * @access protected + */ + protected function inputContent($content) + { + return gzdeflate($content); + } + + /** + * Decodes the content before saving to database + * + * @param string $content + * + * @return string $content + * @access protected + */ + protected function outputContent($content) + { + return gzinflate($content); + } +} diff --git a/tests/UnitTests/__shared/resources/resource.extendsall.php b/tests/UnitTests/__shared/resources/resource.extendsall.php new file mode 100644 index 00000000..9ffddc05 --- /dev/null +++ b/tests/UnitTests/__shared/resources/resource.extendsall.php @@ -0,0 +1,66 @@ +<?php + +use Smarty\Exception; +use Smarty\Template; +use Smarty\Template\Source; + +/** + * Extends All Resource + * Resource Implementation modifying the extends-Resource to walk + * through the template_dirs and inherit all templates of the same name + * + + * @author Rodney Rehm + */ +class My_Resource_Extendsall extends \Smarty\Resource\ExtendsPlugin +{ + /** + * populate Source Object with meta data from Resource + * + * @param Source $source source object + * @param Template $_template template object + * + * @return void + */ + public function populate(Source $source, Template $_template = null) + { + $uid = ''; + $sources = array(); + $timestamp = 0; + foreach ($source->getSmarty()->getTemplateDir() as $key => $directory) { + try { + $s = \Smarty\Template\Source::load(null, $source->getSmarty(), + 'file:' . '[' . $key . ']' . $source->name); + if (!$s->exists) { + continue; + } + $sources[ $s->uid ] = $s; + $uid .= $s->uid; + $timestamp = $s->timestamp > $timestamp ? $s->timestamp : $timestamp; + } catch (Exception $e) { + } + } + if (!$sources) { + $source->exists = false; + return; + } + $sources = array_reverse($sources, true); + reset($sources); + $s = current($sources); + $source->components = $sources; + $source->uid = sha1($uid . $source->getSmarty()->_joined_template_dir); + $source->exists = true; + $source->timestamp = $timestamp; + } + + /** + * Disable timestamp checks for extendsall resource. + * The individual source components will be checked. + * + * @return bool false + */ + public function checkTimestamps() + { + return false; + } +} |
