diff --git a/src/Compile/smarty_internal_compile_block_child.php b/src/Compile/BlockChild.php similarity index 64% rename from src/Compile/smarty_internal_compile_block_child.php rename to src/Compile/BlockChild.php index 54114813..0c50d21f 100644 --- a/src/Compile/smarty_internal_compile_block_child.php +++ b/src/Compile/BlockChild.php @@ -8,19 +8,19 @@ * file that was distributed with this source code. */ -use Smarty\Compile\Child; +namespace Smarty\Compile; /** * Smarty Internal Plugin Compile Block Child Class * * @author Uwe Tews */ -class Smarty_Internal_Compile_Block_Child extends Child -{ - /** - * Tag name - * - * @var string - */ - public $tag = 'block_child'; +class BlockChild extends Child { + + /** + * Tag name + * + * @var string + */ + protected $tag = 'block_child'; } diff --git a/src/Compile/Blockclose.php b/src/Compile/BlockClose.php similarity index 98% rename from src/Compile/Blockclose.php rename to src/Compile/BlockClose.php index b74241f1..c62a909c 100644 --- a/src/Compile/Blockclose.php +++ b/src/Compile/BlockClose.php @@ -8,7 +8,7 @@ use Smarty_Internal_TemplateCompilerBase; /** * Smarty Internal Plugin Compile BlockClose Class */ -class Blockclose extends Inheritance { +class BlockClose extends Inheritance { /** * Compiles code for the {/block} tag diff --git a/src/Compile/smarty_internal_compile_block_parent.php b/src/Compile/BlockParent.php similarity index 53% rename from src/Compile/smarty_internal_compile_block_parent.php rename to src/Compile/BlockParent.php index ab902ff8..f713c73c 100644 --- a/src/Compile/smarty_internal_compile_block_parent.php +++ b/src/Compile/BlockParent.php @@ -8,26 +8,26 @@ * file that was distributed with this source code. */ -use Smarty\Compile\Child; +namespace Smarty\Compile; /** * Smarty Internal Plugin Compile Block Parent Class * * @author Uwe Tews */ -class Smarty_Internal_Compile_Block_Parent extends Child -{ - /** - * Tag name - * - * @var string - */ - public $tag = 'block_parent'; +class BlockParent extends Child { - /** - * Block type - * - * @var string - */ - public $blockType = 'Parent'; + /** + * Tag name + * + * @var string + */ + protected $tag = 'block_parent'; + + /** + * Block type + * + * @var string + */ + protected $blockType = 'Parent'; } diff --git a/src/Compile/BreakTag.php b/src/Compile/BreakTag.php index ebf3012d..a4bbf9a6 100644 --- a/src/Compile/BreakTag.php +++ b/src/Compile/BreakTag.php @@ -10,7 +10,7 @@ namespace Smarty\Compile; -use Smarty_Internal_Compile_Foreach; +use Smarty\Compile\ForeachTag; use Smarty_Internal_TemplateCompilerBase; /** @@ -42,7 +42,7 @@ class BreakTag extends Base { * * @var string */ - private $tag = 'break'; + protected $tag = 'break'; /** * Compiles code for the {break} tag @@ -61,7 +61,7 @@ class BreakTag extends Base { $foreachLevels--; } if ($foreachLevels > 0) { - /* @var Smarty_Internal_Compile_Foreach $foreachCompiler */ + /* @var ForeachTag $foreachCompiler */ $foreachCompiler = $compiler->getTagCompiler('foreach'); $output .= $foreachCompiler->compileRestore($foreachLevels); } diff --git a/src/Compile/Capture.php b/src/Compile/Capture.php new file mode 100644 index 00000000..17fe547c --- /dev/null +++ b/src/Compile/Capture.php @@ -0,0 +1,68 @@ +smarty->ext->_capture->getBuffer($_smarty_tpl' . + (isset($parameter[1]) ? ", {$parameter[ 1 ]})" : ')'); + } + + /** + * Compiles code for the {capture} tag + * + * @param array $args array with attributes from parser + * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object + * @param null $parameter + * + * @return string compiled code + */ + public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = [], $tag = null, $function = null) { + // check and get attributes + $_attr = $this->getAttributes($compiler, $args, $parameter, 'capture'); + $buffer = $_attr['name'] ?? "'default'"; + $assign = $_attr['assign'] ?? 'null'; + $append = $_attr['append'] ?? 'null'; + $compiler->_cache['capture_stack'][] = [$compiler->nocache]; + // maybe nocache because of nocache variables + $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; + $_output = "smarty->ext->_capture->open(\$_smarty_tpl, $buffer, $assign, $append);?>"; + return $_output; + } +} \ No newline at end of file diff --git a/src/Compile/CaptureClose.php b/src/Compile/CaptureClose.php new file mode 100644 index 00000000..c58bc456 --- /dev/null +++ b/src/Compile/CaptureClose.php @@ -0,0 +1,42 @@ +getAttributes($compiler, $args, $parameter, '/capture'); + // must endblock be nocache? + if ($compiler->nocache) { + $compiler->tag_nocache = true; + } + [$compiler->nocache] = array_pop($compiler->_cache['capture_stack']); + return "smarty->ext->_capture->close(\$_smarty_tpl);?>"; + } +} diff --git a/src/Compile/Child.php b/src/Compile/Child.php index ca6140f3..4dd47d89 100644 --- a/src/Compile/Child.php +++ b/src/Compile/Child.php @@ -32,14 +32,14 @@ class Child extends Base { * * @var string */ - private $tag = 'child'; + protected $tag = 'child'; /** * Block type * * @var string */ - private $blockType = 'Child'; + protected $blockType = 'Child'; /** * Compiles code for the {child} tag diff --git a/src/Compile/ContinueTag.php b/src/Compile/ContinueTag.php index 105c4908..12e60232 100644 --- a/src/Compile/ContinueTag.php +++ b/src/Compile/ContinueTag.php @@ -25,5 +25,5 @@ class ContinueTag extends BreakTag { * * @var string */ - public $tag = 'continue'; + protected $tag = 'continue'; } diff --git a/src/Compile/ElseIfTag.php b/src/Compile/ElseIfTag.php new file mode 100644 index 00000000..c4938a8a --- /dev/null +++ b/src/Compile/ElseIfTag.php @@ -0,0 +1,85 @@ +getAttributes($compiler, $args); + [$nesting, $compiler->tag_nocache] = $this->closeTag($compiler, ['if', 'elseif']); + if (!isset($parameter['if condition'])) { + $compiler->trigger_template_error('missing elseif condition', null, true); + } + $assignCode = ''; + $var = ''; + if (is_array($parameter['if condition'])) { + $condition_by_assign = true; + if (is_array($parameter['if condition']['var'])) { + $var = $parameter['if condition']['var']['var']; + } else { + $var = $parameter['if condition']['var']; + } + if ($compiler->nocache) { + // create nocache var to make it know for further compiling + $compiler->setNocacheInVariable($var); + } + $prefixVar = $compiler->getNewPrefixVariable(); + $assignCode = "\n"; + $assignCompiler = new Assign(); + $assignAttr = []; + $assignAttr[]['value'] = $prefixVar; + if (is_array($parameter['if condition']['var'])) { + $assignAttr[]['var'] = $parameter['if condition']['var']['var']; + $assignCode .= $assignCompiler->compile( + $assignAttr, + $compiler, + ['smarty_internal_index' => $parameter['if condition']['var']['smarty_internal_index']] + ); + } else { + $assignAttr[]['var'] = $parameter['if condition']['var']; + $assignCode .= $assignCompiler->compile($assignAttr, $compiler, []); + } + } else { + $condition_by_assign = false; + } + $prefixCode = $compiler->getPrefixCode(); + if (empty($prefixCode)) { + if ($condition_by_assign) { + $this->openTag($compiler, 'elseif', [$nesting + 1, $compiler->tag_nocache]); + $_output = $compiler->appendCode("", $assignCode); + return $compiler->appendCode($_output, ""); + } else { + $this->openTag($compiler, 'elseif', [$nesting, $compiler->tag_nocache]); + return ""; + } + } else { + $_output = $compiler->appendCode("", $prefixCode); + $this->openTag($compiler, 'elseif', [$nesting + 1, $compiler->tag_nocache]); + if ($condition_by_assign) { + $_output = $compiler->appendCode($_output, $assignCode); + return $compiler->appendCode($_output, ""); + } else { + return $compiler->appendCode($_output, ""); + } + } + } +} \ No newline at end of file diff --git a/src/Compile/ElseTag.php b/src/Compile/ElseTag.php new file mode 100644 index 00000000..58eb0e46 --- /dev/null +++ b/src/Compile/ElseTag.php @@ -0,0 +1,28 @@ +tag_nocache] = $this->closeTag($compiler, ['if', 'elseif']); + $this->openTag($compiler, 'else', [$nesting, $compiler->tag_nocache]); + return ''; + } +} \ No newline at end of file diff --git a/src/Compile/ExtendsTag.php b/src/Compile/ExtendsTag.php new file mode 100644 index 00000000..1eb7c57f --- /dev/null +++ b/src/Compile/ExtendsTag.php @@ -0,0 +1,159 @@ +getAttributes($compiler, $args); + if ($_attr['nocache'] === true) { + $compiler->trigger_template_error('nocache option not allowed', $compiler->parser->lex->line - 1); + } + if (strpos($_attr['file'], '$_tmp') !== false) { + $compiler->trigger_template_error('illegal value for file attribute', $compiler->parser->lex->line - 1); + } + // add code to initialize inheritance + $this->registerInit($compiler, true); + $file = trim($_attr['file'], '\'"'); + if (strlen($file) > 8 && substr($file, 0, 8) === 'extends:') { + // generate code for each template + $files = array_reverse(explode('|', substr($file, 8))); + $i = 0; + foreach ($files as $file) { + if ($file[0] === '"') { + $file = trim($file, '".'); + } else { + $file = "'{$file}'"; + } + $i++; + if ($i === count($files) && isset($_attr['extends_resource'])) { + $this->compileEndChild($compiler); + } + $this->compileInclude($compiler, $file); + } + if (!isset($_attr['extends_resource'])) { + $this->compileEndChild($compiler); + } + } else { + $this->compileEndChild($compiler, $_attr['file']); + } + $compiler->has_code = false; + return ''; + } + + /** + * Add code for inheritance endChild() method to end of template + * + * @param \Smarty_Internal_TemplateCompilerBase $compiler + * @param null|string $template optional inheritance parent template + * + * @throws \SmartyCompilerException + * @throws \SmartyException + */ + private function compileEndChild(Smarty_Internal_TemplateCompilerBase $compiler, $template = null) { + $inlineUids = ''; + if (isset($template) && $compiler->smarty->merge_compiled_includes) { + $code = $compiler->compileTag('include', [$template, ['scope' => 'parent']]); + if (preg_match('/([,][\s]*[\'][a-z0-9]+[\'][,][\s]*[\']content.*[\'])[)]/', $code, $match)) { + $inlineUids = $match[1]; + } + } + $compiler->parser->template_postfix[] = new \Smarty\ParseTree\Tag( + $compiler->parser, + 'inheritance->endChild($_smarty_tpl' . + (isset($template) ? + ", {$template}{$inlineUids}" : + '') . ");\n?>" + ); + } + + /** + * Add code for including subtemplate to end of template + * + * @param \Smarty_Internal_TemplateCompilerBase $compiler + * @param string $template subtemplate name + * + * @throws \SmartyCompilerException + * @throws \SmartyException + */ + private function compileInclude(Smarty_Internal_TemplateCompilerBase $compiler, $template) { + $compiler->parser->template_postfix[] = new \Smarty\ParseTree\Tag( + $compiler->parser, + $compiler->compileTag( + 'include', + [ + $template, + ['scope' => 'parent'], + ] + ) + ); + } + + /** + * Create source code for {extends} from source components array + * + * @param \Smarty_Internal_Template $template + * + * @return string + */ + public static function extendsSourceArrayCode(Smarty_Internal_Template $template) { + $resources = []; + foreach ($template->source->components as $source) { + $resources[] = $source->resource; + } + return $template->smarty->left_delimiter . 'extends file=\'extends:' . join('|', $resources) . + '\' extends_resource=true' . $template->smarty->right_delimiter; + } +} diff --git a/src/Compile/ForClose.php b/src/Compile/ForClose.php new file mode 100644 index 00000000..aa5140f0 --- /dev/null +++ b/src/Compile/ForClose.php @@ -0,0 +1,48 @@ +loopNesting--; + // check and get attributes + $this->getAttributes($compiler, $args); + // must endblock be nocache? + if ($compiler->nocache) { + $compiler->tag_nocache = true; + } + [$openTag, $compiler->nocache] = $this->closeTag($compiler, ['for', 'forelse']); + $output = ""; + return $output; + } +} diff --git a/src/Compile/ForElse.php b/src/Compile/ForElse.php new file mode 100644 index 00000000..e8148a7a --- /dev/null +++ b/src/Compile/ForElse.php @@ -0,0 +1,31 @@ +getAttributes($compiler, $args); + [$openTag, $nocache] = $this->closeTag($compiler, ['for']); + $this->openTag($compiler, 'forelse', ['forelse', $nocache]); + return ""; + } +} \ No newline at end of file diff --git a/src/Compile/ForTag.php b/src/Compile/ForTag.php new file mode 100644 index 00000000..5df805d5 --- /dev/null +++ b/src/Compile/ForTag.php @@ -0,0 +1,96 @@ +loopNesting++; + if ($parameter === 0) { + $this->required_attributes = ['start', 'to']; + $this->optional_attributes = ['max', 'step']; + } else { + $this->required_attributes = ['start', 'ifexp', 'var', 'step']; + $this->optional_attributes = []; + } + $this->mapCache = []; + // check and get attributes + $_attr = $this->getAttributes($compiler, $args); + $output = "tpl_vars[$var] = new \\Smarty\\Variable(null, \$_smarty_tpl->isRenderingCache);\n"; + $output .= "\$_smarty_tpl->tpl_vars[$var]->value{$index} = {$_statement['value']};\n"; + } + if (is_array($_attr['var'])) { + $var = $_attr['var']['var']; + $index = $_attr['var']['smarty_internal_index']; + } else { + $var = $_attr['var']; + $index = ''; + } + $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'])) { + $var = $_statement['var']['var']; + $index = $_statement['var']['smarty_internal_index']; + } else { + $var = $_statement['var']; + $index = ''; + } + $output .= "\$_smarty_tpl->tpl_vars[$var] = new \\Smarty\\Variable(null, \$_smarty_tpl->isRenderingCache);"; + if (isset($_attr['step'])) { + $output .= "\$_smarty_tpl->tpl_vars[$var]->step = $_attr[step];"; + } else { + $output .= "\$_smarty_tpl->tpl_vars[$var]->step = 1;"; + } + if (isset($_attr['max'])) { + $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 .= "\$_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 (\$_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 .= '?>'; + $this->openTag($compiler, 'for', ['for', $compiler->nocache]); + // maybe nocache because of nocache variables + $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; + // return compiled code + return $output; + } +} \ No newline at end of file diff --git a/src/Compile/ForeachClose.php b/src/Compile/ForeachClose.php new file mode 100644 index 00000000..79cd78c3 --- /dev/null +++ b/src/Compile/ForeachClose.php @@ -0,0 +1,53 @@ +loopNesting--; + // must endblock be nocache? + if ($compiler->nocache) { + $compiler->tag_nocache = true; + } + [ + $openTag, $compiler->nocache, $local, $itemVar, $restore, + ] = $this->closeTag($compiler, ['foreach', 'foreachelse']); + $output = "getTagCompiler('foreach'); + $output .= $foreachCompiler->compileRestore(1); + $output .= "?>"; + return $output; + } +} diff --git a/src/Compile/ForeachElse.php b/src/Compile/ForeachElse.php new file mode 100644 index 00000000..53a02b1d --- /dev/null +++ b/src/Compile/ForeachElse.php @@ -0,0 +1,35 @@ +getAttributes($compiler, $args); + [$openTag, $nocache, $local, $itemVar, $restore] = $this->closeTag($compiler, ['foreach']); + $this->openTag($compiler, 'foreachelse', ['foreachelse', $nocache, $local, $itemVar, 0]); + $output = "do_else) {\n?>"; + return $output; + } +} \ No newline at end of file diff --git a/src/Compile/ForeachSection.php b/src/Compile/ForeachSection.php index 2ed4a760..d8b52856 100644 --- a/src/Compile/ForeachSection.php +++ b/src/Compile/ForeachSection.php @@ -10,7 +10,6 @@ namespace Smarty\Compile; -use Smarty\Compile\Base; use Smarty_Internal_TemplateCompilerBase; /** @@ -26,33 +25,33 @@ abstract class ForeachSection extends Base { * * @var string */ - public $tagName = ''; + protected $tagName = ''; /** * Valid properties of $smarty.xxx variable * * @var array */ - public $nameProperties = []; + protected $nameProperties = []; /** * {section} tag has no item properties * * @var array */ - public $itemProperties = null; + protected $itemProperties = null; /** * {section} tag has always name attribute * * @var bool */ - public $isNamed = true; + protected $isNamed = true; /** * @var array */ - public $matchResults = []; + protected $matchResults = []; /** * Preg search pattern diff --git a/src/Compile/ForeachTag.php b/src/Compile/ForeachTag.php new file mode 100644 index 00000000..a2949ec0 --- /dev/null +++ b/src/Compile/ForeachTag.php @@ -0,0 +1,266 @@ +loopNesting++; + // init + $this->isNamed = false; + // check and get attributes + $_attr = $this->getAttributes($compiler, $args); + $from = $_attr['from']; + $item = $compiler->getId($_attr['item']); + if ($item === false) { + $item = $compiler->getVariableName($_attr['item']); + } + $key = $name = null; + $attributes = ['item' => $item]; + if (isset($_attr['key'])) { + $key = $compiler->getId($_attr['key']); + if ($key === false) { + $key = $compiler->getVariableName($_attr['key']); + } + $attributes['key'] = $key; + } + if (isset($_attr['name'])) { + $this->isNamed = true; + $name = $attributes['name'] = $compiler->getId($_attr['name']); + } + foreach ($attributes as $a => $v) { + if ($v === false) { + $compiler->trigger_template_error("'{$a}' attribute/variable has illegal value", null, true); + } + } + $fromName = $compiler->getVariableName($_attr['from']); + if ($fromName) { + foreach (['item', 'key'] as $a) { + if (isset($attributes[$a]) && $attributes[$a] === $fromName) { + $compiler->trigger_template_error( + "'{$a}' and 'from' may not have same variable name '{$fromName}'", + null, + true + ); + } + } + } + $itemVar = "\$_smarty_tpl->tpl_vars['{$item}']"; + $local = '$__foreach_' . $attributes['item'] . '_' . $this->counter++ . '_'; + // search for used tag attributes + $itemAttr = []; + $namedAttr = []; + $this->scanForProperties($attributes, $compiler); + if (!empty($this->matchResults['item'])) { + $itemAttr = $this->matchResults['item']; + } + if (!empty($this->matchResults['named'])) { + $namedAttr = $this->matchResults['named']; + } + if (isset($_attr['properties']) && preg_match_all('/[\'](.*?)[\']/', $_attr['properties'], $match)) { + foreach ($match[1] as $prop) { + if (in_array($prop, $this->itemProperties)) { + $itemAttr[$prop] = true; + } else { + $compiler->trigger_template_error("Invalid property '{$prop}'", null, true); + } + } + if ($this->isNamed) { + foreach ($match[1] as $prop) { + if (in_array($prop, $this->nameProperties)) { + $nameAttr[$prop] = true; + } else { + $compiler->trigger_template_error("Invalid property '{$prop}'", null, true); + } + } + } + } + if (isset($itemAttr['first'])) { + $itemAttr['index'] = true; + } + if (isset($namedAttr['first'])) { + $namedAttr['index'] = true; + } + if (isset($namedAttr['last'])) { + $namedAttr['iteration'] = true; + $namedAttr['total'] = true; + } + if (isset($itemAttr['last'])) { + $itemAttr['iteration'] = true; + $itemAttr['total'] = true; + } + if (isset($namedAttr['show'])) { + $namedAttr['total'] = true; + } + if (isset($itemAttr['show'])) { + $itemAttr['total'] = true; + } + $keyTerm = ''; + if (isset($attributes['key'])) { + $keyTerm = "\$_smarty_tpl->tpl_vars['{$key}']->value => "; + } + if (isset($itemAttr['key'])) { + $keyTerm = "{$itemVar}->key => "; + } + if ($this->isNamed) { + $foreachVar = "\$_smarty_tpl->tpl_vars['__smarty_foreach_{$attributes['name']}']"; + } + $needTotal = isset($itemAttr['total']); + // Register tag + $this->openTag( + $compiler, + 'foreach', + ['foreach', $compiler->nocache, $local, $itemVar, empty($itemAttr) ? 1 : 2] + ); + // maybe nocache because of nocache variables + $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; + // generate output code + $output = "smarty->ext->_foreach->init(\$_smarty_tpl, $from, " . + var_export($item, true); + if ($name || $needTotal || $key) { + $output .= ', ' . var_export($needTotal, true); + } + if ($name || $key) { + $output .= ', ' . var_export($key, true); + } + if ($name) { + $output .= ', ' . var_export($name, true) . ', ' . var_export($namedAttr, true); + } + $output .= ");\n"; + if (isset($itemAttr['show'])) { + $output .= "{$itemVar}->show = ({$itemVar}->total > 0);\n"; + } + if (isset($itemAttr['iteration'])) { + $output .= "{$itemVar}->iteration = 0;\n"; + } + if (isset($itemAttr['index'])) { + $output .= "{$itemVar}->index = -1;\n"; + } + $output .= "{$itemVar}->do_else = true;\n"; + $output .= "if (\$_from !== null) foreach (\$_from as {$keyTerm}{$itemVar}->value) {\n"; + $output .= "{$itemVar}->do_else = false;\n"; + if (isset($attributes['key']) && isset($itemAttr['key'])) { + $output .= "\$_smarty_tpl->tpl_vars['{$key}']->value = {$itemVar}->key;\n"; + } + if (isset($itemAttr['iteration'])) { + $output .= "{$itemVar}->iteration++;\n"; + } + if (isset($itemAttr['index'])) { + $output .= "{$itemVar}->index++;\n"; + } + if (isset($itemAttr['first'])) { + $output .= "{$itemVar}->first = !{$itemVar}->index;\n"; + } + if (isset($itemAttr['last'])) { + $output .= "{$itemVar}->last = {$itemVar}->iteration === {$itemVar}->total;\n"; + } + if (isset($foreachVar)) { + if (isset($namedAttr['iteration'])) { + $output .= "{$foreachVar}->value['iteration']++;\n"; + } + if (isset($namedAttr['index'])) { + $output .= "{$foreachVar}->value['index']++;\n"; + } + if (isset($namedAttr['first'])) { + $output .= "{$foreachVar}->value['first'] = !{$foreachVar}->value['index'];\n"; + } + if (isset($namedAttr['last'])) { + $output .= "{$foreachVar}->value['last'] = {$foreachVar}->value['iteration'] === {$foreachVar}->value['total'];\n"; + } + } + if (!empty($itemAttr)) { + $output .= "{$local}saved = {$itemVar};\n"; + } + $output .= '?>'; + return $output; + } + + /** + * Compiles code for to restore saved template variables + * + * @param int $levels number of levels to restore + * + * @return string compiled code + */ + public function compileRestore($levels) { + return "\$_smarty_tpl->smarty->ext->_foreach->restore(\$_smarty_tpl, {$levels});"; + } +} \ No newline at end of file diff --git a/src/Compile/FunctionClose.php b/src/Compile/FunctionClose.php new file mode 100644 index 00000000..1ce3d356 --- /dev/null +++ b/src/Compile/FunctionClose.php @@ -0,0 +1,165 @@ +compiler = $compiler; + $saved_data = $this->closeTag($compiler, ['function']); + $_attr = $saved_data[0]; + $_name = trim($_attr['name'], '\'"'); + $compiler->parent_compiler->tpl_function[$_name]['compiled_filepath'] = + $compiler->parent_compiler->template->compiled->filepath; + $compiler->parent_compiler->tpl_function[$_name]['uid'] = $compiler->template->source->uid; + $_parameter = $_attr; + unset($_parameter['name']); + // default parameter + $_paramsArray = []; + foreach ($_parameter as $_key => $_value) { + if (is_int($_key)) { + $_paramsArray[] = "$_key=>$_value"; + } else { + $_paramsArray[] = "'$_key'=>$_value"; + } + } + if (!empty($_paramsArray)) { + $_params = 'array(' . implode(',', $_paramsArray) . ')'; + $_paramsCode = "\$params = array_merge($_params, \$params);\n"; + } else { + $_paramsCode = ''; + } + $_functionCode = $compiler->parser->current_buffer; + // setup buffer for template function code + $compiler->parser->current_buffer = new \Smarty\ParseTree\Template(); + $_funcName = "smarty_template_function_{$_name}_{$compiler->template->compiled->nocache_hash}"; + $_funcNameCaching = $_funcName . 'Smarty\Compile\Nocache'; + if ($compiler->template->compiled->has_nocache_code) { + $compiler->parent_compiler->tpl_function[$_name]['call_name_caching'] = $_funcNameCaching; + $output = "cStyleComment(" {$_funcNameCaching} ") . "\n"; + $output .= "if (!function_exists('{$_funcNameCaching}')) {\n"; + $output .= "function {$_funcNameCaching} (Smarty_Internal_Template \$_smarty_tpl,\$params) {\n"; + $output .= "ob_start();\n"; + $output .= "\$_smarty_tpl->compiled->has_nocache_code = true;\n"; + $output .= $_paramsCode; + $output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new \\Smarty\\Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}\n"; + $output .= "\$params = var_export(\$params, true);\n"; + $output .= "echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/smarty->ext->_tplFunction->saveTemplateVariables(\\\$_smarty_tpl, '{$_name}');\nforeach (\$params as \\\$key => \\\$value) {\n\\\$_smarty_tpl->tpl_vars[\\\$key] = new \\Smarty\\Variable(\\\$value, \\\$_smarty_tpl->isRenderingCache);\n}\n?>"; + $output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";?>"; + $compiler->parser->current_buffer->append_subtree( + $compiler->parser, + new \Smarty\ParseTree\Tag( + $compiler->parser, + $output + ) + ); + $compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode); + $output = "template->compiled->nocache_hash}%%*/smarty->ext->_tplFunction->restoreTemplateVariables(\\\$_smarty_tpl, '{$_name}');?>\n"; + $output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";\n?>"; + $output .= "template->compiled->nocache_hash}', \$_smarty_tpl->compiled->nocache_hash ?? '', ob_get_clean());\n"; + $output .= "}\n}\n"; + $output .= $compiler->cStyleComment("/ {$_funcName}_nocache ") . "\n\n"; + $output .= "?>\n"; + $compiler->parser->current_buffer->append_subtree( + $compiler->parser, + new \Smarty\ParseTree\Tag( + $compiler->parser, + $output + ) + ); + $_functionCode = new \Smarty\ParseTree\Tag( + $compiler->parser, + preg_replace_callback( + "/((<\?php )?echo '\/\*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/([\S\s]*?)\/\*\/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/", + [$this, 'removeNocache'], + $_functionCode->to_smarty_php($compiler->parser) + ) + ); + } + $compiler->parent_compiler->tpl_function[$_name]['call_name'] = $_funcName; + $output = "cStyleComment(" {$_funcName} ") . "\n"; + $output .= "if (!function_exists('{$_funcName}')) {\n"; + $output .= "function {$_funcName}(Smarty_Internal_Template \$_smarty_tpl,\$params) {\n"; + $output .= $_paramsCode; + $output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new \\Smarty\\Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}\n"; + $output .= "?>\n"; + $compiler->parser->current_buffer->append_subtree( + $compiler->parser, + new \Smarty\ParseTree\Tag( + $compiler->parser, + $output + ) + ); + $compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode); + $output = "cStyleComment("/ {$_funcName} ") . "\n\n"; + $output .= "?>\n"; + $compiler->parser->current_buffer->append_subtree( + $compiler->parser, + new \Smarty\ParseTree\Tag( + $compiler->parser, + $output + ) + ); + $compiler->parent_compiler->blockOrFunctionCode .= $compiler->parser->current_buffer->to_smarty_php($compiler->parser); + // restore old buffer + $compiler->parser->current_buffer = $saved_data[1]; + // restore old status + $compiler->template->compiled->has_nocache_code = $saved_data[2]; + $compiler->template->caching = $saved_data[3]; + return true; + } + + /** + * Remove nocache code + * + * @param $match + * + * @return string + */ + public function removeNocache($match) { + $code = + preg_replace( + "/((<\?php )?echo '\/\*%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/)|(\/\*\/%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/", + '', + $match[0] + ); + $code = str_replace(['\\\'', '\\\\\''], ['\'', '\\\''], $code); + return $code; + } +} diff --git a/src/Compile/FunctionTag.php b/src/Compile/FunctionTag.php new file mode 100644 index 00000000..85b54fdb --- /dev/null +++ b/src/Compile/FunctionTag.php @@ -0,0 +1,72 @@ +getAttributes($compiler, $args); + if ($_attr['nocache'] === true) { + $compiler->trigger_template_error('nocache option not allowed', null, true); + } + unset($_attr['nocache']); + $_name = trim($_attr['name'], '\'"'); + + if (!preg_match('/^[a-zA-Z0-9_\x80-\xff]+$/', $_name)) { + $compiler->trigger_template_error("Function name contains invalid characters: {$_name}", null, true); + } + + $compiler->parent_compiler->tpl_function[$_name] = []; + $save = [ + $_attr, $compiler->parser->current_buffer, $compiler->template->compiled->has_nocache_code, + $compiler->template->caching, + ]; + $this->openTag($compiler, 'function', $save); + // Init temporary context + $compiler->parser->current_buffer = new \Smarty\ParseTree\Template(); + $compiler->template->compiled->has_nocache_code = false; + return true; + } +} \ No newline at end of file diff --git a/src/Compile/IfClose.php b/src/Compile/IfClose.php new file mode 100644 index 00000000..d0804b12 --- /dev/null +++ b/src/Compile/IfClose.php @@ -0,0 +1,45 @@ +nocache) { + $compiler->tag_nocache = true; + } + [$nesting, $compiler->nocache] = $this->closeTag($compiler, ['if', 'else', 'elseif']); + $tmp = ''; + for ($i = 0; $i < $nesting; $i++) { + $tmp .= '}'; + } + return ""; + } +} diff --git a/src/Compile/IfTag.php b/src/Compile/IfTag.php new file mode 100644 index 00000000..bdb54a0a --- /dev/null +++ b/src/Compile/IfTag.php @@ -0,0 +1,66 @@ +getAttributes($compiler, $args); + $this->openTag($compiler, 'if', [1, $compiler->nocache]); + // must whole block be nocache ? + $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; + if (!isset($parameter['if condition'])) { + $compiler->trigger_template_error('missing if condition', null, true); + } + if (is_array($parameter['if condition'])) { + if (is_array($parameter['if condition']['var'])) { + $var = $parameter['if condition']['var']['var']; + } else { + $var = $parameter['if condition']['var']; + } + if ($compiler->nocache) { + // create nocache var to make it know for further compiling + $compiler->setNocacheInVariable($var); + } + $prefixVar = $compiler->getNewPrefixVariable(); + $_output = "\n"; + $assignAttr = []; + $assignAttr[]['value'] = $prefixVar; + $assignCompiler = new Assign(); + if (is_array($parameter['if condition']['var'])) { + $assignAttr[]['var'] = $parameter['if condition']['var']['var']; + $_output .= $assignCompiler->compile( + $assignAttr, + $compiler, + ['smarty_internal_index' => $parameter['if condition']['var']['smarty_internal_index']] + ); + } else { + $assignAttr[]['var'] = $parameter['if condition']['var']; + $_output .= $assignCompiler->compile($assignAttr, $compiler, []); + } + $_output .= ""; + return $_output; + } else { + return ""; + } + } +} \ No newline at end of file diff --git a/src/Compile/Nocache.php b/src/Compile/Nocache.php new file mode 100644 index 00000000..7cc14244 --- /dev/null +++ b/src/Compile/Nocache.php @@ -0,0 +1,40 @@ +getAttributes($compiler, $args); + $this->openTag($compiler, 'nocache', [$compiler->nocache]); + // enter nocache mode + $compiler->nocache = true; + // this tag does not return compiled code + $compiler->has_code = false; + return true; + } +} \ No newline at end of file diff --git a/src/Compile/NocacheClose.php b/src/Compile/NocacheClose.php new file mode 100644 index 00000000..4d7deeef --- /dev/null +++ b/src/Compile/NocacheClose.php @@ -0,0 +1,40 @@ +getAttributes($compiler, $args); + // leave nocache mode + [$compiler->nocache] = $this->closeTag($compiler, ['nocache']); + // this tag does not return compiled code + $compiler->has_code = false; + return true; + } +} diff --git a/src/Compile/smarty_internal_compile_parent.php b/src/Compile/ParentTag.php similarity index 54% rename from src/Compile/smarty_internal_compile_parent.php rename to src/Compile/ParentTag.php index d1148948..fc0b40a5 100644 --- a/src/Compile/smarty_internal_compile_parent.php +++ b/src/Compile/ParentTag.php @@ -8,26 +8,26 @@ * file that was distributed with this source code. */ -use Smarty\Compile\Child; +namespace Smarty\Compile; /** * Smarty Internal Plugin Compile Parent Class * * @author Uwe Tews */ -class Smarty_Internal_Compile_Parent extends Child -{ - /** - * Tag name - * - * @var string - */ - public $tag = 'parent'; +class ParentTag extends Child { - /** - * Block type - * - * @var string - */ - public $blockType = 'Parent'; + /** + * Tag name + * + * @var string + */ + protected $tag = 'parent'; + + /** + * Block type + * + * @var string + */ + protected $blockType = 'Parent'; } diff --git a/src/Compile/PrivateSpecialVariable.php b/src/Compile/PrivateSpecialVariable.php index 8963e1cf..7eea562d 100644 --- a/src/Compile/PrivateSpecialVariable.php +++ b/src/Compile/PrivateSpecialVariable.php @@ -10,10 +10,10 @@ namespace Smarty\Compile; -use _Capture; +use Smarty\Compile\Capture; use Smarty\Compile\Base; -use Smarty_Internal_Compile_Foreach; -use Smarty_Internal_Compile_Section; +use Smarty\Compile\ForeachTag; +use Smarty\Compile\Section; use Smarty_Internal_TemplateCompilerBase; /** @@ -45,11 +45,11 @@ class PrivateSpecialVariable extends Base { ) { switch ($variable) { case 'foreach': - return (new Smarty_Internal_Compile_Foreach())->compileSpecialVariable($compiler, $_index); + return (new ForeachTag())->compileSpecialVariable($compiler, $_index); case 'section': - return (new Smarty_Internal_Compile_Section())->compileSpecialVariable($compiler, $_index); + return (new Section())->compileSpecialVariable($compiler, $_index); case 'capture': - return (new _Capture())->compileSpecialVariable($compiler, $_index); + return (new Capture())->compileSpecialVariable($compiler, $_index); case 'now': return 'time()'; case 'cookies': diff --git a/src/Compile/Rdelim.php b/src/Compile/Rdelim.php new file mode 100644 index 00000000..765370a9 --- /dev/null +++ b/src/Compile/Rdelim.php @@ -0,0 +1,37 @@ +smarty->right_delimiter; + } +} diff --git a/src/Compile/Section.php b/src/Compile/Section.php new file mode 100644 index 00000000..cab698b5 --- /dev/null +++ b/src/Compile/Section.php @@ -0,0 +1,395 @@ +loopNesting++; + // check and get attributes + $_attr = $this->getAttributes($compiler, $args); + $attributes = ['name' => $compiler->getId($_attr['name'])]; + unset($_attr['name']); + foreach ($attributes as $a => $v) { + if ($v === false) { + $compiler->trigger_template_error("'{$a}' attribute/variable has illegal value", null, true); + } + } + $local = "\$__section_{$attributes['name']}_" . $this->counter++ . '_'; + $sectionVar = "\$_smarty_tpl->tpl_vars['__smarty_section_{$attributes['name']}']"; + $this->openTag($compiler, 'section', ['section', $compiler->nocache, $local, $sectionVar]); + // maybe nocache because of nocache variables + $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; + $initLocal = []; + $initNamedProperty = []; + $initFor = []; + $incFor = []; + $cmpFor = []; + $propValue = [ + 'index' => "{$sectionVar}->value['index']", 'show' => 'true', 'step' => 1, + 'iteration' => "{$local}iteration", + ]; + $propType = ['index' => 2, 'iteration' => 2, 'show' => 0, 'step' => 0,]; + // search for used tag attributes + $this->scanForProperties($attributes, $compiler); + if (!empty($this->matchResults['named'])) { + $namedAttr = $this->matchResults['named']; + } + if (isset($_attr['properties']) && preg_match_all("/['](.*?)[']/", $_attr['properties'], $match)) { + foreach ($match[1] as $prop) { + if (in_array($prop, $this->nameProperties)) { + $namedAttr[$prop] = true; + } else { + $compiler->trigger_template_error("Invalid property '{$prop}'", null, true); + } + } + } + $namedAttr['index'] = true; + $output = " $attr_value) { + switch ($attr_name) { + case 'loop': + if (is_numeric($attr_value)) { + $v = (int)$attr_value; + $t = 0; + } else { + $v = "(is_array(@\$_loop=$attr_value) ? count(\$_loop) : max(0, (int) \$_loop))"; + $t = 1; + } + if ($t === 1) { + $initLocal['loop'] = $v; + $v = "{$local}loop"; + } + break; + case 'show': + if (is_bool($attr_value)) { + $v = $attr_value ? 'true' : 'false'; + $t = 0; + } else { + $v = "(bool) $attr_value"; + $t = 3; + } + break; + case 'step': + if (is_numeric($attr_value)) { + $v = (int)$attr_value; + $v = ($v === 0) ? 1 : $v; + $t = 0; + break; + } + $initLocal['step'] = "((int)@$attr_value) === 0 ? 1 : (int)@$attr_value"; + $v = "{$local}step"; + $t = 2; + break; + case 'max': + case 'start': + if (is_numeric($attr_value)) { + $v = (int)$attr_value; + $t = 0; + break; + } + $v = "(int)@$attr_value"; + $t = 3; + break; + } + if ($t === 3 && $compiler->getId($attr_value)) { + $t = 1; + } + $propValue[$attr_name] = $v; + $propType[$attr_name] = $t; + } + if (isset($namedAttr['step'])) { + $initNamedProperty['step'] = $propValue['step']; + } + if (isset($namedAttr['iteration'])) { + $propValue['iteration'] = "{$sectionVar}->value['iteration']"; + } + $incFor['iteration'] = "{$propValue['iteration']}++"; + $initFor['iteration'] = "{$propValue['iteration']} = 1"; + if ($propType['step'] === 0) { + if ($propValue['step'] === 1) { + $incFor['index'] = "{$sectionVar}->value['index']++"; + } elseif ($propValue['step'] > 1) { + $incFor['index'] = "{$sectionVar}->value['index'] += {$propValue['step']}"; + } else { + $incFor['index'] = "{$sectionVar}->value['index'] -= " . -$propValue['step']; + } + } else { + $incFor['index'] = "{$sectionVar}->value['index'] += {$propValue['step']}"; + } + if (!isset($propValue['max'])) { + $propValue['max'] = $propValue['loop']; + $propType['max'] = $propType['loop']; + } elseif ($propType['max'] !== 0) { + $propValue['max'] = "{$propValue['max']} < 0 ? {$propValue['loop']} : {$propValue['max']}"; + $propType['max'] = 1; + } else { + if ($propValue['max'] < 0) { + $propValue['max'] = $propValue['loop']; + $propType['max'] = $propType['loop']; + } + } + if (!isset($propValue['start'])) { + $start_code = + [1 => "{$propValue['step']} > 0 ? ", 2 => '0', 3 => ' : ', 4 => $propValue['loop'], 5 => ' - 1']; + if ($propType['loop'] === 0) { + $start_code[5] = ''; + $start_code[4] = $propValue['loop'] - 1; + } + if ($propType['step'] === 0) { + if ($propValue['step'] > 0) { + $start_code = [1 => '0']; + $propType['start'] = 0; + } else { + $start_code[1] = $start_code[2] = $start_code[3] = ''; + $propType['start'] = $propType['loop']; + } + } else { + $propType['start'] = 1; + } + $propValue['start'] = join('', $start_code); + } else { + $start_code = + [ + 1 => "{$propValue['start']} < 0 ? ", 2 => 'max(', 3 => "{$propValue['step']} > 0 ? ", 4 => '0', + 5 => ' : ', 6 => '-1', 7 => ', ', 8 => "{$propValue['start']} + {$propValue['loop']}", 10 => ')', + 11 => ' : ', 12 => 'min(', 13 => $propValue['start'], 14 => ', ', + 15 => "{$propValue['step']} > 0 ? ", 16 => $propValue['loop'], 17 => ' : ', + 18 => $propType['loop'] === 0 ? $propValue['loop'] - 1 : "{$propValue['loop']} - 1", + 19 => ')', + ]; + if ($propType['step'] === 0) { + $start_code[3] = $start_code[5] = $start_code[15] = $start_code[17] = ''; + if ($propValue['step'] > 0) { + $start_code[6] = $start_code[18] = ''; + } else { + $start_code[4] = $start_code[16] = ''; + } + } + if ($propType['start'] === 0) { + if ($propType['loop'] === 0) { + $start_code[8] = $propValue['start'] + $propValue['loop']; + } + $propType['start'] = $propType['step'] + $propType['loop']; + $start_code[1] = ''; + if ($propValue['start'] < 0) { + for ($i = 11; $i <= 19; $i++) { + $start_code[$i] = ''; + } + if ($propType['start'] === 0) { + $start_code = [ + max( + $propValue['step'] > 0 ? 0 : -1, + $propValue['start'] + $propValue['loop'] + ), + ]; + } + } else { + for ($i = 1; $i <= 11; $i++) { + $start_code[$i] = ''; + } + if ($propType['start'] === 0) { + $start_code = + [ + min( + $propValue['step'] > 0 ? $propValue['loop'] : $propValue['loop'] - 1, + $propValue['start'] + ), + ]; + } + } + } + $propValue['start'] = join('', $start_code); + } + if ($propType['start'] !== 0) { + $initLocal['start'] = $propValue['start']; + $propValue['start'] = "{$local}start"; + } + $initFor['index'] = "{$sectionVar}->value['index'] = {$propValue['start']}"; + if (!isset($_attr['start']) && !isset($_attr['step']) && !isset($_attr['max'])) { + $propValue['total'] = $propValue['loop']; + $propType['total'] = $propType['loop']; + } else { + $propType['total'] = + $propType['start'] + $propType['loop'] + $propType['step'] + $propType['max']; + if ($propType['total'] === 0) { + $propValue['total'] = + min( + ceil( + ($propValue['step'] > 0 ? $propValue['loop'] - $propValue['start'] : + (int)$propValue['start'] + 1) / abs($propValue['step']) + ), + $propValue['max'] + ); + } else { + $total_code = [ + 1 => 'min(', 2 => 'ceil(', 3 => '(', 4 => "{$propValue['step']} > 0 ? ", + 5 => $propValue['loop'], 6 => ' - ', 7 => $propValue['start'], 8 => ' : ', + 9 => $propValue['start'], 10 => '+ 1', 11 => ')', 12 => '/ ', 13 => 'abs(', + 14 => $propValue['step'], 15 => ')', 16 => ')', 17 => ", {$propValue['max']})", + ]; + if (!isset($propValue['max'])) { + $total_code[1] = $total_code[17] = ''; + } + if ($propType['loop'] + $propType['start'] === 0) { + $total_code[5] = $propValue['loop'] - $propValue['start']; + $total_code[6] = $total_code[7] = ''; + } + if ($propType['start'] === 0) { + $total_code[9] = (int)$propValue['start'] + 1; + $total_code[10] = ''; + } + if ($propType['step'] === 0) { + $total_code[13] = $total_code[15] = ''; + if ($propValue['step'] === 1 || $propValue['step'] === -1) { + $total_code[2] = $total_code[12] = $total_code[14] = $total_code[16] = ''; + } elseif ($propValue['step'] < 0) { + $total_code[14] = -$propValue['step']; + } + $total_code[4] = ''; + if ($propValue['step'] > 0) { + $total_code[8] = $total_code[9] = $total_code[10] = ''; + } else { + $total_code[5] = $total_code[6] = $total_code[7] = $total_code[8] = ''; + } + } + $propValue['total'] = join('', $total_code); + } + } + if (isset($namedAttr['loop'])) { + $initNamedProperty['loop'] = "'loop' => {$propValue['loop']}"; + } + if (isset($namedAttr['total'])) { + $initNamedProperty['total'] = "'total' => {$propValue['total']}"; + if ($propType['total'] > 0) { + $propValue['total'] = "{$sectionVar}->value['total']"; + } + } elseif ($propType['total'] > 0) { + $initLocal['total'] = $propValue['total']; + $propValue['total'] = "{$local}total"; + } + $cmpFor['iteration'] = "{$propValue['iteration']} <= {$propValue['total']}"; + foreach ($initLocal as $key => $code) { + $output .= "{$local}{$key} = {$code};\n"; + } + $_vars = 'array(' . join(', ', $initNamedProperty) . ')'; + $output .= "{$sectionVar} = new \\Smarty\\Variable({$_vars});\n"; + $cond_code = "{$propValue['total']} !== 0"; + if ($propType['total'] === 0) { + if ($propValue['total'] === 0) { + $cond_code = 'false'; + } else { + $cond_code = 'true'; + } + } + if ($propType['show'] > 0) { + $output .= "{$local}show = {$propValue['show']} ? {$cond_code} : false;\n"; + $output .= "if ({$local}show) {\n"; + } elseif ($propValue['show'] === 'true') { + $output .= "if ({$cond_code}) {\n"; + } else { + $output .= "if (false) {\n"; + } + $jinit = join(', ', $initFor); + $jcmp = join(', ', $cmpFor); + $jinc = join(', ', $incFor); + $output .= "for ({$jinit}; {$jcmp}; {$jinc}){\n"; + if (isset($namedAttr['rownum'])) { + $output .= "{$sectionVar}->value['rownum'] = {$propValue['iteration']};\n"; + } + if (isset($namedAttr['index_prev'])) { + $output .= "{$sectionVar}->value['index_prev'] = {$propValue['index']} - {$propValue['step']};\n"; + } + if (isset($namedAttr['index_next'])) { + $output .= "{$sectionVar}->value['index_next'] = {$propValue['index']} + {$propValue['step']};\n"; + } + if (isset($namedAttr['first'])) { + $output .= "{$sectionVar}->value['first'] = ({$propValue['iteration']} === 1);\n"; + } + if (isset($namedAttr['last'])) { + $output .= "{$sectionVar}->value['last'] = ({$propValue['iteration']} === {$propValue['total']});\n"; + } + $output .= '?>'; + return $output; + } +} \ No newline at end of file diff --git a/src/Compile/SectionClose.php b/src/Compile/SectionClose.php new file mode 100644 index 00000000..e855f172 --- /dev/null +++ b/src/Compile/SectionClose.php @@ -0,0 +1,50 @@ +loopNesting--; + // must endblock be nocache? + if ($compiler->nocache) { + $compiler->tag_nocache = true; + } + [$openTag, $compiler->nocache, $local, $sectionVar] = + $this->closeTag($compiler, ['section', 'sectionelse']); + $output = "'; + return $output; + } +} diff --git a/src/Compile/SectionElse.php b/src/Compile/SectionElse.php new file mode 100644 index 00000000..67df3abc --- /dev/null +++ b/src/Compile/SectionElse.php @@ -0,0 +1,30 @@ +getAttributes($compiler, $args); + [$openTag, $nocache, $local, $sectionVar] = $this->closeTag($compiler, ['section']); + $this->openTag($compiler, 'sectionelse', ['sectionelse', $nocache, $local, $sectionVar]); + return ""; + } +} \ No newline at end of file diff --git a/src/Compile/Setfilter.php b/src/Compile/Setfilter.php new file mode 100644 index 00000000..3dc8e321 --- /dev/null +++ b/src/Compile/Setfilter.php @@ -0,0 +1,31 @@ +variable_filter_stack[] = $compiler->variable_filters; + $compiler->variable_filters = $parameter['modifier_list']; + // this tag does not return compiled code + $compiler->has_code = false; + return true; + } +} \ No newline at end of file diff --git a/src/Compile/SetfilterClose.php b/src/Compile/SetfilterClose.php new file mode 100644 index 00000000..92acdeb2 --- /dev/null +++ b/src/Compile/SetfilterClose.php @@ -0,0 +1,44 @@ +getAttributes($compiler, $args); + // reset variable filter to previous state + if (count($compiler->variable_filter_stack)) { + $compiler->variable_filters = array_pop($compiler->variable_filter_stack); + } else { + $compiler->variable_filters = []; + } + // this tag does not return compiled code + $compiler->has_code = false; + return true; + } +} diff --git a/src/Compile/Whileclose.php b/src/Compile/WhileClose.php similarity index 96% rename from src/Compile/Whileclose.php rename to src/Compile/WhileClose.php index 3f17c528..3e7d63b4 100644 --- a/src/Compile/Whileclose.php +++ b/src/Compile/WhileClose.php @@ -18,7 +18,7 @@ use Smarty_Internal_TemplateCompilerBase; * @package Smarty * @subpackage Compiler */ -class Whileclose extends Base { +class WhileClose extends Base { /** * Compiles code for the {/while} tag diff --git a/src/Compile/smarty_internal_compile__registered_Private_block.php b/src/Compile/smarty_internal_compile__registered_Private_block.php deleted file mode 100644 index 1f2add11..00000000 --- a/src/Compile/smarty_internal_compile__registered_Private_block.php +++ /dev/null @@ -1,74 +0,0 @@ -smarty->registered_plugins[ \Smarty\Smarty::PLUGIN_BLOCK ][ $tag ])) { - $tag_info = $compiler->smarty->registered_plugins[ \Smarty\Smarty::PLUGIN_BLOCK ][ $tag ]; - $callback = $tag_info[ 0 ]; - if (is_array($callback)) { - if (is_object($callback[ 0 ])) { - $callable = "array(\$_block_plugin{$this->nesting}, '{$callback[1]}')"; - $callback = - array("\$_smarty_tpl->smarty->registered_plugins['block']['{$tag}'][0][0]", "->{$callback[1]}"); - } else { - $callable = "array(\$_block_plugin{$this->nesting}, '{$callback[1]}')"; - $callback = - array("\$_smarty_tpl->smarty->registered_plugins['block']['{$tag}'][0][0]", "::{$callback[1]}"); - } - } else { - $callable = "\$_block_plugin{$this->nesting}"; - $callback = array("\$_smarty_tpl->smarty->registered_plugins['block']['{$tag}'][0]", ''); - } - } else { - $tag_info = $compiler->default_handler_plugins[ \Smarty\Smarty::PLUGIN_BLOCK ][ $tag ]; - $callback = $tag_info[ 0 ]; - if (is_array($callback)) { - $callable = "array('{$callback[0]}', '{$callback[1]}')"; - $callback = "{$callback[1]}::{$callback[1]}"; - } else { - $callable = null; - } - } - $compiler->tag_nocache = !$tag_info[ 1 ] | $compiler->tag_nocache; - $_paramsArray = array(); - foreach ($_attr as $_key => $_value) { - if (is_int($_key)) { - $_paramsArray[] = "$_key=>$_value"; - } elseif ($compiler->template->caching && in_array($_key, $tag_info[ 2 ])) { - $_value = str_replace('\'', "^#^", $_value); - $_paramsArray[] = "'$_key'=>^#^.var_export($_value,true).^#^"; - } else { - $_paramsArray[] = "'$_key'=>$_value"; - } - } - return array($callback, $_paramsArray, $callable); - } -} diff --git a/src/Compile/smarty_internal_compile_capture.php b/src/Compile/smarty_internal_compile_capture.php deleted file mode 100644 index 4c829205..00000000 --- a/src/Compile/smarty_internal_compile_capture.php +++ /dev/null @@ -1,105 +0,0 @@ -smarty->ext->_capture->getBuffer($_smarty_tpl' . - (isset($parameter[ 1 ]) ? ", {$parameter[ 1 ]})" : ')'); - } - - /** - * Compiles code for the {capture} tag - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * @param null $parameter - * - * @return string compiled code - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - // check and get attributes - $_attr = $this->getAttributes($compiler, $args, $parameter, 'capture'); - $buffer = isset($_attr[ 'name' ]) ? $_attr[ 'name' ] : "'default'"; - $assign = isset($_attr[ 'assign' ]) ? $_attr[ 'assign' ] : 'null'; - $append = isset($_attr[ 'append' ]) ? $_attr[ 'append' ] : 'null'; - $compiler->_cache[ 'capture_stack' ][] = array($compiler->nocache); - // maybe nocache because of nocache variables - $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; - $_output = "smarty->ext->_capture->open(\$_smarty_tpl, $buffer, $assign, $append);?>"; - return $_output; - } -} - -/** - * Smarty Internal Plugin Compile Captureclose Class - * - * @package Smarty - * @subpackage Compiler - */ -class _CaptureClose extends Base -{ - /** - * Compiles code for the {/capture} tag - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * @param null $parameter - * - * @return string compiled code - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - // check and get attributes - $_attr = $this->getAttributes($compiler, $args, $parameter, '/capture'); - // must endblock be nocache? - if ($compiler->nocache) { - $compiler->tag_nocache = true; - } - [$compiler->nocache] = array_pop($compiler->_cache[ 'capture_stack' ]); - return "smarty->ext->_capture->close(\$_smarty_tpl);?>"; - } -} diff --git a/src/Compile/smarty_internal_compile_extends.php b/src/Compile/smarty_internal_compile_extends.php deleted file mode 100644 index ba556453..00000000 --- a/src/Compile/smarty_internal_compile_extends.php +++ /dev/null @@ -1,161 +0,0 @@ -getAttributes($compiler, $args); - if ($_attr[ 'nocache' ] === true) { - $compiler->trigger_template_error('nocache option not allowed', $compiler->parser->lex->line - 1); - } - if (strpos($_attr[ 'file' ], '$_tmp') !== false) { - $compiler->trigger_template_error('illegal value for file attribute', $compiler->parser->lex->line - 1); - } - // add code to initialize inheritance - $this->registerInit($compiler, true); - $file = trim($_attr[ 'file' ], '\'"'); - if (strlen($file) > 8 && substr($file, 0, 8) === 'extends:') { - // generate code for each template - $files = array_reverse(explode('|', substr($file, 8))); - $i = 0; - foreach ($files as $file) { - if ($file[ 0 ] === '"') { - $file = trim($file, '".'); - } else { - $file = "'{$file}'"; - } - $i++; - if ($i === count($files) && isset($_attr[ 'extends_resource' ])) { - $this->compileEndChild($compiler); - } - $this->compileInclude($compiler, $file); - } - if (!isset($_attr[ 'extends_resource' ])) { - $this->compileEndChild($compiler); - } - } else { - $this->compileEndChild($compiler, $_attr[ 'file' ]); - } - $compiler->has_code = false; - return ''; - } - - /** - * Add code for inheritance endChild() method to end of template - * - * @param \Smarty_Internal_TemplateCompilerBase $compiler - * @param null|string $template optional inheritance parent template - * - * @throws \SmartyCompilerException - * @throws \SmartyException - */ - private function compileEndChild(Smarty_Internal_TemplateCompilerBase $compiler, $template = null) - { - $inlineUids = ''; - if (isset($template) && $compiler->smarty->merge_compiled_includes) { - $code = $compiler->compileTag('include', array($template, array('scope' => 'parent'))); - if (preg_match('/([,][\s]*[\'][a-z0-9]+[\'][,][\s]*[\']content.*[\'])[)]/', $code, $match)) { - $inlineUids = $match[ 1 ]; - } - } - $compiler->parser->template_postfix[] = new \Smarty\ParseTree\Tag( - $compiler->parser, - 'inheritance->endChild($_smarty_tpl' . - (isset($template) ? - ", {$template}{$inlineUids}" : - '') . ");\n?>" - ); - } - - /** - * Add code for including subtemplate to end of template - * - * @param \Smarty_Internal_TemplateCompilerBase $compiler - * @param string $template subtemplate name - * - * @throws \SmartyCompilerException - * @throws \SmartyException - */ - private function compileInclude(Smarty_Internal_TemplateCompilerBase $compiler, $template) - { - $compiler->parser->template_postfix[] = new \Smarty\ParseTree\Tag( - $compiler->parser, - $compiler->compileTag( - 'include', - array( - $template, - array('scope' => 'parent') - ) - ) - ); - } - - /** - * Create source code for {extends} from source components array - * - * @param \Smarty_Internal_Template $template - * - * @return string - */ - public static function extendsSourceArrayCode(Smarty_Internal_Template $template) - { - $resources = array(); - foreach ($template->source->components as $source) { - $resources[] = $source->resource; - } - return $template->smarty->left_delimiter . 'extends file=\'extends:' . join('|', $resources) . - '\' extends_resource=true' . $template->smarty->right_delimiter; - } -} diff --git a/src/Compile/smarty_internal_compile_for.php b/src/Compile/smarty_internal_compile_for.php deleted file mode 100644 index 9494dd57..00000000 --- a/src/Compile/smarty_internal_compile_for.php +++ /dev/null @@ -1,166 +0,0 @@ -loopNesting++; - if ($parameter === 0) { - $this->required_attributes = array('start', 'to'); - $this->optional_attributes = array('max', 'step'); - } else { - $this->required_attributes = array('start', 'ifexp', 'var', 'step'); - $this->optional_attributes = array(); - } - $this->mapCache = array(); - // check and get attributes - $_attr = $this->getAttributes($compiler, $args); - $output = "tpl_vars[$var] = new \\Smarty\\Variable(null, \$_smarty_tpl->isRenderingCache);\n"; - $output .= "\$_smarty_tpl->tpl_vars[$var]->value{$index} = {$_statement['value']};\n"; - } - if (is_array($_attr[ 'var' ])) { - $var = $_attr[ 'var' ][ 'var' ]; - $index = $_attr[ 'var' ][ 'smarty_internal_index' ]; - } else { - $var = $_attr[ 'var' ]; - $index = ''; - } - $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' ])) { - $var = $_statement[ 'var' ][ 'var' ]; - $index = $_statement[ 'var' ][ 'smarty_internal_index' ]; - } else { - $var = $_statement[ 'var' ]; - $index = ''; - } - $output .= "\$_smarty_tpl->tpl_vars[$var] = new \\Smarty\\Variable(null, \$_smarty_tpl->isRenderingCache);"; - if (isset($_attr[ 'step' ])) { - $output .= "\$_smarty_tpl->tpl_vars[$var]->step = $_attr[step];"; - } else { - $output .= "\$_smarty_tpl->tpl_vars[$var]->step = 1;"; - } - if (isset($_attr[ 'max' ])) { - $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 .= "\$_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 (\$_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 .= '?>'; - $this->openTag($compiler, 'for', array('for', $compiler->nocache)); - // maybe nocache because of nocache variables - $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; - // return compiled code - return $output; - } -} - -/** - * Smarty Internal Plugin Compile Forelse Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Forelse extends Base -{ - /** - * Compiles code for the {forelse} tag - * - * @param array $args array with attributes from parser - * @param object $compiler compiler object - * @param array $parameter array with compilation parameter - * - * @return string compiled code - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - // check and get attributes - $_attr = $this->getAttributes($compiler, $args); - [$openTag, $nocache] = $this->closeTag($compiler, array('for')); - $this->openTag($compiler, 'forelse', array('forelse', $nocache)); - return ""; - } -} - -/** - * Smarty Internal Plugin Compile Forclose Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Forclose extends Base -{ - /** - * Compiles code for the {/for} tag - * - * @param array $args array with attributes from parser - * @param object $compiler compiler object - * @param array $parameter array with compilation parameter - * - * @return string compiled code - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - $compiler->loopNesting--; - // check and get attributes - $_attr = $this->getAttributes($compiler, $args); - // must endblock be nocache? - if ($compiler->nocache) { - $compiler->tag_nocache = true; - } - [$openTag, $compiler->nocache] = $this->closeTag($compiler, array('for', 'forelse')); - $output = ""; - return $output; - } -} diff --git a/src/Compile/smarty_internal_compile_foreach.php b/src/Compile/smarty_internal_compile_foreach.php deleted file mode 100644 index 3a4cdd9b..00000000 --- a/src/Compile/smarty_internal_compile_foreach.php +++ /dev/null @@ -1,346 +0,0 @@ -loopNesting++; - // init - $this->isNamed = false; - // check and get attributes - $_attr = $this->getAttributes($compiler, $args); - $from = $_attr[ 'from' ]; - $item = $compiler->getId($_attr[ 'item' ]); - if ($item === false) { - $item = $compiler->getVariableName($_attr[ 'item' ]); - } - $key = $name = null; - $attributes = array('item' => $item); - if (isset($_attr[ 'key' ])) { - $key = $compiler->getId($_attr[ 'key' ]); - if ($key === false) { - $key = $compiler->getVariableName($_attr[ 'key' ]); - } - $attributes[ 'key' ] = $key; - } - if (isset($_attr[ 'name' ])) { - $this->isNamed = true; - $name = $attributes[ 'name' ] = $compiler->getId($_attr[ 'name' ]); - } - foreach ($attributes as $a => $v) { - if ($v === false) { - $compiler->trigger_template_error("'{$a}' attribute/variable has illegal value", null, true); - } - } - $fromName = $compiler->getVariableName($_attr[ 'from' ]); - if ($fromName) { - foreach (array('item', 'key') as $a) { - if (isset($attributes[ $a ]) && $attributes[ $a ] === $fromName) { - $compiler->trigger_template_error( - "'{$a}' and 'from' may not have same variable name '{$fromName}'", - null, - true - ); - } - } - } - $itemVar = "\$_smarty_tpl->tpl_vars['{$item}']"; - $local = '$__foreach_' . $attributes[ 'item' ] . '_' . $this->counter++ . '_'; - // search for used tag attributes - $itemAttr = array(); - $namedAttr = array(); - $this->scanForProperties($attributes, $compiler); - if (!empty($this->matchResults[ 'item' ])) { - $itemAttr = $this->matchResults[ 'item' ]; - } - if (!empty($this->matchResults[ 'named' ])) { - $namedAttr = $this->matchResults[ 'named' ]; - } - if (isset($_attr[ 'properties' ]) && preg_match_all('/[\'](.*?)[\']/', $_attr[ 'properties' ], $match)) { - foreach ($match[ 1 ] as $prop) { - if (in_array($prop, $this->itemProperties)) { - $itemAttr[ $prop ] = true; - } else { - $compiler->trigger_template_error("Invalid property '{$prop}'", null, true); - } - } - if ($this->isNamed) { - foreach ($match[ 1 ] as $prop) { - if (in_array($prop, $this->nameProperties)) { - $nameAttr[ $prop ] = true; - } else { - $compiler->trigger_template_error("Invalid property '{$prop}'", null, true); - } - } - } - } - if (isset($itemAttr[ 'first' ])) { - $itemAttr[ 'index' ] = true; - } - if (isset($namedAttr[ 'first' ])) { - $namedAttr[ 'index' ] = true; - } - if (isset($namedAttr[ 'last' ])) { - $namedAttr[ 'iteration' ] = true; - $namedAttr[ 'total' ] = true; - } - if (isset($itemAttr[ 'last' ])) { - $itemAttr[ 'iteration' ] = true; - $itemAttr[ 'total' ] = true; - } - if (isset($namedAttr[ 'show' ])) { - $namedAttr[ 'total' ] = true; - } - if (isset($itemAttr[ 'show' ])) { - $itemAttr[ 'total' ] = true; - } - $keyTerm = ''; - if (isset($attributes[ 'key' ])) { - $keyTerm = "\$_smarty_tpl->tpl_vars['{$key}']->value => "; - } - if (isset($itemAttr[ 'key' ])) { - $keyTerm = "{$itemVar}->key => "; - } - if ($this->isNamed) { - $foreachVar = "\$_smarty_tpl->tpl_vars['__smarty_foreach_{$attributes['name']}']"; - } - $needTotal = isset($itemAttr[ 'total' ]); - // Register tag - $this->openTag( - $compiler, - 'foreach', - array('foreach', $compiler->nocache, $local, $itemVar, empty($itemAttr) ? 1 : 2) - ); - // maybe nocache because of nocache variables - $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; - // generate output code - $output = "smarty->ext->_foreach->init(\$_smarty_tpl, $from, " . - var_export($item, true); - if ($name || $needTotal || $key) { - $output .= ', ' . var_export($needTotal, true); - } - if ($name || $key) { - $output .= ', ' . var_export($key, true); - } - if ($name) { - $output .= ', ' . var_export($name, true) . ', ' . var_export($namedAttr, true); - } - $output .= ");\n"; - if (isset($itemAttr[ 'show' ])) { - $output .= "{$itemVar}->show = ({$itemVar}->total > 0);\n"; - } - if (isset($itemAttr[ 'iteration' ])) { - $output .= "{$itemVar}->iteration = 0;\n"; - } - if (isset($itemAttr[ 'index' ])) { - $output .= "{$itemVar}->index = -1;\n"; - } - $output .= "{$itemVar}->do_else = true;\n"; - $output .= "if (\$_from !== null) foreach (\$_from as {$keyTerm}{$itemVar}->value) {\n"; - $output .= "{$itemVar}->do_else = false;\n"; - if (isset($attributes[ 'key' ]) && isset($itemAttr[ 'key' ])) { - $output .= "\$_smarty_tpl->tpl_vars['{$key}']->value = {$itemVar}->key;\n"; - } - if (isset($itemAttr[ 'iteration' ])) { - $output .= "{$itemVar}->iteration++;\n"; - } - if (isset($itemAttr[ 'index' ])) { - $output .= "{$itemVar}->index++;\n"; - } - if (isset($itemAttr[ 'first' ])) { - $output .= "{$itemVar}->first = !{$itemVar}->index;\n"; - } - if (isset($itemAttr[ 'last' ])) { - $output .= "{$itemVar}->last = {$itemVar}->iteration === {$itemVar}->total;\n"; - } - if (isset($foreachVar)) { - if (isset($namedAttr[ 'iteration' ])) { - $output .= "{$foreachVar}->value['iteration']++;\n"; - } - if (isset($namedAttr[ 'index' ])) { - $output .= "{$foreachVar}->value['index']++;\n"; - } - if (isset($namedAttr[ 'first' ])) { - $output .= "{$foreachVar}->value['first'] = !{$foreachVar}->value['index'];\n"; - } - if (isset($namedAttr[ 'last' ])) { - $output .= "{$foreachVar}->value['last'] = {$foreachVar}->value['iteration'] === {$foreachVar}->value['total'];\n"; - } - } - if (!empty($itemAttr)) { - $output .= "{$local}saved = {$itemVar};\n"; - } - $output .= '?>'; - return $output; - } - - /** - * Compiles code for to restore saved template variables - * - * @param int $levels number of levels to restore - * - * @return string compiled code - */ - public function compileRestore($levels) - { - return "\$_smarty_tpl->smarty->ext->_foreach->restore(\$_smarty_tpl, {$levels});"; - } -} - -/** - * Smarty Internal Plugin Compile Foreachelse Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Foreachelse extends Base -{ - /** - * Compiles code for the {foreachelse} tag - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * - * @return string compiled code - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - // check and get attributes - $_attr = $this->getAttributes($compiler, $args); - [$openTag, $nocache, $local, $itemVar, $restore] = $this->closeTag($compiler, array('foreach')); - $this->openTag($compiler, 'foreachelse', array('foreachelse', $nocache, $local, $itemVar, 0)); - $output = "do_else) {\n?>"; - return $output; - } -} - -/** - * Smarty Internal Plugin Compile Foreachclose Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Foreachclose extends Base -{ - /** - * Compiles code for the {/foreach} tag - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * - * @return string compiled code - * @throws \SmartyCompilerException - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - $compiler->loopNesting--; - // must endblock be nocache? - if ($compiler->nocache) { - $compiler->tag_nocache = true; - } - [ - $openTag, $compiler->nocache, $local, $itemVar, $restore - ] = $this->closeTag($compiler, array('foreach', 'foreachelse')); - $output = "getTagCompiler('foreach'); - $output .= $foreachCompiler->compileRestore(1); - $output .= "?>"; - return $output; - } -} diff --git a/src/Compile/smarty_internal_compile_function.php b/src/Compile/smarty_internal_compile_function.php deleted file mode 100644 index 072f75df..00000000 --- a/src/Compile/smarty_internal_compile_function.php +++ /dev/null @@ -1,233 +0,0 @@ -getAttributes($compiler, $args); - if ($_attr[ 'nocache' ] === true) { - $compiler->trigger_template_error('nocache option not allowed', null, true); - } - unset($_attr[ 'nocache' ]); - $_name = trim($_attr[ 'name' ], '\'"'); - - if (!preg_match('/^[a-zA-Z0-9_\x80-\xff]+$/', $_name)) { - $compiler->trigger_template_error("Function name contains invalid characters: {$_name}", null, true); - } - - $compiler->parent_compiler->tpl_function[ $_name ] = array(); - $save = array( - $_attr, $compiler->parser->current_buffer, $compiler->template->compiled->has_nocache_code, - $compiler->template->caching - ); - $this->openTag($compiler, 'function', $save); - // Init temporary context - $compiler->parser->current_buffer = new \Smarty\ParseTree\Template(); - $compiler->template->compiled->has_nocache_code = false; - return true; - } -} - -/** - * Smarty Internal Plugin Compile Functionclose Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Functionclose extends Base -{ - /** - * Compiler object - * - * @var object - */ - private $compiler = null; - - /** - * Compiles code for the {/function} tag - * - * @param array $args array with attributes from parser - * @param object|\Smarty_Internal_TemplateCompilerBase $compiler compiler object - * - * @return bool true - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - $this->compiler = $compiler; - $saved_data = $this->closeTag($compiler, array('function')); - $_attr = $saved_data[ 0 ]; - $_name = trim($_attr[ 'name' ], '\'"'); - $compiler->parent_compiler->tpl_function[ $_name ][ 'compiled_filepath' ] = - $compiler->parent_compiler->template->compiled->filepath; - $compiler->parent_compiler->tpl_function[ $_name ][ 'uid' ] = $compiler->template->source->uid; - $_parameter = $_attr; - unset($_parameter[ 'name' ]); - // default parameter - $_paramsArray = array(); - foreach ($_parameter as $_key => $_value) { - if (is_int($_key)) { - $_paramsArray[] = "$_key=>$_value"; - } else { - $_paramsArray[] = "'$_key'=>$_value"; - } - } - if (!empty($_paramsArray)) { - $_params = 'array(' . implode(',', $_paramsArray) . ')'; - $_paramsCode = "\$params = array_merge($_params, \$params);\n"; - } else { - $_paramsCode = ''; - } - $_functionCode = $compiler->parser->current_buffer; - // setup buffer for template function code - $compiler->parser->current_buffer = new \Smarty\ParseTree\Template(); - $_funcName = "smarty_template_function_{$_name}_{$compiler->template->compiled->nocache_hash}"; - $_funcNameCaching = $_funcName . '_nocache'; - if ($compiler->template->compiled->has_nocache_code) { - $compiler->parent_compiler->tpl_function[ $_name ][ 'call_name_caching' ] = $_funcNameCaching; - $output = "cStyleComment(" {$_funcNameCaching} ") . "\n"; - $output .= "if (!function_exists('{$_funcNameCaching}')) {\n"; - $output .= "function {$_funcNameCaching} (Smarty_Internal_Template \$_smarty_tpl,\$params) {\n"; - $output .= "ob_start();\n"; - $output .= "\$_smarty_tpl->compiled->has_nocache_code = true;\n"; - $output .= $_paramsCode; - $output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new \\Smarty\\Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}\n"; - $output .= "\$params = var_export(\$params, true);\n"; - $output .= "echo \"/*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/smarty->ext->_tplFunction->saveTemplateVariables(\\\$_smarty_tpl, '{$_name}');\nforeach (\$params as \\\$key => \\\$value) {\n\\\$_smarty_tpl->tpl_vars[\\\$key] = new \\Smarty\\Variable(\\\$value, \\\$_smarty_tpl->isRenderingCache);\n}\n?>"; - $output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";?>"; - $compiler->parser->current_buffer->append_subtree( - $compiler->parser, - new \Smarty\ParseTree\Tag( - $compiler->parser, - $output - ) - ); - $compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode); - $output = "template->compiled->nocache_hash}%%*/smarty->ext->_tplFunction->restoreTemplateVariables(\\\$_smarty_tpl, '{$_name}');?>\n"; - $output .= "/*/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%*/\";\n?>"; - $output .= "template->compiled->nocache_hash}', \$_smarty_tpl->compiled->nocache_hash ?? '', ob_get_clean());\n"; - $output .= "}\n}\n"; - $output .= $compiler->cStyleComment("/ {$_funcName}_nocache ") . "\n\n"; - $output .= "?>\n"; - $compiler->parser->current_buffer->append_subtree( - $compiler->parser, - new \Smarty\ParseTree\Tag( - $compiler->parser, - $output - ) - ); - $_functionCode = new \Smarty\ParseTree\Tag( - $compiler->parser, - preg_replace_callback( - "/((<\?php )?echo '\/\*%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/([\S\s]*?)\/\*\/%%SmartyNocache:{$compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/", - array($this, 'removeNocache'), - $_functionCode->to_smarty_php($compiler->parser) - ) - ); - } - $compiler->parent_compiler->tpl_function[ $_name ][ 'call_name' ] = $_funcName; - $output = "cStyleComment(" {$_funcName} ") . "\n"; - $output .= "if (!function_exists('{$_funcName}')) {\n"; - $output .= "function {$_funcName}(Smarty_Internal_Template \$_smarty_tpl,\$params) {\n"; - $output .= $_paramsCode; - $output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new \\Smarty\\Variable(\$value, \$_smarty_tpl->isRenderingCache);\n}\n"; - $output .= "?>\n"; - $compiler->parser->current_buffer->append_subtree( - $compiler->parser, - new \Smarty\ParseTree\Tag( - $compiler->parser, - $output - ) - ); - $compiler->parser->current_buffer->append_subtree($compiler->parser, $_functionCode); - $output = "cStyleComment("/ {$_funcName} ") . "\n\n"; - $output .= "?>\n"; - $compiler->parser->current_buffer->append_subtree( - $compiler->parser, - new \Smarty\ParseTree\Tag( - $compiler->parser, - $output - ) - ); - $compiler->parent_compiler->blockOrFunctionCode .= $compiler->parser->current_buffer->to_smarty_php($compiler->parser); - // restore old buffer - $compiler->parser->current_buffer = $saved_data[ 1 ]; - // restore old status - $compiler->template->compiled->has_nocache_code = $saved_data[ 2 ]; - $compiler->template->caching = $saved_data[ 3 ]; - return true; - } - - /** - * Remove nocache code - * - * @param $match - * - * @return string - */ - public function removeNocache($match) - { - $code = - preg_replace( - "/((<\?php )?echo '\/\*%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/)|(\/\*\/%%SmartyNocache:{$this->compiler->template->compiled->nocache_hash}%%\*\/';(\?>\n)?)/", - '', - $match[ 0 ] - ); - $code = str_replace(array('\\\'', '\\\\\''), array('\'', '\\\''), $code); - return $code; - } -} diff --git a/src/Compile/smarty_internal_compile_if.php b/src/Compile/smarty_internal_compile_if.php deleted file mode 100644 index 948d1c8d..00000000 --- a/src/Compile/smarty_internal_compile_if.php +++ /dev/null @@ -1,210 +0,0 @@ -getAttributes($compiler, $args); - $this->openTag($compiler, 'if', array(1, $compiler->nocache)); - // must whole block be nocache ? - $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; - if (!isset($parameter[ 'if condition' ])) { - $compiler->trigger_template_error('missing if condition', null, true); - } - if (is_array($parameter[ 'if condition' ])) { - if (is_array($parameter[ 'if condition' ][ 'var' ])) { - $var = $parameter[ 'if condition' ][ 'var' ][ 'var' ]; - } else { - $var = $parameter[ 'if condition' ][ 'var' ]; - } - if ($compiler->nocache) { - // create nocache var to make it know for further compiling - $compiler->setNocacheInVariable($var); - } - $prefixVar = $compiler->getNewPrefixVariable(); - $_output = "\n"; - $assignAttr = array(); - $assignAttr[][ 'value' ] = $prefixVar; - $assignCompiler = new Assign(); - if (is_array($parameter[ 'if condition' ][ 'var' ])) { - $assignAttr[][ 'var' ] = $parameter[ 'if condition' ][ 'var' ][ 'var' ]; - $_output .= $assignCompiler->compile( - $assignAttr, - $compiler, - array('smarty_internal_index' => $parameter[ 'if condition' ][ 'var' ][ 'smarty_internal_index' ]) - ); - } else { - $assignAttr[][ 'var' ] = $parameter[ 'if condition' ][ 'var' ]; - $_output .= $assignCompiler->compile($assignAttr, $compiler, array()); - } - $_output .= ""; - return $_output; - } else { - return ""; - } - } -} - -/** - * Smarty Internal Plugin Compile Else Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Else extends Base -{ - /** - * Compiles code for the {else} tag - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * - * @return string compiled code - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - [$nesting, $compiler->tag_nocache] = $this->closeTag($compiler, array('if', 'elseif')); - $this->openTag($compiler, 'else', array($nesting, $compiler->tag_nocache)); - return ''; - } -} - -/** - * Smarty Internal Plugin Compile ElseIf Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Elseif extends Base -{ - /** - * Compiles code for the {elseif} tag - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * @param array $parameter array with compilation parameter - * - * @return string compiled code - * @throws \SmartyCompilerException - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - // check and get attributes - $_attr = $this->getAttributes($compiler, $args); - [$nesting, $compiler->tag_nocache] = $this->closeTag($compiler, array('if', 'elseif')); - if (!isset($parameter[ 'if condition' ])) { - $compiler->trigger_template_error('missing elseif condition', null, true); - } - $assignCode = ''; - $var = ''; - if (is_array($parameter[ 'if condition' ])) { - $condition_by_assign = true; - if (is_array($parameter[ 'if condition' ][ 'var' ])) { - $var = $parameter[ 'if condition' ][ 'var' ][ 'var' ]; - } else { - $var = $parameter[ 'if condition' ][ 'var' ]; - } - if ($compiler->nocache) { - // create nocache var to make it know for further compiling - $compiler->setNocacheInVariable($var); - } - $prefixVar = $compiler->getNewPrefixVariable(); - $assignCode = "\n"; - $assignCompiler = new Assign(); - $assignAttr = array(); - $assignAttr[][ 'value' ] = $prefixVar; - if (is_array($parameter[ 'if condition' ][ 'var' ])) { - $assignAttr[][ 'var' ] = $parameter[ 'if condition' ][ 'var' ][ 'var' ]; - $assignCode .= $assignCompiler->compile( - $assignAttr, - $compiler, - array('smarty_internal_index' => $parameter[ 'if condition' ][ 'var' ][ 'smarty_internal_index' ]) - ); - } else { - $assignAttr[][ 'var' ] = $parameter[ 'if condition' ][ 'var' ]; - $assignCode .= $assignCompiler->compile($assignAttr, $compiler, array()); - } - } else { - $condition_by_assign = false; - } - $prefixCode = $compiler->getPrefixCode(); - if (empty($prefixCode)) { - if ($condition_by_assign) { - $this->openTag($compiler, 'elseif', array($nesting + 1, $compiler->tag_nocache)); - $_output = $compiler->appendCode("", $assignCode); - return $compiler->appendCode($_output, ""); - } else { - $this->openTag($compiler, 'elseif', array($nesting, $compiler->tag_nocache)); - return ""; - } - } else { - $_output = $compiler->appendCode("", $prefixCode); - $this->openTag($compiler, 'elseif', array($nesting + 1, $compiler->tag_nocache)); - if ($condition_by_assign) { - $_output = $compiler->appendCode($_output, $assignCode); - return $compiler->appendCode($_output, ""); - } else { - return $compiler->appendCode($_output, ""); - } - } - } -} - -/** - * Smarty Internal Plugin Compile Ifclose Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Ifclose extends Base -{ - /** - * Compiles code for the {/if} tag - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * - * @return string compiled code - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - // must endblock be nocache? - if ($compiler->nocache) { - $compiler->tag_nocache = true; - } - [$nesting, $compiler->nocache] = $this->closeTag($compiler, array('if', 'else', 'elseif')); - $tmp = ''; - for ($i = 0; $i < $nesting; $i++) { - $tmp .= '}'; - } - return ""; - } -} diff --git a/src/Compile/smarty_internal_compile_nocache.php b/src/Compile/smarty_internal_compile_nocache.php deleted file mode 100644 index 5b063c46..00000000 --- a/src/Compile/smarty_internal_compile_nocache.php +++ /dev/null @@ -1,75 +0,0 @@ -getAttributes($compiler, $args); - $this->openTag($compiler, 'nocache', array($compiler->nocache)); - // enter nocache mode - $compiler->nocache = true; - // this tag does not return compiled code - $compiler->has_code = false; - return true; - } -} - -/** - * Smarty Internal Plugin Compile Nocacheclose Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Nocacheclose extends Base -{ - /** - * Compiles code for the {/nocache} tag - * This tag does not generate compiled output. It only sets a compiler flag. - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * - * @return bool - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - $_attr = $this->getAttributes($compiler, $args); - // leave nocache mode - [$compiler->nocache] = $this->closeTag($compiler, array('nocache')); - // this tag does not return compiled code - $compiler->has_code = false; - return true; - } -} diff --git a/src/Compile/smarty_internal_compile_rdelim.php b/src/Compile/smarty_internal_compile_rdelim.php deleted file mode 100644 index 1025b5df..00000000 --- a/src/Compile/smarty_internal_compile_rdelim.php +++ /dev/null @@ -1,36 +0,0 @@ -smarty->right_delimiter; - } -} diff --git a/src/Compile/smarty_internal_compile_section.php b/src/Compile/smarty_internal_compile_section.php deleted file mode 100644 index e10b857a..00000000 --- a/src/Compile/smarty_internal_compile_section.php +++ /dev/null @@ -1,465 +0,0 @@ -loopNesting++; - // check and get attributes - $_attr = $this->getAttributes($compiler, $args); - $attributes = array('name' => $compiler->getId($_attr[ 'name' ])); - unset($_attr[ 'name' ]); - foreach ($attributes as $a => $v) { - if ($v === false) { - $compiler->trigger_template_error("'{$a}' attribute/variable has illegal value", null, true); - } - } - $local = "\$__section_{$attributes['name']}_" . $this->counter++ . '_'; - $sectionVar = "\$_smarty_tpl->tpl_vars['__smarty_section_{$attributes['name']}']"; - $this->openTag($compiler, 'section', array('section', $compiler->nocache, $local, $sectionVar)); - // maybe nocache because of nocache variables - $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; - $initLocal = array(); - $initNamedProperty = array(); - $initFor = array(); - $incFor = array(); - $cmpFor = array(); - $propValue = array( - 'index' => "{$sectionVar}->value['index']", 'show' => 'true', 'step' => 1, - 'iteration' => "{$local}iteration", - ); - $propType = array('index' => 2, 'iteration' => 2, 'show' => 0, 'step' => 0,); - // search for used tag attributes - $this->scanForProperties($attributes, $compiler); - if (!empty($this->matchResults[ 'named' ])) { - $namedAttr = $this->matchResults[ 'named' ]; - } - if (isset($_attr[ 'properties' ]) && preg_match_all("/['](.*?)[']/", $_attr[ 'properties' ], $match)) { - foreach ($match[ 1 ] as $prop) { - if (in_array($prop, $this->nameProperties)) { - $namedAttr[ $prop ] = true; - } else { - $compiler->trigger_template_error("Invalid property '{$prop}'", null, true); - } - } - } - $namedAttr[ 'index' ] = true; - $output = " $attr_value) { - switch ($attr_name) { - case 'loop': - if (is_numeric($attr_value)) { - $v = (int)$attr_value; - $t = 0; - } else { - $v = "(is_array(@\$_loop=$attr_value) ? count(\$_loop) : max(0, (int) \$_loop))"; - $t = 1; - } - if ($t === 1) { - $initLocal[ 'loop' ] = $v; - $v = "{$local}loop"; - } - break; - case 'show': - if (is_bool($attr_value)) { - $v = $attr_value ? 'true' : 'false'; - $t = 0; - } else { - $v = "(bool) $attr_value"; - $t = 3; - } - break; - case 'step': - if (is_numeric($attr_value)) { - $v = (int)$attr_value; - $v = ($v === 0) ? 1 : $v; - $t = 0; - break; - } - $initLocal[ 'step' ] = "((int)@$attr_value) === 0 ? 1 : (int)@$attr_value"; - $v = "{$local}step"; - $t = 2; - break; - case 'max': - case 'start': - if (is_numeric($attr_value)) { - $v = (int)$attr_value; - $t = 0; - break; - } - $v = "(int)@$attr_value"; - $t = 3; - break; - } - if ($t === 3 && $compiler->getId($attr_value)) { - $t = 1; - } - $propValue[ $attr_name ] = $v; - $propType[ $attr_name ] = $t; - } - if (isset($namedAttr[ 'step' ])) { - $initNamedProperty[ 'step' ] = $propValue[ 'step' ]; - } - if (isset($namedAttr[ 'iteration' ])) { - $propValue[ 'iteration' ] = "{$sectionVar}->value['iteration']"; - } - $incFor[ 'iteration' ] = "{$propValue['iteration']}++"; - $initFor[ 'iteration' ] = "{$propValue['iteration']} = 1"; - if ($propType[ 'step' ] === 0) { - if ($propValue[ 'step' ] === 1) { - $incFor[ 'index' ] = "{$sectionVar}->value['index']++"; - } elseif ($propValue[ 'step' ] > 1) { - $incFor[ 'index' ] = "{$sectionVar}->value['index'] += {$propValue['step']}"; - } else { - $incFor[ 'index' ] = "{$sectionVar}->value['index'] -= " . -$propValue[ 'step' ]; - } - } else { - $incFor[ 'index' ] = "{$sectionVar}->value['index'] += {$propValue['step']}"; - } - if (!isset($propValue[ 'max' ])) { - $propValue[ 'max' ] = $propValue[ 'loop' ]; - $propType[ 'max' ] = $propType[ 'loop' ]; - } elseif ($propType[ 'max' ] !== 0) { - $propValue[ 'max' ] = "{$propValue['max']} < 0 ? {$propValue['loop']} : {$propValue['max']}"; - $propType[ 'max' ] = 1; - } else { - if ($propValue[ 'max' ] < 0) { - $propValue[ 'max' ] = $propValue[ 'loop' ]; - $propType[ 'max' ] = $propType[ 'loop' ]; - } - } - if (!isset($propValue[ 'start' ])) { - $start_code = - array(1 => "{$propValue['step']} > 0 ? ", 2 => '0', 3 => ' : ', 4 => $propValue[ 'loop' ], 5 => ' - 1'); - if ($propType[ 'loop' ] === 0) { - $start_code[ 5 ] = ''; - $start_code[ 4 ] = $propValue[ 'loop' ] - 1; - } - if ($propType[ 'step' ] === 0) { - if ($propValue[ 'step' ] > 0) { - $start_code = array(1 => '0'); - $propType[ 'start' ] = 0; - } else { - $start_code[ 1 ] = $start_code[ 2 ] = $start_code[ 3 ] = ''; - $propType[ 'start' ] = $propType[ 'loop' ]; - } - } else { - $propType[ 'start' ] = 1; - } - $propValue[ 'start' ] = join('', $start_code); - } else { - $start_code = - array( - 1 => "{$propValue['start']} < 0 ? ", 2 => 'max(', 3 => "{$propValue['step']} > 0 ? ", 4 => '0', - 5 => ' : ', 6 => '-1', 7 => ', ', 8 => "{$propValue['start']} + {$propValue['loop']}", 10 => ')', - 11 => ' : ', 12 => 'min(', 13 => $propValue[ 'start' ], 14 => ', ', - 15 => "{$propValue['step']} > 0 ? ", 16 => $propValue[ 'loop' ], 17 => ' : ', - 18 => $propType[ 'loop' ] === 0 ? $propValue[ 'loop' ] - 1 : "{$propValue['loop']} - 1", - 19 => ')' - ); - if ($propType[ 'step' ] === 0) { - $start_code[ 3 ] = $start_code[ 5 ] = $start_code[ 15 ] = $start_code[ 17 ] = ''; - if ($propValue[ 'step' ] > 0) { - $start_code[ 6 ] = $start_code[ 18 ] = ''; - } else { - $start_code[ 4 ] = $start_code[ 16 ] = ''; - } - } - if ($propType[ 'start' ] === 0) { - if ($propType[ 'loop' ] === 0) { - $start_code[ 8 ] = $propValue[ 'start' ] + $propValue[ 'loop' ]; - } - $propType[ 'start' ] = $propType[ 'step' ] + $propType[ 'loop' ]; - $start_code[ 1 ] = ''; - if ($propValue[ 'start' ] < 0) { - for ($i = 11; $i <= 19; $i++) { - $start_code[ $i ] = ''; - } - if ($propType[ 'start' ] === 0) { - $start_code = array( - max( - $propValue[ 'step' ] > 0 ? 0 : -1, - $propValue[ 'start' ] + $propValue[ 'loop' ] - ) - ); - } - } else { - for ($i = 1; $i <= 11; $i++) { - $start_code[ $i ] = ''; - } - if ($propType[ 'start' ] === 0) { - $start_code = - array( - min( - $propValue[ 'step' ] > 0 ? $propValue[ 'loop' ] : $propValue[ 'loop' ] - 1, - $propValue[ 'start' ] - ) - ); - } - } - } - $propValue[ 'start' ] = join('', $start_code); - } - if ($propType[ 'start' ] !== 0) { - $initLocal[ 'start' ] = $propValue[ 'start' ]; - $propValue[ 'start' ] = "{$local}start"; - } - $initFor[ 'index' ] = "{$sectionVar}->value['index'] = {$propValue['start']}"; - if (!isset($_attr[ 'start' ]) && !isset($_attr[ 'step' ]) && !isset($_attr[ 'max' ])) { - $propValue[ 'total' ] = $propValue[ 'loop' ]; - $propType[ 'total' ] = $propType[ 'loop' ]; - } else { - $propType[ 'total' ] = - $propType[ 'start' ] + $propType[ 'loop' ] + $propType[ 'step' ] + $propType[ 'max' ]; - if ($propType[ 'total' ] === 0) { - $propValue[ 'total' ] = - min( - ceil( - ($propValue[ 'step' ] > 0 ? $propValue[ 'loop' ] - $propValue[ 'start' ] : - (int)$propValue[ 'start' ] + 1) / abs($propValue[ 'step' ]) - ), - $propValue[ 'max' ] - ); - } else { - $total_code = array( - 1 => 'min(', 2 => 'ceil(', 3 => '(', 4 => "{$propValue['step']} > 0 ? ", - 5 => $propValue[ 'loop' ], 6 => ' - ', 7 => $propValue[ 'start' ], 8 => ' : ', - 9 => $propValue[ 'start' ], 10 => '+ 1', 11 => ')', 12 => '/ ', 13 => 'abs(', - 14 => $propValue[ 'step' ], 15 => ')', 16 => ')', 17 => ", {$propValue['max']})", - ); - if (!isset($propValue[ 'max' ])) { - $total_code[ 1 ] = $total_code[ 17 ] = ''; - } - if ($propType[ 'loop' ] + $propType[ 'start' ] === 0) { - $total_code[ 5 ] = $propValue[ 'loop' ] - $propValue[ 'start' ]; - $total_code[ 6 ] = $total_code[ 7 ] = ''; - } - if ($propType[ 'start' ] === 0) { - $total_code[ 9 ] = (int)$propValue[ 'start' ] + 1; - $total_code[ 10 ] = ''; - } - if ($propType[ 'step' ] === 0) { - $total_code[ 13 ] = $total_code[ 15 ] = ''; - if ($propValue[ 'step' ] === 1 || $propValue[ 'step' ] === -1) { - $total_code[ 2 ] = $total_code[ 12 ] = $total_code[ 14 ] = $total_code[ 16 ] = ''; - } elseif ($propValue[ 'step' ] < 0) { - $total_code[ 14 ] = -$propValue[ 'step' ]; - } - $total_code[ 4 ] = ''; - if ($propValue[ 'step' ] > 0) { - $total_code[ 8 ] = $total_code[ 9 ] = $total_code[ 10 ] = ''; - } else { - $total_code[ 5 ] = $total_code[ 6 ] = $total_code[ 7 ] = $total_code[ 8 ] = ''; - } - } - $propValue[ 'total' ] = join('', $total_code); - } - } - if (isset($namedAttr[ 'loop' ])) { - $initNamedProperty[ 'loop' ] = "'loop' => {$propValue['loop']}"; - } - if (isset($namedAttr[ 'total' ])) { - $initNamedProperty[ 'total' ] = "'total' => {$propValue['total']}"; - if ($propType[ 'total' ] > 0) { - $propValue[ 'total' ] = "{$sectionVar}->value['total']"; - } - } elseif ($propType[ 'total' ] > 0) { - $initLocal[ 'total' ] = $propValue[ 'total' ]; - $propValue[ 'total' ] = "{$local}total"; - } - $cmpFor[ 'iteration' ] = "{$propValue['iteration']} <= {$propValue['total']}"; - foreach ($initLocal as $key => $code) { - $output .= "{$local}{$key} = {$code};\n"; - } - $_vars = 'array(' . join(', ', $initNamedProperty) . ')'; - $output .= "{$sectionVar} = new \\Smarty\\Variable({$_vars});\n"; - $cond_code = "{$propValue['total']} !== 0"; - if ($propType[ 'total' ] === 0) { - if ($propValue[ 'total' ] === 0) { - $cond_code = 'false'; - } else { - $cond_code = 'true'; - } - } - if ($propType[ 'show' ] > 0) { - $output .= "{$local}show = {$propValue['show']} ? {$cond_code} : false;\n"; - $output .= "if ({$local}show) {\n"; - } elseif ($propValue[ 'show' ] === 'true') { - $output .= "if ({$cond_code}) {\n"; - } else { - $output .= "if (false) {\n"; - } - $jinit = join(', ', $initFor); - $jcmp = join(', ', $cmpFor); - $jinc = join(', ', $incFor); - $output .= "for ({$jinit}; {$jcmp}; {$jinc}){\n"; - if (isset($namedAttr[ 'rownum' ])) { - $output .= "{$sectionVar}->value['rownum'] = {$propValue['iteration']};\n"; - } - if (isset($namedAttr[ 'index_prev' ])) { - $output .= "{$sectionVar}->value['index_prev'] = {$propValue['index']} - {$propValue['step']};\n"; - } - if (isset($namedAttr[ 'index_next' ])) { - $output .= "{$sectionVar}->value['index_next'] = {$propValue['index']} + {$propValue['step']};\n"; - } - if (isset($namedAttr[ 'first' ])) { - $output .= "{$sectionVar}->value['first'] = ({$propValue['iteration']} === 1);\n"; - } - if (isset($namedAttr[ 'last' ])) { - $output .= "{$sectionVar}->value['last'] = ({$propValue['iteration']} === {$propValue['total']});\n"; - } - $output .= '?>'; - return $output; - } -} - -/** - * Smarty Internal Plugin Compile Sectionelse Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Sectionelse extends Base -{ - /** - * Compiles code for the {sectionelse} tag - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * - * @return string compiled code - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - // check and get attributes - $_attr = $this->getAttributes($compiler, $args); - [$openTag, $nocache, $local, $sectionVar] = $this->closeTag($compiler, array('section')); - $this->openTag($compiler, 'sectionelse', array('sectionelse', $nocache, $local, $sectionVar)); - return ""; - } -} - -/** - * Smarty Internal Plugin Compile Sectionclose Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Sectionclose extends Base -{ - /** - * Compiles code for the {/section} tag - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * - * @return string compiled code - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - $compiler->loopNesting--; - // must endblock be nocache? - if ($compiler->nocache) { - $compiler->tag_nocache = true; - } - [$openTag, $compiler->nocache, $local, $sectionVar] = - $this->closeTag($compiler, array('section', 'sectionelse')); - $output = "'; - return $output; - } -} diff --git a/src/Compile/smarty_internal_compile_setfilter.php b/src/Compile/smarty_internal_compile_setfilter.php deleted file mode 100644 index 60e69c69..00000000 --- a/src/Compile/smarty_internal_compile_setfilter.php +++ /dev/null @@ -1,70 +0,0 @@ -variable_filter_stack[] = $compiler->variable_filters; - $compiler->variable_filters = $parameter[ 'modifier_list' ]; - // this tag does not return compiled code - $compiler->has_code = false; - return true; - } -} - -/** - * Smarty Internal Plugin Compile Setfilterclose Class - * - * @package Smarty - * @subpackage Compiler - */ -class _Setfilterclose extends Base -{ - /** - * Compiles code for the {/setfilter} tag - * This tag does not generate compiled output. It resets variable filter. - * - * @param array $args array with attributes from parser - * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object - * - * @return string compiled code - */ - public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter = array(), $tag = null, $function = null) - { - $_attr = $this->getAttributes($compiler, $args); - // reset variable filter to previous state - if (count($compiler->variable_filter_stack)) { - $compiler->variable_filters = array_pop($compiler->variable_filter_stack); - } else { - $compiler->variable_filters = array(); - } - // this tag does not return compiled code - $compiler->has_code = false; - return true; - } -}