Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
API GridState_Data values can have default values specified during re…
…trieval.

Fixes issues with GridStata_Data being returned from various states when value types are necessary.
Pruning of dead code from GridFieldAddExistingAutocompleter
Documentation for GridState
  • Loading branch information
tractorcow committed Oct 24, 2013
1 parent 628b920 commit b6b3cd9
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 68 deletions.
17 changes: 17 additions & 0 deletions docs/en/reference/grid-field.md
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions forms/gridfield/GridField.php
Expand Up @@ -17,6 +17,7 @@
*
* @package framework
* @subpackage fields-gridfield
* @property GridState_Data $State The gridstate of this object
*/
class GridField extends FormField {

Expand Down
67 changes: 12 additions & 55 deletions forms/gridfield/GridFieldAddExistingAutocompleter.php
Expand Up @@ -93,20 +93,13 @@ public function __construct($targetFragment = 'before', $searchFields = null) {
* @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');
Expand All @@ -120,7 +113,7 @@ public function getHTMLFragments($gridField) {
$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);
}

Expand All @@ -139,28 +132,23 @@ public function getHTMLFragments($gridField) {
* @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) {
case 'addto':
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;
}
}
Expand All @@ -173,15 +161,13 @@ public function handleAction(GridField $gridField, $actionName, $arguments, $dat
* @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;
Expand Down Expand Up @@ -375,33 +361,4 @@ public function getResultsLimit() {
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;
}
}
8 changes: 4 additions & 4 deletions forms/gridfield/GridFieldFilterHeader.php
Expand Up @@ -87,12 +87,12 @@ public function handleAction(GridField $gridField, $actionName, $arguments, $dat
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) {
Expand Down
2 changes: 1 addition & 1 deletion forms/gridfield/GridFieldPaginator.php
Expand Up @@ -110,7 +110,7 @@ protected function getGridPagerState(GridField $gridField) {
$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;
}
Expand Down
11 changes: 6 additions & 5 deletions forms/gridfield/GridFieldSortableHeader.php
Expand Up @@ -98,7 +98,7 @@ public function getHTMLFragments($gridField) {
}
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';
}

Expand All @@ -107,10 +107,10 @@ public function getHTMLFragments($gridField) {
"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');
Expand Down Expand Up @@ -165,9 +165,10 @@ public function getManipulatedData(GridField $gridField, SS_List $dataList) {
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'));
}
}
23 changes: 20 additions & 3 deletions forms/gridfield/GridState.php
Expand Up @@ -59,7 +59,7 @@ public function setValue($value) {
}

/**
* @var GridState_Data
* @return GridState_Data
*/
public function getData() {
if(!$this->data) {
Expand Down Expand Up @@ -136,8 +136,25 @@ public function __construct($data = array()) {
}

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]);
}
Expand Down
24 changes: 24 additions & 0 deletions tests/forms/GridFieldTest.php
Expand Up @@ -106,6 +106,30 @@ public function testGetState() {
$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
Expand Down

0 comments on commit b6b3cd9

Please sign in to comment.