From fb7b1734eb58f01a466bdb002c50647d221332bf Mon Sep 17 00:00:00 2001 From: Johannes Hammersen Date: Fri, 26 Jul 2024 00:16:23 +0200 Subject: [PATCH] FIX: Readonly transformation of lazy-loaded searchable dropdown (#11297) Co-authored-by: johannes.hammersen --- 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 97923f711..2f6014d0d 100644 --- a/src/Forms/SearchableDropdownTrait.php +++ b/src/Forms/SearchableDropdownTrait.php @@ -586,4 +586,18 @@ trait SearchableDropdownTrait } 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 000000000..85188045a --- /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; + } +}