Compare commits

..

3 Commits

Author SHA1 Message Date
Simon Wisselink 1ab955ada5 use eval to fix compatability of test code for all supported php versions 2026-02-15 15:20:56 +01:00
Simon Wisselink b925a91b00 fix tests on PHP <= 8.0 2026-02-15 15:15:56 +01:00
Simon Wisselink 27379ab3c4 Add support for Backed Enums
Fixes #1012

Also added docs (and docs for matches operator)
2026-02-15 15:11:29 +01:00
384 changed files with 1238 additions and 1039 deletions
-2
View File
@@ -7,5 +7,3 @@ phpunit*
.phpunit.result.cache
vendor/*
composer.lock
-87
View File
@@ -1,87 +0,0 @@
# AGENTS.md
This file is the single source of truth for AI coding assistants working in this repo (including Claude Code, claude.ai/code).
## Project
Smarty v5 — PHP template engine. Single Composer package (`smarty/smarty`), namespace `Smarty\`, source in `src/`, autoloaded via PSR-4. Supports PHP 7.28.5.
Do not use PHP syntax newer than 7.2 in `src/` unless it is guarded for older runtimes.
## Commands
```bash
# Install dependencies
composer install
# Regenerate lexers and parsers (required before tests; CI runs this)
make -B
# Run all tests
php ./vendor/phpunit/phpunit/phpunit
# Run a single test file
php ./vendor/phpunit/phpunit/phpunit tests/UnitTests/TemplateSource/TagTests/If/CompileIfTest.php
# Run tests matching a PHPUnit group
php ./vendor/phpunit/phpunit/phpunit --group 20221124
# Run tests excluding slow group
php ./vendor/phpunit/phpunit/phpunit --exclude-group slow
```
There is no linter or static analysis configured. No typecheck step.
## Generated code — do not hand-edit
Four files are generated from grammar/lexer definitions via `make`:
| Source (edit this) | Generated (do not edit) |
|---|---|
| `src/Lexer/TemplateLexer.plex` | `src/Lexer/TemplateLexer.php` |
| `src/Lexer/ConfigfileLexer.plex` | `src/Lexer/ConfigfileLexer.php` |
| `src/Parser/TemplateParser.y` | `src/Parser/TemplateParser.php` |
| `src/Parser/ConfigfileParser.y` | `src/Parser/ConfigfileParser.php` |
After editing a `.plex` or `.y` file, run `make -B` to regenerate. The generators require the `smarty/smarty-lexer` dev dependency.
## Architecture
- `src/Smarty.php` — main class, extends `TemplateBase`. Version constant: `Smarty::SMARTY_VERSION`.
- `src/Compile/`, `src/Compiler/` — template compilation pipeline.
- `src/Lexer/`, `src/Parser/` — lexer/parser (generated, see above).
- `src/Extension/` — extension system (`ExtensionInterface`, `CoreExtension`, `DefaultExtension`, `BCPluginsAdapter`).
- `src/Runtime/` — runtime helpers (foreach, capture, inheritance, tpl functions).
- `src/Resource/`, `src/Cacheresource/` — template resource and cache resource handlers.
- `src/BlockHandler/`, `src/FunctionHandler/`, `src/Filter/` — built-in tags, functions, and filters.
- `libs/Smarty.class.php` — non-Composer autoload stub. Points to `src/`. Not the main source.
- `src/functions.php` — global helper functions, always loaded via Composer `files` autoload.
## Tests
- Framework: PHPUnit 7.5/8.5 (bootstrap: `tests/Bootstrap.php`).
- All tests extend `PHPUnit_Smarty` (defined in `tests/PHPUnit_Smarty.php`), which provides `setUpSmarty($dir)`.
- Test suite root: `tests/UnitTests/`. Typical test `setUp()` calls `$this->setUpSmarty(__DIR__)`.
- Each test directory may have its own `templates/`, `configs/` subdirectories. Compiled output goes to `templates_c/` and `cache/` (auto-created by the test harness).
- Running the suite scatters generated `templates_c/`, `cache/`, and `templates_tmp/` directories (and empty runtime `templates/`/`configs/` dirs) throughout `tests/` and the repo root. These are not tracked — treat them as noise in `git status`, never commit them, and clean them with `git clean -fd` (exclude tool dirs like `.serena`).
- Three test files are excluded in `phpunit.xml`: Memcache, APC, and HttpModifiedSince tests (require external services).
- Tests needing MySQL/PDO are gated by constants in `tests/Config.php` (disabled by default).
## CI
GitHub Actions (`.github/workflows/ci.yml`): matrix of PHP 7.28.5 on ubuntu + windows. Steps: `composer install``make -B``phpunit`. No deploy step.
## Docs
Markdown in `docs/`, built with mkdocs + Material theme. Install the toolchain with `pip install -r docs/requirements.txt`, then preview with `mkdocs serve`. Published via `mike deploy 5.x`.
## Release
`./make-release.sh <version>` — only v5.x.x. Updates changelog and version constant, creates a merge commit and tag on `master`.
### Changelog
Every change that should appear in `CHANGELOG.md` must add a new markdown file under `changelog/`. At release time `utilities/update-changelog.php` concatenates all `changelog/*.md` files into the `## [Unreleased]` section, so:
- One file per change, containing a single line that starts with a dash (`- ...`). The filename is arbitrary; name it after the issue number (e.g. `1036.md`) when there is one, otherwise use a short descriptive slug.
- Include a markdown link to the relevant issue when one exists, e.g. `[#1036](https://github.com/smarty-php/smarty/issues/1036)`. Omit the link when there is no public issue (e.g. embargoed security reports).
-29
View File
@@ -6,35 +6,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [5.8.4] - 2026-06-29
- Fixed a `TypeError` on PHP 8 when `Security::$static_classes` was set to a non-array value (e.g. the string `'none'`) to disable static class access; any non-array value now cleanly denies access. Use `Security::$static_classes = null` to disable access to all static classes.
- Security: the built-in `stream:` resource type now validates the nested stream wrapper against the security policy, so a template such as `stream:php://filter/...` can no longer bypass `Security::$streams` (including `Security::$streams = null`) to read local files (CWE-22)
## [5.8.3] - 2026-06-28
- fixed a regression from #1189 where a child template's block override no longer applied to a template {include}d by the parent [#1192](https://github.com/smarty-php/smarty/issues/1192)
## [5.8.2] - 2026-06-24
- Security: prevent symlinks inside a trusted `secure_dir`/template directory from being used to read files outside of it (CWE-22 path traversal), affecting `{include}` and `{fetch}` of local files
- Security: `{html_image}` now escapes the `file`, `path_prefix`, `href`/`link`, `width` and `height` attributes (it already escaped `alt` and pass-through attributes), and `{html_select_date}` casts `day_size`/`month_size`/`year_size` to int (matching `{html_select_time}`), preventing untrusted values passed into these attributes from breaking out of the generated HTML (CWE-79)
- Security: `{fetch}` no longer follows HTTP redirects for remote resources while a security policy is active, preventing an open redirect on a trusted host from bypassing `trusted_uri` (CWE-918 server-side request forgery)
- Fixed "Attempt to assign property step on null" error when using a {for} loop inside a block of an extended template [#1036](https://github.com/smarty-php/smarty/issues/1036)
## [5.8.1] - 2026-06-23
- Re-activated unit tests for user literals, which were previously disabled due to a bug in refactoring to v5.
- fixed a bug where child template's block content leaked into subsequent rendering of the parent template [#1189](https://github.com/smarty-php/smarty/issues/1189)
- Moved all unit test-generated output from inside the working tree to tmp files [#1178](https://github.com/smarty-php/smarty/issues/1178)
## [5.8.0] - 2026-02-15
- Added support for Backed Enums for php versions >= 8.1 [#1171](https://github.com/smarty-php/smarty/pull/1171)
- Added support for new 'matches' operator doing regex matching [#1169](https://github.com/smarty-php/smarty/pull/1169)
- Update documentation to clarify that include inline is currently not implemented in Smarty v5 [#1152](https://github.com/smarty-php/smarty/issues/1152)
- Support for Laravel Collections style object chaining for objects return from function calls implemented as modifiers [#1151](https://github.com/smarty-php/smarty/issues/1151)
## [5.7.0] - 2025-11-19
- PHP 8.5 support
-5
View File
@@ -100,11 +100,6 @@ Enhancement suggestions are tracked as [GitHub issues](https://github.com/smarty
The [docs](docs/index.md) are written in markdown, configured in [mkdocs.yml](mkdocs.yml) and published
to [GitHub pages](https://smarty-php.github.io/smarty) using [mkdocs](https://www.mkdocs.org/) and [mike](https://github.com/jimporter/mike).
You need Python to build the docs. Install the required packages first:
```bash
pip install -r docs/requirements.txt
```
To preview the docs while you are writing, run:
```bash
mkdocs serve
+5 -4
View File
@@ -11,10 +11,10 @@
## include inline
- Re-introduce merge_compiled_includes and the {include inline} attribute?
## Output buffering (major)
- Fix ob_ output buffering commands being scattered around the codebase: Smarty's output model is fundamentally "echo everything, wrap in a buffer to capture". An alternative that would be where rendering returns a string rather than echoing — but that touches the entire compiled template format (the unifunc functions all echo) and is a large change.
## Output buffering
- Fix ob_ output buffering commands being scattered around the codebase
## Review public static vars (major)
## Review public static vars
- such as _CHARSET and _IS_WINDOWS
## Block / inheritance
@@ -24,8 +24,9 @@
## Plugin system
- fix template security checks in one place in compiler
## Beatify output (major)
## Beatify output
- compiled templates could be proper classes, possibly using [nette/php-generator](https://packagist.org/packages/nette/php-generator)
## Unrelated / other
- review (and avoid) use of 'clone' keyword
- what is 'user literal support', why are unit tests skipped?
+1
View File
@@ -0,0 +1 @@
- Support for Laravel Collections style object chaining for objects return from function calls implemented as modifiers [#1151](https://github.com/smarty-php/smarty/issues/1151)
+1
View File
@@ -0,0 +1 @@
- Update documentation to clarify that include inline is currently not implemented in Smarty v5 [#1152](https://github.com/smarty-php/smarty/issues/1152)
+1
View File
@@ -1,3 +1,4 @@
version: "2"
services:
base:
build:
@@ -27,13 +27,6 @@ which item(s) are selected by default as well.
- All parameters that are not in the list above are printed as
name/value-pairs inside each of the created <input\>-tags.
> **Security note**
>
> The `separator` attribute is written into the generated HTML without escaping,
> so it can contain markup such as `separator='<br />'`. If its value originates
> from untrusted input, escape it yourself first to avoid cross-site scripting
> (XSS). Option values and labels are escaped automatically.
## Examples
```php
<?php
@@ -28,13 +28,6 @@ selected by default as well.
- All parameters that are not in the list above are output as
name/value-pairs inside each of the created `<input>`-tags.
> **Security note**
>
> The `separator` attribute is written into the generated HTML without escaping,
> so it can contain markup such as `separator='<br />'`. If its value originates
> from untrusted input, escape it yourself first to avoid cross-site scripting
> (XSS). Option values and labels are escaped automatically.
## Examples
```php
@@ -47,14 +47,6 @@ name/value-pairs inside the `<select>` tags of day, month and year.
> There is an useful php function on the [date tips page](../../appendixes/tips.md)
> for converting `{html_select_date}` form values to a timestamp.
> **Security note**
>
> The `*_extra` attributes, `field_separator`/`option_separator`, and any
> unrecognised parameter (which is emitted as a raw attribute on the `<select>`
> tag) are written into the generated HTML without escaping. If any of these
> values originate from untrusted input, escape them yourself first to avoid
> cross-site scripting (XSS).
## Exaples
Template code
@@ -47,14 +47,6 @@ parseable by PHP's [`strtotime()`](https://www.php.net/strtotime).
| meridian\_empty | null | If supplied then the first element of the meridian's select-box has this value as it's label and "" as it's value. This is useful to make the select-box read "Please select an meridian" for example. |
> **Security note**
>
> The `*_extra` attributes, `field_separator`/`option_separator`, and any
> unrecognised parameter (which is emitted as a raw attribute on the `<select>`
> tag) are written into the generated HTML without escaping. If any of these
> values originate from untrusted input, escape them yourself first to avoid
> cross-site scripting (XSS).
## Examples
```smarty
@@ -31,15 +31,6 @@ dumps an array of data into an HTML `<table>`.
- `trailpad` is the value put into the trailing cells on the last
table row if there are any present.
> **Security note**
>
> The `loop`/`cols` data and the `caption`, `trailpad`, `table_attr`, `tr_attr`,
> `td_attr` and `th_attr` attributes are written into the generated HTML without
> escaping (this is by design — e.g. `table_attr='border="1"'`). If any of these
> values originate from untrusted input, escape them yourself first (e.g. with the
> [`escape`](../language-modifiers/language-modifier-escape.md) modifier) to avoid
> cross-site scripting (XSS).
## Examples
```php
@@ -24,14 +24,6 @@ spiders to lift email addresses off of a site.
> you can use hex encoding too.
> **Security note**
>
> The `extra` attribute is written into the generated `<a>` tag without escaping,
> so that you can add attributes such as `extra='class="mailto"'`. If you pass a
> value that originates from untrusted input, escape it yourself first (e.g. with
> the [`escape`](../language-modifiers/language-modifier-escape.md) modifier) to
> avoid cross-site scripting (XSS).
## Examples
```smarty
-14
View File
@@ -1,14 +0,0 @@
# Python dependencies for building/previewing the docs.
#
# pip install -r docs/requirements.txt
# mkdocs serve # local preview
# mike deploy 5.x # publish
#
# pymdown-extensions must be >=11: earlier releases pass filename=None to
# Pygments, and Pygments >=2.19 then crashes with
# "'NoneType' object has no attribute 'replace'" on any untitled code block.
mkdocs>=1.6
mkdocs-material>=9.7
pymdown-extensions>=11
Pygments>=2.19
mike>=2.2
+1
View File
@@ -20,6 +20,7 @@
<testsuite name="foo">
<directory>./tests/UnitTests/</directory>
<exclude>./tests/UnitTests/CacheResourceTests/Memcache/CacheResourceCustomMemcacheTest.php</exclude>
<exclude>./tests/UnitTests/CacheResourceTests/Apc/CacheResourceCustomApcTest.php</exclude>
<exclude>./tests/UnitTests/CacheModify/ModifiedSince/HttpModifiedSinceTest.php</exclude>
</testsuite>
</testsuites>
+1 -1
View File
@@ -5,7 +5,7 @@
# - ./run-tests-for-all-php-versions.sh --group 20221124
# - ./run-tests-for-all-php-versions.sh --exclude-group slow
COMPOSE_CMD="docker compose"
COMPOSE_CMD="mutagen-compose"
$COMPOSE_CMD run --rm php72 ./run-tests.sh $@ && \
$COMPOSE_CMD run --rm php73 ./run-tests.sh $@ && \
+1 -1
View File
@@ -143,7 +143,7 @@ class File extends Base
*
* @param Template $_template template object
*
* @return string|false content
* @return string content
*/
public function retrieveCachedContent(Template $_template)
{
+12 -15
View File
@@ -51,9 +51,8 @@ class ForTag extends Base {
$var = $_statement['var'];
$index = '';
}
$itemVar = "\$_smarty_tpl->getVariable({$var})";
$output .= "\$_smarty_tpl->assign($var, []);\n";
$output .= "{$itemVar}->value{$index} = {$_statement['value']};\n";
$output .= "\$_smarty_tpl->assign($var, null);\n";
$output .= "\$_smarty_tpl->tpl_vars[$var]->value{$index} = {$_statement['value']};\n";
}
if (is_array($_attr['var'])) {
$var = $_attr['var']['var'];
@@ -62,8 +61,7 @@ class ForTag extends Base {
$var = $_attr['var'];
$index = '';
}
$itemVar = "\$_smarty_tpl->getVariable({$var})";
$output .= "if ($_attr[ifexp]) {\nfor (\$_foo=true;$_attr[ifexp]; {$itemVar}->value{$index}$_attr[step]) {\n";
$output .= "if ($_attr[ifexp]) {\nfor (\$_foo=true;$_attr[ifexp]; \$_smarty_tpl->tpl_vars[$var]->value{$index}$_attr[step]) {\n";
} else {
$_statement = $_attr['start'];
if (is_array($_statement['var'])) {
@@ -73,22 +71,21 @@ class ForTag extends Base {
$var = $_statement['var'];
$index = '';
}
$itemVar = "\$_smarty_tpl->getVariable({$var})";
$output .= "\$_smarty_tpl->assign($var, []);";
$output .= "\$_smarty_tpl->assign($var, null);";
if (isset($_attr['step'])) {
$output .= "{$itemVar}->step = $_attr[step];";
$output .= "\$_smarty_tpl->tpl_vars[$var]->step = $_attr[step];";
} else {
$output .= "{$itemVar}->step = 1;";
$output .= "\$_smarty_tpl->tpl_vars[$var]->step = 1;";
}
if (isset($_attr['max'])) {
$output .= "{$itemVar}->total = (int) min(ceil(({$itemVar}->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs({$itemVar}->step)),$_attr[max]);\n";
$output .= "\$_smarty_tpl->tpl_vars[$var]->total = (int) min(ceil((\$_smarty_tpl->tpl_vars[$var]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$var]->step)),$_attr[max]);\n";
} else {
$output .= "{$itemVar}->total = (int) ceil(({$itemVar}->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs({$itemVar}->step));\n";
$output .= "\$_smarty_tpl->tpl_vars[$var]->total = (int) ceil((\$_smarty_tpl->tpl_vars[$var]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$var]->step));\n";
}
$output .= "if ({$itemVar}->total > 0) {\n";
$output .= "for ({$itemVar}->value{$index} = $_statement[value], {$itemVar}->iteration = 1;{$itemVar}->iteration <= {$itemVar}->total;{$itemVar}->value{$index} += {$itemVar}->step, {$itemVar}->iteration++) {\n";
$output .= "{$itemVar}->first = {$itemVar}->iteration === 1;";
$output .= "{$itemVar}->last = {$itemVar}->iteration === {$itemVar}->total;";
$output .= "if (\$_smarty_tpl->tpl_vars[$var]->total > 0) {\n";
$output .= "for (\$_smarty_tpl->tpl_vars[$var]->value{$index} = $_statement[value], \$_smarty_tpl->tpl_vars[$var]->iteration = 1;\$_smarty_tpl->tpl_vars[$var]->iteration <= \$_smarty_tpl->tpl_vars[$var]->total;\$_smarty_tpl->tpl_vars[$var]->value{$index} += \$_smarty_tpl->tpl_vars[$var]->step, \$_smarty_tpl->tpl_vars[$var]->iteration++) {\n";
$output .= "\$_smarty_tpl->tpl_vars[$var]->first = \$_smarty_tpl->tpl_vars[$var]->iteration === 1;";
$output .= "\$_smarty_tpl->tpl_vars[$var]->last = \$_smarty_tpl->tpl_vars[$var]->iteration === \$_smarty_tpl->tpl_vars[$var]->total;";
}
$output .= '?>';
+1 -16
View File
@@ -189,22 +189,7 @@ class Fetch extends Base {
return;
}
} else {
if ($protocol && isset($template->getSmarty()->security_policy)) {
// Remote resource (e.g. https://) reached through file_get_contents().
// isTrustedUri() only validates the initial URL, but file_get_contents()
// follows redirects by default, so an open redirect on an otherwise
// trusted host could be used to reach a non-trusted target (SSRF).
// Disable redirect-following while a security policy is in effect.
$context = stream_context_create([
'http' => [
'follow_location' => 0,
'max_redirects' => 1,
],
]);
$content = @file_get_contents($params['file'], false, $context);
} else {
$content = @file_get_contents($params['file']);
}
$content = @file_get_contents($params['file']);
if ($content === false) {
throw new Exception("{fetch} cannot read resource '" . $params['file'] . "'");
}
+3 -8
View File
@@ -65,7 +65,7 @@ class HtmlImage extends Base {
break;
case 'link':
case 'href':
$prefix = '<a href="' . smarty_function_escape_special_chars($_val) . '">';
$prefix = '<a href="' . $_val . '">';
$suffix = '</a>';
break;
default:
@@ -143,12 +143,7 @@ class HtmlImage extends Base {
$width = round($width * $_resize);
$height = round($height * $_resize);
}
// $alt and the pass-through attributes ($extra) are already escaped above;
// escape the remaining value-context params at output time so untrusted
// values cannot break out of the attribute (CWE-79). The unescaped $file/
// $width/$height are still used for getimagesize()/DPI math above.
return $prefix . '<img src="' . smarty_function_escape_special_chars($path_prefix . $file) . '" alt="' . $alt
. '" width="' . smarty_function_escape_special_chars($width) . '" height="'
. smarty_function_escape_special_chars($height) . '"' . $extra . ' />' . $suffix;
return $prefix . '<img src="' . $path_prefix . $file . '" alt="' . $alt . '" width="' . $width . '" height="' .
$height . '"' . $extra . ' />' . $suffix;
}
}
+3 -7
View File
@@ -120,6 +120,9 @@ class HtmlSelectDate extends Base {
case 'day_value_format':
case 'month_format':
case 'month_value_format':
case 'day_size':
case 'month_size':
case 'year_size':
case 'all_extra':
case 'day_extra':
case 'month_extra':
@@ -137,13 +140,6 @@ class HtmlSelectDate extends Base {
case 'year_id':
$$_key = (string)$_value;
break;
case 'day_size':
case 'month_size':
case 'year_size':
// numeric HTML size attribute; cast to int (consistent with
// html_select_time) so it cannot break out of size="…" (CWE-79)
$$_key = (int)$_value;
break;
case 'display_days':
case 'display_months':
case 'display_years':
+1 -12
View File
@@ -54,19 +54,8 @@ class StreamPlugin extends RecompiledPlugin {
$filepath = str_replace(':', '://', $source->getFullResourceName());
}
// Validate the underlying stream wrapper against the security policy.
// When the built-in "stream" resource type is used (e.g.
// stream:php://filter/...), BasePlugin::load() matches the "stream"
// sysplugin before the stream_get_wrappers()/isTrustedStream() check,
// so the nested wrapper ("php" here) is never validated. Parse the
// wrapper scheme from the resolved path and check it explicitly so that
// e.g. Security::$streams = null blocks it before fopen() (CWE-22/-441).
$smarty = $source->getSmarty();
if (is_object($smarty->security_policy) && ($_pos = strpos($filepath, '://')) !== false) {
$smarty->security_policy->isTrustedStream(strtolower(substr($filepath, 0, $_pos)));
}
$t = '';
// the availability of the stream has already been checked in Smarty\Resource\Base::fetch()
$fp = fopen($filepath, 'r+');
if ($fp) {
while (!feof($fp) && ($current_line = fgets($fp)) !== false) {
+4 -30
View File
@@ -52,7 +52,7 @@ class Security {
/**
* This is an array of trusted static classes.
* If empty access to all static classes is allowed.
* To disable access to all static classes set $static_classes = null.
* If set to 'none' none is allowed.
*
* @var array
*/
@@ -206,11 +206,7 @@ class Security {
* @return boolean true if class is trusted
*/
public function isTrustedStaticClass($class_name, $compiler) {
// Only an array enables access: an empty array allows all classes, a
// populated array is an allowlist. Any other value (null, or the
// documented "none") denies all. Using is_array() rather than isset()
// also avoids a PHP 8 TypeError from passing a non-array to in_array().
if (is_array($this->static_classes)
if (isset($this->static_classes)
&& (empty($this->static_classes) || in_array($class_name, $this->static_classes))
) {
return true;
@@ -478,34 +474,12 @@ class Security {
* @throws \Smarty\Exception
*/
private function _checkDir($filepath, $dirs) {
// Resolve the canonical, symlink-free path of the requested file so that
// a symlink located inside a trusted directory cannot be abused to read
// a file outside of it (CWE-22 path traversal). Smarty::_realpath() only
// normalizes the path as a string and does not follow symlinks, so we
// fall back to it only when the file does not yet exist on disk (e.g.
// config/cache paths that are validated before being written).
$realpath = @realpath($filepath);
$resolved = $realpath !== false ? $realpath : $this->smarty->_realpath($filepath, true);
$directory = dirname($resolved) . DIRECTORY_SEPARATOR;
// Canonicalize the trusted directories the same way. This keeps
// legitimate symlinked deployment paths working (e.g. a Capistrano-style
// "current" release symlink, or macOS' /var -> /private/var): both the
// file and the trusted directories are compared after symlinks have been
// resolved.
$trusted = [];
foreach ($dirs as $dir => $unused) {
$trusted[$dir] = true;
if (($dirRealpath = @realpath($dir)) !== false) {
$trusted[rtrim($dirRealpath, '\\/') . DIRECTORY_SEPARATOR] = true;
}
}
$directory = dirname($this->smarty->_realpath($filepath, true)) . DIRECTORY_SEPARATOR;
$_directory = [];
if (!preg_match('#[\\\\/][.][.][\\\\/]#', $directory)) {
while (true) {
// test if the directory is trusted
if (isset($trusted[$directory])) {
if (isset($dirs[$directory])) {
return $_directory;
}
// abort if we've reached root
+1 -1
View File
@@ -54,7 +54,7 @@ class Smarty extends \Smarty\TemplateBase {
/**
* smarty version
*/
const SMARTY_VERSION = '5.8.4';
const SMARTY_VERSION = '5.7.0';
/**
* define caching modes
+2 -6
View File
@@ -260,11 +260,7 @@ class Template extends TemplateBase {
$tpl = $this->smarty->doCreateTemplate($template_name, $cache_id, $compile_id, $this, $caching, $cache_lifetime);
// Re-use the same Inheritance object only inside an active inheritance tree, i.e. when this
// (including) template already has one. A template outside any inheritance tree has no
// Inheritance object (null); sub-templates it {include}s must then start with their own, so an
// {include}d template that uses {block}/{extends} creates a fresh root via getInheritance().
$tpl->inheritance = $this->inheritance;
$tpl->inheritance = $this->getInheritance(); // re-use the same Inheritance object inside the inheritance tree
if ($scope) {
$tpl->defaultScope = $scope;
@@ -535,7 +531,7 @@ class Template extends TemplateBase {
*/
public function getRightDelimiter()
{
return $this->right_delimiter ?? $this->getSmarty()->getRightDelimiter();
return $this->right_delimiter ?? $this->getSmarty()->getRightDelimiter();;
}
/**
+1
View File
@@ -15,3 +15,4 @@ if (!ini_get('date.timezone')) {
}
+1
View File
@@ -6,6 +6,7 @@
/*
* Smarty PHPUnit Config
*/
define('individualFolders', true);
define('MysqlCacheEnable', false);
define('PdoCacheEnable', false);
define('PdoGzipCacheEnable', false);
+43 -127
View File
@@ -49,37 +49,6 @@ class PHPUnit_Smarty extends PHPUnit\Framework\TestCase
*/
public static $cwd = null;
/**
* Temp directory base for this test class (compile, cache, templates_tmp)
*
* @var string|null
*/
private static $tempBase = null;
/**
* Unique token for the current test class's temp directory.
* Generated once per class.
*
* @var string|null
*/
private static $tempId = null;
/**
* Return the temp directory base for the current test class.
*
* @return string
* @throws \LogicException If the temp directory base has not been initialized yet.
*/
public static function getTempBase(): string
{
if (self::$tempBase === null) {
throw new \LogicException(
'Temp directory base has not been initialized. Call setUpSmarty() before using temp-path helpers.'
);
}
return self::$tempBase;
}
/**
* PDO object for Mysql tests
*
@@ -106,37 +75,8 @@ class PHPUnit_Smarty extends PHPUnit\Framework\TestCase
*/
public static function tearDownAfterClass(): void
{
// Remove the unique temp directory for this test class unless the caller
// wants to inspect the artifacts (e.g. for debugging a failure).
if (!getenv('KEEP_SMARTY_TEST_ARTIFACTS') && self::$tempBase !== null && is_dir(self::$tempBase)) {
self::removeDir(self::$tempBase);
}
}
/**
* Recursively remove a directory, silently ignoring any errors.
*
* @param string $dir
*/
private static function removeDir(string $dir): void
{
$dir = rtrim($dir, DIRECTORY_SEPARATOR);
$items = @scandir($dir);
if ($items === false) {
return;
}
foreach ($items as $item) {
if ($item === '.' || $item === '..') {
continue;
}
$path = $dir . DIRECTORY_SEPARATOR . $item;
if (is_dir($path) && !is_link($path)) {
self::removeDir($path);
} else {
@unlink($path);
}
}
@rmdir($dir);
//self::$pdo = null;
self::$testNumber = 0;
}
/**
@@ -149,46 +89,12 @@ class PHPUnit_Smarty extends PHPUnit\Framework\TestCase
public function __construct($name = null, array $data = array(), $dataName = '')
{
date_default_timezone_set('Europe/Berlin');
if (!defined('individualFolders')) {
define('individualFolders', true);
}
parent::__construct($name, $data, $dataName);
}
/**
* Compute the temp directory base for a given test directory.
*
* Returns a path unique to this test class run under sys_get_temp_dir(),
* so that concurrent or sequential runs of different test classes never
* share compiled/cached output. The unique token is generated once per
* class lifetime and reset in tearDownAfterClass().
*
* Example:
* /path/to/smarty/tests/UnitTests/TagTests/If
* /tmp/smarty-tests/UnitTests/TagTests/If/<unique-id>/
*
* @param string $dir absolute test directory
* @return string absolute temp base directory (with trailing separator)
*/
private static function getTempDir($dir)
{
// Lazily generate a unique token for this test class.
if (self::$tempId === null) {
self::$tempId = uniqid('', true);
}
$testsRoot = realpath(__DIR__);
$realDir = realpath($dir) ?: $dir;
// compute relative path from tests/ root
if (strpos($realDir, $testsRoot) === 0) {
$relative = substr($realDir, strlen($testsRoot));
} else {
// fallback: use full path hash
$relative = DIRECTORY_SEPARATOR . md5($realDir);
}
return rtrim(sys_get_temp_dir(), DIRECTORY_SEPARATOR)
. DIRECTORY_SEPARATOR . 'smarty-tests'
. $relative
. DIRECTORY_SEPARATOR . self::$tempId
. DIRECTORY_SEPARATOR;
}
/**
* Setup Smarty instance called for each test
*
@@ -196,37 +102,47 @@ class PHPUnit_Smarty extends PHPUnit\Framework\TestCase
*/
public function setUpSmarty($dir)
{
static $s_dir;
// set up current working directory
chdir($dir);
self::$cwd = getcwd();
// compute temp base for this test directory
self::$tempBase = self::getTempDir($dir);
// create missing folders for test
if (self::$init) {
if (!is_dir(self::$tempBase . 'templates_c')) {
mkdir(self::$tempBase . 'templates_c', 0775, true);
if (!is_dir($dir . '/templates')) {
mkdir($dir . '/templates');
}
if (!is_dir(self::$tempBase . 'cache')) {
mkdir(self::$tempBase . 'cache', 0775, true);
if (!is_dir($dir . '/configs')) {
mkdir($dir . '/configs');
}
if (individualFolders != 'true') {
if (!isset($s_dir[ $dir ])) {
$this->cleanDir($dir . '/templates_c');
$this->cleanDir($dir . '/cache');
if (is_dir($dir . '/templates_tmp')) {
$this->cleanDir($dir . '/templates_tmp');
}
$s_dir[ $dir ] = true;
}
$dir = __DIR__;
}
if (!is_dir($dir . '/templates_c')) {
mkdir($dir . '/templates_c');
}
chmod($dir . '/templates_c', 0775);
if (!is_dir($dir . '/cache')) {
mkdir($dir . '/cache');
chmod($dir . '/cache', 0775);
}
if (!is_dir(self::$tempBase . 'templates_tmp')) {
mkdir(self::$tempBase . 'templates_tmp', 0775, true);
}
self::$init = false;
}
clearstatcache();
// instance Smarty class
$this->smarty = new \Smarty\Smarty();
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c');
$this->smarty->setCacheDir(self::getTempBase() . 'cache');
$this->smarty->addTemplateDir(self::getTempBase() . 'templates_tmp');
// Clean output dirs once at the start of each test class run
if (self::$testNumber === 0) {
$this->cleanDirs();
if (individualFolders != 'true') {
$this->smarty->setCompileDir(__DIR__ . '/templates_c');
$this->smarty->setCacheDir(__DIR__ . '/cache');
}
self::$testNumber++;
}
@@ -314,24 +230,24 @@ KEY `name` (`name`)
{
$this->cleanCompileDir();
$this->cleanCacheDir();
$templatesTmpDir = self::getTempBase() . 'templates_tmp';
if (is_dir($templatesTmpDir)) {
$this->cleanDir($templatesTmpDir);
if (is_dir(self::$cwd . '/templates_tmp')) {
$this->cleanDir(self::$cwd . '/templates_tmp');
}
}
$this->assertTrue(true);
}
/**
* Make temporary template file
*
*/
protected function makeTemplateFile($name, $code)
public function makeTemplateFile($name, $code)
{
file_put_contents(self::getTempBase() . 'templates_tmp' . '/' . $name, $code);
}
protected function removeTemplateFile($name)
{
unlink(self::getTempBase() . 'templates_tmp' . '/' . $name);
if (!is_dir(self::$cwd . '/templates_tmp')) {
mkdir(self::$cwd . '/templates_tmp');
chmod(self::$cwd . '/templates_tmp', 0775);
}
$fileName = self::$cwd . '/templates_tmp/' . "{$name}";
file_put_contents($fileName, $code);
}
/**
@@ -18,7 +18,6 @@ class TemplateNormalizationTest extends PHPUnit_Smarty
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
$this->smarty->setTemplateDir(__DIR__ . '/templates');
}
public function testGetTemplateDir()
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -18,6 +18,10 @@ class UndefinedTemplateVarTest extends PHPUnit_Smarty
$this->setUpSmarty(__DIR__);
}
public function testInit()
{
$this->cleanDirs();
}
/**
* Test Error suppression template fetched by Smarty object
*/
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -21,6 +21,10 @@ class FilterTest extends PHPUnit_Smarty
$this->setUpSmarty(__DIR__);
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test loaded filter
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -20,6 +20,10 @@ class GetterSetterTest extends PHPUnit_Smarty
$this->setUpSmarty(__DIR__);
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test setter on Smarty object
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -24,6 +24,10 @@ class DefaultPluginHandlerTest extends PHPUnit_Smarty
}
public function testInit()
{
$this->cleanDirs();
}
public function testDefaultFunctionScript()
{
$this->assertEquals("scriptfunction foo bar", $this->smarty->fetch('test_default_function_script.tpl'));
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -21,6 +21,10 @@ class HttpModifiedSinceTest extends PHPUnit_Smarty
$this->setUpSmarty(__DIR__);
}
public function testInit()
{
$this->cleanDirs();
}
/**
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -25,6 +25,11 @@ class CacheResourceFileTest extends CacheResourceTestCommon
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test getCachedFilepath with configuration['useSubDirs'] enabled
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -32,6 +32,10 @@ class CacheResourceCustomMemcacheTest extends CacheResourceTestCommon
$this->smarty->setCachingType('memcachetest');
}
public function testInit()
{
$this->cleanDirs();
}
protected function doClearCacheAssertion($a, $b)
{
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -29,11 +29,15 @@ if (MysqlCacheEnable == true) {
$this->getConnection();
}
$this->setUpSmarty(__DIR__);
$this->initMysqlCache();
parent::setUp();
$this->smarty->setCachingType('mysqltest');
}
public function testInit()
{
$this->cleanDirs();
$this->initMysqlCache();
}
}
}
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -28,11 +28,15 @@ class CacheResourceCustomPDOTest extends CacheResourceTestCommon
$this->getConnection();
}
$this->setUpSmarty(__DIR__);
$this->initMysqlCache();
parent::setUp();
$this->smarty->registerCacheResource('pdo',
new Smarty_CacheResource_Pdotest($this->getPDO(), 'output_cache'));
}
public function testInit()
{
$this->cleanDirs();
$this->initMysqlCache();
}
}
@@ -2,7 +2,7 @@
use Smarty\Template\Cached;
require_once __DIR__ . '/../_shared/cacheresources/cacheresource.pdo.php';
require_once __DIR__ . '/../../__shared/cacheresources/cacheresource.pdo.php';
class Smarty_CacheResource_Pdotest extends Smarty_CacheResource_Pdo
{
@@ -27,12 +27,16 @@ class CacheResourceCustomPDOGzipTest extends CacheResourceTestCommon
$this->getConnection();
}
$this->setUpSmarty(__DIR__);
$this->initMysqlCache();
parent::setUp();
$this->smarty->setCachingType('pdo');
$this->smarty->registerCacheResource('pdo', new Smarty_CacheResource_Pdo_Gziptest($this->getPDO(),
'output_cache'));
}
public function testInit()
{
$this->cleanDirs();
$this->initMysqlCache();
}
}
@@ -2,7 +2,7 @@
use Smarty\Template\Cached;
require_once __DIR__ . '/../_shared/cacheresources/cacheresource.pdo_gzip.php';
require_once __DIR__ . '/../../__shared/cacheresources/cacheresource.pdo_gzip.php';
class Smarty_CacheResource_Pdo_Gziptest extends Smarty_CacheResource_Pdo_Gzip
{
@@ -26,7 +26,6 @@ if (MysqlCacheEnable == true) {
$this->getConnection();
}
$this->setUpSmarty(__DIR__);
$this->initMysqlCache();
parent::setUp();
if (!class_exists('Smarty_CacheResource_Mysqltest', false)) {
require_once(__DIR__ . "/../_shared/PHPunitplugins/cacheresource.mysqltest.php");
@@ -35,6 +34,11 @@ if (MysqlCacheEnable == true) {
$this->smarty->registerCacheResource('foobar', new Smarty_CacheResource_Mysqltest());
}
public function testInit()
{
$this->cleanDirs();
$this->initMysqlCache();
}
}
}
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -3,7 +3,7 @@
use Smarty\Template;
use Smarty\Template\Cached;
require_once __DIR__ . '/../cacheresources/cacheresource.memcache.php';
require_once __DIR__ . '/../../../__shared/cacheresources/cacheresource.memcache.php';
class Smarty_CacheResource_Memcachetest extends Smarty_CacheResource_Memcache
{
@@ -3,7 +3,7 @@
use Smarty\Exception;
use Smarty\Template\Cached;
require_once __DIR__ . '/../cacheresources/cacheresource.mysql.php';
require_once __DIR__ . '/../../../__shared/cacheresources/cacheresource.mysql.php';
class Smarty_CacheResource_Mysqltest extends Smarty_CacheResource_Mysql
{
@@ -20,6 +20,10 @@ class CompileCompilerPluginTest extends PHPUnit_Smarty
$this->setUpSmarty(__DIR__);
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test compiler plugin tag in template file
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -17,9 +17,13 @@ class AutoliteralTest extends PHPUnit_Smarty
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
$this->smarty->addPluginsDir("./plugins/");
$this->smarty->addPluginsDir("../../__shared/PHPunitplugins/");
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test '{ ' delimiter
@@ -20,6 +20,10 @@ class DelimiterTest extends PHPUnit_Smarty
$this->setUpSmarty(__DIR__);
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test <{ }> delimiter
@@ -17,9 +17,17 @@ class UserliteralTest extends PHPUnit_Smarty
{
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
if (!property_exists('Smarty', 'literals')) {
$this->markTestSkipped('user literal support');
} else {
$this->setUpSmarty(__DIR__);
}
}
public function testInit()
{
$this->cleanDirs();
}
public function testUserLiteral()
{
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -28,6 +28,10 @@ class ConfigVarTest extends PHPUnit_Smarty
/**
* empty templat_c and cache folders
*/
public function testInit()
{
$this->cleanDirs();
}
/**
* test number config variable
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -25,6 +25,10 @@ class CustomResourceAmbiguousTest extends PHPUnit_Smarty
// Smarty::$_resource_cache = array();
}
public function testInit()
{
$this->cleanDirs();
}
protected function relative($path)
{
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -6,7 +6,7 @@
* @author Uwe Tews
*/
require_once __DIR__ . '/resources/resource.extendsall.php';
require_once __DIR__ . '/../../../__shared/resources/resource.extendsall.php';
/**
* class for demo resource plugin extendsall tests
@@ -22,6 +22,10 @@ class ResourceExtendsAllPluginTest extends PHPUnit_Smarty
$this->setUpSmarty(__DIR__);
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test extendsall
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -24,9 +24,17 @@ if (MysqlResourceEnable == true) {
$this->getConnection();
}
$this->setUpSmarty(__DIR__);
$this->smarty->addPluginsDir("./PHPunitplugins/");
}
/**
*
*/
public function testInit()
{
$this->cleanDirs();
$this->initMysqlResource();
PHPUnit_Smarty::$pdo->exec("REPLACE INTO templates (name, source) VALUES ('test.tpl', '{\$x = \'hello world\'}{\$x}')");
$this->smarty->addPluginsDir("./PHPunitplugins/");
}
/**
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -23,6 +23,10 @@ class DefaultTemplateHandlerTest extends PHPUnit_Smarty
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test error on unknow template
*/
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -21,6 +21,10 @@ class EvalResourceTest extends PHPUnit_Smarty
}
public function testInit()
{
$this->cleanDirs();
}
/**
* test template eval exits
*/
@@ -65,6 +69,15 @@ class EvalResourceTest extends PHPUnit_Smarty
$this->assertEquals('', $this->smarty->fetch($tpl));
}
/**
* test usesCompiler
*/
public function testUsesCompiler()
{
$tpl = $this->smarty->createTemplate('eval:hello world');
$this->markTestIncomplete();
}
/**
* test isEvaluated
*/
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -20,6 +20,10 @@ class ExtendsResourceTest extends PHPUnit_Smarty
}
public function testInit()
{
$this->cleanDirs();
}
public function compiledPrefilter($text, Template $tpl)
{
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -23,6 +23,10 @@ class FileResourceTest extends PHPUnit_Smarty
$this->smarty->enableSecurity();
}
public function testInit()
{
$this->cleanDirs();
}
protected function relative($path)
{
@@ -86,6 +90,12 @@ class FileResourceTest extends PHPUnit_Smarty
$this->assertEquals('hello world', $tpl->getSource()->getContent());
}
public function testUsesCompiler()
{
$tpl = $this->smarty->createTemplate('helloworld.tpl');
$this->markTestIncomplete();
}
public function testIsEvaluated()
{
$tpl = $this->smarty->createTemplate('helloworld.tpl');
@@ -161,7 +171,8 @@ class FileResourceTest extends PHPUnit_Smarty
$tpl->fetch();
$timestamp = $tpl->getCached()->timestamp;
$this->setUpSmarty(__DIR__);
$this->smarty = new \Smarty\Smarty();
$this->smarty->caching = true;
$this->smarty->cache_lifetime = 1000;
@@ -260,8 +271,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
chdir(__DIR__ . '/templates/sub/');
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
$this->smarty->setTemplateDir(array(
__DIR__ . '/does-not-exist/',
));
@@ -281,8 +292,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
chdir(__DIR__ . '/templates/sub/');
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
$this->smarty->setTemplateDir(array(
__DIR__ . '/does-not-exist/',
));
@@ -337,8 +348,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
$this->smarty->setTemplateDir(array($dn . '/templates/relativity/theory/',));
$map = array('foo.tpl' => 'theory', './foo.tpl' => 'theory', '././foo.tpl' => 'theory',
@@ -356,8 +367,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
$this->smarty->setTemplateDir(array(
@@ -388,8 +399,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
chdir($dn . '/templates/relativity/theory/');
$this->smarty->setTemplateDir(array(
$dn . '/templates/',
@@ -417,8 +428,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
$this->smarty->setTemplateDir(array($dn . '/templates/relativity/theory/einstein/',));
$map = array('foo.tpl' => 'einstein', './foo.tpl' => 'einstein', '././foo.tpl' => 'einstein',
@@ -437,8 +448,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
$this->smarty->setTemplateDir(array(
$dn . '/templates/relativity/theory/einstein/',
));
@@ -468,8 +479,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
$this->smarty->setTemplateDir(array('../..',));
$map = array('foo.tpl' => 'relativity', './foo.tpl' => 'relativity', '././foo.tpl' => 'relativity',);
@@ -486,8 +497,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
$this->smarty->setTemplateDir(array('../..',));
$map =
@@ -505,8 +516,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
$this->smarty->setTemplateDir(array(
'../..',
));
@@ -538,8 +549,8 @@ class FileResourceTest extends PHPUnit_Smarty
$cwd = getcwd();
$dn = __DIR__;
$this->smarty->setCompileDir(self::getTempBase() . 'templates_c/');
$this->smarty->setCacheDir(self::getTempBase() . 'cache/');
$this->smarty->setCompileDir($dn . '/templates_c/');
$this->smarty->setCacheDir($dn . '/cache/');
$this->smarty->setTemplateDir(array(
'..',
));
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*
@@ -14,13 +14,16 @@ class FileResourceIndexedTest extends PHPUnit_Smarty
public function setUp(): void
{
$this->setUpSmarty(__DIR__);
$this->smarty->setTemplateDir(__DIR__ . '/templates');
$this->smarty->addTemplateDir(__DIR__ . '/templates_2');
// note that 10 is a string!
$this->smarty->addTemplateDir(__DIR__ . '/templates_3', '10');
$this->smarty->addTemplateDir(__DIR__ . '/templates_4', 'foo');
}
public function testInit()
{
$this->cleanDirs();
}
public function testFetch()
{
@@ -0,0 +1,2 @@
# Ignore anything in here, but keep this directory
*

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