Commit 2f0eff5f by Seldaek

+ Syntax: Added shortcut for {$dwoo.const.*} using '%', for example you can use

{%FOO} instead of {$dwoo.const.FOO} + Syntax: When using named parameters, typing a parameter name without any value is the same as typing param=true, for example {foo name="test" bar} and {foo name="test" bar=true} are equals, can be useful for very complex plugins with huge amounts of parameters. + Plugins: Added {loop} that combines {foreach} and {with}, see http://wiki.dwoo.org/index.php/Block:loop for details * API: DwooITemplate->clearCache now requires a Dwoo instance as its first arg, should not affect you unless you built a custom template class from scratch * {include} now uses the current resource if none is provided instead of using file as it did before * Dwoo uses include path instead of absolute includes * Fixed a regression in the handling of custom class plugins * Fixed a bug in DwooSecurityPolicy->getAllowedDirectories(), no security issue though * TestFest happened early for Dwoo, lots of new tests and more code covered git-svn-id: svn://dwoo.org/dwoo/trunk@29 0598d79b-80c4-4d41-97ba-ac86fbbd088b
parent 92a1ced8
[2008-04-] 0.4.0
[2008-04-] 0.4.0 (Happy Getty)
! BC Break: $dwoo->output() and get() have been swapped internally, but it
doesn't change anything for you unless you called output(*, *, *, true)
directly to emulate get(). This was done to reduce some overhead
+ Plugins: Added {extends} and {block} to handle template inheritance, read
more about it at http://wiki.dwoo.org/index.php/TemplateInheritance
+ Plugins: Added {loop} that combines {foreach} and {with}, see
http://wiki.dwoo.org/index.php/Block:loop for details
+ Plugins: Added {do} that executes whatever you feed it whitout echoing the
result, used internally for extends but you can use it if required
+ Syntax: Added shortcut for {$dwoo.const.*} using '%', for example you can use
{%FOO} instead of {$dwoo.const.FOO}
+ Syntax: When using named parameters, typing a parameter name without any
value is the same as typing param=true, for example {foo name="test" bar} and
{foo name="test" bar=true} are equals, can be useful for very complex plugins
with huge amounts of parameters.
+ Syntax: Added support for {$foo+=5}, {$foo="a"}, {$foo++} and {$foo--}
+ Syntax: Added shortcut for $dwoo.*, you can now use {$.const.FOO} instead of
{$dwoo.const.FOO} for example, applies to all $dwoo.* vars
+ Syntax: Added shortcut for $dwoo.*, you can now use {$.foreach.foo} instead
of {$dwoo.foreach.foo} for example, applies to all $dwoo.* vars
+ API: Added getSource(), getUid() and getResourceIdentifier() to DwooITemplate
+ API: Added setSecurityPolicy() too DwooICompiler and modified the arguments
of its compile() method
......@@ -22,6 +30,15 @@
doing {foreach $foo}..{/foreach} will not however, that way you don't have
to do {if isset($foo)} before the foreach, but automated isset() calls don't
impact performance as much as they did before.
* API: DwooITemplate->clearCache now requires a Dwoo instance as its first arg,
should not affect you unless you built a custom template class from scratch
* {include} now uses the current resource if none is provided instead of using
file as it did before
* Dwoo uses include path instead of absolute includes
* Fixed a regression in the handling of custom class plugins
* Fixed a bug in DwooSecurityPolicy->getAllowedDirectories(), no security
issue though
* TestFest happened early for Dwoo, lots of new tests and more code covered
[2008-04-09] 0.3.4
! BC Break: DWOO_PATH constant changed to DWOO_DIRECTORY
......
<?php
include dirname(__FILE__).DIRECTORY_SEPARATOR . 'DwooInterfaces.php';
include dirname(__FILE__).DIRECTORY_SEPARATOR . 'DwooPlugin.php';
include dirname(__FILE__).DIRECTORY_SEPARATOR . 'DwooTemplateString.php';
include dirname(__FILE__).DIRECTORY_SEPARATOR . 'DwooTemplateFile.php';
include dirname(__FILE__).DIRECTORY_SEPARATOR . 'DwooData.php';
set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__));
// TODO move those in Dwoo/Interface, ...
include 'DwooInterfaces.php';
include 'DwooPlugin.php';
include 'DwooTemplateString.php';
include 'DwooTemplateFile.php';
include 'DwooData.php';
define('DWOO_DIRECTORY', dirname(__FILE__).DIRECTORY_SEPARATOR);
if(defined('DWOO_CACHE_DIRECTORY') === false)
......@@ -760,7 +762,7 @@ class Dwoo
* @param int $olderThan minimum time (in seconds) required for a cached template to be cleared
* @return int the amount of templates cleared
*/
public function clearCache($olderThan=0)
public function clearCache($olderThan=-1)
{
$cacheDirs = new RecursiveDirectoryIterator($this->cacheDir);
$cache = new RecursiveIteratorIterator($cacheDirs);
......@@ -768,7 +770,7 @@ class Dwoo
$count = 0;
foreach($cache as $file)
{
if($cache->isDot() || $cache->isDir())
if($cache->isDot() || $cache->isDir() || substr($file, -5) !== '.html')
continue;
if($cache->getCTime() < $expired)
$count += unlink((string) $file) ? 1 : 0;
......@@ -1750,7 +1752,7 @@ class DwooSecurityPolicy
*/
public function getAllowedDirectories()
{
return $this->allowedPHPFunc;
return $this->allowedDirectories;
}
/**
......
......@@ -959,6 +959,10 @@ class DwooCompiler implements DwooICompiler
{
return $this->parseVar($in, $from, $to, $parsingParams, $curBlock, $pointer);
}
elseif($first==='%' && preg_match('#^%[a-z]#i', $substr)) // const
{
return $this->parseConst($in, $from, $to, $parsingParams, $curBlock, $pointer);
}
elseif($first==='"' || $first==="'") // string
{
return $this->parseString($in, $from, $to, $parsingParams, $curBlock, $pointer);
......@@ -1091,13 +1095,18 @@ class DwooCompiler implements DwooICompiler
}
$paramstr = substr($paramstr, 0, $ptr);
$state = 0;
foreach($params as $p)
foreach($params as $k=>$p)
{
if(is_array($p) && is_array($p[1]))
$state |= 2;
else
{
if($state === 2 && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m))
$params[$k] = array($m[2], array('true', 'true'));
else
$state |= 1;
}
}
if($state === 3)
$this->triggerError('Function calls can not have both named and un-named parameters', E_USER_ERROR);
}
......@@ -1232,9 +1241,14 @@ class DwooCompiler implements DwooICompiler
{
$callback = $this->customPlugins[$func]['callback'];
if(!is_array($callback))
{
if(($ref = new ReflectionMethod($callback, 'process')) && $ref->isStatic())
$output = 'call_user_func(array(\''.$callback.'\', \'process\'), '.$params.')';
else
$output = 'call_user_func(array($this->getObjectPlugin(\''.$callback.'\'), \'process\'), '.$params.')';
}
elseif(is_object($callback[0]))
$output = 'call_user_func(array($this->customPlugins[\''.$func.'\'][0], \''.$callback[1].'\'), '.$params.')';
$output = 'call_user_func(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), '.$params.')';
elseif(($ref = new ReflectionMethod($callback[0], $callback[1])) && $ref->isStatic())
$output = 'call_user_func(array(\''.$callback[0].'\', \''.$callback[1].'\'), '.$params.')';
else
......@@ -1254,7 +1268,7 @@ class DwooCompiler implements DwooICompiler
if(is_array($callback))
{
if(is_object($callback[0]))
$output = 'call_user_func_array(array($this->customPlugins[\''.$func.'\'][0], \''.$callback[1].'\'), array(array('.$params.'), $this))';
$output = 'call_user_func_array(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array(array('.$params.'), $this))';
else
$output = 'call_user_func_array(array(\''.$callback[0].'\', \''.$callback[1].'\'), array(array('.$params.'), $this))';
}
......@@ -1352,6 +1366,62 @@ class DwooCompiler implements DwooICompiler
}
/**
* parses a constant
*
* @param string $in the string within which we must parse something
* @param int $from the starting offset of the parsed area
* @param int $to the ending offset of the parsed area
* @param mixed $parsingParams must be an array if we are parsing a function or modifier's parameters, or false by default
* @param string $curBlock the current parser-block being processed
* @param mixed $pointer a reference to a pointer that will be increased by the amount of characters parsed, or null by default
* @return string parsed values
*/
protected function parseConst($in, $from, $to, $parsingParams = false, $curBlock='', &$pointer = null)
{
$substr = substr($in, $from, $to-$from);
if($this->debug)
echo 'CONST FOUND : '.$substr.'<br />';
if(!preg_match('#^%([a-z0-9_:]+)#i', $substr, $m))
$this->triggerError('Invalid constant', E_USER_ERROR);
$output = $this->parseConstKey($m[1], $curBlock);
if(is_array($parsingParams))
{
$parsingParams[] = array($output, $m[1]);
return $parsingParams;
}
elseif($curBlock === 'namedparam')
return array($output, $m[1]);
elseif($curBlock === 'root')
return self::PHP_OPEN.'echo '.$output.';'.self::PHP_CLOSE;
else
return $output;
}
/**
* parses a constant
*
* @param string $key the constant to parse
* @param string $curBlock the current parser-block being processed
* @return string parsed constant
*/
protected function parseConstKey($key, $curBlock)
{
if($this->securityPolicy !== null && $this->securityPolicy->getConstantHandling() === DwooSecurityPolicy::CONST_DISALLOW)
return 'null';
if($curBlock !== 'root')
$output = '(defined("'.$key.'") ? '.$key.' : null)';
else
$output = $key;
return $output;
}
/**
* parses a variable
*
* @param string $in the string within which we must parse something
......@@ -1368,7 +1438,7 @@ class DwooCompiler implements DwooICompiler
if(preg_match('#(\$?\.?[a-z0-9_:]+(?:(?:(?:\.|->)(?:[a-z0-9_:]+|(?R))|\[(?:[a-z0-9_:]+|(?R))\]))*)' . // var key
($curBlock==='root' || $curBlock==='function' || $curBlock==='condition' || $curBlock==='variable' || $curBlock==='expression' ? '(\([^)]*?\)(?:->[a-z0-9_]+(?:\([^)]*?\))?)*)?' : '()') . // method call
($curBlock==='root' || $curBlock==='function' || $curBlock==='condition' || $curBlock==='variable' || $curBlock==='string' ? '((?:(?:[+/*%=-])(?:(?<!=)=?-?\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9.,]*|[+-]))*)':'()') . // simple math expressions
($curBlock==='root' || $curBlock==='function' || $curBlock==='condition' || $curBlock==='variable' || $curBlock==='string' ? '((?:(?:[+/*%=-])(?:(?<!=)=?-?[$%][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|(?<!=)=?-?[0-9.,]*|[+-]))*)':'()') . // simple math expressions
($curBlock!=='modifier'? '((?:\|(?:@?[a-z0-9_]+(?:(?::("|\').+?\5|:[^\s`"\']*))*))+)?':'(())') . // modifiers
'#i', $substr, $match))
{
......@@ -1478,7 +1548,7 @@ class DwooCompiler implements DwooICompiler
// expressions
if($hasExpression)
{
preg_match_all('#(?:([+/*%=-])(=?-?\$[a-z0-9.[\]>_:-]+(?:\([^)]*\))?|=?-?[0-9.,]+|\1))#i', $match[3], $expMatch);
preg_match_all('#(?:([+/*%=-])(=?-?[%$][a-z0-9.[\]>_:-]+(?:\([^)]*\))?|=?-?[0-9.,]+|\1))#i', $match[3], $expMatch);
foreach($expMatch[1] as $k=>$operator)
{
......@@ -1507,6 +1577,10 @@ class DwooCompiler implements DwooICompiler
{
$output = '('.$output.' '.$operator.' '.$this->parseVar($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression').')';
}
elseif(substr($expMatch[2][$k], 0, 1) === '%')
{
$output = '('.$output.' '.$operator.' '.$this->parseConst($expMatch[2][$k], 0, strlen($expMatch[2][$k]), false, 'expression').')';
}
elseif(!empty($expMatch[2][$k]))
$output = '('.$output.' '.$operator.' '.str_replace(',', '.', $expMatch[2][$k]).')';
else
......@@ -1594,16 +1668,9 @@ class DwooCompiler implements DwooICompiler
else
$output = '(isset('.$key.')?'.$key.':null)';
}
elseif(preg_match('#dwoo\.const\.([a-z0-9_:-]+)#i', $key, $m))
elseif(preg_match('#dwoo\.const\.([a-z0-9_:]+)#i', $key, $m))
{
if($this->securityPolicy !== null && $this->securityPolicy->getConstantHandling() === DwooSecurityPolicy::CONST_DISALLOW)
return 'null';
if(strpos($m[1], ':') !== false)
$output = 'constant("'.$m[1].'")';
else
$output = $m[1];
if($curBlock !== 'root')
$output = '(defined("'.$m[1].'") ? '.$output.' : null)';
return $this->parseConstKey($m[1], $curBlock);
}
elseif($this->scope !== null)
{
......@@ -1996,8 +2063,13 @@ class DwooCompiler implements DwooICompiler
if(is_array($p) && is_array($p[1]))
$state |= 2;
else
{
if($state === 2 && preg_match('#^(["\'])(.+?)\1$#', $p[0], $m))
$params[$k] = array($m[2], array('true', 'true'));
else
$state |= 1;
}
}
if($state === 3)
$this->errors[] = 'A function can not have named AND un-named parameters in : '.$cmdstr;
}
......@@ -2043,7 +2115,7 @@ class DwooCompiler implements DwooICompiler
if(is_array($callback))
{
if(is_object($callback[0]))
$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->customPlugins[\''.$func.'\'][0], \''.$callback[1].'\'), array('.$params.'))';
$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array('.$params.'))';
else
$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array(\''.$callback[0].'\', \''.$callback[1].'\'), array('.$params.'))';
}
......@@ -2121,7 +2193,7 @@ class DwooCompiler implements DwooICompiler
if($pluginType & Dwoo::CUSTOM_PLUGIN)
{
if(is_object($callback[0]))
$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->customPlugins[\''.$func.'\'][0], \''.$callback[1].'\'), array('.$params.'))';
$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array($this->plugins[\''.$func.'\'][\'callback\'][0], \''.$callback[1].'\'), array('.$params.'))';
else
$output = ($mapped ? '$this->arrayMap' : 'call_user_func_array').'(array(\''.$callback[0].'\', \''.$callback[1].'\'), array('.$params.'))';
}
......@@ -2429,4 +2501,28 @@ class DwooCompiler implements DwooICompiler
}
}
/**
* dwoo compilation exception class
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* This file is released under the LGPL
* "GNU Lesser General Public License"
* More information can be found here:
* {@link http://www.gnu.org/copyleft/lesser.html}
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @link http://dwoo.org/
* @version 0.3.4
* @date 2008-04-09
* @package Dwoo
*/
class DwooCompilationException extends DwooException
{
}
?>
\ No newline at end of file
......@@ -42,7 +42,8 @@ class DwooData implements DwooIDataProvider
/**
* clears a the entire data or only the given key
*
* @param string $name clears only that value if set or clears the entire data if left null
* @param array|string $name clears only one value if you give a name, multiple values if
* you give an array of names, or the entire data if left null
*/
public function clear($name = null)
{
......
......@@ -79,10 +79,11 @@ interface DwooITemplate
/**
* clears the cached template if it's older than the given time
*
* @param Dwoo $dwoo the dwoo instance that was used to cache that template
* @param int $olderThan minimum time (in seconds) required for the cache to be cleared
* @return bool true if the cache was not present or if it was deleted, false if it remains there
*/
public function clearCache($olderThan=0);
public function clearCache(Dwoo $dwoo, $olderThan = -1);
/**
* returns the compiled template file name
......
......@@ -221,7 +221,7 @@ class DwooTemplateString implements DwooITemplate
return false;
}
// already checked, return cache file
if(isset(self::$cache['cached'][$this->cacheId]) === true)
if(isset(self::$cache['cached'][$this->cacheId]) === true && file_exists($cachedFile))
{
return $cachedFile;
}
......@@ -257,10 +257,11 @@ class DwooTemplateString implements DwooITemplate
/**
* clears the cached template if it's older than the given time
*
* @param Dwoo $dwoo the dwoo instance that was used to cache that template
* @param int $olderThan minimum time (in seconds) required for the cache to be cleared
* @return bool true if the cache was not present or if it was deleted, false if it remains there
*/
public function clearCache($olderThan=0)
public function clearCache(Dwoo $dwoo, $olderThan = -1)
{
$cachedFile = $dwoo->getCacheDir() . $this->cacheId.'.html';
......
......@@ -29,7 +29,7 @@ class DwooPlugin_else extends DwooBlockPlugin implements DwooICompilableBlock
{
$block =& $compiler->getCurrentBlock();
$out = '';
while($block['type'] !== 'if' && $block['type'] !== 'foreach' && $block['type'] !== 'for' && $block['type'] !== 'with')
while($block['type'] !== 'if' && $block['type'] !== 'foreach' && $block['type'] !== 'for' && $block['type'] !== 'with' && $block['type'] !== 'loop')
{
$out .= $compiler->removeTopBlock();
$block =& $compiler->getCurrentBlock();
......
<?php
/**
* TOCOM
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from the use of this software.
*
* This file is released under the LGPL
* "GNU Lesser General Public License"
* More information can be found here:
* {@link http://www.gnu.org/copyleft/lesser.html}
*
* @author Jordi Boggiano <j.boggiano@seld.be>
* @copyright Copyright (c) 2008, Jordi Boggiano
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @link http://dwoo.org/
* @version 0.3.4
* @date 2008-04-09
* @package Dwoo
*/
class DwooPlugin_loop extends DwooBlockPlugin implements DwooICompilableBlock
{
public static $cnt=0;
public function init($from, $name='default')
{
}
public static function preProcessing(DwooCompiler $compiler, array $params, $prepend='', $append='', $type)
{
$params = $compiler->getCompiledParams($params);
$tpl = $compiler->getTemplateSource(true);
// assigns params
$src = $params['from'];
$name = $params['name'];
// evaluates which global variables have to be computed
$varName = '$dwoo.loop.'.trim($name, '"\'').'.';
$shortVarName = '$.loop.'.trim($name, '"\'').'.';
$usesAny = strpos($tpl, $varName) !== false || strpos($tpl, $shortVarName) !== false;
$usesFirst = strpos($tpl, $varName.'first') !== false || strpos($tpl, $shortVarName.'first') !== false;
$usesLast = strpos($tpl, $varName.'last') !== false || strpos($tpl, $shortVarName.'last') !== false;
$usesIndex = $usesFirst || strpos($tpl, $varName.'index') !== false || strpos($tpl, $shortVarName.'index') !== false;
$usesIteration = $usesLast || strpos($tpl, $varName.'iteration') !== false || strpos($tpl, $shortVarName.'iteration') !== false;
$usesShow = strpos($tpl, $varName.'show') !== false || strpos($tpl, $shortVarName.'show') !== false;
$usesTotal = $usesLast || strpos($tpl, $varName.'total') !== false || strpos($tpl, $shortVarName.'total') !== false;
// gets foreach id
$cnt = self::$cnt++;
// builds pre processing output
$out = DwooCompiler::PHP_OPEN . "\n".'$_loop'.$cnt.'_data = '.$src.';';
// adds foreach properties
if($usesAny)
{
$out .= "\n".'$this->globals["loop"]['.$name.'] = array'."\n(";
if($usesIndex) $out .="\n\t".'"index" => 0,';
if($usesIteration) $out .="\n\t".'"iteration" => 1,';
if($usesFirst) $out .="\n\t".'"first" => null,';
if($usesLast) $out .="\n\t".'"last" => null,';
if($usesShow) $out .="\n\t".'"show" => $this->isArray($_loop'.$cnt.'_data, true, true),';
if($usesTotal) $out .="\n\t".'"total" => $this->isArray($_loop'.$cnt.'_data) ? count($_loop'.$cnt.'_data) : 0,';
$out.="\n);\n".'$_loop'.$cnt.'_glob =& $this->globals["loop"]['.$name.'];';
}
// checks if foreach must be looped
$out .= "\n".'if($this->isArray($_loop'.$cnt.'_data, true, true) === true)'."\n{";
// iterates over keys
$out .= "\n\t".'foreach($_loop'.$cnt.'_data as $this->scope["-loop-"])'."\n\t{";
// updates properties
if($usesFirst)
$out .= "\n\t\t".'$_loop'.$cnt.'_glob["first"] = (string) ($_loop'.$cnt.'_glob["index"] === 0);';
if($usesLast)
$out .= "\n\t\t".'$_loop'.$cnt.'_glob["last"] = (string) ($_loop'.$cnt.'_glob["iteration"] === $_loop'.$cnt.'_glob["total"]);';
$out .= "\n\t\t".'$_loop'.$cnt.'_scope = $this->setScope("-loop-");'."\n// -- loop start output\n".DwooCompiler::PHP_CLOSE;
// build post processing output and cache it
$postOut = DwooCompiler::PHP_OPEN . "\n".'// -- loop end output'."\n\t\t".'$this->forceScope($_loop'.$cnt.'_scope);';
// update properties
if($usesIndex)
$postOut.="\n\t\t".'$_loop'.$cnt.'_glob["index"]+=1;';
if($usesIteration)
$postOut.="\n\t\t".'$_loop'.$cnt.'_glob["iteration"]+=1;';
// end loop
$postOut .= "\n\t}\n}\n";
// get block params and save the post-processing output already
$currentBlock =& $compiler->getCurrentBlock();
$currentBlock['params']['postOutput'] = $postOut . DwooCompiler::PHP_CLOSE;
return $out;
}
public static function postProcessing(DwooCompiler $compiler, array $params, $prepend='', $append='')
{
return $params['postOutput'];
}
}
?>
\ No newline at end of file
......@@ -31,14 +31,12 @@ class DwooPlugin_with extends DwooBlockPlugin implements DwooICompilableBlock
$rparams = $compiler->getRealParams($params);
$cparams = $compiler->getCompiledParams($params);
$c = $rparams['var'];
$compiler->setScope($c);
$compiler->setScope($rparams['var']);
$params =& $compiler->getCurrentBlock();
$params['params']['postOutput'] = DwooCompiler::PHP_OPEN."\n// -- end with output\n".'$this->forceScope($_with'.(self::$cnt).');'."\n}\n".DwooCompiler::PHP_CLOSE;
return DwooCompiler::PHP_OPEN.'if('.$cparams['var'].')'."\n{\n".'$_with'.(self::$cnt++).' = $this->setScope("'.$c.'");'."\n// -- start with output\n".DwooCompiler::PHP_CLOSE;
return DwooCompiler::PHP_OPEN.'if('.$cparams['var'].')'."\n{\n".'$_with'.(self::$cnt++).' = $this->setScope("'.$rparams['var'].'");'."\n// -- start with output\n".DwooCompiler::PHP_CLOSE;
}
public static function postProcessing(DwooCompiler $compiler, array $params, $prepend='', $append='')
......
......@@ -51,8 +51,8 @@ class DwooPlugin_dump extends DwooPlugin
{
$out = '';
foreach ($var as $i=>$v) {
if (is_array($v)) {
$out .= $i;
if (is_array($v) || (is_object($v) && $v instanceof Iterator)) {
$out .= $i.' ('.(is_array($v) ? 'array':'object:'.get_class($v)).')';
if($v===$scope) {
$out .= ' (current scope):<div style="background:#ccc;padding-left:20px;">'.$this->export($v, $scope).'</div>';
} else {
......@@ -68,7 +68,7 @@ class DwooPlugin_dump extends DwooPlugin
protected function exportVar($i, $v)
{
if (is_string($v) || is_bool($v) || is_numeric($v)) {
return $i.var_export($v, true).'<br />';
return $i.htmlentities(var_export($v, true)).'<br />';
} elseif (is_null($v)) {
return $i.'null<br />';
} elseif (is_object($v)) {
......@@ -76,7 +76,7 @@ class DwooPlugin_dump extends DwooPlugin
} elseif (is_resource($v)) {
return $i.'resource('.get_resource_type($v).')<br />';
} else {
return $i.var_export($v, true).'<br />';
return $i.htmlentities(var_export($v, true)).'<br />';
}
}
}
......
......@@ -31,7 +31,8 @@ function DwooPlugin_include(Dwoo $dwoo, $file, $cache_time = null, $cache_id = n
}
else
{
$resource = 'file';
// get the current template's resource
$resource = $dwoo->getCurrentTemplate()->getResourceName();
$identifier = $file;
}
......
......@@ -31,6 +31,51 @@ class BlockTests extends PHPUnit_Framework_TestCase
$fixCall->init('');
}
public function testExtends()
{
$tpl = new DwooTemplateFile(dirname(__FILE__).DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'extend1.html');
$tpl->forceCompilation();
$this->assertThat($this->dwoo->get($tpl, array(), $this->compiler), new DwooConstraintStringEquals("foo
child1
toplevelContent1
bar
toplevelContent2
baz"));
}
public function testNonExtendedBlocksFromParent()
{
$tpl = new DwooTemplateFile(dirname(__FILE__).DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'toplevel.html');
$tpl->forceCompilation();
$this->assertThat($this->dwoo->get($tpl, array(), $this->compiler), new DwooConstraintStringEquals("foo
toplevelContent1
bar
toplevelContent2
baz"));
// fixes the init call not being called (which is normal)
$fixCall = new DwooPlugin_block($this->dwoo);
$fixCall->init('');
}
public function testExtendsMultiple()
{
$tpl = new DwooTemplateFile(dirname(__FILE__).DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'extend2.html');
$tpl->forceCompilation();
$this->assertThat($this->dwoo->get($tpl, array('foo'=>'bar'), $this->compiler), new DwooConstraintStringEquals("foo
child1
toplevelContent1child2
bar
FOObartoplevelContent2
baz"));
}
public function testIf()
{
$tpl = new DwooTemplateString('{if "BAR"==reverse($foo|reverse|upper)}true{/if}');
......@@ -224,6 +269,30 @@ class BlockTests extends PHPUnit_Framework_TestCase
$this->assertEquals('bar', $this->dwoo->get($tpl, array(), $this->compiler));
}
public function testLoop()
{
$tpl = new DwooTemplateString('{loop $foo}{$.loop.default.index}>{$0}/{$1}{/loop}');
$tpl->forceCompilation();
$this->assertEquals('0>a/b1>c/d', $this->dwoo->get($tpl, array('foo'=>array(array('a','b'), array('c','d'))) , $this->compiler));
// fixes the init call not being called (which is normal)
$fixCall = new DwooPlugin_loop($this->dwoo);
$fixCall->init('');
}
public function testLoopElse()
{
$tpl = new DwooTemplateString('{loop $foo}{$.loop.default.index}>{$0}/{$1}{else}MOO{/loop}');
$tpl->forceCompilation();
$this->assertEquals('MOO', $this->dwoo->get($tpl, array() , $this->compiler));
// fixes the init call not being called (which is normal)
$fixCall = new DwooPlugin_loop($this->dwoo);
$fixCall->init('');
}
public function testTextFormat()
{
$tpl = new DwooTemplateString('aa{textformat wrap=10}hello world is so unoriginal but hey.. {textformat wrap=4}a a a a a a{/textformat}it works.{/textformat}bb');
......
<?php
require_once dirname(dirname(__FILE__)).'/DwooCompiler.php';
class CallTests extends PHPUnit_Framework_TestCase
{
protected $compiler;
protected $dwoo;
public function __construct()
{
// extend this class and override this in your constructor to test a modded compiler
$this->compiler = new DwooCompiler();
$this->dwoo = new Dwoo();
}
public function testCustomFunctionPlugin()
{
$this->dwoo->addPlugin('test', 'plugin_custom_name');
$tpl = new DwooTemplateString('{test "xxx"}');
$tpl->forceCompilation();
$this->assertEquals('xxxbar', $this->dwoo->get($tpl, array(), $this->compiler));
$this->dwoo->removePlugin('test');
}
public function testHalfCustomClassPluginByClassMethodCallback()
{
$this->dwoo->addPlugin('test', array('plugin_half_custom', 'process'));
$tpl = new DwooTemplateString('{test "xxx"}');
$tpl->forceCompilation();
$this->assertEquals('xxxbar', $this->dwoo->get($tpl, array(), $this->compiler));
$this->dwoo->removePlugin('test');
}
public function testFullCustomClassPluginByClassMethodCallback()
{
$this->dwoo->addPlugin('test', array('plugin_full_custom', 'process'));
$tpl = new DwooTemplateString('{test "xxx"}');
$tpl->forceCompilation();
$this->assertEquals('xxxbar', $this->dwoo->get($tpl, array(), $this->compiler));
$this->dwoo->removePlugin('test');
}
public function testCustomClassPluginByClassname()
{
$this->dwoo->addPlugin('test', 'plugin_full_custom');
$tpl = new DwooTemplateString('{test "xxx"}');
$tpl->forceCompilation();
$this->assertEquals('xxxbar', $this->dwoo->get($tpl, array(), $this->compiler));
$this->dwoo->removePlugin('test');
}
public function testCustomObjectPluginByObjectMethodCallback()
{
$this->dwoo->addPlugin('test', array(new plugin_full_custom(), 'process'));
$tpl = new DwooTemplateString('{test "xxx"}');
$tpl->forceCompilation();
$this->assertEquals('xxxbar', $this->dwoo->get($tpl, array(), $this->compiler));
$this->dwoo->removePlugin('test');
}
public function testCustomBlockPluginByClassMethodCallback()
{
$this->dwoo->addPlugin('test', array('blockplugin_custom', 'process'));
$tpl = new DwooTemplateString('{test "xxx"}aaa{/test}');
$tpl->forceCompilation();
$this->assertEquals('xxxbaraaa', $this->dwoo->get($tpl, array(), $this->compiler));
$this->dwoo->removePlugin('test');
}
public function testCustomBlockPluginByClassname()
{
$this->dwoo->addPlugin('test', 'blockplugin_custom');
$tpl = new DwooTemplateString('{test "xxx"}aaa{/test}');
$tpl->forceCompilation();
$this->assertEquals('xxxbaraaa', $this->dwoo->get($tpl, array(), $this->compiler));
$this->dwoo->removePlugin('test');
}
/**
* @expectedException DwooException
*/
public function testCustomInvalidPlugin()
{
$this->dwoo->addPlugin('test', 'sdfmslkfmsle');
}
}
function plugin_custom_name(Dwoo $dwoo, $foo, $bar="bar")
{
return $foo.$bar;
}
class plugin_half_custom extends DwooPlugin
{
public function process($foo, $bar="bar")
{
return $foo.$bar;
}
}
class plugin_full_custom
{
public function process($foo, $bar="bar")
{
return $foo.$bar;
}
}
class blockplugin_custom extends DwooBlockPlugin
{
public function init($foo, $bar="bar")
{
$this->foo = $foo;
$this->bar = $bar;
}
public function process()
{
return $this->foo.$this->bar.$this->buffer;
}
}
?>
\ No newline at end of file
......@@ -175,6 +175,16 @@ class CompilerTests extends PHPUnit_Framework_TestCase
$this->assertEquals(TEST.' '.(Dwoo::FUNC_PLUGIN*Dwoo::BLOCK_PLUGIN), $this->dwoo->get($tpl, array(), $this->compiler));
}
public function testShortConstants()
{
if(!defined('TEST'))
define('TEST', 'Test');
$tpl = new DwooTemplateString('{%TEST} {$dwoo.const.Dwoo::FUNC_PLUGIN*%Dwoo::BLOCK_PLUGIN}');
$tpl->forceCompilation();
$this->assertEquals(TEST.' '.(Dwoo::FUNC_PLUGIN*Dwoo::BLOCK_PLUGIN), $this->dwoo->get($tpl, array(), $this->compiler));
}
public function testAltDelimiters()
{
$tpl = new DwooTemplateString('{"test"} <%"test"%> <%"foo{lol}\%>"%>');
......@@ -260,6 +270,16 @@ class CompilerTests extends PHPUnit_Framework_TestCase
$this->assertEquals("moo8", $this->dwoo->get($tpl, array('foo'=>0), $this->compiler));
}
public function testSetStringValToTrueWhenUsingNamedParams()
{
$this->dwoo->addPlugin('test', create_function('Dwoo $dwoo, $name, $bool=false', 'return $bool ? $name."!" : $name."?";'));
$tpl = new DwooTemplateString('{test name="Name"}{test name="Name" bool}');
$tpl->forceCompilation();
$this->assertEquals("Name?Name!", $this->dwoo->get($tpl, array(), $this->compiler));
$this->dwoo->removePlugin('test');
}
}
class MethodCallsHelper {
......
......@@ -19,6 +19,10 @@ class CoreTests extends PHPUnit_Framework_TestCase
$this->compiler = new DwooCompiler();
$this->dwoo = new Dwoo();
DwooLoader::rebuildClassPathCache(DWOO_DIRECTORY.'plugins', DWOO_COMPILE_DIRECTORY.DIRECTORY_SEPARATOR.'classpath.cache.php');
// fixes the init call not being called (which is normal)
$fixCall = new DwooPlugin_topLevelBlock($this->dwoo);
$fixCall->init('');
}
public function testReadVar()
......@@ -51,6 +55,72 @@ class CoreTests extends PHPUnit_Framework_TestCase
$this->assertEquals('a', $this->dwoo->readParentVar(2, 'bar'));
}
public function testDwooOutput()
{
$tpl = new DwooTemplateString('a');
$tpl->forceCompilation();
ob_start();
$this->dwoo->output($tpl, array());
$output = ob_get_clean();
$this->assertEquals('a', $output);
}
/**
* @expectedException DwooException
*/
public function testDwooGetNonTemplate()
{
$this->dwoo->output(null, array());
}
/**
* @expectedException DwooException
*/
public function testDwooGetNonData()
{
$tpl = new DwooTemplateString('a');
$this->dwoo->get($tpl, null);
}
public function testGetSetSecurityPolicy()
{
$dwoo = new Dwoo();
$policy = new DwooSecurityPolicy();
$policy->setConstantHandling(DwooSecurityPolicy::CONST_ALLOW);
$dwoo->setSecurityPolicy($policy);
$this->assertEquals($policy, $dwoo->getSecurityPolicy());
$this->assertEquals($policy->getConstantHandling(), $dwoo->getSecurityPolicy()->getConstantHandling());
}
/**
* @expectedException DwooException
*/
public function testWrongResourceName()
{
$this->dwoo->getTemplate('sdmlb', 'fookm');
}
public function testIsCached()
{
$tpl = new DwooTemplateString('foo');
$this->assertEquals(false, $this->dwoo->isCached($tpl));
}
public function testClearCache()
{
$cacheDir = $this->dwoo->getCacheDir();
$this->dwoo->clearCache();
file_put_contents($cacheDir.DIRECTORY_SEPARATOR.'junk.html', 'test');
$this->assertEquals(1, $this->dwoo->clearCache());
}
public function testDwooGetFilename()
{
$this->assertEquals('44BAR', $this->dwoo->get(dirname(__FILE__).DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'test.html', array('foo'=>44, 'bar'=>'BAR')));
}
public function testAssignVarInScope()
{
$tpl = new DwooTemplateString('{assign "Yay!" a.b->qux}{$a.b->qux}');
......@@ -126,7 +196,7 @@ class CoreTests extends PHPUnit_Framework_TestCase
$this->dwoo->addResource('file', 'DwooTemplateString', 'Fake');
$this->dwoo->removeResource('file');
$tpl = new DwooTemplateString('{include file="'.DWOO_DIRECTORY.'tests/resources/test.html" foo=3 bar=4}');
$tpl = new DwooTemplateString('{include file="file:'.DWOO_DIRECTORY.'tests/resources/test.html" foo=3 bar=4}');
$tpl->forceCompilation();
$this->assertEquals("34", $this->dwoo->get($tpl, array()));
}
......@@ -147,6 +217,78 @@ class CoreTests extends PHPUnit_Framework_TestCase
$this->assertEquals(null, $tpl->getCompiler());
$this->assertEquals(false, DwooTemplateString::templateFactory($this->dwoo, 'foo', 5));
}
public function testCachedTemplateAndClearCache()
{
$tpl = new DwooTemplateString('foo{$foo}', 10, 'cachetest');
$tpl->forceCompilation();
$this->assertEquals("foo1", $this->dwoo->get($tpl, array('foo'=>1)));
$this->assertEquals(true, $this->dwoo->isCached($tpl));
$this->assertEquals("foo1", $this->dwoo->get($tpl, array('foo'=>1)));
$this->assertEquals(1, $this->dwoo->clearCache(-11));
$this->assertEquals(false, $this->dwoo->isCached($tpl));
}
public function testCachedTemplateAndOutput()
{
$tpl = new DwooTemplateString('foo{$foo}', 10, 'cachetest');
$tpl->forceCompilation();
ob_start();
$this->dwoo->output($tpl, array('foo'=>1));
$cap = ob_get_clean();
$this->assertEquals("foo1", $cap);
$this->assertEquals(true, $this->dwoo->isCached($tpl));
ob_start();
$this->dwoo->output($tpl, array('foo'=>1));
$cap = ob_get_clean();
$this->assertEquals("foo1", $cap);
$this->assertEquals(1, $this->dwoo->clearCache(-11));
}
public function testCachedTemplateWithDwooCache()
{
$dwoo = new Dwoo();
$dwoo->setCacheTime(5);
$tpl = new DwooTemplateString('foo{$foo}bar', null, 'cachetest2');
$tpl->forceCompilation();
$this->assertEquals("foo1bar", $dwoo->get($tpl, array('foo'=>1)));
$this->assertEquals(true, $dwoo->isCached($tpl));
$this->assertEquals("foo1bar", $dwoo->get($tpl, array('foo'=>1)));
$this->assertEquals(1, $dwoo->clearCache(-11));
$this->assertEquals(false, $dwoo->isCached($tpl));
}
public function testClearCacheOnTemplateClass()
{
$dwoo = new Dwoo();
$dwoo->setCacheTime(5);
$tpl = new DwooTemplateString('foo{$foo}bar', null, 'cachetest2');
$tpl->forceCompilation();
$this->assertEquals("foo1bar", $dwoo->get($tpl, array('foo'=>1)));
$this->assertEquals(true, $dwoo->isCached($tpl));
$this->assertEquals("foo1bar", $dwoo->get($tpl, array('foo'=>1)));
$this->assertEquals(false, $tpl->clearCache($dwoo, 1));
$this->assertEquals(true, $tpl->clearCache($dwoo, -1));
$this->assertEquals(false, $dwoo->isCached($tpl));
}
public function testTemplateGetSet()
{
$dwoo = new Dwoo();
$dwoo->setCacheTime(5);
$tpl = new DwooTemplateString('foo');
$tpl2 = new DwooTemplateFile('./resources/test.html');
$this->assertEquals(false, $tpl->getResourceIdentifier());
$this->assertEquals('string', $tpl->getResourceName());
$this->assertEquals('file', $tpl2->getResourceName());
$this->assertEquals(hash('md4','foo'), $tpl->getUid());
}
}
?>
\ No newline at end of file
......@@ -12,14 +12,12 @@ class DataTests extends PHPUnit_Framework_TestCase
// extend this class and override this in your constructor to test a modded compiler
$this->compiler = new DwooCompiler();
$this->dwoo = new Dwoo();
$this->tpl = new DwooTemplateString('{$var}{$var2}{$var3}{$var4}');
$this->tpl->forceCompilation();
}
public function testDwooData()
public function testSetMergeAndClear()
{
// test simple assign
$tpl = new DwooTemplateString('{$var}{$var2}{$var3}{$var4}');
$tpl->forceCompilation();
$data = new DwooData();
$data->setData(array('foo'));
......@@ -31,6 +29,11 @@ class DataTests extends PHPUnit_Framework_TestCase
$data->clear();
$this->assertEquals(array(), $data->getData());
}
public function testAssign()
{
$data = new DwooData();
$data->assign('var', '1');
$data->assign(array('var2'=>'1', 'var3'=>1));
......@@ -38,7 +41,36 @@ class DataTests extends PHPUnit_Framework_TestCase
$data->assignByRef('var4', $ref);
$ref = 1;
$this->assertEquals('1111', $this->dwoo->get($tpl, $data, $this->compiler));
$this->assertEquals('1111', $this->dwoo->get($this->tpl, $data, $this->compiler));
}
public function testClear()
{
$data = new DwooData();
$data->assign(array('var2'=>'1', 'var3'=>1, 'var4'=>5));
$data->clear(array('var2', 'var4'));
$this->assertEquals(array('var3'=>1), $data->getData());
$data->assign('foo', 'moo');
$data->clear('var3');
$this->assertEquals(array('foo'=>'moo'), $data->getData());
}
public function testAppend()
{
$data = new DwooData();
$data->assign('var', 'val');
$data->append('var', 'moo');
$this->assertEquals(array('var'=>array('val','moo')), $data->getData());
$data->assign('var', 'val');
$data->append(array('var'=>'moo', 'var2'=>'bar'));
$this->assertEquals(array('var'=>array('val','moo'), 'var2'=>array('bar')), $data->getData());
}
}
......
......@@ -33,4 +33,26 @@ class DwooTests {
}
}
// Evaluates two strings and ignores differences in line endings (\r\n == \n == \r)
class DwooConstraintStringEquals extends PHPUnit_Framework_Constraint
{
protected $target;
public function __construct($target)
{
$this->target = preg_replace('#(\r\n|\r)#', "\n", $target);
}
public function evaluate($other)
{
$this->other = preg_replace('#(\r\n|\r)#', "\n", $other);
return $this->target == $this->other;
}
public function toString()
{
return 'equals "'.$this->target.'" / "'.$this->other.'"';
}
}
?>
\ No newline at end of file
......@@ -135,6 +135,14 @@ class FuncTests extends PHPUnit_Framework_TestCase
$this->assertEquals("moo", $this->dwoo->get($tpl, array('foo'=>"moo"), $this->compiler));
}
public function testDoEmpty()
{
$tpl = new DwooTemplateString('{do}');
$tpl->forceCompilation();
$this->assertEquals("", $this->dwoo->get($tpl, array('foo'=>"moo"), $this->compiler));
}
public function testEscape()
{
$tpl = new DwooTemplateString('{escape $foo}');
......@@ -196,32 +204,6 @@ class FuncTests extends PHPUnit_Framework_TestCase
$this->assertEquals("moo+baz", $this->dwoo->get($tpl, array('foo'=>'{$test}', 'test'=>'moo'), $this->compiler));
}
public function testExtends()
{
$tpl = new DwooTemplateFile(dirname(__FILE__).DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'extend1.html');
$tpl->forceCompilation();
$this->assertEquals("foo
child1
toplevelContent1
bar
toplevelContent2
baz", $this->dwoo->get($tpl, array(), $this->compiler));
}
public function testExtendsMultiple()
{
$tpl = new DwooTemplateFile(dirname(__FILE__).DIRECTORY_SEPARATOR.'resources'.DIRECTORY_SEPARATOR.'extend2.html');
$tpl->forceCompilation();
$this->assertEquals("foo
child1
toplevelContent1child2
bar
FOObartoplevelContent2
baz", $this->dwoo->get($tpl, array('foo'=>'bar'), $this->compiler));
}
public function testFetch()
{
$tpl = new DwooTemplateString('{fetch file="'.DWOO_DIRECTORY.'tests/resources/test.html"}');
......@@ -232,7 +214,7 @@ baz", $this->dwoo->get($tpl, array('foo'=>'bar'), $this->compiler));
public function testInclude()
{
$tpl = new DwooTemplateString('{include file=\''.DWOO_DIRECTORY.'tests/resources/test.html\' foo=$a bar=$b}');
$tpl = new DwooTemplateString('{include file=\'file:'.DWOO_DIRECTORY.'tests/resources/test.html\' foo=$a bar=$b}');
$tpl->forceCompilation();
$this->assertEquals("AB", $this->dwoo->get($tpl, array('a'=>'A', 'b'=>'B')));
......
......@@ -69,6 +69,29 @@ class SecurityTests extends PHPUnit_Framework_TestCase
$this->assertEquals("fooOK", $this->dwoo->get($tpl, array(), $this->compiler));
}
public function testAllowDirectoryGetSet()
{
$old = $this->policy->getAllowedDirectories();
$this->policy->allowDirectory(array('./resources'));
$this->policy->allowDirectory('./temp');
$this->assertEquals(array_merge($old, array(realpath('./resources')=>true, realpath('./temp')=>true)), $this->policy->getAllowedDirectories());
$this->policy->disallowDirectory(array('./resources'));
$this->policy->disallowDirectory('./temp');
$this->assertEquals($old, $this->policy->getAllowedDirectories());
}
public function testAllowPhpGetSet()
{
$old = $this->policy->getAllowedPhpFunctions();
$this->policy->allowPhpFunction(array('a','b'));
$this->policy->allowPhpFunction('c');
$this->assertEquals(array_merge($old, array('a'=>true, 'b'=>true, 'c'=>true)), $this->policy->getAllowedPhpFunctions());
$this->policy->disallowPhpFunction(array('a', 'b'));
$this->policy->disallowPhpFunction('c');
$this->assertEquals($old, $this->policy->getAllowedPhpFunctions());
}
}
?>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment