Don't assume records are DataObjects in nested gridfields.

Also don't assume the list is filterable.
This commit is contained in:
Niklas Forsdahl 2024-04-24 09:57:24 +03:00
parent f7b8aea3f8
commit c517c693f9

View File

@ -9,6 +9,7 @@ use SilverStripe\Control\Director;
use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\HTTPResponse;
use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Control\HTTPResponse_Exception;
use SilverStripe\Control\RequestHandler;
use SilverStripe\Core\Config\Configurable; use SilverStripe\Core\Config\Configurable;
use SilverStripe\Forms\GridField\AbstractGridFieldComponent; use SilverStripe\Forms\GridField\AbstractGridFieldComponent;
use SilverStripe\Forms\GridField\GridField; use SilverStripe\Forms\GridField\GridField;
@ -21,6 +22,7 @@ use SilverStripe\Forms\GridField\GridFieldStateAware;
use SilverStripe\ORM\DataList; use SilverStripe\ORM\DataList;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataObjectInterface; use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\ORM\Filterable;
use SilverStripe\ORM\Hierarchy\Hierarchy; use SilverStripe\ORM\Hierarchy\Hierarchy;
use SilverStripe\ORM\SS_List; use SilverStripe\ORM\SS_List;
use SilverStripe\Versioned\Versioned; use SilverStripe\Versioned\Versioned;
@ -294,13 +296,23 @@ class GridFieldNestedForm extends AbstractGridFieldComponent implements
} }
/** /**
* @param GridField $field * @param GridField $gridField
* @return array
*/ */
public function getHTMLFragments($field) public function getHTMLFragments($gridField)
{ {
if (DataObject::has_extension($field->getModelClass(), Hierarchy::class)) { /**
$field->setAttribute('data-url-movetoparent', $field->Link('movetoparent')); * If we have a DataObject with the hierarchy extension, we want to allow moving items to a new parent.
* This is enabled by setting the data-url-movetoparent attribute on the grid field, so that the client
* javascript can handle the move.
* Implemented in getHTMLFragments since this attribute needs to be added before any rendering happens.
*/
if (is_a($gridField->getModelClass(), DataObject::class, true)
&& DataObject::has_extension($gridField->getModelClass(), Hierarchy::class)
) {
$gridField->setAttribute('data-url-movetoparent', $gridField->Link('movetoparent'));
} }
return [];
} }
/** /**
@ -380,16 +392,17 @@ class GridFieldNestedForm extends AbstractGridFieldComponent implements
* @param GridField $gridField * @param GridField $gridField
* @param HTTPRequest|null $request * @param HTTPRequest|null $request
* @param ViewableData|null $record * @param ViewableData|null $record
* @return HTTPResponse * @return HTTPResponse|RequestHandler
*/ */
public function handleNestedItem(GridField $gridField, $request = null, $record = null) public function handleNestedItem(GridField $gridField, $request = null, $record = null)
{ {
if ($this->atMaxNestingLevel($gridField)) { if ($this->atMaxNestingLevel($gridField)) {
throw new Exception('Max nesting level reached'); throw new Exception('Max nesting level reached');
} }
if (!$record && $request) { $list = $gridField->getList();
if (!$record && $request && $list instanceof Filterable) {
$recordID = $request->param('RecordID'); $recordID = $request->param('RecordID');
$record = $gridField->getList()->byID($recordID); $record = $list->byID($recordID);
} }
if (!$record) { if (!$record) {
return ''; return '';
@ -436,9 +449,10 @@ class GridFieldNestedForm extends AbstractGridFieldComponent implements
*/ */
public function toggleNestedItem(GridField $gridField, $request = null, $record = null) public function toggleNestedItem(GridField $gridField, $request = null, $record = null)
{ {
if (!$record) { $list = $gridField->getList();
if (!$record && $request && $list instanceof Filterable) {
$recordID = $request->param('RecordID'); $recordID = $request->param('RecordID');
$record = $gridField->getList()->byID($recordID); $record = $list->byID($recordID);
} }
$manager = $this->getStateManager(); $manager = $this->getStateManager();
if ($gridStateStr = $manager->getStateFromRequest($gridField, $request)) { if ($gridStateStr = $manager->getStateFromRequest($gridField, $request)) {
@ -490,11 +504,13 @@ class GridFieldNestedForm extends AbstractGridFieldComponent implements
$gridField->getState(false)->setValue($gridStateStr); $gridField->getState(false)->setValue($gridStateStr);
} }
foreach ($request->postVars() as $key => $val) { foreach ($request->postVars() as $key => $val) {
if (preg_match("/{$gridField->getName()}-{$postKey}-(\d+)/", $key, $matches)) { $list = $gridField->getList();
if ($list instanceof Filterable && preg_match("/{$gridField->getName()}-{$postKey}-(\d+)/", $key, $matches)) {
$recordID = $matches[1]; $recordID = $matches[1];
$nestedData = $val; $nestedData = $val;
$record = $gridField->getList()->byID($recordID); $record = $list->byID($recordID);
if ($record) { if ($record) {
/** @var GridField */
$nestedGridField = $this->handleNestedItem($gridField, null, $record); $nestedGridField = $this->handleNestedItem($gridField, null, $record);
$nestedGridField->setValue($nestedData); $nestedGridField->setValue($nestedData);
$nestedGridField->saveInto($record); $nestedGridField->saveInto($record);
@ -506,8 +522,10 @@ class GridFieldNestedForm extends AbstractGridFieldComponent implements
public function getManipulatedData(GridField $gridField, SS_List $dataList) public function getManipulatedData(GridField $gridField, SS_List $dataList)
{ {
if ($this->relationName == 'Children' if ($this->relationName == 'Children'
&& is_a($gridField->getModelClass(), DataObject::class, true)
&& DataObject::has_extension($gridField->getModelClass(), Hierarchy::class) && DataObject::has_extension($gridField->getModelClass(), Hierarchy::class)
&& $gridField->getForm()->getController() instanceof ModelAdmin && $gridField->getForm()->getController() instanceof ModelAdmin
&& $dataList instanceof Filterable
) { ) {
$dataList = $dataList->filter('ParentID', 0); $dataList = $dataList->filter('ParentID', 0);
} }