From 21c3571a4832facaf60e0c87ce7c330030305f64 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Thu, 17 Oct 2024 16:36:44 +1100 Subject: [PATCH 1/4] Fixes storing an arrays in placeholders Eg: {% put pageTitles = { '0': "Dashboard", '1': "Products", '2': product.name, } %} --- src/Html/BlockBuilder.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Html/BlockBuilder.php b/src/Html/BlockBuilder.php index a46b69528..ec39cdd78 100644 --- a/src/Html/BlockBuilder.php +++ b/src/Html/BlockBuilder.php @@ -3,7 +3,8 @@ use Exception; /** - * BlockBuilder is used for building placeholders and putting content to them + * BlockBuilder is used for building placeholders and putting content to them, + * the content is most often a string, however, it can also store objects. * * @package october\html * @author Alexey Bobkov, Samuel Georges @@ -90,7 +91,7 @@ public function append(string $name, $content) /** * placeholder returns the layout block contents and deletes the block from memory. */ - public function placeholder(string $name, string $default = null): ?string + public function placeholder(string $name, $default = null) { $result = $this->get($name, $default); unset($this->blocks[$name]); @@ -113,13 +114,13 @@ public function has(string $name): bool /** * get returns the layout block contents but not deletes the block from memory */ - public function get(string $name, string $default = null): ?string + public function get(string $name, $default = null) { if (!isset($this->blocks[$name])) { return $default; } - return (string) $this->blocks[$name]; + return $this->blocks[$name]; } /** From da693bc634786528693edaaf57bbad4ad42b3b2b Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Tue, 29 Oct 2024 10:52:04 +1100 Subject: [PATCH 2/4] Sync structures --- src/Database/Traits/Multisite.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Database/Traits/Multisite.php b/src/Database/Traits/Multisite.php index 7ea94302d..3b7adf0fb 100644 --- a/src/Database/Traits/Multisite.php +++ b/src/Database/Traits/Multisite.php @@ -27,6 +27,7 @@ trait Multisite * Set to an array of options for more granular controls: * * - **sync** - logic to sync specific sites, available options: `all`, `group`, `locale` + * - **structure** - enable the sync of tree/sortable structures, default: `false` * - **delete** - delete all linked records when any record is deleted, default: `true` * * protected $propagatableSync = false; From 86f891bdba7129fc9b488633c632a7d12ae3f298 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Tue, 29 Oct 2024 11:36:02 +1100 Subject: [PATCH 3/4] Adds note about idOrModel --- src/Database/Traits/Multisite.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Database/Traits/Multisite.php b/src/Database/Traits/Multisite.php index 3b7adf0fb..944e715e4 100644 --- a/src/Database/Traits/Multisite.php +++ b/src/Database/Traits/Multisite.php @@ -27,7 +27,7 @@ trait Multisite * Set to an array of options for more granular controls: * * - **sync** - logic to sync specific sites, available options: `all`, `group`, `locale` - * - **structure** - enable the sync of tree/sortable structures, default: `false` + * - **structure** - enable the sync of tree/sortable structures, default: `true` * - **delete** - delete all linked records when any record is deleted, default: `true` * * protected $propagatableSync = false; @@ -356,6 +356,9 @@ public function getMultisiteSyncSites() * For example, finding a model using attributes from another site, or finding * all connected models for all sites. * + * If the value is provided as a string, it must be the ID from the primary record, + * in other words: taken from `site_root_id` not from the `id` column. + * * @param \Illuminate\Database\Eloquent\Builder $query * @param string|\Illuminate\Database\Eloquent\Model $idOrModel * @return \Illuminate\Database\Eloquent\Builder From 0b21726d6d8e9a13d689863274a715c57e3f83bc Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Tue, 29 Oct 2024 12:59:01 +1100 Subject: [PATCH 4/4] Fixes structure propagation support --- src/Database/Traits/SimpleTree.php | 9 +++++++++ src/Database/Traits/Sortable.php | 12 +++++++++++- src/Database/TreeCollection.php | 22 +++++++++++++++++++--- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/Database/Traits/SimpleTree.php b/src/Database/Traits/SimpleTree.php index 181525efb..e3a0aaf60 100644 --- a/src/Database/Traits/SimpleTree.php +++ b/src/Database/Traits/SimpleTree.php @@ -58,6 +58,15 @@ public function initializeSimpleTree() 'key' => $this->getParentColumnName(), 'replicate' => false ]; + + // Multisite + if ( + $this->isClassInstanceOf(\October\Contracts\Database\MultisiteInterface::class) && + $this->isMultisiteSyncEnabled() && + $this->getMultisiteConfig('structure', true) + ) { + $this->addPropagatable(['children', 'parent']); + } } /** diff --git a/src/Database/Traits/Sortable.php b/src/Database/Traits/Sortable.php index 2c274da47..c63d90daa 100644 --- a/src/Database/Traits/Sortable.php +++ b/src/Database/Traits/Sortable.php @@ -68,6 +68,16 @@ public function setSortableOrder($itemIds, $referencePool = null) throw new Exception('Invalid setSortableOrder call - count of itemIds do not match count of referencePool'); } + // Multisite + $keyName = $this->getKeyName(); + if ( + $this->isClassInstanceOf(\October\Contracts\Database\MultisiteInterface::class) && + $this->isMultisiteSyncEnabled() && + $this->getMultisiteConfig('structure', true) + ) { + $keyName = 'site_root_id'; + } + $upsert = []; foreach ($itemIds as $id) { $sortOrder = $sortKeyMap[$id] ?? null; @@ -79,7 +89,7 @@ public function setSortableOrder($itemIds, $referencePool = null) if ($upsert) { foreach ($upsert as $update) { $this->newQuery() - ->where($this->getKeyName(), $update['id']) + ->where($keyName, $update['id']) ->update([$this->getSortOrderColumn() => $update['sort_order']]); } } diff --git a/src/Database/TreeCollection.php b/src/Database/TreeCollection.php index 55ab24501..d67f7e421 100644 --- a/src/Database/TreeCollection.php +++ b/src/Database/TreeCollection.php @@ -19,8 +19,24 @@ class TreeCollection extends Collection */ public function toNested($removeOrphans = true) { + // Multisite + $keyMethod = 'getKey'; + if ( + ($model = $this->first()) && + $model->isClassInstanceOf(\October\Contracts\Database\MultisiteInterface::class) && + $model->isAttributePropagatable('children') && + $model->isAttributePropagatable('parent') + ) { + $keyMethod = 'getMultisiteKey'; + } + + // Get dictionary + $collection = []; + foreach ($this as $item) { + $collection[$item->{$keyMethod}()] = $item; + } + // Set new collection for "children" relations - $collection = $this->getDictionary(); foreach ($collection as $key => $model) { $model->setRelation('children', new Collection); } @@ -34,10 +50,10 @@ public function toNested($removeOrphans = true) if (array_key_exists($parentKey, $collection)) { $collection[$parentKey]->children[] = $model; - $nestedKeys[] = $model->getKey(); + $nestedKeys[] = $model->{$keyMethod}(); } elseif ($removeOrphans) { - $nestedKeys[] = $model->getKey(); + $nestedKeys[] = $model->{$keyMethod}(); } }