Skip to content

Commit a4ecd76

Browse files
Mārtiņš Briedisbriedis
Mārtiņš Briedis
authored andcommitted
Support BackedEnum attribute typecast behaviour.
1 parent 1a54384 commit a4ecd76

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

Diff for: framework/behaviors/AttributeTypecastBehavior.php

+9-2
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,16 @@ protected function typecastValue($value, $type)
267267
return StringHelper::floatToString($value);
268268
}
269269
return (string) $value;
270-
default:
271-
throw new InvalidArgumentException("Unsupported type '{$type}'");
272270
}
271+
272+
if (PHP_VERSION_ID >= 80100 && is_subclass_of($type, \BackedEnum::class)) {
273+
if ($value instanceof $type) {
274+
return $value;
275+
}
276+
return $type::from($value);
277+
}
278+
279+
throw new InvalidArgumentException("Unsupported type '{$type}'");
273280
}
274281

275282
return call_user_func($type, $value);

Diff for: tests/framework/behaviors/AttributeTypecastBehaviorTest.php

+86
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77

88
namespace yiiunit\framework\behaviors;
99

10+
use ValueError;
1011
use Yii;
1112
use yii\base\DynamicModel;
1213
use yii\base\Event;
1314
use yii\behaviors\AttributeTypecastBehavior;
1415
use yii\db\ActiveRecord;
16+
use yiiunit\framework\db\enums\StatusTypeString;
1517
use yiiunit\TestCase;
1618

1719
/**
@@ -47,6 +49,7 @@ protected function setUp(): void
4749
'price' => 'float',
4850
'isActive' => 'boolean',
4951
'callback' => 'string',
52+
'status' => 'string',
5053
];
5154
Yii::$app->getDb()->createCommand()->createTable('test_attribute_typecast', $columns)->execute();
5255
}
@@ -80,6 +83,55 @@ public function testTypecast()
8083
$this->assertSame('callback: foo', $model->callback);
8184
}
8285

86+
public function testTypecastEnum()
87+
{
88+
if (PHP_VERSION_ID < 80100) {
89+
$this->markTestSkipped('Can not be tested on PHP < 8.1');
90+
}
91+
92+
$model = new ActiveRecordAttributeTypecastWithEnum();
93+
94+
$model->status = StatusTypeString::ACTIVE;
95+
96+
$model->getAttributeTypecastBehavior()->typecastAttributes();
97+
98+
$this->assertSame(StatusTypeString::ACTIVE, $model->status);
99+
}
100+
101+
/**
102+
* @depends testTypecastEnum
103+
*/
104+
public function testTypecastEnumFromString()
105+
{
106+
if (PHP_VERSION_ID < 80100) {
107+
$this->markTestSkipped('Can not be tested on PHP < 8.1');
108+
}
109+
110+
$model = new ActiveRecordAttributeTypecastWithEnum();
111+
$model->status = 'active'; // Same as StatusTypeString::ACTIVE->value;
112+
113+
$model->getAttributeTypecastBehavior()->typecastAttributes();
114+
115+
$this->assertSame(StatusTypeString::ACTIVE, $model->status);
116+
}
117+
118+
/**
119+
* @depends testTypecastEnum
120+
*/
121+
public function testTypecastEnumFailWithInvalidValue()
122+
{
123+
if (PHP_VERSION_ID < 80100) {
124+
$this->markTestSkipped('Can not be tested on PHP < 8.1');
125+
}
126+
127+
$model = new ActiveRecordAttributeTypecastWithEnum();
128+
$model->status = 'invalid';
129+
130+
self::expectException(ValueError::class);
131+
132+
$model->getAttributeTypecastBehavior()->typecastAttributes();
133+
}
134+
83135
/**
84136
* @depends testTypecast
85137
*/
@@ -339,3 +391,37 @@ public function getAttributeTypecastBehavior()
339391
return $this->getBehavior('attributeTypecast');
340392
}
341393
}
394+
395+
/**
396+
* Test Active Record class with [[AttributeTypecastBehavior]] behavior attached with an enum field.
397+
*
398+
* @property StatusTypeString $status
399+
*/
400+
class ActiveRecordAttributeTypecastWithEnum extends ActiveRecord
401+
{
402+
public function behaviors()
403+
{
404+
return [
405+
'attributeTypecast' => [
406+
'class' => AttributeTypecastBehavior::className(),
407+
'attributeTypes' => [
408+
'status' => StatusTypeString::class,
409+
],
410+
'typecastBeforeSave' => true,
411+
],
412+
];
413+
}
414+
415+
public static function tableName()
416+
{
417+
return 'test_attribute_typecast';
418+
}
419+
420+
/**
421+
* @return AttributeTypecastBehavior
422+
*/
423+
public function getAttributeTypecastBehavior()
424+
{
425+
return $this->getBehavior('attributeTypecast');
426+
}
427+
}

0 commit comments

Comments
 (0)