mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-09-28 20:29:15 +02:00
FEATURE: Added ArrayList to allow an array of arrays or objects to be handled as a list.
This commit is contained in:
parent
577be1e6fc
commit
7e7677bbba
141
model/ArrayList.php
Normal file
141
model/ArrayList.php
Normal 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
138
tests/model/ArrayListTest.php
Normal file
138
tests/model/ArrayListTest.php
Normal 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user