From a55e06f6b55ef7d1e2bb3be6e43c2c7b5b52db49 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Fri, 9 Mar 2012 14:02:37 +1300 Subject: [PATCH] API CHANGE: Introduce SS_Limitable class for adding to SS_Lists that have limit capability. API CHANGE: Deprecated SS_List::getRange() in favour of SS_Limitable::limit(). API CHANGE: Introduce SS_Limitable::limit($limit, $offset = 0) as the only modern way of specifying limits; deprecate all others. --- core/PaginatedList.php | 2 +- forms/TableListField.php | 2 +- forms/gridfield/GridFieldPaginator.php | 16 +++------------- model/ArrayList.php | 23 ++++++++++++++++++++++- model/DataList.php | 16 ++++++++++------ model/DataQuery.php | 4 ++-- model/Limitable.php | 19 +++++++++++++++++++ model/List.php | 9 --------- model/ListDecorator.php | 10 +++++----- model/SQLQuery.php | 8 ++++---- tests/model/ArrayListTest.php | 4 ++-- tests/model/DataListTest.php | 2 +- tests/model/DataObjectTest.php | 16 +++++----------- tests/model/SQLQueryTest.php | 10 ++-------- 14 files changed, 77 insertions(+), 64 deletions(-) create mode 100644 model/Limitable.php diff --git a/core/PaginatedList.php b/core/PaginatedList.php index 779021d6e..6a2718bc4 100644 --- a/core/PaginatedList.php +++ b/core/PaginatedList.php @@ -149,7 +149,7 @@ class PaginatedList extends SS_ListDecorator { */ public function getIterator() { return new IteratorIterator( - $this->list->getRange($this->getPageStart(), $this->pageLength) + $this->list->limit($this->pageLength, $this->getPageStart()) ); } diff --git a/forms/TableListField.php b/forms/TableListField.php index bd20da389..05cc6b5bd 100644 --- a/forms/TableListField.php +++ b/forms/TableListField.php @@ -430,7 +430,7 @@ JS $SQL_start = 0; } - $items = $items->getRange($SQL_start, $SQL_limit); + $items = $items->limit($SQL_limit, $SQL_start); } return $items; diff --git a/forms/gridfield/GridFieldPaginator.php b/forms/gridfield/GridFieldPaginator.php index 7805f227d..76629be09 100755 --- a/forms/gridfield/GridFieldPaginator.php +++ b/forms/gridfield/GridFieldPaginator.php @@ -64,14 +64,14 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu if(!is_int($state->currentPage)) $state->currentPage = 1; - if(!$this->getListPaginatable($dataList)) { + if(!($dataList instanceof SS_Limitable)) { return $dataList; } if(!$state->currentPage) { - return $dataList->getRange(0, (int)$this->itemsPerPage); + return $dataList->limit((int)$this->itemsPerPage); } $startRow = $this->itemsPerPage * ($state->currentPage - 1); - return $dataList->getRange((int)$startRow, (int)$this->itemsPerPage); + return $dataList->limit((int)$this->itemsPerPage, (int)$startRow); } /** @@ -159,14 +159,4 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu return $this->itemsPerPage; } - /** Duck check to see if list support methods we need to paginate */ - protected function getListPaginatable(SS_List $list) { - // If no list yet, not paginatable - if (!$list) return false; - // Check for methods we use - if(!method_exists($list, 'getRange')) return false; - if(!method_exists($list, 'limit')) return false; - // Default it true - return true; - } } diff --git a/model/ArrayList.php b/model/ArrayList.php index 0df9e7c2f..14f01c4b5 100644 --- a/model/ArrayList.php +++ b/model/ArrayList.php @@ -5,7 +5,7 @@ * @package sapphire * @subpackage model */ -class ArrayList extends ViewableData implements SS_List { +class ArrayList extends ViewableData implements SS_List, SS_Limitable { /** * Holds the items in the list @@ -119,6 +119,18 @@ class ArrayList extends ViewableData implements SS_List { * @return ArrayList */ public function getRange($offset, $length) { + Deprecation::notice("3.0", 'getRange($offset, $length) is deprecated. Use limit($length, $offset) instead. Note the new argument order.'); + return $this->limit($length, $offset); + } + + /** + * Get a sub-range of this dataobjectset as an array + * + * @param int $offset + * @param int $length + * @return ArrayList + */ + public function limit($length, $offset = 0) { return new ArrayList(array_slice($this->items, $offset, $length)); } @@ -357,6 +369,15 @@ class ArrayList extends ViewableData implements SS_List { call_user_func_array('array_multisort', $multisortArgs); return $this; } + + /** + * Returns true if the given column can be used to filter the records. + * + * It works by checking the fields available in the first record of the list. + */ + public function canFilterBy($by) { + return array_key_exists($by, $this->first()); + } /** * Filter the list to include items with these charactaristics diff --git a/model/DataList.php b/model/DataList.php index 5e83a5d7a..7ca91002d 100644 --- a/model/DataList.php +++ b/model/DataList.php @@ -6,7 +6,7 @@ * @package sapphire * @subpackage model */ -class DataList extends ViewableData implements SS_List { +class DataList extends ViewableData implements SS_List, SS_Limitable { /** * The DataObject class name that this data list is querying * @@ -145,8 +145,11 @@ class DataList extends ViewableData implements SS_List { * * @param string $limit */ - public function limit($limit) { - $this->dataQuery->limit($limit); + public function limit($limit, $offset = 0) { + if(!is_numeric($limit)) { + Deprecation::notice('3.0', 'Please pass limits as 2 arguments, rather than an array or SQL fragment.'); + } + $this->dataQuery->limit($limit, $offset); return $this; } @@ -545,7 +548,8 @@ class DataList extends ViewableData implements SS_List { * @return DataList */ public function getRange($offset, $length) { - return $this->limit(array('start' => $offset, 'limit' => $length)); + Deprecation::notice("3.0", 'getRange($offset, $length) is deprecated. Use limit($length, $offset) instead. Note the new argument order.'); + return $this->limit($length, $offset); } /** @@ -813,7 +817,7 @@ class DataList extends ViewableData implements SS_List { * @return bool */ public function offsetExists($key) { - return ($this->getRange($key, 1)->First() != null); + return ($this->limit(1,$key)->First() != null); } /** @@ -823,7 +827,7 @@ class DataList extends ViewableData implements SS_List { * @return DataObject */ public function offsetGet($key) { - return $this->getRange($key, 1)->First(); + return $this->limit(1, $key)->First(); } /** diff --git a/model/DataQuery.php b/model/DataQuery.php index a11dca4e0..de6514e5a 100644 --- a/model/DataQuery.php +++ b/model/DataQuery.php @@ -373,9 +373,9 @@ class DataQuery { /** * Set the limit of this query */ - function limit($limit) { + function limit($limit, $offset = 0) { $clone = $this; - $clone->query->limit($limit); + $clone->query->limit($limit, $offset); return $clone; } diff --git a/model/Limitable.php b/model/Limitable.php new file mode 100644 index 000000000..1c0560b66 --- /dev/null +++ b/model/Limitable.php @@ -0,0 +1,19 @@ +list->remove($itemObject); } - public function getRange($offset, $length) { - return $this->list->getRange($offset, $length); - } - public function getIterator() { return $this->list->getIterator(); } @@ -136,6 +132,10 @@ abstract class SS_ListDecorator extends ViewableData implements SS_List { return call_user_func_array(array($this->list, 'filter'), $args); } + public function limit($length, $offset) { + return $this->list->getRange($length, $offset); + } + /** * Exclude the list to not contain items with these charactaristics * diff --git a/model/SQLQuery.php b/model/SQLQuery.php index f818ceff1..c283474a5 100644 --- a/model/SQLQuery.php +++ b/model/SQLQuery.php @@ -252,10 +252,10 @@ class SQLQuery { * @param string|array $limit * @return SQLQuery This instance */ - public function limit($limit) { + public function limit($limit, $offset = 0) { if($limit && is_numeric($limit)) { $this->limit = array( - 'start' => 0, + 'start' => $offset, 'limit' => $limit, ); } else if($limit && is_string($limit)) { @@ -667,7 +667,7 @@ class SQLQuery { function firstRow() { $query = clone $this; $offset = $this->limit ? $this->limit['start'] : 0; - $query->limit(array('start' => $offset, 'limit' => 1)); + $query->limit(1, $offset); return $query; } @@ -677,7 +677,7 @@ class SQLQuery { function lastRow() { $query = clone $this; $offset = $this->limit ? $this->limit['start'] : 0; - $query->limit(array('start' => $this->count() + $offset - 1, 'limit' => 1)); + $query->limit(1, $this->count() + $offset - 1); return $query; } diff --git a/tests/model/ArrayListTest.php b/tests/model/ArrayListTest.php index bf84fff9f..f06f1a312 100644 --- a/tests/model/ArrayListTest.php +++ b/tests/model/ArrayListTest.php @@ -61,11 +61,11 @@ class ArrayListTest extends SapphireTest { )); } - public function testGetRange() { + public function testLimit() { $list = new ArrayList(array( array('Key' => 1), array('Key' => 2), array('Key' => 3) )); - $this->assertEquals($list->getRange(1, 2)->toArray(), array( + $this->assertEquals($list->limit(2,1)->toArray(), array( array('Key' => 2), array('Key' => 3) )); } diff --git a/tests/model/DataListTest.php b/tests/model/DataListTest.php index 86850b26d..bec99455c 100755 --- a/tests/model/DataListTest.php +++ b/tests/model/DataListTest.php @@ -50,7 +50,7 @@ class DataListTest extends SapphireTest { $this->assertEquals(array('Bob', 'Joe', 'Phil'), $list->column('Name')); // We can also restrict the output to a range - $this->assertEquals(array('Joe', 'Phil'), $list->getRange(1,2)->column('Name')); + $this->assertEquals(array('Joe', 'Phil'), $list->limit(2, 1)->column('Name')); } function testDataClass() { diff --git a/tests/model/DataObjectTest.php b/tests/model/DataObjectTest.php index 6e44a1b92..056c8f2c9 100644 --- a/tests/model/DataObjectTest.php +++ b/tests/model/DataObjectTest.php @@ -197,18 +197,12 @@ class DataObjectTest extends SapphireTest { // There's 4 records in total $this->assertEquals(4, $players->count()); - // Testing "## offset ##" syntax - $this->assertEquals(4, $players->limit("20 OFFSET 0")->count()); - $this->assertEquals(0, $players->limit("20 OFFSET 20")->count()); - $this->assertEquals(2, $players->limit("2 OFFSET 0")->count()); - $this->assertEquals(1, $players->limit("5 OFFSET 3")->count()); - // Testing "##, ##" syntax - $this->assertEquals(4, $players->limit("20")->count()); - $this->assertEquals(4, $players->limit("0, 20")->count()); - $this->assertEquals(0, $players->limit("20, 20")->count()); - $this->assertEquals(2, $players->limit("0, 2")->count()); - $this->assertEquals(1, $players->limit("3, 5")->count()); + $this->assertEquals(4, $players->limit(20)->count()); + $this->assertEquals(4, $players->limit(20, 0)->count()); + $this->assertEquals(0, $players->limit(20, 20)->count()); + $this->assertEquals(2, $players->limit(2, 0)->count()); + $this->assertEquals(1, $players->limit(5, 3)->count()); } /** diff --git a/tests/model/SQLQueryTest.php b/tests/model/SQLQueryTest.php index 8d92021b4..556bdef8e 100755 --- a/tests/model/SQLQueryTest.php +++ b/tests/model/SQLQueryTest.php @@ -87,19 +87,13 @@ class SQLQueryTest extends SapphireTest { // numeric limit $query = new SQLQuery(); $query->from[] = "MyTable"; - $query->limit("99"); + $query->limit(99); $this->assertEquals("SELECT * FROM MyTable LIMIT 99", $query->sql()); - // array limit - $query = new SQLQuery(); - $query->from[] = "MyTable"; - $query->limit(array('limit'=>99)); - $this->assertEquals("SELECT * FROM MyTable LIMIT 99", $query->sql()); - // array limit with start (MySQL specific) $query = new SQLQuery(); $query->from[] = "MyTable"; - $query->limit(array('limit'=>99, 'start'=>97)); + $query->limit(99, 97); $this->assertEquals("SELECT * FROM MyTable LIMIT 99 OFFSET 97", $query->sql()); } }