Fix tabulation

Add 'macro' namespace in import support
This commit is contained in:
bzick 2013-02-23 16:35:11 +04:00
parent b3480e820b
commit 7631e3508d
7 changed files with 238 additions and 221 deletions

View File

@ -1,6 +1,6 @@
<?php
use Aspect\Template,
Aspect\ProviderInterface;
Aspect\ProviderInterface;
/**
* Aspect Template Engine
@ -89,14 +89,14 @@ class Aspect {
protected $_on_cmp = array();
protected $_on_post_cmp = array();
/**
* @var ProviderInterface
*/
private $_provider;
/**
* @var array of Aspect\ProviderInterface
*/
protected $_providers = array();
/**
* @var ProviderInterface
*/
private $_provider;
/**
* @var array of Aspect\ProviderInterface
*/
protected $_providers = array();
/**
* @var array of modifiers [modifier_name => callable]
@ -122,7 +122,7 @@ class Aspect {
protected $_allowed_funcs = array(
"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, "explode" => 1, "implode" => 1
"ip2long" => 1, "long2ip" => 1, "strip_tags" => 1, "nl2br" => 1, "explode" => 1, "implode" => 1
);
/**
@ -252,12 +252,12 @@ class Aspect {
return $aspect;
}
/**
* @param Aspect\ProviderInterface $provider
*/
public function __construct(Aspect\ProviderInterface $provider) {
$this->_provider = $provider;
}
/**
* @param Aspect\ProviderInterface $provider
*/
public function __construct(Aspect\ProviderInterface $provider) {
$this->_provider = $provider;
}
/**
* Set compile directory
@ -482,22 +482,22 @@ class Aspect {
return $this->_options;
}
/**
* @param bool|string $scm
* @return Aspect\ProviderInterface
* @throws InvalidArgumentException
*/
public function getProvider($scm = false) {
if($scm) {
if(isset($this->_provider[$scm])) {
return $this->_provider[$scm];
} else {
throw new InvalidArgumentException("Provider for '$scm' not found");
}
} else {
return $this->_provider;
}
}
/**
* @param bool|string $scm
* @return Aspect\ProviderInterface
* @throws InvalidArgumentException
*/
public function getProvider($scm = false) {
if($scm) {
if(isset($this->_provider[$scm])) {
return $this->_provider[$scm];
} else {
throw new InvalidArgumentException("Provider for '$scm' not found");
}
} else {
return $this->_provider;
}
}
/**
* Return empty template
@ -538,8 +538,8 @@ class Aspect {
*/
public function getTemplate($template) {
if(isset($this->_storage[ $template ])) {
/** @var Aspect\Template $tpl */
$tpl = $this->_storage[ $template ];
/** @var Aspect\Template $tpl */
$tpl = $this->_storage[ $template ];
if(($this->_options & self::CHECK_MTIME) && !$tpl->isValid()) {
return $this->_storage[ $template ] = $this->compile($template);
} else {
@ -589,29 +589,29 @@ class Aspect {
return sprintf("%s.%u.%d.php", basename($tpl), crc32($hash), strlen($hash));
}
/**
* Compile and save template
*
* @param string $tpl
* @param bool $store store template on disk
* @throws RuntimeException
* @return \Aspect\Template
*/
/**
* Compile and save template
*
* @param string $tpl
* @param bool $store store template on disk
* @throws RuntimeException
* @return \Aspect\Template
*/
public function compile($tpl, $store = true) {
$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'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't to move $tpl_tmp to $tpl");
}
}
if($store) {
$tpl_tmp = tempnam($this->_compile_dir, basename($tpl));
$tpl_fp = fopen($tpl_tmp, "w");
if(!$tpl_fp) {
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't to move $tpl_tmp to $tpl");
}
}
return $template;
}

View File

@ -18,8 +18,8 @@ class Compiler {
* @return string
*/
public static function tagInclude(Tokenizer $tokens, Template $tpl) {
$cname = $tpl->parseFirstArg($tokens, $name);
$p = $tpl->parseParams($tokens);
$cname = $tpl->parseFirstArg($tokens, $name);
$p = $tpl->parseParams($tokens);
if($p) { // if we have additionally variables
if($name && ($tpl->getStorage()->getOptions() & \Aspect::FORCE_INCLUDE)) { // if FORCE_INCLUDE enabled and template name known
$inc = $tpl->getStorage()->compile($name, false);
@ -34,10 +34,10 @@ class Compiler {
$tpl->addDepend($inc);
return '$_tpl = (array)$tpl; ?>'.$inc->_body.'<?php $tpl->exchangeArray($_tpl); unset($_tpl);';
} else {
return '$tpl->getStorage()->getTemplate('.$cname.')->display((array)$tpl);';
return '$tpl->getStorage()->getTemplate('.$cname.')->display((array)$tpl);';
}
}
}
}
/**
@ -50,24 +50,24 @@ class Compiler {
*/
public static function ifOpen(Tokenizer $tokens, Scope $scope) {
$scope["else"] = false;
return 'if('.$scope->tpl->parseExp($tokens, true).') {';
}
return 'if('.$scope->tpl->parseExp($tokens, true).') {';
}
/**
* Tag {elseif ...}
*
* @static
* @param Tokenizer $tokens
* @param Scope $scope
* @throws ImproperUseException
* @return string
*/
/**
* Tag {elseif ...}
*
* @static
* @param Tokenizer $tokens
* @param Scope $scope
* @throws ImproperUseException
* @return string
*/
public static function tagElseIf(Tokenizer $tokens, Scope $scope) {
if($scope["else"]) {
throw new ImproperUseException('Incorrect use of the tag {elseif}');
}
return '} elseif('.$scope->tpl->parseExp($tokens, true).') {';
}
return '} elseif('.$scope->tpl->parseExp($tokens, true).') {';
}
/**
* Tag {else}
@ -80,8 +80,8 @@ class Compiler {
*/
public static function tagElse(Tokenizer $tokens, Scope $scope) {
$scope["else"] = true;
return '} else {';
}
return '} else {';
}
/**
* Open tag {foreach ...}
@ -322,11 +322,11 @@ class Compiler {
*/
public static function tagContinue($tokens, Scope $scope) {
if(empty($scope["no-continue"])) {
return 'continue;';
return 'continue;';
} else {
throw new ImproperUseException("Improper usage of the tag {continue}");
}
}
}
/**
* Tag {default}
@ -343,8 +343,8 @@ class Compiler {
$code = $scope["switch"]."\n".$code;
$scope["switch"] = "";
}
return $code;
}
return $code;
}
/**
* Tag {break}
@ -361,28 +361,28 @@ class Compiler {
} else {
throw new ImproperUseException("Improper usage of the tag {break}");
}
}
}
/**
* Dispatch {extends} tag
* @param Tokenizer $tokens
* @param Template $tpl
* @throws ImproperUseException
* @return string
*/
public static function tagExtends(Tokenizer $tokens, Template $tpl) {
/**
* Dispatch {extends} tag
* @param Tokenizer $tokens
* @param Template $tpl
* @throws ImproperUseException
* @return string
*/
public static function tagExtends(Tokenizer $tokens, Template $tpl) {
if(!empty($tpl->_extends)) {
throw new ImproperUseException("Only one {extends} allowed");
}
$tpl_name = $tpl->parseFirstArg($tokens, $name);
$tpl->addPostCompile(__CLASS__."::extendBody");
$tpl->addPostCompile(__CLASS__."::extendBody");
if($name) { // static extends
//$tpl->_static = true;
$tpl->_extends = $tpl->getStorage()->getRawTemplate()->load($name, false);
$tpl->addDepend($tpl->_extends); // for valid compile-time need take template from storage
return "";
$tpl->_extends = $tpl->getStorage()->getRawTemplate()->load($name, false);
$tpl->addDepend($tpl->_extends); // for valid compile-time need take template from storage
return "";
} else { // dynamic extends
$tpl->_extends = $tpl_name;
$tpl->_extends = $tpl_name;
//$tpl->_static = false;
return '$parent = $tpl->getStorage()->getTemplate('.$tpl_name.');';
}
@ -394,8 +394,8 @@ class Compiler {
* @param Template $tpl
*/
public static function extendBody(&$body, $tpl) {
if(isset($tpl->_extends)) { // is child
if(is_object($tpl->_extends)) { // static extends
if(isset($tpl->_extends)) { // is child
if(is_object($tpl->_extends)) { // static extends
/* @var Template $t */
$t = $tpl->_extends;
if(empty($tpl->_dynamic)) {
@ -418,10 +418,10 @@ class Compiler {
$tpl->addDepend($t);
$body = '<?php ob_start(); ?>'.$body.'<?php ob_end_clean(); ?>'.$t->_body;
}
} else { // dynamic extends
$body .= '<?php $parent->blocks = &$tpl->blocks; $parent->display((array)$tpl); unset($tpl->blocks, $parent->blocks); ?>';
}
}
} else { // dynamic extends
$body .= '<?php $parent->blocks = &$tpl->blocks; $parent->display((array)$tpl); unset($tpl->blocks, $parent->blocks); ?>';
}
}
}
/**
@ -433,7 +433,7 @@ class Compiler {
if(!$scalar) {
$tpl->_static = false;
}
}
}
/**
* Tag {block ...}
@ -454,9 +454,9 @@ class Compiler {
/*if($scope->level) {
$scope->tpl->_static = false;
}*/
if(isset($scope->tpl->_extends)) { // is child
return 'if(empty($tpl->blocks['.$scope["cname"].'])) { $tpl->blocks['.$scope["cname"].'] = function($tpl) {';
} else { // is parent
if(isset($scope->tpl->_extends)) { // is child
return 'if(empty($tpl->blocks['.$scope["cname"].'])) { $tpl->blocks['.$scope["cname"].'] = function($tpl) {';
} else { // is parent
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
$scope["body"] = $scope->tpl->_body;
@ -464,9 +464,9 @@ class Compiler {
} // else just put block content as is
return '';
} else {
return '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 {';
}
}
}
}
/**
@ -477,24 +477,24 @@ class Compiler {
*/
public static function tagBlockClose($tokens, Scope $scope) {
if(isset($scope->tpl->_extends)) { // is child
if(isset($scope->tpl->_extends)) { // is child
if(!isset($scope->tpl->_blocks[ $scope["name"] ])) {
$scope->tpl->_blocks[ $scope["name"] ] = $scope->getContent();
} // dynamic extends
return '}; }';
} else { // is parent
} else { // is parent
if(isset($scope->tpl->_blocks)) {
if(isset($scope["body"])) {
$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"] ].'}';
'<?php if(isset($tpl->blocks['.$scope["cname"].'])) { echo $tpl->blocks['.$scope["cname"].']->__invoke($tpl); } else {?>'.
$scope->tpl->_blocks[ $scope["name"] ].'}';
return "";
}
return "";
} else {
return '}';
return '}';
}
}
}
}
public static function tagParent($tokens, Scope $scope) {
@ -510,8 +510,8 @@ class Compiler {
* @return string
*/
public static function stdClose() {
return '}';
}
return '}';
}
/**
* Standard function parser
@ -625,15 +625,20 @@ class Compiler {
}
}
public static function filterOpen(Tokenizer $tokens, Scope $scope) {
$scope["filter"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()");
return "ob_start();";
}
public static function filterOpen(Tokenizer $tokens, Scope $scope) {
$scope["filter"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()");
return "ob_start();";
}
public static function filterClose($tokens, Scope $scope) {
return "echo ".$scope["filter"].";";
}
public static function filterClose($tokens, Scope $scope) {
return "echo ".$scope["filter"].";";
}
/**
* @param Tokenizer $tokens
* @param Scope $scope
* @return string
*/
public static function captureOpen(Tokenizer $tokens, Scope $scope) {
if($tokens->is("|")) {
$scope["value"] = $scope->tpl->parseModifier($tokens, "ob_get_clean()");
@ -650,6 +655,14 @@ class Compiler {
return $scope["var"]." = ".$scope["value"].";";
}
/**
* Tag {cycle}
*
* @param Tokenizer $tokens
* @param Template $tpl
* @return string
* @throws ImproperUseException
*/
public static function tagCycle(Tokenizer $tokens, Template $tpl) {
$exp = $tpl->parseExp($tokens, true);
if($tokens->valid()) {
@ -679,6 +692,9 @@ class Compiler {
}
if($tokens->is(T_AS)) {
$alias = $tokens->next()->get(Tokenizer::MACRO_STRING);
if($alias === "macro") {
$alias = "";
}
$tokens->next();
} else {
$alias = "";
@ -697,10 +713,11 @@ class Compiler {
$tpl->addDepend($donor);
}
return '';
}
/**
* Declare or invoke macros
* Define macro
*
* @param Tokenizer $tokens
* @param Scope $scope

View File

@ -90,13 +90,13 @@ class FSProvider implements ProviderInterface {
}
}
/**
* @param string $tpl
* @return bool
*/
public function isTemplateExists($tpl) {
/**
* @param string $tpl
* @return bool
*/
public function isTemplateExists($tpl) {
return file_exists($this->_path."/".$tpl);
}
}
public function getLastModifiedBatch($tpls) {
$tpls = array_flip($tpls);

View File

@ -25,12 +25,12 @@ class Modifier {
* @return string
*/
public static function dateFormat($date, $format = "%b %e, %Y") {
if(is_string($date) && !is_numeric($date)) {
$date = strtotime($date);
if(!$date) $date = time();
}
return strftime($format, $date);
}
if(is_string($date) && !is_numeric($date)) {
$date = strtotime($date);
if(!$date) $date = time();
}
return strftime($format, $date);
}
/**
* @param string $date
@ -38,12 +38,12 @@ class Modifier {
* @return string
*/
public static function date($date, $format = "Y m d") {
if(is_string($date) && !is_numeric($date)) {
$date = strtotime($date);
if(!$date) $date = time();
}
return date($format, $date);
}
if(is_string($date) && !is_numeric($date)) {
$date = strtotime($date);
if(!$date) $date = time();
}
return date($format, $date);
}
/**
* Escape string
@ -53,14 +53,14 @@ class Modifier {
* @return string
*/
public static function escape($text, $type = 'html') {
switch($type) {
case "url":
switch($type) {
case "url":
return urlencode($text);
case "html";
return htmlspecialchars($text, ENT_COMPAT, 'UTF-8');
default:
return $text;
}
case "html";
return htmlspecialchars($text, ENT_COMPAT, 'UTF-8');
default:
return $text;
}
}
/**
@ -71,15 +71,15 @@ class Modifier {
* @return string
*/
public static function unescape($text, $type = 'html') {
switch($type) {
case "url":
return urldecode($text);
case "html";
return htmlspecialchars_decode($text);
default:
return $text;
}
}
switch($type) {
case "url":
return urldecode($text);
case "html";
return htmlspecialchars_decode($text);
default:
return $text;
}
}
/**
* @param string $string

View File

@ -13,10 +13,10 @@ class Render extends \ArrayObject {
"time" => 0,
"depends" => array()
);
/**
* @var \Closure
*/
protected $_code;
/**
* @var \Closure
*/
protected $_code;
/**
* Template name
* @var string
@ -55,8 +55,8 @@ class Render extends \ArrayObject {
$this->_scm = $props["scm"];
$this->_time = $props["time"];
$this->_depends = $props["depends"];
$this->_code = $code;
}
$this->_code = $code;
}
/**
* Get template storage
@ -86,8 +86,8 @@ class Render extends \ArrayObject {
* @return string
*/
public function __toString() {
return $this->_name;
}
return $this->_name;
}
/**
* Get template name
@ -97,9 +97,9 @@ class Render extends \ArrayObject {
return $this->_name;
}
public function getTime() {
return $this->_time;
}
public function getTime() {
return $this->_time;
}
/**
@ -107,15 +107,15 @@ class Render extends \ArrayObject {
* @return bool
*/
public function isValid() {
$provider = $this->_aspect->getProvider(strstr($this->_name, ":"), true);
if($provider->getLastModified($this->_name) >= $this->_time) {
return false;
}
foreach($this->_depends as $tpl => $time) {
if($this->_aspect->getTemplate($tpl)->getTime() !== $time) {
return false;
}
}
$provider = $this->_aspect->getProvider(strstr($this->_name, ":"), true);
if($provider->getLastModified($this->_name) >= $this->_time) {
return false;
}
foreach($this->_depends as $tpl => $time) {
if($this->_aspect->getTemplate($tpl)->getTime() !== $time) {
return false;
}
}
return true;
}
@ -125,10 +125,10 @@ class Render extends \ArrayObject {
* @return Render
*/
public function display(array $values) {
$this->exchangeArray($values);
$this->_code->__invoke($this);
$this->exchangeArray($values);
$this->_code->__invoke($this);
return $this;
}
}
/**
* Execute template and return result as string
@ -154,6 +154,6 @@ class Render extends \ArrayObject {
* @throws \BadMethodCallException
*/
public function __call($method, $args) {
throw new \BadMethodCallException("Unknown method ".$method);
}
throw new \BadMethodCallException("Unknown method ".$method);
}
}

View File

@ -7,17 +7,17 @@ namespace Aspect;
class Scope extends \ArrayObject {
public $id = 0;
public $line = 0;
public $name;
public $line = 0;
public $name;
public $level = 0;
/**
* @var Template
*/
public $tpl;
/**
* @var Template
*/
public $tpl;
public $closed = false;
public $is_next_close = false;
public $is_compiler = true;
private $_action;
public $is_compiler = true;
private $_action;
private static $count = 0;
/**
@ -29,12 +29,12 @@ class Scope extends \ArrayObject {
*/
public function __construct($name, $tpl, $line, $action, $level) {
$this->id = ++self::$count;
$this->line = $line;
$this->name = $name;
$this->tpl = $tpl;
$this->_action = $action;
$this->level = $level;
}
$this->line = $line;
$this->name = $name;
$this->tpl = $tpl;
$this->_action = $action;
$this->level = $level;
}
/**
*
@ -63,7 +63,7 @@ class Scope extends \ArrayObject {
* @return bool
*/
public function hasTag($tag, $level) {
if(isset($this->_action["tags"][$tag])) {
if(isset($this->_action["tags"][$tag])) {
if($level) {
return isset($this->_action["float_tags"][$tag]);
} else {
@ -71,7 +71,7 @@ class Scope extends \ArrayObject {
}
}
return false;
}
}
/**
* Call tag callback
@ -81,8 +81,8 @@ class Scope extends \ArrayObject {
* @return string
*/
public function tag($tag, $tokenizer) {
return call_user_func($this->_action["tags"][$tag], $tokenizer, $this);
}
return call_user_func($this->_action["tags"][$tag], $tokenizer, $this);
}
/**
* Close callback

View File

@ -220,13 +220,13 @@ class Template extends Render {
return "<?php \n".
"/** Aspect template '".$this->_name."' compiled at ".date('Y-m-d H:i:s')." */\n".
"return new Aspect\\Render(\$aspect, ".$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";
//"options" => $this->_options,
"provider" => $this->_scm,
"name" => $this->_name,
"base_name" => $this->_base_name,
"time" => $this->_time,
"depends" => $this->_depends
), true).");\n";
}
/**
@ -256,13 +256,13 @@ class Template extends Render {
}
/**
* Add depends from template
* @param Render $tpl
*/
public function addDepend(Render $tpl) {
$this->_depends[$tpl->getScm()][$tpl->getName()] = $tpl->getTime();
}
/**
* Add depends from template
* @param Render $tpl
*/
public function addDepend(Render $tpl) {
$this->_depends[$tpl->getScm()][$tpl->getName()] = $tpl->getTime();
}
/**
* Execute template and return result as string
@ -334,13 +334,13 @@ class Template extends Render {
if($tokens->key()) { // if tokenizer still have tokens
throw new UnexpectedException($tokens);
}
if(!$code) {
return "";
} else {
if(!$code) {
return "";
} else {
return "<?php\n/* {$this->_name}:{$this->_line}: {$src} */\n {$code} ?>";
}
} catch (ImproperUseException $e) {
throw new CompileException($e->getMessage()." in {$this} line {$this->_line}", 0, E_ERROR, $this->_name, $this->_line, $e);
throw new CompileException($e->getMessage()." in {$this} line {$this->_line}", 0, E_ERROR, $this->_name, $this->_line, $e);
} catch (\LogicException $e) {
throw new SecurityException($e->getMessage()." in {$this} line {$this->_line}, near '{".$tokens->getSnippetAsString(0,0)."' <- there", 0, E_ERROR, $this->_name, $this->_line, $e);
} catch (\Exception $e) {
@ -645,13 +645,13 @@ class Template extends Render {
return 'isset('.$_var.')';
}
} else {
$expr1 = $this->parseExp($tokens, true);
if(!$tokens->is(":")) {
throw new UnexpectedException($tokens, null, "ternary operator");
}
$expr2 = $this->parseExp($tokens, true);
$expr1 = $this->parseExp($tokens, true);
if(!$tokens->is(":")) {
throw new UnexpectedException($tokens, null, "ternary operator");
}
$expr2 = $this->parseExp($tokens, true);
if($empty) {
return '(empty('.$_var.') ? '.$expr2.' : '.$expr1.')';
return '(empty('.$_var.') ? '.$expr2.' : '.$expr1.')';
} else {
return '(isset('.$_var.') ? '.$expr1.' : '.$expr2.')';
}