Skip to content

Commit

Permalink
Fix/issue 233 (staudenmeir#256)
Browse files Browse the repository at this point in the history
* Add failing test

* reduce fatal error to phpstan failure

* WIP

* wip

* wip

* Refactoring

---------

Co-authored-by: Jonas Staudenmeir <mail@jonas-staudenmeir.de>
  • Loading branch information
SanderMuller and staudenmeir committed Aug 29, 2024
1 parent 7b1dc99 commit 3bdb2b2
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 45 deletions.
17 changes: 17 additions & 0 deletions src/Eloquent/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,21 @@
class Builder extends Base
{
use BuildsAdjacencyListQueries;

/**
* The base query builder instance.
*
* @var \Staudenmeir\LaravelCte\Query\Builder
*/
protected $query;

/**
* Get the underlying query builder instance.
*
* @return \Staudenmeir\LaravelCte\Query\Builder
*/
public function getQuery()
{
return $this->query;
}
}
38 changes: 19 additions & 19 deletions src/Eloquent/Traits/HasAdjacencyList.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public function ancestors()
/**
* Get the model's ancestors and itself.
*
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<self>
*/
public function ancestorsAndSelf()
{
Expand All @@ -164,7 +164,7 @@ public function ancestorsAndSelf()
* @param string $foreignKey
* @param string $localKey
* @param bool $andSelf
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<self>
*/
protected function newAncestors(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
{
Expand All @@ -174,7 +174,7 @@ protected function newAncestors(Builder $query, Model $parent, $foreignKey, $loc
/**
* Get the model's bloodline.
*
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline<self>
*/
public function bloodline()
{
Expand All @@ -193,7 +193,7 @@ public function bloodline()
* @param \Illuminate\Database\Eloquent\Model $parent
* @param string $foreignKey
* @param string $localKey
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Bloodline<self>
*/
protected function newBloodline(Builder $query, Model $parent, $foreignKey, $localKey)
{
Expand All @@ -203,7 +203,7 @@ protected function newBloodline(Builder $query, Model $parent, $foreignKey, $loc
/**
* Get the model's children.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany<static>
* @return \Illuminate\Database\Eloquent\Relations\HasMany<self>
*/
public function children()
{
Expand All @@ -213,7 +213,7 @@ public function children()
/**
* Get the model's children and itself.
*
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<self>
*/
public function childrenAndSelf()
{
Expand All @@ -223,7 +223,7 @@ public function childrenAndSelf()
/**
* Get the model's descendants.
*
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<self>
*/
public function descendants()
{
Expand All @@ -239,7 +239,7 @@ public function descendants()
/**
* Get the model's descendants and itself.
*
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<self>
*/
public function descendantsAndSelf()
{
Expand All @@ -260,7 +260,7 @@ public function descendantsAndSelf()
* @param string $foreignKey
* @param string $localKey
* @param bool $andSelf
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Descendants<self>
*/
protected function newDescendants(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
{
Expand All @@ -270,7 +270,7 @@ protected function newDescendants(Builder $query, Model $parent, $foreignKey, $l
/**
* Get the model's parent.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<static, static>
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<self, self>
*/
public function parent()
{
Expand All @@ -280,7 +280,7 @@ public function parent()
/**
* Get the model's parent and itself.
*
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Ancestors<self>
*/
public function parentAndSelf()
{
Expand All @@ -290,7 +290,7 @@ public function parentAndSelf()
/**
* Get the model's root ancestor.
*
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor<self>
*/
public function rootAncestor()
{
Expand All @@ -309,7 +309,7 @@ public function rootAncestor()
* @param \Illuminate\Database\Eloquent\Model $parent
* @param string $foreignKey
* @param string $localKey
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestor<self>
*/
protected function newRootAncestor(Builder $query, Model $parent, $foreignKey, $localKey)
{
Expand All @@ -319,7 +319,7 @@ protected function newRootAncestor(Builder $query, Model $parent, $foreignKey, $
/**
* Get the model's root ancestor or self.
*
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestorOrSelf<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestorOrSelf<self>
*/
public function rootAncestorOrSelf(): RootAncestorOrSelf
{
Expand All @@ -338,7 +338,7 @@ public function rootAncestorOrSelf(): RootAncestorOrSelf
* @param \Illuminate\Database\Eloquent\Model $parent
* @param string $foreignKey
* @param string $localKey
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestorOrSelf<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\RootAncestorOrSelf<self>
*/
protected function newRootAncestorOrSelf(Builder $query, Model $parent, string $foreignKey, string $localKey): RootAncestorOrSelf
{
Expand All @@ -348,7 +348,7 @@ protected function newRootAncestorOrSelf(Builder $query, Model $parent, string $
/**
* Get the model's siblings.
*
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<self>
*/
public function siblings()
{
Expand All @@ -364,7 +364,7 @@ public function siblings()
/**
* Get the model's siblings and itself.
*
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<self>
*/
public function siblingsAndSelf()
{
Expand All @@ -385,7 +385,7 @@ public function siblingsAndSelf()
* @param string $foreignKey
* @param string $localKey
* @param bool $andSelf
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<static>
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Relations\Siblings<self>
*/
protected function newSiblings(Builder $query, Model $parent, $foreignKey, $localKey, $andSelf)
{
Expand Down Expand Up @@ -436,7 +436,7 @@ public function isIntegerAttribute($attribute)
* Create a new Eloquent query builder for the model.
*
* @param \Illuminate\Database\Query\Builder $query
* @return \Illuminate\Database\Eloquent\Builder|static
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<self>
*/
public function newEloquentBuilder($query)
{
Expand Down
55 changes: 29 additions & 26 deletions src/Eloquent/Traits/HasRecursiveRelationshipScopes.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ trait HasRecursiveRelationshipScopes
/**
* Add a recursive expression for the whole tree to the query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @param int|null $maxDepth
* @return \Illuminate\Database\Eloquent\Builder
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeTree(Builder $query, $maxDepth = null)
{
Expand All @@ -28,10 +28,10 @@ public function scopeTree(Builder $query, $maxDepth = null)
/**
* Add a recursive expression for a custom tree to the query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @param callable|\Illuminate\Database\Eloquent\Model $constraint
* @param int|null $maxDepth
* @return \Illuminate\Database\Eloquent\Builder
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeTreeOf(Builder $query, callable|Model $constraint, $maxDepth = null)
{
Expand All @@ -45,8 +45,8 @@ public function scopeTreeOf(Builder $query, callable|Model $constraint, $maxDept
/**
* Limit the query to models with children.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeHasChildren(Builder $query)
{
Expand All @@ -60,19 +60,20 @@ public function scopeHasChildren(Builder $query)
/**
* Limit the query to models without children.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeDoesntHaveChildren(Builder $query)
{
/** @var \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>|static $query */
return $query->isLeaf();
}

/**
* Limit the query to models with a parent.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeHasParent(Builder $query)
{
Expand All @@ -82,8 +83,8 @@ public function scopeHasParent(Builder $query)
/**
* Limit the query to leaf models.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeIsLeaf(Builder $query)
{
Expand All @@ -97,8 +98,8 @@ public function scopeIsLeaf(Builder $query)
/**
* Limit the query to root models.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeIsRoot(Builder $query)
{
Expand All @@ -108,10 +109,10 @@ public function scopeIsRoot(Builder $query)
/**
* Limit the query by depth.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @param mixed $operator
* @param mixed|null $value
* @return \Illuminate\Database\Eloquent\Builder
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeWhereDepth(Builder $query, $operator, $value = null)
{
Expand All @@ -123,8 +124,8 @@ public function scopeWhereDepth(Builder $query, $operator, $value = null)
/**
* Order the query breadth-first.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeBreadthFirst(Builder $query)
{
Expand All @@ -134,8 +135,8 @@ public function scopeBreadthFirst(Builder $query)
/**
* Order the query depth-first.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeDepthFirst(Builder $query)
{
Expand All @@ -147,13 +148,13 @@ public function scopeDepthFirst(Builder $query)
/**
* Add a recursive expression for the relationship to the query.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @param string $direction
* @param callable $constraint
* @param int $initialDepth
* @param string|null $from
* @param int|null $maxDepth
* @return \Illuminate\Database\Eloquent\Builder
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
public function scopeWithRelationshipExpression(Builder $query, $direction, callable $constraint, $initialDepth, $from = null, $maxDepth = null)
{
Expand All @@ -170,7 +171,9 @@ public function scopeWithRelationshipExpression(Builder $query, $direction, call

$query->getModel()->setTable($name);

return $query->withRecursiveExpression($name, $expression)->from($name);
$query->getQuery()->withRecursiveExpression($name, $expression->getQuery())->from($name);

return $query;
}

/**
Expand All @@ -180,7 +183,7 @@ public function scopeWithRelationshipExpression(Builder $query, $direction, call
* @param callable $constraint
* @param int $initialDepth
* @param string $from
* @return \Illuminate\Database\Eloquent\Builder $query
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
protected function getInitialQuery(ExpressionGrammar $grammar, callable $constraint, $initialDepth, $from)
{
Expand Down Expand Up @@ -221,7 +224,7 @@ protected function getInitialQuery(ExpressionGrammar $grammar, callable $constra
* @param string $direction
* @param string $from
* @param int|null $maxDepth
* @return \Illuminate\Database\Eloquent\Builder $query
* @return \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static>
*/
protected function getRecursiveQuery(ExpressionGrammar $grammar, $direction, $from, $maxDepth = null)
{
Expand Down Expand Up @@ -287,7 +290,7 @@ protected function getRecursiveQuery(ExpressionGrammar $grammar, $direction, $fr
/**
* Add join and where clauses to the recursive query for a relationship expression.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Staudenmeir\LaravelAdjacencyList\Eloquent\Builder<static> $query
* @param string $direction
* @param string $name
* @param array $joinColumns
Expand Down
20 changes: 20 additions & 0 deletions tests/Tree/EloquentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -292,4 +292,24 @@ public function testWithMaxDepthWithNegativeDepth()

$this->assertEquals([2, 5], $users->pluck('id')->all());
}

public function testLazyLoadingWithMultipleScopes()
{
/** @var User $user */
$user = User::find(8);

$ancestorsAndSelf = $user->ancestorAndSelfWithMultipleScopes()->get();

$this->assertEquals([2, 5, 8], $ancestorsAndSelf->pluck('id')->all());
}

public function testEagerLoadingWithMultipleScopes()
{
/** @var User $user */
$user = User::find(8);

$ancestorsAndSelf = $user->ancestorAndSelfWithMultipleScopes;

$this->assertEquals([2, 5, 8], $ancestorsAndSelf->pluck('id')->all());
}
}
Loading

0 comments on commit 3bdb2b2

Please sign in to comment.