diff --git a/model/ArrayList.php b/model/ArrayList.php new file mode 100644 index 000000000..e05e3dff3 --- /dev/null +++ b/model/ArrayList.php @@ -0,0 +1,141 @@ +array = $array; + parent::__construct(); + } + + public function count() { + return count($this->array); + } + + public function getIterator() { + return new ArrayIterator($this->array); + } + + public function toArray() { + return $this->array; + } + + public function toNestedArray() { + $result = array(); + + foreach ($this->array as $item) { + if (is_object($item)) { + if (method_exists($item, 'toMap')) { + $result[] = $item->toMap(); + } else { + $result[] = (array) $item; + } + } else { + $result[] = $item; + } + } + + return $result; + } + + public function getRange($offset, $length) { + return array_slice($this->array, $offset, $length); + } + + public function add($item) { + $this->array[] = $item; + } + + public function remove($item) { + foreach ($this->array as $key => $value) { + if ($item === $value) unset($this->array[$key]); + } + } + + public function first() { + return reset($this->array); + } + + public function last() { + return end($this->array); + } + + public function map($keyfield, $titlefield) { + $map = array(); + foreach ($this->array as $item) { + $map[$this->extract($item, $keyfield)] = $this->extract($item, $titlefield); + } + return $map; + } + + public function find($key, $value) { + foreach ($this->array as $item) { + if ($this->extract($item, $key) == $value) return $item; + } + } + + public function column($field) { + $result = array(); + foreach ($this->array as $item) { + $result[] = $this->extract($item, $field); + } + return $result; + } + + public function canSortBy($by) { + return true; + } + + public function sort($by, $dir = 'ASC') { + $sorts = array(); + $dir = strtoupper($dir) == 'DESC' ? SORT_DESC : SORT_ASC; + + foreach ($this->array as $item) { + $sorts[] = $this->extract($item, $by); + } + + array_multisort($sorts, $dir, $this->array); + } + + public function offsetExists($offset) { + return array_key_exists($offset, $this->array); + } + + public function offsetGet($offset) { + if ($this->offsetExists($offset)) return $this->array[$offset]; + } + + public function offsetSet($offset, $value) { + $this->array[$offset] = $value; + } + + public function offsetUnset($offset) { + unset($this->array[$offset]); + } + + /** + * Extracts a value from an item in the list, where the item is either an + * object or array. + * + * @param array|object $item + * @param string $key + * @return mixed + */ + protected function extract($item, $key) { + if (is_object($item)) { + return $item->$key; + } else { + if (array_key_exists($key, $item)) return $item[$key]; + } + } + +} \ No newline at end of file diff --git a/tests/model/ArrayListTest.php b/tests/model/ArrayListTest.php new file mode 100644 index 000000000..c8ba216f2 --- /dev/null +++ b/tests/model/ArrayListTest.php @@ -0,0 +1,138 @@ +assertEquals(0, $list->count()); + $list = new ArrayList(array(1, 2, 3)); + $this->assertEquals(3, $list->count()); + } + + public function testToNestedArray() { + $list = new ArrayList(array( + array('First' => 'FirstFirst', 'Second' => 'FirstSecond'), + (object) array('First' => 'SecondFirst', 'Second' => 'SecondSecond'), + new ArrayListTest_Object('ThirdFirst', 'ThirdSecond') + )); + + $this->assertEquals($list->toNestedArray(), array( + array('First' => 'FirstFirst', 'Second' => 'FirstSecond'), + array('First' => 'SecondFirst', 'Second' => 'SecondSecond'), + array('First' => 'ThirdFirst', 'Second' => 'ThirdSecond') + )); + } + + public function testGetRange() { + $list = new ArrayList(array( + array('Key' => 1), array('Key' => 2), array('Key' => 3) + )); + $this->assertEquals($list->getRange(1, 2), array( + array('Key' => 2), array('Key' => 3) + )); + } + + public function testAddRemove() { + $list = new ArrayList(array( + array('Key' => 1), array('Key' => 2) + )); + + $list->add(array('Key' => 3)); + $this->assertEquals($list->toArray(), array( + array('Key' => 1), array('Key' => 2), array('Key' => 3) + )); + + $list->remove(array('Key' => 2)); + $this->assertEquals(array_values($list->toArray()), array( + array('Key' => 1), array('Key' => 3) + )); + } + + public function testFirstLast() { + $list = new ArrayList(array( + array('Key' => 1), array('Key' => 2), array('Key' => 3) + )); + $this->assertEquals($list->first(), array('Key' => 1)); + $this->assertEquals($list->last(), array('Key' => 3)); + } + + public function testMap() { + $list = new ArrayList(array( + array('ID' => 1, 'Name' => 'Steve',), + (object) array('ID' => 3, 'Name' => 'Bob'), + array('ID' => 5, 'Name' => 'John') + )); + $this->assertEquals($list->map('ID', 'Name'), array( + 1 => 'Steve', + 3 => 'Bob', + 5 => 'John' + )); + } + + public function testFind() { + $list = new ArrayList(array( + array('Name' => 'Steve'), + (object) array('Name' => 'Bob'), + array('Name' => 'John') + )); + $this->assertEquals($list->find('Name', 'Bob'), (object) array( + 'Name' => 'Bob' + )); + } + + public function testColumn() { + $list = new ArrayList(array( + array('Name' => 'Steve'), + (object) array('Name' => 'Bob'), + array('Name' => 'John') + )); + $this->assertEquals($list->column('Name'), array( + 'Steve', 'Bob', 'John' + )); + } + + public function testSort() { + $list = new ArrayList(array( + array('Name' => 'Steve'), + (object) array('Name' => 'Bob'), + array('Name' => 'John') + )); + + $list->sort('Name'); + $this->assertEquals($list->toArray(), array( + (object) array('Name' => 'Bob'), + array('Name' => 'John'), + array('Name' => 'Steve') + )); + + $list->sort('Name', 'DESC'); + $this->assertEquals($list->toArray(), array( + array('Name' => 'Steve'), + array('Name' => 'John'), + (object) array('Name' => 'Bob') + )); + } + +} + +/** + * @ignore + */ +class ArrayListTest_Object { + + public $First; + public $Second; + + public function __construct($first, $second) { + $this->First = $first; + $this->Second = $second; + } + + public function toMap() { + return array('First' => $this->First, 'Second' => $this->Second); + } + +} \ No newline at end of file