From 547ec8aa506793d3449de878bb0121dfb3e5ab88 Mon Sep 17 00:00:00 2001 From: Mo Alsharaf Date: Wed, 1 Jun 2022 13:00:23 +1200 Subject: [PATCH] ENH: Add performance fixes on saving editable columns - Use one query to fetch all items needed to be saved. - Only save items that are changed. --- src/GridFieldEditableColumns.php | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/GridFieldEditableColumns.php b/src/GridFieldEditableColumns.php index 9be290a..52057da 100644 --- a/src/GridFieldEditableColumns.php +++ b/src/GridFieldEditableColumns.php @@ -19,10 +19,10 @@ use SilverStripe\Forms\GridField\GridField_URLHandler; use SilverStripe\Forms\HTMLEditor\HTMLEditorField; use SilverStripe\Forms\LiteralField; use SilverStripe\Forms\ReadonlyField; +use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\DataList; use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObjectInterface; -use SilverStripe\ORM\FieldType\DBField; use SilverStripe\ORM\ManyManyList; /** @@ -130,14 +130,23 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements /** @var GridFieldOrderableRows $sortable */ $sortable = $grid->getConfig()->getComponentByType(GridFieldOrderableRows::class); + // Fetch the items before processing them + $ids = array_keys($value[self::POST_KEY]); + if (empty($ids)) { + return; + } + $itemsCollection = ArrayList::create($list->filter('ID', $ids)->toArray()); + foreach ($value[self::POST_KEY] as $id => $fields) { if (!is_numeric($id) || !is_array($fields)) { continue; } - $item = $list->byID($id); + // Find the item from the fetched collection of items + $item = $itemsCollection->find('ID', $id); - if (!$item || !$item->canEdit()) { + // Skip not found item, or don't have any changed fields, or current user can't edit + if (!$item || !$this->isChanged($item, $fields) || !$item->canEdit()) { continue; } @@ -323,4 +332,18 @@ class GridFieldEditableColumns extends GridFieldDataColumns implements $name ); } + + /** + * Whether or not an object in the grid field has changed data. + */ + private function isChanged(DataObject $item, array $fields): bool + { + foreach ($fields as $name => $value) { + if ((string) $item->getField($name) !== (string) $value) { + return true; + } + } + + return false; + } }