diff --git a/composer.json b/composer.json index bab2430..7deb027 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "description": "Cytro - fast template engine for PHP", "homepage": "http://bzick.github.io/cytro/", "keywords": ["cytro", "template", "templating"], - "license": "MIT", + "license": "BSD-3", "authors": [ { "name": "Ivan Shalganov", diff --git a/src/Cytro.php b/src/Cytro.php index 7960c93..d2a2546 100644 --- a/src/Cytro.php +++ b/src/Cytro.php @@ -1,4 +1,12 @@ parseFirstArg($tokens, $name); + $cname = $tpl->parsePlainArg($tokens, $name); $p = $tpl->parseParams($tokens); if($p) { // if we have additionally variables if($name && ($tpl->getStorage()->getOptions() & \Cytro::FORCE_INCLUDE)) { // if FORCE_INCLUDE enabled and template name known @@ -371,7 +380,7 @@ class Compiler { if(!empty($tpl->_extends)) { throw new ImproperUseException("Only one {extends} allowed"); } - $tpl_name = $tpl->parseFirstArg($tokens, $name); + $tpl_name = $tpl->parsePlainArg($tokens, $name); if(empty($tpl->_extended)) { $tpl->addPostCompile(__CLASS__."::extendBody"); } @@ -423,13 +432,14 @@ class Compiler { } /** + * Tag {use ...} * @param Tokenizer $tokens * @param Template $tpl * @throws ImproperUseException * @return string */ public static function tagUse(Tokenizer $tokens, Template $tpl) { - $tpl->parseFirstArg($tokens, $name); + $tpl->parsePlainArg($tokens, $name); if($name) { $donor = $tpl->getStorage()->getRawTemplate()->load($name, false); $donor->_extended = true; @@ -457,7 +467,7 @@ class Compiler { * @throws ImproperUseException */ public static function tagBlockOpen(Tokenizer $tokens, Scope $scope) { - $p = $scope->tpl->parseFirstArg($tokens, $name); + $p = $scope->tpl->parsePlainArg($tokens, $name); $scope["name"] = $name; $scope["cname"] = $p; } @@ -750,7 +760,7 @@ class Compiler { $tokens->next(); } - $tpl->parseFirstArg($tokens, $name); + $tpl->parsePlainArg($tokens, $name); if(!$name) { throw new ImproperUseException("Invalid usage tag {import}"); } diff --git a/src/Cytro/FSProvider.php b/src/Cytro/FSProvider.php index 27292fb..213e9e8 100644 --- a/src/Cytro/FSProvider.php +++ b/src/Cytro/FSProvider.php @@ -1,4 +1,12 @@ _path = $_dir; @@ -107,9 +119,9 @@ class FSProvider implements ProviderInterface { } /** - * Verify templates by change time + * Verify templates (check change time) * - * @param array $templates [template_name => modified, ...] By conversation you may trust the template's name + * @param array $templates [template_name => modified, ...] By conversation, you may trust the template's name * @return bool */ public function verify(array $templates) { diff --git a/src/Cytro/Modifier.php b/src/Cytro/Modifier.php index dfdc9c4..7921446 100644 --- a/src/Cytro/Modifier.php +++ b/src/Cytro/Modifier.php @@ -12,8 +12,6 @@ namespace Cytro; /** * Collection of modifiers * - * @package aspect - * @author Ivan Shalganov */ class Modifier { @@ -84,9 +82,9 @@ class Modifier { /** * Crop string by length * UTF8 support - * @param string $string - * @param int $length - * @param string $etc + * @param string $string text witch will be truncate + * @param int $length maximum symbols of result string + * @param string $etc place holder truncated symbols * @param bool $by_words * @param bool $middle * @return string @@ -116,7 +114,7 @@ class Modifier { /** * Strip spaces symbols on edge of string end multiple spaces in string - * @static + * * @param string $str * @param bool $to_line strip line ends * @return string diff --git a/src/Cytro/ProviderInterface.php b/src/Cytro/ProviderInterface.php index 4a67462..08b3747 100644 --- a/src/Cytro/ProviderInterface.php +++ b/src/Cytro/ProviderInterface.php @@ -1,4 +1,12 @@ _aspect = $aspect; + public function __construct(Cytro $cytro, \Closure $code, $props = array()) { + $this->_cytro = $cytro; $props += self::$_props; $this->_name = $props["name"]; - $this->_provider = $this->_aspect->getProvider($props["scm"]); + $this->_provider = $this->_cytro->getProvider($props["scm"]); $this->_scm = $props["scm"]; $this->_time = $props["time"]; $this->_depends = $props["depends"]; @@ -65,7 +87,7 @@ class Render extends \ArrayObject { * @return Cytro */ public function getStorage() { - return $this->_aspect; + return $this->_cytro; } public function getDepends() { @@ -113,12 +135,12 @@ class Render extends \ArrayObject { * @return bool */ public function isValid() { - $provider = $this->_aspect->getProvider(strstr($this->_name, ":"), true); + $provider = $this->_cytro->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) { + if($this->_cytro->getTemplate($tpl)->getTime() !== $time) { return false; } } diff --git a/src/Cytro/Scope.php b/src/Cytro/Scope.php index b7e65fa..6bd1905 100644 --- a/src/Cytro/Scope.php +++ b/src/Cytro/Scope.php @@ -1,4 +1,12 @@ _aspect = $aspect; - $this->_options = $this->_aspect->getOptions(); + public function __construct(Cytro $cytro, $options) { + $this->_cytro = $cytro; + $this->_options = $this->_cytro->getOptions(); } /** @@ -96,7 +98,7 @@ class Template extends Render { } else { $this->_base_name = $name; } - $this->_provider = $this->_aspect->getProvider($provider); + $this->_provider = $this->_cytro->getProvider($provider); $this->_src = $this->_provider->getSource($name, $this->_time); if($compile) { $this->compile(); @@ -143,12 +145,12 @@ class Template extends Render { $pos = $end + 1; // trying finding tags after the comment block continue 2; } - $end = strpos($this->_src, '}', $start); // search close-char of the tag + $end = strpos($this->_src, '}', $start); // search close-symbol of the tag if(!$end) { // if unexpected end of template throw new CompileException("Unclosed tag in line {$this->_line}", 0, 1, $this->_name, $this->_line); } - $frag .= substr($this->_src, $this->_pos, $start - $this->_pos); // variable $frag contains chars after last '}' and next '{' - $tag = substr($this->_src, $start, $end - $start + 1); // variable $tag contains aspect tag '{...}' + $frag .= substr($this->_src, $this->_pos, $start - $this->_pos); // variable $frag contains chars after previous '}' and current '{' + $tag = substr($this->_src, $start, $end - $start + 1); // variable $tag contains cytro 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 @@ -215,6 +217,11 @@ class Template extends Render { $this->_body .= str_replace("'.PHP_EOL, $text); } + /** + * Append PHP_EOL after each '?>' + * @param int $code + * @return string + */ private function _escapeCode($code) { $c = ""; foreach(token_get_all($code) as $token) { @@ -414,7 +421,7 @@ class Template extends Render { return $this->parseMacro($tokens, $name); } - if($act = $this->_aspect->getFunction($action)) { // call some function + if($act = $this->_cytro->getFunction($action)) { // call some function switch($act["type"]) { case Cytro::BLOCK_COMPILER: $scope = new Scope($action, $this, $this->_line, $act, count($this->_stack), $this->_body); @@ -442,7 +449,7 @@ class Template extends Render { return $this->_stack[$i]->tag($action, $tokens); } } - if($tags = $this->_aspect->getTagOwners($action)) { // unknown template tag + if($tags = $this->_cytro->getTagOwners($action)) { // unknown template tag throw new TokenizeException("Unexpected tag '$action' (this tag can be used with '".implode("', '", $tags)."')"); } else { throw new TokenizeException("Unexpected tag $action"); @@ -496,7 +503,7 @@ class Template extends Render { if($tokens->isSpecialVal()) { $_exp .= $tokens->getAndNext(); } elseif($tokens->isNext("(")) { - $func = $this->_aspect->getModifier($tokens->current()); + $func = $this->_cytro->getModifier($tokens->current()); $tokens->next(); $_exp .= $func.$this->parseArgs($tokens); } else { @@ -828,7 +835,7 @@ class Template extends Render { */ public function parseModifier(Tokenizer $tokens, $value) { while($tokens->is("|")) { - $mods = $this->_aspect->getModifier( $tokens->getNext(Tokenizer::MACRO_STRING) ); + $mods = $this->_cytro->getModifier( $tokens->getNext(Tokenizer::MACRO_STRING) ); $tokens->next(); $args = array(); @@ -1008,7 +1015,7 @@ class Template extends Render { * @param string $static * @return mixed|string */ - public function parseFirstArg(Tokenizer $tokens, &$static) { + public function parsePlainArg(Tokenizer $tokens, &$static) { if($tokens->is(T_CONSTANT_ENCAPSED_STRING)) { if($tokens->isNext('|')) { return $this->parseExp($tokens, true); diff --git a/src/Cytro/Tokenizer.php b/src/Cytro/Tokenizer.php index f42d7c6..2a3fd90 100644 --- a/src/Cytro/Tokenizer.php +++ b/src/Cytro/Tokenizer.php @@ -9,9 +9,16 @@ */ namespace Cytro; +/** + * for "level.0.tpl", "level" => 0, "blocks" => array( - "b1" => "", + "b1" => "default 5", "b2" => "empty 0" ), "result" => array( - "b1" => "", + "b1" => "default 5", "b2" => "empty 0" ), ), @@ -79,10 +79,27 @@ class ExtendsTemplateTest extends TestCase { * @group static-extend */ public function testTemplateExtends() { - foreach(self::generate('{block "%s"}%s{/block}', '{extends "level.%d.tpl"}') as $name => $tpl) { + $vars = array( + "b1" => "b1", + "b2" => "b2", + "b3" => "b3", + "b4" => "b4", + "level" => "level", + "default" => 5 + ); + $tpls = self::generate('{block "%s"}%s{/block}', '{extends "level.%d.tpl"}'); + foreach($tpls as $name => $tpl) { $this->tpl($name, $tpl["src"]); //var_dump($src, "----\n\n----", $dst);ob_flush();fgetc(STDIN); - $this->assertSame($this->cytro->fetch($name, array()), $tpl["dst"]); + $this->assertSame($this->cytro->fetch($name, $vars), $tpl["dst"]); + } + $tpls = self::generate('{block "{$%s}"}%s{/block}', '{extends "level.%d.tpl"}'); + arsort($tpls); + foreach($tpls as $name => $tpl) { + $this->tpl("d.".$name, $tpl["src"]); + //var_dump($src, "----\n\n----", $dst);ob_flush();fgetc(STDIN); + $this->assertSame($this->cytro->fetch("d.".$name, $vars), $tpl["dst"]); + //var_dump($name);ob_flush();fgets(STDIN); } }