FIX: Readonly transformation of lazy-loaded searchable dropdown (#11297)

Co-authored-by: johannes.hammersen <Johannes.Hammersen@funkemedien.de>
This commit is contained in:
Johannes Hammersen 2024-07-26 00:16:23 +02:00 committed by GitHub
parent 8a576f91be
commit fb7b1734eb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 64 additions and 0 deletions

View File

@ -586,4 +586,18 @@ trait SearchableDropdownTrait
} }
return $options; 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;
}
} }

View File

@ -0,0 +1,50 @@
<?php
namespace SilverStripe\Forms;
use SilverStripe\Core\Convert;
use SilverStripe\ORM\ArrayLib;
use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataList;
/**
* Read-only complement of {@link SearchableDropdownField} and {@link SearchableMultiDropdownField}.
*
* Shows the "human value" of the SearchableDropdownField for the currently selected
* values.
*/
class SearchableLookupField extends LookupField
{
private ?DataList $sourceList = null;
/**
* To retain compatibility with ancestor getSource() this returns an array of only the selected values
*/
public function getSource(): array
{
$values = $this->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;
}
}