/** * Compiles the opening tag for a function * @param \Box\Brainy\Compiler\TemplateCompiler $compiler A compiler reference * @param array|null $args Arguments * @param array|null $params Parameters * @return mixed */ public static function compileOpen(\Box\Brainy\Compiler\TemplateCompiler $compiler, $args, $params) { $var = self::getRequiredArg($args, 'var'); $value = self::getRequiredArg($args, 'value'); $scopeRaw = self::getOptionalArg($args, 'scope', self::getDefaultScope()); switch (\Box\Brainy\Compiler\Decompile::decompileString($scopeRaw)) { case 'local': $scope = Brainy::SCOPE_LOCAL; break; case 'parent': $scope = Brainy::SCOPE_PARENT; break; case 'root': $scope = Brainy::SCOPE_ROOT; break; case 'global': $scope = Brainy::SCOPE_GLOBAL; break; default: $compiler->trigger_template_error('illegal value for "scope" attribute: ' . $scopeRaw, $compiler->lex->taglineno); } // implement Smarty2's behaviour of variables assigned by reference if ($compiler->template->smarty instanceof SmartyBC && Brainy::$assignment_compat === Brainy::ASSIGN_COMPAT) { $output = "if (isset(\$_smarty_tpl->tpl_vars[{$var}])) {\n"; $output .= " \$_smarty_tpl->tpl_vars[{$var}] = clone \$_smarty_tpl->tpl_vars[{$var}];\n"; $output .= " \$_smarty_tpl->tpl_vars[{$var}]->value = {$value};\n"; $output .= " \$_smarty_tpl->tpl_vars[{$var}]->scope = {$scope};\n"; $output .= "} else {\$_smarty_tpl->assign({$var}, {$value}, {$scope});}\n"; } else { $output = "\$_smarty_tpl->assign({$var}, {$value}, {$scope});\n"; } return $output; }
/** * @param \Box\Brainy\Compiler\TemplateCompiler $compiler * @param string $name * @param string $childBlockVar * @return string */ protected static function compileForced($compiler, $name, $childBlockVar) { $nameVar = '$' . $compiler->getUniqueVarName(); $output = "{$nameVar} = {$name};\n"; $output .= "{$childBlockVar} = \$_smarty_tpl->tpl_vars['smarty']['blocks'][{$nameVar}] ?: null;\n"; $output .= "\$_smarty_tpl->tpl_vars['smarty']['blocks'][{$nameVar}] = function (\$_smarty_tpl) use ({$childBlockVar}) {\n"; return $output; }
/** * @param \Box\Brainy\Compiler\TemplateCompiler $compiler A compiler reference * @param array|null $args Arguments * @return mixed */ public static function compileOpen(\Box\Brainy\Compiler\TemplateCompiler $compiler, $args) { $levels = self::getOptionalArg($args, 'levels'); if (!$levels && isset($args[0])) { $compiler->assertIsNotStrict('Continue shorthand is not allowed in strict mode. Use the levels="" attribute instead.'); $levels = $args[0]; } if ($levels) { return "continue {$levels};\n"; } return "continue;\n"; }
/** * @param \Box\Brainy\Compiler\TemplateCompiler $compiler A compiler reference * @param array|null $args Arguments * @return mixed */ public static function compileOpen(\Box\Brainy\Compiler\TemplateCompiler $compiler, $args) { $name = self::getOptionalArg($args, 'name'); $assign = self::getOptionalArg($args, 'assign'); if (!$name && !$assign && isset($args[0])) { $compiler->assertIsNotStrict('Capture shorthand is not allowed in strict mode. Use the name="" attribute instead.'); $name = $args[0]; } if (!$name && !$assign) { $name = "'default'"; } if ($name && $assign) { throw new \Box\Brainy\Exceptions\SmartyCompilerException('{capture} tags may not set both `name` and `assign`'); } self::openTag($compiler, 'capture', array($name, $assign)); return "ob_start();\n"; }
/** * @param \Box\Brainy\Compiler\TemplateCompiler $compiler A compiler reference * @param array|null $args Arguments * @return mixed */ public static function compileOpen(\Box\Brainy\Compiler\TemplateCompiler $compiler, $args) { $name = self::getRequiredArg($args, 'name'); $assign = self::getOptionalArg($args, 'assign'); $paramArray = self::flattenCompiledArray($args); $paramArray = self::exportArray($paramArray); $tmpVar = '$' . $compiler->getUniqueVarName(); // Evaluate the function name dynamically at runtime $output = "{$tmpVar} = {$name};\n"; // Safety Dance $output .= "if (!array_key_exists({$tmpVar}, \$_smarty_tpl->tpl_vars['smarty']['functions'])) {\n"; $output .= " \$funcs = implode(', ', array_keys(\$_smarty_tpl->tpl_vars['smarty']['functions'])) ?: '<none>';\n"; $output .= " throw new \\Box\\Brainy\\Exceptions\\SmartyException('Call to undefined function \\'' . {$tmpVar} . '\\'. Defined functions: ' . \$funcs);\n"; $output .= "}\n"; if ($assign) { $output .= "ob_start();\n"; } $output .= "\$_smarty_tpl->tpl_vars['smarty']['functions'][{$tmpVar}]({$paramArray});\n"; if ($assign) { $output .= "\$_smarty_tpl->setVariable({$assign}, ob_get_clean());\n"; } return $output; }
/** * Compiles the opening tag for a function * @param \Box\Brainy\Compiler\TemplateCompiler $compiler A compiler reference * @param array|null $args Arguments * @return mixed */ public static function compileOpen(\Box\Brainy\Compiler\TemplateCompiler $compiler, $args) { try { $file = self::getRequiredArg($args, 'file'); } catch (SmartyCompilerException $e) { $compiler->assertIsNotStrict('Include shorthand is not allowed in strict mode. Use the file="" attribute instead.'); if (!isset($args[0])) { throw $e; } $file = $args[0]; } $file = (string) $file; $assign = self::getOptionalArg($args, 'assign'); $compileID = self::getOptionalArg($args, 'compile_id', var_export($compiler->smarty->compile_id, true)); $scope = ConstructAssign::getScope($args, Brainy::SCOPE_LOCAL); if (!$assign) { return self::getDisplayCode($file, $compileID, $scope, $args); } $output = 'ob_start();'; $output .= self::getDisplayCode($file, $compileID, $scope, $args); $output .= "\$_smarty_tpl->assign({$assign}, ob_get_clean(), {$scope});\n"; return $output; }
/** * @param \Box\Brainy\Compiler\TemplateCompiler $compiler A compiler reference * @param array|null $args Arguments * @return mixed */ public static function compileOpenShorthand(\Box\Brainy\Compiler\TemplateCompiler $compiler, $args) { $start = self::getRequiredArg($args, 'start'); $to = self::getRequiredArg($args, 'to'); $step = self::getOptionalArg($args, 'step', 1); $max = self::getOptionalArg($args, 'max', INF); $var = $start['var']; $value = $start['value']; $total = "ceil(({$step} > 0 ? {$to} + 1 - ({$value}) : {$value} - ({$to}) + 1) / abs({$step}))"; if ($max !== INF) { $total = "min({$total}, {$max})"; } $stepVar = '$' . $compiler->getUniqueVarName(); $totalVar = '$' . $compiler->getUniqueVarName(); $iterationVar = '$' . $compiler->getUniqueVarName(); $output = "{$stepVar} = {$step};\n"; $output .= "{$totalVar} = (int) {$total};\n"; $output .= "if ({$totalVar} > 0) {\n"; $output .= " \$_smarty_tpl->setVariable({$var}, 0);\n"; $varVar = "\$_smarty_tpl->tpl_vars[{$var}]"; $output .= " for ({$varVar} = {$value}, {$iterationVar} = 1; {$iterationVar} <= {$totalVar}; {$varVar} += {$stepVar}, {$iterationVar}++) {\n"; self::openTag($compiler, 'for', array('for')); return $output; }
/** * Pop closing tag * * Raise an error if this stack-top doesn't match with expected opening tags * * @param \Box\Brainy\Compiler\TemplateCompiler $compiler * @param array|string $expectedTag the expected opening tag names * @return mixed any type the opening tag's name or saved data */ public static function closeTag($compiler, $expectedTag) { if (count($compiler->_tag_stack) === 0) { // wrong nesting of tags $compiler->trigger_template_error("unexpected closing tag", $compiler->lex->taglineno); } // get stacked info list($openTag, $data) = array_pop($compiler->_tag_stack); // open tag must match with the expected ones if (!in_array($openTag, (array) $expectedTag)) { // wrong nesting of tags $compiler->trigger_template_error("unclosed {$compiler->smarty->left_delimiter}" . $openTag . "{$compiler->smarty->right_delimiter} tag"); return; } return is_null($data) ? $openTag : $data; }