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.
|
||||
|
||||
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
|
||||
|
@ -17,6 +17,7 @@
|
||||
*
|
||||
* @package framework
|
||||
* @subpackage fields-gridfield
|
||||
* @property GridState_Data $State The gridstate of this object
|
||||
*/
|
||||
class GridField extends FormField {
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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'));
|
||||
}
|
||||
}
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user