From 69e2ba9dbca7d9edfa5e13a549e028801830ceb9 Mon Sep 17 00:00:00 2001 From: Tyler Date: Thu, 5 Sep 2024 14:34:03 -0500 Subject: [PATCH] #259: Added method to load in relations. --- src/Eloquent/Collection.php | 55 +++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/Eloquent/Collection.php b/src/Eloquent/Collection.php index 06dc76d..156ebb0 100644 --- a/src/Eloquent/Collection.php +++ b/src/Eloquent/Collection.php @@ -49,4 +49,59 @@ public function toTree($childrenRelation = 'children') return $tree; } + + /** + * Load parent/anscestor relations already present in the tree. + * + * @return static + */ + public function loadTreePathRelations() + { + $instance = $this->first(); + + if (is_null($instance)) { + return $this; + } + + if (! method_exists($instance, 'getPathName') || ! method_exists($instance, 'getPathSeparator')) { + throw new RuntimeException(sprintf( + 'Model [%s] is not have recusive relations.', + $instance::class, + )); + } + + $keyName = $instance->getKeyName(); + $pathName = $instance->getPathName(); + $pathSeparator = $instance->getPathSeparator(); + + $lookup = $this->keyBy($keyName); + + $keys = $this + ->pluck($pathName) + ->flatMap(fn (string $path): array => explode($pathSeparator, $path)) + ->unique() + ->values(); + + $missing = $keys->diff($lookup->modelKeys()); + + if ($missing->isNotEmpty()) { + $lookup->merge($instance->newQuery()->findMany($missing)->keyBy($keyName)); + } + + foreach ($this->all() as $model) { + $path = array_reverse(explode($pathSeparator, $model->getAttribute($pathName))); + + $ancestorsAndSelf = array_reduce( + $path, + fn ($collection, $step) => $collection->push($lookup[$step] ?? null), + $instance->newCollection(), + ); + + $model->setRelation('parent', count($path) > 1 ? $lookup[$path[1]] : null); + $model->setRelation('ancestorsAndSelf', $ancestorsAndSelf); + $model->setRelation('ancestors', $ancestorsAndSelf->slice(0, -1)); + } + + return $this; + } }