To PSR-x format

This commit is contained in:
bzick
2013-07-29 14:58:14 +04:00
parent 4edd0e1708
commit 3674de41cb
27 changed files with 2071 additions and 1674 deletions

View File

@ -15,55 +15,56 @@ use Fenom\Template,
*
* @author Ivan Shalganov <a.cobest@gmail.com>
*/
class Fenom {
class Fenom
{
const VERSION = '1.2';
/* Actions */
const INLINE_COMPILER = 1;
const BLOCK_COMPILER = 2;
const INLINE_FUNCTION = 3;
const BLOCK_FUNCTION = 4;
const MODIFIER = 5;
const INLINE_COMPILER = 1;
const BLOCK_COMPILER = 2;
const INLINE_FUNCTION = 3;
const BLOCK_FUNCTION = 4;
const MODIFIER = 5;
/* Options */
const DENY_METHODS = 0x10;
const DENY_NATIVE_FUNCS = 0x20;
const FORCE_INCLUDE = 0x40;
const AUTO_RELOAD = 0x80;
const FORCE_COMPILE = 0x100;
const AUTO_ESCAPE = 0x200;
const DISABLE_CACHE = 0x400;
const FORCE_VERIFY = 0x800; // reserved
const AUTO_TRIM = 0x1000; // reserved
const DENY_STATICS = 0x2000; // reserved
const DENY_METHODS = 0x10;
const DENY_NATIVE_FUNCS = 0x20;
const FORCE_INCLUDE = 0x40;
const AUTO_RELOAD = 0x80;
const FORCE_COMPILE = 0x100;
const AUTO_ESCAPE = 0x200;
const DISABLE_CACHE = 0x400;
const FORCE_VERIFY = 0x800; // reserved
const AUTO_TRIM = 0x1000; // reserved
const DENY_STATICS = 0x2000; // reserved
/* @deprecated */
const DENY_INLINE_FUNCS = 0x20;
const DENY_INLINE_FUNCS = 0x20;
/* Default parsers */
const DEFAULT_CLOSE_COMPILER = 'Fenom\Compiler::stdClose';
const DEFAULT_FUNC_PARSER = 'Fenom\Compiler::stdFuncParser';
const DEFAULT_FUNC_OPEN = 'Fenom\Compiler::stdFuncOpen';
const DEFAULT_FUNC_CLOSE = 'Fenom\Compiler::stdFuncClose';
const SMART_FUNC_PARSER = 'Fenom\Compiler::smartFuncParser';
const DEFAULT_FUNC_PARSER = 'Fenom\Compiler::stdFuncParser';
const DEFAULT_FUNC_OPEN = 'Fenom\Compiler::stdFuncOpen';
const DEFAULT_FUNC_CLOSE = 'Fenom\Compiler::stdFuncClose';
const SMART_FUNC_PARSER = 'Fenom\Compiler::smartFuncParser';
const MAX_MACRO_RECURSIVE = 32;
const MAX_MACRO_RECURSIVE = 32;
/**
* @var int[] of possible options, as associative array
* @see setOptions
*/
private static $_options_list = array(
"disable_methods" => self::DENY_METHODS,
"disable_methods" => self::DENY_METHODS,
"disable_native_funcs" => self::DENY_NATIVE_FUNCS,
"disable_cache" => self::DISABLE_CACHE,
"force_compile" => self::FORCE_COMPILE,
"auto_reload" => self::AUTO_RELOAD,
"force_include" => self::FORCE_INCLUDE,
"auto_escape" => self::AUTO_ESCAPE,
"force_verify" => self::FORCE_VERIFY,
"auto_trim" => self::AUTO_TRIM,
"disable_statics" => self::DENY_STATICS,
"disable_cache" => self::DISABLE_CACHE,
"force_compile" => self::FORCE_COMPILE,
"auto_reload" => self::AUTO_RELOAD,
"force_include" => self::FORCE_INCLUDE,
"auto_escape" => self::AUTO_ESCAPE,
"force_verify" => self::FORCE_VERIFY,
"auto_trim" => self::AUTO_TRIM,
"disable_statics" => self::DENY_STATICS,
);
/**
@ -97,19 +98,19 @@ class Fenom {
* @var string[] list of modifiers [modifier_name => callable]
*/
protected $_modifiers = array(
"upper" => 'strtoupper',
"up" => 'strtoupper',
"lower" => 'strtolower',
"low" => 'strtolower',
"upper" => 'strtoupper',
"up" => 'strtoupper',
"lower" => 'strtolower',
"low" => 'strtolower',
"date_format" => 'Fenom\Modifier::dateFormat',
"date" => 'Fenom\Modifier::date',
"truncate" => 'Fenom\Modifier::truncate',
"escape" => 'Fenom\Modifier::escape',
"e" => 'Fenom\Modifier::escape', // alias of escape
"unescape" => 'Fenom\Modifier::unescape',
"strip" => 'Fenom\Modifier::strip',
"length" => 'Fenom\Modifier::length',
"iterable" => 'Fenom\Modifier::isIterable'
"date" => 'Fenom\Modifier::date',
"truncate" => 'Fenom\Modifier::truncate',
"escape" => 'Fenom\Modifier::escape',
"e" => 'Fenom\Modifier::escape', // alias of escape
"unescape" => 'Fenom\Modifier::unescape',
"strip" => 'Fenom\Modifier::strip',
"length" => 'Fenom\Modifier::length',
"iterable" => 'Fenom\Modifier::isIterable'
);
/**
@ -136,7 +137,7 @@ class Fenom {
),
'float_tags' => array('break' => 1, 'continue' => 1)
),
'if' => array( // {if ...} {elseif ...} {else} {/if}
'if' => array( // {if ...} {elseif ...} {else} {/if}
'type' => self::BLOCK_COMPILER,
'open' => 'Fenom\Compiler::ifOpen',
'close' => 'Fenom\Compiler::stdClose',
@ -145,7 +146,7 @@ class Fenom {
'else' => 'Fenom\Compiler::tagElse',
)
),
'switch' => array( // {switch ...} {case ...} {break} {default} {/switch}
'switch' => array( // {switch ...} {case ...} {break} {default} {/switch}
'type' => self::BLOCK_COMPILER,
'open' => 'Fenom\Compiler::switchOpen',
'close' => 'Fenom\Compiler::stdClose',
@ -156,7 +157,7 @@ class Fenom {
),
'float_tags' => array('break' => 1)
),
'for' => array( // {for ...} {break} {continue} {/for}
'for' => array( // {for ...} {break} {continue} {/for}
'type' => self::BLOCK_COMPILER,
'open' => 'Fenom\Compiler::forOpen',
'close' => 'Fenom\Compiler::forClose',
@ -167,7 +168,7 @@ class Fenom {
),
'float_tags' => array('break' => 1, 'continue' => 1)
),
'while' => array( // {while ...} {break} {continue} {/while}
'while' => array( // {while ...} {break} {continue} {/while}
'type' => self::BLOCK_COMPILER,
'open' => 'Fenom\Compiler::whileOpen',
'close' => 'Fenom\Compiler::stdClose',
@ -181,12 +182,12 @@ class Fenom {
'type' => self::INLINE_COMPILER,
'parser' => 'Fenom\Compiler::tagInclude'
),
'var' => array( // {var ...}
'var' => array( // {var ...}
'type' => self::BLOCK_COMPILER,
'open' => 'Fenom\Compiler::varOpen',
'close' => 'Fenom\Compiler::varClose'
),
'block' => array( // {block ...} {parent} {/block}
'block' => array( // {block ...} {parent} {/block}
'type' => self::BLOCK_COMPILER,
'open' => 'Fenom\Compiler::tagBlockOpen',
'close' => 'Fenom\Compiler::tagBlockClose',
@ -226,7 +227,7 @@ class Fenom {
'type' => self::INLINE_COMPILER,
'parser' => 'Fenom\Compiler::tagCycle'
),
'raw' => array(
'raw' => array(
'type' => self::INLINE_COMPILER,
'parser' => 'Fenom\Compiler::tagRaw'
),
@ -250,10 +251,11 @@ class Fenom {
* @throws InvalidArgumentException
* @return Fenom
*/
public static function factory($source, $compile_dir = '/tmp', $options = 0) {
if(is_string($source)) {
public static function factory($source, $compile_dir = '/tmp', $options = 0)
{
if (is_string($source)) {
$provider = new Fenom\Provider($source);
} elseif($source instanceof ProviderInterface) {
} elseif ($source instanceof ProviderInterface) {
$provider = $source;
} else {
throw new InvalidArgumentException("Source must be a valid path or provider object");
@ -261,7 +263,7 @@ class Fenom {
$fenom = new static($provider);
/* @var Fenom $fenom */
$fenom->setCompileDir($compile_dir);
if($options) {
if ($options) {
$fenom->setOptions($options);
}
return $fenom;
@ -270,7 +272,8 @@ class Fenom {
/**
* @param Fenom\ProviderInterface $provider
*/
public function __construct(Fenom\ProviderInterface $provider) {
public function __construct(Fenom\ProviderInterface $provider)
{
$this->_provider = $provider;
}
@ -280,7 +283,8 @@ class Fenom {
* @param string $dir directory to store compiled templates in
* @return Fenom
*/
public function setCompileDir($dir) {
public function setCompileDir($dir)
{
$this->_compile_dir = $dir;
return $this;
}
@ -289,7 +293,8 @@ class Fenom {
*
* @param callable $cb
*/
public function addPreCompileFilter($cb) {
public function addPreCompileFilter($cb)
{
$this->_on_pre_cmp[] = $cb;
}
@ -297,14 +302,16 @@ class Fenom {
*
* @param callable $cb
*/
public function addPostCompileFilter($cb) {
public function addPostCompileFilter($cb)
{
$this->_on_post_cmp[] = $cb;
}
/**
* @param callable $cb
*/
public function addCompileFilter($cb) {
public function addCompileFilter($cb)
{
$this->_on_cmp[] = $cb;
}
@ -315,7 +322,8 @@ class Fenom {
* @param string $callback the modifier callback
* @return Fenom
*/
public function addModifier($modifier, $callback) {
public function addModifier($modifier, $callback)
{
$this->_modifiers[$modifier] = $callback;
return $this;
}
@ -327,7 +335,8 @@ class Fenom {
* @param callable $parser
* @return Fenom
*/
public function addCompiler($compiler, $parser) {
public function addCompiler($compiler, $parser)
{
$this->_actions[$compiler] = array(
'type' => self::INLINE_COMPILER,
'parser' => $parser
@ -340,11 +349,12 @@ class Fenom {
* @param string|object $storage
* @return $this
*/
public function addCompilerSmart($compiler, $storage) {
if(method_exists($storage, "tag".$compiler)) {
public function addCompilerSmart($compiler, $storage)
{
if (method_exists($storage, "tag" . $compiler)) {
$this->_actions[$compiler] = array(
'type' => self::INLINE_COMPILER,
'parser' => array($storage, "tag".$compiler)
'parser' => array($storage, "tag" . $compiler)
);
}
return $this;
@ -359,11 +369,12 @@ class Fenom {
* @param array $tags
* @return Fenom
*/
public function addBlockCompiler($compiler, $open_parser, $close_parser = self::DEFAULT_CLOSE_COMPILER, array $tags = array()) {
public function addBlockCompiler($compiler, $open_parser, $close_parser = self::DEFAULT_CLOSE_COMPILER, array $tags = array())
{
$this->_actions[$compiler] = array(
'type' => self::BLOCK_COMPILER,
'open' => $open_parser,
'close' => $close_parser ?: self::DEFAULT_CLOSE_COMPILER,
'close' => $close_parser ? : self::DEFAULT_CLOSE_COMPILER,
'tags' => $tags,
);
return $this;
@ -377,27 +388,28 @@ class Fenom {
* @throws LogicException
* @return Fenom
*/
public function addBlockCompilerSmart($compiler, $storage, array $tags, array $floats = array()) {
public function addBlockCompilerSmart($compiler, $storage, array $tags, array $floats = array())
{
$c = array(
'type' => self::BLOCK_COMPILER,
"tags" => array(),
"float_tags" => array()
);
if(method_exists($storage, $compiler."Open")) {
$c["open"] = $compiler."Open";
if (method_exists($storage, $compiler . "Open")) {
$c["open"] = $compiler . "Open";
} else {
throw new \LogicException("Open compiler {$compiler}Open not found");
}
if(method_exists($storage, $compiler."Close")) {
$c["close"] = $compiler."Close";
if (method_exists($storage, $compiler . "Close")) {
$c["close"] = $compiler . "Close";
} else {
throw new \LogicException("Close compiler {$compiler}Close not found");
}
foreach($tags as $tag) {
if(method_exists($storage, "tag".$tag)) {
$c["tags"][ $tag ] = "tag".$tag;
if($floats && in_array($tag, $floats)) {
$c['float_tags'][ $tag ] = 1;
foreach ($tags as $tag) {
if (method_exists($storage, "tag" . $tag)) {
$c["tags"][$tag] = "tag" . $tag;
if ($floats && in_array($tag, $floats)) {
$c['float_tags'][$tag] = 1;
}
} else {
throw new \LogicException("Tag compiler $tag (tag{$compiler}) not found");
@ -413,7 +425,8 @@ class Fenom {
* @param callable|string $parser
* @return Fenom
*/
public function addFunction($function, $callback, $parser = self::DEFAULT_FUNC_PARSER) {
public function addFunction($function, $callback, $parser = self::DEFAULT_FUNC_PARSER)
{
$this->_actions[$function] = array(
'type' => self::INLINE_FUNCTION,
'parser' => $parser,
@ -427,7 +440,8 @@ class Fenom {
* @param callable $callback
* @return Fenom
*/
public function addFunctionSmart($function, $callback) {
public function addFunctionSmart($function, $callback)
{
$this->_actions[$function] = array(
'type' => self::INLINE_FUNCTION,
'parser' => self::SMART_FUNC_PARSER,
@ -443,12 +457,13 @@ class Fenom {
* @param callable|string $parser_close
* @return Fenom
*/
public function addBlockFunction($function, $callback, $parser_open = self::DEFAULT_FUNC_OPEN, $parser_close = self::DEFAULT_FUNC_CLOSE) {
public function addBlockFunction($function, $callback, $parser_open = self::DEFAULT_FUNC_OPEN, $parser_close = self::DEFAULT_FUNC_CLOSE)
{
$this->_actions[$function] = array(
'type' => self::BLOCK_FUNCTION,
'open' => $parser_open,
'close' => $parser_close,
'function' => $callback,
'type' => self::BLOCK_FUNCTION,
'open' => $parser_open,
'close' => $parser_close,
'function' => $callback,
);
return $this;
}
@ -457,7 +472,8 @@ class Fenom {
* @param array $funcs
* @return Fenom
*/
public function addAllowedFunctions(array $funcs) {
public function addAllowedFunctions(array $funcs)
{
$this->_allowed_funcs = $this->_allowed_funcs + array_flip($funcs);
return $this;
}
@ -469,10 +485,11 @@ class Fenom {
* @param Fenom\Template $template
* @return mixed
*/
public function getModifier($modifier, Template $template = null) {
if(isset($this->_modifiers[$modifier])) {
public function getModifier($modifier, Template $template = null)
{
if (isset($this->_modifiers[$modifier])) {
return $this->_modifiers[$modifier];
} elseif($this->isAllowedFunction($modifier)) {
} elseif ($this->isAllowedFunction($modifier)) {
return $modifier;
} else {
return $this->_loadModifier($modifier, $template);
@ -484,7 +501,8 @@ class Fenom {
* @param Fenom\Template $template
* @return bool
*/
protected function _loadModifier($modifier, $template) {
protected function _loadModifier($modifier, $template)
{
return false;
}
@ -494,7 +512,8 @@ class Fenom {
* @return bool|string
* @deprecated
*/
public function getFunction($function, Template $template = null) {
public function getFunction($function, Template $template = null)
{
return $this->getTag($function, $template);
}
@ -505,8 +524,9 @@ class Fenom {
* @param Fenom\Template $template
* @return string|bool
*/
public function getTag($tag, Template $template = null) {
if(isset($this->_actions[$tag])) {
public function getTag($tag, Template $template = null)
{
if (isset($this->_actions[$tag])) {
return $this->_actions[$tag];
} else {
return $this->_loadTag($tag, $template);
@ -518,7 +538,8 @@ class Fenom {
* @param Fenom\Template $template
* @return bool
*/
protected function _loadTag($tag, $template) {
protected function _loadTag($tag, $template)
{
return false;
}
@ -526,8 +547,9 @@ class Fenom {
* @param string $function
* @return bool
*/
public function isAllowedFunction($function) {
if($this->_options & self::DENY_NATIVE_FUNCS) {
public function isAllowedFunction($function)
{
if ($this->_options & self::DENY_NATIVE_FUNCS) {
return isset($this->_allowed_funcs[$function]);
} else {
return is_callable($function);
@ -538,10 +560,11 @@ class Fenom {
* @param string $tag
* @return array
*/
public function getTagOwners($tag) {
public function getTagOwners($tag)
{
$tags = array();
foreach($this->_actions as $owner => $params) {
if(isset($params["tags"][$tag])) {
foreach ($this->_actions as $owner => $params) {
if (isset($params["tags"][$tag])) {
$tags[] = $owner;
}
}
@ -554,7 +577,8 @@ class Fenom {
* @param string $scm scheme name
* @param Fenom\ProviderInterface $provider provider object
*/
public function addProvider($scm, \Fenom\ProviderInterface $provider) {
public function addProvider($scm, \Fenom\ProviderInterface $provider)
{
$this->_providers[$scm] = $provider;
}
@ -562,8 +586,9 @@ class Fenom {
* Set options
* @param int|array $options
*/
public function setOptions($options) {
if(is_array($options)) {
public function setOptions($options)
{
if (is_array($options)) {
$options = self::_makeMask($options, self::$_options_list, $this->_options);
}
$this->_storage = array();
@ -574,7 +599,8 @@ class Fenom {
* Get options as bits
* @return int
*/
public function getOptions() {
public function getOptions()
{
return $this->_options;
}
@ -583,9 +609,10 @@ class Fenom {
* @return Fenom\ProviderInterface
* @throws InvalidArgumentException
*/
public function getProvider($scm = false) {
if($scm) {
if(isset($this->_providers[$scm])) {
public function getProvider($scm = false)
{
if ($scm) {
if (isset($this->_providers[$scm])) {
return $this->_providers[$scm];
} else {
throw new InvalidArgumentException("Provider for '$scm' not found");
@ -600,7 +627,8 @@ class Fenom {
*
* @return Fenom\Template
*/
public function getRawTemplate() {
public function getRawTemplate()
{
return new Template($this, $this->_options);
}
@ -611,7 +639,8 @@ class Fenom {
* @param array $vars array of data for template
* @return Fenom\Render
*/
public function display($template, array $vars = array()) {
public function display($template, array $vars = array())
{
return $this->getTemplate($template)->display($vars);
}
@ -621,7 +650,8 @@ class Fenom {
* @param array $vars array of data for template
* @return mixed
*/
public function fetch($template, array $vars = array()) {
public function fetch($template, array $vars = array())
{
return $this->getTemplate($template)->fetch($vars);
}
@ -634,7 +664,8 @@ class Fenom {
* @param float $chunk
* @return array
*/
public function pipe($template, $callback, array $vars = array(), $chunk = 1e6) {
public function pipe($template, $callback, array $vars = array(), $chunk = 1e6)
{
ob_start($callback, $chunk, true);
$data = $this->getTemplate($template)->display($vars);
ob_end_flush();
@ -648,21 +679,22 @@ class Fenom {
* @param int $options additional options and flags
* @return Fenom\Template
*/
public function getTemplate($template, $options = 0) {
public function getTemplate($template, $options = 0)
{
$options |= $this->_options;
$key = dechex($options)."@".$template;
if(isset($this->_storage[ $key ])) {
/** @var Fenom\Template $tpl */
$tpl = $this->_storage[ $key ];
if(($this->_options & self::AUTO_RELOAD) && !$tpl->isValid()) {
return $this->_storage[ $key ] = $this->compile($template, true, $options);
$key = dechex($options) . "@" . $template;
if (isset($this->_storage[$key])) {
/** @var Fenom\Template $tpl */
$tpl = $this->_storage[$key];
if (($this->_options & self::AUTO_RELOAD) && !$tpl->isValid()) {
return $this->_storage[$key] = $this->compile($template, true, $options);
} else {
return $tpl;
}
} elseif($this->_options & self::FORCE_COMPILE) {
} elseif ($this->_options & self::FORCE_COMPILE) {
return $this->compile($template, $this->_options & self::DISABLE_CACHE & ~self::FORCE_COMPILE, $options);
} else {
return $this->_storage[ $key ] = $this->_load($template, $options);
return $this->_storage[$key] = $this->_load($template, $options);
}
}
@ -671,9 +703,10 @@ class Fenom {
* @param string $template
* @return bool
*/
public function templateExists($template) {
if($provider = strstr($template, ":", true)) {
if(isset($this->_providers[$provider])) {
public function templateExists($template)
{
if ($provider = strstr($template, ":", true)) {
if (isset($this->_providers[$provider])) {
return $this->_providers[$provider]->templateExists(substr($template, strlen($provider) + 1));
}
} else {
@ -689,13 +722,14 @@ class Fenom {
* @param int $opts
* @return Fenom\Render
*/
protected function _load($tpl, $opts) {
protected function _load($tpl, $opts)
{
$file_name = $this->_getCacheName($tpl, $opts);
if(!is_file($this->_compile_dir."/".$file_name)) {
if (!is_file($this->_compile_dir . "/" . $file_name)) {
return $this->compile($tpl, true, $opts);
} else {
$fenom = $this;
return include($this->_compile_dir."/".$file_name);
return include($this->_compile_dir . "/" . $file_name);
}
}
@ -706,8 +740,9 @@ class Fenom {
* @param int $options
* @return string
*/
private function _getCacheName($tpl, $options) {
$hash = $tpl.":".$options;
private function _getCacheName($tpl, $options)
{
$hash = $tpl . ":" . $options;
return sprintf("%s.%x.%x.php", str_replace(":", "_", basename($tpl)), crc32($hash), strlen($hash));
}
@ -720,20 +755,21 @@ class Fenom {
* @throws RuntimeException
* @return \Fenom\Template
*/
public function compile($tpl, $store = true, $options = 0) {
public function compile($tpl, $store = true, $options = 0)
{
$options = $this->_options | $options;
$template = $this->getRawTemplate()->load($tpl);
if($store) {
if ($store) {
$cache = $this->_getCacheName($tpl, $options);
$tpl_tmp = tempnam($this->_compile_dir, $cache);
$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?");
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."/".$cache;
if(!rename($tpl_tmp, $file_name)) {
$file_name = $this->_compile_dir . "/" . $cache;
if (!rename($tpl_tmp, $file_name)) {
throw new \RuntimeException("Can't to move $tpl_tmp to $tpl");
}
}
@ -743,14 +779,16 @@ class Fenom {
/**
* Flush internal memory template cache
*/
public function flush() {
public function flush()
{
$this->_storage = array();
}
/**
* Remove all compiled templates
*/
public function clearAllCompiles() {
public function clearAllCompiles()
{
\Fenom\Provider::clean($this->_compile_dir);
}
@ -761,7 +799,8 @@ class Fenom {
* @param string $name
* @return Fenom\Template
*/
public function compileCode($code, $name = 'Runtime compile') {
public function compileCode($code, $name = 'Runtime compile')
{
return $this->getRawTemplate()->source($name, $code);
}
@ -775,7 +814,8 @@ class Fenom {
* @return int result, ( $mask | a ) & ~b
* @throws \RuntimeException if key from custom assoc doesn't exists into possible values
*/
private static function _makeMask(array $values, array $options, $mask = 0) {
private static function _makeMask(array $values, array $options, $mask = 0)
{
foreach ($values as $key => $value) {
if (isset($options[$key])) {
if ($options[$key]) {

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,8 @@ namespace Fenom;
* Collection of modifiers
* @author Ivan Shalganov <a.cobest@gmail.com>
*/
class Modifier {
class Modifier
{
/**
* Date format
@ -22,10 +23,11 @@ class Modifier {
* @param string $format
* @return string
*/
public static function dateFormat($date, $format = "%b %e, %Y") {
if(is_string($date) && !is_numeric($date)) {
public static function dateFormat($date, $format = "%b %e, %Y")
{
if (is_string($date) && !is_numeric($date)) {
$date = strtotime($date);
if(!$date) $date = time();
if (!$date) $date = time();
}
return strftime($format, $date);
}
@ -35,10 +37,11 @@ class Modifier {
* @param string $format
* @return string
*/
public static function date($date, $format = "Y m d") {
if(is_string($date) && !is_numeric($date)) {
public static function date($date, $format = "Y m d")
{
if (is_string($date) && !is_numeric($date)) {
$date = strtotime($date);
if(!$date) $date = time();
if (!$date) $date = time();
}
return date($format, $date);
}
@ -50,8 +53,9 @@ class Modifier {
* @param string $type
* @return string
*/
public static function escape($text, $type = 'html') {
switch(strtolower($type)) {
public static function escape($text, $type = 'html')
{
switch (strtolower($type)) {
case "url":
return urlencode($text);
case "html";
@ -68,8 +72,9 @@ class Modifier {
* @param string $type
* @return string
*/
public static function unescape($text, $type = 'html') {
switch(strtolower($type)) {
public static function unescape($text, $type = 'html')
{
switch (strtolower($type)) {
case "url":
return urldecode($text);
case "html";
@ -89,23 +94,24 @@ class Modifier {
* @param bool $middle
* @return string
*/
public static function truncate($string, $length = 80, $etc = '...', $by_words = false, $middle = false) {
if($middle) {
if(preg_match('#^(.{'.$length.'}).*?(.{'.$length.'})?$#usS', $string, $match)) {
if(count($match) == 3) {
if($by_words) {
return preg_replace('#\s.*$#usS', "", $match[1]).$etc.preg_replace('#^.*\s#usS', "", $match[2]);
public static function truncate($string, $length = 80, $etc = '...', $by_words = false, $middle = false)
{
if ($middle) {
if (preg_match('#^(.{' . $length . '}).*?(.{' . $length . '})?$#usS', $string, $match)) {
if (count($match) == 3) {
if ($by_words) {
return preg_replace('#\s.*$#usS', "", $match[1]) . $etc . preg_replace('#^.*\s#usS', "", $match[2]);
} else {
return $match[1].$etc.$match[2];
return $match[1] . $etc . $match[2];
}
}
}
} else {
if(preg_match('#^(.{'.$length.'})#usS', $string, $match)) {
if($by_words) {
return preg_replace('#\s.*$#usS', "", $match[1]).$etc;
if (preg_match('#^(.{' . $length . '})#usS', $string, $match)) {
if ($by_words) {
return preg_replace('#\s.*$#usS', "", $match[1]) . $etc;
} else {
return $match[1].$etc;
return $match[1] . $etc;
}
}
}
@ -119,9 +125,10 @@ class Modifier {
* @param bool $to_line strip line ends
* @return string
*/
public static function strip($str, $to_line = false) {
public static function strip($str, $to_line = false)
{
$str = trim($str);
if($to_line) {
if ($to_line) {
return preg_replace('#[\s]+#ms', ' ', $str);
} else {
return preg_replace('#[ \t]{2,}#', ' ', $str);
@ -133,12 +140,13 @@ class Modifier {
* @param mixed $item
* @return int
*/
public static function length($item) {
if(is_string($item)) {
public static function length($item)
{
if (is_string($item)) {
return strlen(preg_replace('#[\x00-\x7F]|[\x80-\xDF][\x00-\xBF]|[\xE0-\xEF][\x00-\xBF]{2}#s', ' ', $item));
} elseif (is_array($item)) {
return count($item);
} elseif($item instanceof \Countable) {
} elseif ($item instanceof \Countable) {
return count($item);
} else {
return 0;
@ -151,10 +159,11 @@ class Modifier {
* @param mixed $haystack
* @return bool
*/
public static function in($value, $haystack) {
if(is_array($haystack)) {
public static function in($value, $haystack)
{
if (is_array($haystack)) {
return in_array($value, $haystack) || array_key_exists($value, $haystack);
} elseif(is_string($haystack)) {
} elseif (is_string($haystack)) {
return strpos($haystack, $value) !== false;
}
return false;
@ -164,7 +173,8 @@ class Modifier {
* @param $value
* @return bool
*/
public static function isIterable($value) {
public static function isIterable($value)
{
return is_array($value) || ($value instanceof \Iterator);
}
}

View File

@ -10,11 +10,13 @@
namespace Fenom;
use Fenom\ProviderInterface;
/**
* Base template provider
* @author Ivan Shalganov
*/
class Provider implements ProviderInterface {
class Provider implements ProviderInterface
{
private $_path;
/**
@ -22,10 +24,11 @@ class Provider implements ProviderInterface {
*
* @param string $path
*/
public static function clean($path) {
if(is_file($path)) {
public static function clean($path)
{
if (is_file($path)) {
unlink($path);
} elseif(is_dir($path)) {
} elseif (is_dir($path)) {
$iterator = iterator_to_array(
new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path,
@ -33,13 +36,13 @@ class Provider implements ProviderInterface {
\RecursiveIteratorIterator::CHILD_FIRST
)
);
foreach($iterator as $file) {
/* @var \splFileInfo $file*/
if($file->isFile()) {
if(strpos($file->getBasename(), ".") !== 0) {
foreach ($iterator as $file) {
/* @var \splFileInfo $file */
if ($file->isFile()) {
if (strpos($file->getBasename(), ".") !== 0) {
unlink($file->getRealPath());
}
} elseif($file->isDir()) {
} elseif ($file->isDir()) {
rmdir($file->getRealPath());
}
}
@ -51,9 +54,10 @@ class Provider implements ProviderInterface {
*
* @param string $path
*/
public static function rm($path) {
public static function rm($path)
{
self::clean($path);
if(is_dir($path)) {
if (is_dir($path)) {
rmdir($path);
}
}
@ -62,8 +66,9 @@ class Provider implements ProviderInterface {
* @param string $template_dir directory of templates
* @throws \LogicException if directory doesn't exists
*/
public function __construct($template_dir) {
if($_dir = realpath($template_dir)) {
public function __construct($template_dir)
{
if ($_dir = realpath($template_dir)) {
$this->_path = $_dir;
} else {
throw new \LogicException("Template directory {$template_dir} doesn't exists");
@ -76,7 +81,8 @@ class Provider implements ProviderInterface {
* @param int $time load last modified time
* @return string
*/
public function getSource($tpl, &$time) {
public function getSource($tpl, &$time)
{
$tpl = $this->_getTemplatePath($tpl);
clearstatcache(null, $tpl);
$time = filemtime($tpl);
@ -88,7 +94,8 @@ class Provider implements ProviderInterface {
* @param string $tpl
* @return int
*/
public function getLastModified($tpl) {
public function getLastModified($tpl)
{
clearstatcache(null, $tpl = $this->_getTemplatePath($tpl));
return filemtime($tpl);
}
@ -99,7 +106,8 @@ class Provider implements ProviderInterface {
* @param string $extension all templates must have this extension, default .tpl
* @return array|\Iterator
*/
public function getList($extension = "tpl") {
public function getList($extension = "tpl")
{
$list = array();
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($this->_path,
@ -107,9 +115,9 @@ class Provider implements ProviderInterface {
\RecursiveIteratorIterator::CHILD_FIRST
);
$path_len = strlen($this->_path);
foreach($iterator as $file) {
foreach ($iterator as $file) {
/* @var \SplFileInfo $file */
if($file->isFile() && $file->getExtension() == $extension) {
if ($file->isFile() && $file->getExtension() == $extension) {
$list[] = substr($file->getPathname(), $path_len + 1);
}
}
@ -122,8 +130,9 @@ class Provider implements ProviderInterface {
* @return string
* @throws \RuntimeException
*/
protected function _getTemplatePath($tpl) {
if(($path = realpath($this->_path."/".$tpl)) && strpos($path, $this->_path) === 0) {
protected function _getTemplatePath($tpl)
{
if (($path = realpath($this->_path . "/" . $tpl)) && strpos($path, $this->_path) === 0) {
return $path;
} else {
throw new \RuntimeException("Template $tpl not found");
@ -134,8 +143,9 @@ class Provider implements ProviderInterface {
* @param string $tpl
* @return bool
*/
public function templateExists($tpl) {
return file_exists($this->_path."/".$tpl);
public function templateExists($tpl)
{
return file_exists($this->_path . "/" . $tpl);
}
/**
@ -144,10 +154,11 @@ class Provider implements ProviderInterface {
* @param array $templates [template_name => modified, ...] By conversation, you may trust the template's name
* @return bool
*/
public function verify(array $templates) {
foreach($templates as $template => $mtime) {
clearstatcache(null, $template = $this->_path.'/'.$template);
if(@filemtime($template) !== $mtime) {
public function verify(array $templates)
{
foreach ($templates as $template => $mtime) {
clearstatcache(null, $template = $this->_path . '/' . $template);
if (@filemtime($template) !== $mtime) {
return false;
}

View File

@ -14,7 +14,8 @@ namespace Fenom;
* @package Fenom
* @author Ivan Shalganov <a.cobest@gmail.com>
*/
interface ProviderInterface {
interface ProviderInterface
{
/**
* @param string $tpl
* @return bool

View File

@ -14,7 +14,8 @@ use Fenom;
* Primitive template
* @author Ivan Shalganov <a.cobest@gmail.com>
*/
class Render extends \ArrayObject {
class Render extends \ArrayObject
{
private static $_props = array(
"name" => "runtime",
"base_name" => "",
@ -72,7 +73,8 @@ class Render extends \ArrayObject {
* @param callable $code template body
* @param array $props
*/
public function __construct(Fenom $fenom, \Closure $code, array $props = array()) {
public function __construct(Fenom $fenom, \Closure $code, array $props = array())
{
$this->_fenom = $fenom;
$props += self::$_props;
$this->_name = $props["name"];
@ -86,7 +88,8 @@ class Render extends \ArrayObject {
* Get template storage
* @return \Fenom
*/
public function getStorage() {
public function getStorage()
{
return $this->_fenom;
}
@ -94,7 +97,8 @@ class Render extends \ArrayObject {
* Get depends list
* @return array
*/
public function getDepends() {
public function getDepends()
{
return $this->_depends;
}
@ -102,7 +106,8 @@ class Render extends \ArrayObject {
* Get schema name
* @return string
*/
public function getScm() {
public function getScm()
{
return $this->_scm;
}
@ -110,7 +115,8 @@ class Render extends \ArrayObject {
* Get provider of template source
* @return ProviderInterface
*/
public function getProvider() {
public function getProvider()
{
return $this->_fenom->getProvider($this->_scm);
}
@ -118,7 +124,8 @@ class Render extends \ArrayObject {
* Get name without schema
* @return string
*/
public function getBaseName() {
public function getBaseName()
{
return $this->_base_name;
}
@ -126,14 +133,16 @@ class Render extends \ArrayObject {
* Get parse options
* @return int
*/
public function getOptions() {
public function getOptions()
{
return $this->_options;
}
/**
* @return string
*/
public function __toString() {
public function __toString()
{
return $this->_name;
}
@ -141,11 +150,13 @@ class Render extends \ArrayObject {
* Get template name
* @return string
*/
public function getName() {
public function getName()
{
return $this->_name;
}
public function getTime() {
public function getTime()
{
return $this->_time;
}
@ -154,16 +165,17 @@ class Render extends \ArrayObject {
* Validate template
* @return bool
*/
public function isValid() {
if(count($this->_depends) === 1) { // if no external dependencies, only self
public function isValid()
{
if (count($this->_depends) === 1) { // if no external dependencies, only self
$provider = $this->_fenom->getProvider($this->_scm);
if($provider->getLastModified($this->_name) !== $this->_time) {
if ($provider->getLastModified($this->_name) !== $this->_time) {
return false;
}
} else {
foreach($this->_depends as $scm => $templates) {
foreach ($this->_depends as $scm => $templates) {
$provider = $this->_fenom->getProvider($scm);
if(!$provider->verify($templates)) {
if (!$provider->verify($templates)) {
return false;
}
}
@ -176,7 +188,8 @@ class Render extends \ArrayObject {
* @param array $values for template
* @return Render
*/
public function display(array $values) {
public function display(array $values)
{
$this->exchangeArray($values);
$this->_code->__invoke($this);
return $this->exchangeArray(array());
@ -188,7 +201,8 @@ class Render extends \ArrayObject {
* @return string
* @throws \Exception
*/
public function fetch(array $values) {
public function fetch(array $values)
{
ob_start();
try {
$this->display($values);
@ -205,7 +219,8 @@ class Render extends \ArrayObject {
* @param $args
* @throws \BadMethodCallException
*/
public function __call($method, $args) {
throw new \BadMethodCallException("Unknown method ".$method);
public function __call($method, $args)
{
throw new \BadMethodCallException("Unknown method " . $method);
}
}

View File

@ -14,7 +14,8 @@ namespace Fenom;
*
* @author Ivan Shalganov <a.cobest@gmail.com>
*/
class Scope extends \ArrayObject {
class Scope extends \ArrayObject
{
public $line = 0;
public $name;
@ -33,20 +34,21 @@ class Scope extends \ArrayObject {
/**
* Creating cope
*
* @param string $name
* @param string $name
* @param Template $tpl
* @param int $line
* @param array $action
* @param int $level
* @param int $line
* @param array $action
* @param int $level
* @param $body
*/
public function __construct($name, $tpl, $line, $action, $level, &$body) {
public function __construct($name, $tpl, $line, $action, $level, &$body)
{
$this->line = $line;
$this->name = $name;
$this->tpl = $tpl;
$this->_action = $action;
$this->level = $level;
$this->_body = &$body;
$this->_body = & $body;
$this->_offset = strlen($body);
}
@ -54,7 +56,8 @@ class Scope extends \ArrayObject {
*
* @param string $function
*/
public function setFuncName($function) {
public function setFuncName($function)
{
$this["function"] = $function;
$this->is_compiler = false;
$this->escape = $this->tpl->escape;
@ -66,7 +69,8 @@ class Scope extends \ArrayObject {
* @param Tokenizer $tokenizer
* @return mixed
*/
public function open($tokenizer) {
public function open($tokenizer)
{
return call_user_func($this->_action["open"], $tokenizer, $this);
}
@ -77,9 +81,10 @@ class Scope extends \ArrayObject {
* @param int $level
* @return bool
*/
public function hasTag($tag, $level) {
if(isset($this->_action["tags"][$tag])) {
if($level) {
public function hasTag($tag, $level)
{
if (isset($this->_action["tags"][$tag])) {
if ($level) {
return isset($this->_action["float_tags"][$tag]);
} else {
return true;
@ -95,7 +100,8 @@ class Scope extends \ArrayObject {
* @param Tokenizer $tokenizer
* @return string
*/
public function tag($tag, $tokenizer) {
public function tag($tag, $tokenizer)
{
return call_user_func($this->_action["tags"][$tag], $tokenizer, $this);
}
@ -105,7 +111,8 @@ class Scope extends \ArrayObject {
* @param Tokenizer $tokenizer
* @return string
*/
public function close($tokenizer) {
public function close($tokenizer)
{
return call_user_func($this->_action["close"], $tokenizer, $this);
}
@ -115,7 +122,8 @@ class Scope extends \ArrayObject {
* @throws \LogicException
* @return string
*/
public function getContent() {
public function getContent()
{
return substr($this->_body, $this->_offset);
}
@ -125,7 +133,8 @@ class Scope extends \ArrayObject {
* @return string
* @throws \LogicException
*/
public function cutContent() {
public function cutContent()
{
$content = substr($this->_body, $this->_offset + 1);
$this->_body = substr($this->_body, 0, $this->_offset);
return $content;
@ -136,12 +145,14 @@ class Scope extends \ArrayObject {
*
* @param $new_content
*/
public function replaceContent($new_content) {
public function replaceContent($new_content)
{
$this->cutContent();
$this->_body .= $new_content;
}
public function unEscapeContent() {
public function unEscapeContent()
{
}
}

File diff suppressed because it is too large Load Diff

View File

@ -12,13 +12,13 @@ namespace Fenom;
/**
* for <PHP 5.4 compatible
*/
defined('T_INSTEADOF') || define('T_INSTEADOF', 341);
defined('T_TRAIT') || define('T_TRAIT', 355);
defined('T_TRAIT_C') || define('T_TRAIT_C', 365);
defined('T_INSTEADOF') || define('T_INSTEADOF', 341);
defined('T_TRAIT') || define('T_TRAIT', 355);
defined('T_TRAIT_C') || define('T_TRAIT_C', 365);
/**
* for PHP <5.5
*/
defined('T_YIELD') || define('T_YIELD', 370);
defined('T_YIELD') || define('T_YIELD', 370);
/**
* Each token have structure
@ -35,7 +35,8 @@ defined('T_YIELD') || define('T_YIELD', 370);
* @package Fenom
* @author Ivan Shalganov <a.cobest@gmail.com>
*/
class Tokenizer {
class Tokenizer
{
const TOKEN = 0;
const TEXT = 1;
const WHITESPACE = 2;
@ -90,19 +91,19 @@ class Tokenizer {
*/
private static $_macros = array(
self::MACRO_STRING => array(
\T_ABSTRACT => 1, \T_ARRAY => 1, \T_AS => 1, \T_BREAK => 1, \T_BREAK => 1, \T_CASE => 1,
\T_CATCH => 1, \T_CLASS => 1, \T_CLASS_C => 1, \T_CLONE => 1, \T_CONST => 1, \T_CONTINUE => 1,
\T_DECLARE => 1, \T_DEFAULT => 1, \T_DIR => 1, \T_DO => 1, \T_ECHO => 1, \T_ELSE => 1,
\T_ELSEIF => 1, \T_EMPTY => 1, \T_ENDDECLARE => 1, \T_ENDFOR => 1, \T_ENDFOREACH => 1, \T_ENDIF => 1,
\T_ENDSWITCH => 1, \T_ENDWHILE => 1, \T_EVAL => 1, \T_EXIT => 1, \T_EXTENDS => 1, \T_FILE => 1,
\T_FINAL => 1, \T_FOR => 1, \T_FOREACH => 1, \T_FUNCTION => 1, \T_FUNC_C => 1, \T_GLOBAL => 1,
\T_GOTO => 1, \T_HALT_COMPILER => 1, \T_IF => 1, \T_IMPLEMENTS => 1, \T_INCLUDE => 1, \T_INCLUDE_ONCE => 1,
\T_INSTANCEOF => 1, \T_INSTEADOF => 1, \T_INTERFACE => 1, \T_ISSET => 1, \T_LINE => 1, \T_LIST => 1,
\T_LOGICAL_AND => 1, \T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_METHOD_C => 1, \T_NAMESPACE => 1, \T_NS_C => 1,
\T_NEW => 1, \T_PRINT => 1, \T_PRIVATE => 1, \T_PUBLIC => 1, \T_PROTECTED => 1, \T_REQUIRE => 1,
\T_REQUIRE_ONCE => 1,\T_RETURN => 1, \T_RETURN => 1, \T_STRING => 1, \T_SWITCH => 1, \T_THROW => 1,
\T_TRAIT => 1, \T_TRAIT_C => 1, \T_TRY => 1, \T_UNSET => 1, \T_VAR => 1,
\T_WHILE => 1, \T_YIELD => 1, \T_USE => 1
\T_ABSTRACT => 1, \T_ARRAY => 1, \T_AS => 1, \T_BREAK => 1, \T_BREAK => 1, \T_CASE => 1,
\T_CATCH => 1, \T_CLASS => 1, \T_CLASS_C => 1, \T_CLONE => 1, \T_CONST => 1, \T_CONTINUE => 1,
\T_DECLARE => 1, \T_DEFAULT => 1, \T_DIR => 1, \T_DO => 1, \T_ECHO => 1, \T_ELSE => 1,
\T_ELSEIF => 1, \T_EMPTY => 1, \T_ENDDECLARE => 1, \T_ENDFOR => 1, \T_ENDFOREACH => 1, \T_ENDIF => 1,
\T_ENDSWITCH => 1, \T_ENDWHILE => 1, \T_EVAL => 1, \T_EXIT => 1, \T_EXTENDS => 1, \T_FILE => 1,
\T_FINAL => 1, \T_FOR => 1, \T_FOREACH => 1, \T_FUNCTION => 1, \T_FUNC_C => 1, \T_GLOBAL => 1,
\T_GOTO => 1, \T_HALT_COMPILER => 1, \T_IF => 1, \T_IMPLEMENTS => 1, \T_INCLUDE => 1, \T_INCLUDE_ONCE => 1,
\T_INSTANCEOF => 1, \T_INSTEADOF => 1, \T_INTERFACE => 1, \T_ISSET => 1, \T_LINE => 1, \T_LIST => 1,
\T_LOGICAL_AND => 1, \T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_METHOD_C => 1, \T_NAMESPACE => 1, \T_NS_C => 1,
\T_NEW => 1, \T_PRINT => 1, \T_PRIVATE => 1, \T_PUBLIC => 1, \T_PROTECTED => 1, \T_REQUIRE => 1,
\T_REQUIRE_ONCE => 1, \T_RETURN => 1, \T_RETURN => 1, \T_STRING => 1, \T_SWITCH => 1, \T_THROW => 1,
\T_TRAIT => 1, \T_TRAIT_C => 1, \T_TRY => 1, \T_UNSET => 1, \T_VAR => 1,
\T_WHILE => 1, \T_YIELD => 1, \T_USE => 1
),
self::MACRO_INCDEC => array(
\T_INC => 1, \T_DEC => 1
@ -111,41 +112,41 @@ class Tokenizer {
"!" => 1, "~" => 1, "-" => 1
),
self::MACRO_BINARY => array(
\T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1, \T_IS_GREATER_OR_EQUAL => 1, \T_IS_EQUAL => 1, \T_IS_IDENTICAL => 1,
\T_IS_NOT_EQUAL => 1,\T_IS_NOT_IDENTICAL => 1, \T_IS_SMALLER_OR_EQUAL => 1, \T_LOGICAL_AND => 1,
\T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_SL => 1, \T_SR => 1,
\T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1, \T_IS_GREATER_OR_EQUAL => 1, \T_IS_EQUAL => 1, \T_IS_IDENTICAL => 1,
\T_IS_NOT_EQUAL => 1, \T_IS_NOT_IDENTICAL => 1, \T_IS_SMALLER_OR_EQUAL => 1, \T_LOGICAL_AND => 1,
\T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_SL => 1, \T_SR => 1,
"+" => 1, "-" => 1, "*" => 1, "/" => 1, ">" => 1, "<" => 1, "^" => 1, "%" => 1, "&" => 1
),
self::MACRO_BOOLEAN => array(
\T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1, \T_LOGICAL_AND => 1
\T_LOGICAL_OR => 1, \T_LOGICAL_XOR => 1, \T_BOOLEAN_AND => 1, \T_BOOLEAN_OR => 1, \T_LOGICAL_AND => 1
),
self::MACRO_MATH => array(
"+" => 1, "-" => 1, "*" => 1, "/" => 1, "^" => 1, "%" => 1, "&" => 1, "|" => 1
),
self::MACRO_COND => array(
\T_IS_EQUAL => 1, \T_IS_IDENTICAL => 1, ">" => 1, "<" => 1, \T_SL => 1, \T_SR => 1,
\T_IS_NOT_EQUAL => 1,\T_IS_NOT_IDENTICAL => 1, \T_IS_SMALLER_OR_EQUAL => 1,
\T_IS_EQUAL => 1, \T_IS_IDENTICAL => 1, ">" => 1, "<" => 1, \T_SL => 1, \T_SR => 1,
\T_IS_NOT_EQUAL => 1, \T_IS_NOT_IDENTICAL => 1, \T_IS_SMALLER_OR_EQUAL => 1,
),
self::MACRO_EQUALS => array(
\T_AND_EQUAL => 1, \T_CONCAT_EQUAL => 1,\T_DIV_EQUAL => 1, \T_MINUS_EQUAL => 1, \T_MOD_EQUAL => 1,
\T_MUL_EQUAL => 1, \T_OR_EQUAL => 1, \T_PLUS_EQUAL => 1, \T_SL_EQUAL => 1, \T_SR_EQUAL => 1,
\T_XOR_EQUAL => 1, '=' => 1
\T_AND_EQUAL => 1, \T_CONCAT_EQUAL => 1, \T_DIV_EQUAL => 1, \T_MINUS_EQUAL => 1, \T_MOD_EQUAL => 1,
\T_MUL_EQUAL => 1, \T_OR_EQUAL => 1, \T_PLUS_EQUAL => 1, \T_SL_EQUAL => 1, \T_SR_EQUAL => 1,
\T_XOR_EQUAL => 1, '=' => 1
),
self::MACRO_SCALAR => array(
\T_LNUMBER => 1, \T_DNUMBER => 1, \T_CONSTANT_ENCAPSED_STRING => 1
\T_LNUMBER => 1, \T_DNUMBER => 1, \T_CONSTANT_ENCAPSED_STRING => 1
)
);
public static $description = array(
self::MACRO_STRING => 'string',
self::MACRO_INCDEC => 'increment/decrement operator',
self::MACRO_UNARY => 'unary operator',
self::MACRO_BINARY => 'binary operator',
self::MACRO_STRING => 'string',
self::MACRO_INCDEC => 'increment/decrement operator',
self::MACRO_UNARY => 'unary operator',
self::MACRO_BINARY => 'binary operator',
self::MACRO_BOOLEAN => 'boolean operator',
self::MACRO_MATH => 'math operator',
self::MACRO_COND => 'conditional operator',
self::MACRO_EQUALS => 'equal operator',
self::MACRO_SCALAR => 'scalar value'
self::MACRO_MATH => 'math operator',
self::MACRO_COND => 'conditional operator',
self::MACRO_EQUALS => 'equal operator',
self::MACRO_SCALAR => 'scalar value'
);
/**
@ -159,15 +160,16 @@ class Tokenizer {
/**
* @param $query
*/
public function __construct($query) {
public function __construct($query)
{
$tokens = array(-1 => array(\T_WHITESPACE, '', '', 1));
$_tokens = token_get_all("<?php ".$query);
$_tokens = token_get_all("<?php " . $query);
$line = 1;
array_shift($_tokens);
$i = 0;
foreach($_tokens as $token) {
if(is_string($token)) {
if($token === '"' || $token === "'" || $token === "`") {
foreach ($_tokens as $token) {
if (is_string($token)) {
if ($token === '"' || $token === "'" || $token === "`") {
$this->quotes++;
}
$tokens[] = array(
@ -178,13 +180,13 @@ class Tokenizer {
);
$i++;
} elseif ($token[0] === \T_WHITESPACE) {
$tokens[$i-1][2] = $token[1];
$tokens[$i - 1][2] = $token[1];
} else {
$tokens[] = array(
$token[0],
$token[1],
"",
$line = $token[2],
$line = $token[2],
token_name($token[0]) // debug
);
$i++;
@ -202,7 +204,8 @@ class Tokenizer {
*
* @return int
*/
public function isIncomplete() {
public function isIncomplete()
{
return ($this->quotes % 2) || ($this->tokens[$this->_max][0] === T_ENCAPSED_AND_WHITESPACE);
}
@ -212,7 +215,8 @@ class Tokenizer {
* @link http://php.net/manual/en/iterator.current.php
* @return mixed Can return any type.
*/
public function current() {
public function current()
{
return $this->curr[1];
}
@ -222,8 +226,9 @@ class Tokenizer {
* @link http://php.net/manual/en/iterator.next.php
* @return Tokenizer
*/
public function next() {
if($this->p > $this->_max) {
public function next()
{
if ($this->p > $this->_max) {
return $this;
}
$this->p++;
@ -238,15 +243,16 @@ class Tokenizer {
* @param string|int $token
* @return bool
*/
private function _valid($expects, $token) {
foreach($expects as $expect) {
if(is_string($expect) || $expect < 1000) {
if($expect === $token) {
private function _valid($expects, $token)
{
foreach ($expects as $expect) {
if (is_string($expect) || $expect < 1000) {
if ($expect === $token) {
return true;
}
} else {
if(isset(self::$_macros[ $expect ][ $token ])) {
if (isset(self::$_macros[$expect][$token])) {
return true;
}
}
@ -260,13 +266,14 @@ class Tokenizer {
* @throws UnexpectedTokenException
* @return mixed
*/
public function _next($tokens) {
public function _next($tokens)
{
$this->next();
if(!$this->curr) {
if (!$this->curr) {
throw new UnexpectedTokenException($this, $tokens);
}
if($tokens) {
if($this->_valid($tokens, $this->key())) {
if ($tokens) {
if ($this->_valid($tokens, $this->key())) {
return;
}
} else {
@ -279,7 +286,8 @@ class Tokenizer {
* Fetch next specified token or throw an exception
* @return mixed
*/
public function getNext(/*int|string $token1, int|string $token2, ... */) {
public function getNext( /*int|string $token1, int|string $token2, ... */)
{
$this->_next(func_get_args());
return $this->current();
}
@ -288,7 +296,8 @@ class Tokenizer {
* @param $token
* @return bool
*/
public function isNextToken($token) {
public function isNextToken($token)
{
return $this->next ? $this->next[1] == $token : false;
}
@ -298,15 +307,16 @@ class Tokenizer {
* @param int $limit
* @return string
*/
public function getSubstr($offset, $limit = 0) {
public function getSubstr($offset, $limit = 0)
{
$str = '';
if(!$limit) {
if (!$limit) {
$limit = $this->_max;
} else {
$limit += $offset;
}
for($i = $offset; $i <= $limit; $i++){
$str .= $this->tokens[$i][1].$this->tokens[$i][2];
for ($i = $offset; $i <= $limit; $i++) {
$str .= $this->tokens[$i][1] . $this->tokens[$i][2];
}
return $str;
}
@ -316,8 +326,9 @@ class Tokenizer {
* @return mixed
* @throws UnexpectedTokenException
*/
public function getAndNext() {
if($this->curr) {
public function getAndNext()
{
if ($this->curr) {
$cur = $this->curr[1];
$this->next();
return $cur;
@ -331,7 +342,8 @@ class Tokenizer {
* @param $token1
* @return bool
*/
public function isNext($token1/*, ...*/) {
public function isNext($token1 /*, ...*/)
{
return $this->next && $this->_valid(func_get_args(), $this->next[0]);
}
@ -340,7 +352,8 @@ class Tokenizer {
* @param $token1
* @return bool
*/
public function is($token1/*, ...*/) {
public function is($token1 /*, ...*/)
{
return $this->curr && $this->_valid(func_get_args(), $this->curr[0]);
}
@ -349,7 +362,8 @@ class Tokenizer {
* @param $token1
* @return bool
*/
public function isPrev($token1/*, ...*/) {
public function isPrev($token1 /*, ...*/)
{
return $this->prev && $this->_valid(func_get_args(), $this->prev[0]);
}
@ -360,8 +374,9 @@ class Tokenizer {
* @throws UnexpectedTokenException
* @return mixed
*/
public function get($token1 /*, $token2 ...*/) {
if($this->curr && $this->_valid(func_get_args(), $this->curr[0])) {
public function get($token1 /*, $token2 ...*/)
{
if ($this->curr && $this->_valid(func_get_args(), $this->curr[0])) {
return $this->curr[1];
} else {
throw new UnexpectedTokenException($this, func_get_args());
@ -372,8 +387,9 @@ class Tokenizer {
* Step back
* @return Tokenizer
*/
public function back() {
if($this->p === 0) {
public function back()
{
if ($this->p === 0) {
return $this;
}
$this->p--;
@ -385,12 +401,13 @@ class Tokenizer {
* @param $token1
* @return bool
*/
public function hasBackList($token1 /*, $token2 ...*/) {
public function hasBackList($token1 /*, $token2 ...*/)
{
$tokens = func_get_args();
$c = $this->p;
foreach($tokens as $token) {
foreach ($tokens as $token) {
$c--;
if($c < 0 || $this->tokens[$c][0] !== $token) {
if ($c < 0 || $this->tokens[$c][0] !== $token) {
return false;
}
}
@ -403,8 +420,9 @@ class Tokenizer {
* @param string $key
* @return mixed
*/
public function __get($key) {
switch($key) {
public function __get($key)
{
switch ($key) {
case 'curr':
return $this->curr = ($this->p <= $this->_max) ? $this->tokens[$this->p] : null;
case 'next':
@ -416,7 +434,8 @@ class Tokenizer {
}
}
public function count() {
public function count()
{
return $this->_max;
}
@ -424,7 +443,8 @@ class Tokenizer {
* Return the key of the current element
* @return mixed scalar on success, or null on failure.
*/
public function key() {
public function key()
{
return $this->curr ? $this->curr[0] : null;
}
@ -433,7 +453,8 @@ class Tokenizer {
* @return boolean The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
*/
public function valid() {
public function valid()
{
return (bool)$this->curr;
}
@ -443,12 +464,13 @@ class Tokenizer {
* @param int|string $token
* @return string
*/
public static function getName($token) {
if(is_string($token)) {
public static function getName($token)
{
if (is_string($token)) {
return $token;
} elseif(is_integer($token)) {
} elseif (is_integer($token)) {
return token_name($token);
} elseif(is_array($token)) {
} elseif (is_array($token)) {
return token_name($token[0]);
} else {
return null;
@ -461,9 +483,10 @@ class Tokenizer {
* @throws UnexpectedTokenException
* @return Tokenizer
*/
public function skip(/*$token1, $token2, ...*/) {
if(func_num_args()) {
if($this->_valid(func_get_args(), $this->curr[0])) {
public function skip( /*$token1, $token2, ...*/)
{
if (func_num_args()) {
if ($this->_valid(func_get_args(), $this->curr[0])) {
$this->next();
return $this;
} else {
@ -481,8 +504,9 @@ class Tokenizer {
* @param int|string $token1
* @return Tokenizer
*/
public function skipIf($token1/*, $token2, ...*/) {
if($this->_valid(func_get_args(), $this->curr[0])) {
public function skipIf($token1 /*, $token2, ...*/)
{
if ($this->_valid(func_get_args(), $this->curr[0])) {
$this->next();
}
return $this;
@ -495,8 +519,9 @@ class Tokenizer {
* @return Tokenizer
* @throws UnexpectedTokenException
*/
public function need($token1/*, $token2, ...*/) {
if($this->_valid(func_get_args(), $this->curr[0])) {
public function need($token1 /*, $token2, ...*/)
{
if ($this->_valid(func_get_args(), $this->curr[0])) {
return $this;
} else {
throw new UnexpectedTokenException($this, func_get_args());
@ -509,37 +534,38 @@ class Tokenizer {
* @param int $after count tokens after current token
* @return array
*/
public function getSnippet($before = 0, $after = 0) {
public function getSnippet($before = 0, $after = 0)
{
$from = 0;
$to = $this->p;
if($before > 0) {
if($before > $this->p) {
if ($before > 0) {
if ($before > $this->p) {
$from = $this->p;
} else {
$from = $before;
}
} elseif($before < 0) {
} elseif ($before < 0) {
$from = $this->p + $before;
if($from < 0) {
if ($from < 0) {
$from = 0;
}
}
if($after > 0) {
if ($after > 0) {
$to = $this->p + $after;
if($to > $this->_max) {
if ($to > $this->_max) {
$to = $this->_max;
}
} elseif($after < 0) {
} elseif ($after < 0) {
$to = $this->_max + $after;
if($to < $this->p) {
if ($to < $this->p) {
$to = $this->p;
}
} elseif($this->p > $this->_max) {
} elseif ($this->p > $this->_max) {
$to = $this->_max;
}
$code = array();
for($i=$from; $i<=$to; $i++) {
$code[] = $this->tokens[ $i ];
for ($i = $from; $i <= $to; $i++) {
$code[] = $this->tokens[$i];
}
return $code;
@ -551,10 +577,11 @@ class Tokenizer {
* @param int $after
* @return string
*/
public function getSnippetAsString($before = 0, $after = 0) {
public function getSnippetAsString($before = 0, $after = 0)
{
$str = "";
foreach($this->getSnippet($before, $after) as $token) {
$str .= $token[1].$token[2];
foreach ($this->getSnippet($before, $after) as $token) {
$str .= $token[1] . $token[2];
}
return trim(str_replace("\n", '↵', $str));
}
@ -563,7 +590,8 @@ class Tokenizer {
* Check if current is special value: true, TRUE, false, FALSE, null, NULL
* @return bool
*/
public function isSpecialVal() {
public function isSpecialVal()
{
return isset(self::$spec[$this->current()]);
}
@ -571,14 +599,16 @@ class Tokenizer {
* Check if the token is last
* @return bool
*/
public function isLast() {
public function isLast()
{
return $this->p === $this->_max;
}
/**
* Move pointer to the end
*/
public function end() {
public function end()
{
$this->p = $this->_max;
}
@ -586,7 +616,8 @@ class Tokenizer {
* Return line number of the current token
* @return mixed
*/
public function getLine() {
public function getLine()
{
return $this->curr ? $this->curr[3] : $this->_last_no;
}
@ -594,33 +625,13 @@ class Tokenizer {
* Is current token whitespaced, means previous token has whitespace characters
* @return bool
*/
public function isWhiteSpaced() {
public function isWhiteSpaced()
{
return $this->prev ? (bool)$this->prev[2] : false;
}
public function getWhitespace() {
public function getWhitespace()
{
return $this->curr ? $this->curr[2] : false;
}
}
/**
* Unexpected token
*/
class UnexpectedTokenException extends \RuntimeException {
public function __construct(Tokenizer $tokens, $expect = null, $where = null) {
if($expect && count($expect) == 1 && is_string($expect[0])) {
$expect = ", expect '".$expect[0]."'";
} else {
$expect = "";
}
if(!$tokens->curr) {
$this->message = "Unexpected end of ".($where?:"expression")."$expect";
} elseif($tokens->curr[0] === T_WHITESPACE) {
$this->message = "Unexpected whitespace$expect";
} elseif($tokens->curr[0] === T_BAD_CHARACTER) {
$this->message = "Unexpected bad characters (below ASCII 32 except \\t, \\n and \\r) in ".($where?:"expression")."$expect";
} else {
$this->message = "Unexpected token '".$tokens->current()."' in ".($where?:"expression")."$expect";
}
}
};

View File

@ -0,0 +1,29 @@
<?php
namespace Fenom;
/**
* Unexpected token
*/
class UnexpectedTokenException extends \RuntimeException
{
public function __construct(Tokenizer $tokens, $expect = null, $where = null)
{
if ($expect && count($expect) == 1 && is_string($expect[0])) {
$expect = ", expect '" . $expect[0] . "'";
} else {
$expect = "";
}
if (!$tokens->curr) {
$this->message = "Unexpected end of " . ($where ? : "expression") . "$expect";
} elseif ($tokens->curr[0] === T_WHITESPACE) {
$this->message = "Unexpected whitespace$expect";
} elseif ($tokens->curr[0] === T_BAD_CHARACTER) {
$this->message = "Unexpected bad characters (below ASCII 32 except \\t, \\n and \\r) in " . ($where ? : "expression") . "$expect";
} else {
$this->message = "Unexpected token '" . $tokens->current() . "' in " . ($where ? : "expression") . "$expect";
}
}
}
;