Merge pull request #37 from cgray/master

Refactor of Quoted Literal String Handling and More tests
This commit is contained in:
Behrooz Shabani 2014-01-20 09:47:59 -08:00
commit 21b3bf9797
3 changed files with 121 additions and 13 deletions

View File

@ -189,7 +189,9 @@ class Context
*/
public function get($variableName, $strict = false)
{
//Need to clean up
if ($variableName instanceof \Handlebars\String) {
return (string)$variableName;
}
$variableName = trim($variableName);
$level = 0;
while (substr($variableName, 0, 3) == '../') {
@ -217,7 +219,6 @@ class Context
'can not find variable in context'
);
}
return '';
} elseif ($variableName == '.' || $variableName == 'this') {
return $current;
@ -225,12 +226,6 @@ class Context
$current = $this->lastIndex();
} elseif ($variableName == '@key') {
$current = $this->lastKey();
} elseif ($variableName[0] == "'" || $variableName[0] == '"') {
if ($variableName[0] == substr($variableName, -1) && strlen($variableName) > 2) {
$current = substr($variableName, 1, strlen($variableName) -2);
} else {
throw new \RuntimeException("Malformed string: ".$variableName);
}
} else {
$chunks = explode('.', $variableName);
foreach ($chunks as $chunk) {

View File

@ -430,10 +430,22 @@ class Template
*/
public function parseArguments($string)
{
$parts = array();
preg_match_all('#(?<!\\\\)("|\')(?:[^\\\\]|\\\\.)*?\1|\S+#s', $string, $parts);
$parts = isset($parts[0])?$parts[0]:array();
$parts = array_map("stripcslashes", $parts);
return $parts;
$args = array();
preg_match_all('#(?<!\\\\)("|\')(?:[^\\\\]|\\\\.)*?\1|\S+#s', $string, $args);
$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)));
} else {
throw new \RuntimeException("Malformed string: ".$args);
}
}
}
return $args;
}
}

View File

@ -89,6 +89,21 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
'{{data.length}}',
array("data"=> (object)array(1,2,3,4)),
''
),
array(
'{{data.length}}',
array("data"=>array("length"=>"15 inches", "test","test","test")),
"15 inches"
),
array(
'{{data.0}}',
array("data" => array(1,2,3,4)),
'1'
),
array(
'{{data.property.3}}',
array("data"=>array("property"=>array(1,2,3,4))),
'4'
)
);
}
@ -472,5 +487,91 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
array('data.key.key'),
);
}
/**
* Test for proper handling of the length property
**/
public function testArrayLengthEmulation(){
$data = array("numbers"=>array(1,2,3,4),
"object"=>(object)array("prop1"=>"val1", "prop2"=>"val2"),
"object_with_length_property"=>(object)array("length"=>"15cm")
);
$context = new \Handlebars\Context($data);
// make sure we are getting the array length when given an array
$this->assertEquals($context->get("numbers.length"), 4);
// make sure we are not getting a length when given an object
$this->assertEmpty($context->get("object.length"));
// make sure we can still get the length property when given an object
$this->assertEquals($context->get("object_with_length_property.length"), "15cm");
}
public function argumentParserProvider(){
return array(
array('arg1 arg2', array("arg1","arg2")),
array('"arg1 arg2"', array("arg1 arg2")),
array('arg1 arg2 "arg number 3"', array("arg1","arg2","arg number 3")),
array('arg1 "arg\"2" "\"arg3\""', array("arg1",'arg"2', '"arg3"')),
array("'arg1 arg2'", array("arg1 arg2")),
array("arg1 arg2 'arg number 3'", array("arg1","arg2","arg number 3")),
array('arg1 "arg\"2" "\\\'arg3\\\'"', array("arg1",'arg"2', "'arg3'"))
);
}
/**
* Test Argument Parser
*
* @param string $arg_string argument text
* @param array $arg_ array data
*
* @dataProvider argumentParserProvider
*
* @return void
*/
public function testArgumentParser($arg_string, $expected_array){
$engine = new \Handlebars\Handlebars();
$template = new \Handlebars\Template($engine, null, null);
// get the string version of the arguments array
$args = $template->parseArguments($arg_string);
$args = array_map(function($a){ return (string)$a; }, $args);
$this->assertEquals($args, $expected_array);
}
public function stringLiteralInCustomHelperProvider(){
return array(
array('{{#test2 arg1 "Argument 2"}}', array("arg1"=>"Argument 1"), "Argument 1:Argument 2"),
array('{{#test2 "Argument 1" "Argument 2"}}', array("arg1"=>"Argument 1"), "Argument 1:Argument 2"),
array('{{#test2 "Argument 1" arg2}}', array("arg2"=>"Argument 2"), "Argument 1:Argument 2")
);
}
/**
* Test String literals in the context of a helper
*
* @param string $template template text
* @param array $data context data
* @param string $results The Expected Results
*
* @dataProvider stringLiteralInCustomHelperProvider
*
* @return void
*/
public function testStringLiteralInCustomHelper($template, $data, $results){
$engine = new \Handlebars\Handlebars();
$engine->addHelper('test2', function ($template, $context, $args) {
$args = $template->parseArguments($args);
$args = array_map(function ($a) use ($context) {return $context->get($a);}, $args);
return implode(':', $args);
});
$res = $engine->render($template, $data);
$this->assertEquals($res, $results);
}
public function testString(){
$string = new \Handlebars\String("Hello World");
$this->assertEquals((string)$string, "Hello World");
}
}