From 9513af117daca537cbd9862df027143545fa2f43 Mon Sep 17 00:00:00 2001 From: Mohammad Mortazavi Date: Sat, 7 Oct 2023 16:09:06 +0330 Subject: [PATCH 1/7] Override setAttributeMarkedMutatedAttributeValue method; --- src/Eloquent/Model.php | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index 05a20bb31..9aff99f4f 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -251,6 +251,37 @@ public function attributesToArray() return $attributes; } + /** @inheritdoc */ + protected function setAttributeMarkedMutatedAttributeValue($key, $value) + { + $attribute = $this->{Str::camel($key)}(); + + $callback = $attribute->set ?: function ($value) use ($key) { + $this->attributes[$key] = $value; + }; + + $normalizeCastClassResponse = $this->normalizeCastClassResponse( + $key, $callback($value, $this->attributes) + ); + + if (count($normalizeCastClassResponse) > 1) { + $normalizeCastClassResponse = [$key => $normalizeCastClassResponse]; + } + + $this->attributes = array_merge( + $this->attributes, + $normalizeCastClassResponse + ); + + if ($attribute->withCaching || (is_object($value) && $attribute->withObjectCaching)) { + $this->attributeCastCache[$key] = $value; + } else { + unset($this->attributeCastCache[$key]); + } + + return $this; + } + /** @inheritdoc */ public function getCasts() { From 7faeca7ade8c72695b5e667c1d6da4269201280f Mon Sep 17 00:00:00 2001 From: Mohammad Mortazavi Date: Sat, 7 Oct 2023 16:09:21 +0330 Subject: [PATCH 2/7] Add tests; --- tests/ModelTest.php | 13 +++++++++++++ tests/Models/User.php | 8 ++++++++ 2 files changed, 21 insertions(+) diff --git a/tests/ModelTest.php b/tests/ModelTest.php index 44e24b699..af36b681e 100644 --- a/tests/ModelTest.php +++ b/tests/ModelTest.php @@ -114,6 +114,19 @@ public function testUpdate(): void $check = User::find($user->_id); $this->assertEquals(20, $check->age); + + $check->skills = ['PHP', 'Laravel', 'MongoDB', 'Laravel']; + $check->save(); + + $check = User::find($user->_id); + $this->assertCount(3,$check->skills); + $this->assertEquals(['PHP', 'Laravel', 'MongoDB'],$check->skills); + + $check->update(['skills' => ['Git','Github','Unit testing','Github']]); + + $check = User::find($user->_id); + $this->assertCount(3,$check->skills); + $this->assertEquals(['Git','Github','Unit testing'],$check->skills); } public function testManualStringId(): void diff --git a/tests/Models/User.php b/tests/Models/User.php index 523b489e7..00964dbcb 100644 --- a/tests/Models/User.php +++ b/tests/Models/User.php @@ -109,6 +109,14 @@ protected function username(): Attribute ); } + protected function skills(): Attribute + { + return Attribute::make( + get: fn ($value) => $value, + set: fn ($values) => array_unique($values) + ); + } + public function prunable(): Builder { return $this->where('age', '>', 18); From cfed3835f35257bd1c05ca18f7f19cef4dc2b30b Mon Sep 17 00:00:00 2001 From: Mohammad Mortazavi Date: Sat, 7 Oct 2023 16:20:22 +0330 Subject: [PATCH 3/7] Revert "Override setAttributeMarkedMutatedAttributeValue method;" This reverts commit 9513af117daca537cbd9862df027143545fa2f43. --- src/Eloquent/Model.php | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index 9aff99f4f..05a20bb31 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -251,37 +251,6 @@ public function attributesToArray() return $attributes; } - /** @inheritdoc */ - protected function setAttributeMarkedMutatedAttributeValue($key, $value) - { - $attribute = $this->{Str::camel($key)}(); - - $callback = $attribute->set ?: function ($value) use ($key) { - $this->attributes[$key] = $value; - }; - - $normalizeCastClassResponse = $this->normalizeCastClassResponse( - $key, $callback($value, $this->attributes) - ); - - if (count($normalizeCastClassResponse) > 1) { - $normalizeCastClassResponse = [$key => $normalizeCastClassResponse]; - } - - $this->attributes = array_merge( - $this->attributes, - $normalizeCastClassResponse - ); - - if ($attribute->withCaching || (is_object($value) && $attribute->withObjectCaching)) { - $this->attributeCastCache[$key] = $value; - } else { - unset($this->attributeCastCache[$key]); - } - - return $this; - } - /** @inheritdoc */ public function getCasts() { From b8a3b1c7ff8bfe4d8f47053222aa803c4b7af60d Mon Sep 17 00:00:00 2001 From: Mohammad Mortazavi Date: Sat, 7 Oct 2023 16:22:54 +0330 Subject: [PATCH 4/7] Override normalizeCastClassResponse method; --- src/Eloquent/Model.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index 05a20bb31..12bfb5213 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -251,6 +251,12 @@ public function attributesToArray() return $attributes; } + /** @inheritdoc */ + protected function normalizeCastClassResponse($key, $value) + { + return [$key => $value]; + } + /** @inheritdoc */ public function getCasts() { From d5bd061001061304a9cb11bbeb1420ff14d69e56 Mon Sep 17 00:00:00 2001 From: Mohammad Mortazavi Date: Sat, 14 Oct 2023 23:08:22 +0330 Subject: [PATCH 5/7] Refactore normalizeCastClassResponse method; --- src/Eloquent/Model.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Eloquent/Model.php b/src/Eloquent/Model.php index 12bfb5213..5c88dee0e 100644 --- a/src/Eloquent/Model.php +++ b/src/Eloquent/Model.php @@ -20,6 +20,7 @@ use function abs; use function array_key_exists; +use function array_key_first; use function array_keys; use function array_unique; use function array_values; @@ -254,7 +255,11 @@ public function attributesToArray() /** @inheritdoc */ protected function normalizeCastClassResponse($key, $value) { - return [$key => $value]; + if (! is_array($value) || (count($value) && is_numeric(array_key_first($value)))) { + return [$key => $value]; + } + + return $value; } /** @inheritdoc */ From 5e3599b80e81959939bbafb6fe0fe6d4de38d8cd Mon Sep 17 00:00:00 2001 From: Mohammad Mortazavi Date: Sat, 14 Oct 2023 23:09:11 +0330 Subject: [PATCH 6/7] New mutator added; --- tests/Models/User.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/Models/User.php b/tests/Models/User.php index 00964dbcb..8bcd08f55 100644 --- a/tests/Models/User.php +++ b/tests/Models/User.php @@ -18,6 +18,8 @@ use MongoDB\Laravel\Eloquent\MassPrunable; use MongoDB\Laravel\Eloquent\Model as Eloquent; +use function array_unique; + /** * @property string $_id * @property string $name @@ -117,6 +119,14 @@ protected function skills(): Attribute ); } + protected function fullname(): Attribute + { + return Attribute::make( + get: fn ($value) => $this->first_name . ' ' . $this->last_name, + set: fn ($values) => ['first_name' => $values[0], 'last_name' => $values[1]] + ); + } + public function prunable(): Builder { return $this->where('age', '>', 18); From a87d43df140d392035e8880df09c05805cda6466 Mon Sep 17 00:00:00 2001 From: Mohammad Mortazavi Date: Sat, 14 Oct 2023 23:09:23 +0330 Subject: [PATCH 7/7] Tests updated; --- tests/ModelTest.php | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/ModelTest.php b/tests/ModelTest.php index af36b681e..6b98ff90e 100644 --- a/tests/ModelTest.php +++ b/tests/ModelTest.php @@ -112,21 +112,20 @@ public function testUpdate(): void $raw = $user->getAttributes(); $this->assertInstanceOf(ObjectID::class, $raw['_id']); - $check = User::find($user->_id); - $this->assertEquals(20, $check->age); - $check->skills = ['PHP', 'Laravel', 'MongoDB', 'Laravel']; $check->save(); $check = User::find($user->_id); - $this->assertCount(3,$check->skills); - $this->assertEquals(['PHP', 'Laravel', 'MongoDB'],$check->skills); + $this->assertCount(3, $check->skills); + $this->assertEquals(['PHP', 'Laravel', 'MongoDB'], $check->skills); - $check->update(['skills' => ['Git','Github','Unit testing','Github']]); + $check->fullname = ['Hans', 'Thomas']; + $check->save(); $check = User::find($user->_id); - $this->assertCount(3,$check->skills); - $this->assertEquals(['Git','Github','Unit testing'],$check->skills); + self::assertEquals('Hans', $check->first_name); + self::assertEquals('Thomas', $check->last_name); + self::assertEquals('Hans Thomas', $check->fullname); } public function testManualStringId(): void