mirror of
https://github.com/smarty-php/smarty.git
synced 2026-08-06 21:44:17 +02:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 287e12c3be | |||
| 2a87c65994 | |||
| cdee97d3f1 | |||
| 06d6a5efd9 | |||
| 0be92bc8a6 | |||
| 61db287b8f | |||
| 3293a873bd | |||
| 8d53d3cbf2 | |||
| 47c4864dd1 | |||
| f411247aa1 | |||
| 9a8702d937 | |||
| 5ee4363000 | |||
| 768acd96fa | |||
| baa83541d9 | |||
| 6f054ecc2f | |||
| 4fec27ccc2 | |||
| fea0d02d99 |
@@ -6,6 +6,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [5.2.0] - 2024-05-28
|
||||
- Fixed a code injection vulnerability in extends-tag. This addresses CVE-2024-35226.
|
||||
- Added `$smarty->setCacheModifiedCheck()` setter for cache_modified_check
|
||||
- Added a PSR-4 loading script to allow Smarty to be used without Composer [#1017](https://github.com/smarty-php/smarty/pull/1017)
|
||||
|
||||
|
||||
## [5.1.0] - 2024-04-22
|
||||
- Prevent deprecation notices during compilation in PHP8.3 [#996](https://github.com/smarty-php/smarty/issues/996)
|
||||
- Fix that getTemplateVars would return an array of objects instead of the assigned variables values [#994](https://github.com/smarty-php/smarty/issues/994)
|
||||
- Fix Smarty::assign() not returning $this when called with an array as first parameter [#972](https://github.com/smarty-php/smarty/pull/972)
|
||||
- Documented support for `{if $element is in $array}` syntax [#937](https://github.com/smarty-php/smarty/issues/937)
|
||||
- Added support for `{if $element is not in $array}` syntax [#937](https://github.com/smarty-php/smarty/issues/937)
|
||||
- Using stream variables in templates now throws a deprecation notice [#933](https://github.com/smarty-php/smarty/pull/933)
|
||||
- Internal compiler classes always return a string (the internal has_code flag has been removed for simplicity) [#918](https://github.com/smarty-php/smarty/pull/918)
|
||||
- Fix invalid classnames in Runtime code for foreach [#1000](https://github.com/smarty-php/smarty/issues/1000)
|
||||
|
||||
|
||||
## [5.0.1] - 2024-03-27
|
||||
- Fix error in Smarty\Smarty::compileAllTemplates() by including missing FilesystemIterator class [#966](https://github.com/smarty-php/smarty/issues/966)
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
- Added `$smarty->prependTemplateDir()` method [#1022](https://github.com/smarty-php/smarty/issues/1022)
|
||||
@@ -1 +0,0 @@
|
||||
- Internal compiler classes always return a string (the internal has_code flag has been removed for simplicity) [#918](https://github.com/smarty-php/smarty/pull/918)
|
||||
@@ -1 +0,0 @@
|
||||
- Using stream variables in templates now throws a deprecation notice [#933](https://github.com/smarty-php/smarty/pull/933)
|
||||
@@ -1,2 +0,0 @@
|
||||
- Documented support for `{if $element is in $array}` syntax [#937](https://github.com/smarty-php/smarty/issues/937)
|
||||
- Added support for `{if $element is not in $array}` syntax [#937](https://github.com/smarty-php/smarty/issues/937)
|
||||
@@ -0,0 +1 @@
|
||||
- Fixed missing Smarty getErrorUnassigned/setErrorUnassigned methods [#979](https://github.com/smarty-php/smarty/issues/979)
|
||||
+13
-10
@@ -12,24 +12,27 @@ Use `getTemplateDir()` to retrieve the configured paths.
|
||||
<?php
|
||||
|
||||
// set a single directory where the config files are stored
|
||||
$smarty->setTemplateDir('./config');
|
||||
$smarty->setTemplateDir('./templates');
|
||||
|
||||
// set multiple directories where config files are stored
|
||||
$smarty->setTemplateDir(['./config', './config_2', './config_3']);
|
||||
// set multiple directories where templates are stored
|
||||
$smarty->setTemplateDir(['./templates', './templates_2', './templates_3']);
|
||||
|
||||
// add directory where config files are stored to the current list of dirs
|
||||
$smarty->addTemplateDir('./config_1');
|
||||
// add directory where templates files are stored to the current list of dirs
|
||||
$smarty->addTemplateDir('./templates_1');
|
||||
|
||||
// add multiple directories to the current list of dirs
|
||||
$smarty->addTemplateDir([
|
||||
'./config_2',
|
||||
'./config_3',
|
||||
'./templates_2',
|
||||
'./templates_3',
|
||||
]);
|
||||
|
||||
// chaining of method calls
|
||||
$smarty->setTemplateDir('./config')
|
||||
->addTemplateDir('./config_1')
|
||||
->addTemplateDir('./config_2');
|
||||
$smarty->setTemplateDir('./templates')
|
||||
->addTemplateDir('./templates_1')
|
||||
->addTemplateDir('./templates_2');
|
||||
|
||||
// insert a template dir before exising template dirs
|
||||
$smarty->prependTemplateDir('./more_important_templates')
|
||||
|
||||
// get all directories where config files are stored
|
||||
$template_dirs = $smarty->getTemplateDir();
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|----------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| file | Yes | The name of the config file to include |
|
||||
| section | No | The name of the section to load |
|
||||
| scope | no | How the scope of the loaded variables are treated, which must be one of local, parent or global. local means variables are loaded into the local template context. parent means variables are loaded into both the local context and the parent template that called it. global means variables are available to all templates. |
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
@@ -25,9 +25,17 @@ Here's how you create an instance of Smarty in your PHP scripts:
|
||||
```php
|
||||
<?php
|
||||
|
||||
// Instantiated via composer
|
||||
require 'vendor/autoload.php';
|
||||
use Smarty\Smarty;
|
||||
$smarty = new Smarty();
|
||||
|
||||
// or ...
|
||||
|
||||
// Instantiated directly
|
||||
require("/path/to/smarty/libs/Smarty.class.php");
|
||||
use Smarty\Smarty;
|
||||
$smarty = new Smarty();
|
||||
```
|
||||
|
||||
Now that the library files are in place, it's time to set up the Smarty
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// This is a stub PSR-4 loading script that gets all the pieces of //
|
||||
// Smarty 5.x loaded without requiring the use of composer. It's //
|
||||
// not really a 'class' file, but the name is used so we're //
|
||||
// backwards compatible with previous versions of Smarty. //
|
||||
// //
|
||||
// Example: //
|
||||
// require_once("/path/to/smarty/libs/Smarty.class.php"); //
|
||||
// //
|
||||
// $smarty = new Smarty\Smarty; //
|
||||
// $smarty->testInstall(); //
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
define('__SMARTY_DIR', __DIR__ . '/../src/');
|
||||
|
||||
// Global function declarations
|
||||
require_once(__SMARTY_DIR . "/functions.php");
|
||||
|
||||
spl_autoload_register(function ($class) {
|
||||
// Class prefix
|
||||
$prefix = 'Smarty\\';
|
||||
|
||||
// Does the class use the namespace prefix?
|
||||
$len = strlen($prefix);
|
||||
if (strncmp($prefix, $class, $len) !== 0) {
|
||||
// If not, move to the next registered autoloader
|
||||
return;
|
||||
}
|
||||
|
||||
// Hack off the prefix part
|
||||
$relative_class = substr($class, $len);
|
||||
|
||||
// Build a path to the include file
|
||||
$file = __SMARTY_DIR . str_replace('\\', '/', $relative_class) . '.php';
|
||||
|
||||
// If the file exists, require it
|
||||
if (file_exists($file)) {
|
||||
require_once($file);
|
||||
}
|
||||
});
|
||||
+1
-1
@@ -15,7 +15,7 @@ php utilities/update-smarty-version-number.php $1
|
||||
git add changelog CHANGELOG.md src/Smarty.php
|
||||
git commit -m "version bump"
|
||||
|
||||
git checkout master
|
||||
git checkout support/5
|
||||
git pull
|
||||
git merge --no-ff "release/$1"
|
||||
git branch -d "release/$1"
|
||||
|
||||
@@ -43,7 +43,7 @@ class ConfigLoad extends Base {
|
||||
* @var array
|
||||
* @see BasePlugin
|
||||
*/
|
||||
protected $optional_attributes = ['section', 'scope'];
|
||||
protected $optional_attributes = ['section'];
|
||||
|
||||
/**
|
||||
* Attribute definition: Overwrites base class.
|
||||
@@ -51,7 +51,7 @@ class ConfigLoad extends Base {
|
||||
* @var array
|
||||
* @see BasePlugin
|
||||
*/
|
||||
protected $option_flags = ['nocache', 'noscope'];
|
||||
protected $option_flags = [];
|
||||
|
||||
/**
|
||||
* Compiles code for the {config_load} tag
|
||||
@@ -66,9 +66,7 @@ class ConfigLoad extends Base {
|
||||
{
|
||||
// check and get attributes
|
||||
$_attr = $this->getAttributes($compiler, $args);
|
||||
if ($_attr['nocache'] === true) {
|
||||
$compiler->trigger_template_error('nocache option not allowed', null, true);
|
||||
}
|
||||
|
||||
// save possible attributes
|
||||
$conf_file = $_attr['file'];
|
||||
$section = $_attr['section'] ?? 'null';
|
||||
|
||||
@@ -32,7 +32,7 @@ class ExtendsTag extends Inheritance {
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $optional_attributes = ['extends_resource'];
|
||||
protected $optional_attributes = [];
|
||||
|
||||
/**
|
||||
* Attribute definition: Overwrites base class.
|
||||
@@ -64,29 +64,7 @@ class ExtendsTag extends Inheritance {
|
||||
}
|
||||
// add code to initialize inheritance
|
||||
$this->registerInit($compiler, true);
|
||||
$file = trim($_attr['file'], '\'"');
|
||||
if (strlen($file) > 8 && substr($file, 0, 8) === 'extends:') {
|
||||
// generate code for each template
|
||||
$files = array_reverse(explode('|', substr($file, 8)));
|
||||
$i = 0;
|
||||
foreach ($files as $file) {
|
||||
if ($file[0] === '"') {
|
||||
$file = trim($file, '".');
|
||||
} else {
|
||||
$file = "'{$file}'";
|
||||
}
|
||||
$i++;
|
||||
if ($i === count($files) && isset($_attr['extends_resource'])) {
|
||||
$this->compileEndChild($compiler);
|
||||
}
|
||||
$this->compileInclude($compiler, $file);
|
||||
}
|
||||
if (!isset($_attr['extends_resource'])) {
|
||||
$this->compileEndChild($compiler);
|
||||
}
|
||||
} else {
|
||||
$this->compileEndChild($compiler, $_attr['file']);
|
||||
}
|
||||
$this->compileEndChild($compiler, $_attr['file']);
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -106,42 +84,4 @@ class ExtendsTag extends Inheritance {
|
||||
(isset($template) ? ", {$template}, \$_smarty_current_dir" : '') . ");\n?>"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add code for including subtemplate to end of template
|
||||
*
|
||||
* @param \Smarty\Compiler\Template $compiler
|
||||
* @param string $template subtemplate name
|
||||
*
|
||||
* @throws \Smarty\CompilerException
|
||||
* @throws \Smarty\Exception
|
||||
*/
|
||||
private function compileInclude(\Smarty\Compiler\Template $compiler, $template) {
|
||||
$compiler->getParser()->template_postfix[] = new \Smarty\ParseTree\Tag(
|
||||
$compiler->getParser(),
|
||||
$compiler->compileTag(
|
||||
'include',
|
||||
[
|
||||
$template,
|
||||
['scope' => 'parent'],
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create source code for {extends} from source components array
|
||||
*
|
||||
* @param \Smarty\Template $template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function extendsSourceArrayCode(\Smarty\Template $template) {
|
||||
$resources = [];
|
||||
foreach ($template->getSource()->components as $source) {
|
||||
$resources[] = $source->resource;
|
||||
}
|
||||
return $template->getLeftDelimiter() . 'extends file=\'extends:' . join('|', $resources) .
|
||||
'\' extends_resource=true' . $template->getRightDelimiter();
|
||||
}
|
||||
}
|
||||
|
||||
+30
-13
@@ -403,21 +403,37 @@ class Template extends BaseCompiler {
|
||||
}
|
||||
// get template source
|
||||
if (!empty($this->template->getSource()->components)) {
|
||||
// we have array of inheritance templates by extends: resource
|
||||
// generate corresponding source code sequence
|
||||
$_content =
|
||||
ExtendsTag::extendsSourceArrayCode($this->template);
|
||||
|
||||
$_compiled_code = '<?php $_smarty_tpl->getInheritance()->init($_smarty_tpl, true); ?>';
|
||||
|
||||
$i = 0;
|
||||
$reversed_components = array_reverse($this->template->getSource()->components);
|
||||
foreach ($reversed_components as $source) {
|
||||
$i++;
|
||||
if ($i === count($reversed_components)) {
|
||||
$_compiled_code .= '<?php $_smarty_tpl->getInheritance()->endChild($_smarty_tpl); ?>';
|
||||
}
|
||||
$_compiled_code .= $this->compileTag(
|
||||
'include',
|
||||
[
|
||||
var_export($source->resource, true),
|
||||
['scope' => 'parent'],
|
||||
]
|
||||
);
|
||||
}
|
||||
$_compiled_code = $this->smarty->runPostFilters($_compiled_code, $this->template);
|
||||
} else {
|
||||
// get template source
|
||||
$_content = $this->template->getSource()->getContent();
|
||||
$_compiled_code = $this->smarty->runPostFilters(
|
||||
$this->doCompile(
|
||||
$this->smarty->runPreFilters($_content, $this->template),
|
||||
true
|
||||
),
|
||||
$this->template
|
||||
);
|
||||
}
|
||||
$_compiled_code = $this->smarty->runPostFilters(
|
||||
$this->doCompile(
|
||||
$this->smarty->runPreFilters($_content, $this->template),
|
||||
true
|
||||
),
|
||||
$this->template
|
||||
);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
if ($this->smarty->debugging) {
|
||||
$this->smarty->getDebug()->end_compile($this->template);
|
||||
@@ -680,7 +696,8 @@ class Template extends BaseCompiler {
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function appendCode($left, $right) {
|
||||
public function appendCode(string $left, string $right): string
|
||||
{
|
||||
if (preg_match('/\s*\?>\s?$/D', $left) && preg_match('/^<\?php\s+/', $right)) {
|
||||
$left = preg_replace('/\s*\?>\s?$/D', "\n", $left);
|
||||
$left .= preg_replace('/^<\?php\s+/', '', $right);
|
||||
@@ -1056,7 +1073,7 @@ class Template extends BaseCompiler {
|
||||
$prefixArray = array_merge($this->prefix_code, array_pop($this->prefixCodeStack));
|
||||
$this->prefixCodeStack[] = [];
|
||||
foreach ($prefixArray as $c) {
|
||||
$code = $this->appendCode($code, $c);
|
||||
$code = $this->appendCode($code, (string) $c);
|
||||
}
|
||||
$this->prefix_code = [];
|
||||
return $code;
|
||||
|
||||
+4
-1
@@ -224,7 +224,10 @@ class Data
|
||||
return $this->getValue($varName, $searchParents);
|
||||
}
|
||||
|
||||
return array_merge($this->parent && $searchParents ? $this->parent->getTemplateVars() : [], $this->tpl_vars);
|
||||
return array_merge(
|
||||
$this->parent && $searchParents ? $this->parent->getTemplateVars() : [],
|
||||
array_map(function(Variable $var) { return $var->getValue(); }, $this->tpl_vars)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -47,18 +47,18 @@ class Dq extends Base
|
||||
if ($subtree instanceof Code) {
|
||||
$this->subtrees[ $last_subtree ]->data =
|
||||
$parser->compiler->appendCode(
|
||||
$this->subtrees[ $last_subtree ]->data,
|
||||
(string) $this->subtrees[ $last_subtree ]->data,
|
||||
'<?php echo ' . $subtree->data . ';?>'
|
||||
);
|
||||
} elseif ($subtree instanceof DqContent) {
|
||||
$this->subtrees[ $last_subtree ]->data =
|
||||
$parser->compiler->appendCode(
|
||||
$this->subtrees[ $last_subtree ]->data,
|
||||
(string) $this->subtrees[ $last_subtree ]->data,
|
||||
'<?php echo "' . $subtree->data . '";?>'
|
||||
);
|
||||
} else {
|
||||
$this->subtrees[ $last_subtree ]->data =
|
||||
$parser->compiler->appendCode($this->subtrees[ $last_subtree ]->data, $subtree->data);
|
||||
$parser->compiler->appendCode((string) $this->subtrees[ $last_subtree ]->data, (string) $subtree->data);
|
||||
}
|
||||
} else {
|
||||
$this->subtrees[] = $subtree;
|
||||
|
||||
@@ -62,9 +62,9 @@ class Tag extends Base
|
||||
public function assign_to_var(\Smarty\Parser\TemplateParser $parser)
|
||||
{
|
||||
$var = $parser->compiler->getNewPrefixVariable();
|
||||
$tmp = $parser->compiler->appendCode('<?php ob_start();?>', $this->data);
|
||||
$tmp = $parser->compiler->appendCode('<?php ob_start();?>', (string) $this->data);
|
||||
$tmp = $parser->compiler->appendCode($tmp, "<?php {$var}=ob_get_clean();?>");
|
||||
$parser->compiler->appendPrefixCode((string) $tmp);
|
||||
$parser->compiler->appendPrefixCode($tmp);
|
||||
return $var;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ class Template extends Base
|
||||
break;
|
||||
case 'tag':
|
||||
foreach ($chunk['subtrees'] as $subtree) {
|
||||
$text = $parser->compiler->appendCode($text, $subtree->to_smarty_php($parser));
|
||||
$text = $parser->compiler->appendCode($text, (string) $subtree->to_smarty_php($parser));
|
||||
}
|
||||
$code .= $text;
|
||||
break;
|
||||
|
||||
@@ -2536,7 +2536,7 @@ public static $yy_action = array(
|
||||
// line 806 "src/Parser/TemplateParser.y"
|
||||
public function yy_r101(){
|
||||
$prefixVar = $this->compiler->getNewPrefixVariable();
|
||||
$tmp = $this->compiler->appendCode('<?php ob_start();?>', $this->yystack[$this->yyidx + 0]->minor);
|
||||
$tmp = $this->compiler->appendCode('<?php ob_start();?>', (string) $this->yystack[$this->yyidx + 0]->minor);
|
||||
$this->compiler->appendPrefixCode($this->compiler->appendCode($tmp, "<?php {$prefixVar} = ob_get_clean();?>"));
|
||||
$this->_retvalue = $prefixVar;
|
||||
}
|
||||
|
||||
@@ -805,7 +805,7 @@ value(res) ::= varindexed(vi) DOUBLECOLON static_class_access(r). {
|
||||
// Smarty tag
|
||||
value(res) ::= smartytag(st). {
|
||||
$prefixVar = $this->compiler->getNewPrefixVariable();
|
||||
$tmp = $this->compiler->appendCode('<?php ob_start();?>', st);
|
||||
$tmp = $this->compiler->appendCode('<?php ob_start();?>', (string) st);
|
||||
$this->compiler->appendPrefixCode($this->compiler->appendCode($tmp, "<?php {$prefixVar} = ob_get_clean();?>"));
|
||||
res = $prefixVar;
|
||||
}
|
||||
|
||||
@@ -116,22 +116,20 @@ class ForeachRuntime {
|
||||
*
|
||||
* @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0
|
||||
* for empty elements
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function count($value) {
|
||||
if ($value instanceof IteratorAggregate) {
|
||||
public function count($value): int
|
||||
{
|
||||
if ($value instanceof \IteratorAggregate) {
|
||||
// Note: getIterator() returns a Traversable, not an Iterator
|
||||
// thus rewind() and valid() methods may not be present
|
||||
return iterator_count($value->getIterator());
|
||||
} elseif ($value instanceof Iterator) {
|
||||
return $value instanceof Generator ? 1 : iterator_count($value);
|
||||
} elseif ($value instanceof Countable) {
|
||||
} elseif ($value instanceof \Iterator) {
|
||||
return $value instanceof \Generator ? 1 : iterator_count($value);
|
||||
} elseif ($value instanceof \Countable) {
|
||||
return count($value);
|
||||
} elseif ($value instanceof PDOStatement) {
|
||||
return $value->rowCount();
|
||||
} elseif ($value instanceof Traversable) {
|
||||
return iterator_count($value);
|
||||
}
|
||||
return count((array)$value);
|
||||
return count((array) $value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+41
-2
@@ -54,7 +54,7 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
/**
|
||||
* smarty version
|
||||
*/
|
||||
const SMARTY_VERSION = '5.0.1';
|
||||
const SMARTY_VERSION = '5.2.0';
|
||||
|
||||
/**
|
||||
* define caching modes
|
||||
@@ -684,6 +684,21 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a template directory before any existing directoires
|
||||
*
|
||||
* @param string $new_template_dir directory of template sources
|
||||
* @param bool $is_config true for config_dir
|
||||
*
|
||||
* @return static current Smarty instance for chaining
|
||||
*/
|
||||
public function prependTemplateDir($new_template_dir, $is_config = false) {
|
||||
$current_template_dirs = $is_config ? $this->config_dir : $this->template_dir;
|
||||
array_unshift($current_template_dirs, $new_template_dir);
|
||||
$this->setTemplateDir($current_template_dirs, $is_config);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add config directory(s)
|
||||
*
|
||||
@@ -2211,5 +2226,29 @@ class Smarty extends \Smarty\TemplateBase {
|
||||
return $template;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Whether Smarty displays an error when using an unassigned variable
|
||||
*/
|
||||
public function getErrorUnassigned(): bool
|
||||
{
|
||||
return (bool) $this->error_unassigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if Smarty should display an error on using an unassigned variable
|
||||
*/
|
||||
public function setErrorUnassigned(bool $error_unassigned): void
|
||||
{
|
||||
$this->error_unassigned = $error_unassigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets if Smarty should check If-Modified-Since headers to determine cache validity.
|
||||
* @param bool $cache_modified_check
|
||||
* @return void
|
||||
*/
|
||||
public function setCacheModifiedCheck($cache_modified_check): void {
|
||||
$this->cache_modified_check = (bool) $cache_modified_check;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -91,4 +91,13 @@ class FileResourceIndexedTest extends PHPUnit_Smarty
|
||||
|
||||
$this->assertNotEquals($tpl->getCached()->filepath, $tpl2->getCached()->filepath);
|
||||
}
|
||||
|
||||
public function testPrependTemplatePath()
|
||||
{
|
||||
$this->smarty->setTemplateDir(__DIR__ . '/templates');
|
||||
$this->smarty->prependTemplateDir(__DIR__ . '/templates_4');
|
||||
$tpl = $this->smarty->createTemplate('dirname.tpl');
|
||||
$this->assertEquals('templates_4', $this->smarty->fetch($tpl));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,112 +1,126 @@
|
||||
<?php
|
||||
/**
|
||||
* Smarty PHPunit tests getTemplateVars method
|
||||
*
|
||||
|
||||
* @author Uwe Tews
|
||||
*/
|
||||
|
||||
/**
|
||||
* class for getTemplateVars method test
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
class GetTemplateVarsTest extends PHPUnit_Smarty
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->setUpSmarty(__DIR__);
|
||||
}
|
||||
|
||||
public function testInit()
|
||||
{
|
||||
$this->cleanDirs();
|
||||
}
|
||||
/**
|
||||
* test root getTemplateVars single value
|
||||
*/
|
||||
public function testGetSingleTemplateVarScopeRoot()
|
||||
{
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$this->smarty->assign('blar', 'buh');
|
||||
$this->assertEquals("bar", $this->smarty->getTemplateVars('foo'));
|
||||
}
|
||||
|
||||
public function testInit()
|
||||
{
|
||||
$this->cleanDirs();
|
||||
}
|
||||
/**
|
||||
* test root getTemplateVars single value
|
||||
*/
|
||||
public function testGetSingleTemplateVarScopeRoot()
|
||||
{
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$this->smarty->assign('blar', 'buh');
|
||||
$this->assertEquals("bar", $this->smarty->getTemplateVars('foo'));
|
||||
}
|
||||
/**
|
||||
* test root getTemplateVars all values
|
||||
*/
|
||||
public function testGetAllTemplateVarsScopeRoot()
|
||||
{
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$this->smarty->assign('blar', 'buh');
|
||||
$vars = $this->smarty->getTemplateVars();
|
||||
$this->assertTrue(is_array($vars));
|
||||
$this->assertEquals("bar", $vars['foo']);
|
||||
$this->assertEquals("buh", $vars['blar']);
|
||||
}
|
||||
|
||||
/**
|
||||
* test root getTemplateVars all values
|
||||
*/
|
||||
public function testGetAllTemplateVarsScopeRoot()
|
||||
{
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$this->smarty->assign('blar', 'buh');
|
||||
$vars = $this->smarty->getTemplateVars();
|
||||
$this->assertTrue(is_array($vars));
|
||||
$this->assertEquals("bar", $vars['foo']);
|
||||
$this->assertEquals("buh", $vars['blar']);
|
||||
}
|
||||
/**
|
||||
* test single variable with data object chain
|
||||
*/
|
||||
public function testGetSingleTemplateVarScopeAll()
|
||||
{
|
||||
$data1 = $this->smarty->createData($this->smarty);
|
||||
$data2 = $this->smarty->createData($data1);
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$this->smarty->assign('blar', 'buh');
|
||||
$this->assertEquals("bar", $data2->getTemplateVars('foo'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test single variable with data object chain
|
||||
*/
|
||||
public function testGetSingleTemplateVarScopeAll()
|
||||
{
|
||||
$data1 = $this->smarty->createData($this->smarty);
|
||||
$data2 = $this->smarty->createData($data1);
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$this->smarty->assign('blar', 'buh');
|
||||
$this->assertEquals("bar", $data2->getTemplateVars('foo'));
|
||||
}
|
||||
/**
|
||||
* test get all variables with data object chain
|
||||
*/
|
||||
public function testGetAllTemplateVarsScopeAll()
|
||||
{
|
||||
$data1 = $this->smarty->createData($this->smarty);
|
||||
$data2 = $this->smarty->createData($data1);
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$data1->assign('blar', 'buh');
|
||||
$data2->assign('foo2', 'bar2');
|
||||
$vars = $data2->getTemplateVars(null);
|
||||
$this->assertTrue(is_array($vars));
|
||||
$this->assertEquals("bar", $vars['foo']);
|
||||
$this->assertEquals("bar2", $vars['foo2']);
|
||||
$this->assertEquals("buh", $vars['blar']);
|
||||
}
|
||||
|
||||
/**
|
||||
* test get all variables with data object chain
|
||||
*/
|
||||
public function testGetAllTemplateVarsScopeAll()
|
||||
{
|
||||
$data1 = $this->smarty->createData($this->smarty);
|
||||
$data2 = $this->smarty->createData($data1);
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$data1->assign('blar', 'buh');
|
||||
$data2->assign('foo2', 'bar2');
|
||||
$vars = $data2->getTemplateVars(null);
|
||||
$this->assertTrue(is_array($vars));
|
||||
$this->assertEquals("bar", $vars['foo']);
|
||||
$this->assertEquals("bar2", $vars['foo2']);
|
||||
$this->assertEquals("buh", $vars['blar']);
|
||||
}
|
||||
/**
|
||||
* test get all variables with data object chain search parents disabled
|
||||
*/
|
||||
public function testGetAllTemplateVarsScopeAllNoParents()
|
||||
{
|
||||
$data1 = $this->smarty->createData($this->smarty);
|
||||
$data2 = $this->smarty->createData($data1);
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$data1->assign('blar', 'buh');
|
||||
$data2->assign('foo2', 'bar2');
|
||||
$vars = $data2->getTemplateVars(null, false);
|
||||
$this->assertTrue(is_array($vars));
|
||||
$this->assertFalse(isset($vars['foo']));
|
||||
$this->assertEquals("bar2", $vars['foo2']);
|
||||
$this->assertFalse(isset($vars['blar']));
|
||||
}
|
||||
|
||||
/**
|
||||
* test get all variables with data object chain search parents disabled
|
||||
*/
|
||||
public function testGetAllTemplateVarsScopeAllNoParents()
|
||||
{
|
||||
$data1 = $this->smarty->createData($this->smarty);
|
||||
$data2 = $this->smarty->createData($data1);
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$data1->assign('blar', 'buh');
|
||||
$data2->assign('foo2', 'bar2');
|
||||
$vars = $data2->getTemplateVars(null, false);
|
||||
$this->assertTrue(is_array($vars));
|
||||
$this->assertFalse(isset($vars['foo']));
|
||||
$this->assertEquals("bar2", $vars['foo2']);
|
||||
$this->assertFalse(isset($vars['blar']));
|
||||
}
|
||||
/**
|
||||
* test get single variables with data object chain search parents disabled
|
||||
*/
|
||||
public function testGetSingleTemplateVarsScopeAllNoParents()
|
||||
{
|
||||
error_reporting(error_reporting() & ~(E_NOTICE | E_USER_NOTICE));
|
||||
$data1 = $this->smarty->createData($this->smarty);
|
||||
$data2 = $this->smarty->createData($data1);
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$data1->assign('blar', 'buh');
|
||||
$data2->assign('foo2', 'bar2');
|
||||
$this->assertEquals("", $data2->getTemplateVars('foo', false));
|
||||
$this->assertEquals("bar2", $data2->getTemplateVars('foo2', false));
|
||||
$this->assertEquals("", $data2->getTemplateVars('blar', false));
|
||||
}
|
||||
|
||||
/**
|
||||
* test that variable assigned by global assign in template is included in getTemplateVars
|
||||
*/
|
||||
public function testAssignedInTemplate()
|
||||
{
|
||||
$this->smarty->fetch('string:{assign var="b" value="x" scope="global"}');
|
||||
$this->assertEquals('x', $this->smarty->getTemplateVars('b'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test that getTemplateVars returns simple array of values
|
||||
*/
|
||||
public function testSimpleCallReturnsArrayWithAllValues()
|
||||
{
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$this->smarty->assign('i', 3);
|
||||
|
||||
$vars = $this->smarty->getTemplateVars();
|
||||
|
||||
$this->assertArrayHasKey('foo', $vars);
|
||||
$this->assertArrayHasKey('i', $vars);
|
||||
$this->assertEquals('bar', $vars['foo']);
|
||||
$this->assertEquals(3,$vars['i']);
|
||||
}
|
||||
|
||||
/**
|
||||
* test get single variables with data object chain search parents disabled
|
||||
*/
|
||||
public function testGetSingleTemplateVarsScopeAllNoParents()
|
||||
{
|
||||
error_reporting(error_reporting() & ~(E_NOTICE | E_USER_NOTICE));
|
||||
$data1 = $this->smarty->createData($this->smarty);
|
||||
$data2 = $this->smarty->createData($data1);
|
||||
$this->smarty->assign('foo', 'bar');
|
||||
$data1->assign('blar', 'buh');
|
||||
$data2->assign('foo2', 'bar2');
|
||||
$this->assertEquals("", $data2->getTemplateVars('foo', false));
|
||||
$this->assertEquals("bar2", $data2->getTemplateVars('foo2', false));
|
||||
$this->assertEquals("", $data2->getTemplateVars('blar', false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1193,8 +1193,38 @@ class CompileBlockExtendsTest extends PHPUnit_Smarty
|
||||
);
|
||||
}
|
||||
|
||||
public function testBlockWithAssign() {
|
||||
$this->assertEquals('Captured content is: Content with lots of html here', $this->smarty->fetch('038_child.tpl'));
|
||||
}
|
||||
public function testBlockWithAssign() {
|
||||
$this->assertEquals('Captured content is: Content with lots of html here', $this->smarty->fetch('038_child.tpl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test escaping of file parameter
|
||||
*/
|
||||
public function testEscaping()
|
||||
{
|
||||
$this->expectException(\Smarty\Exception::class);
|
||||
$this->expectExceptionMessageMatches('/Unable to load.*/');
|
||||
$this->assertEquals('hello world', $this->smarty->fetch('escaping.tpl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test escaping of file parameter 2
|
||||
*/
|
||||
public function testEscaping2()
|
||||
{
|
||||
$this->expectException(\Smarty\Exception::class);
|
||||
$this->expectExceptionMessageMatches('/Unable to load.*/');
|
||||
$this->assertEquals('hello world', $this->smarty->fetch('escaping2.tpl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test escaping of file parameter 3
|
||||
*/
|
||||
public function testEscaping3()
|
||||
{
|
||||
$this->expectException(\Smarty\Exception::class);
|
||||
$this->expectExceptionMessageMatches('/Unable to load.*/');
|
||||
$this->assertEquals('hello world', $this->smarty->fetch('escaping3.tpl'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{extends "extends:helloworld.tpl', var_dump(shell_exec('ls')), 1, 2, 3);}}?>"}
|
||||
@@ -0,0 +1 @@
|
||||
{extends 'extends:"helloworld.tpl\', var_dump(shell_exec(\'ls\')), 1, 2, 3);}}?>'}
|
||||
@@ -0,0 +1 @@
|
||||
{extends file='extends:"helloworld.tpl'|cat:"', var_dump(shell_exec('ls')), 1, 2, 3);}}?>"}
|
||||
@@ -82,6 +82,18 @@ class CompileIncludeTest extends PHPUnit_Smarty
|
||||
$this->assertEquals('I1I2I3', $content, $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* test template name escaping
|
||||
*/
|
||||
public function testIncludeFilenameEscaping()
|
||||
{
|
||||
$this->expectException(\Smarty\Exception::class);
|
||||
$this->expectExceptionMessageMatches('/Unable to load.*/');
|
||||
$tpl = $this->smarty->createTemplate('test_include_security.tpl');
|
||||
$content = $this->smarty->fetch($tpl);
|
||||
$this->assertEquals("hello world", $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* test standard output
|
||||
*
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{include file="helloworld.tpl', var_dump(shell_exec('ls')), 1, 2, 3);}}?>"}
|
||||
@@ -32,4 +32,11 @@ class ExtendsIssue419Test extends PHPUnit_Smarty
|
||||
$this->assertEquals('child', $this->smarty->fetch('extends:001_parent.tpl|001_child.tpl'));
|
||||
}
|
||||
|
||||
public function testextendsSecurity()
|
||||
{
|
||||
$this->expectException(\Smarty\Exception::class);
|
||||
$this->expectExceptionMessageMatches('/Unable to load.*/');
|
||||
$this->assertEquals('child', $this->smarty->fetch('string:{include "001_parent.tpl\', var_dump(shell_exec(\'ls\')), 1, 2, 3);}}?>"}'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user