From 9e0c19d4e6eb91f41926dc58c831941d0c07a40c Mon Sep 17 00:00:00 2001 From: Will Rossiter Date: Tue, 15 Aug 2023 09:49:58 +1200 Subject: [PATCH] fix: use a unique field for linking blocks (fixes #55) --- src/Extension/BaseElementExtension.php | 77 ++++++++++++++++++++++---- src/Model/ElementVirtual.php | 12 +++- 2 files changed, 77 insertions(+), 12 deletions(-) diff --git a/src/Extension/BaseElementExtension.php b/src/Extension/BaseElementExtension.php index b041607..6385cb0 100644 --- a/src/Extension/BaseElementExtension.php +++ b/src/Extension/BaseElementExtension.php @@ -2,9 +2,11 @@ namespace DNADesign\ElementalVirtual\Extensions; +use DNADesign\Elemental\Models\BaseElement; use DNADesign\Elemental\Models\ElementalArea; use DNADesign\ElementalVirtual\Forms\ElementalGridFieldDeleteAction; use DNADesign\ElementalVirtual\Model\ElementVirtual; +use SilverStripe\Core\Convert; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\GridField\GridFieldAddExistingAutocompleter; use SilverStripe\Forms\GridField\GridFieldAddNewButton; @@ -13,8 +15,10 @@ use SilverStripe\Forms\GridField\GridFieldDataColumns; use SilverStripe\Forms\GridField\GridFieldDetailForm; use SilverStripe\Forms\LiteralField; +use SilverStripe\Forms\ReadonlyField; use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\DataExtension; +use SilverStripe\ORM\DB; use SilverStripe\ORM\FieldType\DBHTMLText; use SilverStripe\Versioned\Versioned; @@ -31,7 +35,8 @@ class BaseElementExtension extends DataExtension * @var array */ private static $db = [ - 'AvailableGlobally' => 'Boolean(1)' + 'AvailableGlobally' => 'Boolean(1)', + 'VirtualLookupTitle' => 'Varchar(200)' ]; /** @@ -48,6 +53,32 @@ public function populateDefaults() $this->owner->AvailableGlobally = $default; } + + public function requireDefaultRecords() + { + $update = BaseElement::get()->where('VirtualLookupTitle IS NULL AND AvailableGlobally = 1'); + $table = BaseElement::singleton()->baseTable(); + + foreach ($update as $element) { + $title = $element->getVirtualLinkedSummary(); + + // populate the new VirtualLookupTitle + DB::query(sprintf( + "UPDATE %s SET VirtualLookupTitle = '%s' WHERE ID = %d", + $table, + $title, + $element->ID + )); + + DB::query(sprintf( + "UPDATE %s_Live SET VirtualLookupTitle = '%s' WHERE ID = %d", + $table, + $title, + $element->ID + )); + } + } + /** * @param ElementVirtual * @@ -85,7 +116,16 @@ public function getVirtualElements() */ public function getVirtualLinkedSummary() { - return sprintf('%s (%s #%s)', $this->owner->Title, $this->owner->getType(), $this->owner->ID); + $summary = sprintf( + '%s (%s #%s)', + Convert::raw2sql($this->owner->Title), + $this->owner->getType(), + $this->owner->ID + ); + + $this->owner->invokeWithExtensions('updateVirtualLinkedSummary', $summary); + + return $summary; } /** @@ -109,8 +149,17 @@ public function updateCMSFields(FieldList $fields) $global = $fields->dataFieldByName('AvailableGlobally'); if ($global) { - $fields->removeByName('AvailableGlobally'); - $fields->addFieldToTab('Root.Settings', $global); + $desc = _t(__CLASS__ . '.LookupDescription', 'Search for the above title when linking to this element'); + $fields->removeByName([ + 'VirtualLookupTitle', + 'AvailableGlobally' + ]); + + $fields->addFieldsToTab('Root.Settings', [ + $global, + ReadonlyField::create('VirtualLookupTitle', _t(__CLASS__ . '.LookupTitle', 'Virtual Lookup Title')) + ->setDescription($desc) + ]); } if ($virtual = $fields->dataFieldByName('VirtualClones')) { @@ -125,8 +174,8 @@ public function updateCMSFields(FieldList $fields) 'DisplaysOnPage', sprintf( "

" - . _t(__CLASS__ . '.OriginalContentFrom', 'The original content element appears on') - . " %s

", + . _t(__CLASS__ . '.OriginalContentFrom', 'The original content element appears on') + . " %s

", ($ownerPage->hasMethod('CMSEditLink') && $ownerPage->canEdit()) ? $ownerPage->CMSEditLink() : $ownerPage->Link(), $ownerPage->MenuTitle ) @@ -139,11 +188,11 @@ public function updateCMSFields(FieldList $fields) $virtual ->setTitle(_t(__CLASS__ . '.OtherPages', 'Other pages')) ->getConfig() - ->removeComponentsByType(GridFieldAddExistingAutocompleter::class) - ->removeComponentsByType(GridFieldAddNewButton::class) - ->removeComponentsByType(GridFieldDeleteAction::class) - ->removeComponentsByType(GridFieldDetailForm::class) - ->addComponent(new ElementalGridFieldDeleteAction()); + ->removeComponentsByType(GridFieldAddExistingAutocompleter::class) + ->removeComponentsByType(GridFieldAddNewButton::class) + ->removeComponentsByType(GridFieldDeleteAction::class) + ->removeComponentsByType(GridFieldDetailForm::class) + ->addComponent(new ElementalGridFieldDeleteAction()); $virtual->getConfig() ->getComponentByType(GridFieldDataColumns::class) @@ -157,6 +206,12 @@ public function updateCMSFields(FieldList $fields) } } + + public function onBeforeWrite() + { + $this->owner->setField('VirtualLookupTitle', $this->owner->getVirtualLinkedSummary()); + } + /** * Ensure that if there are elements that are virtualised from this element * that we move the original element to replace one of the virtual elements diff --git a/src/Model/ElementVirtual.php b/src/Model/ElementVirtual.php index 9c1e04c..acc9242 100644 --- a/src/Model/ElementVirtual.php +++ b/src/Model/ElementVirtual.php @@ -12,6 +12,8 @@ * * As elemental is based on a natural has_one relation to an object, * this allows the same element to be linked to multiple pages. + * + * @method LinkedElement() BaseElement */ class ElementVirtual extends BaseElement { @@ -31,9 +33,16 @@ class ElementVirtual extends BaseElement private static $singular_name = 'Virtual block'; private static $inline_editable = true; - + private static $controller_template = 'ElementHolder_VirtualLinked'; + /** + * @config + * + * @var string A field to use as the title in the linkable dropdown. Must be a DatabaseField on BaseElement + */ + private static $linkable_title_field = 'VirtualLookupTitle'; + /** * @param BaseElement * @param boolean $isSingleton @@ -70,6 +79,7 @@ public function getCMSFields() ->setIsMultiple(false) ->setCanCreate(false) ->setShouldLazyLoad(true) + ->setTitleField($this->config()->get('linkable_title_field')) ); if ($this->LinkedElementID) {