Add comments and license block

This commit is contained in:
bzick 2013-04-28 11:33:36 +04:00
parent 5d4d218942
commit 614428e88d
11 changed files with 136 additions and 39 deletions

View File

@ -4,7 +4,7 @@
"description": "Cytro - fast template engine for PHP", "description": "Cytro - fast template engine for PHP",
"homepage": "http://bzick.github.io/cytro/", "homepage": "http://bzick.github.io/cytro/",
"keywords": ["cytro", "template", "templating"], "keywords": ["cytro", "template", "templating"],
"license": "MIT", "license": "BSD-3",
"authors": [ "authors": [
{ {
"name": "Ivan Shalganov", "name": "Ivan Shalganov",

View File

@ -1,4 +1,12 @@
<?php <?php
/*
* This file is part of Cytro.
*
* (c) 2013 Ivan Shalganov
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Cytro\Template, use Cytro\Template,
Cytro\ProviderInterface; Cytro\ProviderInterface;

View File

@ -1,4 +1,12 @@
<?php <?php
/*
* This file is part of Cytro.
*
* (c) 2013 Ivan Shalganov
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Cytro; namespace Cytro;
use Cytro\Tokenizer; use Cytro\Tokenizer;
use Cytro\Template; use Cytro\Template;
@ -6,6 +14,7 @@ use Cytro\Scope;
/** /**
* Compilers collection * Compilers collection
* @package Cytro
*/ */
class Compiler { class Compiler {
/** /**
@ -18,7 +27,7 @@ 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); $cname = $tpl->parsePlainArg($tokens, $name);
$p = $tpl->parseParams($tokens); $p = $tpl->parseParams($tokens);
if($p) { // if we have additionally variables if($p) { // if we have additionally variables
if($name && ($tpl->getStorage()->getOptions() & \Cytro::FORCE_INCLUDE)) { // if FORCE_INCLUDE enabled and template name known 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)) { if(!empty($tpl->_extends)) {
throw new ImproperUseException("Only one {extends} allowed"); throw new ImproperUseException("Only one {extends} allowed");
} }
$tpl_name = $tpl->parseFirstArg($tokens, $name); $tpl_name = $tpl->parsePlainArg($tokens, $name);
if(empty($tpl->_extended)) { if(empty($tpl->_extended)) {
$tpl->addPostCompile(__CLASS__."::extendBody"); $tpl->addPostCompile(__CLASS__."::extendBody");
} }
@ -423,13 +432,14 @@ class Compiler {
} }
/** /**
* Tag {use ...}
* @param Tokenizer $tokens * @param Tokenizer $tokens
* @param Template $tpl * @param Template $tpl
* @throws ImproperUseException * @throws ImproperUseException
* @return string * @return string
*/ */
public static function tagUse(Tokenizer $tokens, Template $tpl) { public static function tagUse(Tokenizer $tokens, Template $tpl) {
$tpl->parseFirstArg($tokens, $name); $tpl->parsePlainArg($tokens, $name);
if($name) { if($name) {
$donor = $tpl->getStorage()->getRawTemplate()->load($name, false); $donor = $tpl->getStorage()->getRawTemplate()->load($name, false);
$donor->_extended = true; $donor->_extended = true;
@ -457,7 +467,7 @@ class Compiler {
* @throws ImproperUseException * @throws ImproperUseException
*/ */
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->parsePlainArg($tokens, $name);
$scope["name"] = $name; $scope["name"] = $name;
$scope["cname"] = $p; $scope["cname"] = $p;
} }
@ -750,7 +760,7 @@ class Compiler {
$tokens->next(); $tokens->next();
} }
$tpl->parseFirstArg($tokens, $name); $tpl->parsePlainArg($tokens, $name);
if(!$name) { if(!$name) {
throw new ImproperUseException("Invalid usage tag {import}"); throw new ImproperUseException("Invalid usage tag {import}");
} }

View File

@ -1,4 +1,12 @@
<?php <?php
/*
* This file is part of Cytro.
*
* (c) 2013 Ivan Shalganov
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Cytro; namespace Cytro;
use Cytro\ProviderInterface; use Cytro\ProviderInterface;
@ -46,6 +54,10 @@ class FSProvider implements ProviderInterface {
} }
} }
/**
* @param string $template_dir directory of templates
* @throws \LogicException if directory doesn't exists
*/
public function __construct($template_dir) { public function __construct($template_dir) {
if($_dir = realpath($template_dir)) { if($_dir = realpath($template_dir)) {
$this->_path = $_dir; $this->_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 * @return bool
*/ */
public function verify(array $templates) { public function verify(array $templates) {

View File

@ -12,8 +12,6 @@ namespace Cytro;
/** /**
* Collection of modifiers * Collection of modifiers
* *
* @package aspect
* @author Ivan Shalganov <owner@bzick.net>
*/ */
class Modifier { class Modifier {
@ -84,9 +82,9 @@ class Modifier {
/** /**
* Crop string by length * Crop string by length
* UTF8 support * UTF8 support
* @param string $string * @param string $string text witch will be truncate
* @param int $length * @param int $length maximum symbols of result string
* @param string $etc * @param string $etc place holder truncated symbols
* @param bool $by_words * @param bool $by_words
* @param bool $middle * @param bool $middle
* @return string * @return string
@ -116,7 +114,7 @@ class Modifier {
/** /**
* Strip spaces symbols on edge of string end multiple spaces in string * Strip spaces symbols on edge of string end multiple spaces in string
* @static *
* @param string $str * @param string $str
* @param bool $to_line strip line ends * @param bool $to_line strip line ends
* @return string * @return string

View File

@ -1,4 +1,12 @@
<?php <?php
/*
* This file is part of Cytro.
*
* (c) 2013 Ivan Shalganov
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Cytro; namespace Cytro;
interface ProviderInterface { interface ProviderInterface {

View File

@ -1,4 +1,12 @@
<?php <?php
/*
* This file is part of Cytro.
*
* (c) 2013 Ivan Shalganov
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Cytro; namespace Cytro;
use Cytro; use Cytro;
@ -22,20 +30,34 @@ class Render extends \ArrayObject {
* @var string * @var string
*/ */
protected $_name = 'runtime'; protected $_name = 'runtime';
/**
* Provider's schema
* @var bool
*/
protected $_scm = false; protected $_scm = false;
/**
* Basic template name
* @var string
*/
protected $_base_name = 'runtime'; protected $_base_name = 'runtime';
/** /**
* @var Cytro * @var Cytro
*/ */
protected $_aspect; protected $_cytro;
/** /**
* Timestamp of compilation * Timestamp of compilation
* @var float * @var float
*/ */
protected $_time = 0.0; protected $_time = 0.0;
/**
* @var array depends list
*/
protected $_depends = array(); protected $_depends = array();
/**
* @var int tempalte options (see Cytro options)
*/
protected $_options = 0; protected $_options = 0;
/** /**
@ -45,15 +67,15 @@ class Render extends \ArrayObject {
protected $_provider; protected $_provider;
/** /**
* @param Cytro $aspect * @param Cytro $cytro
* @param callable $code template body * @param callable $code template body
* @param array $props * @param array $props
*/ */
public function __construct(Cytro $aspect, \Closure $code, $props = array()) { public function __construct(Cytro $cytro, \Closure $code, $props = array()) {
$this->_aspect = $aspect; $this->_cytro = $cytro;
$props += self::$_props; $props += self::$_props;
$this->_name = $props["name"]; $this->_name = $props["name"];
$this->_provider = $this->_aspect->getProvider($props["scm"]); $this->_provider = $this->_cytro->getProvider($props["scm"]);
$this->_scm = $props["scm"]; $this->_scm = $props["scm"];
$this->_time = $props["time"]; $this->_time = $props["time"];
$this->_depends = $props["depends"]; $this->_depends = $props["depends"];
@ -65,7 +87,7 @@ class Render extends \ArrayObject {
* @return Cytro * @return Cytro
*/ */
public function getStorage() { public function getStorage() {
return $this->_aspect; return $this->_cytro;
} }
public function getDepends() { public function getDepends() {
@ -113,12 +135,12 @@ class Render extends \ArrayObject {
* @return bool * @return bool
*/ */
public function isValid() { 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) { if($provider->getLastModified($this->_name) >= $this->_time) {
return false; return false;
} }
foreach($this->_depends as $tpl => $time) { foreach($this->_depends as $tpl => $time) {
if($this->_aspect->getTemplate($tpl)->getTime() !== $time) { if($this->_cytro->getTemplate($tpl)->getTime() !== $time) {
return false; return false;
} }
} }

View File

@ -1,4 +1,12 @@
<?php <?php
/*
* This file is part of Cytro.
*
* (c) 2013 Ivan Shalganov
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Cytro; namespace Cytro;
/** /**

View File

@ -68,6 +68,7 @@ class Template extends Render {
* Just factory * Just factory
* *
* @param \Cytro $aspect * @param \Cytro $aspect
* @param $options
* @return Template * @return Template
*/ */
public static function factory(Cytro $aspect, $options) { public static function factory(Cytro $aspect, $options) {
@ -75,11 +76,12 @@ class Template extends Render {
} }
/** /**
* @param Cytro $aspect Template storage * @param Cytro $cytro Template storage
* @param $options
*/ */
public function __construct(Cytro $aspect, $options) { public function __construct(Cytro $cytro, $options) {
$this->_aspect = $aspect; $this->_cytro = $cytro;
$this->_options = $this->_aspect->getOptions(); $this->_options = $this->_cytro->getOptions();
} }
/** /**
@ -96,7 +98,7 @@ class Template extends Render {
} else { } else {
$this->_base_name = $name; $this->_base_name = $name;
} }
$this->_provider = $this->_aspect->getProvider($provider); $this->_provider = $this->_cytro->getProvider($provider);
$this->_src = $this->_provider->getSource($name, $this->_time); $this->_src = $this->_provider->getSource($name, $this->_time);
if($compile) { if($compile) {
$this->compile(); $this->compile();
@ -143,12 +145,12 @@ class Template extends Render {
$pos = $end + 1; // trying finding tags after the comment block $pos = $end + 1; // trying finding tags after the comment block
continue 2; 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 if(!$end) { // if unexpected end of template
throw new CompileException("Unclosed tag in line {$this->_line}", 0, 1, $this->_name, $this->_line); 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 '{' $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 aspect tag '{...}' $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) $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 $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 echo "<?"; ?>'.PHP_EOL, $text); $this->_body .= str_replace("<?", '<?php echo "<?"; ?>'.PHP_EOL, $text);
} }
/**
* Append PHP_EOL after each '?>'
* @param int $code
* @return string
*/
private function _escapeCode($code) { private function _escapeCode($code) {
$c = ""; $c = "";
foreach(token_get_all($code) as $token) { foreach(token_get_all($code) as $token) {
@ -414,7 +421,7 @@ class Template extends Render {
return $this->parseMacro($tokens, $name); 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"]) { switch($act["type"]) {
case Cytro::BLOCK_COMPILER: case Cytro::BLOCK_COMPILER:
$scope = new Scope($action, $this, $this->_line, $act, count($this->_stack), $this->_body); $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); 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)."')"); throw new TokenizeException("Unexpected tag '$action' (this tag can be used with '".implode("', '", $tags)."')");
} else { } else {
throw new TokenizeException("Unexpected tag $action"); throw new TokenizeException("Unexpected tag $action");
@ -496,7 +503,7 @@ class Template extends Render {
if($tokens->isSpecialVal()) { if($tokens->isSpecialVal()) {
$_exp .= $tokens->getAndNext(); $_exp .= $tokens->getAndNext();
} elseif($tokens->isNext("(")) { } elseif($tokens->isNext("(")) {
$func = $this->_aspect->getModifier($tokens->current()); $func = $this->_cytro->getModifier($tokens->current());
$tokens->next(); $tokens->next();
$_exp .= $func.$this->parseArgs($tokens); $_exp .= $func.$this->parseArgs($tokens);
} else { } else {
@ -828,7 +835,7 @@ class Template extends Render {
*/ */
public function parseModifier(Tokenizer $tokens, $value) { public function parseModifier(Tokenizer $tokens, $value) {
while($tokens->is("|")) { while($tokens->is("|")) {
$mods = $this->_aspect->getModifier( $tokens->getNext(Tokenizer::MACRO_STRING) ); $mods = $this->_cytro->getModifier( $tokens->getNext(Tokenizer::MACRO_STRING) );
$tokens->next(); $tokens->next();
$args = array(); $args = array();
@ -1008,7 +1015,7 @@ class Template extends Render {
* @param string $static * @param string $static
* @return mixed|string * @return mixed|string
*/ */
public function parseFirstArg(Tokenizer $tokens, &$static) { public function parsePlainArg(Tokenizer $tokens, &$static) {
if($tokens->is(T_CONSTANT_ENCAPSED_STRING)) { if($tokens->is(T_CONSTANT_ENCAPSED_STRING)) {
if($tokens->isNext('|')) { if($tokens->isNext('|')) {
return $this->parseExp($tokens, true); return $this->parseExp($tokens, true);

View File

@ -9,9 +9,16 @@
*/ */
namespace Cytro; namespace Cytro;
/**
* for <PHP 5.4 compatible
*/
defined('T_INSTEADOF') || define('T_INSTEADOF', 341); defined('T_INSTEADOF') || define('T_INSTEADOF', 341);
defined('T_TRAIT') || define('T_TRAIT', 355); defined('T_TRAIT') || define('T_TRAIT', 355);
defined('T_TRAIT_C') || define('T_TRAIT_C', 365); defined('T_TRAIT_C') || define('T_TRAIT_C', 365);
/**
* for PHP <5.5
*/
defined('T_YIELD') || define('T_YIELD', 370);
/** /**
* Each token have structure * Each token have structure

View File

@ -11,11 +11,11 @@ class ExtendsTemplateTest extends TestCase {
"name" => "level.0.tpl", "name" => "level.0.tpl",
"level" => 0, "level" => 0,
"blocks" => array( "blocks" => array(
"b1" => "", "b1" => "default 5",
"b2" => "empty 0" "b2" => "empty 0"
), ),
"result" => array( "result" => array(
"b1" => "", "b1" => "default 5",
"b2" => "empty 0" "b2" => "empty 0"
), ),
), ),
@ -79,10 +79,27 @@ class ExtendsTemplateTest extends TestCase {
* @group static-extend * @group static-extend
*/ */
public function testTemplateExtends() { 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"]); $this->tpl($name, $tpl["src"]);
//var_dump($src, "----\n\n----", $dst);ob_flush();fgetc(STDIN); //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);
} }
} }