Add parent reference to Template instances

This commit is contained in:
Kijin Sung 2023-10-22 00:46:58 +09:00
parent 4054dec926
commit a5d6a76cf4
3 changed files with 57 additions and 18 deletions

View file

@ -13,9 +13,16 @@ class Template
public $user; public $user;
/** /**
* Properties for internal use * Properties for configuration
*/ */
public $config; public $config;
public $source_type;
public $parent;
public $vars;
/**
* Properties for path manipulation
*/
public $absolute_dirname; public $absolute_dirname;
public $relative_dirname; public $relative_dirname;
public $filename; public $filename;
@ -23,17 +30,23 @@ class Template
public $exists; public $exists;
public $absolute_path; public $absolute_path;
public $relative_path; public $relative_path;
public $cache_path;
/**
* Properties for caching
*/
public $cache_enabled = true; public $cache_enabled = true;
public $source_type; public $cache_path;
public $ob_level;
public $vars; /**
* Properties for state management during compilation/execution
*/
protected $_ob_level;
protected $_fragments = []; protected $_fragments = [];
protected static $_loopvars = []; protected static $_loopvars = [];
protected static $_stacks = []; protected static $_stacks = [];
/** /**
* Static properties * Properties for optimization
*/ */
protected static $_mtime; protected static $_mtime;
protected static $_delay_compile; protected static $_delay_compile;
@ -191,6 +204,27 @@ class Template
return $this->exists ? true : false; 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. * Get vars.
* *
@ -395,7 +429,7 @@ class Template
$__Context = $this->vars ?: \Context::getAll(); $__Context = $this->vars ?: \Context::getAll();
// Start the output buffer. // Start the output buffer.
$this->ob_level = ob_get_level(); $this->_ob_level = ob_get_level();
ob_start(); ob_start();
// Include the compiled template. // 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. // Fetch the content of the output buffer until the buffer level is the same as before.
$content = ''; $content = '';
while (ob_get_level() > $this->ob_level) while (ob_get_level() > $this->_ob_level)
{ {
$content .= ob_get_clean(); $content .= ob_get_clean();
} }
@ -571,6 +605,7 @@ class Template
} }
// Set variables. // Set variables.
$template->setParent($this);
if ($this->vars) if ($this->vars)
{ {
$template->setVars($this->vars); $template->setVars($this->vars);

View file

@ -407,7 +407,7 @@ class TemplateParser_v2
// Generate the code to create a new Template object and compile it. // Generate the code to create a new Template object and compile it.
$tpl = '<?php $__tpl = new \Rhymix\Framework\Template(' . $dir . ', "' . $path . '", "' . ($this->template->extension ?: 'auto') . '"); '; $tpl = '<?php $__tpl = new \Rhymix\Framework\Template(' . $dir . ', "' . $path . '", "' . ($this->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 .= !empty($attrs['vars']) ? '$__tpl->addVars(' . self::_convertVariableScope($attrs['vars']) . '); ' : '';
$tpl .= 'echo $__tpl->compile(); ?>'; $tpl .= 'echo $__tpl->compile(); ?>';

View file

@ -50,42 +50,42 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
{ {
// Basic usage // Basic usage
$source = '<include src="foobar" />'; $source = '<include src="foobar" />';
$target = '<?php $__tpl = new \Rhymix\Framework\Template($this->relative_dirname, "foobar", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>'; $target = '<?php $__tpl = new \Rhymix\Framework\Template($this->relative_dirname, "foobar", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>';
$this->assertEquals($target, $this->_parse($source)); $this->assertEquals($target, $this->_parse($source));
// Legacy 'target' attribute // Legacy 'target' attribute
$source = '<include target="subdir/foobar" />'; $source = '<include target="subdir/foobar" />';
$target = '<?php $__tpl = new \Rhymix\Framework\Template($this->normalizePath($this->relative_dirname . "subdir"), "foobar", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?>'; $target = '<?php $__tpl = new \Rhymix\Framework\Template($this->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)); $this->assertEquals($target, $this->_parse($source));
// Conditional include // Conditional include
$source = '<include src="../up/foobar" if="$cond" />'; $source = '<include src="../up/foobar" if="$cond" />';
$target = '<?php if(!empty($cond)): ?><?php $__tpl = new \Rhymix\Framework\Template($this->normalizePath($this->relative_dirname . "../up"), "foobar", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?><?php endif; ?>'; $target = '<?php if(!empty($cond)): ?><?php $__tpl = new \Rhymix\Framework\Template($this->normalizePath($this->relative_dirname . "../up"), "foobar", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?><?php endif; ?>';
$this->assertEquals($target, $this->_parse($source)); $this->assertEquals($target, $this->_parse($source));
// Conditional include with legacy 'cond' attribute // Conditional include with legacy 'cond' attribute
$source = '<include target="legacy/cond.statement.html" cond="$cond" />'; $source = '<include target="legacy/cond.statement.html" cond="$cond" />';
$target = '<?php if(!empty($cond)): ?><?php $__tpl = new \Rhymix\Framework\Template($this->normalizePath($this->relative_dirname . "legacy"), "cond.statement.html", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?><?php endif; ?>'; $target = '<?php if(!empty($cond)): ?><?php $__tpl = new \Rhymix\Framework\Template($this->normalizePath($this->relative_dirname . "legacy"), "cond.statement.html", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?><?php endif; ?>';
$this->assertEquals($target, $this->_parse($source)); $this->assertEquals($target, $this->_parse($source));
// Path relative to Rhymix installation directory // Path relative to Rhymix installation directory
$source = '<include src="^/modules/foobar/views/baz" when="$cond" />'; $source = '<include src="^/modules/foobar/views/baz" when="$cond" />';
$target = '<?php if(!empty($cond)): ?><?php $__tpl = new \Rhymix\Framework\Template("modules/foobar/views", "baz", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?><?php endif; ?>'; $target = '<?php if(!empty($cond)): ?><?php $__tpl = new \Rhymix\Framework\Template("modules/foobar/views", "baz", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?><?php endif; ?>';
$this->assertEquals($target, $this->_parse($source)); $this->assertEquals($target, $this->_parse($source));
// Unless // Unless
$source = '<include src="^/modules/foobar/views/baz" unless="$cond" />'; $source = '<include src="^/modules/foobar/views/baz" unless="$cond" />';
$target = '<?php if(empty($cond)): ?><?php $__tpl = new \Rhymix\Framework\Template("modules/foobar/views", "baz", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?><?php endif; ?>'; $target = '<?php if(empty($cond)): ?><?php $__tpl = new \Rhymix\Framework\Template("modules/foobar/views", "baz", "html"); $__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?><?php endif; ?>';
$this->assertEquals($target, $this->_parse($source)); $this->assertEquals($target, $this->_parse($source));
// With variables // With variables
$source = '<include src="foobar" vars="$vars" />'; $source = '<include src="foobar" vars="$vars" />';
$target = '<?php $__tpl = new \Rhymix\Framework\Template($this->relative_dirname, "foobar", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; $__tpl->addVars($__Context->vars); echo $__tpl->compile(); ?>'; $target = '<?php $__tpl = new \Rhymix\Framework\Template($this->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)); $this->assertEquals($target, $this->_parse($source));
// With array literal passed as variables // With array literal passed as variables
$source = '<include src="foobar" vars="[\'foo\' => \'bar\']" />'; $source = '<include src="foobar" vars="[\'foo\' => \'bar\']" />';
$target = '<?php $__tpl = new \Rhymix\Framework\Template($this->relative_dirname, "foobar", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; $__tpl->addVars([\'foo\' => \'bar\']); echo $__tpl->compile(); ?>'; $target = '<?php $__tpl = new \Rhymix\Framework\Template($this->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)); $this->assertEquals($target, $this->_parse($source));
// Blade-style @include // Blade-style @include
@ -1071,7 +1071,11 @@ class TemplateParserV2Test extends \Codeception\Test\Unit
// cond is OK in includes // cond is OK in includes
$source = '<include src="foo.html" cond="$bar" />'; $source = '<include src="foo.html" cond="$bar" />';
$target = '<?php if(!empty($bar)): ?><?php $__tpl = new \Rhymix\Framework\Template($this->relative_dirname, "foo.html", "html"); if ($this->vars): $__tpl->setVars($this->vars); endif; echo $__tpl->compile(); ?><?php endif; ?>';; $target = implode(' ', [
'<?php if(!empty($bar)): ?><?php $__tpl = new \Rhymix\Framework\Template($this->relative_dirname, "foo.html", "html");',
'$__tpl->setParent($this); if ($this->vars): $__tpl->setVars($this->vars); endif;',
'echo $__tpl->compile(); ?><?php endif; ?>',
]);
$this->assertEquals($target, $this->_parse($source)); $this->assertEquals($target, $this->_parse($source));
// loop // loop