FEATURE: Added ArrayList to allow an array of arrays or objects to be handled as a list.

This commit is contained in:
ajshort 2011-05-04 00:06:42 +10:00
parent 577be1e6fc
commit 7e7677bbba
2 changed files with 279 additions and 0 deletions

141
model/ArrayList.php Normal file
View File

@ -0,0 +1,141 @@
<?php
/**
* A list object that wraps around an array of objects or arrays.
*
* @package sapphire
* @subpackage model
*/
class ArrayList extends ViewableData implements SS_List {
/**
* @var array
*/
protected $array;
public function __construct(array $array = array()) {
$this->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];
}
}
}

View File

@ -0,0 +1,138 @@
<?php
/**
* @package sapphire
* @subpackage tests
*/
class ArrayListTest extends SapphireTest {
public function testCount() {
$list = new ArrayList();
$this->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);
}
}