Fix ArrayAccess priority:

* Methods brump properties and ArrayAccess
 * Properties beat ArrayAccess
 * ArrayAccess beats nothing at all
 * ArrayAccess also beats private properties

Add a test case to verify.

See #178
This commit is contained in:
Justin Hileman
2013-12-06 19:45:28 -08:00
parent 04b016016e
commit 38b6b245b1
2 changed files with 60 additions and 11 deletions
+7 -11
View File
@@ -133,17 +133,13 @@ class Mustache_Context
private function findVariableInStack($id, array $stack) private function findVariableInStack($id, array $stack)
{ {
for ($i = count($stack) - 1; $i >= 0; $i--) { for ($i = count($stack) - 1; $i >= 0; $i--) {
if (is_object($stack[$i])) { if (is_object($stack[$i]) && !($stack[$i] instanceof Closure)) {
if ($stack[$i] instanceof ArrayAccess) { if (method_exists($stack[$i], $id)) {
if (isset($stack[$i][$id])) { return $stack[$i]->$id();
return $stack[$i][$id]; } elseif (isset($stack[$i]->$id)) {
} return $stack[$i]->$id;
} elseif (!($stack[$i] instanceof Closure)) { } elseif ($stack[$i] instanceof ArrayAccess && isset($stack[$i][$id])) {
if (method_exists($stack[$i], $id)) { return $stack[$i][$id];
return $stack[$i]->$id();
} elseif (isset($stack[$i]->$id)) {
return $stack[$i]->$id;
}
} }
} elseif (is_array($stack[$i]) && array_key_exists($id, $stack[$i])) { } elseif (is_array($stack[$i]) && array_key_exists($id, $stack[$i])) {
return $stack[$i][$id]; return $stack[$i][$id];
+53
View File
@@ -109,6 +109,16 @@ class Mustache_Test_ContextTest extends PHPUnit_Framework_TestCase
$this->assertEquals('see', $context->findDot('a.b.c')); $this->assertEquals('see', $context->findDot('a.b.c'));
$this->assertEquals(null, $context->findDot('a.b.c.d')); $this->assertEquals(null, $context->findDot('a.b.c.d'));
} }
public function testAccessorPriority()
{
$context = new Mustache_Context(new Mustache_Test_AllTheThings);
$this->assertEquals('win', $context->find('foo'), 'method beats property');
$this->assertEquals('win', $context->find('bar'), 'property beats ArrayAccess');
$this->assertEquals('win', $context->find('baz'), 'ArrayAccess stands alone');
$this->assertEquals('win', $context->find('qux'), 'ArrayAccess beats private property');
}
} }
class Mustache_Test_TestDummy class Mustache_Test_TestDummy
@@ -166,3 +176,46 @@ class Mustache_Test_TestArrayAccess implements ArrayAccess
return isset($this->container[$offset]) ? $this->container[$offset] : null; return isset($this->container[$offset]) ? $this->container[$offset] : null;
} }
} }
class Mustache_Test_AllTheThings implements ArrayAccess
{
public $foo = 'fail';
public $bar = 'win';
private $qux = 'fail';
public function foo()
{
return 'win';
}
public function offsetExists($offset)
{
return true;
}
public function offsetGet($offset)
{
switch ($offset) {
case 'foo':
case 'bar':
return 'fail';
case 'baz':
case 'qux':
return 'win';
default:
return 'lolwhut';
}
}
public function offsetSet($offset, $value)
{
// nada
}
public function offsetUnset($offset)
{
// nada
}
}