diff --git a/src/Fenom.php b/src/Fenom.php
index e4c0c11..8c52654 100644
--- a/src/Fenom.php
+++ b/src/Fenom.php
@@ -17,7 +17,7 @@ use Fenom\Template;
*/
class Fenom
{
- const VERSION = '1.3';
+ const VERSION = '1.4';
/* Actions */
const INLINE_COMPILER = 1;
@@ -246,10 +246,6 @@ class Fenom
'type' => self::BLOCK_COMPILER,
'open' => 'Fenom\Compiler::autoescapeOpen',
'close' => 'Fenom\Compiler::autoescapeClose'
- ),
- 'unset' => array(
- 'type' => self::INLINE_COMPILER,
- 'parser' => 'Fenom\Compiler::tagUnset'
)
);
@@ -434,18 +430,18 @@ class Fenom
"float_tags" => array()
);
if (method_exists($storage, $compiler . "Open")) {
- $c["open"] = $compiler . "Open";
+ $c["open"] = array($storage, $compiler . "Open");
} else {
throw new \LogicException("Open compiler {$compiler}Open not found");
}
if (method_exists($storage, $compiler . "Close")) {
- $c["close"] = $compiler . "Close";
+ $c["close"] = array($storage, $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;
+ $c["tags"][$tag] = array($storage, "tag" . $tag);
if ($floats && in_array($tag, $floats)) {
$c['float_tags'][$tag] = 1;
}
@@ -544,17 +540,6 @@ class Fenom
return false;
}
- /**
- * @param string $function
- * @param Fenom\Template $template
- * @return bool|string
- * @deprecated
- */
- public function getFunction($function, Template $template = null)
- {
- return $this->getTag($function, $template);
- }
-
/**
* Returns tag info
*
@@ -771,7 +756,6 @@ class Fenom
$fenom = $this; // used in template
$_tpl = include($this->_compile_dir . "/" . $file_name);
/* @var Fenom\Render $_tpl */
-// var_dump($tpl, $_tpl->isValid()); exit;
if (!($this->_options & self::AUTO_RELOAD) || ($this->_options & self::AUTO_RELOAD) && $_tpl->isValid()) {
return $_tpl;
}
diff --git a/src/Fenom/Compiler.php b/src/Fenom/Compiler.php
index 75ca77b..59ef3f0 100644
--- a/src/Fenom/Compiler.php
+++ b/src/Fenom/Compiler.php
@@ -1034,4 +1034,5 @@ class Compiler
{
$scope->tpl->escape = $scope["escape"];
}
+
}
diff --git a/src/Fenom/Error/UnexpectedTokenException.php b/src/Fenom/Error/UnexpectedTokenException.php
index f72ea4b..3087148 100644
--- a/src/Fenom/Error/UnexpectedTokenException.php
+++ b/src/Fenom/Error/UnexpectedTokenException.php
@@ -25,10 +25,6 @@ class UnexpectedTokenException extends \RuntimeException
}
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";
}
diff --git a/src/Fenom/Render.php b/src/Fenom/Render.php
index 468d08a..138af26 100644
--- a/src/Fenom/Render.php
+++ b/src/Fenom/Render.php
@@ -85,6 +85,7 @@ class Render extends \ArrayObject
$this->_fenom = $fenom;
$props += self::$_props;
$this->_name = $props["name"];
+ $this->_base_name = $props["base_name"];
$this->_scm = $props["scm"];
$this->_time = $props["time"];
$this->_depends = $props["depends"];
diff --git a/src/Fenom/Template.php b/src/Fenom/Template.php
index 8030371..ce85a37 100644
--- a/src/Fenom/Template.php
+++ b/src/Fenom/Template.php
@@ -163,7 +163,7 @@ class Template extends Render
{
$this->_name = $name;
$this->_crc = crc32($this->_name);
- if ($provider = strstr($name, ":", true)) {
+ if ($provider = strstr($name, ':', true)) {
$this->_scm = $provider;
$this->_base_name = substr($name, strlen($provider) + 1);
} else {
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 05a6624..629b495 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -114,6 +114,7 @@ class TestCase extends \PHPUnit_Framework_TestCase
* @param string $result expected result.
* @param int $options
* @param bool $dump dump source and result code (for debug)
+ * @return \Fenom\Template
*/
public function exec($code, $vars, $result, $options = 0, $dump = false)
{
@@ -123,6 +124,7 @@ class TestCase extends \PHPUnit_Framework_TestCase
echo "\n========= DUMP BEGIN ===========\n" . $code . "\n--- to ---\n" . $tpl->getBody() . "\n========= DUMP END =============\n";
}
$this->assertSame(Modifier::strip($result), Modifier::strip($tpl->fetch($vars), true), "Test $code");
+ return $tpl;
}
public function execTpl($name, $code, $vars, $result, $dump = false)
@@ -162,9 +164,10 @@ class TestCase extends \PHPUnit_Framework_TestCase
{
$template = $this->fenom->compileCode($tpl);
if ($debug) {
- print_r("$tpl:\n" . $template->getBody());
+ print_r("\nDEBUG $tpl:\n" . $template->getBody());
}
$this->assertSame($result, $template->fetch($this->values));
+ return $template;
}
@@ -271,37 +274,3 @@ class TestCase extends \PHPUnit_Framework_TestCase
);
}
}
-
-class Fake implements \ArrayAccess
-{
- public $vars;
-
- public function offsetExists($offset)
- {
- return true;
- }
-
- public function offsetGet($offset)
- {
- if ($offset == "object") {
- return new self();
- } else {
- return new self($offset);
- }
- }
-
- public function offsetSet($offset, $value)
- {
- $this->vars[$offset] = $value;
- }
-
- public function offsetUnset($offset)
- {
- unset($this->vars[$offset]);
- }
-
- public function proxy()
- {
- return implode(", ", func_get_args());
- }
-}
diff --git a/tests/cases/Fenom/CustomProviderTest.php b/tests/cases/Fenom/CustomProviderTest.php
index 137ead6..483ed1c 100644
--- a/tests/cases/Fenom/CustomProviderTest.php
+++ b/tests/cases/Fenom/CustomProviderTest.php
@@ -14,6 +14,8 @@ class CustomProviderTest extends TestCase
public function testCustom()
{
+ $this->assertTrue($this->fenom->templateExists('my:include.tpl'));
+ $this->assertFalse($this->fenom->templateExists('my:include-none.tpl'));
$this->assertRender("start: {include 'my:include.tpl'}", 'start: include template');
//$this->assertRender("start: {import 'my:macros.tpl' as ops} {ops.add a=3 b=6}");
}
diff --git a/tests/cases/Fenom/TemplateTest.php b/tests/cases/Fenom/TemplateTest.php
index 7dbd658..aec2a94 100644
--- a/tests/cases/Fenom/TemplateTest.php
+++ b/tests/cases/Fenom/TemplateTest.php
@@ -209,6 +209,7 @@ class TemplateTest extends TestCase
array('If: {$a != 5 => 4} end', 'Fenom\Error\CompileException', "Unexpected token '=>'"),
array('If: {$a + (*6)} end', 'Fenom\Error\CompileException', "Unexpected token '*'"),
array('If: {$a + ( 6} end', 'Fenom\Error\CompileException', "Unexpected end of expression, expect ')'"),
+ array('If: {$a end', 'Fenom\Error\CompileException', "Unclosed tag in line"),
);
}
@@ -266,7 +267,7 @@ class TemplateTest extends TestCase
"username" => "Master",
"email" => "dev@null.net"
);
- $result = 'Include Welcome, Master (dev@null.net) template';
+ $result = 'Include Welcome, Master (dev@null.net) template';
return array(
array('Include {insert "welcome.tpl"} template', $a, $result),
array("Include {insert 'welcome.tpl'} template", $a, $result),
@@ -684,6 +685,7 @@ class TemplateTest extends TestCase
array('{if null is set} block1 {else} block2 {/if}', 'block2'),
array('{if 0 is empty} block1 {else} block2 {/if}', 'block1'),
array('{if "" is empty} block1 {else} block2 {/if}', 'block1'),
+ array('{if [] is empty} block1 {else} block2 {/if}', 'block1'),
array('{if "data" is empty} block1 {else} block2 {/if}', 'block2'),
array('{if time() is not empty} block1 {else} block2 {/if}', 'block1'),
// is empty
@@ -700,8 +702,10 @@ class TemplateTest extends TestCase
// event, odd
array('{if $one is odd} block1 {else} block2 {/if}', 'block1'),
array('{if $one is even} block1 {else} block2 {/if}', 'block2'),
+ array('{if ($one + 1) is even} block1 {else} block2 {/if}', 'block1'),
array('{if $two is even} block1 {else} block2 {/if}', 'block1'),
array('{if $two is odd} block1 {else} block2 {/if}', 'block2'),
+ array('{if ($two+1) is odd} block1 {else} block2 {/if}', 'block1'),
// template
array('{if "welcome.tpl" is template} block1 {else} block2 {/if}', 'block1'),
array('{if "welcome2.tpl" is template} block1 {else} block2 {/if}', 'block2'),
@@ -754,13 +758,19 @@ class TemplateTest extends TestCase
array('{$.get.one?}', '1'),
array('{$.get.one is set}', '1'),
array('{$.get.two is empty}', '1'),
+
+ array('{$.version}', Fenom::VERSION),
+ array('{$.tpl?}', '1'),
+ array('{$.tpl.name}', 'runtime.tpl'),
+ array('{$.tpl.time}', '0'),
+ array('{$.tpl.schema}', ''),
);
}
public function _testSandbox()
{
try {
- var_dump($this->fenom->setOptions(Fenom::FORCE_VERIFY)->compileCode('{if $unexist} block1 {else} block2 {/if}')->getBody());
+ var_dump($this->fenom->setOptions(Fenom::FORCE_VERIFY)->addFilter(function ($txt) {return $txt;})->compileCode('- -')->fetch(['a' => 1]));
} catch (\Exception $e) {
print_r($e->getMessage() . "\n" . $e->getTraceAsString());
}
@@ -839,7 +849,11 @@ class TemplateTest extends TestCase
*/
public function testInsert($code, $vars, $result)
{
- $this->exec($code, $vars, $result);
+ $this->values = $vars;
+ $this->tpl("insert.tpl", $code);
+ $tpl = $this->fenom->getTemplate('insert.tpl');
+ $this->assertSame($result, $tpl->fetch($vars));
+ $this->assertTrue($tpl->isValid());
}
/**
diff --git a/tests/cases/Fenom/TokenizerTest.php b/tests/cases/Fenom/TokenizerTest.php
index ff656af..5fbfb42 100644
--- a/tests/cases/Fenom/TokenizerTest.php
+++ b/tests/cases/Fenom/TokenizerTest.php
@@ -1,5 +1,6 @@
assertSame("sin", $tokens->getNext($tokens::MACRO_STRING));
$this->assertSame("sin", $tokens->current());
+ $this->assertTrue($tokens->isPrev(":"));
$this->assertSame(T_STRING, $tokens->key());
$this->assertTrue($tokens->is(T_STRING));
$this->assertTrue($tokens->is($tokens::MACRO_STRING));
@@ -58,8 +60,9 @@ class TokenizerTest extends \PHPUnit_Framework_TestCase
$tokens->next();
$this->assertSame("+", $tokens->getNext($tokens::MACRO_BINARY));
- $this->assertSame('sin($x)+tan($x*$t)', $tokens->getSnippetAsString(-4, 6));
$this->assertSame($code, $tokens->getSnippetAsString(-100, 100));
+ $this->assertSame('+', $tokens->getSnippetAsString(100, -100));
+ $this->assertSame('sin($x)+tan($x*$t)', $tokens->getSnippetAsString(-4, 6));
}
public function testSkip()
diff --git a/tests/cases/FenomTest.php b/tests/cases/FenomTest.php
index 1810718..00ba02e 100644
--- a/tests/cases/FenomTest.php
+++ b/tests/cases/FenomTest.php
@@ -21,13 +21,26 @@ class FenomTest extends \Fenom\TestCase
}
public function testCreating() {
- $time = $this->tpl('template1.tpl', 'Template 1 a');
- Fenom::factory(FENOM_RESOURCES . '/template', FENOM_RESOURCES . '/compile');
- $fenom = new Fenom($provider =new \Fenom\Provider(FENOM_RESOURCES . '/template'), FENOM_RESOURCES . '/compile', Fenom::AUTO_ESCAPE);
- $this->assertInstanceOf('Fenom\Template', $tpl = $fenom->getTemplate('template1.tpl'));
+ $time = $this->tpl('temp.tpl', 'Template 1 a');
+ $fenom = new Fenom($provider = new \Fenom\Provider(FENOM_RESOURCES . '/template'));
+ $fenom->setCompileDir(FENOM_RESOURCES . '/compile');
+ $this->assertInstanceOf('Fenom\Template', $tpl = $fenom->getTemplate('temp.tpl'));
$this->assertSame($provider, $tpl->getProvider());
- $this->assertSame('template1.tpl', $tpl->getBaseName());
+ $this->assertSame('temp.tpl', $tpl->getBaseName());
+ $this->assertSame('temp.tpl', $tpl->getName());
$this->assertSame($time, $tpl->getTime());
+ $fenom->clearAllCompiles();
+ }
+
+ public function testFactory() {
+ $time = $this->tpl('temp.tpl', 'Template 1 a');
+ $fenom = Fenom::factory($provider = new \Fenom\Provider(FENOM_RESOURCES . '/template'), FENOM_RESOURCES . '/compile', Fenom::AUTO_ESCAPE);
+ $this->assertInstanceOf('Fenom\Template', $tpl = $fenom->getTemplate('temp.tpl'));
+ $this->assertSame($provider, $tpl->getProvider());
+ $this->assertSame('temp.tpl', $tpl->getBaseName());
+ $this->assertSame('temp.tpl', $tpl->getName());
+ $this->assertSame($time, $tpl->getTime());
+ $fenom->clearAllCompiles();
}
public function testCompileFile()
@@ -146,6 +159,48 @@ class FenomTest extends \Fenom\TestCase
return "|--- $text ---|";
});
- $this->assertSame('+++ |--- == hello ---||--- world == ---| +++', $this->fenom->compileCode('hello {var $user} god {/var} world')->fetch(array()));
+ $this->assertSame('+++ |--- == hello ---||--- world == ---| +++', $this->fenom->compileCode('hello {var $user} misterio {/var} world')->fetch(array()));
+ $this->assertSame('+++ |--- == hello ---||--- world == ---| +++', $this->fenom->compileCode('hello {var $user} {/var} world')->fetch(array()));
}
-}
\ No newline at end of file
+
+ public function testAddInlineCompilerSmart() {
+ $this->fenom->addCompilerSmart('SayA','TestTags');
+ $this->tpl('inline_compiler.tpl', 'I just {SayA}.');
+ $this->assertSame('I just Say A.', $this->fenom->fetch('inline_compiler.tpl', array()));
+ }
+
+ public function testAddBlockCompilerSmart() {
+ $this->fenom->addBlockCompilerSmart('SayBlock', 'TestTags', array('SaySomething'), array('SaySomething'));
+ $this->tpl('block_compiler.tpl', '{SayBlock} and {SaySomething}. It is all, {/SayBlock}');
+ $this->assertSame('Start saying and say blah-blah-blah. It is all, Stop saying',
+ $this->fenom->fetch('block_compiler.tpl', array()));
+ }
+
+ public function testAddFunctions() {
+ $this->fenom->setOptions(Fenom::DENY_NATIVE_FUNCS);
+ $this->assertFalse($this->fenom->isAllowedFunction('substr'));
+ $this->fenom->addAllowedFunctions(array('substr'));
+ $this->assertTrue($this->fenom->isAllowedFunction('substr'));
+ }
+}
+
+
+
+class TestTags {
+
+ public static function tagSayA() {
+ return 'echo "Say A"';
+ }
+
+ public static function SayBlockOpen() {
+ return 'echo "Start saying"';
+ }
+
+ public static function tagSaySomething() {
+ return 'echo "say blah-blah-blah"';
+ }
+
+ public static function SayBlockClose() {
+ return 'echo "Stop saying"';
+ }
+}