WIP moving Smarty to PSR-4.

This commit is contained in:
Simon Wisselink
2023-01-02 00:49:38 +01:00
parent 6b9e2fadd1
commit 60a56969dd
103 changed files with 1161 additions and 2101 deletions

View File

@@ -1,104 +0,0 @@
<?php
use Smarty\Resource\CustomPlugin;
use Smarty\Exception;
/**
* MySQL Resource
* Resource Implementation based on the Custom API to use
* MySQL as the storage resource for Smarty's templates and configs.
* Table definition:
* <pre>CREATE TABLE IF NOT EXISTS `templates` (
* `name` varchar(100) NOT NULL,
* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
* `source` text,
* PRIMARY KEY (`name`)
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8;</pre>
* Demo data:
* <pre>INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello
* world"}{$x}');</pre>
*
*
* @package Resource-examples
* @author Rodney Rehm
*/
class _MysqlPlugin extends CustomPlugin
{
/**
* PDO instance
*
* @var \PDO
*/
protected $db;
/**
* prepared fetch() statement
*
* @var \PDOStatement
*/
protected $fetch;
/**
* prepared fetchTimestamp() statement
*
* @var \PDOStatement
*/
protected $mtime;
/**
* Smarty_Resource_Mysql constructor.
*
* @throws \Smarty\Exception
*/
public function __construct()
{
try {
$this->db = 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, source FROM templates WHERE name = :name');
$this->mtime = $this->db->prepare('SELECT modified FROM templates WHERE name = :name');
}
/**
* Fetch a template and its modification time from database
*
* @param string $name template name
* @param string $source template source
* @param integer $mtime template modification timestamp (epoch)
*
* @return void
*/
protected function fetch($name, &$source, &$mtime)
{
$this->fetch->execute(array('name' => $name));
$row = $this->fetch->fetch();
$this->fetch->closeCursor();
if ($row) {
$source = $row[ 'source' ];
$mtime = strtotime($row[ 'modified' ]);
} else {
$source = null;
$mtime = null;
}
}
/**
* Fetch a template's modification time from database
*
* @note implementing this method is optional. Only implement it if modification times can be accessed faster than
* loading the comple template source.
*
* @param string $name template name
*
* @return integer timestamp (epoch) the template was modified
*/
protected function fetchTimestamp($name)
{
$this->mtime->execute(array('name' => $name));
$mtime = $this->mtime->fetchColumn();
$this->mtime->closeCursor();
return strtotime($mtime);
}
}

View File

@@ -1,80 +0,0 @@
<?php
use Smarty\Resource\CustomPlugin;
use Smarty\Exception;
/**
* MySQL Resource
* Resource Implementation based on the Custom API to use
* MySQL as the storage resource for Smarty's templates and configs.
* Note that this MySQL implementation fetches the source and timestamps in
* a single database query, instead of two separate like resource.mysql.php does.
* Table definition:
* <pre>CREATE TABLE IF NOT EXISTS `templates` (
* `name` varchar(100) NOT NULL,
* `modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
* `source` text,
* PRIMARY KEY (`name`)
* ) ENGINE=InnoDB DEFAULT CHARSET=utf8;</pre>
* Demo data:
* <pre>INSERT INTO `templates` (`name`, `modified`, `source`) VALUES ('test.tpl', "2010-12-25 22:00:00", '{$x="hello
* world"}{$x}');</pre>
*
*
* @package Resource-examples
* @author Rodney Rehm
*/
class _MysqlsPlugin extends CustomPlugin
{
/**
* PDO instance
*
* @var \PDO
*/
protected $db;
/**
* prepared fetch() statement
*
* @var \PDOStatement
*/
protected $fetch;
/**
* Smarty_Resource_Mysqls constructor.
*
* @throws \Smarty\Exception
*/
public function __construct()
{
try {
$this->db = 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, source FROM templates WHERE name = :name');
}
/**
* Fetch a template and its modification time from database
*
* @param string $name template name
* @param string $source template source
* @param integer $mtime template modification timestamp (epoch)
*
* @return void
*/
protected function fetch($name, &$source, &$mtime)
{
$this->fetch->execute(array('name' => $name));
$row = $this->fetch->fetch();
$this->fetch->closeCursor();
if ($row) {
$source = $row[ 'source' ];
$mtime = strtotime($row[ 'modified' ]);
} else {
$source = null;
$mtime = null;
}
}
}

View File

@@ -11,8 +11,7 @@ of the console.
Set [`$debugging`](../programmers/api-variables/variable-debugging.md) to TRUE in Smarty, and if needed Set [`$debugging`](../programmers/api-variables/variable-debugging.md) to TRUE in Smarty, and if needed
set [`$debug_tpl`](../programmers/api-variables/variable-debug-template.md) to the template resource set [`$debug_tpl`](../programmers/api-variables/variable-debug-template.md) to the template resource
path to `debug.tpl` (this is in [`SMARTY_DIR`](../programmers/smarty-constants.md) by path to `debug.tpl`. When you load the page, a Javascript console window will pop
default). When you load the page, a Javascript console window will pop
up and give you the names of all the included templates and assigned up and give you the names of all the included templates and assigned
variables for the current page. variables for the current page.

View File

@@ -37,7 +37,6 @@ and 480 for $height, the result is:
## Smarty for php developers ## Smarty for php developers
- [Charset Encoding](./programmers/charset.md) - [Charset Encoding](./programmers/charset.md)
- [Constants](./programmers/smarty-constants.md)
- [Smarty Class Variables](./programmers/api-variables.md) - [Smarty Class Variables](./programmers/api-variables.md)
- [Smarty Class Methods](./programmers/api-functions.md) - [Smarty Class Methods](./programmers/api-functions.md)
- [Caching](./programmers/caching.md) - [Caching](./programmers/caching.md)

View File

@@ -31,7 +31,9 @@ PARAMETER.COMPILEID
<?php <?php
include(SMARTY_DIR.'Smarty.class.php');
use Smarty\Smarty;
$smarty = new Smarty(); $smarty = new Smarty();
$smarty->setCaching(true); $smarty->setCaching(true);

View File

@@ -37,7 +37,6 @@ them directly, or use the corresponding setter/getter methods.
- [$left_delimiter](./api-variables/variable-left-delimiter.md) - [$left_delimiter](./api-variables/variable-left-delimiter.md)
- [$locking_timeout](./api-variables/variable-locking-timeout.md) - [$locking_timeout](./api-variables/variable-locking-timeout.md)
- [$merge_compiled_includes](./api-variables/variable-merge-compiled-includes.md) - [$merge_compiled_includes](./api-variables/variable-merge-compiled-includes.md)
- [$plugins_dir](./api-variables/variable-plugins-dir.md)
- [$right_delimiter](./api-variables/variable-right-delimiter.md) - [$right_delimiter](./api-variables/variable-right-delimiter.md)
- [$smarty_debug_id](./api-variables/variable-smarty-debug-id.md) - [$smarty_debug_id](./api-variables/variable-smarty-debug-id.md)
- [$template_dir](./api-variables/variable-template-dir.md) - [$template_dir](./api-variables/variable-template-dir.md)

View File

@@ -2,8 +2,7 @@
============ ============
This is the name of the template file used for the debugging console. By This is the name of the template file used for the debugging console. By
default, it is named `debug.tpl` and is located in the default, it is named `debug.tpl` and is located in `src/debug.tpl`.
[`SMARTY_DIR`](#constant.smarty.dir).
See also [`$debugging`](#variable.debugging) and the [debugging See also [`$debugging`](#variable.debugging) and the [debugging
console](#chapter.debugging.console) section. console](#chapter.debugging.console) section.

View File

@@ -1,28 +0,0 @@
\$plugins\_dir {#variable.plugins.dir}
==============
This is the directory or directories where Smarty will look for the
plugins that it needs. Default is `plugins/` under the
[`SMARTY_DIR`](#constant.smarty.dir). If you supply a relative path,
Smarty will first look under the [`SMARTY_DIR`](#constant.smarty.dir),
then relative to the current working directory, then relative to the PHP
include\_path. If `$plugins_dir` is an array of directories, Smarty will
search for your plugin in each plugin directory **in the order they are
given**.
> **Note**
>
> For best performance, do not setup your `$plugins_dir` to have to use
> the PHP include path. Use an absolute pathname, or a path relative to
> `SMARTY_DIR` or the current working directory.
> **Note**
>
> As of Smarty 3.1 the attribute \$plugins\_dir is no longer accessible
> directly. Use [`getPluginsDir()`](#api.get.plugins.dir),
> [`setPluginsDir()`](#api.set.plugins.dir) and
> [`addPluginsDir()`](#api.add.plugins.dir) instead.
See also [`getPluginsDir()`](#api.get.plugins.dir),
[`setPluginsDir()`](#api.set.plugins.dir) and
[`addPluginsDir()`](#api.add.plugins.dir).

View File

@@ -1,26 +0,0 @@
Constants {#smarty.constants}
=========
SMARTY\_DIR {#constant.smarty.dir}
===========
This is the **full system path** to the location of the Smarty class
files. If this is not defined in your script, then Smarty will attempt
to determine the appropriate value automatically. If defined, the path
**must end with a trailing slash/**.
<?php
// set path to Smarty directory *nix style
define('SMARTY_DIR', '/usr/local/lib/php/Smarty-v.e.r/libs/');
// path to Smarty windows style
define('SMARTY_DIR', 'c:/webroot/libs/Smarty-v.e.r/libs/');
// include the smarty class, note 'S' is upper case
require_once(SMARTY_DIR . 'Smarty.class.php');
?>
See also [`$smarty.const`](../designers/language-variables/language-variables-smarty.md).

View File

@@ -0,0 +1,18 @@
<?php
namespace Smarty\BlockHandler;
use Smarty\Template;
class BlockPluginWrapper implements BlockHandlerInterface {
private $callback;
public function __construct($callback) {
$this->callback = $callback;
}
public function handle($params, $content, Template $template, &$repeat) {
return call_user_func($this->callback, $params, $content, $template, $repeat);
}
}

View File

@@ -2,6 +2,8 @@
namespace Smarty\Cacheresource; namespace Smarty\Cacheresource;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Smarty\Smarty; use Smarty\Smarty;
use Smarty\Template; use Smarty\Template;
use Smarty\Template\Cached; use Smarty\Template\Cached;
@@ -206,7 +208,7 @@ class File extends Base
if (isset($resource_name)) { if (isset($resource_name)) {
$_save_stat = $smarty->caching; $_save_stat = $smarty->caching;
$smarty->caching = \Smarty\Smarty::CACHING_LIFETIME_CURRENT; $smarty->caching = \Smarty\Smarty::CACHING_LIFETIME_CURRENT;
$tpl = new $smarty->template_class($resource_name, $smarty); $tpl = new \Smarty\Template($resource_name, $smarty);
$smarty->caching = $_save_stat; $smarty->caching = $_save_stat;
// remove from template cache // remove from template cache
$tpl->source; // have the template registered before unset() $tpl->source; // have the template registered before unset()

View File

@@ -8,7 +8,9 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
namespace Smarty\Compile\Tag; namespace Smarty\Compile;
use Smarty\Compile\Tag\Base;
/** /**
* Smarty Internal Plugin Compile Block Plugin Class * Smarty Internal Plugin Compile Block Plugin Class
@@ -16,7 +18,7 @@ namespace Smarty\Compile\Tag;
* @package Smarty * @package Smarty
* @subpackage Compiler * @subpackage Compiler
*/ */
class PrivateBlockPlugin extends Base { class BlockCompiler extends Base {
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
@@ -83,14 +85,8 @@ class PrivateBlockPlugin extends Base {
$mod_content2 = "\$_block_content{$this->nesting}"; $mod_content2 = "\$_block_content{$this->nesting}";
$mod_content = "\$_block_content{$this->nesting} = ob_get_clean();\n"; $mod_content = "\$_block_content{$this->nesting} = ob_get_clean();\n";
$mod_pre = "ob_start();\n"; $mod_pre = "ob_start();\n";
$mod_post = 'echo ' . $compiler->compileTag( $mod_post = 'echo ' . $compiler->compileModifier($parameter['modifier_list'], 'ob_get_clean()')
'private_modifier', . ";\n";
[],
[
'modifierlist' => $parameter['modifier_list'],
'value' => 'ob_get_clean()',
]
) . ";\n";
} }
$output = $output =
"<?php {$mod_content}\$_block_repeat=false;\n{$mod_pre}echo {$callback}({$_params}, {$mod_content2}, \$_smarty_tpl, \$_block_repeat);\n{$mod_post}}\n"; "<?php {$mod_content}\$_block_repeat=false;\n{$mod_pre}echo {$callback}({$_params}, {$mod_content2}, \$_smarty_tpl, \$_block_repeat);\n{$mod_post}}\n";

View File

@@ -8,8 +8,9 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
namespace Smarty\Compile\Tag; namespace Smarty\Compile;
use Smarty\Compile\Tag\Base;
use Smarty\Compiler\Template; use Smarty\Compiler\Template;
use Smarty\Smarty; use Smarty\Smarty;
@@ -19,7 +20,7 @@ use Smarty\Smarty;
* @package Smarty * @package Smarty
* @subpackage Compiler * @subpackage Compiler
*/ */
class PrivateRegisteredFunction extends Base { class FunctionCallCompiler extends Base {
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
@@ -35,7 +36,8 @@ class PrivateRegisteredFunction extends Base {
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param Template $compiler compiler object * @param Template $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* @param string $tag name of function * @param string $tag name of tag
* @param string $function name of function
* *
* @return string compiled code * @return string compiled code
* @throws \Smarty\CompilerException * @throws \Smarty\CompilerException
@@ -45,21 +47,18 @@ class PrivateRegisteredFunction extends Base {
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
unset($_attr['nocache']); unset($_attr['nocache']);
if (isset($compiler->smarty->registered_plugins[Smarty::PLUGIN_FUNCTION][$tag])) {
$tag_info = $compiler->smarty->registered_plugins[Smarty::PLUGIN_FUNCTION][$tag];
$is_registered = true; $functionHandler = $compiler->smarty->getFunctionHandler($function);
} else {
$tag_info = $compiler->default_handler_plugins[Smarty::PLUGIN_FUNCTION][$tag];
$is_registered = false;
}
// not cacheable? // not cacheable?
$compiler->tag_nocache = $compiler->tag_nocache || !$tag_info[1]; $compiler->tag_nocache = $compiler->tag_nocache || !$functionHandler->isCacheable();
// convert attributes into parameter array string // convert attributes into parameter array string
$_paramsArray = []; $_paramsArray = [];
foreach ($_attr as $_key => $_value) { foreach ($_attr as $_key => $_value) {
if (is_int($_key)) { if (is_int($_key)) {
$_paramsArray[] = "$_key=>$_value"; $_paramsArray[] = "$_key=>$_value";
} elseif ($compiler->template->caching && in_array($_key, $tag_info[2])) { } elseif ($compiler->template->caching && in_array($_key, $functionHandler->getCacheAttributes())) {
$_value = str_replace('\'', "^#^", $_value); $_value = str_replace('\'', "^#^", $_value);
$_paramsArray[] = "'$_key'=>^#^.var_export($_value,true).^#^"; $_paramsArray[] = "'$_key'=>^#^.var_export($_value,true).^#^";
} else { } else {
@@ -67,29 +66,13 @@ class PrivateRegisteredFunction extends Base {
} }
} }
$_params = 'array(' . implode(',', $_paramsArray) . ')'; $_params = 'array(' . implode(',', $_paramsArray) . ')';
// compile code
if ($is_registered) { $output = "\$_smarty_tpl->smarty->getFunctionHandler(" . var_export($function, true) . ")";
$output = $output .= "->handle($_params, \$_smarty_tpl)";
"call_user_func_array( \$_smarty_tpl->smarty->registered_plugins[\\Smarty\\Smarty::PLUGIN_FUNCTION]['{$tag}'][0], array( {$_params},\$_smarty_tpl ) )";
} else {
$function = $tag_info[0];
if (!is_array($function)) {
$output = "{$function}({$_params},\$_smarty_tpl)";
} else {
$output = "{$function[0]}::{$function[1]}({$_params},\$_smarty_tpl)";
}
}
if (!empty($parameter['modifierlist'])) { if (!empty($parameter['modifierlist'])) {
$output = $compiler->compileTag( $output = $compiler->compileModifier($parameter['modifierlist'], $output);
'private_modifier',
[],
[
'modifierlist' => $parameter['modifierlist'],
'value' => $output,
]
);
} }
$output = "<?php echo {$output};?>\n"; return "<?php echo {$output};?>\n";
return $output;
} }
} }

View File

@@ -0,0 +1,19 @@
<?php
namespace Smarty\Compile\Modifier;
class BCPluginWrapper extends Base {
private $callback;
public function __construct($callback) {
$this->callback = $callback;
}
/**
* @inheritDoc
*/
public function compile($params, \Smarty\Compiler\Template $compiler) {
return call_user_func($this->callback, $params, $compiler);
}
}

View File

@@ -50,6 +50,6 @@ class EscapeModifierCompiler extends Base {
} catch (Exception $e) { } catch (Exception $e) {
// pass through to regular plugin fallback // pass through to regular plugin fallback
} }
return 'smarty_modifier_escape(' . join(', ', $params) . ')'; return '$_smarty_tpl->smarty->getModifierCallback(\'escape\')(' . join(', ', $params) . ')';
} }
} }

View File

@@ -0,0 +1,79 @@
<?php
/**
* Smarty Internal Plugin Compile Modifier
* Compiles code for modifier execution
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
namespace Smarty\Compile;
use Smarty\Compile\Tag\Base;
/**
* Smarty Internal Plugin Compile Modifier Class
*
* @package Smarty
* @subpackage Compiler
*/
class ModifierCompiler extends Base {
/**
* Compiles code for modifier execution
*
* @param array $args array with attributes from parser
* @param \Smarty\Compiler\Template $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return string compiled code
* @throws \Smarty\CompilerException
* @throws \Smarty\Exception
*/
public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) {
$compiler->has_code = true;
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
$output = $parameter['value'];
// loop over list of modifiers
foreach ($parameter['modifierlist'] as $single_modifier) {
/* @var string $modifier */
$modifier = $single_modifier[0];
$single_modifier[0] = $output;
$params = implode(',', $single_modifier);
if (!is_object($compiler->smarty->security_policy)
|| $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)
) {
if ($handler = $compiler->getModifierCompiler($modifier)) {
return $handler->compile($single_modifier, $compiler);
} elseif ($compiler->getSmarty()->getModifierCallback($modifier)) {
return sprintf(
'$_smarty_tpl->smarty->getModifierCallback(%s)(%s)',
var_export($modifier, true),
$params
);
} elseif ($callback = $compiler->getPluginFromDefaultHandler($modifier, \Smarty\Smarty::PLUGIN_MODIFIERCOMPILER)) {
$wrapper = new \Smarty\Compile\Modifier\BCPluginWrapper($callback);
return $wrapper->compile($single_modifier, $compiler);
} elseif ($function = $compiler->getPluginFromDefaultHandler($modifier, \Smarty\Smarty::PLUGIN_MODIFIER)) {
if (!is_array($function)) {
return "{$function}({$params})";
}
$operator = is_object($function[0]) ? '->' : '::';
return $function[0] . $operator . $function[1] . '(' . $params . ')';
} else {
$compiler->trigger_template_error("unknown modifier '{$modifier}'", null, true);
}
}
}
return $output;
}
}

View File

@@ -8,7 +8,7 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
namespace Smarty\Compile\Tag; namespace Smarty\Compile;
use Smarty\Compiler\Template; use Smarty\Compiler\Template;
@@ -18,7 +18,7 @@ use Smarty\Compiler\Template;
* @package Smarty * @package Smarty
* @subpackage Compiler * @subpackage Compiler
*/ */
class PrivateObjectBlockFunction extends PrivateBlockPlugin { class ObjectMethodBlockCompiler extends BlockCompiler {
/** /**
* Setup callback and parameter array * Setup callback and parameter array

View File

@@ -8,7 +8,9 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
namespace Smarty\Compile\Tag; namespace Smarty\Compile;
use Smarty\Compile\Tag\Base;
/** /**
* Smarty Internal Plugin Compile Object Function Class * Smarty Internal Plugin Compile Object Function Class
@@ -16,7 +18,7 @@ namespace Smarty\Compile\Tag;
* @package Smarty * @package Smarty
* @subpackage Compiler * @subpackage Compiler
*/ */
class PrivateObjectFunction extends Base { class ObjectMethodCallCompiler extends Base {
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
@@ -71,11 +73,7 @@ class PrivateObjectFunction extends Base {
$output = "\$_smarty_tpl->smarty->registered_objects['{$tag}'][0]->{$function}"; $output = "\$_smarty_tpl->smarty->registered_objects['{$tag}'][0]->{$function}";
} }
if (!empty($parameter['modifierlist'])) { if (!empty($parameter['modifierlist'])) {
$output = $compiler->compileTag( $output = $compiler->compileModifier($parameter['modifierlist'], $output);
'private_modifier',
[],
['modifierlist' => $parameter['modifierlist'], 'value' => $output]
);
} }
if (empty($_assign)) { if (empty($_assign)) {
return "<?php echo {$output};?>\n"; return "<?php echo {$output};?>\n";

View File

@@ -8,7 +8,9 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
namespace Smarty\Compile\Tag; namespace Smarty\Compile;
use Smarty\Compile\Tag\Base;
/** /**
* Smarty Internal Plugin Compile Print Expression Class * Smarty Internal Plugin Compile Print Expression Class
@@ -16,13 +18,13 @@ namespace Smarty\Compile\Tag;
* @package Smarty * @package Smarty
* @subpackage Compiler * @subpackage Compiler
*/ */
class PrivatePrintExpression extends Base { class PrintExpressionCompiler extends Base {
/** /**
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
public $optional_attributes = ['assign']; public $optional_attributes = ['assign'];
@@ -30,7 +32,7 @@ class PrivatePrintExpression extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
protected $option_flags = ['nocache', 'nofilter']; protected $option_flags = ['nocache', 'nofilter'];
@@ -45,19 +47,15 @@ class PrivatePrintExpression extends Base {
* @throws \Smarty\Exception * @throws \Smarty\Exception
*/ */
public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) { public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) {
$compiler->has_code = true;
// check and get attributes // check and get attributes
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
$output = $parameter['value']; $output = $parameter['value'];
// tag modifier // tag modifier
if (!empty($parameter['modifierlist'])) { if (!empty($parameter['modifierlist'])) {
$output = $compiler->compileTag( $output = $compiler->compileModifier($parameter['modifierlist'], $output);
'private_modifier',
[],
[
'modifierlist' => $parameter['modifierlist'],
'value' => $output,
]
);
} }
if (isset($_attr['assign'])) { if (isset($_attr['assign'])) {
// assign output to variable // assign output to variable
@@ -83,14 +81,7 @@ class PrivatePrintExpression extends Base {
} }
$compiler->default_modifier_list = $modifierlist; $compiler->default_modifier_list = $modifierlist;
} }
$output = $compiler->compileTag( $output = $compiler->compileModifier($compiler->default_modifier_list, $output);
'private_modifier',
[],
[
'modifierlist' => $compiler->default_modifier_list,
'value' => $output,
]
);
} }
// autoescape html // autoescape html
if ($compiler->template->smarty->escape_html) { if ($compiler->template->smarty->escape_html) {
@@ -111,11 +102,13 @@ class PrivatePrintExpression extends Base {
} }
} }
foreach ($compiler->variable_filters as $filter) { foreach ($compiler->variable_filters as $filter) {
$output = $compiler->compileTag( if (count($filter) === 1
'private_modifier', && ($result = $this->compile_variable_filter($compiler, $filter[0], $output)) !== false
[], ) {
['modifierlist' => [$filter], 'value' => $output] $output = $result;
); } else {
$output = $compiler->compileModifier([$filter], $output);
}
} }
} }
$output = "<?php echo {$output};?>\n"; $output = "<?php echo {$output};?>\n";

View File

@@ -8,7 +8,14 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
namespace Smarty\Compile\Tag; namespace Smarty\Compile;
use Smarty\Compile\Tag\Base;
use Smarty\Compile\Tag\Capture;
use Smarty\Compile\Tag\ForeachTag;
use Smarty\Compile\Tag\Section;
use Smarty\Compiler\Template;
use Smarty\CompilerException;
/** /**
* Smarty Internal Plugin Compile special Smarty Variable Class * Smarty Internal Plugin Compile special Smarty Variable Class
@@ -16,19 +23,24 @@ namespace Smarty\Compile\Tag;
* @package Smarty * @package Smarty
* @subpackage Compiler * @subpackage Compiler
*/ */
class PrivateSpecialVariable extends Base { class SpecialVariableCompiler extends Base {
/** /**
* Compiles code for the special $smarty variables * Compiles code for the special $smarty variables
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param \Smarty\Compiler\Template $compiler compiler object * @param Template $compiler compiler object
* @param $parameter * @param array $parameter
* @param null $tag
* @param null $function
* *
* @return string compiled code * @return string compiled code
* @throws \Smarty\CompilerException * @throws CompilerException
*/ */
public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) { public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) {
$compiler->has_code = true;
$_index = preg_split("/\]\[/", substr($parameter, 1, strlen($parameter) - 2)); $_index = preg_split("/\]\[/", substr($parameter, 1, strlen($parameter) - 2));
$variable = smarty_strtolower_ascii($compiler->getId($_index[0])); $variable = smarty_strtolower_ascii($compiler->getId($_index[0]));
if ($variable === false) { if ($variable === false) {

View File

@@ -6,8 +6,9 @@ class BCPluginWrapper extends Base {
private $callback; private $callback;
public function __construct($callback) { public function __construct($callback, bool $cacheable = true) {
$this->callback = $callback; $this->callback = $callback;
$this->cacheable = $cacheable;
} }
/** /**

View File

@@ -40,6 +40,10 @@ abstract class Base implements TagCompilerInterface {
* @var array * @var array
*/ */
protected $option_flags = ['nocache']; protected $option_flags = ['nocache'];
/**
* @var bool
*/
protected $cacheable = true;
/** /**
* Mapping array for boolean option value * Mapping array for boolean option value
@@ -55,6 +59,10 @@ abstract class Base implements TagCompilerInterface {
*/ */
protected $mapCache = []; protected $mapCache = [];
public function isCacheable(): bool {
return $this->cacheable;
}
/** /**
* This function checks if the attributes passed are valid * This function checks if the attributes passed are valid
* The attributes passed for the tag to compile are checked against the list of required and * The attributes passed for the tag to compile are checked against the list of required and
@@ -201,7 +209,7 @@ abstract class Base implements TagCompilerInterface {
* @param \Smarty\Compiler\Template $compiler compiler object * @param \Smarty\Compiler\Template $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return bool|string compiled code or true if no code has been compiled
* @throws \Smarty\CompilerException * @throws \Smarty\CompilerException
*/ */
abstract public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = array(), $tag = null, $function = null); abstract public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = array(), $tag = null, $function = null);

View File

@@ -39,7 +39,7 @@ class BlockClose extends Inheritance {
$compiler->parser->current_buffer = new Template(); $compiler->parser->current_buffer = new Template();
$output = "<?php\n"; $output = "<?php\n";
$output .= $compiler->cStyleComment(" {block {$_name}} ") . "\n"; $output .= $compiler->cStyleComment(" {block {$_name}} ") . "\n";
$output .= "class {$_className} extends \\Smarty\\Block\n"; $output .= "class {$_className} extends \\Smarty\\Runtime\\Block\n";
$output .= "{\n"; $output .= "{\n";
foreach ($_block as $property => $value) { foreach ($_block as $property => $value) {
$output .= "public \${$property} = " . var_export($value, true) . ";\n"; $output .= "public \${$property} = " . var_export($value, true) . ";\n";

View File

@@ -22,7 +22,7 @@ class Call extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
public $required_attributes = ['name']; public $required_attributes = ['name'];
@@ -30,7 +30,7 @@ class Call extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
public $shorttag_order = ['name']; public $shorttag_order = ['name'];
@@ -38,7 +38,7 @@ class Call extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
public $optional_attributes = ['_any']; public $optional_attributes = ['_any'];

View File

@@ -22,7 +22,7 @@ class EvalTag extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
public $required_attributes = ['var']; public $required_attributes = ['var'];
@@ -30,7 +30,7 @@ class EvalTag extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
public $optional_attributes = ['assign']; public $optional_attributes = ['assign'];
@@ -38,7 +38,7 @@ class EvalTag extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
public $shorttag_order = ['var', 'assign']; public $shorttag_order = ['var', 'assign'];
@@ -59,7 +59,7 @@ class EvalTag extends Base {
} }
// create template object // create template object
$_output = $_output =
"\$_template = new {$compiler->smarty->template_class}('eval:'.{$_attr[ 'var' ]}, \$_smarty_tpl->smarty, \$_smarty_tpl);"; "\$_template = new \\Smarty\\Template('eval:'.{$_attr[ 'var' ]}, \$_smarty_tpl->smarty, \$_smarty_tpl);";
//was there an assign attribute? //was there an assign attribute?
if (isset($_assign)) { if (isset($_assign)) {
$_output .= "\$_smarty_tpl->assign($_assign,\$_template->fetch());"; $_output .= "\$_smarty_tpl->assign($_assign,\$_template->fetch());";

View File

@@ -172,13 +172,7 @@ abstract class ForeachSection extends Base {
$_content = $nextCompiler->template->source->getContent(); $_content = $nextCompiler->template->source->getContent();
if ($_content !== '') { if ($_content !== '') {
// run pre filter if required // run pre filter if required
if (isset($nextCompiler->smarty->registered_filters['pre'])) { $_content = $nextCompiler->smarty->runPreFilters($_content, $nextCompiler->template);
$_content = $nextCompiler->smarty->runFilter(
'pre',
$_content,
$nextCompiler->template
);
}
$this->matchProperty($_content); $this->matchProperty($_content);
} }
} }

View File

@@ -31,7 +31,7 @@ class IncludeTag extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
protected $required_attributes = ['file']; protected $required_attributes = ['file'];
@@ -39,7 +39,7 @@ class IncludeTag extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
protected $shorttag_order = ['file']; protected $shorttag_order = ['file'];
@@ -47,7 +47,7 @@ class IncludeTag extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
protected $option_flags = ['nocache', 'inline', 'caching']; protected $option_flags = ['nocache', 'inline', 'caching'];
@@ -55,7 +55,7 @@ class IncludeTag extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
protected $optional_attributes = ['_any']; protected $optional_attributes = ['_any'];
@@ -206,7 +206,7 @@ class IncludeTag extends Base {
$t_hash = sha1($c_id . ($_caching ? '--caching' : '--nocaching')); $t_hash = sha1($c_id . ($_caching ? '--caching' : '--nocaching'));
$compiler->smarty->allow_ambiguous_resources = true; $compiler->smarty->allow_ambiguous_resources = true;
/* @var \Smarty\Template $tpl */ /* @var \Smarty\Template $tpl */
$tpl = new $compiler->smarty->template_class( $tpl = new \Smarty\Template(
trim($fullResourceName, '"\''), trim($fullResourceName, '"\''),
$compiler->smarty, $compiler->smarty,
$compiler->template, $compiler->template,
@@ -328,7 +328,7 @@ class IncludeTag extends Base {
$compiled_code .= "?>\n" . $tpl->compiler->compileTemplateSource($tpl, null, $compiler->parent_compiler); $compiled_code .= "?>\n" . $tpl->compiler->compileTemplateSource($tpl, null, $compiler->parent_compiler);
$compiled_code .= "<?php\n"; $compiled_code .= "<?php\n";
$compiled_code .= "}\n?>\n"; $compiled_code .= "}\n?>\n";
$compiled_code .= $tpl->compiler->postFilter($tpl->compiler->blockOrFunctionCode); $compiled_code .= $tpl->smarty->runPostFilters($tpl->compiler->blockOrFunctionCode, $tpl);
$compiled_code .= "<?php\n\n"; $compiled_code .= "<?php\n\n";
$compiled_code .= $compiler->cStyleComment(" End inline template \"{$sourceInfo}\" =============================") . "\n"; $compiled_code .= $compiler->cStyleComment(" End inline template \"{$sourceInfo}\" =============================") . "\n";
$compiled_code .= '?>'; $compiled_code .= '?>';

View File

@@ -22,7 +22,7 @@ class MakeNocache extends Base {
* Attribute definition: Overwrites base class. * Attribute definition: Overwrites base class.
* *
* @var array * @var array
* @see Base * @see BaseCompiler
*/ */
protected $option_flags = []; protected $option_flags = [];

View File

@@ -33,6 +33,7 @@ class NocacheClose extends Base {
[$compiler->nocache] = $this->closeTag($compiler, ['nocache']); [$compiler->nocache] = $this->closeTag($compiler, ['nocache']);
// this tag does not return compiled code // this tag does not return compiled code
$compiler->has_code = false; $compiler->has_code = false;
echo "has_code set to false in " . __METHOD__ . "\n";
return true; return true;
} }
} }

View File

@@ -1,79 +0,0 @@
<?php
/**
* Smarty Internal Plugin Compile Function Plugin
* Compiles code for the execution of function plugin
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
namespace Smarty\Compile\Tag;
/**
* Smarty Internal Plugin Compile Function Plugin Class
*
* @package Smarty
* @subpackage Compiler
*/
class PrivateFunctionPlugin extends Base {
/**
* Attribute definition: Overwrites base class.
*
* @var array
* @see Base
*/
protected $required_attributes = [];
/**
* Attribute definition: Overwrites base class.
*
* @var array
* @see Base
*/
protected $optional_attributes = ['_any'];
/**
* Compiles code for the execution of function plugin
*
* @param array $args array with attributes from parser
* @param \Smarty\Compiler\Template $compiler compiler object
* @param array $parameter array with compilation parameter
* @param string $tag name of function plugin
* @param string $function PHP function name
*
* @return string compiled code
* @throws \Smarty\CompilerException
* @throws \Smarty\Exception
*/
public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) {
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
unset($_attr['nocache']);
// convert attributes into parameter array string
$_paramsArray = [];
foreach ($_attr as $_key => $_value) {
if (is_int($_key)) {
$_paramsArray[] = "$_key=>$_value";
} else {
$_paramsArray[] = "'$_key'=>$_value";
}
}
$_params = 'array(' . implode(',', $_paramsArray) . ')';
// compile code
$output = "{$function}({$_params},\$_smarty_tpl)";
if (!empty($parameter['modifierlist'])) {
$output = $compiler->compileTag(
'private_modifier',
[],
[
'modifierlist' => $parameter['modifierlist'],
'value' => $output,
]
);
}
$output = "<?php echo {$output};?>\n";
return $output;
}
}

View File

@@ -1,134 +0,0 @@
<?php
/**
* Smarty Internal Plugin Compile Modifier
* Compiles code for modifier execution
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
namespace Smarty\Compile\Tag;
/**
* Smarty Internal Plugin Compile Modifier Class
*
* @package Smarty
* @subpackage Compiler
*/
class PrivateModifier extends Base {
/**
* Compiles code for modifier execution
*
* @param array $args array with attributes from parser
* @param \Smarty\Compiler\Template $compiler compiler object
* @param array $parameter array with compilation parameter
*
* @return string compiled code
* @throws \Smarty\CompilerException
* @throws \Smarty\Exception
*/
public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) {
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
$output = $parameter['value'];
// loop over list of modifiers
foreach ($parameter['modifierlist'] as $single_modifier) {
/* @var string $modifier */
$modifier = $single_modifier[0];
$single_modifier[0] = $output;
$params = implode(',', $single_modifier);
// check if we know already the type of modifier
if (isset($compiler->known_modifier_type[$modifier])) {
$modifier_types = [$compiler->known_modifier_type[$modifier]];
} else {
$modifier_types = [1, 2, 3, 4, 6];
}
foreach ($modifier_types as $type) {
switch ($type) {
case 1:
// registered modifier
if (isset($compiler->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_MODIFIER][$modifier])) {
if (is_callable($compiler->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_MODIFIER][$modifier][0])) {
$output =
sprintf(
'call_user_func_array($_smarty_tpl->registered_plugins[ \'%s\' ][ %s ][ 0 ], array( %s ))',
\Smarty\Smarty::PLUGIN_MODIFIER,
var_export($modifier, true),
$params
);
$compiler->known_modifier_type[$modifier] = $type;
break 2;
}
}
break;
case 2:
// registered modifier compiler
if (isset($compiler->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_MODIFIERCOMPILER][$modifier][0])) {
$output =
call_user_func(
$compiler->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_MODIFIERCOMPILER][$modifier][0],
$single_modifier,
$compiler->smarty
);
$compiler->known_modifier_type[$modifier] = $type;
break 2;
}
break;
case 3:
// modifiercompiler plugin
// check if modifier allowed
if ($compiler->getModifierCompiler($modifier)) {
$output = $compiler->compileModifier($modifier, $single_modifier);
}
$compiler->known_modifier_type[$modifier] = $type;
break 2;
case 4:
// modifier plugin
if ($function = $compiler->getPlugin($modifier, \Smarty\Smarty::PLUGIN_MODIFIER)) {
// check if modifier allowed
if (!is_object($compiler->smarty->security_policy)
|| $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)
) {
$output = "{$function}({$params})";
}
$compiler->known_modifier_type[$modifier] = $type;
break 2;
}
break;
// Case 5 was a direct call to a callable (usually PHP function).
// This was removed in Smarty v5 after being deprecated in 4.3.
case 6:
// default plugin handler
if (isset($compiler->default_handler_plugins[\Smarty\Smarty::PLUGIN_MODIFIER][$modifier])
|| (is_callable($compiler->smarty->default_plugin_handler_func)
&& $compiler->getPluginFromDefaultHandler($modifier, \Smarty\Smarty::PLUGIN_MODIFIER))
) {
$function = $compiler->default_handler_plugins[\Smarty\Smarty::PLUGIN_MODIFIER][$modifier][0];
// check if modifier allowed
if (!is_object($compiler->smarty->security_policy)
|| $compiler->smarty->security_policy->isTrustedModifier($modifier, $compiler)
) {
if (!is_array($function)) {
$output = "{$function}({$params})";
} else {
if (is_object($function[0])) {
$output = $function[0] . '->' . $function[1] . '(' . $params . ')';
} else {
$output = $function[0] . '::' . $function[1] . '(' . $params . ')';
}
}
}
$compiler->known_modifier_type[$modifier] = $type;
break 2;
}
}
}
if (!isset($compiler->known_modifier_type[$modifier])) {
$compiler->trigger_template_error("unknown modifier '{$modifier}'", null, true);
}
}
return $output;
}
}

View File

@@ -17,8 +17,10 @@ interface TagCompilerInterface {
* @param \Smarty\Compiler\Template $compiler compiler object * @param \Smarty\Compiler\Template $compiler compiler object
* @param array $parameter array with compilation parameter * @param array $parameter array with compilation parameter
* *
* @return string compiled code * @return bool|string compiled code or true if no code has been compiled
* @throws \Smarty\CompilerException * @throws \Smarty\CompilerException
*/ */
public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null); public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null);
public function isCacheable(): bool;
} }

View File

@@ -0,0 +1,23 @@
<?php
namespace Smarty\Compiler;
use Smarty\Smarty;
abstract class BaseCompiler {
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
/**
* @return Smarty|null
*/
public function getSmarty(): Smarty {
return $this->smarty;
}
}

View File

@@ -58,7 +58,7 @@ class CodeFrame
str_replace('*/', '* /', $this->_template->source->filepath) str_replace('*/', '* /', $this->_template->source->filepath)
); );
$output .= "/* @var \\Smarty\\Template \$_smarty_tpl */\n"; $output .= "/* @var \\Smarty\\Template \$_smarty_tpl */\n";
$dec = "\$_smarty_tpl->_decodeProperties(\$_smarty_tpl, " . var_export($properties, true) . ',' . $dec = "\$_smarty_tpl->isFresh(\$_smarty_tpl, " . var_export($properties, true) . ',' .
($cache ? 'true' : 'false') . ')'; ($cache ? 'true' : 'false') . ')';
$output .= "if ({$dec}) {\n"; $output .= "if ({$dec}) {\n";
$output .= "function {$properties['unifunc']} (\\Smarty\\Template \$_smarty_tpl) {\n"; $output .= "function {$properties['unifunc']} (\\Smarty\\Template \$_smarty_tpl) {\n";

View File

@@ -10,9 +10,9 @@
*/ */
namespace Smarty\Compiler; namespace Smarty\Compiler;
use Smarty\Smarty;
use Smarty\Lexer\ConfigfileLexer; use Smarty\Lexer\ConfigfileLexer;
use Smarty\Parser\ConfigfileParser; use Smarty\Parser\ConfigfileParser;
use Smarty\Smarty;
use Smarty\Template; use Smarty\Template;
use Smarty\CompilerException; use Smarty\CompilerException;
@@ -22,33 +22,19 @@ use Smarty\CompilerException;
* @package Smarty * @package Smarty
* @subpackage Config * @subpackage Config
*/ */
class Configfile { class Configfile extends BaseCompiler {
/**
* Lexer class name
*
* @var string
*/
public $lexer_class;
/**
* Parser class name
*
* @var string
*/
public $parser_class;
/** /**
* Lexer object * Lexer object
* *
* @var object * @var ConfigfileLexer
*/ */
public $lex; public $lex;
/** /**
* Parser object * Parser object
* *
* @var object * @var ConfigfileParser
*/ */
public $parser; public $parser;
@@ -76,15 +62,11 @@ class Configfile {
/** /**
* Initialize compiler * Initialize compiler
* *
* @param string $lexer_class class name
* @param string $parser_class class name
* @param Smarty $smarty global instance * @param Smarty $smarty global instance
*/ */
public function __construct($lexer_class, $parser_class, Smarty $smarty) { public function __construct(Smarty $smarty) {
$this->smarty = $smarty; $this->smarty = $smarty;
// get required plugins // get required plugins
$this->lexer_class = $lexer_class;
$this->parser_class = $parser_class;
$this->smarty = $smarty; $this->smarty = $smarty;
$this->config_data['sections'] = []; $this->config_data['sections'] = [];
$this->config_data['vars'] = []; $this->config_data['vars'] = [];
@@ -113,8 +95,8 @@ class Configfile {
$this->smarty->_debug->start_compile($this->template); $this->smarty->_debug->start_compile($this->template);
} }
// init the lexer/parser to compile the config file // init the lexer/parser to compile the config file
/* @var \Smarty\Lexer\ConfigfileLexer $this->lex */ /* @var ConfigfileLexer $this->lex */
$this->lex = new $this->lexer_class( $this->lex = new ConfigfileLexer(
str_replace( str_replace(
[ [
"\r\n", "\r\n",
@@ -125,8 +107,8 @@ class Configfile {
) . "\n", ) . "\n",
$this $this
); );
/* @var \Smarty\Parser\ConfigfileParser $this->parser */ /* @var ConfigfileParser $this->parser */
$this->parser = new $this->parser_class($this->lex, $this); $this->parser = new ConfigfileParser($this->lex, $this);
if (function_exists('mb_internal_encoding') if (function_exists('mb_internal_encoding')
&& function_exists('ini_get') && function_exists('ini_get')
&& ((int)ini_get('mbstring.func_overload')) & 2 && ((int)ini_get('mbstring.func_overload')) & 2
@@ -142,7 +124,7 @@ class Configfile {
// get tokens from lexer and parse them // get tokens from lexer and parse them
while ($this->lex->yylex()) { while ($this->lex->yylex()) {
if ($this->smarty->_parserdebug) { if ($this->smarty->_parserdebug) {
echo "<br>Parsing {$this->parser->yyTokenName[$this->lex->token]} Token {$this->lex->value} Line {$this->lex->line} \n"; echo "Parsing {$this->parser->yyTokenName[$this->lex->token]} Token {$this->lex->value} Line {$this->lex->line} \n";
} }
$this->parser->doParse($this->lex->token, $this->lex->value); $this->parser->doParse($this->lex->token, $this->lex->value);
} }

View File

@@ -10,12 +10,21 @@
namespace Smarty\Compiler; namespace Smarty\Compiler;
use Smarty\Smarty; use Smarty\Compile\BlockCompiler;
use Smarty\Compile\Tag\Base; use Smarty\Compile\ModifierCompiler;
use Smarty\Compile\Tag\ExtendsTag; use Smarty\Compile\ObjectMethodBlockCompiler;
use Smarty\Compile\ObjectMethodCallCompiler;
use Smarty\Compile\FunctionCallCompiler;
use Smarty\Lexer\TemplateLexer;
use Smarty\Parser\TemplateParser; use Smarty\Parser\TemplateParser;
use Smarty\Smarty;
use Smarty\Compile\Tag\ExtendsTag;
use Smarty\CompilerException; use Smarty\CompilerException;
use Smarty\Exception; use Smarty\Exception;
use function array_merge;
use function is_array;
use function strlen;
use function substr;
/** /**
* Class SmartyTemplateCompiler * Class SmartyTemplateCompiler
@@ -23,7 +32,7 @@ use Smarty\Exception;
* @package Smarty * @package Smarty
* @subpackage Compiler * @subpackage Compiler
*/ */
class Template { class Template extends BaseCompiler {
/** /**
* counter for prefix variable number * counter for prefix variable number
@@ -32,13 +41,6 @@ class Template {
*/ */
public static $prefixVariableNumber = 0; public static $prefixVariableNumber = 0;
/**
* Smarty object
*
* @var Smarty
*/
public $smarty = null;
/** /**
* Parser object * Parser object
* *
@@ -123,13 +125,6 @@ class Template {
*/ */
public $trace_filepath = ''; public $trace_filepath = '';
/**
* plugins loaded by default plugin handler
*
* @var array
*/
public $default_handler_plugins = [];
/** /**
* saved preprocessed modifier list * saved preprocessed modifier list
* *
@@ -165,13 +160,6 @@ class Template {
*/ */
public $modifier_plugins = []; public $modifier_plugins = [];
/**
* type of already compiled modifier
*
* @var array
*/
public $known_modifier_type = [];
/** /**
* parent compiler object for merged subtemplates and template functions * parent compiler object for merged subtemplates and template functions
* *
@@ -250,16 +238,11 @@ class Template {
public $stripRegEx = '![\t ]*[\r\n]+[\t ]*!'; public $stripRegEx = '![\t ]*[\r\n]+[\t ]*!';
/** /**
* plugin search order * General storage area for tag compiler plugins
* *
* @var array * @var array
*/ */
public $plugin_search_order = [ public $_cache = array();
'function',
'block',
'compiler',
'class',
];
/** /**
* Lexer preg pattern for left delimiter * Lexer preg pattern for left delimiter
@@ -296,20 +279,6 @@ class Template {
*/ */
private $literalPreg = ''; private $literalPreg = '';
/**
* Lexer class name
*
* @var string
*/
public $lexer_class;
/**
* Parser class name
*
* @var string
*/
public $parser_class;
/** /**
* array of callbacks called when the normal compile process of template is finished * array of callbacks called when the normal compile process of template is finished
* *
@@ -334,11 +303,9 @@ class Template {
/** /**
* Initialize compiler * Initialize compiler
* *
* @param string $lexer_class class name
* @param string $parser_class class name
* @param Smarty $smarty global instance * @param Smarty $smarty global instance
*/ */
public function __construct($lexer_class, $parser_class, Smarty $smarty) { public function __construct(Smarty $smarty) {
$this->smarty = $smarty; $this->smarty = $smarty;
$this->nocache_hash = str_replace( $this->nocache_hash = str_replace(
[ [
@@ -348,9 +315,6 @@ class Template {
'_', '_',
uniqid(mt_rand(), true) uniqid(mt_rand(), true)
); );
// get required plugins
$this->lexer_class = $lexer_class;
$this->parser_class = $parser_class;
} }
/** /**
@@ -375,7 +339,7 @@ class Template {
$nocache, $nocache,
$parent_compiler $parent_compiler
), ),
$this->postFilter($this->blockOrFunctionCode) . $this->smarty->runPostFilters($this->blockOrFunctionCode, $this->template) .
join('', $this->mergedSubTemplatesCode), join('', $this->mergedSubTemplatesCode),
false, false,
$this $this
@@ -442,8 +406,14 @@ class Template {
// get template source // get template source
$_content = $this->template->source->getContent(); $_content = $this->template->source->getContent();
} }
$_compiled_code = $this->postFilter($this->doCompile($this->preFilter($_content), true)); $_compiled_code = $this->smarty->runPostFilters(
} catch (Exception $e) { $this->doCompile(
$this->smarty->runPreFilters($_content, $this->template),
true
),
$this->template
);
} catch (\Exception $e) {
if ($this->smarty->debugging) { if ($this->smarty->debugging) {
$this->smarty->_debug->end_compile($this->template); $this->smarty->_debug->end_compile($this->template);
} }
@@ -462,40 +432,6 @@ class Template {
return $_compiled_code; return $_compiled_code;
} }
/**
* Optionally process compiled code by post filter
*
* @param string $code compiled code
*
* @return string
* @throws \Smarty\Exception
*/
public function postFilter($code) {
// run post filter if on code
if (!empty($code) && isset($this->smarty->registered_filters['post'])) {
return $this->smarty->runFilter('post', $code, $this->template);
} else {
return $code;
}
}
/**
* Run optional prefilter
*
* @param string $_content template source
*
* @return string
* @throws \Smarty\Exception
*/
public function preFilter($_content) {
// run pre filter if required
if ($_content !== '' && isset($this->smarty->registered_filters['pre'])) {
return $this->smarty->runFilter('pre', $_content, $this->template);
} else {
return $_content;
}
}
/** /**
* Compile Tag * Compile Tag
* This is a call back from the lexer/parser * This is a call back from the lexer/parser
@@ -521,10 +457,18 @@ class Template {
return $result; return $result;
} }
public function compileModifier($modifier, $args) { /**
if ($modifierCompiler = $this->getModifierCompiler($modifier)) { * Compiles code for modifier execution
return $modifierCompiler->compile($args, $this); *
} * @param $modifierlist
* @param $value
*
* @return string compiled code
* @throws CompilerException
* @throws Exception
*/
public function compileModifier($modifierlist, $value) {
return (new ModifierCompiler())->compile([], $this, ['modifierlist' => $modifierlist, 'value' => $value]);
} }
/** /**
@@ -697,27 +641,6 @@ class Template {
return $text; return $text;
} }
/**
* lazy loads internal compile plugin for tag and calls the compile method
* compile objects cached for reuse.
* class name format: \Smarty\Compile\TagName
*
* @param string $tag tag name
* @param array $args list of tag attributes
* @param mixed $param1 optional parameter
* @param mixed $param2 optional parameter
* @param mixed $param3 optional parameter
*
* @return bool|string compiled code or false
* @throws \Smarty\CompilerException
*/
private function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null) {
/* @var Base $tagCompiler */
$tagCompiler = $this->getTagCompiler($tag);
// compile this tag
return $tagCompiler === false ? false : $tagCompiler->compile($args, $this, $param1, $param2, $param3);
}
/** /**
* lazy loads internal compile plugin for tag compile objects cached for reuse. * lazy loads internal compile plugin for tag compile objects cached for reuse.
* *
@@ -725,21 +648,21 @@ class Template {
* *
* @param string $tag tag name * @param string $tag tag name
* *
* @return bool|\Smarty\Compile\Tag\TagCompilerInterface tag compiler object or false if not found or untrusted by security policy * @return ?\Smarty\Compile\Tag\TagCompilerInterface tag compiler object or null if not found or untrusted by security policy
*/ */
public function getTagCompiler($tag) { public function getTagCompiler($tag): ?\Smarty\Compile\Tag\TagCompilerInterface {
if (isset($this->smarty->security_policy) && !$this->smarty->security_policy->isTrustedTag($tag, $this)) { if (isset($this->smarty->security_policy) && !$this->smarty->security_policy->isTrustedTag($tag, $this)) {
return false; return null;
} }
foreach ($this->smarty->getExtensions() as $extension) { foreach ($this->smarty->getExtensions() as $extension) {
if ($tag = $extension->getTagCompiler($tag)) { if ($compiler = $extension->getTagCompiler($tag)) {
return $tag; return $compiler;
} }
} }
return false; return null;
} }
/** /**
@@ -764,42 +687,34 @@ class Template {
return false; return false;
} }
/**
* Check for plugins and return function name
*
* @param $plugin_name
* @param string $plugin_type type of plugin
*
* @return string call name of function
*/
public function getPlugin($plugin_name, $plugin_type) {
// loop through plugin dirs and find the plugin
$function = 'smarty_' . $plugin_type . '_' . $plugin_name;
if ($plugin_type === 'modifier') {
$this->modifier_plugins[$plugin_name] = true;
}
return $function;
}
/** /**
* Check for plugins by default plugin handler * Check for plugins by default plugin handler
* *
* @param string $tag name of tag * @param string $tag name of tag
* @param string $plugin_type type of plugin * @param string $plugin_type type of plugin
* *
* @return bool true if found * @return callback|null
* @throws \Smarty\CompilerException * @throws \Smarty\CompilerException
*/ */
public function getPluginFromDefaultHandler($tag, $plugin_type) { public function getPluginFromDefaultHandler($tag, $plugin_type): ?callback {
$defaultPluginHandlerFunc = $this->smarty->getDefaultPluginHandlerFunc();
if (!is_callable($defaultPluginHandlerFunc)) {
return null;
}
$callback = null; $callback = null;
$script = null; $script = null;
$cacheable = true; $cacheable = true;
$result = call_user_func_array( $result = call_user_func_array(
$this->smarty->default_plugin_handler_func, $defaultPluginHandlerFunc,
[ [
$tag, $tag,
$plugin_type, $plugin_type,
$this->template, null, // This used to pass $this->template, but this parameter has been removed in 5.0
&$callback, &$callback,
&$script, &$script,
&$cacheable, &$cacheable,
@@ -815,17 +730,12 @@ class Template {
} }
} }
if (is_callable($callback)) { if (is_callable($callback)) {
$this->default_handler_plugins[$plugin_type][$tag] = [ return $callback;
$callback,
true,
[],
];
return true;
} else { } else {
$this->trigger_template_error("Default plugin handler: Returned callback for '{$tag}' not callable"); $this->trigger_template_error("Default plugin handler: Returned callback for '{$tag}' not callable");
} }
} }
return false; return null;
} }
/** /**
@@ -1269,6 +1179,23 @@ class Template {
return '/*' . str_replace('*/', '* /', $string) . '*/'; return '/*' . str_replace('*/', '* /', $string) . '*/';
} }
private function argsContainNocache(array $args): bool {
foreach ($args as $arg) {
if (!is_array($arg)) {
if ($arg === "'nocache'" || $arg === 'nocache') {
return true;
}
} else {
foreach ($arg as $k => $v) {
if (($k === "'nocache'" || $k === 'nocache') && (trim($v, "'\" ") === 'true')) {
return true;
}
}
}
}
return false;
}
/** /**
* Compile Tag * Compile Tag
* *
@@ -1281,284 +1208,97 @@ class Template {
* @throws CompilerException * @throws CompilerException
*/ */
private function compileTag2($tag, $args, $parameter) { private function compileTag2($tag, $args, $parameter) {
$plugin_type = '';
// $args contains the attributes parsed and compiled by the lexer/parser // $args contains the attributes parsed and compiled by the lexer/parser
// assume that tag does compile into code, but creates no HTML output // assume that tag does compile into code, but creates no HTML output
$this->has_code = true; $this->has_code = true;
// check nocache option flag // check nocache option flag
foreach ($args as $arg) { if ($this->argsContainNocache($args)) {
if (!is_array($arg)) { $this->tag_nocache = true;
if ($arg === "'nocache'" || $arg === 'nocache') { }
$this->tag_nocache = true;
} // compile built-in tags
} else { if ($tagCompiler = $this->getTagCompiler($tag)) {
foreach ($arg as $k => $v) { if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($tag, $this)) {
if (($k === "'nocache'" || $k === 'nocache') && (trim($v, "'\" ") === 'true')) { $this->tag_nocache = !$tagCompiler->isCacheable();
$this->tag_nocache = true; $_output = $tagCompiler->compile($args, $this, $parameter);
} return $this->has_code ? $_output : null;
}
} }
} }
// compile the smarty tag (required compile classes to compile the tag are auto loaded)
if (($_output = $this->callTagCompiler($tag, $args, $parameter)) === false) { // template defined by {template} tag
if (isset($this->parent_compiler->tpl_function[$tag]) if ($this->canCompileTemplateCall($tag)) {
|| ($this->template->smarty->hasRuntime('TplFunction') $args['_attr']['name'] = "'{$tag}'";
&& $this->template->smarty->getRuntime('TplFunction')->getTplFunction($this->template, $tag) !== false) $tagCompiler = $this->getTagCompiler($tag);
) { // compile this tag
// template defined by {template} tag $_output = $tagCompiler === null ? false : $tagCompiler->compile($args, $this, $parameter);
$args['_attr']['name'] = "'{$tag}'"; return $this->has_code ? $_output : null;
$_output = $this->callTagCompiler('call', $args, $parameter); }
// @TODO: This code was in here in v4, but it might not do anything (anymore)
// foreach ($args['_attr'] ?? [] as $attribute) {
// if (is_array($attribute)) {
// $args = array_merge($args, $attribute);
// }
// }
// remaining tastes: (object-)function, (object-function-)block, custom-compiler
// opening and closing tags for these are handled with the same handler
$base_tag = $this->getBaseTag($tag);
// check if tag is a registered object
if (isset($this->smarty->registered_objects[$base_tag]) && isset($parameter['object_method'])) {
return $this->compileRegisteredObjectMethodCall($base_tag, $args, $parameter, $tag);
}
// check if tag is a function
if ($this->smarty->getFunctionHandler($base_tag)) {
if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) {
$compiler = new FunctionCallCompiler();
return $compiler->compile($args, $this, $parameter, $tag, $base_tag);
} }
} }
if ($_output !== false) {
if ($_output !== true) { // check if tag is a block
// did we get compiled code if ($this->smarty->getBlockHandler($base_tag)) {
if ($this->has_code) { if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) {
// return compiled code $compiler = new BlockCompiler();
return $_output; return $compiler->compile($args, $this, $parameter, $tag, $base_tag);
}
}
// the default plugin handler is a handler of last resort, it may also handle not specifically registered tags.
if ($callback = $this->getPluginFromDefaultHandler($tag, Smarty::PLUGIN_COMPILER)) {
$tagCompiler = new \Smarty\Compile\Tag\BCPluginWrapper($callback);
$new_args = [];
foreach ($args as $key => $mixed) {
if (is_array($mixed)) {
$new_args = array_merge($new_args, $mixed);
} else {
$new_args[$key] = $mixed;
} }
} }
// tag did not produce compiled code return $tagCompiler->compile($new_args, $this, $parameter);
return null; }
if ($this->getPluginFromDefaultHandler($tag, Smarty::PLUGIN_FUNCTION)) {
$compiler = new FunctionCallCompiler();
return $compiler->compile($args, $this, $parameter, $tag, $base_tag);
}
if ($this->getPluginFromDefaultHandler($tag, Smarty::PLUGIN_BLOCK)) {
$compiler = new BlockCompiler();
return $compiler->compile($args, $this, $parameter, $tag, $base_tag);
}
$this->trigger_template_error("unknown tag '{$tag}'", null, true);
}
private function getBaseTag($tag) {
if (strlen($tag) < 6 || substr($tag, -5) !== 'close') {
return $tag;
} else { } else {
// map_named attributes return substr($tag, 0, -5);
if (isset($args['_attr'])) {
foreach ($args['_attr'] as $key => $attribute) {
if (is_array($attribute)) {
$args = array_merge($args, $attribute);
}
}
}
// not an internal compiler tag
if (strlen($tag) < 6 || substr($tag, -5) !== 'close') {
// check if tag is a registered object
if (isset($this->smarty->registered_objects[$tag]) && isset($parameter['object_method'])) {
$method = $parameter['object_method'];
if (!in_array($method, $this->smarty->registered_objects[$tag][3])
&& (empty($this->smarty->registered_objects[$tag][1])
|| in_array($method, $this->smarty->registered_objects[$tag][1]))
) {
return $this->callTagCompiler('private_object_function', $args, $parameter, $tag, $method);
} elseif (in_array($method, $this->smarty->registered_objects[$tag][3])) {
return $this->callTagCompiler(
'private_object_block_function',
$args,
$parameter,
$tag,
$method
);
} else {
// throw exception
$this->trigger_template_error(
'not allowed method "' . $method . '" in registered object "' .
$tag . '"',
null,
true
);
}
}
// check if tag is registered
foreach ([
\Smarty\Smarty::PLUGIN_COMPILER,
\Smarty\Smarty::PLUGIN_FUNCTION,
\Smarty\Smarty::PLUGIN_BLOCK,
] as $plugin_type) {
if (isset($this->smarty->registered_plugins[$plugin_type][$tag])) {
// if compiler function plugin call it now
if ($plugin_type === \Smarty\Smarty::PLUGIN_COMPILER) {
$new_args = [];
foreach ($args as $key => $mixed) {
if (is_array($mixed)) {
$new_args = array_merge($new_args, $mixed);
} else {
$new_args[$key] = $mixed;
}
}
if (!$this->smarty->registered_plugins[$plugin_type][$tag][1]) {
$this->tag_nocache = true;
}
return call_user_func_array(
$this->smarty->registered_plugins[$plugin_type][$tag][0],
[
$new_args,
$this,
]
);
}
// compile registered function or block function
if ($plugin_type === \Smarty\Smarty::PLUGIN_FUNCTION || $plugin_type === \Smarty\Smarty::PLUGIN_BLOCK) {
return $this->callTagCompiler(
'private_registered_' . $plugin_type,
$args,
$parameter,
$tag
);
}
}
}
// check plugins from plugins folder
foreach ($this->plugin_search_order as $plugin_type) {
if ($plugin_type === \Smarty\Smarty::PLUGIN_COMPILER
&& (!isset($this->smarty->security_policy)
|| $this->smarty->security_policy->isTrustedTag($tag, $this))
) {
$plugin = 'smarty_compiler_' . $tag;
if (is_callable($plugin)) {
// convert arguments format for old compiler plugins
$new_args = [];
foreach ($args as $key => $mixed) {
if (is_array($mixed)) {
$new_args = array_merge($new_args, $mixed);
} else {
$new_args[$key] = $mixed;
}
}
return $plugin($new_args, $this->smarty);
}
if (class_exists($plugin, false)) {
$plugin_object = new $plugin;
if (method_exists($plugin_object, 'compile')) {
return $plugin_object->compile($args, $this);
}
}
throw new Exception("Plugin '{$tag}' not callable");
} else {
if ($function = $this->getPlugin($tag, $plugin_type)) {
if (!isset($this->smarty->security_policy)
|| $this->smarty->security_policy->isTrustedTag($tag, $this)
) {
return $this->callTagCompiler(
'private_' . $plugin_type . '_plugin',
$args,
$parameter,
$tag,
$function
);
}
}
}
}
if (is_callable($this->smarty->default_plugin_handler_func)) {
$found = false;
// look for already resolved tags
foreach ($this->plugin_search_order as $plugin_type) {
if (isset($this->default_handler_plugins[$plugin_type][$tag])) {
$found = true;
break;
}
}
if (!$found) {
// call default handler
foreach ($this->plugin_search_order as $plugin_type) {
if ($this->getPluginFromDefaultHandler($tag, $plugin_type)) {
$found = true;
break;
}
}
}
if ($found) {
// if compiler function plugin call it now
if ($plugin_type === \Smarty\Smarty::PLUGIN_COMPILER) {
$new_args = [];
foreach ($args as $key => $mixed) {
if (is_array($mixed)) {
$new_args = array_merge($new_args, $mixed);
} else {
$new_args[$key] = $mixed;
}
}
return call_user_func_array(
$this->default_handler_plugins[$plugin_type][$tag][0],
[
$new_args,
$this,
]
);
} else {
return $this->callTagCompiler(
'private_registered_' . $plugin_type,
$args,
$parameter,
$tag
);
}
}
}
} else {
// compile closing tag of block function
$base_tag = substr($tag, 0, -5);
// check if closing tag is a registered object
if (isset($this->smarty->registered_objects[$base_tag]) && isset($parameter['object_method'])) {
$method = $parameter['object_method'];
if (in_array($method, $this->smarty->registered_objects[$base_tag][3])) {
return $this->callTagCompiler(
'private_object_block_function',
$args,
$parameter,
$tag,
$method
);
} else {
// throw exception
$this->trigger_template_error(
'not allowed closing tag method "' . $method .
'" in registered object "' . $base_tag . '"',
null,
true
);
}
}
// registered block tag ?
if (isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_BLOCK][$base_tag])
|| isset($this->default_handler_plugins[\Smarty\Smarty::PLUGIN_BLOCK][$base_tag])
) {
return $this->callTagCompiler('private_registered_block', $args, $parameter, $tag);
}
// registered function tag ?
if (isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_FUNCTION][$tag])) {
return $this->callTagCompiler('private_registered_function', $args, $parameter, $tag);
}
// block plugin?
if ($function = $this->getPlugin($base_tag, \Smarty\Smarty::PLUGIN_BLOCK)) {
return $this->callTagCompiler('private_block_plugin', $args, $parameter, $tag, $function);
}
// function plugin?
if ($function = $this->getPlugin($tag, \Smarty\Smarty::PLUGIN_FUNCTION)) {
if (!isset($this->smarty->security_policy)
|| $this->smarty->security_policy->isTrustedTag($tag, $this)
) {
return $this->callTagCompiler('private_function_plugin', $args, $parameter, $tag, $function);
}
}
// registered compiler plugin ?
if (isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_COMPILER][$tag])) {
// if compiler function plugin call it now
$args = [];
if (!$this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_COMPILER][$tag][1]) {
$this->tag_nocache = true;
}
return call_user_func_array(
$this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_COMPILER][$tag][0],
[
$args,
$this,
]
);
}
$plugin = 'smarty_compiler_' . $tag;
if (is_callable($plugin)) {
return $plugin($args, $this->smarty);
}
if (class_exists($plugin, false)) {
$plugin_object = new $plugin;
if (method_exists($plugin_object, 'compile')) {
return $plugin_object->compile($args, $this);
}
}
throw new Exception("Plugin '{$tag}' not callable");
}
$this->trigger_template_error("unknown tag '{$tag}'", null, true);
} }
} }
@@ -1576,9 +1316,8 @@ class Template {
tags in the templates are replaces with PHP code, tags in the templates are replaces with PHP code,
then written to compiled files. */ then written to compiled files. */
// init the lexer/parser to compile the template // init the lexer/parser to compile the template
$this->parser = $this->parser = new TemplateParser(
new $this->parser_class( new TemplateLexer(
new $this->lexer_class(
str_replace( str_replace(
[ [
"\r\n", "\r\n",
@@ -1610,8 +1349,8 @@ class Template {
// get tokens from lexer and parse them // get tokens from lexer and parse them
while ($this->parser->lex->yylex()) { while ($this->parser->lex->yylex()) {
if ($this->smarty->_parserdebug) { if ($this->smarty->_parserdebug) {
echo "<pre>Line {$this->parser->lex->line} Parsing {$this->parser->yyTokenName[$this->parser->lex->token]} Token " . echo "Line {$this->parser->lex->line} Parsing {$this->parser->yyTokenName[$this->parser->lex->token]} Token " .
htmlentities($this->parser->lex->value) . "</pre>"; $this->parser->lex->value;
} }
$this->parser->doParse($this->parser->lex->token, $this->parser->lex->value); $this->parser->doParse($this->parser->lex->token, $this->parser->lex->value);
} }
@@ -1667,4 +1406,61 @@ class Template {
public function unregisterPostCompileCallback($key) { public function unregisterPostCompileCallback($key) {
unset($this->postCompileCallbacks[$key]); unset($this->postCompileCallbacks[$key]);
} }
/**
* @param string $tag
*
* @return bool
* @throws Exception
*/
private function canCompileTemplateCall(string $tag): bool {
return
isset($this->parent_compiler->tpl_function[$tag])
|| (
$this->template->smarty->hasRuntime('TplFunction')
&& ($this->template->smarty->getRuntime('TplFunction')->getTplFunction($this->template, $tag) !== false)
);
}
/**
* @throws CompilerException
*/
private function compileRegisteredObjectMethodCall(string $base_tag, array $args, array $parameter, string $tag) {
$method = $parameter['object_method'];
$allowedAsBlockFunction = in_array($method, $this->smarty->registered_objects[$base_tag][3]);
if ($base_tag === $tag) {
// opening tag
$allowedAsNormalFunction = empty($this->smarty->registered_objects[$base_tag][1])
|| in_array($method, $this->smarty->registered_objects[$base_tag][1]);
if ($allowedAsBlockFunction) {
return (new ObjectMethodBlockCompiler())->compile($args, $this, $parameter, $tag, $method);
} elseif ($allowedAsNormalFunction) {
return (new ObjectMethodCallCompiler())->compile($args, $this, $parameter, $tag, $method);
}
$this->trigger_template_error(
'not allowed method "' . $method . '" in registered object "' .
$tag . '"',
null,
true
);
}
// closing tag
if ($allowedAsBlockFunction) {
return (new ObjectMethodBlockCompiler())->compile($args, $this, $parameter, $tag, $method);
}
$this->trigger_template_error(
'not allowed closing tag method "' . $method .
'" in registered object "' . $base_tag . '"',
null,
true
);
}
} }

View File

@@ -31,13 +31,6 @@ abstract class Data
*/ */
public $_objType = 4; public $_objType = 4;
/**
* name of class used for templates
*
* @var string
*/
public $template_class = 'Smarty\Template';
/** /**
* template variables * template variables
* *
@@ -119,7 +112,7 @@ abstract class Data
// $tpl_var is an array, ignore $value // $tpl_var is an array, ignore $value
foreach ($tpl_var as $_key => $_val) { foreach ($tpl_var as $_key => $_val) {
if ($_key !== '') { if ($_key !== '') {
$this->append($this, $_key, $_val, $merge, $nocache); $this->append($_key, $_val, $merge, $nocache);
} }
} }
} else { } else {
@@ -211,7 +204,7 @@ abstract class Data
* *
* @return Data * @return Data
*/ */
public function assignByRef($tpl_var, &$value, $nocache) public function assignByRef($tpl_var, &$value, $nocache = false)
{ {
if ($tpl_var !== '') { if ($tpl_var !== '') {
$this->tpl_vars[ $tpl_var ] = new \Smarty\Variable(null, $nocache); $this->tpl_vars[ $tpl_var ] = new \Smarty\Variable(null, $nocache);
@@ -439,7 +432,7 @@ abstract class Data
*/ */
public function configLoad($config_file, $sections = null) public function configLoad($config_file, $sections = null)
{ {
$this->_loadConfigfile($this, $config_file, $sections, null); $this->_loadConfigfile($config_file, $sections, null);
return $this; return $this;
} }

View File

@@ -200,7 +200,7 @@ class Debug extends Data
$smarty = $obj->_getSmartyObj(); $smarty = $obj->_getSmartyObj();
// create fresh instance of smarty for displaying the debug console // create fresh instance of smarty for displaying the debug console
// to avoid problems if the application did overload the Smarty class // to avoid problems if the application did overload the Smarty class
$debObj = new \Smarty(); $debObj = new \Smarty\Smarty();
// copy the working dirs from application // copy the working dirs from application
$debObj->setCompileDir($smarty->getCompileDir()); $debObj->setCompileDir($smarty->getCompileDir());
$debObj->force_compile = false; $debObj->force_compile = false;
@@ -211,9 +211,7 @@ class Debug extends Data
$debObj->debugging = false; $debObj->debugging = false;
$debObj->debugging_ctrl = 'NONE'; $debObj->debugging_ctrl = 'NONE';
$debObj->error_reporting = E_ALL & ~E_NOTICE; $debObj->error_reporting = E_ALL & ~E_NOTICE;
$debObj->debug_tpl = $debObj->debug_tpl = $smarty->debug_tpl ?? 'file:' . __DIR__ . '/../debug.tpl';
isset($smarty->debug_tpl) ? $smarty->debug_tpl : 'file:' . __DIR__ . '/../debug.tpl';
$debObj->registered_plugins = array();
$debObj->registered_resources = array(); $debObj->registered_resources = array();
$debObj->registered_filters = array(); $debObj->registered_filters = array();
$debObj->default_modifiers = array(); $debObj->default_modifiers = array();

View File

@@ -2,7 +2,10 @@
namespace Smarty\Extension; namespace Smarty\Extension;
use Smarty\Compile\Tag\BCPluginWrapper; use Smarty\BlockHandler\BlockPluginWrapper;
use Smarty\Compile\Modifier\BCPluginWrapper as ModifierCompilerPluginWrapper;
use Smarty\Compile\Tag\BCPluginWrapper as TagPluginWrapper;
use Smarty\FunctionHandler\BCPluginWrapper as FunctionPluginWrapper;
class BCPluginsAdapter extends Base { class BCPluginsAdapter extends Base {
@@ -15,13 +18,104 @@ class BCPluginsAdapter extends Base {
$this->smarty = $smarty; $this->smarty = $smarty;
} }
//$smarty->registered_plugins[$type][$name] = [$callback, (bool)$cacheable, (array)$cache_attr]; private function findPlugin($type, $name): ?array {
if (null !== $plugin = $this->smarty->getRegisteredPlugin($type, $name)) {
return $plugin;
}
return null;
}
public function getTagCompiler(string $tag): ?\Smarty\Compile\Tag\TagCompilerInterface { public function getTagCompiler(string $tag): ?\Smarty\Compile\Tag\TagCompilerInterface {
if (!isset($smarty->registered_plugins['compiler'][$tag])) {
$plugin = $this->findPlugin(\Smarty\Smarty::PLUGIN_COMPILER, $tag);
if ($plugin === null) {
return null; return null;
} }
$callback = reset($smarty->registered_plugins['compiler'][$tag]); $callback = $plugin[0];
return new BCPluginWrapper($callback); $cacheable = (bool) $plugin[1] ?? true;
return new TagPluginWrapper($callback, $cacheable);
} }
public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandler\FunctionHandlerInterface {
$plugin = $this->findPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, $functionName);
if ($plugin === null) {
return null;
}
$callback = $plugin[0];
$cacheable = (bool) $plugin[1] ?? true;
$cache_attributes = (array) $plugin[2] ?? [];
return new FunctionPluginWrapper($callback, $cacheable, $cache_attributes);
}
public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface {
$plugin = $this->findPlugin(\Smarty\Smarty::PLUGIN_BLOCK, $blockTagName);
if ($plugin === null) {
return null;
}
$callback = $plugin[0];
return new BlockPluginWrapper($callback);
}
public function getModifierCallback(string $modifierName) {
$plugin = $this->findPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, $modifierName);
if ($plugin === null) {
return null;
}
return $plugin[0];
}
public function getModifierCompiler(string $modifier): ?\Smarty\Compile\Modifier\ModifierCompilerInterface {
$plugin = $this->findPlugin(\Smarty\Smarty::PLUGIN_MODIFIERCOMPILER, $modifier);
if ($plugin === null) {
return null;
}
$callback = $plugin[0];
return new ModifierCompilerPluginWrapper($callback);
}
public function loadPluginsFromDir(string $path) {
foreach([
'function',
'modifier',
'block',
'compiler',
'prefilter',
'postfilter',
'outputfilter',
'resource',
'insert',
] as $type) {
foreach (glob($path . $type . '.?*.php') as $filename) {
$pluginName = $this->getPluginNameFromFilename($filename);
if ($pluginName !== null) {
require_once $filename;
if (function_exists($functionName = 'smarty_' . $type . '_' . $pluginName)) {
$this->smarty->registerPlugin($type, $pluginName, $functionName, true, []);
}
}
}
}
}
/**
* @param $filename
*
* @return string|null
*/
private function getPluginNameFromFilename($filename) {
if (!preg_match('/.*\.([a-z_A-Z0-9]+)\.php$/',$filename,$matches)) {
return null;
}
return $matches[1];
}
} }

View File

@@ -18,7 +18,7 @@ class Base implements ExtensionInterface {
return null; return null;
} }
public function getBlockHandler(string $functionName): ?\Smarty\FunctionHandler\BlockHandlerInterface { public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface {
return null; return null;
} }
@@ -26,6 +26,14 @@ class Base implements ExtensionInterface {
return null; return null;
} }
public function getPreFilters(): array {
return [];
}
public function getPostFilters(): array {
return [];
}
public function getOutputFilters(): array { public function getOutputFilters(): array {
return []; return [];
} }

View File

@@ -0,0 +1,55 @@
<?php
namespace Smarty\Extension;
class CoreExtension extends Base {
public function getTagCompiler(string $tag): ?\Smarty\Compile\Tag\TagCompilerInterface {
switch ($tag) {
case 'append': return new \Smarty\Compile\Tag\Append();
case 'assign': return new \Smarty\Compile\Tag\Assign();
case 'block': return new \Smarty\Compile\Tag\Block();
case 'blockclose': return new \Smarty\Compile\Tag\BlockClose();
case 'break': return new \Smarty\Compile\Tag\BreakTag();
case 'call': return new \Smarty\Compile\Tag\Call();
case 'capture': return new \Smarty\Compile\Tag\Capture();
case 'captureclose': return new \Smarty\Compile\Tag\CaptureClose();
case 'child': return new \Smarty\Compile\Tag\Child();
case 'block_child': return new \Smarty\Compile\Tag\BlockChild();
case 'block_parent': return new \Smarty\Compile\Tag\BlockParent();
case 'config_load': return new \Smarty\Compile\Tag\ConfigLoad();
case 'continue': return new \Smarty\Compile\Tag\ContinueTag();
case 'debug': return new \Smarty\Compile\Tag\Debug();
case 'eval': return new \Smarty\Compile\Tag\EvalTag();
case 'extends': return new \Smarty\Compile\Tag\ExtendsTag();
case 'for': return new \Smarty\Compile\Tag\ForTag();
case 'foreach': return new \Smarty\Compile\Tag\ForeachTag();
case 'foreachelse': return new \Smarty\Compile\Tag\ForeachElse();
case 'foreachclose': return new \Smarty\Compile\Tag\ForeachClose();
case 'forelse': return new \Smarty\Compile\Tag\ForElse();
case 'forclose': return new \Smarty\Compile\Tag\ForClose();
case 'function': return new \Smarty\Compile\Tag\FunctionTag();
case 'functionclose': return new \Smarty\Compile\Tag\FunctionClose();
case 'if': return new \Smarty\Compile\Tag\IfTag();
case 'else': return new \Smarty\Compile\Tag\ElseTag();
case 'elseif': return new \Smarty\Compile\Tag\ElseIfTag();
case 'ifclose': return new \Smarty\Compile\Tag\IfClose();
case 'include': return new \Smarty\Compile\Tag\IncludeTag();
case 'insert': return new \Smarty\Compile\Inser();
case 'ldelim': return new \Smarty\Compile\Tag\Ldelim();
case 'rdelim': return new \Smarty\Compile\Tag\Rdelim();
case 'make_nocache': return new \Smarty\Compile\Tag\MakeNocache();
case 'nocache': return new \Smarty\Compile\Tag\Nocache();
case 'nocacheclose': return new \Smarty\Compile\Tag\NocacheClose();
case 'parent': return new \Smarty\Compile\Tag\ParentTag();
case 'section': return new \Smarty\Compile\Tag\Section();
case 'sectionelse': return new \Smarty\Compile\Tag\SectionElse();
case 'sectionclose': return new \Smarty\Compile\Tag\SectionClose();
case 'setfilter': return new \Smarty\Compile\Tag\Setfilter();
case 'setfilterclose': return new \Smarty\Compile\Tag\SetfilterClose();
case 'while': return new \Smarty\Compile\Tag\WhileTag();
case 'whileclose': return new \Smarty\Compile\Tag\WhileClose();
}
return null;
}
}

View File

@@ -2,64 +2,7 @@
namespace Smarty\Extension; namespace Smarty\Extension;
class Core extends Base { class DefaultExtension extends Base {
public function getTagCompiler(string $tag): ?\Smarty\Compile\Tag\TagCompilerInterface {
switch ($tag) {
case 'append': return new \Smarty\Compile\Tag\Append();
case 'assign': return new \Smarty\Compile\Tag\Assign();
case 'block': return new \Smarty\Compile\Tag\Block();
case 'blockclose': return new \Smarty\Compile\Tag\BlockClose();
case 'break': return new \Smarty\Compile\Tag\BreakTag();
case 'call': return new \Smarty\Compile\Tag\Call();
case 'capture': return new \Smarty\Compile\Tag\Capture();
case 'captureclose': return new \Smarty\Compile\Tag\CaptureClose();
case 'child': return new \Smarty\Compile\Tag\Child();
case 'block_child': return new \Smarty\Compile\Tag\BlockChild();
case 'block_parent': return new \Smarty\Compile\Tag\BlockParent();
case 'config_load': return new \Smarty\Compile\Tag\ConfigLoad();
case 'continue': return new \Smarty\Compile\Tag\ContinueTag();
case 'debug': return new \Smarty\Compile\Tag\Debug();
case 'eval': return new \Smarty\Compile\Tag\EvalTag();
case 'extends': return new \Smarty\Compile\Tag\ExtendsTag();
case 'for': return new \Smarty\Compile\Tag\ForTag();
case 'foreach': return new \Smarty\Compile\Tag\ForeachTag();
case 'foreachelse': return new \Smarty\Compile\Tag\ForeachElse();
case 'foreachclose': return new \Smarty\Compile\Tag\ForeachClose();
case 'forelse': return new \Smarty\Compile\Tag\ForElse();
case 'forclose': return new \Smarty\Compile\Tag\ForClose();
case 'function': return new \Smarty\Compile\Tag\FunctionTag();
case 'functionclose': return new \Smarty\Compile\Tag\FunctionClose();
case 'if': return new \Smarty\Compile\Tag\IfTag();
case 'else': return new \Smarty\Compile\Tag\ElseTag();
case 'elseif': return new \Smarty\Compile\Tag\ElseIfTag();
case 'ifclose': return new \Smarty\Compile\Tag\IfClose();
case 'include': return new \Smarty\Compile\Tag\IncludeTag();
case 'insert': return new \Smarty\Compile\Inser();
case 'ldelim': return new \Smarty\Compile\Tag\Ldelim();
case 'rdelim': return new \Smarty\Compile\Tag\Rdelim();
case 'make_nocache': return new \Smarty\Compile\Tag\MakeNocache();
case 'nocache': return new \Smarty\Compile\Tag\Nocache();
case 'nocacheclose': return new \Smarty\Compile\Tag\NocacheClose();
case 'parent': return new \Smarty\Compile\Tag\ParentTag();
case 'private_block_plugin': return new \Smarty\Compile\Tag\PrivateBlockPlugin();
case 'private_function_plugin': return new \Smarty\Compile\Tag\PrivateFunctionPlugin();
case 'private_modifier': return new \Smarty\Compile\Tag\PrivateModifier();
case 'private_object_function': return new \Smarty\Compile\Tag\PrivateObjectFunction();
case 'private_object_block_function': return new \Smarty\Compile\Tag\PrivateObjectBlockFunction();
case 'private_print_expression': return new \Smarty\Compile\Tag\PrivatePrintExpression();
case 'private_registered_function': return new \Smarty\Compile\Tag\PrivateRegisteredFunction();
case 'private_special_variable': return new \Smarty\Compile\Tag\PrivateSpecialVariable();
case 'section': return new \Smarty\Compile\Tag\Section();
case 'sectionelse': return new \Smarty\Compile\Tag\SectionElse();
case 'sectionclose': return new \Smarty\Compile\Tag\SectionClose();
case 'setfilter': return new \Smarty\Compile\Tag\Setfilter();
case 'setfilterclose': return new \Smarty\Compile\Tag\SetfilterClose();
case 'while': return new \Smarty\Compile\Tag\WhileTag();
case 'whileclose': return new \Smarty\Compile\Tag\WhileClose();
}
return null;
}
public function getModifierCompiler(string $modifier): ?\Smarty\Compile\Modifier\ModifierCompilerInterface { public function getModifierCompiler(string $modifier): ?\Smarty\Compile\Modifier\ModifierCompilerInterface {
switch ($modifier) { switch ($modifier) {
case 'cat': return new \Smarty\Compile\Modifier\CatModifierCompiler(); case 'cat': return new \Smarty\Compile\Modifier\CatModifierCompiler();
@@ -67,7 +10,7 @@ class Core extends Base {
case 'count_paragraphs': return new \Smarty\Compile\Modifier\CountParagraphsModifierCompiler(); case 'count_paragraphs': return new \Smarty\Compile\Modifier\CountParagraphsModifierCompiler();
case 'count_sentences': return new \Smarty\Compile\Modifier\CountSentencesModifierCompiler(); case 'count_sentences': return new \Smarty\Compile\Modifier\CountSentencesModifierCompiler();
case 'count_words': return new \Smarty\Compile\Modifier\CountWordsModifierCompiler(); case 'count_words': return new \Smarty\Compile\Modifier\CountWordsModifierCompiler();
case 'default': return new \Smarty\Compile\DefaultModifierCompiler(); case 'default': return new \Smarty\Compile\Modifier\DefaultModifierCompiler();
case 'escape': return new \Smarty\Compile\Modifier\EscapeModifierCompiler(); case 'escape': return new \Smarty\Compile\Modifier\EscapeModifierCompiler();
case 'from_charset': return new \Smarty\Compile\Modifier\FromCharsetModifierCompiler(); case 'from_charset': return new \Smarty\Compile\Modifier\FromCharsetModifierCompiler();
case 'indent': return new \Smarty\Compile\Modifier\IndentModifierCompiler(); case 'indent': return new \Smarty\Compile\Modifier\IndentModifierCompiler();
@@ -90,7 +33,6 @@ class Core extends Base {
public function getModifierCallback(string $modifierName) { public function getModifierCallback(string $modifierName) {
switch ($modifierName) { switch ($modifierName) {
case 'spacify': return [$this, 'smarty_modifier_spacify'];
case 'capitalize': return [$this, 'smarty_modifier_capitalize']; case 'capitalize': return [$this, 'smarty_modifier_capitalize'];
case 'count': return [$this, 'smarty_modifier_count']; case 'count': return [$this, 'smarty_modifier_count'];
case 'date_format': return [$this, 'smarty_modifier_date_format']; case 'date_format': return [$this, 'smarty_modifier_date_format'];
@@ -101,6 +43,7 @@ class Core extends Base {
case 'number_format': return [$this, 'smarty_modifier_number_format']; case 'number_format': return [$this, 'smarty_modifier_number_format'];
case 'regex_replace': return [$this, 'smarty_modifier_regex_replace']; case 'regex_replace': return [$this, 'smarty_modifier_regex_replace'];
case 'replace': return [$this, 'smarty_modifier_replace']; case 'replace': return [$this, 'smarty_modifier_replace'];
case 'spacify': return [$this, 'smarty_modifier_spacify'];
case 'truncate': return [$this, 'smarty_modifier_truncate']; case 'truncate': return [$this, 'smarty_modifier_truncate'];
} }
return null; return null;
@@ -124,7 +67,7 @@ class Core extends Base {
return null; return null;
} }
public function getBlockHandler(string $blockTagName): ?\Smarty\FunctionHandler\BlockHandlerInterface { public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface {
switch ($blockTagName) { switch ($blockTagName) {
case 'textformat': return new \Smarty\BlockHandler\TextFormat(); case 'textformat': return new \Smarty\BlockHandler\TextFormat();
} }
@@ -151,7 +94,7 @@ class Core extends Base {
* *
* @return string * @return string
*/ */
private function smarty_modifier_spacify($string, $spacify_char = ' ') public function smarty_modifier_spacify($string, $spacify_char = ' ')
{ {
// well… what about charsets besides latin and UTF-8? // well… what about charsets besides latin and UTF-8?
return implode($spacify_char, preg_split('//' . \Smarty\Smarty::$_UTF8_MODIFIER, $string, -1, PREG_SPLIT_NO_EMPTY)); return implode($spacify_char, preg_split('//' . \Smarty\Smarty::$_UTF8_MODIFIER, $string, -1, PREG_SPLIT_NO_EMPTY));
@@ -172,7 +115,7 @@ class Core extends Base {
* @author Monte Ohrt <monte at ohrt dot com> * @author Monte Ohrt <monte at ohrt dot com>
* @author Rodney Rehm * @author Rodney Rehm
*/ */
private function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false) public function smarty_modifier_capitalize($string, $uc_digits = false, $lc_rest = false)
{ {
$string = (string) $string; $string = (string) $string;
@@ -239,7 +182,7 @@ class Core extends Base {
* *
* @return int * @return int
*/ */
private function smarty_modifier_count($arrayOrObject, $mode = 0) { public function smarty_modifier_count($arrayOrObject, $mode = 0) {
/* /*
* @see https://www.php.net/count * @see https://www.php.net/count
* > Prior to PHP 8.0.0, if the parameter was neither an array nor an object that implements the Countable interface, * > Prior to PHP 8.0.0, if the parameter was neither an array nor an object that implements the Countable interface,
@@ -275,7 +218,7 @@ class Core extends Base {
* @return string |void * @return string |void
* @uses smarty_make_timestamp() * @uses smarty_make_timestamp()
*/ */
private function smarty_modifier_date_format($string, $format = null, $default_date = '', $formatter = 'auto') public function smarty_modifier_date_format($string, $format = null, $default_date = '', $formatter = 'auto')
{ {
if ($format === null) { if ($format === null) {
$format = \Smarty\Smarty::$_DATE_FORMAT; $format = \Smarty\Smarty::$_DATE_FORMAT;
@@ -341,7 +284,7 @@ class Core extends Base {
* *
* @return string * @return string
*/ */
private function smarty_modifier_debug_print_var($var, $max = 10, $length = 40, $depth = 0, $objects = array()) public function smarty_modifier_debug_print_var($var, $max = 10, $length = 40, $depth = 0, $objects = array())
{ {
$_replace = array("\n" => '\n', "\r" => '\r', "\t" => '\t'); $_replace = array("\n" => '\n', "\r" => '\r', "\t" => '\t');
switch (gettype($var)) { switch (gettype($var)) {
@@ -426,7 +369,7 @@ class Core extends Base {
* *
* @return string escaped input string * @return string escaped input string
*/ */
private function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $double_encode = true) public function smarty_modifier_escape($string, $esc_type = 'html', $char_set = null, $double_encode = true)
{ {
if (!$char_set) { if (!$char_set) {
$char_set = \Smarty\Smarty::$_CHARSET; $char_set = \Smarty\Smarty::$_CHARSET;
@@ -549,7 +492,7 @@ class Core extends Base {
* *
* @return array * @return array
*/ */
private function smarty_modifier_explode($separator, $string, ?int $limit = null) public function smarty_modifier_explode($separator, $string, ?int $limit = null)
{ {
// provide $string default to prevent deprecation errors in PHP >=8.1 // provide $string default to prevent deprecation errors in PHP >=8.1
return explode($separator, $string ?? '', $limit ?? PHP_INT_MAX); return explode($separator, $string ?? '', $limit ?? PHP_INT_MAX);
@@ -571,7 +514,7 @@ class Core extends Base {
* @return string wrapped string * @return string wrapped string
* @author Rodney Rehm * @author Rodney Rehm
*/ */
private function smarty_modifier_mb_wordwrap($str, $width = 75, $break = "\n", $cut = false) public function smarty_modifier_mb_wordwrap($str, $width = 75, $break = "\n", $cut = false)
{ {
return smarty_mb_wordwrap($str, $width, $break, $cut); return smarty_mb_wordwrap($str, $width, $break, $cut);
} }
@@ -589,7 +532,7 @@ class Core extends Base {
* *
* @return string * @return string
*/ */
private function smarty_modifier_number_format(?float $num, int $decimals = 0, ?string $decimal_separator = ".", ?string $thousands_separator = ",") public function smarty_modifier_number_format(?float $num, int $decimals = 0, ?string $decimal_separator = ".", ?string $thousands_separator = ",")
{ {
// provide $num default to prevent deprecation errors in PHP >=8.1 // provide $num default to prevent deprecation errors in PHP >=8.1
return number_format($num ?? 0.0, $decimals, $decimal_separator, $thousands_separator); return number_format($num ?? 0.0, $decimals, $decimal_separator, $thousands_separator);
@@ -612,7 +555,7 @@ class Core extends Base {
* *
* @return string * @return string
*/ */
private function smarty_modifier_regex_replace($string, $search, $replace, $limit = -1) public function smarty_modifier_regex_replace($string, $search, $replace, $limit = -1)
{ {
if (is_array($search)) { if (is_array($search)) {
foreach ($search as $idx => $s) { foreach ($search as $idx => $s) {
@@ -660,7 +603,7 @@ class Core extends Base {
* *
* @return string * @return string
*/ */
private function smarty_modifier_replace($string, $search, $replace) public function smarty_modifier_replace($string, $search, $replace)
{ {
return smarty_mb_str_replace($search, $replace, $string); return smarty_mb_str_replace($search, $replace, $string);
} }
@@ -684,7 +627,7 @@ class Core extends Base {
* *
* @return string truncated string * @return string truncated string
*/ */
private function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_words = false, $middle = false) public function smarty_modifier_truncate($string, $length = 80, $etc = '...', $break_words = false, $middle = false)
{ {
if ($length === 0) { if ($length === 0) {
return ''; return '';

View File

@@ -10,10 +10,12 @@ interface ExtensionInterface {
public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandler\FunctionHandlerInterface; public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandler\FunctionHandlerInterface;
public function getBlockHandler(string $blockTagName): ?\Smarty\FunctionHandler\BlockHandlerInterface; public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface;
public function getModifierCallback(string $modifierName); public function getModifierCallback(string $modifierName);
public function getPreFilters(): array;
public function getPostFilters(): array;
public function getOutputFilters(): array; public function getOutputFilters(): array;
} }

View File

@@ -0,0 +1,22 @@
<?php
namespace Smarty\FunctionHandler;
use Smarty\Template;
class BCPluginWrapper extends Base {
private $callback;
public function __construct($callback, bool $cacheable = true, array $cache_attributes = []) {
$this->callback = $callback;
$this->cacheable = $cacheable;
$this->cache_attributes = $cache_attributes;
}
public function handle($params, Template $template) {
$func = $this->callback;
return $func($params, $template->smarty);
}
}

View File

@@ -6,6 +6,24 @@ use Smarty\Template;
class Base implements FunctionHandlerInterface { class Base implements FunctionHandlerInterface {
/**
* @var bool
*/
protected $cacheable = true;
/**
* @var array
*/
protected $cache_attributes = [];
public function isCacheable(): bool {
return $this->cacheable;
}
public function getCacheAttributes(): array {
return $this->cache_attributes;
}
public function handle($params, Template $template) { public function handle($params, Template $template) {
// TODO: Implement handle() method. // TODO: Implement handle() method.
} }

View File

@@ -6,5 +6,6 @@ use Smarty\Template;
interface FunctionHandlerInterface { interface FunctionHandlerInterface {
public function handle($params, Template $template); public function handle($params, Template $template);
public function isCacheable(): bool;
public function getCacheAttributes(): array;
} }

View File

@@ -304,9 +304,9 @@ template ::= .
smartytag(A) ::= SIMPELOUTPUT(B). { smartytag(A) ::= SIMPELOUTPUT(B). {
$var = trim(substr(B, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' $'); $var = trim(substr(B, $this->compiler->getLdelLength(), -$this->compiler->getRdelLength()), ' $');
if (preg_match('/^(.*)(\s+nocache)$/', $var, $match)) { if (preg_match('/^(.*)(\s+nocache)$/', $var, $match)) {
A = $this->compiler->compileTag('private_print_expression',array('nocache'),array('value'=>$this->compiler->compileVariable('\''.$match[1].'\''))); A = (new \Smarty\Compile\PrintExpressionCompiler())->compile(array('nocache'),$this->compiler,array('value'=>$this->compiler->compileVariable('\''.$match[1].'\'')));
} else { } else {
A = $this->compiler->compileTag('private_print_expression',array(),array('value'=>$this->compiler->compileVariable('\''.$var.'\''))); A = (new \Smarty\Compile\PrintExpressionCompiler())->compile(array(),$this->compiler,array('value'=>$this->compiler->compileVariable('\''.$var.'\'')));
} }
} }
@@ -321,7 +321,7 @@ smartytag(A)::= SIMPLETAG(B). {
if ($this->security) { if ($this->security) {
$this->security->isTrustedConstant($tag, $this->compiler); $this->security->isTrustedConstant($tag, $this->compiler);
} }
A = $this->compiler->compileTag('private_print_expression',array(),array('value'=>$tag)); A = (new \Smarty\Compile\PrintExpressionCompiler())->compile(array(),$this->compiler,array('value'=>$tag));
} else { } else {
if (preg_match('/^(.*)(\s+nocache)$/', $tag, $match)) { if (preg_match('/^(.*)(\s+nocache)$/', $tag, $match)) {
A = $this->compiler->compileTag($match[1],array('\'nocache\'')); A = $this->compiler->compileTag($match[1],array('\'nocache\''));
@@ -352,7 +352,7 @@ smartytag(A) ::= LDEL tagbody(B) RDEL. {
} }
// output with optional attributes // output with optional attributes
tagbody(A) ::= outattr(B). { tagbody(A) ::= outattr(B). {
A = $this->compiler->compileTag('private_print_expression',B[1],array('value'=>B[0])); A = (new \Smarty\Compile\PrintExpressionCompiler())->compile(B[1],$this->compiler,array('value'=>B[0]));
} }
// //
@@ -392,7 +392,7 @@ tag(res) ::= LDEL ID(i) attributes(a). {
if ($this->security) { if ($this->security) {
$this->security->isTrustedConstant(i, $this->compiler); $this->security->isTrustedConstant(i, $this->compiler);
} }
res = $this->compiler->compileTag('private_print_expression',a,array('value'=>i)); res = (new \Smarty\Compile\PrintExpressionCompiler())->compile(a,$this->compiler,array('value'=>i));
} else { } else {
res = $this->compiler->compileTag(i,a); res = $this->compiler->compileTag(i,a);
} }
@@ -402,7 +402,7 @@ tag(res) ::= LDEL ID(i). {
if ($this->security) { if ($this->security) {
$this->security->isTrustedConstant(i, $this->compiler); $this->security->isTrustedConstant(i, $this->compiler);
} }
res = $this->compiler->compileTag('private_print_expression',array(),array('value'=>i)); res = (new \Smarty\Compile\PrintExpressionCompiler())->compile(array(),$this->compiler,array('value'=>i));
} else { } else {
res = $this->compiler->compileTag(i,array()); res = $this->compiler->compileTag(i,array());
} }
@@ -415,7 +415,7 @@ tag(res) ::= LDEL ID(i) modifierlist(l)attributes(a). {
if ($this->security) { if ($this->security) {
$this->security->isTrustedConstant(i, $this->compiler); $this->security->isTrustedConstant(i, $this->compiler);
} }
res = $this->compiler->compileTag('private_print_expression',a,array('value'=>i, 'modifierlist'=>l)); res = (new \Smarty\Compile\PrintExpressionCompiler())->compile(a,$this->compiler,array('value'=>i, 'modifierlist'=>l));
} else { } else {
res = $this->compiler->compileTag(i,a, array('modifierlist'=>l)); res = $this->compiler->compileTag(i,a, array('modifierlist'=>l));
} }
@@ -764,7 +764,7 @@ value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). {
} }
$prefixVar = $this->compiler->getNewPrefixVariable(); $prefixVar = $this->compiler->getNewPrefixVariable();
if (vi['var'] === '\'smarty\'') { if (vi['var'] === '\'smarty\'') {
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).';?>'); $this->compiler->appendPrefixCode("<?php {$prefixVar} = ". (new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,vi['smarty_internal_index']).';?>');
} else { } else {
$this->compiler->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].';?>'); $this->compiler->appendPrefixCode("<?php {$prefixVar} = ". $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].';?>');
} }
@@ -780,7 +780,7 @@ value(res) ::= smartytag(st). {
} }
value(res) ::= value(v) modifierlist(l). { value(res) ::= value(v) modifierlist(l). {
res = $this->compiler->compileTag('private_modifier',array(),array('value'=>v,'modifierlist'=>l)); res = $this->compiler->compileModifier(l, v);
} }
// name space constant // name space constant
value(res) ::= NAMESPACE(c). { value(res) ::= NAMESPACE(c). {
@@ -827,7 +827,7 @@ variable(res) ::= DOLLARID(i). {
} }
variable(res) ::= varindexed(vi). { variable(res) ::= varindexed(vi). {
if (vi['var'] === '\'smarty\'') { if (vi['var'] === '\'smarty\'') {
$smarty_var = $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']); $smarty_var = (new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,vi['smarty_internal_index']);
res = $smarty_var; res = $smarty_var;
} else { } else {
// used for array reset,next,prev,end,current // used for array reset,next,prev,end,current
@@ -912,11 +912,11 @@ indexdef(res) ::= DOT LDEL expr(e) RDEL. {
// section tag index // section tag index
indexdef(res) ::= OPENB ID(i)CLOSEB. { indexdef(res) ::= OPENB ID(i)CLOSEB. {
res = '['.$this->compiler->compileTag('private_special_variable',array(),'[\'section\'][\''.i.'\'][\'index\']').']'; res = '['.(new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,'[\'section\'][\''.i.'\'][\'index\']').']';
} }
indexdef(res) ::= OPENB ID(i) DOT ID(i2) CLOSEB. { indexdef(res) ::= OPENB ID(i) DOT ID(i2) CLOSEB. {
res = '['.$this->compiler->compileTag('private_special_variable',array(),'[\'section\'][\''.i.'\'][\''.i2.'\']').']'; res = '['.(new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,'[\'section\'][\''.i.'\'][\''.i2.'\']').']';
} }
indexdef(res) ::= OPENB SINGLEQUOTESTRING(s) CLOSEB. { indexdef(res) ::= OPENB SINGLEQUOTESTRING(s) CLOSEB. {
res = '['.s.']'; res = '['.s.']';
@@ -982,7 +982,7 @@ varvarele(res) ::= LDEL expr(e) RDEL. {
// //
object(res) ::= varindexed(vi) objectchain(oc). { object(res) ::= varindexed(vi) objectchain(oc). {
if (vi['var'] === '\'smarty\'') { if (vi['var'] === '\'smarty\'') {
res = $this->compiler->compileTag('private_special_variable',array(),vi['smarty_internal_index']).oc; res = (new \Smarty\Compile\SpecialVariableCompiler())->compile(array(),$this->compiler,vi['smarty_internal_index']).oc;
} else { } else {
res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].oc; res = $this->compiler->compileVariable(vi['var']).vi['smarty_internal_index'].oc;
} }

View File

@@ -177,7 +177,7 @@ abstract class BasePlugin
*/ */
public static function source( public static function source(
\Smarty\Template $_template = null, \Smarty\Template $_template = null,
\Smarty $smarty = null, \Smarty\Smarty $smarty = null,
$template_resource = null $template_resource = null
) { ) {
return \Smarty\Template\Source::load($_template, $smarty, $template_resource); return \Smarty\Template\Source::load($_template, $smarty, $template_resource);

View File

@@ -55,7 +55,7 @@ abstract class RecompiledPlugin extends BasePlugin {
// call compiler // call compiler
try { try {
eval('?>' . $_smarty_tpl->compiler->compileTemplate($_smarty_tpl)); eval('?>' . $_smarty_tpl->compiler->compileTemplate($_smarty_tpl));
} catch (Exception $e) { } catch (\Exception $e) {
unset($_smarty_tpl->compiler); unset($_smarty_tpl->compiler);
while (ob_get_level() > $level) { while (ob_get_level() > $level) {
ob_end_clean(); ob_end_clean();

View File

@@ -131,7 +131,7 @@ class InheritanceRuntime {
} }
/** /**
* \Smarty\Block constructor. * \Smarty\Runtime\Block constructor.
* - if outer level {block} of child template ($state === 1) save it as child root block * - if outer level {block} of child template ($state === 1) save it as child root block
* - otherwise process inheritance and render * - otherwise process inheritance and render
* *

View File

@@ -353,16 +353,7 @@ class Security {
*/ */
public function isTrustedTag($tag_name, $compiler) { public function isTrustedTag($tag_name, $compiler) {
// check for internal always required tags // check for internal always required tags
if (in_array( if (in_array($tag_name, ['assign', 'call'])) {
$tag_name,
[
'assign', 'call', 'private_filter', 'private_block_plugin', 'private_function_plugin',
'private_object_block_function', 'private_object_function', 'private_registered_function',
'private_registered_block', 'private_special_variable', 'private_print_expression',
'private_modifier',
]
)
) {
return true; return true;
} }
// check security settings // check security settings

View File

@@ -2,8 +2,12 @@
namespace Smarty; namespace Smarty;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use Smarty\Extension\Base; use Smarty\Extension\Base;
use Smarty\Extension\Core; use Smarty\Extension\BCPluginsAdapter;
use Smarty\Extension\CoreExtension;
use Smarty\Extension\DefaultExtension;
use Smarty\Extension\ExtensionInterface; use Smarty\Extension\ExtensionInterface;
use Smarty\Smarty\Runtime\CaptureRuntime; use Smarty\Smarty\Runtime\CaptureRuntime;
use Smarty\Smarty\Runtime\ForeachRuntime; use Smarty\Smarty\Runtime\ForeachRuntime;
@@ -49,7 +53,7 @@ class Smarty extends \Smarty\TemplateBase
/** /**
* smarty version * smarty version
*/ */
const SMARTY_VERSION = '4.3.0'; const SMARTY_VERSION = '5.0.0';
/** /**
* define variable scopes * define variable scopes
*/ */
@@ -184,7 +188,7 @@ class Smarty extends \Smarty\TemplateBase
* *
* @var callable * @var callable
*/ */
public $default_plugin_handler_func = null; private $default_plugin_handler_func = null;
/** /**
* flag if template_dir is normalized * flag if template_dir is normalized
@@ -193,13 +197,6 @@ class Smarty extends \Smarty\TemplateBase
*/ */
public $_compileDirNormalized = false; public $_compileDirNormalized = false;
/**
* flag if plugins_dir is normalized
*
* @var bool
*/
public $_pluginsDirNormalized = false;
/** /**
* flag if template_dir is normalized * flag if template_dir is normalized
* *
@@ -572,8 +569,12 @@ class Smarty extends \Smarty\TemplateBase
* @var ExtensionInterface[] * @var ExtensionInterface[]
*/ */
private $extensions = []; private $extensions = [];
/**
* @var BCPluginsAdapter
*/
private $BCPluginsAdapter;
/** /**
* Initialize new Smarty object * Initialize new Smarty object
*/ */
public function __construct() public function __construct()
@@ -593,8 +594,12 @@ class Smarty extends \Smarty\TemplateBase
if (\Smarty\Smarty::$_CHARSET !== 'UTF-8') { if (\Smarty\Smarty::$_CHARSET !== 'UTF-8') {
\Smarty\Smarty::$_UTF8_MODIFIER = ''; \Smarty\Smarty::$_UTF8_MODIFIER = '';
} }
$this->BCPluginsAdapter = new BCPluginsAdapter($this);
$this->extensions[] = new Core(); $this->extensions[] = new CoreExtension();
$this->extensions[] = new DefaultExtension();
$this->extensions[] = $this->BCPluginsAdapter;
} }
/** /**
@@ -785,17 +790,95 @@ class Smarty extends \Smarty\TemplateBase
return $this->setTemplateDir($config_dir, true); return $this->setTemplateDir($config_dir, true);
} }
/**
/**
* Registers plugin to be used in templates
*
* @param string $type plugin type
* @param string $name name of template tag
* @param callable $callback PHP callback to register
* @param bool $cacheable if true (default) this function is cache able
* @param mixed $cache_attr caching attributes if any
*
* @return $this
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.register.plugin.tpl
*
* @api Smarty::registerPlugin()
*/
public function registerPlugin($type, $name, $callback, $cacheable = true, $cache_attr = null) {
if (isset($this->registered_plugins[$type][$name])) {
throw new Exception("Plugin tag '{$name}' already registered");
} elseif (!is_callable($callback)) {
throw new Exception("Plugin '{$name}' not callable");
} elseif ($cacheable && $cache_attr) {
throw new Exception("Cannot set caching attributes for plugin '{$name}' when it is cacheable.");
} else {
$this->registered_plugins[$type][$name] = [$callback, (bool)$cacheable, (array)$cache_attr];
}
return $this;
}
/**
* Returns plugin previously registered using ::registerPlugin as a numerical array as follows or null if not found:
* [
* 0 => the callback
* 1 => (bool) $cacheable
* 2 => (array) $cache_attr
* ]
*
* @param string $type plugin type
* @param string $name name of template tag
*
* @return array|null
* @link https://www.smarty.net/docs/en/api.unregister.plugin.tpl
*
* @api Smarty::unregisterPlugin()
*/
public function getRegisteredPlugin($type, $name): ?array {
if (isset($this->registered_plugins[$type][$name])) {
return $this->registered_plugins[$type][$name];
}
return null;
}
/**
* Unregisters plugin previously registered using ::registerPlugin
*
* @param string $type plugin type
* @param string $name name of template tag
*
* @return $this
* @link https://www.smarty.net/docs/en/api.unregister.plugin.tpl
*
* @api Smarty::unregisterPlugin()
*/
public function unregisterPlugin($type, $name) {
if (isset($this->registered_plugins[$type][$name])) {
unset($this->registered_plugins[$type][$name]);
}
return $this;
}
/**
* Adds directory of plugin files * Adds directory of plugin files
* *
* @param null|array|string $plugins_dir * @param null|array|string $plugins_dir
* *
* @return Smarty current Smarty instance for chaining * @return Smarty current Smarty instance for chaining
* @deprecated since 5.0
*/ */
public function addPluginsDir($plugins_dir) public function addPluginsDir($plugins_dir)
{ {
$this->plugins_dir = array_merge($this->plugins_dir, (array)$plugins_dir); trigger_error('Using Smarty::addPluginsDir() to load plugins is deprecated and will be ' .
$this->_pluginsDirNormalized = false; 'removed in a future release. Use Smarty::addExtension() to add an extension or Smarty::registerPlugin to ' .
'quickly register a plugin using a callback function.', E_USER_DEPRECATED);
foreach ((array) $plugins_dir as $v) {
$path = $this->_realpath(rtrim($v ?? '', '/\\') . DIRECTORY_SEPARATOR, true);
$this->BCPluginsAdapter->loadPluginsFromDir($path);
}
return $this; return $this;
} }
@@ -803,17 +886,13 @@ class Smarty extends \Smarty\TemplateBase
* Get plugin directories * Get plugin directories
* *
* @return array list of plugin directories * @return array list of plugin directories
* @deprecated since 5.0
*/ */
public function getPluginsDir() public function getPluginsDir()
{ {
if (!$this->_pluginsDirNormalized) { trigger_error('Using Smarty::getPluginsDir() is deprecated and will be ' .
foreach ($this->plugins_dir as $k => $v) { 'removed in a future release. It will always return an empty array.', E_USER_DEPRECATED);
$this->plugins_dir[ $k ] = $this->_realpath(rtrim($v ?? '', '/\\') . DIRECTORY_SEPARATOR, true); return [];
}
$this->_cache[ 'plugin_files' ] = array();
$this->_pluginsDirNormalized = true;
}
return $this->plugins_dir;
} }
@@ -823,14 +902,52 @@ class Smarty extends \Smarty\TemplateBase
* @param string|array $plugins_dir directory(s) of plugins * @param string|array $plugins_dir directory(s) of plugins
* *
* @return Smarty current Smarty instance for chaining * @return Smarty current Smarty instance for chaining
* @deprecated since 5.0
*/ */
public function setPluginsDir($plugins_dir) public function setPluginsDir($plugins_dir)
{ {
$this->plugins_dir = (array)$plugins_dir; trigger_error('Using Smarty::getPluginsDir() is deprecated and will be ' .
$this->_pluginsDirNormalized = false; 'removed in a future release. For now, it will remove the DefaultExtension from the extensions list and ' .
return $this; 'proceed to call Smartyy::addPluginsDir..', E_USER_DEPRECATED);
$this->extensions = array_filter(
$this->extensions,
function ($extension) {
return !($extension instanceof DefaultExtension);
}
);
return $this->addPluginsDir($plugins_dir);
} }
/**
* Registers a default plugin handler
*
* @param callable $callback class/method name
*
* @return $this
* @throws Exception if $callback is not callable
* @link https://www.smarty.net/docs/en/api.register.default.plugin.handler.tpl
*
* @api Smarty::registerDefaultPluginHandler()
*
* @deprecated since 5.0
*/
public function registerDefaultPluginHandler($callback) {
trigger_error('Using Smarty::registerDefaultPluginHandler() is deprecated and will be ' .
'removed in a future release. Please rewrite your plugin handler as an extension.',
E_USER_DEPRECATED);
if (is_callable($callback)) {
$this->default_plugin_handler_func = $callback;
} else {
throw new Exception("Default plugin handler '$callback' not callable");
}
return $this;
}
/** /**
* Get compiled directory * Get compiled directory
* *
@@ -925,8 +1042,7 @@ class Smarty extends \Smarty\TemplateBase
$tpl->inheritance = null; $tpl->inheritance = null;
$tpl->tpl_vars = $tpl->config_vars = array(); $tpl->tpl_vars = $tpl->config_vars = array();
} else { } else {
/* @var \Smarty\Template $tpl */ $tpl = new \Smarty\Template($template, $this, null, $cache_id, $compile_id, null, null);
$tpl = new $this->template_class($template, $this, null, $cache_id, $compile_id, null, null);
$tpl->templateId = $_templateId; $tpl->templateId = $_templateId;
} }
if ($do_clone) { if ($do_clone) {
@@ -1368,8 +1484,8 @@ class Smarty extends \Smarty\TemplateBase
$_count = 0; $_count = 0;
try { try {
$_compileDirs = new RecursiveDirectoryIterator($_dir); $_compileDirs = new RecursiveDirectoryIterator($_dir);
// NOTE: UnexpectedValueException thrown for PHP >= 5.3 } catch (\UnexpectedValueException $e) {
} catch (Exception $e) { // path not found / not a dir
return 0; return 0;
} }
$_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST); $_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST);
@@ -1515,16 +1631,14 @@ class Smarty extends \Smarty\TemplateBase
if ($_fileinfo->getPath() !== substr($_dir, 0, -1)) { if ($_fileinfo->getPath() !== substr($_dir, 0, -1)) {
$_file = substr($_fileinfo->getPath(), strlen($_dir)) . DIRECTORY_SEPARATOR . $_file; $_file = substr($_fileinfo->getPath(), strlen($_dir)) . DIRECTORY_SEPARATOR . $_file;
} }
echo "\n<br>", $_dir, '---', $_file; echo "\n", $_dir, '---', $_file;
flush(); flush();
$_start_time = microtime(true); $_start_time = microtime(true);
$_smarty = clone $this; $_smarty = clone $this;
// //
$_smarty->_cache = array();
$_smarty->force_compile = $force_compile; $_smarty->force_compile = $force_compile;
try { try {
/* @var Template $_tpl */ $_tpl = new \Smarty\Template($_file, $_smarty);
$_tpl = new $this->template_class($_file, $_smarty);
$_tpl->caching = self::CACHING_OFF; $_tpl->caching = self::CACHING_OFF;
$_tpl->source = $_tpl->source =
$isConfig ? \Smarty\Template\Config::load($_tpl) : \Smarty\Template\Source::load($_tpl); $isConfig ? \Smarty\Template\Config::load($_tpl) : \Smarty\Template\Source::load($_tpl);
@@ -1537,20 +1651,20 @@ class Smarty extends \Smarty\TemplateBase
echo ' is up to date'; echo ' is up to date';
flush(); flush();
} }
} catch (Exception $e) { } catch (\Exception $e) {
echo "\n<br> ------>Error: ", $e->getMessage(), "<br><br>\n"; echo "\n ------>Error: ", $e->getMessage(), "\n";
$_error_count++; $_error_count++;
} }
// free memory // free memory
unset($_tpl); unset($_tpl);
$_smarty->_clearTemplateCache(); $_smarty->_clearTemplateCache();
if ($max_errors !== null && $_error_count === $max_errors) { if ($max_errors !== null && $_error_count === $max_errors) {
echo "\n<br><br>too many errors\n"; echo "\ntoo many errors\n";
exit(1); exit(1);
} }
} }
} }
echo "\n<br>"; echo "\n";
return $_count; return $_count;
} }
@@ -1611,25 +1725,106 @@ class Smarty extends \Smarty\TemplateBase
} }
} }
public function getModifierCallback(string $modifierName) {
foreach ($this->getExtensions() as $extension) {
if ($callback = $extension->getModifierCallback($modifierName)) {
return $callback;
}
}
return null;
}
public function getFunctionHandler(string $functionName): ?\Smarty\FunctionHandler\FunctionHandlerInterface {
foreach ($this->getExtensions() as $extension) {
if ($handler = $extension->getFunctionHandler($functionName)) {
return $handler;
}
}
return null;
}
public function getBlockHandler(string $blockTagName): ?\Smarty\BlockHandler\BlockHandlerInterface {
foreach ($this->getExtensions() as $extension) {
if ($handler = $extension->getBlockHandler($blockTagName)) {
return $handler;
}
}
return null;
}
public function getModifierCompiler(string $modifier): ?\Smarty\Compile\Modifier\ModifierCompilerInterface {
foreach ($this->getExtensions() as $extension) {
if ($handler = $extension->getModifierCompiler($modifier)) {
return $handler;
}
}
return null;
}
/** /**
* Run filters over content * Run pre-filters over template source
* The filters will be lazy loaded if required *
* @param string $source the content which shall be processed by the filters
* @param Template $template template object
*
* @return string the filtered source
*/
public function runPreFilters($source, Template $template)
{
foreach ($this->getExtensions() as $extension) {
/** @var \Smarty\Filter\FilterInterface $filter */
foreach ($extension->getPreFilters() as $filter) {
$source = $filter->filter($source, $template);
}
}
// return filtered output
return $source;
}
/**
* Run post-filters over template's compiled code
*
* @param string $code the content which shall be processed by the filters
* @param Template $template template object
*
* @return string the filtered code
*/
public function runPostFilters($code, Template $template)
{
foreach ($this->getExtensions() as $extension) {
/** @var \Smarty\Filter\FilterInterface $filter */
foreach ($extension->getPostFilters() as $filter) {
$code = $filter->filter($code, $template);
}
}
// return filtered output
return $code;
}
/**
* Run filters over template output
* *
* @param string $type the type of filter ('pre','post','output') which shall run
* @param string $content the content which shall be processed by the filters * @param string $content the content which shall be processed by the filters
* @param Template $template template object * @param Template $template template object
* *
* @return string the filtered content * @return string the filtered (modified) output
*@throws Exception
*/ */
public function runFilter($type, $content, Template $template) public function runOutputFilters($content, Template $template)
{ {
// loop over registered filters of specified type
if (!empty($this->registered_filters[ $type ])) { foreach ($this->getExtensions() as $extension) {
foreach ($this->registered_filters[ $type ] as $key => $name) { /** @var \Smarty\Filter\FilterInterface $filter */
$content = call_user_func($this->registered_filters[ $type ][ $key ], $content, $template); foreach ($extension->getOutputFilters() as $filter) {
$content = $filter->filter($content, $template);
} }
} }
// return filtered output // return filtered output
return $content; return $content;
} }
@@ -1911,4 +2106,11 @@ class Smarty extends \Smarty\TemplateBase
} }
} }
/**
* @return callable|null
*/
public function getDefaultPluginHandlerFunc(): ?callable {
return $this->default_plugin_handler_func;
}
} }

View File

@@ -23,7 +23,6 @@ use Smarty\Template\Config;
* @property Compiled $compiled * @property Compiled $compiled
* @property Cached $cached * @property Cached $cached
* @property \Smarty\Compiler\Template $compiler * @property \Smarty\Compiler\Template $compiler
* @property mixed|\Smarty\Template\Cached registered_plugins
*/ */
#[\AllowDynamicProperties] #[\AllowDynamicProperties]
class Template extends TemplateBase { class Template extends TemplateBase {
@@ -224,7 +223,7 @@ class Template extends TemplateBase {
if ((!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) if ((!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled)
&& !$no_output_filter && isset($this->smarty->registered_filters['output']) && !$no_output_filter && isset($this->smarty->registered_filters['output'])
) { ) {
echo $this->smarty->runFilter('output', ob_get_clean(), $this); echo $this->smarty->runOutputFilters(ob_get_clean(), $this);
} else { } else {
echo ob_get_clean(); echo ob_get_clean();
} }
@@ -247,7 +246,7 @@ class Template extends TemplateBase {
&& (!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) && (!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled)
&& isset($this->smarty->registered_filters['output']) && isset($this->smarty->registered_filters['output'])
) { ) {
return $this->smarty->runFilter('output', ob_get_clean(), $this); return $this->smarty->runOutputFilters(ob_get_clean(), $this);
} }
// return cache content // return cache content
return null; return null;
@@ -360,7 +359,6 @@ class Template extends TemplateBase {
$this->cached->hashes[$tpl->compiled->nocache_hash] = true; $this->cached->hashes[$tpl->compiled->nocache_hash] = true;
} }
} }
$tpl->_cache = [];
if (isset($uid)) { if (isset($uid)) {
if ($smarty->debugging) { if ($smarty->debugging) {
if (!isset($smarty->_debug)) { if (!isset($smarty->_debug)) {
@@ -442,7 +440,7 @@ class Template extends TemplateBase {
* @return bool flag if compiled or cache file is valid * @return bool flag if compiled or cache file is valid
* @throws \Smarty\Exception * @throws \Smarty\Exception
*/ */
public function _decodeProperties(Template $tpl, $properties, $cache = false) { public function isFresh(Template $tpl, $properties, $cache = false) {
// on cache resources other than file check version stored in cache code // on cache resources other than file check version stored in cache code
if (!isset($properties['version']) || \Smarty\Smarty::SMARTY_VERSION !== $properties['version']) { if (!isset($properties['version']) || \Smarty\Smarty::SMARTY_VERSION !== $properties['version']) {
if ($cache) { if ($cache) {
@@ -468,7 +466,7 @@ class Template extends TemplateBase {
$mtime = is_file($_file_to_check[0]) ? filemtime($_file_to_check[0]) : false; $mtime = is_file($_file_to_check[0]) ? filemtime($_file_to_check[0]) : false;
} }
} else { } else {
$handler = Smarty\Resource\BasePlugin::load($tpl->smarty, $_file_to_check[2]); $handler = \Smarty\Resource\BasePlugin::load($tpl->smarty, $_file_to_check[2]);
if ($handler->checkTimestamps()) { if ($handler->checkTimestamps()) {
$source = Source::load($tpl, $tpl->smarty, $_file_to_check[0]); $source = Source::load($tpl, $tpl->smarty, $_file_to_check[0]);
$mtime = $source->getTimeStamp(); $mtime = $source->getTimeStamp();
@@ -601,12 +599,7 @@ class Template extends TemplateBase {
* @throws \Smarty\Exception * @throws \Smarty\Exception
*/ */
public function loadCompiler() { public function loadCompiler() {
$this->compiler = $this->compiler = $this->source->createCompiler();
new $this->source->compiler_class(
$this->source->template_lexer_class,
$this->source->template_parser_class,
$this->smarty
);
} }
/** /**

View File

@@ -370,7 +370,7 @@ class Cached extends ResourceBase {
&& !$_template->cached->has_nocache_code && !$_template->cached->has_nocache_code
&& isset($_template->smarty->registered_filters['output']) && isset($_template->smarty->registered_filters['output'])
) { ) {
$content = $_template->smarty->runFilter('output', $content, $_template); $content = $_template->smarty->runOutputFilters($content, $_template);
} }
// write cache file content // write cache file content
$_template->writeCachedContent($content); $_template->writeCachedContent($content);

View File

@@ -181,7 +181,7 @@ class Compiled extends ResourceBase {
// call compiler // call compiler
$_template->loadCompiler(); $_template->loadCompiler();
$this->write($_template, $_template->compiler->compileTemplate($_template)); $this->write($_template, $_template->compiler->compileTemplate($_template));
} catch (Exception $e) { } catch (\Exception $e) {
// restore old timestamp in case of error // restore old timestamp in case of error
if ($saved_timestamp && is_file($this->filepath)) { if ($saved_timestamp && is_file($this->filepath)) {
touch($this->filepath, $saved_timestamp); touch($this->filepath, $saved_timestamp);

View File

@@ -35,27 +35,6 @@ class Config extends Source {
*/ */
public $isConfig = true; public $isConfig = true;
/**
* Name of the Class to compile this resource's contents with
*
* @var string
*/
public $compiler_class = \Smarty\Compiler\Configfile::class;
/**
* Name of the Class to tokenize this resource's contents with
*
* @var string
*/
public $template_lexer_class = \Smarty\Lexer\ConfigfileLexer::class;
/**
* Name of the Class to parse this resource's contents with
*
* @var string
*/
public $template_parser_class = \Smarty\Parser\ConfigfileParser::class;
/** /**
* initialize Source Object for given resource * initialize Source Object for given resource
* Either [$_template] or [$smarty, $template_resource] must be specified * Either [$_template] or [$smarty, $template_resource] must be specified
@@ -81,7 +60,7 @@ class Config extends Source {
throw new Exception('Source: Missing name'); throw new Exception('Source: Missing name');
} }
// parse resource_name, load resource handler // parse resource_name, load resource handler
[$name, $type] = Smarty\Resource\BasePlugin::parseResourceName($template_resource, $smarty->default_config_type); [$name, $type] = \Smarty\Resource\BasePlugin::parseResourceName($template_resource, $smarty->default_config_type);
// make sure configs are not loaded via anything smarty can't handle // make sure configs are not loaded via anything smarty can't handle
if (isset($_incompatible_resources[$type])) { if (isset($_incompatible_resources[$type])) {
throw new Exception("Unable to use resource '{$type}' for config"); throw new Exception("Unable to use resource '{$type}' for config");
@@ -94,4 +73,8 @@ class Config extends Source {
} }
return $source; return $source;
} }
public function createCompiler(): \Smarty\Compiler\BaseCompiler {
return new \Smarty\Compiler\Configfile($this->smarty);
}
} }

View File

@@ -107,27 +107,6 @@ class Source {
*/ */
public $content = null; public $content = null;
/**
* Name of the Class to compile this resource's contents with
*
* @var string
*/
public $compiler_class = \Smarty\Compiler\Template::class;
/**
* Name of the Class to tokenize this resource's contents with
*
* @var string
*/
public $template_lexer_class = \Smarty\Lexer\TemplateLexer::class;
/**
* Name of the Class to parse this resource's contents with
*
* @var string
*/
public $template_parser_class = \Smarty\Parser\TemplateParser::class;
/** /**
* create Source Object container * create Source Object container
* *
@@ -152,9 +131,9 @@ class Source {
* initialize Source Object for given resource * initialize Source Object for given resource
* Either [$_template] or [$smarty, $template_resource] must be specified * Either [$_template] or [$smarty, $template_resource] must be specified
* *
* @param Template $_template template object * @param Template|null $_template template object
* @param Smarty $smarty smarty object * @param Smarty|null $smarty smarty object
* @param string $template_resource resource identifier * @param null $template_resource resource identifier
* *
* @return Source Source Object * @return Source Source Object
* @throws Exception * @throws Exception
@@ -210,7 +189,7 @@ class Source {
* @throws \Smarty\Exception * @throws \Smarty\Exception
*/ */
public function getContent() { public function getContent() {
return isset($this->content) ? $this->content : $this->handler->getContent($this); return $this->content ?? $this->handler->getContent($this);
} }
/** /**
@@ -241,7 +220,7 @@ class Source {
$this->content = $_content; $this->content = $_content;
$this->exists = true; $this->exists = true;
$this->uid = $this->name = sha1($_content); $this->uid = $this->name = sha1($_content);
$this->handler = Smarty\Resource\BasePlugin::load($this->smarty, 'eval'); $this->handler = \Smarty\Resource\BasePlugin::load($this->smarty, 'eval');
} else { } else {
$this->exists = false; $this->exists = false;
throw new Exception( throw new Exception(
@@ -250,4 +229,9 @@ class Source {
); );
} }
} }
public function createCompiler(): \Smarty\Compiler\BaseCompiler {
return new \Smarty\Compiler\Template($this->smarty);
}
} }

View File

@@ -237,7 +237,7 @@ abstract class TemplateBase extends Data {
error_reporting($_smarty_old_error_level); error_reporting($_smarty_old_error_level);
} }
return $result; return $result;
} catch (Throwable $e) { } catch (\Throwable $e) {
while (ob_get_level() > $level) { while (ob_get_level() > $level) {
ob_end_clean(); ob_end_clean();
} }
@@ -252,54 +252,6 @@ abstract class TemplateBase extends Data {
} }
} }
/**
* Registers plugin to be used in templates
*
* @param string $type plugin type
* @param string $name name of template tag
* @param callable $callback PHP callback to register
* @param bool $cacheable if true (default) this function is cache able
* @param mixed $cache_attr caching attributes if any
*
* @return \Smarty|\Smarty\Template
* @throws \Smarty\Exception
* @link https://www.smarty.net/docs/en/api.register.plugin.tpl
*
* @api Smarty::registerPlugin()
*/
public function registerPlugin($type, $name, $callback, $cacheable = true, $cache_attr = null) {
$smarty = $this->_getSmartyObj();
if (isset($smarty->registered_plugins[$type][$name])) {
throw new Exception("Plugin tag '{$name}' already registered");
} elseif (!is_callable($callback)) {
throw new Exception("Plugin '{$name}' not callable");
} elseif ($cacheable && $cache_attr) {
throw new Exception("Cannot set caching attributes for plugin '{$name}' when it is cacheable.");
} else {
$smarty->registered_plugins[$type][$name] = [$callback, (bool)$cacheable, (array)$cache_attr];
}
return $this;
}
/**
* Registers plugin to be used in templates
*
* @param string $type plugin type
* @param string $name name of template tag
*
* @return \Smarty|\Smarty\Template
* @link https://www.smarty.net/docs/en/api.unregister.plugin.tpl
*
* @api Smarty::unregisterPlugin()
*/
public function unregisterPlugin($type, $name) {
$smarty = $this->_getSmartyObj();
if (isset($smarty->registered_plugins[$type][$name])) {
unset($smarty->registered_plugins[$type][$name]);
}
return $this;
}
/** /**
* load a filter of specified type and name * load a filter of specified type and name
* *
@@ -780,27 +732,6 @@ abstract class TemplateBase extends Data {
return $this; return $this;
} }
/**
* Registers a default plugin handler
*
* @param callable $callback class/method name
*
* @return TemplateBase
* @throws Exception if $callback is not callable
* @link https://www.smarty.net/docs/en/api.register.default.plugin.handler.tpl
*
* @api Smarty::registerDefaultPluginHandler()
*/
public function registerDefaultPluginHandler($callback) {
$smarty = $this->_getSmartyObj();
if (is_callable($callback)) {
$smarty->default_plugin_handler_func = $callback;
} else {
throw new Exception("Default plugin handler '$callback' not callable");
}
return $this;
}
/** /**
* Register template default handler * Register template default handler
* *
@@ -832,7 +763,7 @@ abstract class TemplateBase extends Data {
* *
* @api Smarty::registerResource() * @api Smarty::registerResource()
*/ */
public function registerResource($name, Smarty\Resource\Base $resource_handler) { public function registerResource($name, \Smarty\Resource\BasePlugin $resource_handler) {
$smarty = $this->_getSmartyObj(); $smarty = $this->_getSmartyObj();
$smarty->registered_resources[$name] = $resource_handler; $smarty->registered_resources[$name] = $resource_handler;
return $this; return $this;

View File

@@ -604,8 +604,9 @@ KEY `name` (`name`)
$_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null; $_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null;
$_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null; $_cache_id = isset($cache_id) ? preg_replace('![^\w\|]+!', '_', $cache_id) : null;
return sha1($uid . $_cache_id . $_compile_id); return sha1($uid . $_cache_id . $_compile_id);
case 'memcache':
case 'memcachetest': case 'memcachetest':
case 'acp': case 'apc':
$sp = $this->buildSourcePath($tpl, $name, $type, $dir); $sp = $this->buildSourcePath($tpl, $name, $type, $dir);
$uid = $this->buildUid($tpl, $sp, $name, $type); $uid = $this->buildUid($tpl, $sp, $name, $type);
$_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null; $_compile_id = isset($compile_id) ? preg_replace('![^\w\|]+!', '_', $compile_id) : null;

View File

@@ -1,145 +0,0 @@
<?php
/*
* This file is part of the Smarty PHPUnit tests.
*/
/**
* class for path normalization tests
*
* @runTestsInSeparateProcess
* @preserveGlobalState disabled
* @backupStaticAttributes enabled
*/
class PluginNormalizationTest extends PHPUnit_Smarty
{
/*
* Setup test fixture
*/
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
}
public function testGetPluginsDefaultDir()
{
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->assertEquals(SMARTY_PLUGINS_DIR, $result[ 0 ]);
}
public function testGetPluginsDefaultDir2()
{
$this->smarty->addPluginsDir('./foo/');
$result = $this->smarty->getPluginsDir();
$this->assertEquals(2, count($result));
$this->assertEquals(SMARTY_PLUGINS_DIR, $result[ 0 ]);
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $result[ 1 ]);
}
public function testSetPluginsDir1()
{
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->smarty->setPluginsDir('foo');
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $result[ 0 ]);
}
public function testSetPluginsDir2()
{
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->smarty->setPluginsDir('foo/');
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $result[ 0 ]);
}
public function testSetPluginsDir3()
{
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->smarty->setPluginsDir('foo/.');
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $result[ 0 ]);
}
public function testSetPluginsDir4()
{
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->smarty->setPluginsDir('foo/./');
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $result[ 0 ]);
}
public function testSetPluginsDir5()
{
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->smarty->setPluginsDir('.foo');
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . '.foo' . DIRECTORY_SEPARATOR, $result[ 0 ]);
}
public function testSetPluginsDir6()
{
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->smarty->setPluginsDir('..foo');
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . '..foo' . DIRECTORY_SEPARATOR, $result[ 0 ]);
}
public function testSetPluginsDir7()
{
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->smarty->setPluginsDir('../foo');
$result = $this->smarty->getPluginsDir();
$this->assertEquals(1, count($result));
$this->assertEquals(substr(getcwd(), 0, - strlen(basename(getcwd()))) . 'foo' . DIRECTORY_SEPARATOR,
$result[ 0 ]);
}
public function testSetPluginsDir8()
{
$this->smarty->setPluginsDir(array('foo', 'bah'));
$result = $this->smarty->getPluginsDir();
$this->assertEquals(2, count($result));
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $result[ 0 ]);
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'bah' . DIRECTORY_SEPARATOR, $result[ 1 ]);
}
public function testSetPluginsDir9()
{
$this->smarty->setPluginsDir(array('foo', 'bah'));
$result = $this->smarty->getPluginsDir();
$this->assertEquals(2, count($result));
$this->smarty->addPluginsDir('blar');
$result = $this->smarty->getPluginsDir();
$this->assertEquals(3, count($result));
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $result[ 0 ]);
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'bah' . DIRECTORY_SEPARATOR, $result[ 1 ]);
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'blar' . DIRECTORY_SEPARATOR, $result[ 2 ]);
}
public function testSetPluginsDir10()
{
$this->smarty->setPluginsDir(array('foo', 'bah'));
$result = $this->smarty->getPluginsDir();
$this->assertEquals(2, count($result));
$this->smarty->addPluginsDir(array('blar', 'smarty'));
$result = $this->smarty->getPluginsDir();
$this->assertEquals(4, count($result));
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $result[ 0 ]);
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'bah' . DIRECTORY_SEPARATOR, $result[ 1 ]);
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'blar' . DIRECTORY_SEPARATOR, $result[ 2 ]);
$this->assertEquals(getcwd() . DIRECTORY_SEPARATOR . 'smarty' . DIRECTORY_SEPARATOR, $result[ 3 ]);
}
}

View File

@@ -3,6 +3,8 @@
* This file is part of the Smarty PHPUnit tests. * This file is part of the Smarty PHPUnit tests.
*/ */
use Smarty\Smarty;
/** /**
* class for protected $template_dir, $compile_dir, $cache_dir, $config_dir, $plugins_dir property tests * class for protected $template_dir, $compile_dir, $cache_dir, $config_dir, $plugins_dir property tests
* *
@@ -112,51 +114,6 @@ class ProtectedFolderVarsTest extends PHPUnit_Smarty
$this->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'bar' . DIRECTORY_SEPARATOR, $d[ 0 ]); $this->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'bar' . DIRECTORY_SEPARATOR, $d[ 0 ]);
} }
/*
* plugins_dir
*/
public function testPluginDirDirectRelative()
{
$s = new Smarty();
$s->setPluginsDir('./foo');
$d = $s->getPluginsDir();
$this->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $d[ 0 ]);
}
public function testPluginDirDirectRelativeArray()
{
$s = new Smarty();
$s->setPluginsDir(array('./foo', './bar/'));
$d = $s->getPluginsDir();
$this->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $d[ 0 ]);
$this->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'bar' . DIRECTORY_SEPARATOR, $d[ 1 ]);
}
public function testPluginDirDirectRelativeArrayAdd()
{
$s = new Smarty();
$s->setPluginsDir('./foo');
$s->addPluginsDir('./bar/');
$d = $s->getPluginsDir();
$this->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR, $d[ 0 ]);
$this->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'bar' . DIRECTORY_SEPARATOR, $d[ 1 ]);
}
public function testPluginDirDirectRelativeExtends()
{
$s = new FolderT();
$d = $s->getPluginsDir();
$this->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'plug' . DIRECTORY_SEPARATOR, $d[ 0 ]);
}
public function testPluginDirDirectRelativeExtends2()
{
$s = new FolderT();
$s->setPluginsDir('./bar');
$d = $s->getPluginsDir();
$this->assertEquals(__DIR__ . DIRECTORY_SEPARATOR . 'bar' . DIRECTORY_SEPARATOR, $d[ 0 ]);
}
/* /*
* compile_dir * compile_dir
*/ */

View File

@@ -37,11 +37,11 @@ class LoadPluginTest extends PHPUnit_Smarty
} }
/** /**
* loadPlugin test $template_class exists * loadPlugin test \Smarty\Template exists
*/ */
public function testLoadPluginSmartyTemplateClass() public function testLoadPluginSmartyTemplateClass()
{ {
$this->assertTrue($this->smarty->loadPlugin($this->smarty->template_class) == true); $this->assertTrue($this->smarty->loadPlugin(\Smarty\Template) == true);
} }
/** /**

View File

@@ -6,6 +6,7 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
include_once __DIR__ . '/../Memcache/CacheResourceCustomMemcacheTest.php'; include_once __DIR__ . '/../Memcache/CacheResourceCustomMemcacheTest.php';
include_once __DIR__ . '/../_shared/PHPunitplugins/cacheresource.apctest.php';
/** /**
* class for cache resource file tests * class for cache resource file tests
@@ -24,7 +25,7 @@ class CacheResourceCustomApcTest extends CacheResourceCustomMemcacheTest
$this->setUpSmarty(__DIR__); $this->setUpSmarty(__DIR__);
parent::setUp(); parent::setUp();
$this->smarty->setCachingType('apc'); $this->smarty->setCachingType('apc');
$this->smarty->addPluginsDir(SMARTY_DIR . '../demo/plugins/'); $this->smarty->registerCacheResource('apc', new Smarty_CacheResource_Apctest());
} }
} }

View File

@@ -5,43 +5,41 @@
* @package PHPunit * @package PHPunit
* @author Uwe Tews * @author Uwe Tews
*/ */
if (PdoCacheEnable == true) {
include_once __DIR__ . '/../_shared/CacheResourceTestCommon.php'; include_once __DIR__ . '/../_shared/CacheResourceTestCommon.php';
include_once __DIR__ . '/../_shared/PHPunitplugins/cacheresource.pdotest.php';
/** /**
* class for cache resource file tests * class for cache resource file tests
* *
* @runTestsInSeparateProcess * @runTestsInSeparateProcess
* @preserveGlobalState disabled * @preserveGlobalState disabled
* @backupStaticAttributes enabled * @backupStaticAttributes enabled
*/ */
class CacheResourceCustomPDOTest extends CacheResourceTestCommon class CacheResourceCustomPDOTest extends CacheResourceTestCommon
{
public function setUp($dir = null, $clear = true): void
{ {
if (PdoCacheEnable != true) {
public function setUp($dir = null, $clear = true) $this->markTestSkipped('mysql Pdo tests are disabled');
{
if (PdoCacheEnable != true) {
$this->markTestSkipped('mysql Pdo tests are disabled');
}
if (self::$init) {
$this->getConnection();
}
$this->setUpSmarty(__DIR__);
parent::setUp();
$this->smarty->setCachingType('pdo');
$this->smarty->addPluginsDir(SMARTY_DIR . '../demo/plugins/');
$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'));
} }
if (self::$init) {
public function testInit() $this->getConnection();
{
$this->cleanDirs();
$this->initMysqlCache();
} }
$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'));
}
public function testInit()
{
$this->cleanDirs();
$this->initMysqlCache();
} }
} }

View File

@@ -5,41 +5,40 @@
* @package PHPunit * @package PHPunit
* @author Uwe Tews * @author Uwe Tews
*/ */
if (PdoGzipCacheEnable == true) {
include_once __DIR__ . '/../_shared/CacheResourceTestCommon.php';
/** include_once __DIR__ . '/../_shared/CacheResourceTestCommon.php';
* class for cache resource file tests include_once __DIR__ . '/../_shared/PHPunitplugins/cacheresource.pdo_gziptest.php';
*
* @backupStaticAttributes enabled /**
*/ * class for cache resource file tests
class CacheResourceCustomPDOGzipTest extends CacheResourceTestCommon *
* @backupStaticAttributes enabled
*/
class CacheResourceCustomPDOGzipTest extends CacheResourceTestCommon
{
public function setUp($dir = null, $clear = true): void
{ {
if (PdoGzipCacheEnable != true) {
public function setUp($dir = null, $clear = true) $this->markTestSkipped('mysql Pdo Gzip tests are disabled');
{
if (PdoGzipCacheEnable != true) {
$this->markTestSkipped('mysql Pdo Gzip tests are disabled');
}
if (self::$init) {
$this->getConnection();
}
$this->setUpSmarty(__DIR__);
parent::setUp();
$this->smarty->setCachingType('pdo');
$this->smarty->addPluginsDir(SMARTY_DIR . '../demo/plugins/');
$this->assertTrue(false !== $this->smarty->loadPlugin('Smarty_CacheResource_Pdo_Gziptest'),
'loadPlugin() could not load PDOGzip cache resource');
$this->smarty->registerCacheResource('pdo', new Smarty_CacheResource_Pdo_Gziptest($this->getPDO(),
'output_cache'));
} }
if (self::$init) {
public function testInit() $this->getConnection();
{
$this->cleanDirs();
$this->initMysqlCache();
} }
$this->setUpSmarty(__DIR__);
parent::setUp();
$this->smarty->setCachingType('pdo');
$this->assertTrue(false !== $this->smarty->loadPlugin('Smarty_CacheResource_Pdo_Gziptest'),
'loadPlugin() could not load PDOGzip cache resource');
$this->smarty->registerCacheResource('pdo', new Smarty_CacheResource_Pdo_Gziptest($this->getPDO(),
'output_cache'));
}
public function testInit()
{
$this->cleanDirs();
$this->initMysqlCache();
} }
} }

View File

@@ -4,7 +4,7 @@ use Smarty\Smarty;
use Smarty\Template; use Smarty\Template;
use Smarty\Template\Cached; use Smarty\Template\Cached;
require_once SMARTY_DIR . '../demo/plugins/cacheresource.apc.php'; require_once __DIR__ . '/../../../__shared/cacheresources/cacheresource.apc.php';
class Smarty_CacheResource_Apctest extends My_CacheResource_Apc class Smarty_CacheResource_Apctest extends My_CacheResource_Apc
{ {

View File

@@ -3,7 +3,7 @@
use Smarty\Template; use Smarty\Template;
use Smarty\Template\Cached; use Smarty\Template\Cached;
require_once SMARTY_DIR . '../demo/plugins/cacheresource.memcache.php'; require_once __DIR__ . '/../../../__shared/cacheresources/cacheresource.memcache.php';
class Smarty_CacheResource_Memcachetest extends Smarty_CacheResource_Memcache class Smarty_CacheResource_Memcachetest extends Smarty_CacheResource_Memcache
{ {

View File

@@ -3,7 +3,7 @@
use Smarty\Exception; use Smarty\Exception;
use Smarty\Template\Cached; use Smarty\Template\Cached;
require_once SMARTY_DIR . '../demo/plugins/cacheresource.mysql.php'; require_once __DIR__ . '/../../../__shared/cacheresources/cacheresource.mysql.php';
class Smarty_CacheResource_Mysqltest extends Smarty_CacheResource_Mysql class Smarty_CacheResource_Mysqltest extends Smarty_CacheResource_Mysql
{ {

View File

@@ -2,13 +2,13 @@
use Smarty\Template\Cached; use Smarty\Template\Cached;
require_once SMARTY_DIR . '../demo/plugins/cacheresource.pdo_gzip.php'; require_once __DIR__ . '/../../../__shared/cacheresources/cacheresource.pdo_gzip.php';
class Smarty_CacheResource_Pdo_Gziptest extends Smarty_CacheResource_Pdo_Gzip class Smarty_CacheResource_Pdo_Gziptest extends My_CacheResource_Pdo_Gzip
{ {
public $lockTime = 0; public $lockTime = 0;
public function hasLock(Smarty $smarty, Cached $cached) public function hasLock(\Smarty\Smarty $smarty, Cached $cached)
{ {
if ($this->lockTime) { if ($this->lockTime) {
$this->lockTime--; $this->lockTime--;

View File

@@ -2,14 +2,14 @@
use Smarty\Template\Cached; use Smarty\Template\Cached;
require_once SMARTY_DIR . '../demo/plugins/cacheresource.pdo.php'; require_once __DIR__ . '/../../../__shared/cacheresources/cacheresource.pdo.php';
class Smarty_CacheResource_Pdotest extends Smarty_CacheResource_Pdo class Smarty_CacheResource_Pdotest extends My_CacheResource_Pdo
{ {
public $lockTime = 0; public $lockTime = 0;
public function hasLock(Smarty $smarty, Cached $cached) public function hasLock(\Smarty\Smarty $smarty, Cached $cached)
{ {
if ($this->lockTime) { if ($this->lockTime) {
$this->lockTime--; $this->lockTime--;

View File

@@ -6,6 +6,8 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
use Smarty\Smarty;
/** /**
* class for default config handler test * class for default config handler test
* *
@@ -117,7 +119,7 @@ class DefaultConfigHandlerTest extends PHPUnit_Smarty
* *
* @return bool * @return bool
*/ */
function configHandlerData($resource_type, $resource_name, &$config_source, &$config_timestamp, Smarty $smarty) function configHandlerData($resource_type, $resource_name, &$config_source, &$config_timestamp, \Smarty\Smarty $smarty)
{ {
if ($resource_name !== 'foo.conf') { if ($resource_name !== 'foo.conf') {
return false; return false;
@@ -140,7 +142,7 @@ function configHandlerData($resource_type, $resource_name, &$config_source, &$co
* *
* @return string * @return string
*/ */
function configHandlerFile($resource_type, $resource_name, &$config_source, &$config_timestamp, Smarty $smarty) function configHandlerFile($resource_type, $resource_name, &$config_source, &$config_timestamp, \Smarty\Smarty $smarty)
{ {
if ($resource_name !== 'foo.conf') { if ($resource_name !== 'foo.conf') {
return 'no.conf'; return 'no.conf';
@@ -160,7 +162,7 @@ function configHandlerFile($resource_type, $resource_name, &$config_source, &$co
* *
* @return bool * @return bool
*/ */
function configHandlerFalse($resource_type, $resource_name, &$config_source, &$config_timestamp, Smarty $smarty) function configHandlerFalse($resource_type, $resource_name, &$config_source, &$config_timestamp, \Smarty\Smarty $smarty)
{ {
return false; return false;
} }

View File

@@ -387,7 +387,7 @@ class ConfigVarTest extends PHPUnit_Smarty
public function testConfigResourceDb4() public function testConfigResourceDb4()
{ {
$this->smarty->addPluginsDir(__DIR__ . "/PHPunitplugins/"); $this->smarty->addPluginsDir(__DIR__ . "/../../ResourceTests/ResourcePlugins/PHPunitplugins/");
$this->smarty->configLoad('db4:foo.conf'); $this->smarty->configLoad('db4:foo.conf');
$this->assertEquals("bar", $this->smarty->fetch('foo.tpl')); $this->assertEquals("bar", $this->smarty->fetch('foo.tpl'));
} }

View File

@@ -1,30 +0,0 @@
<?php
/*
* Smarty plugin
* -------------------------------------------------------------
* File: resource.db3.php
* Type: resource
* Name: db
* Purpose: Fetches templates from a database
* -------------------------------------------------------------
*/
use Smarty\Template;
use Smarty\Template\Source;
class Smarty_Resource_Db4 extends Smarty\Resource\BasePlugin
{
public function populate(Source $source, Template $_template = null)
{
$source->filepath = 'db4:';
$source->uid = sha1($source->resource);
$source->timestamp = 0;
$source->exists = true;
}
public function getContent(Source $source)
{
return "foo = 'bar'\n";
}
}

View File

@@ -6,6 +6,8 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
require_once __DIR__ . '/../../../__shared/resources/resource.extendsall.php';
/** /**
* class for demo resource plugin extendsall tests * class for demo resource plugin extendsall tests
* *
@@ -33,7 +35,7 @@ class ResourceExtendsAllPluginTest extends PHPUnit_Smarty
*/ */
public function testResourcePluginExtendsall() public function testResourcePluginExtendsall()
{ {
$this->smarty->addPluginsDir(SMARTY_DIR . "../demo/plugins/"); $this->smarty->registerResource('extendsall', new My_Resource_Extendsall());
$this->smarty->setTemplateDir(array('root' => './templates', './templates_2', './templates_3', $this->smarty->setTemplateDir(array('root' => './templates', './templates_2', './templates_3',
'./templates_4',)); './templates_4',));
@@ -51,8 +53,8 @@ class ResourceExtendsAllPluginTest extends PHPUnit_Smarty
public function testResourcePluginExtendsall2() public function testResourcePluginExtendsall2()
{ {
$this->smarty->setMergeCompiledIncludes(true); $this->smarty->registerResource('extendsall', new My_Resource_Extendsall());
$this->smarty->addPluginsDir(SMARTY_DIR . "../demo/plugins/"); $this->smarty->setMergeCompiledIncludes(true);
$this->smarty->setTemplateDir(array('./templates_3', './templates_4',)); $this->smarty->setTemplateDir(array('./templates_3', './templates_4',));
$expected = "templates_3templates_3templates_3templates_4"; $expected = "templates_3templates_3templates_3templates_4";
@@ -61,7 +63,7 @@ class ResourceExtendsAllPluginTest extends PHPUnit_Smarty
public function testResourcePluginExtendsallOne() public function testResourcePluginExtendsallOne()
{ {
$this->smarty->addPluginsDir(SMARTY_DIR . "../demo/plugins/"); $this->smarty->registerResource('extendsall', new My_Resource_Extendsall());
$this->smarty->setTemplateDir(array('root' => './templates', './templates_2', './templates_3', $this->smarty->setTemplateDir(array('root' => './templates', './templates_2', './templates_3',
'./templates_4',)); './templates_4',));
@@ -77,7 +79,7 @@ class ResourceExtendsAllPluginTest extends PHPUnit_Smarty
*/ */
public function testResourcePluginExtendsallSpecialApplication() public function testResourcePluginExtendsallSpecialApplication()
{ {
$this->smarty->addPluginsDir(SMARTY_DIR . "../demo/plugins/"); $this->smarty->registerResource('extendsall', new My_Resource_Extendsall());
$this->smarty->setTemplateDir(array('./templates_2', './templates_1',)); $this->smarty->setTemplateDir(array('./templates_2', './templates_1',));
$this->smarty->setDefaultResourceType('extendsall'); $this->smarty->setDefaultResourceType('extendsall');
$this->assertEquals('<p>data1 from templates1</p><p>data1 from templates2</p><p>data2 from templates1</p>', $this->assertEquals('<p>data1 from templates1</p><p>data1 from templates2</p><p>data2 from templates1</p>',
@@ -92,7 +94,7 @@ class ResourceExtendsAllPluginTest extends PHPUnit_Smarty
*/ */
public function testResourcePluginExtendsallSpecialApplication2() public function testResourcePluginExtendsallSpecialApplication2()
{ {
$this->smarty->addPluginsDir(SMARTY_DIR . "../demo/plugins/"); $this->smarty->registerResource('extendsall', new My_Resource_Extendsall());
$this->smarty->setTemplateDir(array('./templates_3', './templates_2', './templates_1',)); $this->smarty->setTemplateDir(array('./templates_3', './templates_2', './templates_1',));
$this->smarty->setDefaultResourceType('extendsall'); $this->smarty->setDefaultResourceType('extendsall');
$this->assertEquals('<p>data1 from templates1</p><p>data1 from templates3</p><p>data1 from templates2</p><p>data2 from templates1</p>', $this->assertEquals('<p>data1 from templates1</p><p>data1 from templates3</p><p>data1 from templates2</p><p>data2 from templates1</p>',
@@ -108,7 +110,7 @@ class ResourceExtendsAllPluginTest extends PHPUnit_Smarty
public function testResourcePluginExtendsallSpecialApplication3() public function testResourcePluginExtendsallSpecialApplication3()
{ {
$this->smarty->setMergeCompiledIncludes(true); $this->smarty->setMergeCompiledIncludes(true);
$this->smarty->addPluginsDir(SMARTY_DIR . "../demo/plugins/"); $this->smarty->registerResource('extendsall', new My_Resource_Extendsall());
$this->smarty->setTemplateDir(array('./templates_2', './templates_1',)); $this->smarty->setTemplateDir(array('./templates_2', './templates_1',));
$this->smarty->setDefaultResourceType('extendsall'); $this->smarty->setDefaultResourceType('extendsall');
$this->assertEquals('<p>data1 from templates1</p><p>data1 from templates2</p><p>data2 from templates1</p>', $this->assertEquals('<p>data1 from templates1</p><p>data1 from templates2</p><p>data2 from templates1</p>',
@@ -124,7 +126,7 @@ class ResourceExtendsAllPluginTest extends PHPUnit_Smarty
public function testResourcePluginExtendsallSpecialApplication4() public function testResourcePluginExtendsallSpecialApplication4()
{ {
$this->smarty->setMergeCompiledIncludes(true); $this->smarty->setMergeCompiledIncludes(true);
$this->smarty->addPluginsDir(SMARTY_DIR . "../demo/plugins/"); $this->smarty->registerResource('extendsall', new My_Resource_Extendsall());
$this->smarty->setTemplateDir(array('./templates_2', './templates_1',)); $this->smarty->setTemplateDir(array('./templates_2', './templates_1',));
$this->smarty->setDefaultResourceType('extendsall'); $this->smarty->setDefaultResourceType('extendsall');
$this->assertEquals('<p>data1 from templates1</p><p>data1 from templates2</p><p>data2 from templates1</p>', $this->assertEquals('<p>data1 from templates1</p><p>data1 from templates2</p><p>data2 from templates1</p>',
@@ -140,7 +142,7 @@ class ResourceExtendsAllPluginTest extends PHPUnit_Smarty
public function testResourcePluginExtendsallSpecialApplication5() public function testResourcePluginExtendsallSpecialApplication5()
{ {
$this->smarty->setMergeCompiledIncludes(true); $this->smarty->setMergeCompiledIncludes(true);
$this->smarty->addPluginsDir(SMARTY_DIR . "../demo/plugins/"); $this->smarty->registerResource('extendsall', new My_Resource_Extendsall());
$this->smarty->setTemplateDir(array('./templates_3', './templates_2', './templates_1',)); $this->smarty->setTemplateDir(array('./templates_3', './templates_2', './templates_1',));
$this->smarty->setDefaultResourceType('extendsall'); $this->smarty->setDefaultResourceType('extendsall');
$this->assertEquals('<p>data1 from templates1</p><p>data1 from templates3</p><p>data1 from templates2</p><p>data2 from templates1</p>', $this->assertEquals('<p>data1 from templates1</p><p>data1 from templates3</p><p>data1 from templates2</p><p>data2 from templates1</p>',
@@ -156,7 +158,7 @@ class ResourceExtendsAllPluginTest extends PHPUnit_Smarty
public function testResourcePluginExtendsallSpecialApplication6() public function testResourcePluginExtendsallSpecialApplication6()
{ {
$this->smarty->setMergeCompiledIncludes(true); $this->smarty->setMergeCompiledIncludes(true);
$this->smarty->addPluginsDir(SMARTY_DIR . "../demo/plugins/"); $this->smarty->registerResource('extendsall', new My_Resource_Extendsall());
$this->smarty->setTemplateDir(array('./templates_3', './templates_2', './templates_1',)); $this->smarty->setTemplateDir(array('./templates_3', './templates_2', './templates_1',));
$this->smarty->setDefaultResourceType('extendsall'); $this->smarty->setDefaultResourceType('extendsall');
$this->assertEquals('<p>data1 from templates1</p><p>data1 from templates3</p><p>data1 from templates2</p><p>data2 from templates1</p>', $this->assertEquals('<p>data1 from templates1</p><p>data1 from templates3</p><p>data1 from templates2</p><p>data2 from templates1</p>',

View File

@@ -1,21 +0,0 @@
<?php
use Smarty\Exception;
require_once SMARTY_DIR . '../demo/plugins/resource.mysqls.php';
class Smarty_Resource_Mysqlstest extends _MysqlsPlugin
{
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, source FROM templates WHERE name = :name');
}
}

View File

@@ -1,22 +0,0 @@
<?php
use Smarty\Exception;
require_once SMARTY_DIR . '../demo/plugins/resource.mysql.php';
class Smarty_Resource_Mysqltest extends _MysqlPlugin
{
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, source FROM templates WHERE name = :name');
$this->mtime = $this->db->prepare('SELECT modified FROM templates WHERE name = :name');
}
}

View File

@@ -93,7 +93,7 @@ class DefaultTemplateHandlerTest extends PHPUnit_Smarty
} }
} }
function my_template_handler($resource_type, $resource_name, &$template_source, &$template_timestamp, Smarty $smarty) function my_template_handler($resource_type, $resource_name, &$template_source, &$template_timestamp, \Smarty\Smarty $smarty)
{ {
$output = "Recsource $resource_name of type $resource_type not found"; $output = "Recsource $resource_name of type $resource_type not found";
$template_source = $output; $template_source = $output;
@@ -102,12 +102,12 @@ function my_template_handler($resource_type, $resource_name, &$template_source,
return true; return true;
} }
function my_template_handler_file($resource_type, $resource_name, &$template_source, &$template_timestamp, Smarty $smarty) function my_template_handler_file($resource_type, $resource_name, &$template_source, &$template_timestamp, \Smarty\Smarty $smarty)
{ {
return $smarty->getTemplateDir(0) . 'helloworld.tpl'; return $smarty->getTemplateDir(0) . 'helloworld.tpl';
} }
function my_false($resource_type, $resource_name, &$template_source, &$template_timestamp, Smarty $smarty) function my_false($resource_type, $resource_name, &$template_source, &$template_timestamp, \Smarty\Smarty $smarty)
{ {
return false; return false;
} }

View File

@@ -1,301 +0,0 @@
<?php
/**
* Smarty PHPunit tests for PHP resources
*
* @package PHPunit
* @author Uwe Tews
*/
/**
* class for PHP resource tests
*
* @runTestsInSeparateProcess
* @preserveGlobalState disabled
* @backupStaticAttributes enabled
*/
class PhpResourceTest extends PHPUnit_Smarty
{
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
}
public function testInit()
{
$this->cleanDirs();
}
protected function relative($path)
{
$path = str_replace(str_replace("\\", "/", __DIR__), '.', str_replace("\\", "/", $path));
return $path;
}
/**
* test getTemplateFilepath
*/
public function testGetTemplateFilepath()
{
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertEquals($this->normalizePath("./templates/phphelloworld.php"), $tpl->source->filepath);
}
/**
* test getTemplateTimestamp
*/
public function testGetTemplateTimestamp()
{
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertTrue(is_integer($tpl->source->getTimeStamp()));
$this->assertEquals(10, strlen($tpl->source->getTimeStamp()));
}
/**
* test getTemplateSource
*-/
* public function testGetTemplateSource()
* {
* $tpl = $this->smarty->createTemplate('php:phphelloworld.php');
* $this->assertStringContainsString('php hello world', $tpl->source->getContent());
* }
* /**
* test usesCompiler
*/
public function testUsesCompiler()
{
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertTrue($tpl->source->handler->uncompiled);
}
/**
* test isEvaluated
*/
public function testIsEvaluated()
{
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertFalse($tpl->source->handler->recompiled);
}
/**
* test mustCompile
*/
public function testMustCompile()
{
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertFalse($tpl->mustCompile());
}
/**
* test getCachedFilepath
*/
public function testGetCachedFilepath()
{
$this->smarty->setAllowPhpTemplates(true);
$this->smarty->caching = true;
$this->smarty->cache_lifetime = 1000;
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$expected = $this->buildCachedPath($tpl, false, null, null, 'phphelloworld.php', 'php',
$this->smarty->getTemplateDir(0), 'file');
$this->assertEquals($expected, $tpl->cached->filepath);
}
/**
* test create cache file used by the following tests
*/
public function testCreateCacheFile()
{
// create dummy cache file
$this->smarty->setAllowPhpTemplates(true);
$this->smarty->caching = true;
$this->smarty->cache_lifetime = 1000;
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertStringContainsString('php hello world', $this->smarty->fetch($tpl));
}
/**
* test getCachedTimestamp caching enabled
*
* @runInSeparateProcess
* @preserveGlobalState disabled
*
*/
public function testGetCachedTimestamp()
{
$this->smarty->setAllowPhpTemplates(true);
$this->smarty->caching = true;
$this->smarty->cache_lifetime = 1000;
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertTrue(is_integer($tpl->cached->timestamp));
$this->assertEquals(10, strlen($tpl->cached->timestamp));
}
/**
* test isCached
*
* @runInSeparateProcess
* @preserveGlobalState disabled
*
*/
public function testIsCached()
{
$this->smarty->setAllowPhpTemplates(true);
$this->smarty->caching = true;
$this->smarty->cache_lifetime = 10000;
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertTrue($tpl->isCached());
}
/**
* test isCached caching disabled
*/
public function testIsCachedCachingDisabled()
{
$this->smarty->setAllowPhpTemplates(true);
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertFalse($tpl->isCached());
}
/**
* test isCached on touched source
*
* @runInSeparateProcess
* @preserveGlobalState disabled
* @doesNotPerformAssertions
*/
public function testIsCachedTouchedSourcePrepare()
{
$this->smarty->setAllowPhpTemplates(true);
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
sleep(2);
touch($tpl->source->filepath);
}
/**
*
* @runInSeparateProcess
* @preserveGlobalState disabled
*
*/
public function testIsCachedTouchedSource()
{
$this->smarty->setAllowPhpTemplates(true);
$this->smarty->caching = true;
$this->smarty->cache_lifetime = 1000;
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertFalse($tpl->isCached());
}
/**
* test is cache file is written
*/
public function testWriteCachedContent()
{
$this->smarty->setAllowPhpTemplates(true);
$this->smarty->caching = true;
$this->smarty->cache_lifetime = 1000;
$this->cleanCacheDir();
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->smarty->fetch($tpl);
$this->assertTrue(file_exists($tpl->cached->filepath));
}
/**
* test getRenderedTemplate
*/
public function testGetRenderedTemplate()
{
$this->smarty->setAllowPhpTemplates(true);
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertStringContainsString('php hello world', $tpl->fetch());
}
/**
* test $smarty->is_cached
* @doesNotPerformAssertions
*/
public function testSmartyIsCachedPrepare()
{
// clean up for next tests
$this->cleanCacheDir();
$this->smarty->setAllowPhpTemplates(true);
// prepare files for next test
$this->smarty->caching = true;
$this->smarty->cache_lifetime = 1000;
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->smarty->fetch($tpl);
}
/**
*
* @runInSeparateProcess
* @preserveGlobalState disabled
*
*/
public function testSmartyIsCached()
{
$this->smarty->setAllowPhpTemplates(true);
$this->smarty->caching = true;
$this->smarty->cache_lifetime = 1000;
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertTrue($this->smarty->isCached($tpl));
}
/**
* test $smarty->is_cached caching disabled
*/
public function testSmartyIsCachedCachingDisabled()
{
$this->smarty->setAllowPhpTemplates(true);
$tpl = $this->smarty->createTemplate('php:phphelloworld.php');
$this->assertFalse($this->smarty->isCached($tpl));
}
public function testGetTemplateFilepathName()
{
$this->smarty->addTemplateDir('./templates_2', 'foo');
$tpl = $this->smarty->createTemplate('php:[foo]helloworld.php');
$this->assertEquals('./templates_2/helloworld.php', $this->relative($tpl->source->filepath));
}
public function testGetCachedFilepathName()
{
$this->smarty->addTemplateDir('./templates_2', 'foo');
$this->smarty->caching = true;
$this->smarty->cache_lifetime = 1000;
$tpl = $this->smarty->createTemplate('php:[foo]helloworld.php');
$path = $tpl->cached->filepath;
$expected = $this->buildCachedPath($tpl, false, null, null, 'helloworld.php', 'php',
$this->smarty->getTemplateDir('foo'), 'file');
$this->assertEquals($expected, $path);
}
/**
* test {include} php resource
*/
public function testIncludePhpTemplate()
{
$this->smarty->setAllowPhpTemplates(true);
$this->assertStringContainsString('php hello world', $this->smarty->fetch('includephp.tpl'));
}
/**
* test {include} php resource caching
*/
public function testIncludePhpTemplateCaching()
{
$this->smarty->caching = true;
$this->smarty->setAllowPhpTemplates(true);
$this->assertStringContainsString('php hello world', $this->smarty->fetch('includephp.tpl'));
}
/**
* test clearCompiledTemplate()
*/
public function testClearCompiled()
{
$this->smarty->setAllowPhpTemplates(true);
$this->assertEquals(0, $this->smarty->clearCompiledTemplate('php:phphelloworld.php'));
}
}

View File

@@ -1,2 +0,0 @@
# Ignore anything in here, but keep this directory
*

View File

@@ -1 +0,0 @@
{include 'php:phphelloworld.php'}

View File

@@ -1 +0,0 @@
php hello world

View File

@@ -1 +0,0 @@
php hello world

View File

@@ -1,2 +0,0 @@
# Ignore anything in here, but keep this directory
*

View File

@@ -71,9 +71,6 @@ class ClearCompiledTest extends PHPUnit_Smarty
$this->_files[$template . '#' . $compile_id] = substr($tpl->compiled->filepath, $directory_length); $this->_files[$template . '#' . $compile_id] = substr($tpl->compiled->filepath, $directory_length);
} }
} }
// TODO
//Smarty::$_resource_cache = array();
//$this->getSmartyObj()->_cache['template_objects'] = array();
return $this->_files; return $this->_files;
} }

View File

@@ -6,6 +6,8 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
use Smarty\Smarty;
/** /**
* class for register->block / unregister->block methods tests * class for register->block / unregister->block methods tests
* *
@@ -31,21 +33,21 @@ class RegisterBlockTest extends PHPUnit_Smarty
*/ */
public function testRegisterBlockFunction() public function testRegisterBlockFunction()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock', 'myblock'); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', 'myblock');
$this->smarty->assign('value', 1); $this->smarty->assign('value', 1);
$this->assertEquals('function hello world 1 1 function hello world 1 2 function hello world 1 3 ', $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock}')); $this->assertEquals('function hello world 1 1 function hello world 1 2 function hello world 1 3 ', $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock}'));
} }
public function testRegisterBlockFunctionModifier1() public function testRegisterBlockFunctionModifier1()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock', 'myblock'); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', 'myblock');
$this->smarty->assign('value', 1); $this->smarty->assign('value', 1);
$this->assertEquals(strtoupper('function hello world 1 1 function hello world 1 2 function hello world 1 3 '), $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock|upper}')); $this->assertEquals(strtoupper('function hello world 1 1 function hello world 1 2 function hello world 1 3 '), $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock|upper}'));
} }
public function testRegisterBlockFunctionModifier2() public function testRegisterBlockFunctionModifier2()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock', 'myblock'); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', 'myblock');
$this->smarty->assign('value', 1); $this->smarty->assign('value', 1);
$this->assertEquals(strtoupper('function hello world 1 1 function hello world 1 2 function hello world 1 3 '), $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock|default:""|upper}')); $this->assertEquals(strtoupper('function hello world 1 1 function hello world 1 2 function hello world 1 3 '), $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock|default:""|upper}'));
} }
@@ -62,7 +64,7 @@ class RegisterBlockTest extends PHPUnit_Smarty
*/ */
public function testRegisterBlockClass() public function testRegisterBlockClass()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock', array('myblockclass', 'static_method')); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', array('myblockclass', 'static_method'));
$this->smarty->assign('value', 2); $this->smarty->assign('value', 2);
$this->assertEquals('static hello world 2 1 static hello world 2 2 static hello world 2 3 ', $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock}')); $this->assertEquals('static hello world 2 1 static hello world 2 2 static hello world 2 3 ', $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock}'));
} }
@@ -80,7 +82,7 @@ class RegisterBlockTest extends PHPUnit_Smarty
public function testRegisterBlockObject() public function testRegisterBlockObject()
{ {
$myblock_object = new myblockclass; $myblock_object = new myblockclass;
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock', array($myblock_object, 'object_method')); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', array($myblock_object, 'object_method'));
$this->smarty->assign('value', 3); $this->smarty->assign('value', 3);
$this->assertEquals('object hello world 3 1 object hello world 3 2 object hello world 3 3 ', $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock}')); $this->assertEquals('object hello world 3 1 object hello world 3 2 object hello world 3 3 ', $this->smarty->fetch('eval:{testblock}hello world {$value}{/testblock}'));
} }
@@ -104,7 +106,7 @@ class RegisterBlockTest extends PHPUnit_Smarty
$this->smarty->assign('x', 1); $this->smarty->assign('x', 1);
$this->smarty->assign('y', 10); $this->smarty->assign('y', 10);
$this->smarty->assign('z', 100); $this->smarty->assign('z', 100);
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock', 'myblockcache'); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', 'myblockcache');
$this->assertEquals('1 10 100', $this->smarty->fetch('test_register_block.tpl')); $this->assertEquals('1 10 100', $this->smarty->fetch('test_register_block.tpl'));
} }
@@ -120,7 +122,7 @@ class RegisterBlockTest extends PHPUnit_Smarty
$this->smarty->assign('x', 2); $this->smarty->assign('x', 2);
$this->smarty->assign('y', 20); $this->smarty->assign('y', 20);
$this->smarty->assign('z', 200); $this->smarty->assign('z', 200);
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock', 'myblockcache'); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', 'myblockcache');
$this->assertEquals('1 10 100', $this->smarty->fetch('test_register_block.tpl')); $this->assertEquals('1 10 100', $this->smarty->fetch('test_register_block.tpl'));
} }
@@ -137,7 +139,7 @@ class RegisterBlockTest extends PHPUnit_Smarty
$this->smarty->assign('x', 3); $this->smarty->assign('x', 3);
$this->smarty->assign('y', 30); $this->smarty->assign('y', 30);
$this->smarty->assign('z', 300); $this->smarty->assign('z', 300);
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock', 'myblockcache', false); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', 'myblockcache', false);
$this->assertEquals('3 30 300', $this->smarty->fetch('test_register_block.tpl')); $this->assertEquals('3 30 300', $this->smarty->fetch('test_register_block.tpl'));
} }
@@ -153,7 +155,7 @@ class RegisterBlockTest extends PHPUnit_Smarty
$this->smarty->assign('x', 4); $this->smarty->assign('x', 4);
$this->smarty->assign('y', 40); $this->smarty->assign('y', 40);
$this->smarty->assign('z', 400); $this->smarty->assign('z', 400);
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock', 'myblockcache', false); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', 'myblockcache', false);
$this->assertEquals('3 40 300', $this->smarty->fetch('test_register_block.tpl')); $this->assertEquals('3 40 300', $this->smarty->fetch('test_register_block.tpl'));
} }
@@ -228,16 +230,16 @@ class RegisterBlockTest extends PHPUnit_Smarty
*/ */
public function testUnregisterBlock() public function testUnregisterBlock()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock', 'myblock'); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testblock', 'myblock');
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock'); $this->smarty->unregisterPlugin(Smarty::PLUGIN_BLOCK, 'testblock');
$this->assertFalse(isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_BLOCK]['testblock'])); $this->assertNull($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_BLOCK, 'testblock'));
} }
public function testUnregisterBlockWrapper() public function testUnregisterBlockWrapper()
{ {
$this->smarty->registerPlugin('block', 'testblock', 'myblock'); $this->smarty->registerPlugin('block', 'testblock', 'myblock');
$this->smarty->unregisterPlugin('block', 'testblock'); $this->smarty->unregisterPlugin('block', 'testblock');
$this->assertFalse(isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_BLOCK]['testblock'])); $this->assertNull($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_BLOCK, 'testblock'));
} }
/** /**
@@ -245,8 +247,8 @@ class RegisterBlockTest extends PHPUnit_Smarty
*/ */
public function testUnregisterBlockNotRegistered() public function testUnregisterBlockNotRegistered()
{ {
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testblock'); $this->smarty->unregisterPlugin(Smarty::PLUGIN_BLOCK, 'testblock');
$this->assertFalse(isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_BLOCK]['testblock'])); $this->assertNull($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_BLOCK, 'testblock'));
} }
} }

View File

@@ -6,6 +6,8 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
use Smarty\Smarty;
/** /**
* class for register->compilerFunction / unregister->compilerFunction methods tests * class for register->compilerFunction / unregister->compilerFunction methods tests
* *
@@ -30,8 +32,8 @@ class RegisterCompilerFunctionTest extends PHPUnit_Smarty
*/ */
public function testRegisterCompilerFunction() public function testRegisterCompilerFunction()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_COMPILER, 'testcompilerfunction', 'mycompilerfunction'); $this->smarty->registerPlugin(Smarty::PLUGIN_COMPILER, 'testcompilerfunction', 'mycompilerfunction');
$this->assertEquals('mycompilerfunction', $this->smarty->registered_plugins['compiler']['testcompilerfunction'][0]); $this->assertEquals('mycompilerfunction', $this->smarty->getRegisteredPlugin('compiler', 'testcompilerfunction')[0]);
$this->assertEquals('hello world 1', $this->smarty->fetch('eval:{testcompilerfunction var=1}')); $this->assertEquals('hello world 1', $this->smarty->fetch('eval:{testcompilerfunction var=1}'));
} }
@@ -40,8 +42,8 @@ class RegisterCompilerFunctionTest extends PHPUnit_Smarty
*/ */
public function testRegisterCompilerFunctionBlock() public function testRegisterCompilerFunctionBlock()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_COMPILER, 'foo', 'mycompilerfunctionopen'); $this->smarty->registerPlugin(Smarty::PLUGIN_COMPILER, 'foo', 'mycompilerfunctionopen');
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_COMPILER, 'fooclose', 'mycompilerfunctionclose'); $this->smarty->registerPlugin(Smarty::PLUGIN_COMPILER, 'fooclose', 'mycompilerfunctionclose');
$result = $this->smarty->fetch('eval:{foo} hallo {/foo}'); $result = $this->smarty->fetch('eval:{foo} hallo {/foo}');
$this->assertEquals('open tag hallo close tag', $result); $this->assertEquals('open tag hallo close tag', $result);
} }
@@ -51,7 +53,7 @@ class RegisterCompilerFunctionTest extends PHPUnit_Smarty
*/ */
public function testRegisterCompilerFunctionClass() public function testRegisterCompilerFunctionClass()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_COMPILER, 'testcompilerfunction', array('mycompilerfunctionclass', 'execute')); $this->smarty->registerPlugin(Smarty::PLUGIN_COMPILER, 'testcompilerfunction', array('mycompilerfunctionclass', 'execute'));
$this->assertEquals('hello world 2', $this->smarty->fetch('eval:{testcompilerfunction var1=2}')); $this->assertEquals('hello world 2', $this->smarty->fetch('eval:{testcompilerfunction var1=2}'));
} }
@@ -61,7 +63,7 @@ class RegisterCompilerFunctionTest extends PHPUnit_Smarty
public function testRegisterCompilerFunctionObject() public function testRegisterCompilerFunctionObject()
{ {
$obj = new mycompilerfunctionclass; $obj = new mycompilerfunctionclass;
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_COMPILER, 'testcompilerfunction', array($obj, 'compile')); $this->smarty->registerPlugin(Smarty::PLUGIN_COMPILER, 'testcompilerfunction', array($obj, 'compile'));
$this->assertEquals('hello world 3', $this->smarty->fetch('eval:{testcompilerfunction var2=3}')); $this->assertEquals('hello world 3', $this->smarty->fetch('eval:{testcompilerfunction var2=3}'));
} }
@@ -70,9 +72,9 @@ class RegisterCompilerFunctionTest extends PHPUnit_Smarty
*/ */
public function testUnregisterCompilerFunction() public function testUnregisterCompilerFunction()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_COMPILER, 'testcompilerfunction', 'mycompilerfunction'); $this->smarty->registerPlugin(Smarty::PLUGIN_COMPILER, 'testcompilerfunction', 'mycompilerfunction');
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_COMPILER, 'testcompilerfunction'); $this->smarty->unregisterPlugin(Smarty::PLUGIN_COMPILER, 'testcompilerfunction');
$this->assertFalse(isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_COMPILER]['testcompilerfunction'])); $this->assertNull($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_COMPILER, 'testcompilerfunction'));
} }
/** /**
@@ -80,8 +82,8 @@ class RegisterCompilerFunctionTest extends PHPUnit_Smarty
*/ */
public function testUnregisterCompilerFunctionNotRegistered() public function testUnregisterCompilerFunctionNotRegistered()
{ {
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_COMPILER, 'testcompilerfunction'); $this->smarty->unregisterPlugin(Smarty::PLUGIN_COMPILER, 'testcompilerfunction');
$this->assertFalse(isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_COMPILER]['testcompilerfunction'])); $this->assertNull($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_COMPILER, 'testcompilerfunction'));
} }
/** /**
@@ -89,9 +91,9 @@ class RegisterCompilerFunctionTest extends PHPUnit_Smarty
*/ */
public function testUnregisterCompilerFunctionOtherRegistered() public function testUnregisterCompilerFunctionOtherRegistered()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testcompilerfunction', 'mycompilerfunction'); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testcompilerfunction', 'mycompilerfunction');
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_COMPILER, 'testcompilerfunction'); $this->smarty->unregisterPlugin(Smarty::PLUGIN_COMPILER, 'testcompilerfunction');
$this->assertTrue(isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_BLOCK]['testcompilerfunction'])); $this->assertIsArray($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_BLOCK, 'testcompilerfunction'));
} }
} }

View File

@@ -6,6 +6,8 @@
* @author Uwe Tews * @author Uwe Tews
*/ */
use Smarty\Smarty;
/** /**
* class for register/unregister function plugins methods tests * class for register/unregister function plugins methods tests
* *
@@ -31,9 +33,9 @@ class RegisterFunctionTest extends PHPUnit_Smarty
*/ */
public function testRegisterFunction() public function testRegisterFunction()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction'); $this->smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction');
$this->assertEquals('myfunction', $this->assertEquals('myfunction',
$this->smarty->registered_plugins[ \Smarty\Smarty::PLUGIN_FUNCTION ][ 'testfunction' ][ 0 ]); $this->smarty->getRegisteredPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction')[0]);
$this->assertEquals('hello world 1', $this->smarty->fetch('eval:{testfunction value=1}')); $this->assertEquals('hello world 1', $this->smarty->fetch('eval:{testfunction value=1}'));
} }
@@ -42,7 +44,7 @@ class RegisterFunctionTest extends PHPUnit_Smarty
*/ */
public function testRegisterFunctionClass() public function testRegisterFunctionClass()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction', array('myfunctionclass', 'execute')); $this->smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction', array('myfunctionclass', 'execute'));
$this->assertEquals('hello world 2', $this->smarty->fetch('eval:{testfunction value=2}')); $this->assertEquals('hello world 2', $this->smarty->fetch('eval:{testfunction value=2}'));
} }
@@ -52,7 +54,7 @@ class RegisterFunctionTest extends PHPUnit_Smarty
public function testRegisterFunctionObject() public function testRegisterFunctionObject()
{ {
$myfunction_object = new myfunctionclass; $myfunction_object = new myfunctionclass;
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction', array($myfunction_object, 'execute')); $this->smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction', array($myfunction_object, 'execute'));
$this->assertEquals('hello world 3', $this->smarty->fetch('eval:{testfunction value=3}')); $this->assertEquals('hello world 3', $this->smarty->fetch('eval:{testfunction value=3}'));
} }
@@ -69,7 +71,7 @@ class RegisterFunctionTest extends PHPUnit_Smarty
$this->smarty->setForceCompile(true); $this->smarty->setForceCompile(true);
$this->smarty->assign('x', 0); $this->smarty->assign('x', 0);
$this->smarty->assign('y', 10); $this->smarty->assign('y', 10);
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction'); $this->smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction');
$this->assertEquals('hello world 0 10', $this->smarty->fetch('test_register_function.tpl')); $this->assertEquals('hello world 0 10', $this->smarty->fetch('test_register_function.tpl'));
} }
@@ -86,7 +88,7 @@ class RegisterFunctionTest extends PHPUnit_Smarty
$this->smarty->cache_lifetime = 1000; $this->smarty->cache_lifetime = 1000;
$this->smarty->assign('x', 1); $this->smarty->assign('x', 1);
$this->smarty->assign('y', 20); $this->smarty->assign('y', 20);
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction'); $this->smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction');
$this->assertEquals('hello world 0 10', $this->smarty->fetch('test_register_function.tpl')); $this->assertEquals('hello world 0 10', $this->smarty->fetch('test_register_function.tpl'));
} }
@@ -104,7 +106,7 @@ class RegisterFunctionTest extends PHPUnit_Smarty
$this->smarty->setForceCompile(true); $this->smarty->setForceCompile(true);
$this->smarty->assign('x', 2); $this->smarty->assign('x', 2);
$this->smarty->assign('y', 30); $this->smarty->assign('y', 30);
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction', false); $this->smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction', false);
$this->assertEquals('hello world 2 30', $this->smarty->fetch('test_register_function.tpl')); $this->assertEquals('hello world 2 30', $this->smarty->fetch('test_register_function.tpl'));
} }
@@ -121,7 +123,7 @@ class RegisterFunctionTest extends PHPUnit_Smarty
$this->smarty->cache_lifetime = 1000; $this->smarty->cache_lifetime = 1000;
$this->smarty->assign('x', 3); $this->smarty->assign('x', 3);
$this->smarty->assign('y', 40); $this->smarty->assign('y', 40);
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction', false); $this->smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction', false);
$this->assertEquals('hello world 3 30', $this->smarty->fetch('test_register_function.tpl')); $this->assertEquals('hello world 3 30', $this->smarty->fetch('test_register_function.tpl'));
} }
@@ -130,28 +132,28 @@ class RegisterFunctionTest extends PHPUnit_Smarty
*/ */
public function testUnregisterFunction() public function testUnregisterFunction()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction'); $this->smarty->registerPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction', 'myfunction');
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction'); $this->smarty->unregisterPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction');
$this->assertFalse(isset($this->smarty->registered_plugins[ \Smarty\Smarty::PLUGIN_FUNCTION ][ 'testfunction' ])); $this->assertNull($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction'));
} }
/** /**
* test test unregisterPlugin method for function not registered * test unregisterPlugin method for function not registered
*/ */
public function testUnregisterFunctionNotRegistered() public function testUnregisterFunctionNotRegistered()
{ {
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction'); $this->smarty->unregisterPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction');
$this->assertFalse(isset($this->smarty->registered_plugins[ \Smarty\Smarty::PLUGIN_FUNCTION ][ 'testfunction' ])); $this->assertNull($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction'));
} }
/** /**
* test test unregisterPlugin method for function other registered * test unregisterPlugin method for function other registered
*/ */
public function testUnregisterFunctionOtherRegistered() public function testUnregisterFunctionOtherRegistered()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testfunction', 'myfunction'); $this->smarty->registerPlugin(Smarty::PLUGIN_BLOCK, 'testfunction', 'myfunction');
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_FUNCTION, 'testfunction'); $this->smarty->unregisterPlugin(Smarty::PLUGIN_FUNCTION, 'testfunction');
$this->assertTrue(isset($this->smarty->registered_plugins[ \Smarty\Smarty::PLUGIN_BLOCK ][ 'testfunction' ])); $this->assertIsArray($this->smarty->getRegisteredPlugin(Smarty::PLUGIN_BLOCK, 'testfunction'));
} }
} }

View File

@@ -31,7 +31,7 @@ class RegisterModifierTest extends PHPUnit_Smarty
public function testRegisterModifier() public function testRegisterModifier()
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier', 'mymodifier'); $this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier', 'mymodifier');
$this->assertEquals('mymodifier', $this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_MODIFIER]['testmodifier'][0]); $this->assertEquals('mymodifier', $this->smarty->getRegisteredPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier')[0]);
$this->smarty->assign('foo', 'foo'); $this->smarty->assign('foo', 'foo');
$this->smarty->assign('bar', 'bar'); $this->smarty->assign('bar', 'bar');
$this->assertEquals('foo function blar bar', $this->smarty->fetch('eval:{$foo|testmodifier:blar:$bar}')); $this->assertEquals('foo function blar bar', $this->smarty->fetch('eval:{$foo|testmodifier:blar:$bar}'));
@@ -67,7 +67,7 @@ class RegisterModifierTest extends PHPUnit_Smarty
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier', 'mymodifier'); $this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier', 'mymodifier');
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier'); $this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier');
$this->assertFalse(isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_MODIFIER]['testmodifier'])); $this->assertNull($this->smarty->getRegisteredPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier'));
} }
/** /**
@@ -76,7 +76,7 @@ class RegisterModifierTest extends PHPUnit_Smarty
public function testUnregisterModifierNotRegistered() public function testUnregisterModifierNotRegistered()
{ {
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier'); $this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier');
$this->assertFalse(isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_MODIFIER]['testmodifier'])); $this->assertNull($this->smarty->getRegisteredPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier'));
} }
/** /**
@@ -86,7 +86,7 @@ class RegisterModifierTest extends PHPUnit_Smarty
{ {
$this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testmodifier', 'mymodifier'); $this->smarty->registerPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testmodifier', 'mymodifier');
$this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier'); $this->smarty->unregisterPlugin(\Smarty\Smarty::PLUGIN_MODIFIER, 'testmodifier');
$this->assertTrue(isset($this->smarty->registered_plugins[\Smarty\Smarty::PLUGIN_BLOCK]['testmodifier'])); $this->assertIsArray($this->smarty->getRegisteredPlugin(\Smarty\Smarty::PLUGIN_BLOCK, 'testmodifier'));
} }
} }

View File

@@ -36,7 +36,7 @@ class CommentsTest extends PHPUnit_Smarty
$name = empty($testName) ? $testNumber : $testName; $name = empty($testName) ? $testNumber : $testName;
$file = "testComments_{$name}.tpl"; $file = "testComments_{$name}.tpl";
$this->makeTemplateFile($file, $code); $this->makeTemplateFile($file, $code);
$this->smarty->template_dir = './templates_tmp'; $this->smarty->setTemplateDir('./templates_tmp');
$this->assertEquals($result, $this->assertEquals($result,
$this->smarty->fetch($file), $this->smarty->fetch($file),
$file); $file);

View File

@@ -37,7 +37,7 @@ class SpacingTest extends PHPUnit_Smarty
$name = empty($testName) ? $testNumber : $testName; $name = empty($testName) ? $testNumber : $testName;
$file = "Spacing_{$name}.tpl"; $file = "Spacing_{$name}.tpl";
$this->makeTemplateFile($file, $code); $this->makeTemplateFile($file, $code);
$this->smarty->template_dir = './templates_tmp'; $this->smarty->setTemplateDir('./templates_tmp');
$this->smarty->assign('file', $file); $this->smarty->assign('file', $file);
$this->smarty->assign('foo', 'bar'); $this->smarty->assign('foo', 'bar');
$this->assertEquals($result, $this->assertEquals($result,

View File

@@ -248,19 +248,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
$this->assertEquals('defaultblock hello world', $this->smarty->fetch('default2.tpl')); $this->assertEquals('defaultblock hello world', $this->smarty->fetch('default2.tpl'));
} }
/**
* test tag stack
*
* @runInSeparateProcess
* @preserveGlobalState disabled
*
*/
public function testBlockPluginTagStack()
{
$this->assertEquals('noop-teststack', $this->smarty->fetch('tag_stack.tpl'));
$this->assertEmpty($this->smarty->_cache[ '_tag_stack' ]);
}
/** /**
* Test caching * Test caching
* *

View File

@@ -1,25 +0,0 @@
<?php
/**
* Smarty plugin for testing block plugins
*
* @package Smarty
* @subpackage PHPunitPlugin
*/
/**
* Smarty {teststack}{/teststack} block plugin
*
* @param array $params parameter array
* @param string $content contents of the block
* @param object $template template object
* @param bool $repeat flag
*
* @return string content re-formatted
*/
function smarty_block_teststack($params, $content, $template, &$repeat)
{
if (isset($content)) {
$stack = $template->smarty->_cache['_tag_stack'];
return $stack[0][0] . '-' . $stack[1][0];
}
}

