Develop
This commit is contained in:
parent
7c83fe6460
commit
9ed8e987b9
|
@ -3,7 +3,7 @@
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"description": "Aspect - fast template engine for PHP",
|
"description": "Aspect - fast template engine for PHP",
|
||||||
"homepage": "https://github.com/bzick/aspect",
|
"homepage": "https://github.com/bzick/aspect",
|
||||||
"keywords": ["aspect", "templater", "templating", "template", "yohoho"],
|
"keywords": ["aspect", "templater", "templating", "template"],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
|
@ -18,7 +18,8 @@
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "3.7.*",
|
"phpunit/phpunit": "3.7.*",
|
||||||
"smarty/smarty": "3.*",
|
"smarty/smarty": "3.*",
|
||||||
"twig/twig": "1.*"
|
"twig/twig": "1.*",
|
||||||
|
"latte/latte": "dev-master"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-0": { "Aspect": "src/" }
|
"psr-0": { "Aspect": "src/" }
|
||||||
|
|
|
@ -18,20 +18,24 @@ class Compiler {
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function tagInclude(Tokenizer $tokens, Template $tpl) {
|
public static function tagInclude(Tokenizer $tokens, Template $tpl) {
|
||||||
|
$cname = $tpl->parseFirstArg($tokens, $name);
|
||||||
$p = $tpl->parseParams($tokens);
|
$p = $tpl->parseParams($tokens);
|
||||||
if(isset($p[0])) {
|
if($p) { // if we have additionally variables
|
||||||
$file_name = $p[0];
|
if($name && ($tpl->getStorage()->getOptions() & \Aspect::FORCE_INCLUDE)) { // if FORCE_INCLUDE enabled and template name known
|
||||||
} elseif (isset($p["file"])) {
|
$inc = $tpl->getStorage()->compile($name, false);
|
||||||
$file_name = $p["file"];
|
$tpl->addDepend($inc);
|
||||||
|
return '$_tpl = (array)$tpl; $tpl->exchangeArray('.self::_toArray($p).'+$_tpl); ?>'.$inc->_body.'<?php $tpl->exchangeArray($_tpl); unset($_tpl);';
|
||||||
|
} else {
|
||||||
|
return '$tpl->getStorage()->getTemplate('.$cname.')->display('.self::_toArray($p).'+(array)$tpl);';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new ImproperUseException("The tag {include} requires 'file' parameter");
|
if($name && ($tpl->getStorage()->getOptions() & \Aspect::FORCE_INCLUDE)) { // if FORCE_INCLUDE enabled and template name known
|
||||||
}
|
$inc = $tpl->getStorage()->compile($name, false);
|
||||||
unset($p["file"], $p[0]);
|
$tpl->addDepend($inc);
|
||||||
if($p) {
|
return '$_tpl = (array)$tpl; ?>'.$inc->_body.'<?php $tpl->exchangeArray($_tpl); unset($_tpl);';
|
||||||
return '$tpl->getStorage()->getTemplate('.$file_name.')->display('.self::_toArray($p).'+(array)$tpl);';
|
} else {
|
||||||
} else {
|
return '$tpl->getStorage()->getTemplate('.$cname.')->display((array)$tpl);';
|
||||||
return '$tpl->getStorage()->getTemplate('.$file_name.')->display((array)$tpl);';
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,8 +88,8 @@ class Compiler {
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
* @param Tokenizer $tokens
|
* @param Tokenizer $tokens
|
||||||
* @param Tokenizer $tokens
|
* @param Scope $scope
|
||||||
* @param Scope $scope
|
* @throws UnexpectedException
|
||||||
* @throws ImproperUseException
|
* @throws ImproperUseException
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -285,7 +289,7 @@ class Compiler {
|
||||||
public static function switchOpen(Tokenizer $tokens, Scope $scope) {
|
public static function switchOpen(Tokenizer $tokens, Scope $scope) {
|
||||||
$scope["no-break"] = $scope["no-continue"] = true;
|
$scope["no-break"] = $scope["no-continue"] = true;
|
||||||
$scope["switch"] = 'switch('.$scope->tpl->parseExp($tokens, true).') {';
|
$scope["switch"] = 'switch('.$scope->tpl->parseExp($tokens, true).') {';
|
||||||
// lazy switch init
|
// lazy init
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,6 +332,8 @@ class Compiler {
|
||||||
* Tag {default}
|
* Tag {default}
|
||||||
*
|
*
|
||||||
* @static
|
* @static
|
||||||
|
* @param Tokenizer $tokens
|
||||||
|
* @param Scope $scope
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function tagDefault($tokens, Scope $scope) {
|
public static function tagDefault($tokens, Scope $scope) {
|
||||||
|
@ -371,12 +377,14 @@ class Compiler {
|
||||||
$tpl_name = $tpl->parseFirstArg($tokens, $name);
|
$tpl_name = $tpl->parseFirstArg($tokens, $name);
|
||||||
$tpl->addPostCompile(__CLASS__."::extendBody");
|
$tpl->addPostCompile(__CLASS__."::extendBody");
|
||||||
if($name) { // static extends
|
if($name) { // static extends
|
||||||
|
//$tpl->_static = true;
|
||||||
$tpl->_extends = $tpl->getStorage()->getRawTemplate()->load($name, false);
|
$tpl->_extends = $tpl->getStorage()->getRawTemplate()->load($name, false);
|
||||||
$tpl->addDepend($tpl->_extends); // for valid compile-time need take template from storage
|
$tpl->addDepend($tpl->_extends); // for valid compile-time need take template from storage
|
||||||
return "/* Static extends */";
|
return "";
|
||||||
} else { // dynamic extends
|
} else { // dynamic extends
|
||||||
$tpl->_extends = $tpl_name;
|
$tpl->_extends = $tpl_name;
|
||||||
return '/* Dynamic extends */'."\n".'$parent = $tpl->getStorage()->getTemplate('.$tpl_name.');';
|
//$tpl->_static = false;
|
||||||
|
return '$parent = $tpl->getStorage()->getTemplate('.$tpl_name.');';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,23 +396,43 @@ class Compiler {
|
||||||
public static function extendBody(&$body, $tpl) {
|
public static function extendBody(&$body, $tpl) {
|
||||||
if(isset($tpl->_extends)) { // is child
|
if(isset($tpl->_extends)) { // is child
|
||||||
if(is_object($tpl->_extends)) { // static extends
|
if(is_object($tpl->_extends)) { // static extends
|
||||||
$t = $tpl->_extends;
|
|
||||||
/* @var Template $t */
|
/* @var Template $t */
|
||||||
do {
|
$t = $tpl->_extends;
|
||||||
|
if(empty($tpl->_dynamic)) {
|
||||||
|
do {
|
||||||
|
$t->_blocks = &$tpl->_blocks;
|
||||||
|
$t->compile();
|
||||||
|
$tpl->addDepend($t);
|
||||||
|
if(!empty($t->_dynamic)) {
|
||||||
|
$body = '<?php ob_start(); ?>'.$body.'<?php ob_end_clean(); ?>'.$t->_body;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
$body .= $t->_body;
|
||||||
|
}
|
||||||
|
} while(isset($t->_extends) && $t = $t->_extends);
|
||||||
|
$body = $t->_body;
|
||||||
|
} else {
|
||||||
$t->_blocks = &$tpl->_blocks;
|
$t->_blocks = &$tpl->_blocks;
|
||||||
|
$t->_dyn = &$tpl->_dynamic;
|
||||||
$t->compile();
|
$t->compile();
|
||||||
$tpl->addDepend($t);
|
$tpl->addDepend($t);
|
||||||
} while(isset($t->_extends) && $t = $t->_extends);
|
$body = '<?php ob_start(); ?>'.$body.'<?php ob_end_clean(); ?>'.$t->_body;
|
||||||
$body = $t->_body;
|
}
|
||||||
} else { // dynamic extends
|
} else { // dynamic extends
|
||||||
$body .= '<?php $parent->blocks = &$tpl->blocks; $parent->display((array)$tpl); unset($tpl->blocks, $parent->blocks); ?>';
|
$body .= '<?php $parent->blocks = &$tpl->blocks; $parent->display((array)$tpl); unset($tpl->blocks, $parent->blocks); ?>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
public static function tagUse(Tokenizer $tokens, Template $tpl) {
|
* @param Tokenizer $tokens
|
||||||
|
* @param Template $tpl
|
||||||
|
*/
|
||||||
|
public static function tagUse(Tokenizer $tokens, Template $tpl) {
|
||||||
|
$p = $tpl->parseFirstArg($tokens, $scalar);
|
||||||
|
if(!$scalar) {
|
||||||
|
$tpl->_static = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -417,19 +445,17 @@ class Compiler {
|
||||||
public static function tagBlockOpen(Tokenizer $tokens, Scope $scope) {
|
public static function tagBlockOpen(Tokenizer $tokens, Scope $scope) {
|
||||||
$p = $scope->tpl->parseFirstArg($tokens, $name);
|
$p = $scope->tpl->parseFirstArg($tokens, $name);
|
||||||
if ($name) {
|
if ($name) {
|
||||||
$scope["static"] = true;
|
|
||||||
$scope["name"] = $name;
|
$scope["name"] = $name;
|
||||||
$scope["cname"] = '"'.addslashes($name).'"';
|
$scope["cname"] = $p;
|
||||||
} else {
|
} else {
|
||||||
$scope["static"] = false;
|
$scope->tpl->_dynamic = true;
|
||||||
$scope["name"] = $scope["cname"] = $p;
|
$scope["name"] = $scope["cname"] = $p;
|
||||||
}
|
}
|
||||||
|
/*if($scope->level) {
|
||||||
|
$scope->tpl->_static = false;
|
||||||
|
}*/
|
||||||
if(isset($scope->tpl->_extends)) { // is child
|
if(isset($scope->tpl->_extends)) { // is child
|
||||||
if(is_object($scope->tpl->_extends) && $scope["static"]) { // static extends
|
return 'if(empty($tpl->blocks['.$scope["cname"].'])) { $tpl->blocks['.$scope["cname"].'] = function($tpl) {';
|
||||||
$code = "";
|
|
||||||
} else { // dynamic extends
|
|
||||||
$code = 'if(empty($tpl->blocks['.$scope["cname"].'])) { $tpl->blocks['.$scope["cname"].'] = function($tpl) {';
|
|
||||||
}
|
|
||||||
} else { // is parent
|
} else { // is parent
|
||||||
if(isset($scope->tpl->_blocks)) { // has blocks from child
|
if(isset($scope->tpl->_blocks)) { // has blocks from child
|
||||||
if(isset($scope->tpl->_blocks[ $scope["name"] ])) { // skip own block and insert child's block after
|
if(isset($scope->tpl->_blocks[ $scope["name"] ])) { // skip own block and insert child's block after
|
||||||
|
@ -438,11 +464,9 @@ class Compiler {
|
||||||
} // else just put block content as is
|
} // else just put block content as is
|
||||||
return '';
|
return '';
|
||||||
} else {
|
} else {
|
||||||
$code = 'if(isset($tpl->blocks['.$scope["cname"].'])) { echo $tpl->blocks['.$scope["cname"].']->__invoke($tpl); } else {';
|
return 'if(isset($tpl->blocks['.$scope["cname"].'])) { echo $tpl->blocks['.$scope["cname"].']->__invoke($tpl); } else {';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$scope["offset"] = strlen($scope->tpl->getBody()) + strlen($code);
|
|
||||||
return $code;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -454,18 +478,17 @@ class Compiler {
|
||||||
public static function tagBlockClose($tokens, Scope $scope) {
|
public static function tagBlockClose($tokens, Scope $scope) {
|
||||||
|
|
||||||
if(isset($scope->tpl->_extends)) { // is child
|
if(isset($scope->tpl->_extends)) { // is child
|
||||||
if(is_object($scope->tpl->_extends) && $scope["static"]) { // static extends
|
if(!isset($scope->tpl->_blocks[ $scope["name"] ])) {
|
||||||
if(!isset($scope->tpl->_blocks[ $scope["name"] ])) {
|
$scope->tpl->_blocks[ $scope["name"] ] = $scope->getContent();
|
||||||
$scope->tpl->_blocks[ $scope["name"] ] = substr($scope->tpl->getBody(), $scope["offset"]);
|
} // dynamic extends
|
||||||
}
|
return '}; }';
|
||||||
return "";
|
|
||||||
} else { // dynamic extends
|
|
||||||
return '} }';
|
|
||||||
}
|
|
||||||
} else { // is parent
|
} else { // is parent
|
||||||
if(isset($scope->tpl->_blocks)) {
|
if(isset($scope->tpl->_blocks)) {
|
||||||
if(isset($scope["body"])) {
|
if(isset($scope["body"])) {
|
||||||
$scope->tpl->_body = $scope["body"].$scope->tpl->_blocks[ $scope["name"] ];
|
$scope->tpl->_body = $scope["body"].
|
||||||
|
'<?php if(isset($tpl->blocks['.$scope["cname"].'])) { echo $tpl->blocks['.$scope["cname"].']->__invoke($tpl); } else {?>'.
|
||||||
|
$scope->tpl->_blocks[ $scope["name"] ].'}';
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
|
@ -474,6 +497,12 @@ class Compiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function tagParent($tokens, Scope $scope) {
|
||||||
|
if(empty($scope->tpl->_extends)) {
|
||||||
|
throw new ImproperUseException("Tag {parent} may be declared in childs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard close tag {/...}
|
* Standard close tag {/...}
|
||||||
*
|
*
|
||||||
|
@ -573,7 +602,7 @@ class Compiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set variable expression parser
|
* Set variable expression
|
||||||
* @param Tokenizer $tokens
|
* @param Tokenizer $tokens
|
||||||
* @param Template $tpl
|
* @param Template $tpl
|
||||||
* @param bool $allow_array
|
* @param bool $allow_array
|
||||||
|
@ -591,13 +620,45 @@ class Compiler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function tagModifyOpen(Tokenizer $tokens, Scope $scope) {
|
public static function filterOpen(Tokenizer $tokens, Scope $scope) {
|
||||||
$scope["modifiers"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()");
|
$scope["filter"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()");
|
||||||
return "ob_start();";
|
return "ob_start();";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function tagModifyClose($tokens, Scope $scope) {
|
public static function filterClose($tokens, Scope $scope) {
|
||||||
return "echo ".$scope["modifiers"].";";
|
return "echo ".$scope["filter"].";";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function captureOpen(Tokenizer $tokens, Scope $scope) {
|
||||||
|
if($tokens->is("|")) {
|
||||||
|
$scope["value"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()");
|
||||||
|
} else {
|
||||||
|
$scope["value"] = "ob_get_clean()";
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope["var"] = $scope->tpl->parseVar($tokens, Template::DENY_MODS);
|
||||||
|
|
||||||
|
return "ob_start();";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function captureClose($tokens, Scope $scope) {
|
||||||
|
return $scope["var"]." = ".$scope["value"].";";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function tagCycle(Tokenizer $tokens, Template $tpl) {
|
||||||
|
$exp = $tpl->parseExp($tokens, true);
|
||||||
|
if($tokens->valid()) {
|
||||||
|
$p = $tpl->parseParams($tokens);
|
||||||
|
if(empty($p["index"])) {
|
||||||
|
throw new ImproperUseException("Cycle may contain only index attribute");
|
||||||
|
} else {
|
||||||
|
return __CLASS__.'::cycle((array)'.$exp.', '.$p["index"].');';
|
||||||
|
//$index = $p["index"];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return __CLASS__.'::cycle((array)'.$exp.', isset($i) ? $i++ : ($i = 0) );';
|
||||||
|
//$index = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,8 @@ class Misc {
|
||||||
foreach($iterator as $file) {
|
foreach($iterator as $file) {
|
||||||
/* @var \splFileInfo $file*/
|
/* @var \splFileInfo $file*/
|
||||||
if($file->isFile()) {
|
if($file->isFile()) {
|
||||||
unlink($file->getRealPath());
|
if(strpos($file->getBasename(), ",") !== 0)
|
||||||
|
unlink($file->getRealPath());
|
||||||
} elseif($file->isDir()) {
|
} elseif($file->isDir()) {
|
||||||
rmdir($file->getRealPath());
|
rmdir($file->getRealPath());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,58 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Aspect\Template;
|
namespace Aspect;
|
||||||
use Aspect, Aspect\Modifier, Aspect\TestCase;
|
use Aspect, Aspect\Modifier, Aspect\TestCase;
|
||||||
|
|
||||||
class ExtendsTest extends TestCase {
|
class ExtendsTemplateTest extends TestCase {
|
||||||
public static function providerExtends() {
|
public static function providerExtends() {
|
||||||
|
$a = array("one" => 1, "two" => 2, "three" => 3);
|
||||||
return array(
|
return array(
|
||||||
array('{extends "parent.tpl"}{block "bk1"} block1 {/block}', "Template extended by block1"),
|
array("parent.tpl", "Parent. B1: {block b1}{/block}\nB2: {block 'b2'}empty {\$iteration}{/block}", $a,
|
||||||
array('{extends "parent.tpl"}{block "bk1"} block1 {/block}{block "bk2"} block2 {/block} garbage', "Template extended by block1"),
|
"Parent. B1: \nB2: empty 0"),
|
||||||
array('{extends "parent.tpl"}{block "bk1"} block1 {/block}{block "bk2"} block2 {/block} {block "bk3"} block3 {/block} garbage', "Template multi-extended by block1"),
|
array("child1.tpl", '{extends "parent.tpl"} {block b1}from child1 {$iteration}{/block} some trash', $a,
|
||||||
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"),
|
"Parent. B1: from child1 1\nB2: empty 1"),
|
||||||
|
array("child2.tpl", '{extends "child1.tpl"} {block "b2"}from child2 {$iteration}{/block} some {block b4}what is it?{/block} trash', $a,
|
||||||
|
"Parent. B1: from child1 2\nB2: from child2 2"),
|
||||||
|
array("child3.tpl", '{extends "child2.tpl"} {block \'b1\'}from child3 {$iteration}{/block} {block "b2"}from child3 {$iteration}{/block} some {block b4}what is it?{/block} trash', $a,
|
||||||
|
"Parent. B1: from child3 3\nB2: from child3 3")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function providerDynamicExtends() {
|
||||||
|
$data = self::providerExtends();
|
||||||
|
$data[2][1] = str_replace('"b2"', '"b{$two}"', $data[2][1]);
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerExtends
|
||||||
|
* @param $name
|
||||||
|
* @param $code
|
||||||
|
* @param $vars
|
||||||
|
* @param $result
|
||||||
|
*/
|
||||||
|
public function _testStaticExtends($name, $code, $vars, $result) {
|
||||||
|
static $i = 0;
|
||||||
|
$vars["iteration"] = $i++;
|
||||||
|
$this->execTpl($name, $code, $vars, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providerDynamicExtends
|
||||||
|
* @param $name
|
||||||
|
* @param $code
|
||||||
|
* @param $vars
|
||||||
|
* @param $result
|
||||||
|
*/
|
||||||
|
public function testDynamicExtends($name, $code, $vars, $result) {
|
||||||
|
static $i = 0;
|
||||||
|
$vars["iteration"] = $i++;
|
||||||
|
$this->execTpl($name, $code, $vars, $result);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group extends
|
* @group extends
|
||||||
*/
|
*/
|
||||||
public function testParentLevel() {
|
public function _testParentLevel() {
|
||||||
//echo($this->aspect->getTemplate("parent.tpl")->_body); exit;
|
//echo($this->aspect->getTemplate("parent.tpl")->_body); exit;
|
||||||
$this->assertSame($this->aspect->fetch("parent.tpl", array("a" => "a char")), "Parent template\nBlock1: Block2: Block3: default");
|
$this->assertSame($this->aspect->fetch("parent.tpl", array("a" => "a char")), "Parent template\nBlock1: Block2: Block3: default");
|
||||||
}
|
}
|
||||||
|
@ -23,7 +60,7 @@ class ExtendsTest extends TestCase {
|
||||||
/**
|
/**
|
||||||
* @group extends
|
* @group extends
|
||||||
*/
|
*/
|
||||||
public function testChildLevel1() {
|
public function _testChildLevel1() {
|
||||||
//echo($this->aspect->fetch("child1.tpl", array("a" => "a char"))); exit;
|
//echo($this->aspect->fetch("child1.tpl", array("a" => "a char"))); exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue