diff --git a/src/Compile/BlockCompiler.php b/src/Compile/BlockCompiler.php index f7b0660d..616edd4a 100644 --- a/src/Compile/BlockCompiler.php +++ b/src/Compile/BlockCompiler.php @@ -35,7 +35,7 @@ class BlockCompiler extends Base { * * @var int */ - public $nesting = 0; + private $nesting = 0; /** diff --git a/src/Compile/DefaultHandlerBlockCompiler.php b/src/Compile/DefaultHandlerBlockCompiler.php new file mode 100644 index 00000000..faa322a9 --- /dev/null +++ b/src/Compile/DefaultHandlerBlockCompiler.php @@ -0,0 +1,21 @@ +smarty->getRuntime('DefaultPluginHandler')->hasPlugin(" . + var_export($function, true) . ", 'block')"; + } + + /** + * @inheritDoc + */ + protected function getFullCallbackCode($tag, $function): string { + return "\$_smarty_tpl->smarty->getRuntime('DefaultPluginHandler')->getCallback(" . + var_export($function, true) . ", 'block')"; + } +} \ No newline at end of file diff --git a/src/Compile/DefaultHandlerFunctionCallCompiler.php b/src/Compile/DefaultHandlerFunctionCallCompiler.php index 54344541..5b9833ec 100644 --- a/src/Compile/DefaultHandlerFunctionCallCompiler.php +++ b/src/Compile/DefaultHandlerFunctionCallCompiler.php @@ -35,8 +35,8 @@ class DefaultHandlerFunctionCallCompiler extends Base { $_paramsArray = $this->formatParamsArray($_attr); $_params = 'array(' . implode(',', $_paramsArray) . ')'; - $output = "\$_smarty_tpl->smarty->getRuntime('DefaultPluginHandler')->runPlugin(" . var_export($function, true) . - ",'function',$_params, \$_smarty_tpl)"; + $output = "\$_smarty_tpl->smarty->getRuntime('DefaultPluginHandler')->getCallback(" . var_export($function, true) . + ",'function')($_params, \$_smarty_tpl)"; if (!empty($parameter['modifierlist'])) { $output = $compiler->compileModifier($parameter['modifierlist'], $output); diff --git a/src/Compiler/Template.php b/src/Compiler/Template.php index 863b30c0..69bef1c1 100644 --- a/src/Compiler/Template.php +++ b/src/Compiler/Template.php @@ -11,6 +11,7 @@ namespace Smarty\Compiler; use Smarty\Compile\BlockCompiler; +use Smarty\Compile\DefaultHandlerBlockCompiler; use Smarty\Compile\DefaultHandlerFunctionCallCompiler; use Smarty\Compile\ModifierCompiler; use Smarty\Compile\ObjectMethodBlockCompiler; @@ -290,6 +291,30 @@ class Template extends BaseCompiler { * @var ObjectMethodBlockCompiler */ private $objectMethodBlockCompiler; + /** + * @var DefaultHandlerBlockCompiler + */ + private $defaultHandlerBlockCompiler; + /** + * @var BlockCompiler + */ + private $blockCompiler; + /** + * @var DefaultHandlerFunctionCallCompiler + */ + private $defaultHandlerFunctionCallCompiler; + /** + * @var FunctionCallCompiler + */ + private $functionCallCompiler; + /** + * @var ObjectMethodCallCompiler + */ + private $objectMethodCallCompiler; + /** + * @var ModifierCompiler + */ + private $modifierCompiler; /** * Initialize compiler @@ -307,7 +332,13 @@ class Template extends BaseCompiler { uniqid(mt_rand(), true) ); + $this->modifierCompiler = new ModifierCompiler(); + $this->functionCallCompiler = new FunctionCallCompiler(); + $this->defaultHandlerFunctionCallCompiler = new DefaultHandlerFunctionCallCompiler(); + $this->blockCompiler = new BlockCompiler(); + $this->defaultHandlerBlockCompiler = new DefaultHandlerBlockCompiler(); $this->objectMethodBlockCompiler = new ObjectMethodBlockCompiler(); + $this->objectMethodCallCompiler = new ObjectMethodCallCompiler(); } /** @@ -461,7 +492,7 @@ class Template extends BaseCompiler { * @throws Exception */ public function compileModifier($modifierlist, $value) { - return (new ModifierCompiler())->compile([], $this, ['modifierlist' => $modifierlist, 'value' => $value]); + return $this->modifierCompiler->compile([], $this, ['modifierlist' => $modifierlist, 'value' => $value]); } /** @@ -1247,21 +1278,19 @@ class Template extends BaseCompiler { // check if tag is a function if ($this->smarty->getFunctionHandler($base_tag)) { if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) { - $compiler = new FunctionCallCompiler(); - return $compiler->compile($args, $this, $parameter, $tag, $base_tag); + return $this->functionCallCompiler->compile($args, $this, $parameter, $tag, $base_tag); } } // check if tag is a block if ($this->smarty->getBlockHandler($base_tag)) { if (!isset($this->smarty->security_policy) || $this->smarty->security_policy->isTrustedTag($base_tag, $this)) { - $compiler = new BlockCompiler(); - return $compiler->compile($args, $this, $parameter, $tag, $base_tag); + return $this->blockCompiler->compile($args, $this, $parameter, $tag, $base_tag); } } // the default plugin handler is a handler of last resort, it may also handle not specifically registered tags. - if ($callback = $this->getPluginFromDefaultHandler($tag, Smarty::PLUGIN_COMPILER)) { + if ($callback = $this->getPluginFromDefaultHandler($base_tag, Smarty::PLUGIN_COMPILER)) { $tagCompiler = new \Smarty\Compile\Tag\BCPluginWrapper($callback); $new_args = []; foreach ($args as $key => $mixed) { @@ -1274,14 +1303,12 @@ class Template extends BaseCompiler { return $tagCompiler->compile($new_args, $this, $parameter); } - if ($this->getPluginFromDefaultHandler($tag, Smarty::PLUGIN_FUNCTION)) { - $compiler = new DefaultHandlerFunctionCallCompiler(); - return $compiler->compile($args, $this, $parameter, $tag, $base_tag); + if ($this->getPluginFromDefaultHandler($base_tag, Smarty::PLUGIN_FUNCTION)) { + return $this->defaultHandlerFunctionCallCompiler->compile($args, $this, $parameter, $tag, $base_tag); } - if ($this->getPluginFromDefaultHandler($tag, Smarty::PLUGIN_BLOCK)) { - $compiler = new BlockCompiler(); - return $compiler->compile($args, $this, $parameter, $tag, $base_tag); + if ($this->getPluginFromDefaultHandler($base_tag, Smarty::PLUGIN_BLOCK)) { + return $this->defaultHandlerBlockCompiler->compile($args, $this, $parameter, $tag, $base_tag); } $this->trigger_template_error("unknown tag '{$tag}'", null, true); @@ -1432,7 +1459,7 @@ class Template extends BaseCompiler { if ($allowedAsBlockFunction) { return $this->objectMethodBlockCompiler->compile($args, $this, $parameter, $tag, $method); } elseif ($allowedAsNormalFunction) { - return (new ObjectMethodCallCompiler())->compile($args, $this, $parameter, $tag, $method); + return $this->objectMethodCallCompiler->compile($args, $this, $parameter, $tag, $method); } $this->trigger_template_error( diff --git a/src/Runtime/DefaultPluginHandlerRuntime.php b/src/Runtime/DefaultPluginHandlerRuntime.php index e53de7b4..ad6ed74d 100644 --- a/src/Runtime/DefaultPluginHandlerRuntime.php +++ b/src/Runtime/DefaultPluginHandlerRuntime.php @@ -15,10 +15,34 @@ class DefaultPluginHandlerRuntime { $this->defaultPluginHandler = $defaultPluginHandler; } + public function hasPlugin($tag, $plugin_type): bool { + if ($this->defaultPluginHandler === null) { + return false; + } + + $callback = null; + + // these are not used here + $script = null; + $cacheable = null; + + return (call_user_func_array( + $this->defaultPluginHandler, + [ + $tag, + $plugin_type, + null, // This used to pass $this->template, but this parameter has been removed in 5.0 + &$callback, + &$script, + &$cacheable, + ] + ) && $callback); + } + /** * @throws Exception */ - public function runPlugin($tag, $plugin_type, $params, \Smarty\Template $template) { + public function getCallback($tag, $plugin_type) { if ($this->defaultPluginHandler === null) { return false; @@ -41,8 +65,9 @@ class DefaultPluginHandlerRuntime { &$cacheable, ] ) && $callback) { - return $callback($params, $template); + return $callback; } throw new Exception("Default plugin handler: Returned callback for '{$tag}' not callable at runtime"); } + } \ No newline at end of file diff --git a/tests/UnitTests/TemplateSource/TagTests/BlockPlugin/CompileBlockPluginTest.php b/tests/UnitTests/TemplateSource/TagTests/BlockPlugin/CompileBlockPluginTest.php index 13887877..1ff364d6 100644 --- a/tests/UnitTests/TemplateSource/TagTests/BlockPlugin/CompileBlockPluginTest.php +++ b/tests/UnitTests/TemplateSource/TagTests/BlockPlugin/CompileBlockPluginTest.php @@ -429,8 +429,8 @@ function my_block_plugin_handler($tag, $type, $template, &$callback, &$script, & case \Smarty\Smarty::PLUGIN_BLOCK: switch ($tag) { case 'scriptblock': - $script = './scripts/script_block_tag.php'; - $callback = 'default_script_block_tag'; + $script = './scripts/script_block_tag2.php'; + $callback = 'default_script_block_tag2'; return true; default: diff --git a/tests/UnitTests/TemplateSource/TagTests/BlockPlugin/scripts/script_block_tag.php b/tests/UnitTests/TemplateSource/TagTests/BlockPlugin/scripts/script_block_tag2.php similarity index 53% rename from tests/UnitTests/TemplateSource/TagTests/BlockPlugin/scripts/script_block_tag.php rename to tests/UnitTests/TemplateSource/TagTests/BlockPlugin/scripts/script_block_tag2.php index a61f14d6..71497a40 100644 --- a/tests/UnitTests/TemplateSource/TagTests/BlockPlugin/scripts/script_block_tag.php +++ b/tests/UnitTests/TemplateSource/TagTests/BlockPlugin/scripts/script_block_tag2.php @@ -1,5 +1,5 @@ setUpSmarty(__DIR__); } + public function testInit() + { + $this->cleanDirs(); + } + public function testDefault() { $result = "This is foo. This is foo. This is foo.\nThis is foo. This is foo. This is foo.\n\nThis is bar.\n\nbar foo bar foo foo. bar foo bar foo\nfoo. bar foo bar foo foo. bar foo bar\nfoo foo. bar foo bar foo foo. bar foo\nbar foo foo. bar foo bar foo foo.\n\n";