From b6b3cd98891e0f6134c77225e76147d8721d0129 Mon Sep 17 00:00:00 2001 From: Damian Mooyman Date: Fri, 11 Oct 2013 10:08:59 +1300 Subject: [PATCH] API GridState_Data values can have default values specified during retrieval. Fixes issues with GridStata_Data being returned from various states when value types are necessary. Pruning of dead code from GridFieldAddExistingAutocompleter Documentation for GridState --- docs/en/reference/grid-field.md | 17 +++++ forms/gridfield/GridField.php | 1 + .../GridFieldAddExistingAutocompleter.php | 67 ++++--------------- forms/gridfield/GridFieldFilterHeader.php | 8 +-- forms/gridfield/GridFieldPaginator.php | 2 +- forms/gridfield/GridFieldSortableHeader.php | 11 +-- forms/gridfield/GridState.php | 23 ++++++- tests/forms/GridFieldTest.php | 24 +++++++ 8 files changed, 85 insertions(+), 68 deletions(-) diff --git a/docs/en/reference/grid-field.md b/docs/en/reference/grid-field.md index fbc05e9c1..bd877ddc0 100644 --- a/docs/en/reference/grid-field.md +++ b/docs/en/reference/grid-field.md @@ -345,6 +345,23 @@ transfered between page requests by being inserted as a hidden field in the form A GridFieldComponent sets and gets data from the GridState. +Data within this object can be nested, allowing for organisation of information in a logical fashion. Additionally, +default values can be specified for any data field by invoking that field as a method, passing the default value +as the first parameter. If no default is specified then a nested `GridState_Data` is returned, which may be chained +to subsequently nest data values. + +Example: + + :::php + + public function getManipulatedData(GridField $gridField, SS_List $dataList) { + // Accesses the GridState, returns a nested GridState_Data, and retrieve a single field with a default of null + $objectID = $gridField->State->MyComponent->RecordID(null); + if($objectID) $dataList = $dataList->filter('ParentID', $objectID); + return $dataList; + } + + ## Permissions Since GridField is mostly used in the CMS, the controller managing a GridField instance diff --git a/forms/gridfield/GridField.php b/forms/gridfield/GridField.php index d529f51dd..f53b58d6e 100644 --- a/forms/gridfield/GridField.php +++ b/forms/gridfield/GridField.php @@ -17,6 +17,7 @@ * * @package framework * @subpackage fields-gridfield + * @property GridState_Data $State The gridstate of this object */ class GridField extends FormField { diff --git a/forms/gridfield/GridFieldAddExistingAutocompleter.php b/forms/gridfield/GridFieldAddExistingAutocompleter.php index fa891feeb..23eb8406b 100644 --- a/forms/gridfield/GridFieldAddExistingAutocompleter.php +++ b/forms/gridfield/GridFieldAddExistingAutocompleter.php @@ -93,20 +93,13 @@ class GridFieldAddExistingAutocompleter * @return string - HTML */ public function getHTMLFragments($gridField) { - $searchState = $gridField->State->GridFieldSearchRelation; $dataClass = $gridField->getList()->dataClass(); $forTemplate = new ArrayData(array()); $forTemplate->Fields = new ArrayList(); - $searchFields = ($this->getSearchFields()) - ? $this->getSearchFields() - : $this->scaffoldSearchFields($dataClass); + $searchField = new TextField('gridfield_relationsearch', _t('GridField.RelationSearch', "Relation search")); - $value = $this->findSingleEntry($gridField, $searchFields, $searchState, $dataClass); - - $searchField = new TextField('gridfield_relationsearch', - _t('GridField.RelationSearch', "Relation search"), $value); $searchField->setAttribute('data-search-url', Controller::join_links($gridField->Link('search'))); $searchField->setAttribute('placeholder', $this->getPlaceholderText($dataClass)); $searchField->addExtraClass('relation-search no-change-track'); @@ -120,7 +113,7 @@ class GridFieldAddExistingAutocompleter $addAction->setAttribute('data-icon', 'chain--plus'); // If an object is not found, disable the action - if(!is_int($gridField->State->GridFieldAddRelation)) { + if(!is_int($gridField->State->GridFieldAddRelation(null))) { $addAction->setReadonly(true); } @@ -139,17 +132,16 @@ class GridFieldAddExistingAutocompleter * @return array */ public function getActions($gridField) { - return array('addto', 'find'); + return array('addto'); } /** - * Manipulate the state to either add a new relation, or doing a small search + * Manipulate the state to add a new relation * * @param GridField $gridField - * @param string $actionName - * @param string $arguments - * @param string $data - * @return string + * @param string $actionName Action identifier, see {@link getActions()}. + * @param array $arguments Arguments relevant for this + * @param array $data All form data */ public function handleAction(GridField $gridField, $actionName, $arguments, $data) { switch($actionName) { @@ -157,10 +149,6 @@ class GridFieldAddExistingAutocompleter if(isset($data['relationID']) && $data['relationID']){ $gridField->State->GridFieldAddRelation = $data['relationID']; } - $gridField->State->GridFieldSearchRelation = ''; - break; - case 'find' && isset($data['autosuggest_search']): - $gridField->State->GridFieldSearchRelation = $data['autosuggest_search']; break; } } @@ -173,15 +161,13 @@ class GridFieldAddExistingAutocompleter * @return SS_List */ public function getManipulatedData(GridField $gridField, SS_List $dataList) { - if(!$gridField->State->GridFieldAddRelation) { + $objectID = $gridField->State->GridFieldAddRelation(null); + if(empty($objectID)) { return $dataList; } - $objectID = Convert::raw2sql($gridField->State->GridFieldAddRelation); - if($objectID) { - $object = DataObject::get_by_id($dataList->dataclass(), $objectID); - if($object) { - $dataList->add($object); - } + $object = DataObject::get_by_id($dataList->dataclass(), $objectID); + if($object) { + $dataList->add($object); } $gridField->State->GridFieldAddRelation = null; return $dataList; @@ -375,33 +361,4 @@ class GridFieldAddExistingAutocompleter public function setResultsLimit($limit) { $this->resultsLimit = $limit; } - - /** - * This will provide a StartsWith search that only returns a value if we are - * matching ONE object only. We wouldn't want to attach used any object to - * the list. - * - * @param GridField $gridField - * @param string $field - * @param string $searchTerm - * @param string $dataclass - * @return string - */ - protected function findSingleEntry($gridField, $field, $searchTerm, $dataclass) { - $fullList = DataList::create($dataclass); - $searchTerm = Convert::raw2sql($searchTerm); - if(!$searchTerm) { - return; - } - $existingList = clone $gridField->getList(); - $searchResults = $fullList->subtract($existingList->limit(0))->filter($field.':StartsWith', $searchTerm); - - // If more than one, skip - if($searchResults->count() != 1) { - return ''; - } - - $gridField->State->GridFieldAddRelation = $searchResults->first()->ID; - return $searchResults->first()->$field; - } } diff --git a/forms/gridfield/GridFieldFilterHeader.php b/forms/gridfield/GridFieldFilterHeader.php index e566ced38..b5b2d9d47 100755 --- a/forms/gridfield/GridFieldFilterHeader.php +++ b/forms/gridfield/GridFieldFilterHeader.php @@ -87,12 +87,12 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan public function getManipulatedData(GridField $gridField, SS_List $dataList) { if(!$this->checkDataType($dataList)) return $dataList; - $state = $gridField->State->GridFieldFilterHeader; - if(!isset($state->Columns)) { + $columns = $gridField->State->GridFieldFilterHeader->Columns(null); + if(empty($columns)) { return $dataList; - } + } - $filterArguments = $state->Columns->toArray(); + $filterArguments = $columns->toArray(); $dataListClone = clone($dataList); foreach($filterArguments as $columnName => $value ) { if($dataList->canFilterBy($columnName) && $value) { diff --git a/forms/gridfield/GridFieldPaginator.php b/forms/gridfield/GridFieldPaginator.php index 4e96cdf27..ef9418442 100755 --- a/forms/gridfield/GridFieldPaginator.php +++ b/forms/gridfield/GridFieldPaginator.php @@ -110,7 +110,7 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu $state = $gridField->State->GridFieldPaginator; // Force the state to the initial page if none is set - if(empty($state->currentPage)) $state->currentPage = 1; + $state->currentPage(1); return $state; } diff --git a/forms/gridfield/GridFieldSortableHeader.php b/forms/gridfield/GridFieldSortableHeader.php index 598394089..a1ee0938a 100644 --- a/forms/gridfield/GridFieldSortableHeader.php +++ b/forms/gridfield/GridFieldSortableHeader.php @@ -98,7 +98,7 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM } if($title && $gridField->getList()->canSortBy($columnField)) { $dir = 'asc'; - if($state->SortColumn == $columnField && $state->SortDirection == 'asc') { + if($state->SortColumn(null) == $columnField && $state->SortDirection('asc') == 'asc') { $dir = 'desc'; } @@ -107,10 +107,10 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM "sort$dir", array('SortColumn' => $columnField) )->addExtraClass('ss-gridfield-sort'); - if($state->SortColumn == $columnField){ + if($state->SortColumn(null) == $columnField){ $field->addExtraClass('ss-gridfield-sorted'); - if($state->SortDirection == 'asc') + if($state->SortDirection('asc') == 'asc') $field->addExtraClass('ss-gridfield-sorted-asc'); else $field->addExtraClass('ss-gridfield-sorted-desc'); @@ -165,9 +165,10 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM if(!$this->checkDataType($dataList)) return $dataList; $state = $gridField->State->GridFieldSortableHeader; - if ($state->SortColumn == "") { + $sortColumn = $state->SortColumn(); + if (empty($sortcolumn)) { return $dataList; } - return $dataList->sort($state->SortColumn, $state->SortDirection); + return $dataList->sort($sortColumn, $state->SortDirection('asc')); } } diff --git a/forms/gridfield/GridState.php b/forms/gridfield/GridState.php index f94719a87..b9edec273 100644 --- a/forms/gridfield/GridState.php +++ b/forms/gridfield/GridState.php @@ -59,7 +59,7 @@ class GridState extends HiddenField { } /** - * @var GridState_Data + * @return GridState_Data */ public function getData() { if(!$this->data) { @@ -136,8 +136,25 @@ class GridState_Data { } public function __get($name) { - if(!isset($this->data[$name])) { - $this->data[$name] = new GridState_Data(); + return $this->getData($name, new GridState_Data()); + } + + public function __call($name, $arguments) { + // Assume first parameter is default value + $default = empty($arguments) ? new GridState_Data() : $arguments[0]; + return $this->getData($name, $default); + } + + /** + * Retrieve the value for the given key + * + * @param string $name The name of the value to retrieve + * @param mixed $default Default value to assign if not set + * @return mixed The value associated with this key, or the value specified by $default if not set + */ + public function getData($name, $default = null) { + if(empty($this->data[$name])) { + $this->data[$name] = $default; } else if(is_array($this->data[$name])) { $this->data[$name] = new GridState_Data($this->data[$name]); } diff --git a/tests/forms/GridFieldTest.php b/tests/forms/GridFieldTest.php index 7f60210d5..b06355531 100644 --- a/tests/forms/GridFieldTest.php +++ b/tests/forms/GridFieldTest.php @@ -106,6 +106,30 @@ class GridFieldTest extends SapphireTest { $this->assertTrue($obj->getState() instanceof GridState_Data); $this->assertTrue($obj->getState(false) instanceof GridState); } + + /** + * Tests usage of nested GridState values + * + * @covers GridState_Data::__get + * @covers GridState_Data::__call + * @covers GridState_Data::getData + */ + public function testGetStateData() { + $obj = new GridField('testfield', 'testfield'); + + // Check value persistance + $this->assertEquals(15, $obj->State->NoValue(15)); + $this->assertEquals(15, $obj->State->NoValue(-1)); + $obj->State->NoValue = 10; + $this->assertEquals(10, $obj->State->NoValue); + $this->assertEquals(10, $obj->State->NoValue(20)); + + // Check nested values + $this->assertInstanceOf('GridState_Data', $obj->State->Nested); + $this->assertInstanceOf('GridState_Data', $obj->State->Nested->DeeperNested()); + $this->assertEquals(3, $obj->State->Nested->DataValue(3)); + $this->assertEquals(10, $obj->State->Nested->DeeperNested->DataValue(10)); + } /** * @covers GridField::getColumns