Skip to content

Commit

Permalink
ENH: Add performance fixes on saving editable columns
Browse files Browse the repository at this point in the history
- Use one query to fetch all items needed to be saved.
- Only save items that are changed.
  • Loading branch information
satrun77 committed Jun 16, 2022
1 parent 71d60b0 commit 547ec8a
Showing 1 changed file with 26 additions and 3 deletions.
29 changes: 26 additions & 3 deletions src/GridFieldEditableColumns.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
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;

/**
Expand Down Expand Up @@ -130,14 +130,23 @@ public function handleSave(GridField $grid, DataObjectInterface $record)
/** @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;
}

Expand Down Expand Up @@ -323,4 +332,18 @@ protected function getFieldName($name, GridField $grid, DataObjectInterface $rec
$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;
}
}

0 comments on commit 547ec8a

Please sign in to comment.