mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-03 01:44:26 +02:00
Fix code duplication in block compilers and fix (most) BlockPluginTests. Default plugin handler blocks still need fixing.
This commit is contained in:
@@ -13,6 +13,6 @@ class BlockPluginWrapper implements BlockHandlerInterface {
|
||||
}
|
||||
|
||||
public function handle($params, $content, Template $template, &$repeat) {
|
||||
return call_user_func($this->callback, $params, $content, $template, $repeat);
|
||||
return call_user_func_array($this->callback, [$params, $content, $template, &$repeat]);
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Smarty\BlockHandler;
|
||||
|
||||
use Smarty\Smarty;
|
||||
use Smarty\Template;
|
||||
|
||||
/**
|
||||
@@ -78,8 +79,8 @@ class TextFormat implements BlockHandlerInterface {
|
||||
$_paragraph =
|
||||
preg_replace(
|
||||
array(
|
||||
'!\s+!' . \Smarty::$_UTF8_MODIFIER,
|
||||
'!(^\s+)|(\s+$)!' . \Smarty::$_UTF8_MODIFIER
|
||||
'!\s+!' . Smarty::$_UTF8_MODIFIER,
|
||||
'!(^\s+)|(\s+$)!' . Smarty::$_UTF8_MODIFIER
|
||||
),
|
||||
array(
|
||||
' ',
|
||||
|
@@ -10,6 +10,10 @@
|
||||
|
||||
namespace Smarty\Compile;
|
||||
|
||||
use Smarty\Compiler\Template;
|
||||
use Smarty\CompilerException;
|
||||
use Smarty\Exception;
|
||||
|
||||
/**
|
||||
* Smarty Internal Plugin Compile Block Plugin Class
|
||||
*
|
||||
@@ -33,78 +37,117 @@ class BlockCompiler extends Base {
|
||||
*/
|
||||
public $nesting = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Compiles code for the execution of block plugin
|
||||
*
|
||||
* @param array $args array with attributes from parser
|
||||
* @param \Smarty\Compiler\Template $compiler compiler object
|
||||
* @param Template $compiler compiler object
|
||||
* @param array $parameter array with compilation parameter
|
||||
* @param string $tag name of block plugin
|
||||
* @param string $function PHP function name
|
||||
*
|
||||
* @return string compiled code
|
||||
* @throws \Smarty\CompilerException
|
||||
* @throws \Smarty\Exception
|
||||
* @throws CompilerException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) {
|
||||
public function compile($args, Template $compiler, $parameter = [], $tag = null, $function = null) {
|
||||
|
||||
if (!isset($tag[5]) || substr($tag, -5) !== 'close') {
|
||||
// opening tag of block plugin
|
||||
// check and get attributes
|
||||
$_attr = $this->getAttributes($compiler, $args);
|
||||
$this->nesting++;
|
||||
unset($_attr['nocache']);
|
||||
[$callback, $_paramsArray, $callable] = $this->setup($compiler, $_attr, $tag, $function);
|
||||
$_params = 'array(' . implode(',', $_paramsArray) . ')';
|
||||
// compile code
|
||||
$output = "<?php ";
|
||||
if (is_array($callback)) {
|
||||
$output .= "\$_block_plugin{$this->nesting} = isset({$callback[0]}) ? {$callback[0]} : null;\n";
|
||||
$callback = "\$_block_plugin{$this->nesting}{$callback[1]}";
|
||||
}
|
||||
if (isset($callable)) {
|
||||
$output .= "if (!is_callable({$callable})) {\nthrow new \\Smarty\\Exception('block tag \'{$tag}\' not callable or registered');\n}\n";
|
||||
}
|
||||
$output .= "\$_block_repeat=true;\necho {$callback}({$_params}, null, \$_smarty_tpl, \$_block_repeat);\nwhile (\$_block_repeat) {\nob_start();?>";
|
||||
$this->openTag($compiler, $tag, [$_params, $compiler->nocache, $callback]);
|
||||
// maybe nocache because of nocache variables or nocache plugin
|
||||
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
|
||||
$output = $this->compileOpeningTag($compiler, $args, $tag, $function);
|
||||
} else {
|
||||
// must endblock be nocache?
|
||||
if ($compiler->nocache) {
|
||||
$compiler->tag_nocache = true;
|
||||
}
|
||||
// closing tag of block plugin, restore nocache
|
||||
[$_params, $compiler->nocache, $callback] = $this->closeTag($compiler, substr($tag, 0, -5));
|
||||
// compile code
|
||||
if (!isset($parameter['modifier_list'])) {
|
||||
$mod_pre = $mod_post = $mod_content = '';
|
||||
$mod_content2 = 'ob_get_clean()';
|
||||
} else {
|
||||
$mod_content2 = "\$_block_content{$this->nesting}";
|
||||
$mod_content = "\$_block_content{$this->nesting} = ob_get_clean();\n";
|
||||
$mod_pre = "ob_start();\n";
|
||||
$mod_post = 'echo ' . $compiler->compileModifier($parameter['modifier_list'], 'ob_get_clean()')
|
||||
. ";\n";
|
||||
}
|
||||
$output =
|
||||
"<?php {$mod_content}\$_block_repeat=false;\n{$mod_pre}echo {$callback}({$_params}, {$mod_content2}, \$_smarty_tpl, \$_block_repeat);\n{$mod_post}}\n";
|
||||
$output .= '?>';
|
||||
$output = $this->compileClosingTag($compiler, $tag, $parameter, $function);
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup callback and parameter array
|
||||
* Returns the code used for the isset check
|
||||
*
|
||||
* @param \Smarty\Compiler\Template $compiler
|
||||
* @param array $_attr attributes
|
||||
* @param string $tag
|
||||
* @param string $function
|
||||
* @param string $tag tag name
|
||||
* @param string $function base tag or method name
|
||||
*
|
||||
* @return array
|
||||
* @return string
|
||||
*/
|
||||
protected function setup(\Smarty\Compiler\Template $compiler, $_attr, $tag, $function) {
|
||||
$_paramsArray = $this->formatParamsArray($_attr);
|
||||
return [$function, $_paramsArray, null];
|
||||
protected function getIsCallableCode($tag, $function): string {
|
||||
return "\$_smarty_tpl->smarty->getBlockHandler(" . var_export($function, true) . ")";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full code used to call the callback
|
||||
*
|
||||
* @param string $tag tag name
|
||||
* @param string $function base tag or method name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getFullCallbackCode($tag, $function): string {
|
||||
return "\$_smarty_tpl->smarty->getBlockHandler(" . var_export($function, true) . ")->handle";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Template $compiler
|
||||
* @param array $args
|
||||
* @param string|null $tag
|
||||
* @param string|null $function
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function compileOpeningTag(Template $compiler, array $args, ?string $tag, ?string $function): string {
|
||||
|
||||
// check and get attributes
|
||||
$_attr = $this->getAttributes($compiler, $args);
|
||||
$this->nesting++;
|
||||
unset($_attr['nocache']);
|
||||
$_params = 'array(' . implode(',', $this->formatParamsArray($_attr)) . ')';
|
||||
|
||||
// compile code
|
||||
$output = "<?php \$_block_repeat=true;
|
||||
if (!" . $this->getIsCallableCode($tag, $function) .") {\nthrow new \\Smarty\\Exception('block tag \'{$tag}\' not callable or registered');\n}\n
|
||||
echo " . $this->getFullCallbackCode($tag, $function) . "({$_params}, null, \$_smarty_tpl, \$_block_repeat);
|
||||
while (\$_block_repeat) {
|
||||
ob_start();
|
||||
?>";
|
||||
$this->openTag($compiler, $tag, [$_params, $compiler->nocache]);
|
||||
// maybe nocache because of nocache variables or nocache plugin
|
||||
$compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Template $compiler
|
||||
* @param string $tag
|
||||
* @param array $parameter
|
||||
* @param string|null $function
|
||||
*
|
||||
* @return string
|
||||
* @throws CompilerException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function compileClosingTag(Template $compiler, string $tag, array $parameter, ?string $function): string {
|
||||
// must endblock be nocache?
|
||||
if ($compiler->nocache) {
|
||||
$compiler->tag_nocache = true;
|
||||
}
|
||||
// closing tag of block plugin, restore nocache
|
||||
$base_tag = substr($tag, 0, -5);
|
||||
[$_params, $compiler->nocache] = $this->closeTag($compiler, $base_tag);
|
||||
// compile code
|
||||
if (!isset($parameter['modifier_list'])) {
|
||||
$mod_pre = $mod_post = $mod_content = '';
|
||||
$mod_content2 = 'ob_get_clean()';
|
||||
} else {
|
||||
$mod_content2 = "\$_block_content{$this->nesting}";
|
||||
$mod_content = "\$_block_content{$this->nesting} = ob_get_clean();\n";
|
||||
$mod_pre = "ob_start();\n";
|
||||
$mod_post = 'echo ' . $compiler->compileModifier($parameter['modifier_list'], 'ob_get_clean()')
|
||||
. ";\n";
|
||||
}
|
||||
$output = "<?php {$mod_content}\$_block_repeat=false;\n{$mod_pre}";
|
||||
$callback = $this->getFullCallbackCode($base_tag, $function);
|
||||
$output .= "echo {$callback}({$_params}, {$mod_content2}, \$_smarty_tpl, \$_block_repeat);\n";
|
||||
$output .= "{$mod_post}}\n?>";
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -11,6 +11,8 @@
|
||||
namespace Smarty\Compile;
|
||||
|
||||
use Smarty\Compiler\Template;
|
||||
use Smarty\CompilerException;
|
||||
use Smarty\Exception;
|
||||
|
||||
/**
|
||||
* Smarty Internal Plugin Compile Object Block Function Class
|
||||
@@ -21,18 +23,19 @@ use Smarty\Compiler\Template;
|
||||
class ObjectMethodBlockCompiler extends BlockCompiler {
|
||||
|
||||
/**
|
||||
* Setup callback and parameter array
|
||||
*
|
||||
* @param Template $compiler
|
||||
* @param array $_attr attributes
|
||||
* @param string $tag
|
||||
* @param string $function
|
||||
*
|
||||
* @return array
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function setup(Template $compiler, $_attr, $tag, $function) {
|
||||
$_paramsArray = $this->formatParamsArray($_attr);
|
||||
$callback = ["\$_smarty_tpl->smarty->registered_objects['{$tag}'][0]", "->{$function}"];
|
||||
return [$callback, $_paramsArray, "array(\$_block_plugin{$this->nesting}, '{$function}')"];
|
||||
protected function getIsCallableCode($tag, $function): string {
|
||||
$callbackObject = "\$_smarty_tpl->smarty->registered_objects['{$tag}'][0]";
|
||||
return "(isset({$callbackObject}) && is_callable(array({$callbackObject}, '{$function}')))";
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getFullCallbackCode($tag, $function): string {
|
||||
$callbackObject = "\$_smarty_tpl->smarty->registered_objects['{$tag}'][0]";
|
||||
return "{$callbackObject}->{$function}";
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -286,6 +286,10 @@ class Template extends BaseCompiler {
|
||||
* @var string
|
||||
*/
|
||||
public $postfixCompiledCode = '';
|
||||
/**
|
||||
* @var ObjectMethodBlockCompiler
|
||||
*/
|
||||
private $objectMethodBlockCompiler;
|
||||
|
||||
/**
|
||||
* Initialize compiler
|
||||
@@ -302,6 +306,8 @@ class Template extends BaseCompiler {
|
||||
'_',
|
||||
uniqid(mt_rand(), true)
|
||||
);
|
||||
|
||||
$this->objectMethodBlockCompiler = new ObjectMethodBlockCompiler();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1424,7 +1430,7 @@ class Template extends BaseCompiler {
|
||||
|| in_array($method, $this->smarty->registered_objects[$base_tag][1]);
|
||||
|
||||
if ($allowedAsBlockFunction) {
|
||||
return (new ObjectMethodBlockCompiler())->compile($args, $this, $parameter, $tag, $method);
|
||||
return $this->objectMethodBlockCompiler->compile($args, $this, $parameter, $tag, $method);
|
||||
} elseif ($allowedAsNormalFunction) {
|
||||
return (new ObjectMethodCallCompiler())->compile($args, $this, $parameter, $tag, $method);
|
||||
}
|
||||
@@ -1439,7 +1445,7 @@ class Template extends BaseCompiler {
|
||||
|
||||
// closing tag
|
||||
if ($allowedAsBlockFunction) {
|
||||
return (new ObjectMethodBlockCompiler())->compile($args, $this, $parameter, $tag, $method);
|
||||
return $this->objectMethodBlockCompiler->compile($args, $this, $parameter, $tag, $method);
|
||||
}
|
||||
|
||||
$this->trigger_template_error(
|
||||
|
@@ -57,10 +57,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin function definition in script
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginRegisteredFunction()
|
||||
{
|
||||
@@ -70,9 +66,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin function definition in script
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*/
|
||||
public function testBlockPluginRegisteredFunction2()
|
||||
{
|
||||
@@ -83,10 +76,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin static method
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginRegisteredStatic()
|
||||
{
|
||||
@@ -96,10 +85,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin static method failure
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginRegisteredStatic2()
|
||||
{
|
||||
@@ -110,10 +95,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin object method
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginRegisteredMethod()
|
||||
{
|
||||
@@ -124,9 +105,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin object method failure
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*/
|
||||
public function testBlockPluginRegisteredMethod2()
|
||||
{
|
||||
@@ -137,10 +115,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin registered object
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginRegisteredObject()
|
||||
{
|
||||
@@ -151,23 +125,16 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin registered object failure
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*/
|
||||
public function testBlockPluginRegisteredObject2()
|
||||
{
|
||||
$this->expectException(\Smarty\Exception::class);
|
||||
$this->expectExceptionMessage('block tag \'myobject\' not callable');
|
||||
$this->expectExceptionMessage('block tag \'myobject\' not callable or registered');
|
||||
$this->assertEquals('object block test', $this->smarty->fetch('registered_object.tpl'));
|
||||
}
|
||||
|
||||
/**
|
||||
* test block plugin repeat function
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginRepeat()
|
||||
{
|
||||
@@ -176,10 +143,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin repeat function with modifier
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginRepeatModidier1()
|
||||
{
|
||||
@@ -188,10 +151,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin repeat function with modifier list
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginRepeatModidier2()
|
||||
{
|
||||
@@ -200,10 +159,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test block plugin with no output
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginNoOutput()
|
||||
{
|
||||
@@ -212,10 +167,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test nested block plugin
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginNested()
|
||||
{
|
||||
@@ -224,10 +175,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test default block plugin
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginDefault1()
|
||||
{
|
||||
@@ -237,10 +184,6 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
|
||||
/**
|
||||
* test default block plugin
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
*
|
||||
*/
|
||||
public function testBlockPluginDefault2()
|
||||
{
|
||||
@@ -251,10 +194,7 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
/**
|
||||
* Test caching
|
||||
*
|
||||
* @runInSeparateProcess
|
||||
* @preserveGlobalState disabled
|
||||
* @dataProvider data
|
||||
*
|
||||
*/
|
||||
public function testCache($isCached,
|
||||
$caching,
|
||||
@@ -304,9 +244,7 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
/**
|
||||
* Test spacings
|
||||
*
|
||||
* @preserveGlobalState disabled
|
||||
* @dataProvider dataTestSpacing
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testSpacing($code, $result, $testName, $testNumber)
|
||||
{
|
||||
@@ -345,9 +283,7 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
/**
|
||||
* Test spacings
|
||||
*
|
||||
* @preserveGlobalState disabled
|
||||
* @dataProvider dataTestDefaultSpacing
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testSpacingDefault($code, $result, $testName, $testNumber)
|
||||
{
|
||||
@@ -389,9 +325,7 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
/**
|
||||
* Test nocache block spacings
|
||||
*
|
||||
* @preserveGlobalState disabled
|
||||
* @dataProvider dataTestNocacheSpacing
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testBlockNocache($code, $result, $testName, $testNumber)
|
||||
{
|
||||
@@ -409,9 +343,7 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
/**
|
||||
* Test nocache block spacings
|
||||
*
|
||||
* @preserveGlobalState disabled
|
||||
* @dataProvider dataTestNocacheSpacing
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testBlockNocache2($code, $result, $testName, $testNumber)
|
||||
{
|
||||
@@ -446,7 +378,7 @@ class CompileBlockPluginTest extends PHPUnit_Smarty
|
||||
}
|
||||
|
||||
}
|
||||
function myblockplugintest($params, $content, &$smarty_tpl, &$repeat)
|
||||
function myblockplugintest($params, $content, $smarty_tpl, &$repeat)
|
||||
{
|
||||
if (!$repeat) {
|
||||
$output = str_replace('hello world', 'block test', $content);
|
||||
@@ -455,7 +387,7 @@ function myblockplugintest($params, $content, &$smarty_tpl, &$repeat)
|
||||
}
|
||||
}
|
||||
|
||||
function myblockplugintest2($params, $content, &$smarty_tpl, &$repeat)
|
||||
function myblockplugintest2($params, $content, $smarty_tpl, &$repeat)
|
||||
{
|
||||
if (!$repeat) {
|
||||
$output = str_replace('hello world', "block test{$params['var']}", $content);
|
||||
@@ -466,7 +398,7 @@ function myblockplugintest2($params, $content, &$smarty_tpl, &$repeat)
|
||||
|
||||
class myblockclass1
|
||||
{
|
||||
static function staticfunc($params, $content, &$smarty_tpl, &$repeat)
|
||||
static function staticfunc($params, $content, $smarty_tpl, &$repeat)
|
||||
{
|
||||
if (!$repeat) {
|
||||
$output = str_replace('hello world', 'static block test', $content);
|
||||
@@ -474,7 +406,7 @@ class myblockclass1
|
||||
}
|
||||
}
|
||||
|
||||
public function methodfunc($params, $content, &$smarty_tpl, &$repeat)
|
||||
public function methodfunc($params, $content, $smarty_tpl, &$repeat)
|
||||
{
|
||||
if (!$repeat) {
|
||||
$output = str_replace('hello world', 'method block test', $content);
|
||||
@@ -482,7 +414,7 @@ class myblockclass1
|
||||
}
|
||||
}
|
||||
|
||||
public function objectfunc($params, $content, &$smarty_tpl, &$repeat)
|
||||
public function objectfunc($params, $content, $smarty_tpl, &$repeat)
|
||||
{
|
||||
if (!$repeat) {
|
||||
$output = str_replace('hello world', 'object block test', $content);
|
||||
|
Reference in New Issue
Block a user