Skip to content

Commit 4ca4a16

Browse files
authored
[13.x] Fix scope removal in nested where conditions (laravel#54816)
* Add tests * Remove any scopes removed in a nested where * Update tests to expect calls to `removedScopes`
1 parent 54c7325 commit 4ca4a16

File tree

3 files changed

+43
-0
lines changed

3 files changed

+43
-0
lines changed

src/Illuminate/Database/Eloquent/Builder.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ public function where($column, $operator = null, $value = null, $boolean = 'and'
326326

327327
$this->eagerLoad = array_merge($this->eagerLoad, $query->getEagerLoads());
328328

329+
$this->withoutGlobalScopes(
330+
$query->removedScopes()
331+
);
329332
$this->query->addNestedWhereQuery($query->getQuery(), $boolean);
330333
} else {
331334
$this->query->where(...func_get_args());

tests/Database/DatabaseEloquentBuilderTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1042,6 +1042,7 @@ public function testNestedWhere()
10421042
$nestedRawQuery = $this->getMockQueryBuilder();
10431043
$nestedQuery->shouldReceive('getQuery')->once()->andReturn($nestedRawQuery);
10441044
$nestedQuery->shouldReceive('getEagerLoads')->once()->andReturn([]);
1045+
$nestedQuery->shouldReceive('removedScopes')->once()->andReturn([]);
10451046
$model = $this->getMockModel()->makePartial();
10461047
$model->shouldReceive('newQueryWithoutRelationships')->once()->andReturn($nestedQuery);
10471048
$builder = $this->getBuilder();
@@ -1104,6 +1105,7 @@ public function testWhereNot()
11041105
$nestedRawQuery = $this->getMockQueryBuilder();
11051106
$nestedQuery->shouldReceive('getQuery')->once()->andReturn($nestedRawQuery);
11061107
$nestedQuery->shouldReceive('getEagerLoads')->once()->andReturn([]);
1108+
$nestedQuery->shouldReceive('removedScopes')->once()->andReturn([]);
11071109
$model = $this->getMockModel()->makePartial();
11081110
$model->shouldReceive('newQueryWithoutRelationships')->once()->andReturn($nestedQuery);
11091111
$builder = $this->getBuilder();
@@ -1133,6 +1135,7 @@ public function testOrWhereNot()
11331135
$nestedRawQuery = $this->getMockQueryBuilder();
11341136
$nestedQuery->shouldReceive('getQuery')->once()->andReturn($nestedRawQuery);
11351137
$nestedQuery->shouldReceive('getEagerLoads')->once()->andReturn([]);
1138+
$nestedQuery->shouldReceive('removedScopes')->once()->andReturn([]);
11361139
$model = $this->getMockModel()->makePartial();
11371140
$model->shouldReceive('newQueryWithoutRelationships')->once()->andReturn($nestedQuery);
11381141
$builder = $this->getBuilder();

tests/Database/DatabaseEloquentGlobalScopesTest.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,38 @@ public function testHasQueryWhereBothModelsHaveGlobalScopes()
147147
$this->assertEquals($mainQuery, $query->toSql());
148148
$this->assertEquals(['bar', 1, 'baz', 1], $query->getBindings());
149149
}
150+
151+
public function testRegularScopesThatRemoveGlobalScopes()
152+
{
153+
$query = EloquentClosureGlobalScopesTestModel::where('foo', 'foo')->approved()->notApproved();
154+
155+
$this->assertSame('select * from "table" where "foo" = ? and ("approved" = ? or "should_approve" = ?) and ("approved" = ? or "should_approve" = ?) order by "name" asc', $query->toSql());
156+
$this->assertEquals(['foo', 1, 0, 0, 1], $query->getBindings());
157+
}
158+
159+
public function testRegularScopesThatRemoveGlobalScopesCalledInNestedWhereCondition()
160+
{
161+
$query = EloquentClosureGlobalScopesTestModel::where('foo', 'foo')->where(function ($query) {
162+
$query->approved();
163+
$query->orWhere(function ($query) {
164+
$query->notApproved();
165+
});
166+
});
167+
168+
$this->assertSame('select * from "table" where "foo" = ? and (("approved" = ? or "should_approve" = ?) or (("approved" = ? or "should_approve" = ?))) order by "name" asc', $query->toSql());
169+
$this->assertEquals(['foo', 1, 0, 0, 1], $query->getBindings());
170+
}
171+
172+
public function testRemovingGlobalScopeInNestedWhereCondition()
173+
{
174+
$query = EloquentClosureGlobalScopesTestModel::where('foo', 'foo')->where(function ($query) {
175+
$query->approved();
176+
$query->withoutGlobalScope('active_scope');
177+
});
178+
179+
$this->assertSame('select * from "table" where "foo" = ? and (("approved" = ? or "should_approve" = ?)) order by "name" asc', $query->toSql());
180+
$this->assertEquals(['foo', 1, 0], $query->getBindings());
181+
}
150182
}
151183

152184
class EloquentClosureGlobalScopesTestModel extends Model
@@ -171,6 +203,11 @@ public function scopeApproved($query)
171203
return $query->where('approved', 1)->orWhere('should_approve', 0);
172204
}
173205

206+
public function scopeNotApproved($query)
207+
{
208+
return $query->where('approved', 0)->orWhere('should_approve', 1)->withoutGlobalScope('active_scope');
209+
}
210+
174211
public function scopeOrApproved($query)
175212
{
176213
return $query->orWhere('approved', 1)->orWhere('should_approve', 0);

0 commit comments

Comments
 (0)