Example #1
0
 /**
  * @dataProvider sourcesProvider
  */
 public function testCompiles($source, $expectedOutput, $locals)
 {
     //
     // parse
     //
     $parseContext = new ParserContext();
     $parseContext->setString($source)->setBaseDirectory(__DIR__);
     $template = $parseContext->parse();
     $this->assertInstanceOf('Skrz\\Templating\\Engine\\AST\\TemplateNode', $template);
     //
     // compile
     //
     $compilerContext = new CompilerContext();
     $compilerContext->setNamespace('Skrz\\Templating\\Engine')->setClassName("Template_" . sha1(uniqid('', true)))->setTemplate($template)->setParserContext($parseContext)->addModifier("strip_tags", function (Compiler $compiler, ModifierNode $modifier, $text) {
         return new ModifierCompilerResult("strip_tags({$text})");
     })->addFunction("inferno", function (Compiler $compiler, FunctionNode $function) {
         /** @var StatementAndExpressionVO $hell */
         $hell = $compiler->walk($function->getArgument("hell"));
         $ret = "";
         $ret .= "echo '666 ';";
         $ret .= $hell->getStatement();
         $ret .= "echo " . $hell->getExpression() . ";";
         $ret .= "echo ' 666';";
         return new FunctionCompilerResult($ret);
     });
     $compiled = $compilerContext->compile();
     //
     // debug
     //
     //		echo "\n\n";
     //		echo "$source\n";
     //		echo "--------\n";
     //		echo $compiled;
     //		echo "\n";
     //
     // run
     //
     $this->assertNull(eval("?>{$compiled}"));
     $fullyQualifiedClassName = $compilerContext->getFullyQualifiedClassName();
     $templateInstance = new $fullyQualifiedClassName();
     ob_start();
     $templateInstance($locals);
     $actualOutput = ob_get_contents();
     ob_end_clean();
     $this->assertEquals($expectedOutput, $actualOutput);
 }
Example #2
0
 protected function walkExpression(ExpressionNode $expression)
 {
     $ret = $this->walk($expression->getExpression());
     $statements = array();
     foreach ($expression->getModifiers() as $modifier) {
         $modifierCompiler = $this->context->getModifier($modifier->getName());
         if ($modifierCompiler === null) {
             if (!function_exists($modifier->getName())) {
                 throw new CompilerException($this->context, "Modifier `{$modifier->getName()}` not registered in compiler context. Template in " . $modifier->getFileName() . " @ " . $modifier->getRow() . ":" . $modifier->getColumn());
             } else {
                 $modifierCompiler = function (Compiler $compiler, ModifierNode $modifier, $expressionCode) {
                     return new ModifierCompilerResult($modifier->getName() . "({$expressionCode} " . ($modifier->hasArgument(0) ? ", " : "") . implode(", ", $compiler->walkEach($modifier->getArguments())) . ")");
                 };
             }
         }
         $modifierResult = $modifierCompiler($this, $modifier, $ret);
         if (!$modifierResult instanceof ModifierCompilerResult) {
             throw new CompilerException($this->context, "Modifier `{$modifier->getName()}` did not return " . __NAMESPACE__ . "\\ModifierCompilerResult.");
         }
         $statements[] = $modifierResult->getStatement();
         $ret = $modifierResult->getExpression();
     }
     return new StatementAndExpressionVO(implode("", $statements), $ret);
 }
Example #3
0
 /**
  * Prepare some of default smarty modifiers
  */
 public static function prepareModifiers(CompilerContext $compilerContext)
 {
     $compilerContext->addModifier("truncate", function (Compiler $compiler, ModifierNode $modifier, $expressionCode) {
         return new ModifierCompilerResult("\\Skrz\\Templating\\Engine\\Helpers::truncate({$expressionCode}" . ($modifier->hasArgument(0) ? "," . implode(",", array_map(function (PHPNode $php) {
             return $php->getCode();
         }, $modifier->getArguments())) : "") . ")");
     });
     $compilerContext->addModifier("strip_tags", function (Compiler $compiler, ModifierNode $modifier, $expressionCode) {
         if (!$modifier->hasArgument(0) || $modifier->hasArgument(0) && strcasecmp($modifier->getArgument(0)->getCode(), "true") === 0) {
             return new ModifierCompilerResult("preg_replace('/<[^>]*?>/', ' ', {$expressionCode})");
         } else {
             return new ModifierCompilerResult("strip_tags({$expressionCode})");
         }
     });
     $compilerContext->addModifier("escape", function (Compiler $compiler, ModifierNode $modifier, $expressionCode) {
         $type = strtolower(trim($modifier->hasArgument(0) ? $modifier->getArgument(0)->getCode() : "html", "\"'() \t\r\n"));
         switch ($type) {
             case "html":
                 return new ModifierCompilerResult("htmlspecialchars({$expressionCode}, ENT_QUOTES)");
             case "url":
                 return new ModifierCompilerResult("rawurlencode({$expressionCode})");
             case "javascript":
                 return new ModifierCompilerResult("\\Skrz\\Templating\\Engine\\Helpers::escapeJavascript({$expressionCode})");
             default:
                 throw new CompilerException($compiler->getContext(), "Only `html`, `url`, and `javascript` modes supported for `truncate` modifier, `{$type}` supplied. Template in " . $modifier->getFileName() . " @ " . $modifier->getRow() . ":" . $modifier->getColumn());
         }
     });
     $compilerContext->addModifier("default", function (Compiler $compiler, ModifierNode $modifier, $expressionCode) {
         $resultSym = $compiler->gensym();
         return new ModifierCompilerResult($resultSym, "{$resultSym} = @({$expressionCode}); " . "if ({$resultSym} == null) { {$resultSym} = " . ($modifier->hasArgument(0) ? $compiler->walk($modifier->getArgument(0)) : "''") . "; }");
     });
     $compilerContext->addModifier("replace", function (Compiler $compiler, ModifierNode $modifier, $expressionCode) {
         return new ModifierCompilerResult("str_replace(" . $compiler->walk($modifier->getArgument(0)) . ", " . $compiler->walk($modifier->getArgument(1)) . ", " . $expressionCode . ")");
     });
     $compilerContext->addModifier("count", function (Compiler $compiler, ModifierNode $modifier, $expressionCode) {
         return new ModifierCompilerResult("count({$expressionCode})");
     });
     $compilerContext->addModifier("mb_ucfirst", function (Compiler $compiler, ModifierNode $modifier, $expressionCode) {
         $resultSym = $compiler->gensym();
         return new ModifierCompilerResult("(mb_strtoupper(mb_substr({$resultSym}, 0, 1)) . mb_substr({$resultSym}, 1))", "{$resultSym} = {$expressionCode};");
     });
     $compilerContext->addModifier("mb_lcfirst", function (Compiler $compiler, ModifierNode $modifier, $expressionCode) {
         $resultSym = $compiler->gensym();
         return new ModifierCompilerResult("(mb_strtolower(mb_substr({$resultSym}, 0, 1)) . mb_substr({$resultSym}, 1))", "{$resultSym} = {$expressionCode};");
     });
     $compilerContext->addModifier("string_format", function (Compiler $compiler, ModifierNode $modifier, $expressionCode) {
         return new ModifierCompilerResult("sprintf(" . $compiler->walk($modifier->getArgument(0)) . ", {$expressionCode})");
     });
     // TODO: add needed modifiers
 }