From 323f15dac0009d86b45b302822dbbebd22352d65 Mon Sep 17 00:00:00 2001 From: Gusakov Egor Date: Wed, 26 Jul 2023 23:35:25 +0300 Subject: [PATCH] Fix #19872: Fixed the definition of dirty attributes in AR properties for a non-associative array in case of changing the order of elements --- framework/CHANGELOG.md | 1 + framework/db/BaseActiveRecord.php | 2 +- tests/framework/db/BaseActiveRecordTest.php | 42 +++++++++++++++++ .../db/mysql/BaseActiveRecordTest.php | 37 +++++++++++++++ .../db/pgsql/BaseActiveRecordTest.php | 46 +++++++++++++++++++ 5 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 tests/framework/db/BaseActiveRecordTest.php create mode 100644 tests/framework/db/mysql/BaseActiveRecordTest.php create mode 100644 tests/framework/db/pgsql/BaseActiveRecordTest.php diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index dc620a07486..8c1342ad98b 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -4,6 +4,7 @@ Yii Framework 2 Change Log 2.0.49 under development ------------------------ +- Bug #19872: Fixed the definition of dirty attributes in AR properties for a non-associative array in case of changing the order of elements (eegusakov) - Bug #19899: Fixed `GridView` in some cases calling `Model::generateAttributeLabel()` to generate label values that are never used (PowerGamer1) - Bug #9899: Fix caching a MSSQL query with BLOB data type (terabytesoftw) - Bug #16208: Fix `yii\log\FileTarget` to not export empty messages (terabytesoftw) diff --git a/framework/db/BaseActiveRecord.php b/framework/db/BaseActiveRecord.php index 88fb2f11d7c..2648a48dae4 100644 --- a/framework/db/BaseActiveRecord.php +++ b/framework/db/BaseActiveRecord.php @@ -1774,7 +1774,7 @@ private function setRelationDependencies($name, $relation, $viaRelationName = nu */ private function isValueDifferent($newValue, $oldValue) { - if (is_array($newValue) && is_array($oldValue) && !ArrayHelper::isAssociative($oldValue)) { + if (is_array($newValue) && is_array($oldValue) && ArrayHelper::isAssociative($oldValue)) { $newValue = ArrayHelper::recursiveSort($newValue); $oldValue = ArrayHelper::recursiveSort($oldValue); } diff --git a/tests/framework/db/BaseActiveRecordTest.php b/tests/framework/db/BaseActiveRecordTest.php new file mode 100644 index 00000000000..0427421cd81 --- /dev/null +++ b/tests/framework/db/BaseActiveRecordTest.php @@ -0,0 +1,42 @@ +getConnection(); + } + + public function provideArrayValueWithChange() + { + return [ + 'not an associative array with data change' => [ + [1, 2, 3], + [1, 3, 2], + ], + + 'associative array with data change case 1' => [ + ['pineapple' => 2, 'apple' => 5, 'banana' => 1], + ['apple' => 5, 'pineapple' => 1, 'banana' => 3], + ], + 'associative array with data change case 2' => [ + ['pineapple' => 2, 'apple' => 5, 'banana' => 1], + ['pineapple' => 2, 'apple' => 3, 'banana' => 1], + ], + + 'filling an empty array' => [ + [], + ['pineapple' => 3, 'apple' => 1, 'banana' => 1], + ], + 'zeroing the array' => [ + ['pineapple' => 3, 'apple' => 1, 'banana' => 17], + [], + ], + ]; + } +} diff --git a/tests/framework/db/mysql/BaseActiveRecordTest.php b/tests/framework/db/mysql/BaseActiveRecordTest.php new file mode 100644 index 00000000000..394922e87f7 --- /dev/null +++ b/tests/framework/db/mysql/BaseActiveRecordTest.php @@ -0,0 +1,37 @@ +getConnection()->getSchema()->getServerVersion(), '5.7', '<')) { + $this->markTestSkipped('JSON columns are not supported in MySQL < 5.7'); + } + if (version_compare(PHP_VERSION, '5.6', '<')) { + $this->markTestSkipped('JSON columns are not supported in PDO for PHP < 5.6'); + } + + $createdStorage = new Storage(['data' => $actual]); + + $createdStorage->save(); + + $foundStorage = Storage::find()->limit(1)->one(); + + $this->assertNotNull($foundStorage); + + $foundStorage->data = $modified; + + $this->assertSame(['data' => $modified], $foundStorage->getDirtyAttributes()); + } +} diff --git a/tests/framework/db/pgsql/BaseActiveRecordTest.php b/tests/framework/db/pgsql/BaseActiveRecordTest.php new file mode 100644 index 00000000000..a4993685249 --- /dev/null +++ b/tests/framework/db/pgsql/BaseActiveRecordTest.php @@ -0,0 +1,46 @@ + new JsonExpression($actual), + ]); + + $createdStorage->save(); + + $foundStorage = ArrayAndJsonType::find()->limit(1)->one(); + + $this->assertNotNull($foundStorage); + + $foundStorage->json_col = $modified; + + $this->assertSame(['json_col' => $modified], $foundStorage->getDirtyAttributes()); + } +} + +/** + * {@inheritdoc} + * @property array id + * @property array json_col + */ +class ArrayAndJsonType extends ActiveRecord +{ + public static function tableName() + { + return '{{%array_and_json_types}}'; + } +}