mirror of
https://github.com/fenom-template/fenom.git
synced 2023-08-10 21:13:07 +03:00
Refactory template ctor
Dev extends
This commit is contained in:
parent
95daa95cd2
commit
8c618c2b34
@ -94,7 +94,7 @@ class Aspect {
|
||||
protected $_on_post_cmp = array();
|
||||
|
||||
/**
|
||||
* @var Aspect\Provider
|
||||
* @var ProviderInterface
|
||||
*/
|
||||
private $_provider;
|
||||
/**
|
||||
@ -107,7 +107,9 @@ class Aspect {
|
||||
*/
|
||||
protected $_modifiers = array(
|
||||
"upper" => 'strtoupper',
|
||||
"up" => 'strtoupper',
|
||||
"lower" => 'strtolower',
|
||||
"low" => 'strtolower',
|
||||
"date_format" => 'Aspect\Modifier::dateFormat',
|
||||
"date" => 'Aspect\Modifier::date',
|
||||
"truncate" => 'Aspect\Modifier::truncate',
|
||||
@ -123,9 +125,9 @@ class Aspect {
|
||||
* @var array of allowed PHP functions
|
||||
*/
|
||||
protected $_allowed_funcs = array(
|
||||
"empty" => 1, "isset" => 1, "count" => 1, "is_string" => 1, "is_array" => 1, "is_numeric" => 1, "is_int" => 1,
|
||||
"count" => 1, "is_string" => 1, "is_array" => 1, "is_numeric" => 1, "is_int" => 1,
|
||||
"is_object" => 1, "strtotime" => 1, "gettype" => 1, "is_double" => 1, "json_encode" => 1, "json_decode" => 1,
|
||||
"ip2long" => 1, "long2ip" => 1, "strip_tags" => 1, "nl2br" => 1
|
||||
"ip2long" => 1, "long2ip" => 1, "strip_tags" => 1, "nl2br" => 1, "explode" => 1, "implode" => 1
|
||||
);
|
||||
|
||||
/**
|
||||
@ -215,18 +217,25 @@ class Aspect {
|
||||
|
||||
);
|
||||
|
||||
/**
|
||||
* Factory
|
||||
* @param string $template_dir path to templates
|
||||
* @param string $compile_dir path to compiled files
|
||||
* @param int $options
|
||||
* @param \Aspect\Provider $provider
|
||||
* @return Aspect
|
||||
*/
|
||||
public static function factory($template_dir, $compile_dir, $options = 0, Aspect\Provider $provider = null) {
|
||||
/**
|
||||
* Just factory
|
||||
*
|
||||
* @param string|Aspect\ProviderInterface $source path to templates or custom provider
|
||||
* @param string $compile_dir path to compiled files
|
||||
* @param int $options
|
||||
* @throws InvalidArgumentException
|
||||
* @return Aspect
|
||||
*/
|
||||
public static function factory($source, $compile_dir = '/tmp', $options = 0) {
|
||||
if(is_string($source)) {
|
||||
$provider = new \Aspect\Provider\FS($source);
|
||||
} elseif($source instanceof Aspect\ProviderInterface) {
|
||||
$provider = $source;
|
||||
} else {
|
||||
throw new InvalidArgumentException("Source must be a valid path or provider object");
|
||||
}
|
||||
$aspect = new static($provider);
|
||||
$aspect->setCompileDir($compile_dir);
|
||||
$aspect->setTemplateDirs($template_dir);
|
||||
if($options) {
|
||||
$aspect->setOptions($options);
|
||||
}
|
||||
@ -234,10 +243,10 @@ class Aspect {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Aspect\Provider $provider
|
||||
* @param Aspect\ProviderInterface $provider
|
||||
*/
|
||||
public function __construct(Aspect\Provider $provider = null) {
|
||||
$this->_provider = $provider ?: new Aspect\Provider();
|
||||
public function __construct(Aspect\ProviderInterface $provider) {
|
||||
$this->_provider = $provider;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -271,16 +280,6 @@ class Aspect {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set template directory
|
||||
* @param string|array $dirs directory(s) of template sources
|
||||
* @return Aspect
|
||||
*/
|
||||
public function setTemplateDirs($dirs) {
|
||||
$this->_provider->setTemplateDirs($dirs);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param callable $cb
|
||||
@ -446,19 +445,8 @@ class Aspect {
|
||||
return $tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add template directory
|
||||
* @static
|
||||
* @param string $dir
|
||||
* @return \Aspect
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addTemplateDir($dir) {
|
||||
$this->_provider->addTemplateDir($dir);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addProvider($scm, \Aspect\Provider $provider) {
|
||||
public function addProvider($scm, \Aspect\ProviderInterface $provider) {
|
||||
$this->_providers[$scm] = $provider;
|
||||
}
|
||||
|
||||
@ -489,7 +477,7 @@ class Aspect {
|
||||
|
||||
/**
|
||||
* @param bool|string $scm
|
||||
* @return Aspect\Provider
|
||||
* @return Aspect\ProviderInterface
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function getProvider($scm = false) {
|
||||
@ -504,6 +492,10 @@ class Aspect {
|
||||
}
|
||||
}
|
||||
|
||||
public function getRawTemplate() {
|
||||
return new \Aspect\Template($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute template and write result into stdout
|
||||
*
|
||||
@ -556,7 +548,6 @@ class Aspect {
|
||||
*/
|
||||
public function addTemplate(Aspect\Render $template) {
|
||||
$this->_storage[ $template->getName() ] = $template;
|
||||
$template->setStorage($this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -572,9 +563,7 @@ class Aspect {
|
||||
return $this->compile($tpl);
|
||||
} else {
|
||||
/** @var Aspect\Render $tpl */
|
||||
$tpl = include($this->_compile_dir."/".$file_name);
|
||||
$tpl->setStorage($this);
|
||||
return $tpl;
|
||||
return include($this->_compile_dir."/".$file_name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -593,24 +582,23 @@ class Aspect {
|
||||
* Compile and save template
|
||||
*
|
||||
* @param string $tpl
|
||||
* @param bool $store
|
||||
* @param bool $store store template on disk
|
||||
* @throws RuntimeException
|
||||
* @return \Aspect\Template
|
||||
*/
|
||||
public function compile($tpl, $store = true) {
|
||||
$provider = $this->getProvider(strstr($tpl, ":", true));
|
||||
$template = new Template($this, $provider->loadCode($tpl), $tpl);
|
||||
$template = Template::factory($this)->load($tpl);
|
||||
if($store) {
|
||||
$tpl_tmp = tempnam($this->_compile_dir, basename($tpl));
|
||||
$tpl_fp = fopen($tpl_tmp, "w");
|
||||
if(!$tpl_fp) {
|
||||
throw new \RuntimeException("Can not open temporary file $tpl_tmp. Directory ".$this->_compile_dir." is writable?");
|
||||
throw new \RuntimeException("Can't to open temporary file $tpl_tmp. Directory ".$this->_compile_dir." is writable?");
|
||||
}
|
||||
fwrite($tpl_fp, $template->getTemplateCode());
|
||||
fclose($tpl_fp);
|
||||
$file_name = $this->_compile_dir."/".$this->_getHash($tpl);
|
||||
if(!rename($tpl_tmp, $file_name)) {
|
||||
throw new \RuntimeException("Can not to move $tpl_tmp to $tpl");
|
||||
throw new \RuntimeException("Can't to move $tpl_tmp to $tpl");
|
||||
}
|
||||
}
|
||||
return $template;
|
||||
@ -654,7 +642,7 @@ class Aspect {
|
||||
* @return Aspect\Template
|
||||
*/
|
||||
public function compileCode($code, $name = 'Runtime compile') {
|
||||
return new Template($this, $code, $name);
|
||||
return Template::factory($this)->source($name, $code);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -357,16 +357,6 @@ class Compiler {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check if value is scalar, like "string", 2, 2.2, true, false, null
|
||||
* @param string $value
|
||||
* @return bool
|
||||
* @todo add 'string' support
|
||||
*/
|
||||
public static function isScalar($value) {
|
||||
return json_decode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch {extends} tag
|
||||
* @param Tokenizer $tokens
|
||||
@ -378,18 +368,11 @@ class Compiler {
|
||||
if(!empty($tpl->_extends)) {
|
||||
throw new ImproperUseException("Only one {extends} allowed");
|
||||
}
|
||||
$p = $tpl->parseParams($tokens);
|
||||
if(isset($p[0])) {
|
||||
$tpl_name = $p[0];
|
||||
} elseif (isset($p["file"])) {
|
||||
$tpl_name = $p["file"];
|
||||
} else {
|
||||
throw new ImproperUseException("{extends} require 'file' parameter");
|
||||
}
|
||||
$tpl_name = $tpl->parseFirstArg($tokens, $name);
|
||||
$tpl->addPostCompile(__CLASS__."::extendBody");
|
||||
if($name = self::isScalar($tpl_name)) { // static extends
|
||||
$tpl->_extends = $tpl->getStorage()->compile($name, false);
|
||||
$tpl->addDepend($tpl->getStorage()->getTemplate($name)); // for valid compile-time need take template from storage
|
||||
if($name) { // static extends
|
||||
$tpl->_extends = $tpl->getStorage()->getRawTemplate()->load($name, false);
|
||||
$tpl->addDepend($tpl->_extends); // for valid compile-time need take template from storage
|
||||
return "/* Static extends */";
|
||||
} else { // dynamic extends
|
||||
$tpl->_extends = $tpl_name;
|
||||
@ -443,9 +426,7 @@ class Compiler {
|
||||
*/
|
||||
public static function tagBlockOpen(Tokenizer $tokens, Scope $scope) {
|
||||
$p = $scope->tpl->parseParams($tokens);
|
||||
if(isset($p["name"])) {
|
||||
$scope["name"] = $p["name"];
|
||||
} elseif (isset($p[0])) {
|
||||
if (isset($p[0])) {
|
||||
$scope["name"] = $p[0];
|
||||
} else {
|
||||
throw new ImproperUseException("{block} must be named");
|
||||
@ -476,7 +457,7 @@ class Compiler {
|
||||
* @return string
|
||||
*/
|
||||
public static function tagBlockClose($tokens, Scope $scope) {
|
||||
$scope->tpl->_blocks[ self::isScalar($scope["name"]) ] = substr($scope->tpl->getBody(), $scope["offset"]);
|
||||
$scope->tpl->_blocks[ $scope["name"] ] = substr($scope->tpl->getBody(), $scope["offset"]);
|
||||
if(isset($scope->tpl->_extends)) { // is child
|
||||
if(is_object($scope->tpl->_extends)) { // static extends
|
||||
return "";
|
||||
|
@ -6,6 +6,13 @@ use Aspect;
|
||||
* Primitive template
|
||||
*/
|
||||
class Render extends \ArrayObject {
|
||||
private static $_props = array(
|
||||
"name" => "runtime",
|
||||
"base_name" => "",
|
||||
"scm" => false,
|
||||
"time" => 0,
|
||||
"depends" => array()
|
||||
);
|
||||
/**
|
||||
* @var \Closure
|
||||
*/
|
||||
@ -14,7 +21,9 @@ class Render extends \ArrayObject {
|
||||
* Template name
|
||||
* @var string
|
||||
*/
|
||||
protected $_name = 'runtime template';
|
||||
protected $_name = 'runtime';
|
||||
protected $_scm = false;
|
||||
protected $_base_name = 'runtime';
|
||||
/**
|
||||
* @var Aspect
|
||||
*/
|
||||
@ -28,24 +37,26 @@ class Render extends \ArrayObject {
|
||||
protected $_depends = array();
|
||||
|
||||
/**
|
||||
* @param string $name template name
|
||||
* @param callable $code template body
|
||||
* @param mixed $props signature
|
||||
* Template provider
|
||||
* @var ProviderInterface
|
||||
*/
|
||||
public function __construct($name, \Closure $code, $props = array()) {
|
||||
$this->_name = $name;
|
||||
$this->_code = $code;
|
||||
$this->_time = isset($props["time"]) ? $props["time"] : microtime(true);
|
||||
$this->_depends = isset($props["depends"]) ? $props["depends"] : array();
|
||||
}
|
||||
protected $_provider;
|
||||
|
||||
/**
|
||||
* Set template storage
|
||||
* @param Aspect $aspect
|
||||
* @param callable $code template body
|
||||
* @param array $props
|
||||
*/
|
||||
public function setStorage(Aspect $aspect) {
|
||||
public function __construct(Aspect $aspect, \Closure $code, $props = array()) {
|
||||
$this->_aspect = $aspect;
|
||||
}
|
||||
$props += self::$_props;
|
||||
$this->_name = $props["name"];
|
||||
$this->_provider = $this->_aspect->getProvider($props["scm"]);
|
||||
$this->_scm = $props["scm"];
|
||||
$this->_time = $props["time"];
|
||||
$this->_depends = $props["depends"];
|
||||
$this->_code = $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get template storage
|
||||
@ -55,11 +66,23 @@ class Render extends \ArrayObject {
|
||||
return $this->_aspect;
|
||||
}
|
||||
|
||||
public function getScm() {
|
||||
return $this->_scm;
|
||||
}
|
||||
|
||||
public function getProvider() {
|
||||
return $this->_provider;
|
||||
}
|
||||
|
||||
public function getBaseName() {
|
||||
return $this->_base_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() {
|
||||
return "Template({$this->_name})";
|
||||
return $this->_name;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,27 +53,65 @@ class Template extends Render {
|
||||
*/
|
||||
public static $sysvar = array('$aspect' => 1, '$smarty' => 1);
|
||||
|
||||
/**
|
||||
* @param Aspect $aspect Template storage
|
||||
* @param string $code template source
|
||||
* @param string $name template name
|
||||
* @param bool $auto_compile
|
||||
*/
|
||||
public function __construct(Aspect $aspect, $code, $name = "runtime template", $auto_compile = true) {
|
||||
$this->_src = $code;
|
||||
$this->_name = $name;
|
||||
$this->_aspect = $aspect;
|
||||
$this->_options = $aspect->getOptions();
|
||||
if($auto_compile) {
|
||||
$this->compile();
|
||||
}
|
||||
public static function factory(Aspect $aspect) {
|
||||
return new static($aspect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Aspect $aspect Template storage
|
||||
*/
|
||||
public function __construct(Aspect $aspect) {
|
||||
$this->_aspect = $aspect;
|
||||
$this->_options = $this->_aspect->getOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load source from provider
|
||||
* @param string $name
|
||||
* @param bool $compile
|
||||
* @return \Aspect\Template
|
||||
*/
|
||||
public function load($name, $compile = true) {
|
||||
$this->_name = $name;
|
||||
if($provider = strstr($name, ":", true)) {
|
||||
$this->_scm = $provider;
|
||||
$this->_base_name = substr($name, strlen($provider));
|
||||
} else {
|
||||
$this->_base_name = $name;
|
||||
}
|
||||
$this->_provider = $this->_aspect->getProvider($provider);
|
||||
$this->_src = $this->_provider->getSource($name, $this->_time);
|
||||
if($compile) {
|
||||
$this->compile();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load custom source
|
||||
* @param string $name template name
|
||||
* @param string $src template source
|
||||
* @param bool $compile
|
||||
* @return \Aspect\Template
|
||||
*/
|
||||
public function source($name, $src, $compile = true) {
|
||||
$this->_name = $name;
|
||||
$this->_src = $src;
|
||||
if($compile) {
|
||||
$this->compile();
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert template to PHP code
|
||||
*
|
||||
* @throws CompileException
|
||||
*/
|
||||
public function compile() {
|
||||
if(!isset($this->_src)) {
|
||||
return;
|
||||
}
|
||||
$this->_time = microtime(true);
|
||||
$pos = 0;
|
||||
while(($start = strpos($this->_src, '{', $pos)) !== false) { // search open-char of tags
|
||||
switch($this->_src[$start + 1]) { // check next char
|
||||
@ -95,19 +133,20 @@ class Template extends Render {
|
||||
$tag = substr($this->_src, $start, $end - $start + 1); // variable $tag contains aspect tag '{...}'
|
||||
$this->_line += substr_count($this->_src, "\n", $this->_pos, $end - $start + 1); // count lines in $frag and $tag (using original text $code)
|
||||
$pos = $this->_pos = $end + 1; // move search-pointer to end of the tag
|
||||
if($this->_trim) { // if previous tag has trim flag
|
||||
$frag = ltrim($frag);
|
||||
}
|
||||
//if($this->_trim) { // if previous tag has trim flag
|
||||
// $frag = ltrim($frag);
|
||||
//}
|
||||
|
||||
$this->_body .= str_replace("<?", '<?php echo "<?" ?>', $frag);
|
||||
|
||||
$tag = $this->_tag($tag, $this->_trim); // dispatching tags
|
||||
|
||||
if($this->_trim) { // if current tag has trim flag
|
||||
$frag = rtrim($frag);
|
||||
}
|
||||
$this->_body .= str_replace("<?", '<?php echo "<?" ?>', $frag).$tag;
|
||||
|
||||
//if($this->_trim) { // if current tag has trim flag
|
||||
// $frag = rtrim($frag);
|
||||
//}
|
||||
$this->_body .= $tag;
|
||||
}
|
||||
$this->_body .= substr($this->_src, $this->_pos);
|
||||
$this->_body .= str_replace("<?", '<?php echo "<?" ?>', substr($this->_src, $this->_pos));
|
||||
if($this->_stack) {
|
||||
$_names = array();
|
||||
$_line = 0;
|
||||
@ -146,9 +185,11 @@ class Template extends Render {
|
||||
public function getTemplateCode() {
|
||||
return "<?php \n".
|
||||
"/** Aspect template '".$this->_name."' compiled at ".date('Y-m-d H:i:s')." */\n".
|
||||
"return new Aspect\\Render('{$this->_name}', ".$this->_getClosureCode().", ".var_export(array(
|
||||
"options" => $this->_options,
|
||||
//"provider" =>
|
||||
"return new Aspect\\Render(\$this, ".$this->_getClosureSource().", ".var_export(array(
|
||||
//"options" => $this->_options,
|
||||
"provider" => $this->_scm,
|
||||
"name" => $this->_name,
|
||||
"base_name" => $this->_base_name,
|
||||
"time" => $this->_time,
|
||||
"depends" => $this->_depends
|
||||
), true).");\n";
|
||||
@ -158,7 +199,7 @@ class Template extends Render {
|
||||
* Return closure code
|
||||
* @return string
|
||||
*/
|
||||
private function _getClosureCode() {
|
||||
private function _getClosureSource() {
|
||||
return "function (\$tpl) {\n?>{$this->_body}<?php\n}";
|
||||
}
|
||||
|
||||
@ -172,7 +213,7 @@ class Template extends Render {
|
||||
public function display(array $values) {
|
||||
if(!$this->_code) {
|
||||
// evaluate template's code
|
||||
eval("\$this->_code = ".$this->_getClosureCode().";");
|
||||
eval("\$this->_code = ".$this->_getClosureSource().";");
|
||||
if(!$this->_code) {
|
||||
throw new CompileException("Fatal error while creating the template");
|
||||
}
|
||||
@ -186,6 +227,7 @@ class Template extends Render {
|
||||
* @param Render $tpl
|
||||
*/
|
||||
public function addDepend(Render $tpl) {
|
||||
|
||||
$this->_depends[$tpl->getName()] = $tpl->getCompileTime();
|
||||
}
|
||||
|
||||
@ -197,7 +239,7 @@ class Template extends Render {
|
||||
*/
|
||||
public function fetch(array $values) {
|
||||
if(!$this->_code) {
|
||||
eval("\$this->_code = ".$this->_getClosureCode().";");
|
||||
eval("\$this->_code = ".$this->_getClosureSource().";");
|
||||
if(!$this->_code) {
|
||||
throw new CompileException("Fatal error while creating the template");
|
||||
}
|
||||
@ -245,9 +287,6 @@ class Template extends Render {
|
||||
break;
|
||||
default:
|
||||
$code = $this->_parseAct($tokens);
|
||||
if($code === null) {
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -823,6 +862,18 @@ class Template extends Render {
|
||||
throw new TokenizeException("Unexpected token '".$tokens->current()."' in argument list");
|
||||
}
|
||||
|
||||
public function parseFirstArg(Tokenizer $tokens, &$static) {
|
||||
if($tokens->is(T_CONSTANT_ENCAPSED_STRING)) {
|
||||
$str = $tokens->getAndNext();
|
||||
$static = stripslashes(substr($str, 1, -1));
|
||||
return $str;
|
||||
} elseif($tokens->is(Tokenizer::MACRO_STRING)) {
|
||||
return $static = $tokens->getAndNext();
|
||||
} else {
|
||||
return $this->parseExp($tokens, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse parameters as $key=$value
|
||||
* param1=$var param2=3 ...
|
||||
|
@ -11,15 +11,19 @@ class RenderTest extends \PHPUnit_Framework_TestCase {
|
||||
public static $render;
|
||||
|
||||
public static function setUpBeforeClass() {
|
||||
self::$render = new Render("render.tpl", function ($tpl) {
|
||||
echo "It is render function ".$tpl["render"];
|
||||
}, array());
|
||||
self::$render = new Render(Aspect::factory("."), function ($tpl) {
|
||||
echo "It is render's function ".$tpl["render"];
|
||||
}, array(
|
||||
"name" => "render.tpl"
|
||||
));
|
||||
}
|
||||
|
||||
public function testCreate() {
|
||||
$r = new Render("test.render.tpl", function () {
|
||||
$r = new Render(Aspect::factory("."), function () {
|
||||
echo "Test render";
|
||||
}, array());
|
||||
}, array(
|
||||
"name" => "test.render.tpl"
|
||||
));
|
||||
$this->assertSame("Test render", $r->fetch(array()));
|
||||
}
|
||||
|
||||
@ -27,22 +31,24 @@ class RenderTest extends \PHPUnit_Framework_TestCase {
|
||||
ob_start();
|
||||
self::$render->display(array("render" => "display"));
|
||||
$out = ob_get_clean();
|
||||
$this->assertSame("It is render function display", $out);
|
||||
$this->assertSame("It is render's function display", $out);
|
||||
}
|
||||
|
||||
public function testFetch() {
|
||||
$this->assertSame("It is render function fetch", self::$render->fetch(array("render" => "fetch")));
|
||||
$this->assertSame("It is render's function fetch", self::$render->fetch(array("render" => "fetch")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException RuntimeException
|
||||
* @expectedException \RuntimeException
|
||||
* @expectedExceptionMessage template error
|
||||
*/
|
||||
public function testFetchException() {
|
||||
$render = new Render("render.tpl", function ($tpl) {
|
||||
$render = new Render(Aspect::factory("."), function () {
|
||||
echo "error";
|
||||
throw new \RuntimeException("template error");
|
||||
});
|
||||
}, array(
|
||||
"name" => "render.tpl"
|
||||
));
|
||||
$render->fetch(array());
|
||||
}
|
||||
|
||||
|
72
tests/cases/Aspect/Template/ExtendsTest.php
Normal file
72
tests/cases/Aspect/Template/ExtendsTest.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
namespace Aspect\Template;
|
||||
use Aspect, Aspect\Modifier;
|
||||
|
||||
class ExtendsTest extends \PHPUnit_Framework_TestCase {
|
||||
/**
|
||||
* @var Aspect
|
||||
*/
|
||||
public static $aspect;
|
||||
|
||||
public function setUp() {
|
||||
if(!file_exists(ASPECT_RESOURCES.'/compile')) {
|
||||
mkdir(ASPECT_RESOURCES.'/compile', 0777, true);
|
||||
} else {
|
||||
exec("rm -f ".ASPECT_RESOURCES.'/compile/*');
|
||||
}
|
||||
self::$aspect = Aspect::factory(ASPECT_RESOURCES.'/template', ASPECT_RESOURCES.'/compile');
|
||||
}
|
||||
|
||||
public static function providerExtends() {
|
||||
return array(
|
||||
array('{extends "parent.tpl"}{block "bk1"} block1 {/block}', "Template extended by block1"),
|
||||
array('{extends "parent.tpl"}{block "bk1"} block1 {/block}{block "bk2"} block2 {/block} garbage', "Template extended by block1"),
|
||||
array('{extends "parent.tpl"}{block "bk1"} block1 {/block}{block "bk2"} block2 {/block} {block "bk3"} block3 {/block} garbage', "Template multi-extended by block1"),
|
||||
array('{extends "parent.tpl"}{var $bk = "bk3"}{block "bk1"} block1 {/block}{block "bk2"} block2 {/block} {block "$bk"} block3 {/block} garbage', "Template multi-extended by block1"),
|
||||
);
|
||||
}
|
||||
|
||||
public function exec($code, $vars, $result, $dump = false) {
|
||||
$tpl = self::$aspect->compileCode($code, "inline.tpl");
|
||||
if($dump) {
|
||||
echo "\n===========================\n".$code.": ".$tpl->getBody();
|
||||
}
|
||||
$this->assertSame(Modifier::strip($result), Modifier::strip($tpl->fetch($vars), true), "Test $code");
|
||||
}
|
||||
|
||||
public function execError($code, $exception, $message, $options) {
|
||||
self::$aspect->setOptions($options);
|
||||
try {
|
||||
self::$aspect->compileCode($code, "inline.tpl");
|
||||
} catch(\Exception $e) {
|
||||
$this->assertSame($exception, get_class($e), "Exception $code");
|
||||
$this->assertStringStartsWith($message, $e->getMessage());
|
||||
self::$aspect->setOptions(0);
|
||||
return;
|
||||
}
|
||||
self::$aspect->setOptions(0);
|
||||
$this->fail("Code $code must be invalid");
|
||||
}
|
||||
|
||||
/**
|
||||
* @group extends
|
||||
*/
|
||||
public function testParent() {
|
||||
//echo(self::$aspect->getTemplate("parent.tpl")->getBody()); exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @group extends
|
||||
*/
|
||||
public function ___testChildLevel1() {
|
||||
echo(self::$aspect->getTemplate("child1.tpl")->getBody()); exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @group extends
|
||||
*/
|
||||
public function __testExtends() {
|
||||
echo(self::$aspect->fetch("child1.tpl", array("a" => "value", "z" => ""))."\n"); exit;
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,11 @@ class TemplateTest extends \PHPUnit_Framework_TestCase {
|
||||
exec("rm -f ".ASPECT_RESOURCES.'/compile/*');
|
||||
}
|
||||
self::$aspect = Aspect::factory(ASPECT_RESOURCES.'/template', ASPECT_RESOURCES.'/compile');
|
||||
self::$aspect->addTemplate(new Render("welcome.tpl", function ($tpl) {
|
||||
self::$aspect->addTemplate(new Render(self::$aspect, function ($tpl) {
|
||||
echo "<b>Welcome, ".$tpl["username"]." (".$tpl["email"].")</b>";
|
||||
}, array()));
|
||||
}, array(
|
||||
"name" => "welcome.tpl"
|
||||
)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,7 +21,6 @@ class AspectTest extends \PHPUnit_Framework_TestCase {
|
||||
self::tearDownAfterClass();
|
||||
$this->aspect = $aspect = Aspect::factory(ASPECT_RESOURCES.'/template', ASPECT_RESOURCES.'/compile');
|
||||
$aspect->setCompileDir(ASPECT_RESOURCES.'/compile');
|
||||
$aspect->addTemplateDir(ASPECT_RESOURCES.'/template');
|
||||
$aspect->setForceCompile(false);
|
||||
$aspect->setCompileCheck(false);
|
||||
}
|
||||
@ -36,11 +35,13 @@ class AspectTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testAddRender() {
|
||||
$test = $this;
|
||||
$this->aspect->addTemplate(new Render('render.tpl', function($tpl) use ($test) {
|
||||
$this->aspect->addTemplate(new Render($this->aspect, function($tpl) use ($test) {
|
||||
/** @var \PHPUnit_Framework_TestCase $test */
|
||||
$test->assertInstanceOf('Aspect\Render', $tpl);
|
||||
echo "Inline render";
|
||||
}, array()));
|
||||
}, array(
|
||||
"name" => 'render.tpl'
|
||||
)));
|
||||
|
||||
$this->assertSame("Inline render", $this->aspect->fetch('render.tpl', array()));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user