diff --git a/src/Database/Traits/Multisite.php b/src/Database/Traits/Multisite.php index 7ea94302d..944e715e4 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: `true` * - **delete** - delete all linked records when any record is deleted, default: `true` * * protected $propagatableSync = false; @@ -355,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 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}(); } }