Exemplo n.º 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);
 }
Exemplo n.º 2
0
 public function fetch($templateFile)
 {
     if (strncmp($templateFile, "string:", strlen("string:")) === 0) {
         $this->parserContext->setString(substr($templateFile, strlen("string:")));
         $this->compilerContext->setClassName("Template_" . md5($this->parserContext->getString()));
     } else {
         if (!is_null($this->parserContext->getBaseDirectory()) && strncmp($templateFile, $this->parserContext->getBaseDirectory(), strlen($this->parserContext->getBaseDirectory())) === 0) {
             $templateFile = substr($templateFile, strlen($this->parserContext->getBaseDirectory()) + 1);
         }
         // must be set before CompilerContext::getFullyQualifiedClassName() is called
         // FIXME: uncouple this
         $this->parserContext->setFile($templateFile);
     }
     $className = $this->compilerContext->getFullyQualifiedClassName();
     if (!class_exists($className)) {
         $saveFileName = $this->classDirectory . "/" . str_replace("\\", "/", trim($className, "\\") . ".php");
         if (file_exists($saveFileName)) {
             require_once $saveFileName;
         } else {
             $oldUmask = umask(0);
             $compiledTemplate = $this->compilerContext->setTemplate($this->parserContext->parse())->compile();
             if (!is_dir(dirname($saveFileName))) {
                 @mkdir(dirname($saveFileName), $this->dirPerms, true);
             }
             file_put_contents($saveFileName, $compiledTemplate);
             @chmod($saveFileName, $this->dirPerms);
             umask($oldUmask);
             require_once $saveFileName;
         }
     }
     $templateInstance = new $className();
     ob_start();
     $templateInstance($this->locals);
     $output = ob_get_clean();
     foreach ($this->outputFilters as $filter) {
         $output = $filter($output);
     }
     return $output;
 }
Exemplo n.º 3
0
 /**
  * @return string
  * @throws CompilerException
  */
 public function compile()
 {
     $namespace = null;
     $className = trim($this->context->getFullyQualifiedClassName(), "\\");
     $pos = strrpos($className, "\\");
     if ($pos !== false) {
         $namespace = substr($className, 0, $pos);
         $className = substr($className, $pos + 1);
     }
     // prelude
     $ret = "";
     $ret .= "<?php\n";
     if ($namespace) {
         $ret .= "namespace {$namespace};\n";
         $ret .= "\n";
     }
     foreach ($this->context->getUses() as $alias => $fqn) {
         $ret .= "use {$fqn} as {$alias};\n";
     }
     $ret .= "\n";
     $ret .= "class {$className} implements \\Skrz\\Templating\\Engine\\TemplateInterface {\n";
     $ret .= "\n";
     $ret .= "public function __invoke(array \$____) {\n";
     $ret .= "\t\$this->render(\$____);\n";
     $ret .= "}\n";
     $ret .= "\n";
     $ret .= "public function fetch(array \$____) {\n";
     $ret .= "\tob_start();\n";
     $ret .= "\t\$this->render(\$____);\n";
     $ret .= "\treturn ob_get_clean();\n";
     $ret .= "}\n";
     $ret .= "\n";
     $ret .= "public function fetchFunction(\$functionName, array \$____) {\n";
     $ret .= "\tob_start();\n";
     $ret .= "\t\$this->{'render' . \$functionName}(\$____);\n";
     $ret .= "\treturn ob_get_clean();\n";
     $ret .= "}\n";
     $ret .= "\n";
     $ret .= "public function renderFunction(\$functionName, array \$____) {\n";
     $ret .= "\t\$this->{'render' . \$functionName}(\$____);\n";
     $ret .= "}\n";
     $ret .= "\n";
     // find function declarations
     $functionDeclarationFinder = new FunctionDeclarationsWalker();
     $functionDeclarationFinder->walk($this->context->getTemplate());
     // function declarations have to be registered first and compiled into render functions,
     // otherwise recursive calls would not be possible
     $ret .= "private \$functions = array(";
     foreach ($functionDeclarationFinder->getDeclarations() as $declaration) {
         $ret .= var_export($declaration->getName(), true) . "=>true,";
         $this->context->addFunction($declaration->getName(), function (Compiler $compiler, FunctionNode $node) use($declaration) {
             $statement = "";
             $args = "array(";
             foreach ($node->getArguments() as $name => $expression) {
                 $statementAndExpression = $compiler->walkExpression($expression);
                 $statement .= $statementAndExpression->getStatement();
                 $args .= var_export($name, true) . '=>' . $statementAndExpression->getExpression() . ",";
             }
             $args .= ")";
             return new FunctionCompilerResult($statement . "\$this->" . $this->getRenderName($declaration->getName()) . "(" . $args . " + \$____);");
         });
     }
     $ret .= ");\n\n";
     $ret .= "public function hasFunction(\$functionName) {\n";
     $ret .= "\treturn isset(\$this->functions[\$functionName]);\n";
     $ret .= "}\n\n";
     foreach ($functionDeclarationFinder->getDeclarations() as $declaration) {
         $ret .= $this->compileRender($declaration->getName(), $declaration->getBody(), $declaration->getDefaultArguments());
     }
     // compile main render
     $ret .= $this->compileRender("", array($this->context->getTemplate()));
     // end
     $ret .= "\n";
     $ret .= "}\n";
     return $ret;
 }