Some test improvement and add an ArrayLoader

This commit is contained in:
fzerorubigd 2014-02-26 20:26:51 +03:30
parent 3514a2b151
commit 939c58bbee
No known key found for this signature in database
GPG Key ID: D6EE858AF9D2999A
3 changed files with 235 additions and 71 deletions

View File

@ -0,0 +1,76 @@
<?php
/**
* This file is part of Handlebars-php
* Base on mustache-php https://github.com/bobthecow/mustache.php
*
* PHP version 5.3
*
* @category Xamin
* @package Handlebars
* @author fzerorubigd <fzerorubigd@gmail.com>
* @copyright 2014 (c) f0ruD
* @license MIT <http://opensource.org/licenses/MIT>
* @version GIT: $Id$
* @link http://xamin.ir
*/
namespace Handlebars\Loader;
use Handlebars\Loader;
/**
* Handlebars Template array Loader implementation.
*
* @category Xamin
* @package Handlebars
* @author fzerorubigd <fzerorubigd@gmail.com>
* @copyright 2014 (c) f0ruD
* @license MIT <http://opensource.org/licenses/MIT>
* @version Release: @package_version@
* @link http://xamin.ir *
*/
class ArrayLoader implements Loader
{
private $_templates;
/**
* Create a new loader with associative array style
*
* @param array $templates the templates to load
*/
public function __construct(array $templates = array())
{
$this->_templates = $templates;
}
/**
* Add a template to list
*
* @param string $name template name
* @param string $template the template
*
* @return void
*/
public function addTemplate($name, $template)
{
$this->_templates[$name] = $template;
}
/**
* Load a Template by name.
*
* @param string $name template name to load
*
* @throws \RuntimeException
* @return String
*/
public function load($name)
{
if (isset($this->_templates[$name])) {
return $this->_templates[$name];
}
throw new \RuntimeException(
"Can not find the $name template"
);
}
}

View File

@ -243,6 +243,100 @@ class Template
array_push($this->_stack, $topStack);
}
/**
* Process handlebars section style
*
* @param Context $context current context
* @param array $current section node data
*
* @return mixed|string
*/
private function _handlebarsStyleSection(Context $context, $current)
{
$helpers = $this->handlebars->getHelpers();
$sectionName = $current[Tokenizer::NAME];
if (isset($current[Tokenizer::END])) {
$source = substr(
$this->getSource(),
$current[Tokenizer::INDEX],
$current[Tokenizer::END] - $current[Tokenizer::INDEX]
);
} else {
$source = '';
}
$params = array(
$this, //First argument is this template
$context, //Second is current context
$current[Tokenizer::ARGS], //Arguments
$source
);
$return = call_user_func_array($helpers->$sectionName, $params);
if ($return instanceof String) {
return $this->handlebars->loadString($return)->render($context);
} else {
return $return;
}
}
/**
* Process Mustache section style
*
* @param Context $context current context
* @param array $current section node data
*
* @throws \RuntimeException
* @return mixed|string
*/
private function _mustacheStyleSection(Context $context, $current)
{
$sectionName = $current[Tokenizer::NAME];
// fallback to mustache style each/with/for just if there is
// no argument at all.
try {
$sectionVar = $context->get($sectionName, true);
} catch (\InvalidArgumentException $e) {
throw new \RuntimeException(
$sectionName . ' is not registered as a helper'
);
}
$buffer = '';
if (is_array($sectionVar) || $sectionVar instanceof \Traversable) {
$isList = is_array($sectionVar) &&
(array_keys($sectionVar) == range(0, count($sectionVar) - 1));
$index = 0;
$lastIndex = $isList ? (count($sectionVar) - 1) : false;
foreach ($sectionVar as $key => $d) {
$specialVariables = array(
'@index' => $index,
'@first' => ($index === 0),
'@last' => ($index === $lastIndex),
);
if (!$isList) {
$specialVariables['@key'] = $key;
}
$context->pushSpecialVariables($specialVariables);
$context->push($d);
$buffer .= $this->render($context);
$context->pop();
$context->popSpecialVariables();
$index++;
}
} elseif (is_object($sectionVar)) {
//Act like with
$context->push($sectionVar);
$buffer = $this->render($context);
$context->pop();
} elseif ($sectionVar) {
$buffer = $this->render($context);
}
return $buffer;
}
/**
* Process section nodes
*
@ -257,70 +351,9 @@ class Template
$helpers = $this->handlebars->getHelpers();
$sectionName = $current[Tokenizer::NAME];
if ($helpers->has($sectionName)) {
if (isset($current[Tokenizer::END])) {
$source = substr(
$this->getSource(),
$current[Tokenizer::INDEX],
$current[Tokenizer::END] - $current[Tokenizer::INDEX]
);
} else {
$source = '';
}
$params = array(
$this, //First argument is this template
$context, //Second is current context
$current[Tokenizer::ARGS], //Arguments
$source
);
$return = call_user_func_array($helpers->$sectionName, $params);
if ($return instanceof String) {
return $this->handlebars->loadString($return)->render($context);
} else {
return $return;
}
return $this->_handlebarsStyleSection($context, $current);
} elseif (trim($current[Tokenizer::ARGS]) == '') {
// fallback to mustache style each/with/for just if there is
// no argument at all.
try {
$sectionVar = $context->get($sectionName, true);
} catch (\InvalidArgumentException $e) {
throw new \RuntimeException(
$sectionName . ' is not registered as a helper'
);
}
$buffer = '';
if (is_array($sectionVar) || $sectionVar instanceof \Traversable) {
$isList = is_array($sectionVar) && (array_keys($sectionVar) == range(0, count($sectionVar) - 1));
$index = 0;
$lastIndex = $isList ? (count($sectionVar) - 1) : false;
foreach ($sectionVar as $key => $d) {
$specialVariables = array(
'@index' => $index,
'@first' => ($index === 0),
'@last' => ($index === $lastIndex),
);
if (!$isList) {
$specialVariables['@key'] = $key;
}
$context->pushSpecialVariables($specialVariables);
$context->push($d);
$buffer .= $this->render($context);
$context->pop();
$context->popSpecialVariables();
$index++;
}
} elseif (is_object($sectionVar)) {
//Act like with
$context->push($sectionVar);
$buffer = $this->render($context);
$context->pop();
} elseif ($sectionVar) {
$buffer = $this->render($context);
}
return $buffer;
return $this->_mustacheStyleSection($context, $current);
} else {
throw new \RuntimeException(
$sectionName . ' is not registered as a helper'
@ -380,6 +413,7 @@ class Template
$helpers = $this->getEngine()->getHelpers();
// Tokenizer doesn't process the args -if any- so be aware of that
$name = explode(' ', $current[Tokenizer::NAME], 2);
return $helpers->has(reset($name));
}
@ -457,32 +491,34 @@ class Template
return $value;
}
/**
* Break an argument string into an array of strings
*
* @param string $string Argument String as passed to a helper
*
* @throws \RuntimeException
* @return array the argument list as an array
*/
public function parseArguments($string)
{
$args = array();
preg_match_all('#(?:[^\'"\[\]\s]|\[.+?\])+|(?<!\\\\)("|\')(?:[^\\\\]|\\\\.)*?\1|\S+#s', $string, $args);
$args = isset($args[0])?$args[0]:array();
for ($x=0, $argc = count($args); $x<$argc;$x++) {
$args = isset($args[0]) ? $args[0] : array();
for ($x = 0, $argc = count($args); $x < $argc; $x++) {
// check to see if argument is a quoted string literal
if ($args[$x][0] == "'" || $args[$x][0] == '"') {
if ($args[$x][0] === substr($args[$x], -1)) {
// remove enclosing quotes and unescape
$args[$x] = new \Handlebars\String(stripcslashes(substr($args[$x], 1, strlen($args[$x]) -2)));
$args[$x] = new \Handlebars\String(stripcslashes(substr($args[$x], 1, strlen($args[$x]) - 2)));
} else {
throw new \RuntimeException("Malformed string: ".$args);
throw new \RuntimeException("Malformed string: " . $args);
}
}
}
return $args;
}
}