View File

@@ -5,8 +5,8 @@ use Smarty\Compile\Tag\Base;
class smarty_compiler_test extends Base class smarty_compiler_test extends Base
{ {
public function compile($args, $compiler)
{ public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) {
$this->required_attributes = array('data'); $this->required_attributes = array('data');
$_attr = $this->getAttributes($compiler, $args); $_attr = $this->getAttributes($compiler, $args);
@@ -16,15 +16,3 @@ class smarty_compiler_test extends Base
return "<?php echo 'test output'; ?>"; return "<?php echo 'test output'; ?>";
} }
} }
// compiler.testclose.php
class smarty_compiler_testclose extends Base
{
public function compile($args, $compiler)
{
$this->closeTag($compiler, 'test');
return '';
}
}

View File

@@ -5,11 +5,11 @@ use Smarty\Compile\Tag\Base;
class smarty_compiler_testclose extends Base class smarty_compiler_testclose extends Base
{ {
public function execute($args, $compiler)
{
$this->closeTag($compiler, 'test'); public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) {
return ''; $this->closeTag($compiler, 'test');
}
} return '';
}
}

View File

@@ -30,13 +30,13 @@ class MbSplitEncodingIssue549Test extends PHPUnit_Smarty
public function setUp(): void public function setUp(): void
{ {
$this->charset = \Smarty::$_CHARSET; $this->charset = \Smarty\Smarty::$_CHARSET;
$this->setUpSmarty(__DIR__); $this->setUpSmarty(__DIR__);
} }
protected function tearDown(): void protected function tearDown(): void
{ {
\Smarty::$_CHARSET = $this->charset ?: \Smarty::$_CHARSET; \Smarty\Smarty::$_CHARSET = $this->charset ?: \Smarty\Smarty::$_CHARSET;
$this->cleanDirs(); $this->cleanDirs();
} }
@@ -65,7 +65,7 @@ class MbSplitEncodingIssue549Test extends PHPUnit_Smarty
\extract($data, \EXTR_SKIP); \extract($data, \EXTR_SKIP);
\mb_regex_encoding($mb_regex_encoding); \mb_regex_encoding($mb_regex_encoding);
\Smarty::$_CHARSET = $mb_int_encoding; \Smarty\Smarty::$_CHARSET = $mb_int_encoding;
$this->assertEquals($result, $this->smarty->fetch("string:{\"$subject\"|replace:\"$pattern\":\"$replacement\"}")); $this->assertEquals($result, $this->smarty->fetch("string:{\"$subject\"|replace:\"$pattern\":\"$replacement\"}"));
} }

View File

@@ -37,7 +37,7 @@ class NewlineSpacing extends PHPUnit_Smarty
$name = empty($testName) ? $testNumber : $testName; $name = empty($testName) ? $testNumber : $testName;
$file = "Spacing_{$name}.tpl"; $file = "Spacing_{$name}.tpl";
$this->makeTemplateFile($file, $code); $this->makeTemplateFile($file, $code);
$this->smarty->template_dir = './templates_tmp'; $this->smarty->setTemplateDir('./templates_tmp');
$this->smarty->assign('file', $file); $this->smarty->assign('file', $file);
$this->smarty->assign('foo', 'bar'); $this->smarty->assign('foo', 'bar');
$this->assertEquals($result, $this->assertEquals($result,

View File

@@ -41,7 +41,7 @@ class smarty_compiler_getparamsshort extends Base
*/ */
public $shorttag_order = array('s1', 's2', 's3'); 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); $_attr = $this->getAttributes($compiler, $args);
$output = '<?php echo "array('; $output = '<?php echo "array(';

Some files were not shown because too many files have changed in this diff Show More