--- /dev/null
+<?php
+
+namespace PFF;
+
+class MultidimensionalArray implements \ArrayAccess
+{
+ private $keys = array();
+ private $storage = array();
+
+ function count()
+ {
+ return count($this->keys);
+ }
+
+ function contains()
+ {
+ return $this->offsetExists(func_get_args());
+ }
+
+ function offsetExists($key)
+ {
+ $key = array_values($key);
+ return false !== array_search($key, $this->keys);
+ }
+
+ function get()
+ {
+ return $this->offsetGet(func_get_args());
+ }
+
+ function offsetGet($key)
+ {
+ $key = array_values($key);
+ $index = array_search($key, $this->keys);
+ if ($index !== false)
+ return $this->storage[$index];
+ else
+ return null;
+ }
+
+ function set()
+ {
+ $key = func_get_args();
+ $value = array_pop($key);
+ $this->offsetSet($key, $value);
+ return $this;
+ }
+
+ function offsetSet($key, $value)
+ {
+ $key = array_values($key);
+ $index = array_search($key, $this->keys);
+ if ($index === false) {
+ $this->keys[] = $key;
+ end($this->keys);
+ $index = key($this->keys);
+ }
+ $this->storage[$index] = $value;
+ }
+
+ function reset()
+ {
+ $this->offsetUnset(func_get_args());
+ return $this;
+ }
+
+ function offsetUnset($key)
+ {
+ $key = array_values($key);
+ $index = array_search($key, $this->keys);
+ if ($index !== false) {
+ unset($this->keys[$index]);
+ unset($this->storage[$index]);
+ }
+ }
+
+ function __debugInfo()
+ {
+ $i = array();
+ foreach ($this->keys as $index => $key) {
+ $i[implode(', ', $key)] = $this->storage[$index];
+ }
+ return $i;
+ }
+
+ public function ensureKeyExists($key, $default=null)
+ {
+ $key = array_values($key);
+ $index = array_search($key, $this->keys);
+ if ($index === false) {
+ $this->keys[] = $key;
+ end($this->keys);
+ $index = key($this->keys);
+ $this->storage[$index] = $default;
+ }
+ return $this;
+ }
+
+ public function pushToKey($key, $value)
+ {
+ $key = array_values($key);
+ $index = array_search($key, $this->keys);
+ if ($index === false) {
+ $this->keys[] = $key;
+ end($this->keys);
+ $index = key($this->keys);
+
+ $this->storage[$index] = array($value);
+ } else {
+ $this->storage[$index][] = $value;
+ }
+ return $this;
+ }
+}
+
--- /dev/null
+<?php
+
+class MultidimensionalArrayTest extends PHPUnit_Framework_TestCase
+{
+ public function testGet()
+ {
+ $arr = new \PFF\MultidimensionalArray;
+ $arr->set('fruit', 'apple', 100);
+ $arr->set('fruit', 'grapefruit', 400);
+ $arr->set('vegetable', 'carrot', 50);
+
+ $this->assertEquals(400, $arr->get('fruit', 'grapefruit'));
+ $this->assertEquals(null, $arr->get('fruit', 'orange'));
+ $this->assertEquals(null, $arr->get('apple', 'fruit'));
+ }
+
+ public function testEnsureKeyExists()
+ {
+ $arr = new \PFF\MultidimensionalArray;
+ $arr->set('fruit', 'apple', 100);
+ $arr->set('fruit', 'grapefruit', 400);
+ $arr->set('vegetable', 'carrot', 50);
+
+ $this->assertEquals(false, $arr->contains('orange'));
+ $arr->ensureKeyExists(array('orange'));
+ $this->assertEquals(true, $arr->contains('orange'));
+ }
+
+ public function testPushToKey()
+ {
+ $arr = new \PFF\MultidimensionalArray;
+ $arr->set('vegetable', 'carrot', array('orange'));
+
+ $arr->pushToKey(array('fruit', 'apple'), 'green')
+ ->pushToKey(array('vegetable', 'carrot'), 'long')
+ ->pushToKey(array('fruit', 'apple'), 'sweet');
+
+ $this->assertEquals(array('green', 'sweet'), $arr->get('fruit', 'apple'));
+ $this->assertEquals(array('orange', 'long'), $arr->get('vegetable', 'carrot'));
+ }
+
+ public function testPop()
+ {
+ $arr = array(
+ 'apple' => 100,
+ 'grapefruit' => 400,
+ 'carrot' => 50,
+ );
+
+ $apple = \PFF\Arr::pop($arr, 'apple');
+ $this->assertEquals(false, array_key_exists('apple', $arr));
+ $this->assertEquals(100, $apple);
+
+ $apple = \PFF\Arr::pop($arr, 'apple');
+ $this->assertEquals(null, $apple);
+
+ $apple = \PFF\Arr::pop($arr, 'apple', 'what?');
+ $this->assertEquals('what?', $apple);
+ }
+}
+