mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #2522 from tractorcow/pulls/3.2-gridstate-api-fix
API GridState_Data values can have default values specified during retrieval.
This commit is contained in:
commit
723c4e3f4e
@ -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.
|
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
|
## Permissions
|
||||||
|
|
||||||
Since GridField is mostly used in the CMS, the controller managing a GridField instance
|
Since GridField is mostly used in the CMS, the controller managing a GridField instance
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
*
|
*
|
||||||
* @package framework
|
* @package framework
|
||||||
* @subpackage fields-gridfield
|
* @subpackage fields-gridfield
|
||||||
|
* @property GridState_Data $State The gridstate of this object
|
||||||
*/
|
*/
|
||||||
class GridField extends FormField {
|
class GridField extends FormField {
|
||||||
|
|
||||||
|
@ -93,20 +93,13 @@ class GridFieldAddExistingAutocompleter
|
|||||||
* @return string - HTML
|
* @return string - HTML
|
||||||
*/
|
*/
|
||||||
public function getHTMLFragments($gridField) {
|
public function getHTMLFragments($gridField) {
|
||||||
$searchState = $gridField->State->GridFieldSearchRelation;
|
|
||||||
$dataClass = $gridField->getList()->dataClass();
|
$dataClass = $gridField->getList()->dataClass();
|
||||||
|
|
||||||
$forTemplate = new ArrayData(array());
|
$forTemplate = new ArrayData(array());
|
||||||
$forTemplate->Fields = new ArrayList();
|
$forTemplate->Fields = new ArrayList();
|
||||||
|
|
||||||
$searchFields = ($this->getSearchFields())
|
$searchField = new TextField('gridfield_relationsearch', _t('GridField.RelationSearch', "Relation search"));
|
||||||
? $this->getSearchFields()
|
|
||||||
: $this->scaffoldSearchFields($dataClass);
|
|
||||||
|
|
||||||
$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('data-search-url', Controller::join_links($gridField->Link('search')));
|
||||||
$searchField->setAttribute('placeholder', $this->getPlaceholderText($dataClass));
|
$searchField->setAttribute('placeholder', $this->getPlaceholderText($dataClass));
|
||||||
$searchField->addExtraClass('relation-search no-change-track');
|
$searchField->addExtraClass('relation-search no-change-track');
|
||||||
@ -120,7 +113,7 @@ class GridFieldAddExistingAutocompleter
|
|||||||
$addAction->setAttribute('data-icon', 'chain--plus');
|
$addAction->setAttribute('data-icon', 'chain--plus');
|
||||||
|
|
||||||
// If an object is not found, disable the action
|
// 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);
|
$addAction->setReadonly(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,17 +132,16 @@ class GridFieldAddExistingAutocompleter
|
|||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getActions($gridField) {
|
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 GridField $gridField
|
||||||
* @param string $actionName
|
* @param string $actionName Action identifier, see {@link getActions()}.
|
||||||
* @param string $arguments
|
* @param array $arguments Arguments relevant for this
|
||||||
* @param string $data
|
* @param array $data All form data
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
||||||
switch($actionName) {
|
switch($actionName) {
|
||||||
@ -157,10 +149,6 @@ class GridFieldAddExistingAutocompleter
|
|||||||
if(isset($data['relationID']) && $data['relationID']){
|
if(isset($data['relationID']) && $data['relationID']){
|
||||||
$gridField->State->GridFieldAddRelation = $data['relationID'];
|
$gridField->State->GridFieldAddRelation = $data['relationID'];
|
||||||
}
|
}
|
||||||
$gridField->State->GridFieldSearchRelation = '';
|
|
||||||
break;
|
|
||||||
case 'find' && isset($data['autosuggest_search']):
|
|
||||||
$gridField->State->GridFieldSearchRelation = $data['autosuggest_search'];
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,16 +161,14 @@ class GridFieldAddExistingAutocompleter
|
|||||||
* @return SS_List
|
* @return SS_List
|
||||||
*/
|
*/
|
||||||
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
||||||
if(!$gridField->State->GridFieldAddRelation) {
|
$objectID = $gridField->State->GridFieldAddRelation(null);
|
||||||
|
if(empty($objectID)) {
|
||||||
return $dataList;
|
return $dataList;
|
||||||
}
|
}
|
||||||
$objectID = Convert::raw2sql($gridField->State->GridFieldAddRelation);
|
|
||||||
if($objectID) {
|
|
||||||
$object = DataObject::get_by_id($dataList->dataclass(), $objectID);
|
$object = DataObject::get_by_id($dataList->dataclass(), $objectID);
|
||||||
if($object) {
|
if($object) {
|
||||||
$dataList->add($object);
|
$dataList->add($object);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
$gridField->State->GridFieldAddRelation = null;
|
$gridField->State->GridFieldAddRelation = null;
|
||||||
return $dataList;
|
return $dataList;
|
||||||
}
|
}
|
||||||
@ -375,33 +361,4 @@ class GridFieldAddExistingAutocompleter
|
|||||||
public function setResultsLimit($limit) {
|
public function setResultsLimit($limit) {
|
||||||
$this->resultsLimit = $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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -87,12 +87,12 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
|||||||
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
||||||
if(!$this->checkDataType($dataList)) return $dataList;
|
if(!$this->checkDataType($dataList)) return $dataList;
|
||||||
|
|
||||||
$state = $gridField->State->GridFieldFilterHeader;
|
$columns = $gridField->State->GridFieldFilterHeader->Columns(null);
|
||||||
if(!isset($state->Columns)) {
|
if(empty($columns)) {
|
||||||
return $dataList;
|
return $dataList;
|
||||||
}
|
}
|
||||||
|
|
||||||
$filterArguments = $state->Columns->toArray();
|
$filterArguments = $columns->toArray();
|
||||||
$dataListClone = clone($dataList);
|
$dataListClone = clone($dataList);
|
||||||
foreach($filterArguments as $columnName => $value ) {
|
foreach($filterArguments as $columnName => $value ) {
|
||||||
if($dataList->canFilterBy($columnName) && $value) {
|
if($dataList->canFilterBy($columnName) && $value) {
|
||||||
|
@ -110,7 +110,7 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu
|
|||||||
$state = $gridField->State->GridFieldPaginator;
|
$state = $gridField->State->GridFieldPaginator;
|
||||||
|
|
||||||
// Force the state to the initial page if none is set
|
// Force the state to the initial page if none is set
|
||||||
if(empty($state->currentPage)) $state->currentPage = 1;
|
$state->currentPage(1);
|
||||||
|
|
||||||
return $state;
|
return $state;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
|
|||||||
}
|
}
|
||||||
if($title && $gridField->getList()->canSortBy($columnField)) {
|
if($title && $gridField->getList()->canSortBy($columnField)) {
|
||||||
$dir = 'asc';
|
$dir = 'asc';
|
||||||
if($state->SortColumn == $columnField && $state->SortDirection == 'asc') {
|
if($state->SortColumn(null) == $columnField && $state->SortDirection('asc') == 'asc') {
|
||||||
$dir = 'desc';
|
$dir = 'desc';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,10 +107,10 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
|
|||||||
"sort$dir", array('SortColumn' => $columnField)
|
"sort$dir", array('SortColumn' => $columnField)
|
||||||
)->addExtraClass('ss-gridfield-sort');
|
)->addExtraClass('ss-gridfield-sort');
|
||||||
|
|
||||||
if($state->SortColumn == $columnField){
|
if($state->SortColumn(null) == $columnField){
|
||||||
$field->addExtraClass('ss-gridfield-sorted');
|
$field->addExtraClass('ss-gridfield-sorted');
|
||||||
|
|
||||||
if($state->SortDirection == 'asc')
|
if($state->SortDirection('asc') == 'asc')
|
||||||
$field->addExtraClass('ss-gridfield-sorted-asc');
|
$field->addExtraClass('ss-gridfield-sorted-asc');
|
||||||
else
|
else
|
||||||
$field->addExtraClass('ss-gridfield-sorted-desc');
|
$field->addExtraClass('ss-gridfield-sorted-desc');
|
||||||
@ -165,9 +165,10 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
|
|||||||
if(!$this->checkDataType($dataList)) return $dataList;
|
if(!$this->checkDataType($dataList)) return $dataList;
|
||||||
|
|
||||||
$state = $gridField->State->GridFieldSortableHeader;
|
$state = $gridField->State->GridFieldSortableHeader;
|
||||||
if ($state->SortColumn == "") {
|
$sortColumn = $state->SortColumn();
|
||||||
|
if (empty($sortcolumn)) {
|
||||||
return $dataList;
|
return $dataList;
|
||||||
}
|
}
|
||||||
return $dataList->sort($state->SortColumn, $state->SortDirection);
|
return $dataList->sort($sortColumn, $state->SortDirection('asc'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ class GridState extends HiddenField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var GridState_Data
|
* @return GridState_Data
|
||||||
*/
|
*/
|
||||||
public function getData() {
|
public function getData() {
|
||||||
if(!$this->data) {
|
if(!$this->data) {
|
||||||
@ -136,8 +136,25 @@ class GridState_Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function __get($name) {
|
public function __get($name) {
|
||||||
if(!isset($this->data[$name])) {
|
return $this->getData($name, new GridState_Data());
|
||||||
$this->data[$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])) {
|
} else if(is_array($this->data[$name])) {
|
||||||
$this->data[$name] = new GridState_Data($this->data[$name]);
|
$this->data[$name] = new GridState_Data($this->data[$name]);
|
||||||
}
|
}
|
||||||
|
@ -107,6 +107,30 @@ class GridFieldTest extends SapphireTest {
|
|||||||
$this->assertTrue($obj->getState(false) instanceof GridState);
|
$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
|
* @covers GridField::getColumns
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user