Merge pull request #10331 from creative-commoners/pulls/4/gridfield-keep-state

ENH Restore gridfield state from get vars (POC)
This commit is contained in:
Guy Sartorelli 2022-07-29 11:33:19 +12:00 committed by GitHub
commit c7504aa337
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 143 additions and 13 deletions

View File

@ -4,10 +4,13 @@ namespace SilverStripe\Forms\GridField;
use InvalidArgumentException;
use LogicException;
use SilverStripe\Control\Controller;
use SilverStripe\Control\HasRequestHandler;
use SilverStripe\Control\HTTP;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Control\NullHTTPRequest;
use SilverStripe\Control\RequestHandler;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injector;
@ -45,6 +48,8 @@ use SilverStripe\View\HTML;
*/
class GridField extends FormField
{
use GridFieldStateAware;
/**
* @var array
*/
@ -435,6 +440,8 @@ class GridField extends FormField
{
$this->state = new GridState($this);
$this->addStateFromRequest();
$data = $this->state->getData();
foreach ($this->getComponents() as $item) {
@ -444,6 +451,56 @@ class GridField extends FormField
}
}
/**
* Adds state for this gridfield from the request variables.
*
* If there is state already set on this GridField, that takes precedent
* over state from the request.
*/
private function addStateFromRequest(): void
{
$request = $this->getRequest();
if (($request instanceof NullHTTPRequest) && Controller::has_curr()) {
$request = Controller::curr()->getRequest();
}
$stateStr = $this->getStateManager()->getStateFromRequest($this, $request);
if ($stateStr) {
$oldState = $this->getState(false);
// Create a dummy state so that we can merge the current state with the request state.
$newState = new GridState($this, $stateStr);
// Put the current state on top of the request state.
$newState->setValue($oldState->Value());
$this->state = $newState;
}
}
/**
* Add GET and POST parameters pertaining to other gridfield's state to the URL.
* Also add this gridfield's own state to the URL.
*/
public function addAllStateToUrl(string $link): string
{
$request = $this->getRequest();
if ($request->param('Action')) {
$requestVars = $request->requestVars();
$params = [];
foreach ($requestVars as $key => $val) {
// Get gridfield states that are for other gridfields
if (stripos($key, 'gridState') === 0
&& $key !== $this->getStateManager()->getStateKey($this)
) {
$params[$key] = $val;
}
}
foreach ($params as $key => $val) {
$link = HTTP::setGetVar($key, $val, $link);
}
}
return $this->getStateManager()->addStateToURL($this, $link);
}
/**
* Returns the whole gridfield rendered with all the attached components.
*

View File

@ -481,7 +481,7 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler
$backlink = $toplevelController->Link();
}
return $backlink;
return $this->gridField->addAllStateToUrl($backlink);
}
/**
@ -817,6 +817,12 @@ class GridFieldDetailForm_ItemRequest extends RequestHandler
]));
}
foreach ($items as $item) {
if ($item->Link) {
$item->Link = $this->gridField->addAllStateToUrl($item->Link);
}
}
$this->extend('updateBreadcrumbs', $items);
return $items;
}

View File

@ -61,6 +61,7 @@ class GridFieldEditButton extends AbstractGridFieldComponent implements GridFiel
/**
* @inheritdoc
* @param bool $addState DEPRECATED: Should be removed in major release
*/
public function getUrl($gridField, $record, $columnName, $addState = true)
{
@ -70,11 +71,7 @@ class GridFieldEditButton extends AbstractGridFieldComponent implements GridFiel
'edit'
);
if ($addState) {
$link = $this->getStateManager()->addStateToURL($gridField, $link);
}
return $link;
return $gridField->addAllStateToUrl($link, $addState);
}
/**

View File

@ -44,7 +44,8 @@ class GridFieldViewButton extends AbstractGridFieldComponent implements GridFiel
*/
public function getUrl($gridField, $record, $columnName)
{
return Controller::join_links($gridField->Link('item'), $record->ID, 'view');
$link = Controller::join_links($gridField->Link('item'), $record->ID, 'view');
return $gridField->addAllStateToUrl($link);
}
public function augmentColumns($field, &$columns)

View File

@ -341,10 +341,11 @@ class GridFieldDetailFormTest extends FunctionalTest
);
$this->assertEquals(
sprintf(
'GridFieldDetailFormTest_GroupController/Form/field/testfield/item/%d/ItemEditForm/field/People'
. '/item/%d/edit',
'/GridFieldDetailFormTest_GroupController/Form/field/testfield/item/%d/ItemEditForm/field/People'
. '/item/%d/edit%s',
$group->ID,
$person->ID
$person->ID,
'?gridState-People-1=%7B%22GridFieldAddRelation%22%3Anull%7D'
),
(string)$personEditLink[0]['href']
);
@ -359,11 +360,12 @@ class GridFieldDetailFormTest extends FunctionalTest
);
$this->assertEquals(
sprintf(
'GridFieldDetailFormTest_GroupController/Form/field/testfield/item/%d/ItemEditForm/field/People'
. '/item/%d/ItemEditForm/field/Categories/item/%d/edit',
'/GridFieldDetailFormTest_GroupController/Form/field/testfield/item/%d/ItemEditForm/field/People'
. '/item/%d/ItemEditForm/field/Categories/item/%d/edit%s',
$group->ID,
$person->ID,
$category->ID
$category->ID,
'?gridState-Categories-2=%7B%22GridFieldAddRelation%22%3Anull%7D'
),
(string)$categoryEditLink[0]['href']
);

View File

@ -4,6 +4,8 @@ namespace SilverStripe\Forms\Tests\GridField;
use InvalidArgumentException;
use LogicException;
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Dev\CSSContentParser;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldList;
@ -659,4 +661,69 @@ class GridFieldTest extends SapphireTest
$gridfieldOutput = $gridField->FieldHolder();
$this->assertStringNotContainsString('<p class="message ' . ValidationResult::TYPE_ERROR . '">', $gridfieldOutput);
}
public function testAddRequestToURL()
{
$gridField = new GridField('testfield', 'testfield');
$link = Controller::join_links('class-name', 'item', '1');
// The actual URL path here is arbitrary
$request = new HTTPRequest(
'POST',
'admin/gridfield',
[
'gridState-Test-0' => [
'State' => [
'Column' => 'Name'
],
]
],
[
'action_gridFieldAlterAction?StateID=1',
'ActionState' => json_encode([
'grid' => $gridField->getName(),
'actionName' => 'edit',
'args' => [],
]),
'gridState-Test-1' => [
'State' => [
'Column' => 'Name'
],
]
]
);
$request->setRouteParams(['Action' => 'edit']);
$gridField->setRequest($request);
$this->assertEquals(
$gridField->addAllStateToUrl($link),
'/class-name/item/1?gridState-Test-0%5BState%5D%5BColumn%5D=Name&gridState-Test-1%5BState%5D%5BColumn%5D=Name'
);
// The actual URL path here is arbitrary
$request = new HTTPRequest(
'GET',
'admin/gridfield',
[
'action_gridFieldAlterAction?StateID=1',
'ActionState' => json_encode([
'grid' => $gridField->getName(),
'actionName' => 'edit',
'args' => [],
]),
'gridState-Test' => [
'State' => [
'Column' => 'Name'
],
]
]
);
$request->setRouteParams(['Action' => 'edit']);
$gridField->setRequest($request);
$this->assertEquals(
$gridField->addAllStateToUrl($link),
'/class-name/item/1?gridState-Test%5BState%5D%5BColumn%5D=Name'
);
}
}