From 69882220cfc47f89ae53e7052ec5dc0d01830a41 Mon Sep 17 00:00:00 2001 From: "johannes.hammersen" Date: Tue, 2 Jul 2024 11:14:11 +0200 Subject: [PATCH] FIX: Readonly transformation of lazy-loaded searchable dropdown --- src/Forms/SearchableDropdownTrait.php | 14 ++++++++ src/Forms/SearchableLookupField.php | 50 +++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/Forms/SearchableLookupField.php diff --git a/src/Forms/SearchableDropdownTrait.php b/src/Forms/SearchableDropdownTrait.php index 97923f711d0..2f6014d0dd6 100644 --- a/src/Forms/SearchableDropdownTrait.php +++ b/src/Forms/SearchableDropdownTrait.php @@ -586,4 +586,18 @@ private function updateOptionsForSchema( } return $options; } + + public function performReadonlyTransformation() + { + // This is calling a non-static method statically + // using call_user_func() here to prevent an IDE warning + // The reason we're calling FormField::castedCopy directly is to prevent an ancestor + // call to $this->getSource() which will load the entire DataList into memory which + // causes issues with very large datasets and isn't needed when the field is read-only + $field = call_user_func('SilverStripe\\Forms\\FormField::castedCopy', SearchableLookupField::class); + $field->setSource($this->sourceList); + $field->setReadonly(true); + + return $field; + } } diff --git a/src/Forms/SearchableLookupField.php b/src/Forms/SearchableLookupField.php new file mode 100644 index 00000000000..85188045a61 --- /dev/null +++ b/src/Forms/SearchableLookupField.php @@ -0,0 +1,50 @@ +getValueArray(); + if (empty($values) || $this->sourceList === null) { + $selectedValuesList = ArrayList::create(); + } else { + $selectedValuesList = $this->sourceList->filterAny(['ID' => $values]); + } + return $this->getListMap($selectedValuesList); + } + + /** + * @param mixed $source + */ + public function setSource($source): static + { + // Setting to $this->sourceList instead of $this->source because SelectField.source + // docblock type is array|ArrayAccess i.e. does not allow DataList + if ($source instanceof DataList) { + $this->sourceList = $source; + } else { + $this->sourceList = null; + } + return $this; + } +}