From a0402824bf479dc5135b40a7f40095d4e2bbb265 Mon Sep 17 00:00:00 2001 From: denis Date: Fri, 17 Mar 2017 11:34:01 +0300 Subject: [PATCH 1/6] add date and cast check for dirty --- .../Eloquent/Concerns/HasAttributes.php | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index 1654e39b12b7..e05a35584346 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -960,11 +960,8 @@ public function getDirty() { $dirty = []; - foreach ($this->attributes as $key => $value) { - if (! array_key_exists($key, $this->original)) { - $dirty[$key] = $value; - } elseif ($value !== $this->original[$key] && - ! $this->originalIsNumericallyEquivalent($key)) { + foreach ($this->getAttributes() as $key => $value) { + if (! $this->originalIsEquivalent($key, $value)) { $dirty[$key] = $value; } } @@ -973,16 +970,27 @@ public function getDirty() } /** - * Determine if the new and old values for a given key are numerically equivalent. + * Determine if the new and old values for a given key are equivalent. * - * @param string $key + * @param string $key + * @param mixed $current * @return bool */ - protected function originalIsNumericallyEquivalent($key) + protected function originalIsEquivalent($key, $current) { - $current = $this->attributes[$key]; + if (! array_key_exists($key, $this->original)) { + return false; + } + + $original = $this->getOriginal($key); - $original = $this->original[$key]; + if ($this->isDateAttribute($key)) { + return $this->fromDateTime($current) === $this->fromDateTime($original); + } + + if ($this->hasCast($key)) { + return $this->castAttribute($key, $current) === $this->castAttribute($key, $original); + } // This method checks if the two values are numerically equivalent even if they // are different types. This is in case the two values are not the same type From 4df653ef08ce2d6035acb21c4192bb2886e3f6e1 Mon Sep 17 00:00:00 2001 From: denis Date: Fri, 17 Mar 2017 12:53:12 +0300 Subject: [PATCH 2/6] add check for simple equals --- src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index e05a35584346..72a3b72429f5 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -982,7 +982,9 @@ protected function originalIsEquivalent($key, $current) return false; } - $original = $this->getOriginal($key); + if ($current === $original = $this->getOriginal($key)) { + return true; + } if ($this->isDateAttribute($key)) { return $this->fromDateTime($current) === $this->fromDateTime($original); From d6a1889cdc6041325d2df828d028b45db9aa4d62 Mon Sep 17 00:00:00 2001 From: dgolubkov Date: Sat, 18 Mar 2017 14:24:49 +0300 Subject: [PATCH 3/6] add test for checking dirty on castable or date attributes --- tests/Database/DatabaseEloquentModelTest.php | 21 ++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index 9a3307e11cef..b665e45548fb 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -67,6 +67,27 @@ public function testDirtyAttributes() $this->assertTrue($model->isDirty(['foo', 'bar'])); } + public function testDirtyOnCastOrDateAttributes(){ + $model = new EloquentModelCastingStub; + $model->setDateFormat('Y-m-d H:i:s'); + $model->boolAttribute = true; + $model->foo = 1; + $model->bar = '2017-03-18'; + $model->dateAttribute = '2017-03-18'; + $model->syncOriginal(); + + $model->foo = true; + $model->bar = '2017-03-18 00:00:00'; + $model->boolAttribute = 1; + $model->dateAttribute = '2017-03-18 00:00:00'; + + $this->assertTrue($model->isDirty()); + $this->assertTrue($model->isDirty('foo')); + $this->assertTrue($model->isDirty('bar')); + $this->assertFalse($model->isDirty('boolAttribute')); + $this->assertFalse($model->isDirty('dateAttribute')); + } + public function testCleanAttributes() { $model = new EloquentModelStub(['foo' => '1', 'bar' => 2, 'baz' => 3]); From ea6cc5bff167a9e5c0b513c5adeaf4f3ff93c9ab Mon Sep 17 00:00:00 2001 From: dgolubkov Date: Sat, 18 Mar 2017 14:26:36 +0300 Subject: [PATCH 4/6] fix --- tests/Database/DatabaseEloquentModelTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index b665e45548fb..3727561853b1 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -70,7 +70,7 @@ public function testDirtyAttributes() public function testDirtyOnCastOrDateAttributes(){ $model = new EloquentModelCastingStub; $model->setDateFormat('Y-m-d H:i:s'); - $model->boolAttribute = true; + $model->boolAttribute = 1; $model->foo = 1; $model->bar = '2017-03-18'; $model->dateAttribute = '2017-03-18'; @@ -78,7 +78,7 @@ public function testDirtyOnCastOrDateAttributes(){ $model->foo = true; $model->bar = '2017-03-18 00:00:00'; - $model->boolAttribute = 1; + $model->boolAttribute = true; $model->dateAttribute = '2017-03-18 00:00:00'; $this->assertTrue($model->isDirty()); From e1cf300da9db1591cef905e1475ac9ea74dbad30 Mon Sep 17 00:00:00 2001 From: dgolubkov Date: Thu, 23 Mar 2017 22:38:30 +0300 Subject: [PATCH 5/6] checking current attribute value for nullable before comparing --- src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php | 6 ++++++ tests/Database/DatabaseEloquentModelTest.php | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index 72a3b72429f5..7fbc524fad8d 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -986,6 +986,12 @@ protected function originalIsEquivalent($key, $current) return true; } + // When check rich this check and current attribute value not equals with original, we should skip next steps + // if current is null + if (is_null($current)) { + return false; + } + if ($this->isDateAttribute($key)) { return $this->fromDateTime($current) === $this->fromDateTime($original); } diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index de1f576ee7ec..7c897b704c75 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -74,18 +74,21 @@ public function testDirtyOnCastOrDateAttributes(){ $model->foo = 1; $model->bar = '2017-03-18'; $model->dateAttribute = '2017-03-18'; + $model->datetimeAttribute = '2017-03-23 22:17:00'; $model->syncOriginal(); + $model->boolAttribute = true; $model->foo = true; $model->bar = '2017-03-18 00:00:00'; - $model->boolAttribute = true; $model->dateAttribute = '2017-03-18 00:00:00'; + $model->datetimeAttribute = null; $this->assertTrue($model->isDirty()); $this->assertTrue($model->isDirty('foo')); $this->assertTrue($model->isDirty('bar')); $this->assertFalse($model->isDirty('boolAttribute')); $this->assertFalse($model->isDirty('dateAttribute')); + $this->assertTrue($model->isDirty('datetimeAttribute')); } public function testCleanAttributes() From 01d6896cb402d7b641c84ed8d541b1bc96af34ce Mon Sep 17 00:00:00 2001 From: dgolubkov Date: Thu, 23 Mar 2017 22:39:29 +0300 Subject: [PATCH 6/6] apply style ci --- tests/Database/DatabaseEloquentModelTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index 7c897b704c75..9102b3c37a98 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -67,7 +67,8 @@ public function testDirtyAttributes() $this->assertTrue($model->isDirty(['foo', 'bar'])); } - public function testDirtyOnCastOrDateAttributes(){ + public function testDirtyOnCastOrDateAttributes() + { $model = new EloquentModelCastingStub; $model->setDateFormat('Y-m-d H:i:s'); $model->boolAttribute = 1;