From ade14f6489739e26ec053b95ccc74120d81a2e4d Mon Sep 17 00:00:00 2001 From: Tigrov Date: Sun, 17 Dec 2023 09:55:30 +0700 Subject: [PATCH] Refactor `BaseActiveRecord::getDirtyAttributes()` --- src/BaseActiveRecord.php | 42 ++++++++++-------------------- tests/ActiveRecordTest.php | 52 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 28 deletions(-) diff --git a/src/BaseActiveRecord.php b/src/BaseActiveRecord.php index d6cb497e3..eaa4eedc0 100644 --- a/src/BaseActiveRecord.php +++ b/src/BaseActiveRecord.php @@ -22,8 +22,10 @@ use Yiisoft\Db\Helper\DbStringHelper; use function array_combine; +use function array_diff_key; use function array_flip; use function array_intersect; +use function array_intersect_key; use function array_key_exists; use function array_keys; use function array_search; @@ -188,40 +190,24 @@ public function getOldAttribute(string $name): mixed public function getDirtyAttributes(array $names = null): array { if ($names === null) { - $names = $this->attributes(); + $attributes = $this->attributes; + } else { + $attributes = array_intersect_key($this->attributes, array_flip($names)); } - $names = array_flip($names); - $attributes = []; - if ($this->oldAttributes === null) { - /** - * @var string $name - * @var mixed $value - */ - foreach ($this->attributes as $name => $value) { - if (isset($names[$name])) { - /** @psalm-var mixed */ - $attributes[$name] = $value; - } - } - } else { - /** - * @var string $name - * @var mixed $value - */ - foreach ($this->attributes as $name => $value) { - if ( - isset($names[$name]) - && (!array_key_exists($name, $this->oldAttributes) || $value !== $this->oldAttributes[$name]) - ) { - /** @psalm-var mixed */ - $attributes[$name] = $value; - } + return $attributes; + } + + $result = array_diff_key($attributes, $this->oldAttributes); + + foreach (array_diff_key($attributes, $result) as $name => $value) { + if ($value !== $this->oldAttributes[$name]) { + $result[$name] = $value; } } - return $attributes; + return $result; } public function getOldAttributes(): array diff --git a/tests/ActiveRecordTest.php b/tests/ActiveRecordTest.php index 903ee53ce..a85d2bbcf 100644 --- a/tests/ActiveRecordTest.php +++ b/tests/ActiveRecordTest.php @@ -836,4 +836,56 @@ public function testToArrayForArrayable(): void ]), ); } + + public function testGetDirtyAttributesOnNewRecord(): void + { + $this->checkFixture($this->db, 'customer'); + + $customer = new Customer($this->db); + + $this->assertSame([], $customer->getDirtyAttributes()); + + $customer->setAttribute('name', 'Adam'); + $customer->setAttribute('email', 'adam@example.com'); + $customer->setAttribute('address', null); + + $this->assertEquals( + ['name' => 'Adam', 'email' => 'adam@example.com', 'address' => null], + $customer->getDirtyAttributes() + ); + $this->assertEquals( + ['email' => 'adam@example.com', 'address' => null], + $customer->getDirtyAttributes(['id', 'email', 'address', 'status']), + ); + + $this->assertTrue($customer->save()); + $this->assertSame([], $customer->getDirtyAttributes()); + + $customer->setAttribute('address', ''); + + $this->assertSame(['address' => ''], $customer->getDirtyAttributes()); + } + + public function testGetDirtyAttributesAfterFind(): void + { + $this->checkFixture($this->db, 'customer'); + + $customerQuery = new ActiveQuery(Customer::class, $this->db); + $customer = $customerQuery->findOne(1); + + $this->assertSame([], $customer->getDirtyAttributes()); + + $customer->setAttribute('name', 'Adam'); + $customer->setAttribute('email', 'adam@example.com'); + $customer->setAttribute('address', null); + + $this->assertEquals( + ['name' => 'Adam', 'email' => 'adam@example.com', 'address' => null], + $customer->getDirtyAttributes(), + ); + $this->assertEquals( + ['email' => 'adam@example.com', 'address' => null], + $customer->getDirtyAttributes(['id', 'email', 'address', 'status']), + ); + } }