mirror of
https://github.com/Mibew/handlebars.php.git
synced 2024-11-15 08:44:12 +03:00
Improve arguments parsing
This commit is contained in:
parent
bacde14221
commit
17dc20203b
187
src/Handlebars/Arguments.php
Normal file
187
src/Handlebars/Arguments.php
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* This file is part of Handlebars-php
|
||||||
|
*
|
||||||
|
* PHP version 5.3
|
||||||
|
*
|
||||||
|
* @category Xamin
|
||||||
|
* @package Handlebars
|
||||||
|
* @author Dmitriy Simushev <simushevds@gmail.com>
|
||||||
|
* @copyright 2014 Authors
|
||||||
|
* @license MIT <http://opensource.org/licenses/MIT>
|
||||||
|
* @version GIT: $Id$
|
||||||
|
* @link http://xamin.ir
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Handlebars;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encapsulates helpers arguments.
|
||||||
|
*
|
||||||
|
* @category Xamin
|
||||||
|
* @package Handlebars
|
||||||
|
* @author Dmitriy Simushev <simushevds@gmail.com>
|
||||||
|
* @copyright 2014 Authors
|
||||||
|
* @license MIT <http://opensource.org/licenses/MIT>
|
||||||
|
* @version Release: @package_version@
|
||||||
|
* @link http://xamin.ir
|
||||||
|
*/
|
||||||
|
class Arguments
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* List of named arguments.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $namedArgs = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of positional arguments.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $positionalArgs = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The original arguments string that was used to fill in arguments.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $originalString = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class constructor.
|
||||||
|
*
|
||||||
|
* @param string $args_string Arguments string as passed to a helper.
|
||||||
|
*/
|
||||||
|
public function __construct($args_string = false)
|
||||||
|
{
|
||||||
|
$this->originalString = $args_string;
|
||||||
|
|
||||||
|
if ($args_string) {
|
||||||
|
$this->parse($args_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns string representation of the arguments list.
|
||||||
|
*
|
||||||
|
* This method is here mostly for backward compatibility reasons.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function __toString()
|
||||||
|
{
|
||||||
|
return $this->originalString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of named arguments.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getNamedArguments()
|
||||||
|
{
|
||||||
|
return $this->namedArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of positional arguments.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getPositionalArguments()
|
||||||
|
{
|
||||||
|
return $this->positionalArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Breaks an argument string into arguments and stores them inside the
|
||||||
|
* object.
|
||||||
|
*
|
||||||
|
* @param string $args_string Arguments string as passed to a helper.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws \InvalidArgumentException
|
||||||
|
*/
|
||||||
|
protected function parse($args_string)
|
||||||
|
{
|
||||||
|
$bad_chars = preg_quote(Context::NOT_VALID_NAME_CHARS, '#');
|
||||||
|
$bad_seg_chars = preg_quote(Context::NOT_VALID_SEGMENT_NAME_CHARS, '#');
|
||||||
|
|
||||||
|
$name_chunk = '(?:[^' . $bad_chars . '\s]+)|(?:\[[^' . $bad_seg_chars . ']+\])';
|
||||||
|
$variable_name = '(?:\.\.\/)*(?:(?:' . $name_chunk . ')[\.\/])*(?:' . $name_chunk . ')\.?';
|
||||||
|
$escaped_value = '(?:(?<!\\\\)".*?(?<!\\\\)"|(?<!\\\\)\'.*?(?<!\\\\)\')';
|
||||||
|
$argument_name = $name_chunk;
|
||||||
|
$positional_argument = '#^(' . $variable_name . '|' . $escaped_value . ')#';
|
||||||
|
$named_argument = '#^(' . $argument_name . ')\s*=\s*(' . $escaped_value . '|' . $variable_name . ')#';
|
||||||
|
|
||||||
|
$current_str = trim($args_string);
|
||||||
|
|
||||||
|
// Split arguments string
|
||||||
|
while (strlen($current_str) !== 0) {
|
||||||
|
if (preg_match($named_argument, $current_str, $matches)) {
|
||||||
|
// Named argument found
|
||||||
|
$name = $this->prepareArgumentName($matches[1]);
|
||||||
|
$value = $this->prepareArgumentValue($matches[2]);
|
||||||
|
|
||||||
|
$this->namedArgs[$name] = $value;
|
||||||
|
|
||||||
|
// Remove found argument from arguments string.
|
||||||
|
$current_str = ltrim(substr($current_str, strlen($matches[0])));
|
||||||
|
} elseif (preg_match($positional_argument, $current_str, $matches)) {
|
||||||
|
// A positional argument found. It cannot follow named arguments
|
||||||
|
if (count($this->namedArgs) !== 0) {
|
||||||
|
throw new \InvalidArgumentException('Positional arguments cannot follow named arguments');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->positionalArgs[] = $this->prepareArgumentValue($matches[1]);
|
||||||
|
|
||||||
|
// Remove found argument from arguments string.
|
||||||
|
$current_str = ltrim(substr($current_str, strlen($matches[0])));
|
||||||
|
} else {
|
||||||
|
throw new \InvalidArgumentException('Malformed arguments string');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares argument's value to add to arguments list.
|
||||||
|
*
|
||||||
|
* The method unescapes value and wrap it into \Handlebars\String class if
|
||||||
|
* needed.
|
||||||
|
*
|
||||||
|
* @param string $value Argument's value
|
||||||
|
*
|
||||||
|
* @return string|\Handlebars\String
|
||||||
|
*/
|
||||||
|
protected function prepareArgumentValue($value)
|
||||||
|
{
|
||||||
|
// Check if argument's value is a quoted string literal
|
||||||
|
if ($value[0] == "'" || $value[0] == '"') {
|
||||||
|
// Remove enclosing quotes and unescape
|
||||||
|
$value = new String(stripcslashes(substr($value, 1, -1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares argument's name.
|
||||||
|
*
|
||||||
|
* Remove sections braces if needed.
|
||||||
|
*
|
||||||
|
* @param strign $name Argument's name
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function prepareArgumentName($name)
|
||||||
|
{
|
||||||
|
// Check if argument's name is a segment
|
||||||
|
if ($name[0] == '[') {
|
||||||
|
$name = substr($name, 1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
}
|
@ -590,38 +590,14 @@ class Template
|
|||||||
*/
|
*/
|
||||||
public function parseNamedArguments($string)
|
public function parseNamedArguments($string)
|
||||||
{
|
{
|
||||||
$variableName = '(?:(?:[^\'"\[\]\s]|\[.+?\])+)';
|
if ($string instanceof Arguments) {
|
||||||
$escapedValue = '(?:(?<!\\\\)".*?(?<!\\\\)"|(?<!\\\\)\'.*?(?<!\\\\)\')';
|
// This code is needed only for backward compatibility
|
||||||
|
$args = $string;
|
||||||
// Get list of named arguemnts
|
} else {
|
||||||
$matches = array();
|
$args = new Arguments($string);
|
||||||
preg_match_all(
|
|
||||||
'#(' . $variableName . ')\s*=\s*(' . $escapedValue . '|' . $variableName . ')#',
|
|
||||||
$string,
|
|
||||||
$matches,
|
|
||||||
PREG_SET_ORDER
|
|
||||||
);
|
|
||||||
|
|
||||||
$args = array();
|
|
||||||
for ($x = 0, $c = count($matches); $x < $c; $x++) {
|
|
||||||
$name = $matches[$x][1];
|
|
||||||
$value = $matches[$x][2];
|
|
||||||
|
|
||||||
// Check if argument's name is a segment
|
|
||||||
if ($name[0] == '[') {
|
|
||||||
$name = substr($name, 1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if argument's value is a quoted string literal
|
|
||||||
if ($value[0] == "'" || $value[0] == '"') {
|
|
||||||
// Remove enclosing quotes and unescape
|
|
||||||
$value = new \Handlebars\String(stripcslashes(substr($value, 1, -1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$args[$name] = $value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $args;
|
return $args->getNamedArguments();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -634,23 +610,13 @@ class Template
|
|||||||
*/
|
*/
|
||||||
public function parseArguments($string)
|
public function parseArguments($string)
|
||||||
{
|
{
|
||||||
$args = array();
|
if ($string instanceof Arguments) {
|
||||||
preg_match_all('#(?:[^\'"\[\]\s]|\[.+?\])+|(?<!\\\\)("|\')(?:[^\\\\]|\\\\.)*?\1|\S+#s', $string, $args);
|
// This code is needed only for backward compatibility
|
||||||
$args = isset($args[0]) ? $args[0] : array();
|
$args = $string;
|
||||||
|
} else {
|
||||||
for ($x = 0, $argc = count($args); $x < $argc; $x++) {
|
$args = new Arguments($string);
|
||||||
// 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;
|
return $args->getPositionalArguments();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -983,4 +983,14 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals('good', $engine->render('{{#with b}}{{#if this}}{{../../a}}{{/if}}{{/with}}', array('a' => 'good', 'b' => 'stump')));
|
$this->assertEquals('good', $engine->render('{{#with b}}{{#if this}}{{../../a}}{{/if}}{{/with}}', array('a' => 'good', 'b' => 'stump')));
|
||||||
$this->assertEquals('good', $engine->render('{{#with b}}{{#unless false}}{{../../a}}{{/unless}}{{/with}}', array('a' => 'good', 'b' => 'stump')));
|
$this->assertEquals('good', $engine->render('{{#with b}}{{#unless false}}{{../../a}}{{/unless}}{{/with}}', array('a' => 'good', 'b' => 'stump')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test of Arguments to string conversion.
|
||||||
|
*/
|
||||||
|
public function testArgumentsString()
|
||||||
|
{
|
||||||
|
$argsString = 'foo bar [foo bar] baz="value"';
|
||||||
|
$args = new \Handlebars\Arguments($argsString);
|
||||||
|
$this->assertEquals($argsString, (string)$args);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user