View File

@ -283,6 +283,22 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('<strong>Test</strong>', $engine->render('{{safeStringTest}}', array()));
}
public function testInvalidHelperMustacheStyle()
{
$this->setExpectedException('RuntimeException');
$loader = new \Handlebars\Loader\StringLoader();
$engine = new \Handlebars\Handlebars(array('loader' => $loader));
$engine->render('{{#NOTVALID}}XXX{{/NOTVALID}}', array());
}
public function testInvalidHelper()
{
$this->setExpectedException('RuntimeException');
$loader = new \Handlebars\Loader\StringLoader();
$engine = new \Handlebars\Handlebars(array('loader' => $loader));
$engine->render('{{#NOTVALID argument}}XXX{{/NOTVALID}}', array());
}
/**
* Test mustache style loop and if
*/
@ -412,6 +428,18 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(1, count(glob($path . '/*')));
}
public function testArrayLoader()
{
$loader = new \Handlebars\Loader\ArrayLoader(array('test' => 'HELLO'));
$loader->addTemplate('another', 'GOODBYE');
$engine = new \Handlebars\Handlebars(array('loader' => $loader));
$this->assertEquals($engine->render('test', array()), 'HELLO');
$this->assertEquals($engine->render('another', array()), 'GOODBYE');
$this->setExpectedException('RuntimeException');
$engine->render('invalid-template', array());
}
/**
* Test file system loader
*/
@ -477,6 +505,29 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('test', $engine->render('{{>loader}}', array()));
}
public function testPartial()
{
$loader = new \Handlebars\Loader\StringLoader();
$partialLoader = new \Handlebars\Loader\ArrayLoader(array('test' => '{{key}}', 'bar' => 'its foo'));
$partialAliasses = array('foo' => 'bar');
$engine = new \Handlebars\Handlebars(
array(
'loader' => $loader,
'partials_loader' => $partialLoader,
'partials_alias' => $partialAliasses
)
);
$this->assertEquals('HELLO', $engine->render('{{>test parameter}}', array('parameter' => array('key' => 'HELLO'))));
$this->assertEquals('its foo', $engine->render('{{>foo}}', array()));
$engine->registerPartial('foo-again', 'bar');
$this->assertEquals('its foo', $engine->render('{{>foo-again}}', array()));
$engine->unRegisterPartial('foo-again');
$this->setExpectedException('RuntimeException');
$engine->render('{{>foo-again}}', array());
}
/**
* test variable access
*/
@ -588,11 +639,12 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
array('"arg1.[value 1]" arg2', array("arg1.[value 1]", 'arg2')),
);
}
/**
* Test Argument Parser
*
* @param string $arg_string argument text
* @param array $arg_ array data
* @param $expected_array
*
* @dataProvider argumentParserProvider
*