diff --git a/src/Mixins/QueryRelationshipExistence.php b/src/Mixins/QueryRelationshipExistence.php index 3441a31..8664c53 100644 --- a/src/Mixins/QueryRelationshipExistence.php +++ b/src/Mixins/QueryRelationshipExistence.php @@ -13,6 +13,13 @@ public function getGroupBy() }; } + public function getScopes() + { + return function () { + return $this->scopes; + }; + } + public function getSelect() { return function () { diff --git a/src/Mixins/RelationshipsExtraMethods.php b/src/Mixins/RelationshipsExtraMethods.php index 02ebd6c..066851e 100644 --- a/src/Mixins/RelationshipsExtraMethods.php +++ b/src/Mixins/RelationshipsExtraMethods.php @@ -2,6 +2,7 @@ namespace Kirschbaum\PowerJoins\Mixins; +use Illuminate\Database\Eloquent\Model; use Stringable; use Illuminate\Support\Str; use Kirschbaum\PowerJoins\StaticCache; @@ -16,6 +17,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\Eloquent\Relations\MorphOneOrMany; +use Illuminate\Database\Eloquent\SoftDeletingScope; /** * @method \Illuminate\Database\Eloquent\Model getModel() @@ -86,7 +88,7 @@ protected function performJoinForEloquentPowerJoinsForBelongsTo() "{$joinedTable}.{$this->ownerKey}" ); - if ($disableExtraConditions === false && $this->usesSoftDeletes($this->query->getModel())) { + if ($disableExtraConditions === false && $this->usesSoftDeletes($this->query->getScopes())) { $join->whereNull("{$joinedTable}.{$this->query->getModel()->getDeletedAtColumn()}"); } @@ -139,7 +141,7 @@ protected function performJoinForEloquentPowerJoinsForBelongsToMany() "{$joinedTable}.{$this->getRelatedPivotKeyName()}" ); - if ($disableExtraConditions === false && $this->usesSoftDeletes($this->query->getModel())) { + if ($disableExtraConditions === false && $this->usesSoftDeletes($this->query->getScopes())) { $join->whereNull($this->query->getModel()->getQualifiedDeletedAtColumn()); } @@ -200,7 +202,7 @@ protected function performJoinForEloquentPowerJoinsForMorphToMany() "{$joinedTable}.{$this->getRelatedPivotKeyName()}" ); - if ($disableExtraConditions === false && $this->usesSoftDeletes($this->query->getModel())) { + if ($disableExtraConditions === false && $this->usesSoftDeletes($this->query->getScopes())) { $join->whereNull($this->query->getModel()->getQualifiedDeletedAtColumn()); } @@ -226,7 +228,7 @@ protected function performJoinForEloquentPowerJoinsForMorph() "{$this->parent->getTable()}.{$this->localKey}" )->where("{$this->getModel()->getTable()}.{$this->getMorphType()}", '=', $this->getMorphClass()); - if ($disableExtraConditions === false && $this->usesSoftDeletes($this->query->getModel())) { + if ($disableExtraConditions === false && $this->usesSoftDeletes($this->query->getScopes())) { $join->whereNull($this->query->getModel()->getQualifiedDeletedAtColumn()); } @@ -249,6 +251,7 @@ protected function performJoinForEloquentPowerJoinsForMorph() protected function performJoinForEloquentPowerJoinsForMorphTo() { return function ($builder, $joinType, $callback = null, $alias = null, bool $disableExtraConditions = false, string $morphable = null) { + /** @var Model */ $modelInstance = new $morphable; $builder->{$joinType}($modelInstance->getTable(), function ($join) use ($modelInstance, $callback, $disableExtraConditions) { @@ -258,7 +261,7 @@ protected function performJoinForEloquentPowerJoinsForMorphTo() "{$modelInstance->getTable()}.{$modelInstance->getKeyName()}" )->where("{$this->getModel()->getTable()}.{$this->getMorphType()}", '=', $modelInstance->getMorphClass()); - if ($disableExtraConditions === false && $this->usesSoftDeletes($modelInstance)) { + if ($disableExtraConditions === false && $this->usesSoftDeletes($modelInstance->getScopes())) { $join->whereNull($modelInstance->getQualifiedDeletedAtColumn()); } @@ -304,7 +307,7 @@ protected function performJoinForEloquentPowerJoinsForHasMany() "{$parentTable}.{$this->localKey}" ); - if ($disableExtraConditions === false && $this->usesSoftDeletes($this->query->getModel())) { + if ($disableExtraConditions === false && $this->usesSoftDeletes($this->query->getScopes())) { $join->whereNull( "{$joinedTable}.{$this->query->getModel()->getDeletedAtColumn()}" ); @@ -370,7 +373,7 @@ protected function performJoinForEloquentPowerJoinsForHasManyThrough() "{$throughTable}.{$this->secondLocalKey}" ); - if ($this->usesSoftDeletes($this->getModel())) { + if ($this->usesSoftDeletes($this->getScopes())) { $join->whereNull("{$farTable}.{$this->getModel()->getDeletedAtColumn()}"); } @@ -408,8 +411,15 @@ public function performHavingForEloquentPowerJoins() */ public function usesSoftDeletes() { + /** + * @param \Illuminate\Database\Eloquent\Model|array $model + */ return function ($model) { - return in_array(SoftDeletes::class, class_uses_recursive($model)); + if ($model instanceof Model) { + return in_array(SoftDeletes::class, class_uses_recursive($model)); + } + + return array_key_exists(SoftDeletingScope::class, $model); }; } diff --git a/src/PowerJoinClause.php b/src/PowerJoinClause.php index b213038..09dd216 100644 --- a/src/PowerJoinClause.php +++ b/src/PowerJoinClause.php @@ -219,18 +219,27 @@ public function withTrashed(): self */ public function onlyTrashed(): self { - if (! $this->getModel() || ! in_array(SoftDeletes::class, class_uses_recursive($this->getModel()))) { + if (! $this->getModel() + || ! in_array(SoftDeletes::class, class_uses_recursive($this->getModel())) + ) { return $this; } - $this->wheres = array_map(function ($where) { + $hasCondition = null; + + $this->wheres = array_map(function ($where) use (&$hasCondition) { if ($where['type'] === 'Null' && Str::contains($where['column'], $this->getModel()->getDeletedAtColumn())) { $where['type'] = 'NotNull'; + $hasCondition = true; } return $where; }, $this->wheres); + if (! $hasCondition) { + $this->whereNotNull($this->getModel()->getQualifiedDeletedAtColumn()); + } + return $this; } diff --git a/tests/JoinRelationshipExtraConditionsTest.php b/tests/JoinRelationshipExtraConditionsTest.php index 634b080..427b1c3 100644 --- a/tests/JoinRelationshipExtraConditionsTest.php +++ b/tests/JoinRelationshipExtraConditionsTest.php @@ -24,12 +24,13 @@ public function test_join_belongs_to_with_additional_conditions() $query = Post::query()->joinRelationship('userWithTrashed')->toSql(); $posts = Post::query()->joinRelationship('userWithTrashed')->get(); - $this->assertCount(1, $posts); $this->assertStringContainsString( - 'inner join "users" on "posts"."user_id" = "users"."id" and "users"."deleted_at" is null', + 'inner join "users" on "posts"."user_id" = "users"."id"', $query ); + + $this->assertCount(2, $posts); } /** @test */ diff --git a/tests/Models/User.php b/tests/Models/User.php index a3532c1..e5f0535 100644 --- a/tests/Models/User.php +++ b/tests/Models/User.php @@ -39,6 +39,11 @@ public function posts(): HasMany return $this->hasMany(Post::class); } + public function postsWithTrashed(): HasMany + { + return $this->hasMany(Post::class)->withTrashed(); + } + public function publishedPosts(): HasMany { return $this->hasMany(Post::class)->where(function ($query) { diff --git a/tests/SoftDeletesTest.php b/tests/SoftDeletesTest.php index 5459943..2558669 100644 --- a/tests/SoftDeletesTest.php +++ b/tests/SoftDeletesTest.php @@ -89,4 +89,20 @@ public function it_can_disable_soft_deletes_when_using_an_alias() $query ); } + + public function test_it_respects_with_trashed() + { + User::query()->joinRelationship('postsWithTrashed')->get(); + $sql = User::query()->joinRelationship('postsWithTrashed')->toSql(); + + $this->assertStringContainsString( + 'inner join "posts" on "posts"."user_id" = "users"."id"', + $sql + ); + + $this->assertStringNotContainsString( + '"posts"."deleted_at" is null', + $sql + ); + } }