diff --git a/forms/gridfield/GridField.php b/forms/gridfield/GridField.php index ac1fbbd39f9..9aef66d79d7 100755 --- a/forms/gridfield/GridField.php +++ b/forms/gridfield/GridField.php @@ -323,7 +323,7 @@ public function FieldHolder() { foreach($this->components as $item) { if($item instanceof GridField_HTMLProvider) { $fragments = $item->getHTMLFragments($this); - foreach($fragments as $k => $v) { + if($fragments) foreach($fragments as $k => $v) { $k = strtolower($k); if(!isset($content[$k])) $content[$k] = ""; $content[$k] .= $v . "\n"; diff --git a/forms/gridfield/GridFieldConfig.php b/forms/gridfield/GridFieldConfig.php index 76ad37a6b0a..b6da4213fd1 100755 --- a/forms/gridfield/GridFieldConfig.php +++ b/forms/gridfield/GridFieldConfig.php @@ -132,10 +132,14 @@ public static function create($itemsPerPage=null){ */ public function __construct($itemsPerPage=null) { $this->addComponent(new GridFieldToolbarHeader()); - $this->addComponent(new GridFieldSortableHeader()); - $this->addComponent(new GridFieldFilterHeader()); + $this->addComponent($sort = new GridFieldSortableHeader()); + $this->addComponent($filter = new GridFieldFilterHeader()); $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 @@ public static function create($itemsPerPage=null){ */ public function __construct($itemsPerPage=null) { $this->addComponent(new GridFieldToolbarHeader()); - $this->addComponent(new GridFieldSortableHeader()); - $this->addComponent(new GridFieldFilterHeader()); + $this->addComponent($sort = new GridFieldSortableHeader()); + $this->addComponent($filter = new GridFieldFilterHeader()); $this->addComponent(new GridFieldDataColumns()); $this->addComponent(new GridFieldEditButton()); $this->addComponent(new GridFieldDeleteAction()); - $this->addComponent(new GridFieldPaginator($itemsPerPage)); + $this->addComponent($pagination = new GridFieldPaginator($itemsPerPage)); $this->addComponent(new GridFieldDetailForm()); + + $sort->throwExceptionOnBadDataType(false); + $filter->throwExceptionOnBadDataType(false); + $pagination->throwExceptionOnBadDataType(false); } } @@ -202,12 +210,16 @@ public static function create($itemsPerPage=null){ public function __construct($itemsPerPage=null) { $this->addComponent(new GridFieldToolbarHeader()); $this->addComponent(new GridFieldAddExistingAutocompleter()); - $this->addComponent(new GridFieldSortableHeader()); - $this->addComponent(new GridFieldFilterHeader()); + $this->addComponent($sort = new GridFieldSortableHeader()); + $this->addComponent($filter = new GridFieldFilterHeader()); $this->addComponent(new GridFieldDataColumns()); $this->addComponent(new GridFieldEditButton()); - $this->addComponent(new GridFieldDeleteAction(true)); - $this->addComponent(new GridFieldPaginator($itemsPerPage)); + $this->addComponent(new GridFieldDeleteAction()); + $this->addComponent($pagination = new GridFieldPaginator($itemsPerPage)); $this->addComponent(new GridFieldDetailForm()); + + $sort->throwExceptionOnBadDataType(false); + $filter->throwExceptionOnBadDataType(false); + $pagination->throwExceptionOnBadDataType(false); } } diff --git a/forms/gridfield/GridFieldFilterHeader.php b/forms/gridfield/GridFieldFilterHeader.php index 4990efe60eb..b59c38ee69f 100644 --- a/forms/gridfield/GridFieldFilterHeader.php +++ b/forms/gridfield/GridFieldFilterHeader.php @@ -8,17 +8,54 @@ * @subpackage fields-relational */ 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 * @return array */ public function getActions($gridField) { + if(!$this->checkDataType($gridField->getList())) return; + return array('filter', 'reset'); } function handleAction(GridField $gridField, $actionName, $arguments, $data) { + if(!$this->checkDataType($gridField->getList())) return; + $state = $gridField->State->GridFieldFilterHeader; if($actionName === 'filter') { if(isset($data['filter'])){ @@ -39,6 +76,8 @@ function handleAction(GridField $gridField, $actionName, $arguments, $data) { * @return SS_List */ public function getManipulatedData(GridField $gridField, SS_List $dataList) { + if(!$this->checkDataType($dataList)) return $dataList; + $state = $gridField->State->GridFieldFilterHeader; if(!isset($state->Columns)) { return $dataList; @@ -54,6 +93,8 @@ public function getManipulatedData(GridField $gridField, SS_List $dataList) { } public function getHTMLFragments($gridField) { + if(!$this->checkDataType($gridField->getList())) return; + $forTemplate = new ArrayData(array()); $forTemplate->Fields = new ArrayList; diff --git a/forms/gridfield/GridFieldPaginator.php b/forms/gridfield/GridFieldPaginator.php index 76629be09dc..7ee32008d44 100755 --- a/forms/gridfield/GridFieldPaginator.php +++ b/forms/gridfield/GridFieldPaginator.php @@ -20,6 +20,11 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu */ protected $itemClass = 'GridFieldPaginator_Row'; + /** + * See {@link throwExceptionOnBadDataType()} + */ + protected $throwExceptionOnBadDataType = true; + /** * * @param int $itemsPerPage - How many items should be displayed per page @@ -27,6 +32,34 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu public function __construct($itemsPerPage=null) { 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; + } + } /** * @@ -34,6 +67,8 @@ public function __construct($itemsPerPage=null) { * @return array */ public function getActions($gridField) { + if(!$this->checkDataType($gridField->getList())) return; + return array('paginate'); } @@ -46,6 +81,8 @@ public function getActions($gridField) { * @return void */ public function handleAction(GridField $gridField, $actionName, $arguments, $data) { + if(!$this->checkDataType($gridField->getList())) return; + if($actionName !== 'paginate') { return; } @@ -60,6 +97,8 @@ public function handleAction(GridField $gridField, $actionName, $arguments, $dat * @return SS_List */ public function getManipulatedData(GridField $gridField, SS_List $dataList) { + if(!$this->checkDataType($dataList)) return $dataList; + $state = $gridField->State->GridFieldPaginator; if(!is_int($state->currentPage)) $state->currentPage = 1; @@ -80,6 +119,8 @@ public function getManipulatedData(GridField $gridField, SS_List $dataList) { * @return array */ public function getHTMLFragments($gridField) { + if(!$this->checkDataType($gridField->getList())) return; + $state = $gridField->State->GridFieldPaginator; if(!is_int($state->currentPage)) $state->currentPage = 1; diff --git a/forms/gridfield/GridFieldSortableHeader.php b/forms/gridfield/GridFieldSortableHeader.php index 130cadc46f5..e5213886418 100644 --- a/forms/gridfield/GridFieldSortableHeader.php +++ b/forms/gridfield/GridFieldSortableHeader.php @@ -8,11 +8,46 @@ * @subpackage fields-relational */ 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 */ public function getHTMLFragments($gridField) { + if(!$this->checkDataType($gridField->getList())) return; + $forTemplate = new ArrayData(array()); $forTemplate->Fields = new ArrayList; @@ -58,10 +93,14 @@ public function getHTMLFragments($gridField) { * @return array */ public function getActions($gridField) { + if(!$this->checkDataType($gridField->getList())) return; + return array('sortasc', 'sortdesc'); } function handleAction(GridField $gridField, $actionName, $arguments, $data) { + if(!$this->checkDataType($gridField->getList())) return; + $state = $gridField->State->GridFieldSortableHeader; switch($actionName) { case 'sortasc': @@ -77,6 +116,8 @@ function handleAction(GridField $gridField, $actionName, $arguments, $data) { } public function getManipulatedData(GridField $gridField, SS_List $dataList) { + if(!$this->checkDataType($dataList)) return $dataList; + $state = $gridField->State->GridFieldSortableHeader; if ($state->SortColumn == "") { return $dataList;