diff --git a/common/framework/Template.php b/common/framework/Template.php
index 9d743d069..0443918cf 100644
--- a/common/framework/Template.php
+++ b/common/framework/Template.php
@@ -13,9 +13,16 @@ class Template
public $user;
/**
- * Properties for internal use
+ * Properties for configuration
*/
public $config;
+ public $source_type;
+ public $parent;
+ public $vars;
+
+ /**
+ * Properties for path manipulation
+ */
public $absolute_dirname;
public $relative_dirname;
public $filename;
@@ -23,17 +30,23 @@ class Template
public $exists;
public $absolute_path;
public $relative_path;
- public $cache_path;
+
+ /**
+ * Properties for caching
+ */
public $cache_enabled = true;
- public $source_type;
- public $ob_level;
- public $vars;
+ public $cache_path;
+
+ /**
+ * Properties for state management during compilation/execution
+ */
+ protected $_ob_level;
protected $_fragments = [];
protected static $_loopvars = [];
protected static $_stacks = [];
/**
- * Static properties
+ * Properties for optimization
*/
protected static $_mtime;
protected static $_delay_compile;
@@ -191,6 +204,27 @@ class Template
return $this->exists ? true : false;
}
+ /**
+ * Get the parent template.
+ *
+ * @return ?self
+ */
+ public function getParent(): ?self
+ {
+ return $this->parent;
+ }
+
+ /**
+ * Set the parent template.
+ *
+ * @param ?self $parent
+ * @return void
+ */
+ public function setParent(self $parent): void
+ {
+ $this->parent = $parent;
+ }
+
/**
* Get vars.
*
@@ -395,7 +429,7 @@ class Template
$__Context = $this->vars ?: \Context::getAll();
// Start the output buffer.
- $this->ob_level = ob_get_level();
+ $this->_ob_level = ob_get_level();
ob_start();
// Include the compiled template.
@@ -403,7 +437,7 @@ class Template
// Fetch the content of the output buffer until the buffer level is the same as before.
$content = '';
- while (ob_get_level() > $this->ob_level)
+ while (ob_get_level() > $this->_ob_level)
{
$content .= ob_get_clean();
}
@@ -571,6 +605,7 @@ class Template
}
// Set variables.
+ $template->setParent($this);
if ($this->vars)
{
$template->setVars($this->vars);
diff --git a/common/framework/parsers/template/TemplateParser_v2.php b/common/framework/parsers/template/TemplateParser_v2.php
index e2d87b6ea..890fac53a 100644
--- a/common/framework/parsers/template/TemplateParser_v2.php
+++ b/common/framework/parsers/template/TemplateParser_v2.php
@@ -407,7 +407,7 @@ class TemplateParser_v2
// Generate the code to create a new Template object and compile it.
$tpl = 'template->extension ?: 'auto') . '"); ';
- $tpl .= 'if ($this->vars): $__tpl->setVars($this->vars); endif; ';
+ $tpl .= '$__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; ';
$tpl .= !empty($attrs['vars']) ? '$__tpl->addVars(' . self::_convertVariableScope($attrs['vars']) . '); ' : '';
$tpl .= 'echo $__tpl->compile(); ?>';
diff --git a/tests/unit/framework/parsers/TemplateParserV2Test.php b/tests/unit/framework/parsers/TemplateParserV2Test.php
index 987465352..80a58389b 100644
--- a/tests/unit/framework/parsers/TemplateParserV2Test.php
+++ b/tests/unit/framework/parsers/TemplateParserV2Test.php
@@ -50,42 +50,42 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
{
// Basic usage
$source = '';
- $target = 'relative_dirname, "foobar", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
+ $target = 'relative_dirname, "foobar", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
$this->assertEquals($target, $this->_parse($source));
// Legacy 'target' attribute
$source = '';
- $target = 'normalizePath($this->relative_dirname . "subdir"), "foobar", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
+ $target = 'normalizePath($this->relative_dirname . "subdir"), "foobar", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
$this->assertEquals($target, $this->_parse($source));
// Conditional include
$source = '';
- $target = 'normalizePath($this->relative_dirname . "../up"), "foobar", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
+ $target = 'normalizePath($this->relative_dirname . "../up"), "foobar", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
$this->assertEquals($target, $this->_parse($source));
// Conditional include with legacy 'cond' attribute
$source = '';
- $target = 'normalizePath($this->relative_dirname . "legacy"), "cond.statement.html", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
+ $target = 'normalizePath($this->relative_dirname . "legacy"), "cond.statement.html", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
$this->assertEquals($target, $this->_parse($source));
// Path relative to Rhymix installation directory
$source = '';
- $target = 'vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
+ $target = 'setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
$this->assertEquals($target, $this->_parse($source));
// Unless
$source = '';
- $target = 'vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
+ $target = 'setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
$this->assertEquals($target, $this->_parse($source));
// With variables
$source = '';
- $target = 'relative_dirname, "foobar", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; $__tpl->addVars($__Context->vars); echo $__tpl->compile(); ?>';
+ $target = 'relative_dirname, "foobar", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; $__tpl->addVars($__Context->vars); echo $__tpl->compile(); ?>';
$this->assertEquals($target, $this->_parse($source));
// With array literal passed as variables
$source = '';
- $target = 'relative_dirname, "foobar", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; $__tpl->addVars([\'foo\' => \'bar\']); echo $__tpl->compile(); ?>';
+ $target = 'relative_dirname, "foobar", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; $__tpl->addVars([\'foo\' => \'bar\']); echo $__tpl->compile(); ?>';
$this->assertEquals($target, $this->_parse($source));
// Blade-style @include
@@ -1071,7 +1071,11 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
// cond is OK in includes
$source = '';
- $target = 'relative_dirname, "foo.html", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';;
+ $target = implode(' ', [
+ 'relative_dirname, "foo.html", "html");',
+ '$__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif;',
+ 'echo $__tpl->compile(); ?>',
+ ]);
$this->assertEquals($target, $this->_parse($source));
// loop