Skip to content

Commit

Permalink
[10.x] Do not apply global scopes when incrementing/decrementing an e…
Browse files Browse the repository at this point in the history
…xisting model (#47629)

* do not apply global scopes when incrementing or decrementing if model exists

* fix DatabaseEloquentModelTest expectations for `newQueryWithoutScopes`

* add test for increment/decrement existing model
  • Loading branch information
cosmastech authored Jul 4, 2023
1 parent 6b948d9 commit b8f385b
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 10 deletions.
6 changes: 2 additions & 4 deletions src/Illuminate/Database/Eloquent/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -951,10 +951,8 @@ protected function decrement($column, $amount = 1, array $extra = [])
*/
protected function incrementOrDecrement($column, $amount, $extra, $method)
{
$query = $this->newQueryWithoutRelationships();

if (! $this->exists) {
return $query->{$method}($column, $amount, $extra);
return $this->newQueryWithoutRelationships()->{$method}($column, $amount, $extra);
}

$this->{$column} = $this->isClassDeviable($column)
Expand All @@ -967,7 +965,7 @@ protected function incrementOrDecrement($column, $amount, $extra, $method)
return false;
}

return tap($this->setKeysForSaveQuery($query)->{$method}($column, $amount, $extra), function () use ($column) {
return tap($this->setKeysForSaveQuery($this->newQueryWithoutScopes())->{$method}($column, $amount, $extra), function () use ($column) {
$this->syncChanges();

$this->fireModelEvent('updated', false);
Expand Down
13 changes: 7 additions & 6 deletions tests/Database/DatabaseEloquentModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2017,16 +2017,17 @@ public function testReplicateQuietlyCreatesANewModelInstanceWithSameAttributeVal

public function testIncrementOnExistingModelCallsQueryAndSetsAttribute()
{
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutRelationships]');
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutScopes]');
$model->exists = true;
$model->id = 1;
$model->syncOriginalAttribute('id');
$model->foo = 2;

$model->shouldReceive('newQueryWithoutRelationships')->andReturn($query = m::mock(stdClass::class));
$model->shouldReceive('newQueryWithoutScopes')->andReturn($query = m::mock(stdClass::class));
$query->shouldReceive('where')->andReturn($query);
$query->shouldReceive('increment');

// hmm
$model->publicIncrement('foo', 1);
$this->assertFalse($model->isDirty());

Expand All @@ -2038,13 +2039,13 @@ public function testIncrementOnExistingModelCallsQueryAndSetsAttribute()

public function testIncrementQuietlyOnExistingModelCallsQueryAndSetsAttributeAndIsQuiet()
{
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutRelationships]');
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutScopes]');
$model->exists = true;
$model->id = 1;
$model->syncOriginalAttribute('id');
$model->foo = 2;

$model->shouldReceive('newQueryWithoutRelationships')->andReturn($query = m::mock(stdClass::class));
$model->shouldReceive('newQueryWithoutScopes')->andReturn($query = m::mock(stdClass::class));
$query->shouldReceive('where')->andReturn($query);
$query->shouldReceive('increment');

Expand All @@ -2065,13 +2066,13 @@ public function testIncrementQuietlyOnExistingModelCallsQueryAndSetsAttributeAnd

public function testDecrementQuietlyOnExistingModelCallsQueryAndSetsAttributeAndIsQuiet()
{
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutRelationships]');
$model = m::mock(EloquentModelStub::class.'[newQueryWithoutScopes]');
$model->exists = true;
$model->id = 1;
$model->syncOriginalAttribute('id');
$model->foo = 4;

$model->shouldReceive('newQueryWithoutRelationships')->andReturn($query = m::mock(stdClass::class));
$model->shouldReceive('newQueryWithoutScopes')->andReturn($query = m::mock(stdClass::class));
$query->shouldReceive('where')->andReturn($query);
$query->shouldReceive('decrement');

Expand Down
18 changes: 18 additions & 0 deletions tests/Integration/Database/EloquentUpdateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,24 @@ public function testIncrement()
$this->assertEquals(1, $models[0]->counter);
$this->assertEquals(0, $models[1]->counter);
}

public function testIncrementOrDecrementIgnoresGlobalScopes()
{
/** @var TestUpdateModel3 $deletedModel */
$deletedModel = tap(TestUpdateModel3::create([
'counter' => 0,
]), fn ($model) => $model->delete());

$deletedModel->increment('counter');

$this->assertEquals(1, $deletedModel->counter);

$deletedModel->fresh();
$this->assertEquals(1, $deletedModel->counter);

$deletedModel->decrement('counter');
$this->assertEquals(0, $deletedModel->fresh()->counter);
}
}

class TestUpdateModel1 extends Model
Expand Down

0 comments on commit b8f385b

Please sign in to comment.