diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index fb5b1fc96a1..6fc3c51a6a5 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -23,6 +23,7 @@ Yii Framework 2 Change Log - Bug #20750: Fix `@return` annotation for `yii\console\Controller::runAction()` (mspirkov) - Bug #20750: Add the missing `@property-write` annotation to `yii\console\Controller` (mspirkov) - Bug #20751: Fix `@param` annotation for `$param` parameter in `Sort::parseSortParam()` (mspirkov) +- Bug #20781: Fix enum handling in `ArrayHelper::toArray()` (WarLikeLaux) 2.0.54 January 09, 2026 diff --git a/framework/helpers/BaseArrayHelper.php b/framework/helpers/BaseArrayHelper.php index ac369120231..864c725323b 100644 --- a/framework/helpers/BaseArrayHelper.php +++ b/framework/helpers/BaseArrayHelper.php @@ -64,13 +64,21 @@ public static function toArray($object, $properties = [], $recursive = true) if (is_array($object)) { if ($recursive) { foreach ($object as $key => $value) { - if (is_array($value) || is_object($value)) { + if (PHP_VERSION_ID >= 80100 && $value instanceof \BackedEnum) { + $object[$key] = $value->value; + } elseif (PHP_VERSION_ID >= 80100 && $value instanceof \UnitEnum) { + $object[$key] = $value->name; + } elseif (is_array($value) || is_object($value)) { $object[$key] = static::toArray($value, $properties, true); } } } return $object; + } elseif (PHP_VERSION_ID >= 80100 && $object instanceof \BackedEnum) { + return [$object->value]; + } elseif (PHP_VERSION_ID >= 80100 && $object instanceof \UnitEnum) { + return [$object->name]; } elseif ($object instanceof \DateTimeInterface) { return (array)$object; } elseif (is_object($object)) { diff --git a/phpstan-baseline-7x.neon b/phpstan-baseline-7x.neon index d09a46b3bf0..491098049ed 100644 --- a/phpstan-baseline-7x.neon +++ b/phpstan-baseline-7x.neon @@ -40,6 +40,26 @@ parameters: count: 1 path: framework/db/Command.php + - + message: "#^Class BackedEnum not found\\.$#" + count: 2 + path: framework/helpers/BaseArrayHelper.php + + - + message: "#^Access to property \\$value on an unknown class BackedEnum\\.$#" + count: 2 + path: framework/helpers/BaseArrayHelper.php + + - + message: "#^Class UnitEnum not found\\.$#" + count: 2 + path: framework/helpers/BaseArrayHelper.php + + - + message: "#^Access to property \\$name on an unknown class UnitEnum\\.$#" + count: 2 + path: framework/helpers/BaseArrayHelper.php + - message: "#^Call to an undefined method ReflectionType\\:\\:getName\\(\\)\\.$#" count: 2 diff --git a/tests/framework/helpers/ArrayHelperTest.php b/tests/framework/helpers/ArrayHelperTest.php index 34cbf0b7c1f..063cdd649bc 100644 --- a/tests/framework/helpers/ArrayHelperTest.php +++ b/tests/framework/helpers/ArrayHelperTest.php @@ -22,6 +22,9 @@ use yii\base\Model; use yii\data\Sort; use yii\helpers\ArrayHelper; +use yiiunit\framework\helpers\enums\IntBackedEnum; +use yiiunit\framework\helpers\enums\PureEnum; +use yiiunit\framework\helpers\enums\StringBackedEnum; use yiiunit\TestCase; /** @@ -132,6 +135,63 @@ public function testToArray(): void ], ArrayHelper::toArray(new DateTime('2021-09-13 15:16:17', new DateTimeZone('UTC')))); } + public function testToArrayStringBackedEnum(): void + { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } + $this->assertSame(['hearts'], ArrayHelper::toArray(StringBackedEnum::Hearts)); + } + + public function testToArrayIntBackedEnum(): void + { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } + $this->assertSame([1], ArrayHelper::toArray(IntBackedEnum::Active)); + } + + public function testToArrayUnitEnum(): void + { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } + $this->assertSame(['Red'], ArrayHelper::toArray(PureEnum::Red)); + } + + public function testToArrayWithBackedEnumInArray(): void + { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } + $this->assertSame( + ['hearts', 'diamonds'], + ArrayHelper::toArray([StringBackedEnum::Hearts, StringBackedEnum::Diamonds]) + ); + } + + public function testToArrayWithUnitEnumInArray(): void + { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } + $this->assertSame( + ['Red', 'Blue'], + ArrayHelper::toArray([PureEnum::Red, PureEnum::Blue]) + ); + } + + public function testToArrayWithMixedEnumInArray(): void + { + if (version_compare(PHP_VERSION, '8.1.0', '<')) { + $this->markTestSkipped('Enums require PHP 8.1+'); + } + $this->assertSame( + ['hearts', 1, 'Red'], + ArrayHelper::toArray([StringBackedEnum::Hearts, IntBackedEnum::Active, PureEnum::Red]) + ); + } + public function testRemove(): void { $array = ['name' => 'b', 'age' => 3]; diff --git a/tests/framework/helpers/enums/IntBackedEnum.php b/tests/framework/helpers/enums/IntBackedEnum.php new file mode 100644 index 00000000000..2115c5fee44 --- /dev/null +++ b/tests/framework/helpers/enums/IntBackedEnum.php @@ -0,0 +1,9 @@ +