mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-09-17 23:16:04 +02:00
Merge branch 'more-list-interfaces' of https://github.com/silverstripe-scienceninjas/sapphire
This commit is contained in:
commit
83bfe54b01
@ -149,7 +149,7 @@ class PaginatedList extends SS_ListDecorator {
|
|||||||
*/
|
*/
|
||||||
public function getIterator() {
|
public function getIterator() {
|
||||||
return new IteratorIterator(
|
return new IteratorIterator(
|
||||||
$this->list->getRange($this->getPageStart(), $this->pageLength)
|
$this->list->limit($this->pageLength, $this->getPageStart())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,7 +430,7 @@ JS
|
|||||||
$SQL_start = 0;
|
$SQL_start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$items = $items->getRange($SQL_start, $SQL_limit);
|
$items = $items->limit($SQL_limit, $SQL_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $items;
|
return $items;
|
||||||
|
@ -323,7 +323,7 @@ class GridField extends FormField {
|
|||||||
foreach($this->components as $item) {
|
foreach($this->components as $item) {
|
||||||
if($item instanceof GridField_HTMLProvider) {
|
if($item instanceof GridField_HTMLProvider) {
|
||||||
$fragments = $item->getHTMLFragments($this);
|
$fragments = $item->getHTMLFragments($this);
|
||||||
foreach($fragments as $k => $v) {
|
if($fragments) foreach($fragments as $k => $v) {
|
||||||
$k = strtolower($k);
|
$k = strtolower($k);
|
||||||
if(!isset($content[$k])) $content[$k] = "";
|
if(!isset($content[$k])) $content[$k] = "";
|
||||||
$content[$k] .= $v . "\n";
|
$content[$k] .= $v . "\n";
|
||||||
@ -650,7 +650,7 @@ class GridField extends FormField {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(in_array($actionName, array_map('strtolower', $component->getActions($this)))) {
|
if(is_array($component->getActions($this)) && in_array($actionName, array_map('strtolower', $component->getActions($this)))) {
|
||||||
return $component->handleAction($this, $actionName, $args, $data);
|
return $component->handleAction($this, $actionName, $args, $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,10 +132,14 @@ class GridFieldConfig_Base extends GridFieldConfig {
|
|||||||
*/
|
*/
|
||||||
public function __construct($itemsPerPage=null) {
|
public function __construct($itemsPerPage=null) {
|
||||||
$this->addComponent(new GridFieldToolbarHeader());
|
$this->addComponent(new GridFieldToolbarHeader());
|
||||||
$this->addComponent(new GridFieldSortableHeader());
|
$this->addComponent($sort = new GridFieldSortableHeader());
|
||||||
$this->addComponent(new GridFieldFilterHeader());
|
$this->addComponent($filter = new GridFieldFilterHeader());
|
||||||
$this->addComponent(new GridFieldDataColumns());
|
$this->addComponent(new GridFieldDataColumns());
|
||||||
$this->addComponent(new GridFieldPaginator($itemsPerPage));
|
$this->addComponent($pagination = new GridFieldPaginator($itemsPerPage));
|
||||||
|
|
||||||
|
$sort->throwExceptionOnBadDataType(false);
|
||||||
|
$filter->throwExceptionOnBadDataType(false);
|
||||||
|
$pagination->throwExceptionOnBadDataType(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,13 +163,17 @@ class GridFieldConfig_RecordEditor extends GridFieldConfig {
|
|||||||
*/
|
*/
|
||||||
public function __construct($itemsPerPage=null) {
|
public function __construct($itemsPerPage=null) {
|
||||||
$this->addComponent(new GridFieldToolbarHeader());
|
$this->addComponent(new GridFieldToolbarHeader());
|
||||||
$this->addComponent(new GridFieldSortableHeader());
|
$this->addComponent($sort = new GridFieldSortableHeader());
|
||||||
$this->addComponent(new GridFieldFilterHeader());
|
$this->addComponent($filter = new GridFieldFilterHeader());
|
||||||
$this->addComponent(new GridFieldDataColumns());
|
$this->addComponent(new GridFieldDataColumns());
|
||||||
$this->addComponent(new GridFieldEditButton());
|
$this->addComponent(new GridFieldEditButton());
|
||||||
$this->addComponent(new GridFieldDeleteAction());
|
$this->addComponent(new GridFieldDeleteAction());
|
||||||
$this->addComponent(new GridFieldPaginator($itemsPerPage));
|
$this->addComponent($pagination = new GridFieldPaginator($itemsPerPage));
|
||||||
$this->addComponent(new GridFieldDetailForm());
|
$this->addComponent(new GridFieldDetailForm());
|
||||||
|
|
||||||
|
$sort->throwExceptionOnBadDataType(false);
|
||||||
|
$filter->throwExceptionOnBadDataType(false);
|
||||||
|
$pagination->throwExceptionOnBadDataType(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,12 +210,16 @@ class GridFieldConfig_RelationEditor extends GridFieldConfig {
|
|||||||
public function __construct($itemsPerPage=null) {
|
public function __construct($itemsPerPage=null) {
|
||||||
$this->addComponent(new GridFieldToolbarHeader());
|
$this->addComponent(new GridFieldToolbarHeader());
|
||||||
$this->addComponent(new GridFieldAddExistingAutocompleter());
|
$this->addComponent(new GridFieldAddExistingAutocompleter());
|
||||||
$this->addComponent(new GridFieldSortableHeader());
|
$this->addComponent($sort = new GridFieldSortableHeader());
|
||||||
$this->addComponent(new GridFieldFilterHeader());
|
$this->addComponent($filter = new GridFieldFilterHeader());
|
||||||
$this->addComponent(new GridFieldDataColumns());
|
$this->addComponent(new GridFieldDataColumns());
|
||||||
$this->addComponent(new GridFieldEditButton());
|
$this->addComponent(new GridFieldEditButton());
|
||||||
$this->addComponent(new GridFieldDeleteAction(true));
|
$this->addComponent(new GridFieldDeleteAction());
|
||||||
$this->addComponent(new GridFieldPaginator($itemsPerPage));
|
$this->addComponent($pagination = new GridFieldPaginator($itemsPerPage));
|
||||||
$this->addComponent(new GridFieldDetailForm());
|
$this->addComponent(new GridFieldDetailForm());
|
||||||
|
|
||||||
|
$sort->throwExceptionOnBadDataType(false);
|
||||||
|
$filter->throwExceptionOnBadDataType(false);
|
||||||
|
$pagination->throwExceptionOnBadDataType(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,16 +9,53 @@
|
|||||||
*/
|
*/
|
||||||
class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider {
|
class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link throwExceptionOnBadDataType()}
|
||||||
|
*/
|
||||||
|
protected $throwExceptionOnBadDataType = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine what happens when this component is used with a list that isn't {@link SS_Filterable}.
|
||||||
|
*
|
||||||
|
* - true: An exception is thrown
|
||||||
|
* - false: This component will be ignored - it won't make any changes to the GridField.
|
||||||
|
*
|
||||||
|
* By default, this is set to true so that it's clearer what's happening, but the predefined
|
||||||
|
* {@link GridFieldConfig} subclasses set this to false for flexibility.
|
||||||
|
*/
|
||||||
|
public function throwExceptionOnBadDataType($throwExceptionOnBadDataType) {
|
||||||
|
$this->throwExceptionOnBadDataType = $throwExceptionOnBadDataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that this dataList is of the right data type.
|
||||||
|
* Returns false if it's a bad data type, and if appropriate, throws an exception.
|
||||||
|
*/
|
||||||
|
protected function checkDataType($dataList) {
|
||||||
|
if($dataList instanceof SS_Filterable) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if($this->throwExceptionOnBadDataType) {
|
||||||
|
throw new LogicException(get_class($this) . " expects an SS_Filterable list to be passed to the GridField.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param GridField $gridField
|
* @param GridField $gridField
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getActions($gridField) {
|
public function getActions($gridField) {
|
||||||
|
if(!$this->checkDataType($gridField->getList())) return;
|
||||||
|
|
||||||
return array('filter', 'reset');
|
return array('filter', 'reset');
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
||||||
|
if(!$this->checkDataType($gridField->getList())) return;
|
||||||
|
|
||||||
$state = $gridField->State->GridFieldFilterHeader;
|
$state = $gridField->State->GridFieldFilterHeader;
|
||||||
if($actionName === 'filter') {
|
if($actionName === 'filter') {
|
||||||
if(isset($data['filter'])){
|
if(isset($data['filter'])){
|
||||||
@ -39,6 +76,8 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
|||||||
* @return SS_List
|
* @return SS_List
|
||||||
*/
|
*/
|
||||||
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
||||||
|
if(!$this->checkDataType($dataList)) return $dataList;
|
||||||
|
|
||||||
$state = $gridField->State->GridFieldFilterHeader;
|
$state = $gridField->State->GridFieldFilterHeader;
|
||||||
if(!isset($state->Columns)) {
|
if(!isset($state->Columns)) {
|
||||||
return $dataList;
|
return $dataList;
|
||||||
@ -54,6 +93,8 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getHTMLFragments($gridField) {
|
public function getHTMLFragments($gridField) {
|
||||||
|
if(!$this->checkDataType($gridField->getList())) return;
|
||||||
|
|
||||||
$forTemplate = new ArrayData(array());
|
$forTemplate = new ArrayData(array());
|
||||||
$forTemplate->Fields = new ArrayList;
|
$forTemplate->Fields = new ArrayList;
|
||||||
|
|
||||||
|
@ -20,6 +20,11 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
|
|||||||
*/
|
*/
|
||||||
protected $itemClass = 'GridFieldPaginator_Row';
|
protected $itemClass = 'GridFieldPaginator_Row';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link throwExceptionOnBadDataType()}
|
||||||
|
*/
|
||||||
|
protected $throwExceptionOnBadDataType = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param int $itemsPerPage - How many items should be displayed per page
|
* @param int $itemsPerPage - How many items should be displayed per page
|
||||||
@ -28,12 +33,42 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
|
|||||||
if($itemsPerPage) $this->itemsPerPage = $itemsPerPage;
|
if($itemsPerPage) $this->itemsPerPage = $itemsPerPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine what happens when this component is used with a list that isn't {@link SS_Filterable}.
|
||||||
|
*
|
||||||
|
* - true: An exception is thrown
|
||||||
|
* - false: This component will be ignored - it won't make any changes to the GridField.
|
||||||
|
*
|
||||||
|
* By default, this is set to true so that it's clearer what's happening, but the predefined
|
||||||
|
* {@link GridFieldConfig} subclasses set this to false for flexibility.
|
||||||
|
*/
|
||||||
|
public function throwExceptionOnBadDataType($throwExceptionOnBadDataType) {
|
||||||
|
$this->throwExceptionOnBadDataType = $throwExceptionOnBadDataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that this dataList is of the right data type.
|
||||||
|
* Returns false if it's a bad data type, and if appropriate, throws an exception.
|
||||||
|
*/
|
||||||
|
protected function checkDataType($dataList) {
|
||||||
|
if($dataList instanceof SS_Limitable) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if($this->throwExceptionOnBadDataType) {
|
||||||
|
throw new LogicException(get_class($this) . " expects an SS_Limitable list to be passed to the GridField.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param GridField $gridField
|
* @param GridField $gridField
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getActions($gridField) {
|
public function getActions($gridField) {
|
||||||
|
if(!$this->checkDataType($gridField->getList())) return;
|
||||||
|
|
||||||
return array('paginate');
|
return array('paginate');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,6 +81,8 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
|
|||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
||||||
|
if(!$this->checkDataType($gridField->getList())) return;
|
||||||
|
|
||||||
if($actionName !== 'paginate') {
|
if($actionName !== 'paginate') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -53,6 +90,8 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
|
|||||||
$state->currentPage = (int)$arguments;
|
$state->currentPage = (int)$arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected $totalItems = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param GridField $gridField
|
* @param GridField $gridField
|
||||||
@ -60,18 +99,23 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
|
|||||||
* @return SS_List
|
* @return SS_List
|
||||||
*/
|
*/
|
||||||
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
||||||
$state = $gridField->State->GridFieldPaginator;
|
if(!$this->checkDataType($dataList)) return $dataList;
|
||||||
if(!is_int($state->currentPage))
|
|
||||||
$state->currentPage = 1;
|
|
||||||
|
|
||||||
if(!$this->getListPaginatable($dataList)) {
|
$this->totalItems = $gridField->getList()->count();
|
||||||
|
|
||||||
|
$state = $gridField->State->GridFieldPaginator;
|
||||||
|
if(!is_int($state->currentPage)) {
|
||||||
|
$state->currentPage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!($dataList instanceof SS_Limitable)) {
|
||||||
return $dataList;
|
return $dataList;
|
||||||
}
|
}
|
||||||
if(!$state->currentPage) {
|
if(!$state->currentPage) {
|
||||||
return $dataList->getRange(0, (int)$this->itemsPerPage);
|
return $dataList->limit((int)$this->itemsPerPage);
|
||||||
}
|
}
|
||||||
$startRow = $this->itemsPerPage * ($state->currentPage - 1);
|
$startRow = $this->itemsPerPage * ($state->currentPage - 1);
|
||||||
return $dataList->getRange((int)$startRow, (int)$this->itemsPerPage);
|
return $dataList->limit((int)$this->itemsPerPage, (int)$startRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,13 +124,14 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getHTMLFragments($gridField) {
|
public function getHTMLFragments($gridField) {
|
||||||
|
if(!$this->checkDataType($gridField->getList())) return;
|
||||||
|
|
||||||
$state = $gridField->State->GridFieldPaginator;
|
$state = $gridField->State->GridFieldPaginator;
|
||||||
if(!is_int($state->currentPage))
|
if(!is_int($state->currentPage))
|
||||||
$state->currentPage = 1;
|
$state->currentPage = 1;
|
||||||
|
|
||||||
// Figure out which page and record range we're on
|
// Figure out which page and record range we're on
|
||||||
$countList = clone $gridField->List;
|
$totalRows = $this->totalItems;
|
||||||
$totalRows = $countList->limit(null)->count();
|
|
||||||
if(!$totalRows) return array();
|
if(!$totalRows) return array();
|
||||||
|
|
||||||
$totalPages = ceil($totalRows/$this->itemsPerPage);
|
$totalPages = ceil($totalRows/$this->itemsPerPage);
|
||||||
@ -159,14 +204,4 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
|
|||||||
return $this->itemsPerPage;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,45 @@
|
|||||||
*/
|
*/
|
||||||
class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider {
|
class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See {@link throwExceptionOnBadDataType()}
|
||||||
|
*/
|
||||||
|
protected $throwExceptionOnBadDataType = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine what happens when this component is used with a list that isn't {@link SS_Filterable}.
|
||||||
|
*
|
||||||
|
* - true: An exception is thrown
|
||||||
|
* - false: This component will be ignored - it won't make any changes to the GridField.
|
||||||
|
*
|
||||||
|
* By default, this is set to true so that it's clearer what's happening, but the predefined
|
||||||
|
* {@link GridFieldConfig} subclasses set this to false for flexibility.
|
||||||
|
*/
|
||||||
|
public function throwExceptionOnBadDataType($throwExceptionOnBadDataType) {
|
||||||
|
$this->throwExceptionOnBadDataType = $throwExceptionOnBadDataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that this dataList is of the right data type.
|
||||||
|
* Returns false if it's a bad data type, and if appropriate, throws an exception.
|
||||||
|
*/
|
||||||
|
protected function checkDataType($dataList) {
|
||||||
|
if($dataList instanceof SS_Sortable) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if($this->throwExceptionOnBadDataType) {
|
||||||
|
throw new LogicException(get_class($this) . " expects an SS_Sortable list to be passed to the GridField.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the header row providing titles with sort buttons
|
* Returns the header row providing titles with sort buttons
|
||||||
*/
|
*/
|
||||||
public function getHTMLFragments($gridField) {
|
public function getHTMLFragments($gridField) {
|
||||||
|
if(!$this->checkDataType($gridField->getList())) return;
|
||||||
|
|
||||||
$forTemplate = new ArrayData(array());
|
$forTemplate = new ArrayData(array());
|
||||||
$forTemplate->Fields = new ArrayList;
|
$forTemplate->Fields = new ArrayList;
|
||||||
|
|
||||||
@ -58,10 +93,14 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getActions($gridField) {
|
public function getActions($gridField) {
|
||||||
|
if(!$this->checkDataType($gridField->getList())) return;
|
||||||
|
|
||||||
return array('sortasc', 'sortdesc');
|
return array('sortasc', 'sortdesc');
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
||||||
|
if(!$this->checkDataType($gridField->getList())) return;
|
||||||
|
|
||||||
$state = $gridField->State->GridFieldSortableHeader;
|
$state = $gridField->State->GridFieldSortableHeader;
|
||||||
switch($actionName) {
|
switch($actionName) {
|
||||||
case 'sortasc':
|
case 'sortasc':
|
||||||
@ -77,6 +116,8 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
||||||
|
if(!$this->checkDataType($dataList)) return $dataList;
|
||||||
|
|
||||||
$state = $gridField->State->GridFieldSortableHeader;
|
$state = $gridField->State->GridFieldSortableHeader;
|
||||||
if ($state->SortColumn == "") {
|
if ($state->SortColumn == "") {
|
||||||
return $dataList;
|
return $dataList;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* @package sapphire
|
* @package sapphire
|
||||||
* @subpackage model
|
* @subpackage model
|
||||||
*/
|
*/
|
||||||
class ArrayList extends ViewableData implements SS_List {
|
class ArrayList extends ViewableData implements SS_List, SS_Filterable, SS_Sortable, SS_Limitable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the items in the list
|
* Holds the items in the list
|
||||||
@ -119,6 +119,18 @@ class ArrayList extends ViewableData implements SS_List {
|
|||||||
* @return ArrayList
|
* @return ArrayList
|
||||||
*/
|
*/
|
||||||
public function getRange($offset, $length) {
|
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));
|
return new ArrayList(array_slice($this->items, $offset, $length));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,6 +370,15 @@ class ArrayList extends ViewableData implements SS_List {
|
|||||||
return $this;
|
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
|
* Filter the list to include items with these charactaristics
|
||||||
*
|
*
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* @package sapphire
|
* @package sapphire
|
||||||
* @subpackage model
|
* @subpackage model
|
||||||
*/
|
*/
|
||||||
class DataList extends ViewableData implements SS_List {
|
class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortable, SS_Limitable {
|
||||||
/**
|
/**
|
||||||
* The DataObject class name that this data list is querying
|
* The DataObject class name that this data list is querying
|
||||||
*
|
*
|
||||||
@ -145,8 +145,14 @@ class DataList extends ViewableData implements SS_List {
|
|||||||
*
|
*
|
||||||
* @param string $limit
|
* @param string $limit
|
||||||
*/
|
*/
|
||||||
public function limit($limit) {
|
public function limit($limit, $offset = 0) {
|
||||||
$this->dataQuery->limit($limit);
|
if(!$limit && !$offset) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
if($limit && !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;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,7 +551,8 @@ class DataList extends ViewableData implements SS_List {
|
|||||||
* @return DataList
|
* @return DataList
|
||||||
*/
|
*/
|
||||||
public function getRange($offset, $length) {
|
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 +820,7 @@ class DataList extends ViewableData implements SS_List {
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function offsetExists($key) {
|
public function offsetExists($key) {
|
||||||
return ($this->getRange($key, 1)->First() != null);
|
return ($this->limit(1,$key)->First() != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -823,7 +830,7 @@ class DataList extends ViewableData implements SS_List {
|
|||||||
* @return DataObject
|
* @return DataObject
|
||||||
*/
|
*/
|
||||||
public function offsetGet($key) {
|
public function offsetGet($key) {
|
||||||
return $this->getRange($key, 1)->First();
|
return $this->limit(1, $key)->First();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1309,7 +1309,7 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
*
|
*
|
||||||
* @return HasManyList The components of the one-to-many relationship.
|
* @return HasManyList The components of the one-to-many relationship.
|
||||||
*/
|
*/
|
||||||
public function getComponents($componentName, $filter = "", $sort = "", $join = "", $limit = "") {
|
public function getComponents($componentName, $filter = "", $sort = "", $join = "", $limit = null) {
|
||||||
$result = null;
|
$result = null;
|
||||||
|
|
||||||
if(!$componentClass = $this->has_many($componentName)) {
|
if(!$componentClass = $this->has_many($componentName)) {
|
||||||
@ -2479,11 +2479,17 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity
|
|||||||
*
|
*
|
||||||
* @return mixed The objects matching the filter, in the class specified by $containerClass
|
* @return mixed The objects matching the filter, in the class specified by $containerClass
|
||||||
*/
|
*/
|
||||||
public static function get($callerClass, $filter = "", $sort = "", $join = "", $limit = "", $containerClass = "DataList") {
|
public static function get($callerClass, $filter = "", $sort = "", $join = "", $limit = null, $containerClass = "DataList") {
|
||||||
// Todo: Determine if we can deprecate for 3.0.0 and use DI or something instead
|
// Todo: Determine if we can deprecate for 3.0.0 and use DI or something instead
|
||||||
// Todo: Make the $containerClass method redundant
|
// Todo: Make the $containerClass method redundant
|
||||||
if($containerClass != "DataList") user_error("The DataObject::get() \$containerClass argument has been deprecated", E_USER_NOTICE);
|
if($containerClass != "DataList") user_error("The DataObject::get() \$containerClass argument has been deprecated", E_USER_NOTICE);
|
||||||
$result = DataList::create($callerClass)->where($filter)->sort($sort)->limit($limit);
|
$result = DataList::create($callerClass)->where($filter)->sort($sort);
|
||||||
|
if($limit && strpos($limit, ',') !== false) {
|
||||||
|
$limitArguments = explode(',', $limit);
|
||||||
|
$result->limit($limitArguments[1],$limitArguments[0]);
|
||||||
|
} elseif($limit) {
|
||||||
|
$result->limit($limit);
|
||||||
|
}
|
||||||
if($join) $result = $result->join($join);
|
if($join) $result = $result->join($join);
|
||||||
$result->setModel(DataModel::inst());
|
$result->setModel(DataModel::inst());
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -373,9 +373,9 @@ class DataQuery {
|
|||||||
/**
|
/**
|
||||||
* Set the limit of this query
|
* Set the limit of this query
|
||||||
*/
|
*/
|
||||||
function limit($limit) {
|
function limit($limit, $offset = 0) {
|
||||||
$clone = $this;
|
$clone = $this;
|
||||||
$clone->query->limit($limit);
|
$clone->query->limit($limit, $offset);
|
||||||
return $clone;
|
return $clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
40
model/Filterable.php
Normal file
40
model/Filterable.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional interface for {@link SS_List} classes that are filterable.
|
||||||
|
*
|
||||||
|
* @see SS_List, SS_Sortable, SS_Limitable
|
||||||
|
*/
|
||||||
|
interface SS_Filterable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if the list can be filtered by a given field expression.
|
||||||
|
*
|
||||||
|
* @param string $by
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function canFilterBy($by);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the list to include items with these charactaristics
|
||||||
|
*
|
||||||
|
* @example $list->filter('Name', 'bob'); // only bob in the list
|
||||||
|
* @example $list->filter('Name', array('aziz', 'bob'); // aziz and bob in list
|
||||||
|
* @example $list->filter(array('Name'=>'bob, 'Age'=>21)); // bob with the age 21
|
||||||
|
* @example $list->filter(array('Name'=>'bob, 'Age'=>array(21, 43))); // bob with the Age 21 or 43
|
||||||
|
* @example $list->filter(array('Name'=>array('aziz','bob'), 'Age'=>array(21, 43))); // aziz with the age 21 or 43 and bob with the Age 21 or 43
|
||||||
|
*/
|
||||||
|
public function filter();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exclude the list to not contain items with these charactaristics
|
||||||
|
*
|
||||||
|
* @example $list->exclude('Name', 'bob'); // exclude bob from list
|
||||||
|
* @example $list->exclude('Name', array('aziz', 'bob'); // exclude aziz and bob from list
|
||||||
|
* @example $list->exclude(array('Name'=>'bob, 'Age'=>21)); // exclude bob that has Age 21
|
||||||
|
* @example $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob with Age 21 or 43
|
||||||
|
* @example $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43))); // bob age 21 or 43, phil age 21 or 43 would be excluded
|
||||||
|
*/
|
||||||
|
public function exclude();
|
||||||
|
|
||||||
|
}
|
19
model/Limitable.php
Normal file
19
model/Limitable.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional interface for {@link SS_List} classes that are limitable - able to have a subset of the list extracted.
|
||||||
|
*
|
||||||
|
* @see SS_List, SS_Sortable, SS_Filterable
|
||||||
|
*/
|
||||||
|
interface SS_Limitable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a filtered version of this where no more than $limit records are included.
|
||||||
|
* If $offset is specified, then that many records at the beginning of the list will be skipped.
|
||||||
|
* This matches the behaviour of the SQL LIMIT clause.
|
||||||
|
*
|
||||||
|
* @return SS_List
|
||||||
|
*/
|
||||||
|
public function limit($limit, $offset = 0);
|
||||||
|
|
||||||
|
}
|
@ -21,15 +21,6 @@ interface SS_List extends ArrayAccess, Countable, IteratorAggregate {
|
|||||||
*/
|
*/
|
||||||
public function toNestedArray();
|
public function toNestedArray();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a subset of the items within the list.
|
|
||||||
*
|
|
||||||
* @param int $offset
|
|
||||||
* @param int $length
|
|
||||||
* @return SS_List
|
|
||||||
*/
|
|
||||||
public function getRange($offset, $length);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an item to the list, making no guarantees about where it will
|
* Adds an item to the list, making no guarantees about where it will
|
||||||
* appear.
|
* appear.
|
||||||
@ -87,45 +78,4 @@ interface SS_List extends ArrayAccess, Countable, IteratorAggregate {
|
|||||||
*/
|
*/
|
||||||
public function column($colName = "ID");
|
public function column($colName = "ID");
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns TRUE if the list can be sorted by a field.
|
|
||||||
*
|
|
||||||
* @param string $by
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function canSortBy($by);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sorts this list by one or more fields. You can either pass in a single
|
|
||||||
* field name and direction, or a map of field names to sort directions.
|
|
||||||
*
|
|
||||||
* @example $list->sort('Name'); // default ASC sorting
|
|
||||||
* @example $list->sort('Name DESC'); // DESC sorting
|
|
||||||
* @example $list->sort('Name', 'ASC');
|
|
||||||
* @example $list->sort(array('Name'=>'ASC,'Age'=>'DESC'));
|
|
||||||
*/
|
|
||||||
public function sort();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filter the list to include items with these charactaristics
|
|
||||||
*
|
|
||||||
* @example $list->filter('Name', 'bob'); // only bob in the list
|
|
||||||
* @example $list->filter('Name', array('aziz', 'bob'); // aziz and bob in list
|
|
||||||
* @example $list->filter(array('Name'=>'bob, 'Age'=>21)); // bob with the age 21
|
|
||||||
* @example $list->filter(array('Name'=>'bob, 'Age'=>array(21, 43))); // bob with the Age 21 or 43
|
|
||||||
* @example $list->filter(array('Name'=>array('aziz','bob'), 'Age'=>array(21, 43))); // aziz with the age 21 or 43 and bob with the Age 21 or 43
|
|
||||||
*/
|
|
||||||
public function filter();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Exclude the list to not contain items with these charactaristics
|
|
||||||
*
|
|
||||||
* @example $list->exclude('Name', 'bob'); // exclude bob from list
|
|
||||||
* @example $list->exclude('Name', array('aziz', 'bob'); // exclude aziz and bob from list
|
|
||||||
* @example $list->exclude(array('Name'=>'bob, 'Age'=>21)); // exclude bob that has Age 21
|
|
||||||
* @example $list->exclude(array('Name'=>'bob, 'Age'=>array(21, 43))); // exclude bob with Age 21 or 43
|
|
||||||
* @example $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43))); // bob age 21 or 43, phil age 21 or 43 would be excluded
|
|
||||||
*/
|
|
||||||
public function exclude();
|
|
||||||
|
|
||||||
}
|
}
|
@ -7,7 +7,7 @@
|
|||||||
* @package sapphire
|
* @package sapphire
|
||||||
* @subpackage model
|
* @subpackage model
|
||||||
*/
|
*/
|
||||||
abstract class SS_ListDecorator extends ViewableData implements SS_List {
|
abstract class SS_ListDecorator extends ViewableData implements SS_List, SS_Sortable, SS_Filterable, SS_Limitable {
|
||||||
|
|
||||||
protected $list;
|
protected $list;
|
||||||
|
|
||||||
@ -61,10 +61,6 @@ abstract class SS_ListDecorator extends ViewableData implements SS_List {
|
|||||||
$this->list->remove($itemObject);
|
$this->list->remove($itemObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getRange($offset, $length) {
|
|
||||||
return $this->list->getRange($offset, $length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getIterator() {
|
public function getIterator() {
|
||||||
return $this->list->getIterator();
|
return $this->list->getIterator();
|
||||||
}
|
}
|
||||||
@ -123,6 +119,10 @@ abstract class SS_ListDecorator extends ViewableData implements SS_List {
|
|||||||
return call_user_func_array(array($this->list, 'sort'), $args);
|
return call_user_func_array(array($this->list, 'sort'), $args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function canFilterBy($by) {
|
||||||
|
return $this->list->canFilterBy($by);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter the list to include items with these charactaristics
|
* Filter the list to include items with these charactaristics
|
||||||
*
|
*
|
||||||
@ -136,6 +136,10 @@ abstract class SS_ListDecorator extends ViewableData implements SS_List {
|
|||||||
return call_user_func_array(array($this->list, 'filter'), $args);
|
return call_user_func_array(array($this->list, 'filter'), $args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function limit($limit, $offset = 0) {
|
||||||
|
return $this->list->getRange($length, $offset);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exclude the list to not contain items with these charactaristics
|
* Exclude the list to not contain items with these charactaristics
|
||||||
*
|
*
|
||||||
|
@ -252,10 +252,10 @@ class SQLQuery {
|
|||||||
* @param string|array $limit
|
* @param string|array $limit
|
||||||
* @return SQLQuery This instance
|
* @return SQLQuery This instance
|
||||||
*/
|
*/
|
||||||
public function limit($limit) {
|
public function limit($limit, $offset = 0) {
|
||||||
if($limit && is_numeric($limit)) {
|
if($limit && is_numeric($limit)) {
|
||||||
$this->limit = array(
|
$this->limit = array(
|
||||||
'start' => 0,
|
'start' => $offset,
|
||||||
'limit' => $limit,
|
'limit' => $limit,
|
||||||
);
|
);
|
||||||
} else if($limit && is_string($limit)) {
|
} else if($limit && is_string($limit)) {
|
||||||
@ -667,7 +667,7 @@ class SQLQuery {
|
|||||||
function firstRow() {
|
function firstRow() {
|
||||||
$query = clone $this;
|
$query = clone $this;
|
||||||
$offset = $this->limit ? $this->limit['start'] : 0;
|
$offset = $this->limit ? $this->limit['start'] : 0;
|
||||||
$query->limit(array('start' => $offset, 'limit' => 1));
|
$query->limit(1, $offset);
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,7 +677,7 @@ class SQLQuery {
|
|||||||
function lastRow() {
|
function lastRow() {
|
||||||
$query = clone $this;
|
$query = clone $this;
|
||||||
$offset = $this->limit ? $this->limit['start'] : 0;
|
$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;
|
return $query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
29
model/Sortable.php
Normal file
29
model/Sortable.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Additional interface for {@link SS_List} classes that are sortable.
|
||||||
|
*
|
||||||
|
* @see SS_List, SS_Filterable, SS_Limitable
|
||||||
|
*/
|
||||||
|
interface SS_Sortable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns TRUE if the list can be sorted by a field.
|
||||||
|
*
|
||||||
|
* @param string $by
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function canSortBy($by);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorts this list by one or more fields. You can either pass in a single
|
||||||
|
* field name and direction, or a map of field names to sort directions.
|
||||||
|
*
|
||||||
|
* @example $list->sort('Name'); // default ASC sorting
|
||||||
|
* @example $list->sort('Name DESC'); // DESC sorting
|
||||||
|
* @example $list->sort('Name', 'ASC');
|
||||||
|
* @example $list->sort(array('Name'=>'ASC,'Age'=>'DESC'));
|
||||||
|
*/
|
||||||
|
public function sort();
|
||||||
|
|
||||||
|
}
|
@ -30,12 +30,15 @@ class GridFieldTest extends SapphireTest {
|
|||||||
|
|
||||||
$expectedComponents = new ArrayList(array(
|
$expectedComponents = new ArrayList(array(
|
||||||
new GridFieldToolbarHeader(),
|
new GridFieldToolbarHeader(),
|
||||||
new GridFieldSortableHeader,
|
$sort = new GridFieldSortableHeader(),
|
||||||
new GridFieldFilterHeader,
|
$filter = new GridFieldFilterHeader(),
|
||||||
new GridFieldDataColumns,
|
new GridFieldDataColumns(),
|
||||||
new GridFieldPaginator,
|
$pagination = new GridFieldPaginator(),
|
||||||
new GridState_Component,
|
new GridState_Component(),
|
||||||
));
|
));
|
||||||
|
$sort->throwExceptionOnBadDataType(false);
|
||||||
|
$filter->throwExceptionOnBadDataType(false);
|
||||||
|
$pagination->throwExceptionOnBadDataType(false);
|
||||||
|
|
||||||
$this->assertEquals($expectedComponents, $obj->getConfig()->getComponents(), 'Testing default Config');
|
$this->assertEquals($expectedComponents, $obj->getConfig()->getComponents(), 'Testing default Config');
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
<?php
|
<?php
|
||||||
class GridFieldToolbarHeaderTest extends SapphireTest {
|
class GridFieldToolbarHeaderTest extends SapphireTest {
|
||||||
|
|
||||||
|
static $fixture_file = 'GridFieldToolbarHeaderTest.yml';
|
||||||
|
|
||||||
|
protected $extraDataObjects = array(
|
||||||
|
'GridFieldToolbarHeaderTest_Company',
|
||||||
|
);
|
||||||
|
|
||||||
public function testGridTitleAddNewEnabled() {
|
public function testGridTitleAddNewEnabled() {
|
||||||
$this->logInWithPermission('ADMIN');
|
$this->logInWithPermission('ADMIN');
|
||||||
@ -8,7 +13,7 @@ class GridFieldToolbarHeaderTest extends SapphireTest {
|
|||||||
$config = new GridFieldConfig();
|
$config = new GridFieldConfig();
|
||||||
$config->addComponent($titleField = new GridFieldToolbarHeader());
|
$config->addComponent($titleField = new GridFieldToolbarHeader());
|
||||||
$actions = new FieldList();
|
$actions = new FieldList();
|
||||||
$grid = new GridField('TestField', 'Test Field', new DataList('Company'),$config);
|
$grid = new GridField('TestField', 'Test Field', new DataList('GridFieldToolbarHeaderTest_Company'),$config);
|
||||||
$fields = new FieldList($rootTab = new TabSet("Root",$tabMain = new Tab('Main',$grid)));
|
$fields = new FieldList($rootTab = new TabSet("Root",$tabMain = new Tab('Main',$grid)));
|
||||||
$form = new Form(Controller::curr(), "TestForm", $fields, $actions);
|
$form = new Form(Controller::curr(), "TestForm", $fields, $actions);
|
||||||
|
|
||||||
@ -23,7 +28,7 @@ class GridFieldToolbarHeaderTest extends SapphireTest {
|
|||||||
$config = new GridFieldConfig();
|
$config = new GridFieldConfig();
|
||||||
$config->addComponent($titleField = new GridFieldToolbarHeader());
|
$config->addComponent($titleField = new GridFieldToolbarHeader());
|
||||||
$actions = new FieldList();
|
$actions = new FieldList();
|
||||||
$grid = new GridField('TestField', 'Test Field', new DataList('Company'),$config);
|
$grid = new GridField('TestField', 'Test Field', new DataList('GridFieldToolbarHeaderTest_Company'),$config);
|
||||||
$fields = new FieldList($rootTab = new TabSet("Root",$tabMain = new Tab('Main',$grid)));
|
$fields = new FieldList($rootTab = new TabSet("Root",$tabMain = new Tab('Main',$grid)));
|
||||||
$form = new Form(Controller::curr(), "TestForm", $fields, $actions);
|
$form = new Form(Controller::curr(), "TestForm", $fields, $actions);
|
||||||
|
|
||||||
@ -36,7 +41,7 @@ class GridFieldToolbarHeaderTest extends SapphireTest {
|
|||||||
if(Member::currentUser()) { Member::currentUser()->logOut(); }
|
if(Member::currentUser()) { Member::currentUser()->logOut(); }
|
||||||
$config = new GridFieldConfig();
|
$config = new GridFieldConfig();
|
||||||
$config->addComponent($titleField = new GridFieldToolbarHeader());
|
$config->addComponent($titleField = new GridFieldToolbarHeader());
|
||||||
$grid = new GridField('TestField', 'Test Field', new DataList('Company'),$config);
|
$grid = new GridField('TestField', 'Test Field', new DataList('GridFieldToolbarHeaderTest_Company'),$config);
|
||||||
$fields = new FieldList(new TabSet("Root",$tabMain = new Tab('Main',$grid)));
|
$fields = new FieldList(new TabSet("Root",$tabMain = new Tab('Main',$grid)));
|
||||||
$form = new Form(Controller::curr(), "TestForm", $fields, new FieldList());
|
$form = new Form(Controller::curr(), "TestForm", $fields, new FieldList());
|
||||||
|
|
||||||
@ -44,3 +49,10 @@ class GridFieldToolbarHeaderTest extends SapphireTest {
|
|||||||
$this->assertNotContains('data-icon="add"', $html, "HTML should not contain the 'add new' button");
|
$this->assertNotContains('data-icon="add"', $html, "HTML should not contain the 'add new' button");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class GridFieldToolbarHeaderTest_Company extends DataObject implements TestOnly {
|
||||||
|
|
||||||
|
public static $db = array(
|
||||||
|
'Name' => 'Varchar(100)'
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
5
tests/forms/gridfield/GridFieldToolbarHeaderTest.yml
Normal file
5
tests/forms/gridfield/GridFieldToolbarHeaderTest.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
GridFieldToolbarHeaderTest_Company:
|
||||||
|
test-company-1:
|
||||||
|
Name: Test company 1
|
||||||
|
test-company-2:
|
||||||
|
Name: Test company 2
|
@ -61,11 +61,11 @@ class ArrayListTest extends SapphireTest {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testGetRange() {
|
public function testLimit() {
|
||||||
$list = new ArrayList(array(
|
$list = new ArrayList(array(
|
||||||
array('Key' => 1), array('Key' => 2), array('Key' => 3)
|
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)
|
array('Key' => 2), array('Key' => 3)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ class DataListTest extends SapphireTest {
|
|||||||
$this->assertEquals(array('Bob', 'Joe', 'Phil'), $list->column('Name'));
|
$this->assertEquals(array('Bob', 'Joe', 'Phil'), $list->column('Name'));
|
||||||
|
|
||||||
// We can also restrict the output to a range
|
// 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() {
|
function testDataClass() {
|
||||||
|
@ -197,18 +197,12 @@ class DataObjectTest extends SapphireTest {
|
|||||||
// There's 4 records in total
|
// There's 4 records in total
|
||||||
$this->assertEquals(4, $players->count());
|
$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
|
// Testing "##, ##" syntax
|
||||||
$this->assertEquals(4, $players->limit("20")->count());
|
$this->assertEquals(4, $players->limit(20)->count());
|
||||||
$this->assertEquals(4, $players->limit("0, 20")->count());
|
$this->assertEquals(4, $players->limit(20, 0)->count());
|
||||||
$this->assertEquals(0, $players->limit("20, 20")->count());
|
$this->assertEquals(0, $players->limit(20, 20)->count());
|
||||||
$this->assertEquals(2, $players->limit("0, 2")->count());
|
$this->assertEquals(2, $players->limit(2, 0)->count());
|
||||||
$this->assertEquals(1, $players->limit("3, 5")->count());
|
$this->assertEquals(1, $players->limit(5, 3)->count());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,19 +87,13 @@ class SQLQueryTest extends SapphireTest {
|
|||||||
// numeric limit
|
// numeric limit
|
||||||
$query = new SQLQuery();
|
$query = new SQLQuery();
|
||||||
$query->from[] = "MyTable";
|
$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());
|
$this->assertEquals("SELECT * FROM MyTable LIMIT 99", $query->sql());
|
||||||
|
|
||||||
// array limit with start (MySQL specific)
|
// array limit with start (MySQL specific)
|
||||||
$query = new SQLQuery();
|
$query = new SQLQuery();
|
||||||
$query->from[] = "MyTable";
|
$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());
|
$this->assertEquals("SELECT * FROM MyTable LIMIT 99 OFFSET 97", $query->sql());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user