Merge pull request #51 from Mibew/each_special_variables

Each special variables
This commit is contained in:
Behrooz Shabani 2014-02-25 22:40:26 +03:30
commit 3514a2b151
4 changed files with 83 additions and 59 deletions

View File

@ -65,6 +65,12 @@ class Context
*/
protected $key = array();
/**
* @var array Special variables stack for sections. Each stack element can
* contain elements with "@index", "@key", "@first" and "@last" keys.
*/
protected $specialVariables = array();
/**
* Mustache rendering Context constructor.
*
@ -90,27 +96,17 @@ class Context
}
/**
* Push an Index onto the index stack
* Push an array of special variables to stack.
*
* @param integer $index Index of the current section item.
* @param array $variables An associative array of special variables.
*
* @return void
*/
public function pushIndex($index)
{
array_push($this->index, $index);
}
/**
* Push a Key onto the key stack
*
* @param string $key Key of the current object property.
*
* @return void
* @see \Handlebars\Context::$specialVariables
*/
public function pushKey($key)
public function pushSpecialVariables($variables)
{
array_push($this->key, $key);
array_push($this->specialVariables, $variables);
}
/**
@ -124,23 +120,15 @@ class Context
}
/**
* Pop the last index from the stack.
* Pop the last special variables set from the stack.
*
* @return int Last index
*/
public function popIndex()
{
return array_pop($this->index);
}
/**
* Pop the last key from the stack.
* @return array Associative array of special variables.
*
* @return string Last key
* @see \Handlebars\Context::$specialVariables
*/
public function popKey()
public function popSpecialVariables()
{
return array_pop($this->key);
return array_pop($this->specialVariables);
}
/**
@ -154,23 +142,15 @@ class Context
}
/**
* Get the index of current section item.
* Get the last special variables set from the stack.
*
* @return mixed Last index
*/
public function lastIndex()
{
return end($this->index);
}
/**
* Get the key of current object property.
* @return array Associative array of special variables.
*
* @return mixed Last key
* @see \Handlebars\Context::$specialVariables
*/
public function lastKey()
public function lastSpecialVariables()
{
return end($this->key);
return end($this->specialVariables);
}
/**
@ -236,10 +216,17 @@ class Context
return '';
} elseif ($variableName == '.' || $variableName == 'this') {
return $current;
} elseif ($variableName == '@index') {
$current = $this->lastIndex();
} elseif ($variableName == '@key') {
$current = $this->lastKey();
} elseif ($variableName[0] == '@') {
$specialVariables = $this->lastSpecialVariables();
if (isset($specialVariables[$variableName])) {
return $specialVariables[$variableName];
} elseif ($strict) {
throw new \InvalidArgumentException(
'can not find variable in context'
);
} else {
return '';
}
} else {
$chunks = $this->_splitVariableName($variableName);
foreach ($chunks as $chunk) {

View File

@ -124,24 +124,27 @@ class Helpers
$template->setStopToken(false);
$buffer = $template->render($context);
} elseif (is_array($tmp) || $tmp instanceof \Traversable) {
$islist = ($tmp instanceof \Generator) || (array_keys($tmp) == range(0, count($tmp) - 1));
$isList = is_array($tmp) && (array_keys($tmp) == range(0, count($tmp) - 1));
$index = 0;
$lastIndex = $isList ? (count($tmp) - 1) : false;
foreach ($tmp as $key => $var) {
if ($islist) {
$context->pushIndex($key);
} else {
$context->pushKey($key);
$specialVariables = array(
'@index' => $index,
'@first' => ($index === 0),
'@last' => ($index === $lastIndex),
);
if (!$isList) {
$specialVariables['@key'] = $key;
}
$context->pushSpecialVariables($specialVariables);
$context->push($var);
$template->setStopToken('else');
$template->rewind();
$buffer .= $template->render($context);
$context->pop();
if ($islist) {
$context->popIndex();
} else {
$context->popKey();
}
$context->popSpecialVariables();
$index++;
}
$template->setStopToken(false);

View File

@ -291,12 +291,25 @@ class Template
}
$buffer = '';
if (is_array($sectionVar) || $sectionVar instanceof \Traversable) {
foreach ($sectionVar as $index => $d) {
$context->pushIndex($index);
$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->popIndex();
$context->popSpecialVariables();
$index++;
}
} elseif (is_object($sectionVar)) {
//Act like with

View File

@ -173,6 +173,26 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
array('data' => array('key1'=>1, 'key2'=>2,)),
'key1=>1key2=>2'
),
array(
'{{#each data}}{{@key}}=>{{this}}{{/each}}',
array('data' => new \ArrayIterator(array('key1'=>1, 'key2'=>2))),
'key1=>1key2=>2'
),
array(
'{{#each data}}{{@index}}=>{{this}},{{/each}}',
array('data' => array('key1'=>1, 'key2'=>2,)),
'0=>1,1=>2,'
),
array(
'{{#each data}}{{#if @first}}the first is {{this}}{{/if}}{{/each}}',
array('data' => array('one', 'two', 'three')),
'the first is one'
),
array(
'{{#each data}}{{#if @last}}the last is {{this}}{{/if}}{{/each}}',
array('data' => array('one', 'two', 'three')),
'the last is three'
),
array(
'{{#each data}}{{this}}{{else}}fail{{/each}}',
array('data' => array(1, 2, 3, 4)),
@ -274,6 +294,8 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('', $engine->render('{{#x}}yes{{/x}}', array ('x' => false)));
$this->assertEquals('yes', $engine->render('{{^x}}yes{{/x}}', array ('x' => false)));
$this->assertEquals('1234', $engine->render('{{#x}}{{this}}{{/x}}', array ('x' => array (1,2,3,4))));
$this->assertEquals('012', $engine->render('{{#x}}{{@index}}{{/x}}', array ('x' => array ('a','b','c'))));
$this->assertEquals('abc', $engine->render('{{#x}}{{@key}}{{/x}}', array ('x' => array ('a'=>1,'b'=>2,'c'=>3))));
$std = new stdClass();
$std->value = 1;
$this->assertEquals('1', $engine->render('{{#x}}{{value}}{{/x}}', array ('x' => $std)));
@ -512,7 +534,6 @@ class HandlebarsTest extends \PHPUnit_Framework_TestCase
$context->pop();
$this->assertEquals('value', $context->get('value'));
$this->assertEquals('value', $context->get('value', true));
$this->assertFalse($context->lastIndex());
}
/**