mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-04 06:37:55 +08:00 
			
		
		
		
	Fix #18435: Change the check order whether an object is an implementation of Arrayable or JsonSerializable in \yii\base\ArrayableTrait::toArray() and \yii\rest\Serializer::serialize()
				
					
				
			This commit is contained in:
		
							
								
								
									
										1
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/workflows/build.yml
									
									
									
									
										vendored
									
									
								
							@ -5,6 +5,7 @@ on: [push, pull_request]
 | 
				
			|||||||
env:
 | 
					env:
 | 
				
			||||||
  DEFAULT_COMPOSER_FLAGS: "--prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi"
 | 
					  DEFAULT_COMPOSER_FLAGS: "--prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi"
 | 
				
			||||||
  PHPUNIT_EXCLUDE_GROUP: mssql,oci,wincache,xcache,zenddata,cubrid
 | 
					  PHPUNIT_EXCLUDE_GROUP: mssql,oci,wincache,xcache,zenddata,cubrid
 | 
				
			||||||
 | 
					  XDEBUG_MODE: coverage, develop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  phpunit:
 | 
					  phpunit:
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ Yii Framework 2 Change Log
 | 
				
			|||||||
- Bug #18426: Fix check for route's leading slash in `yii\widgets\Menu` (stevekr)
 | 
					- Bug #18426: Fix check for route's leading slash in `yii\widgets\Menu` (stevekr)
 | 
				
			||||||
- Bug #16492: Fix eager loading Active Record relations when relation key is a subject to a type-casting behavior (bizley)
 | 
					- Bug #16492: Fix eager loading Active Record relations when relation key is a subject to a type-casting behavior (bizley)
 | 
				
			||||||
- Bug #18435: Fix ensuring Active Record relation links' keys to be strings (bizley)
 | 
					- Bug #18435: Fix ensuring Active Record relation links' keys to be strings (bizley)
 | 
				
			||||||
 | 
					- Bug #18435: Change the check order whether an object is an implementation of `Arrayable` or `JsonSerializable` in `\yii\base\ArrayableTrait::toArray()` and `\yii\rest\Serializer::serialize()` (spell6inder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2.0.39.3 November 23, 2020
 | 
					2.0.39.3 November 23, 2020
 | 
				
			||||||
 | 
				
			|||||||
@ -128,17 +128,17 @@ trait ArrayableTrait
 | 
				
			|||||||
            if ($recursive) {
 | 
					            if ($recursive) {
 | 
				
			||||||
                $nestedFields = $this->extractFieldsFor($fields, $field);
 | 
					                $nestedFields = $this->extractFieldsFor($fields, $field);
 | 
				
			||||||
                $nestedExpand = $this->extractFieldsFor($expand, $field);
 | 
					                $nestedExpand = $this->extractFieldsFor($expand, $field);
 | 
				
			||||||
                if ($attribute instanceof \JsonSerializable) {
 | 
					                if ($attribute instanceof Arrayable) {
 | 
				
			||||||
                    $attribute = $attribute->jsonSerialize();
 | 
					 | 
				
			||||||
                } elseif ($attribute instanceof Arrayable) {
 | 
					 | 
				
			||||||
                    $attribute = $attribute->toArray($nestedFields, $nestedExpand);
 | 
					                    $attribute = $attribute->toArray($nestedFields, $nestedExpand);
 | 
				
			||||||
 | 
					                } elseif ($attribute instanceof \JsonSerializable) {
 | 
				
			||||||
 | 
					                    $attribute = $attribute->jsonSerialize();
 | 
				
			||||||
                } elseif (is_array($attribute)) {
 | 
					                } elseif (is_array($attribute)) {
 | 
				
			||||||
                    $attribute = array_map(
 | 
					                    $attribute = array_map(
 | 
				
			||||||
                        function ($item) use ($nestedFields, $nestedExpand) {
 | 
					                        function ($item) use ($nestedFields, $nestedExpand) {
 | 
				
			||||||
                            if ($item instanceof \JsonSerializable) {
 | 
					                            if ($item instanceof Arrayable) {
 | 
				
			||||||
                                return $item->jsonSerialize();
 | 
					 | 
				
			||||||
                            } elseif ($item instanceof Arrayable) {
 | 
					 | 
				
			||||||
                                return $item->toArray($nestedFields, $nestedExpand);
 | 
					                                return $item->toArray($nestedFields, $nestedExpand);
 | 
				
			||||||
 | 
					                            } elseif ($item instanceof \JsonSerializable) {
 | 
				
			||||||
 | 
					                                return $item->jsonSerialize();
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                            return $item;
 | 
					                            return $item;
 | 
				
			||||||
                        },
 | 
					                        },
 | 
				
			||||||
 | 
				
			|||||||
@ -146,10 +146,10 @@ class Serializer extends Component
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        if ($data instanceof Model && $data->hasErrors()) {
 | 
					        if ($data instanceof Model && $data->hasErrors()) {
 | 
				
			||||||
            return $this->serializeModelErrors($data);
 | 
					            return $this->serializeModelErrors($data);
 | 
				
			||||||
        } elseif ($data instanceof \JsonSerializable) {
 | 
					 | 
				
			||||||
            return $data->jsonSerialize();
 | 
					 | 
				
			||||||
        } elseif ($data instanceof Arrayable) {
 | 
					        } elseif ($data instanceof Arrayable) {
 | 
				
			||||||
            return $this->serializeModel($data);
 | 
					            return $this->serializeModel($data);
 | 
				
			||||||
 | 
					        } elseif ($data instanceof \JsonSerializable) {
 | 
				
			||||||
 | 
					            return $data->jsonSerialize();
 | 
				
			||||||
        } elseif ($data instanceof DataProviderInterface) {
 | 
					        } elseif ($data instanceof DataProviderInterface) {
 | 
				
			||||||
            return $this->serializeDataProvider($data);
 | 
					            return $this->serializeDataProvider($data);
 | 
				
			||||||
        } elseif (is_array($data)) {
 | 
					        } elseif (is_array($data)) {
 | 
				
			||||||
 | 
				
			|||||||
@ -421,9 +421,11 @@ class SerializerTest extends TestCase
 | 
				
			|||||||
    public function testSerializeJsonSerializable()
 | 
					    public function testSerializeJsonSerializable()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $serializer = new Serializer();
 | 
					        $serializer = new Serializer();
 | 
				
			||||||
        $model = new TestModel3();
 | 
					        $model3 = new TestModel3();
 | 
				
			||||||
 | 
					        $model4 = new TestModel4();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->assertEquals(['customField' => 'test3/test4'], $serializer->serialize($model));
 | 
					        $this->assertEquals(['customField' => 'test3/test4'], $serializer->serialize($model3));
 | 
				
			||||||
 | 
					        $this->assertEquals(['customField2' => 'test5/test6'], $serializer->serialize($model4));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -432,15 +434,18 @@ class SerializerTest extends TestCase
 | 
				
			|||||||
    public function testSerializeArrayableWithJsonSerializableAttribute()
 | 
					    public function testSerializeArrayableWithJsonSerializableAttribute()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $serializer = new Serializer();
 | 
					        $serializer = new Serializer();
 | 
				
			||||||
        $model = new TestModel4();
 | 
					        $model = new TestModel5();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->assertEquals([
 | 
					        $this->assertEquals(
 | 
				
			||||||
            'field3' => 'test3',
 | 
					            [
 | 
				
			||||||
            'field4' => 'test4',
 | 
					                'field7' => 'test7',
 | 
				
			||||||
 | 
					                'field8' => 'test8',
 | 
				
			||||||
                'testModel3' => ['customField' => 'test3/test4'],
 | 
					                'testModel3' => ['customField' => 'test3/test4'],
 | 
				
			||||||
            'testModelArray' => [['customField' => 'test3/test4']],
 | 
					                'testModel4' => ['customField2' => 'test5/test6'],
 | 
				
			||||||
 | 
					                'testModelArray' => [['customField' => 'test3/test4'], ['customField2' => 'test5/test6']],
 | 
				
			||||||
            ],
 | 
					            ],
 | 
				
			||||||
        $serializer->serialize($model));
 | 
					            $serializer->serialize($model)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -523,7 +528,11 @@ class TestModel3 extends Model implements \JsonSerializable
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public function fields()
 | 
					    public function fields()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return static::$fields;
 | 
					        return [
 | 
				
			||||||
 | 
					            'customField' => function() {
 | 
				
			||||||
 | 
					                return $this->field3.'/'.$this->field4;
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function extraFields()
 | 
					    public function extraFields()
 | 
				
			||||||
@ -531,22 +540,32 @@ class TestModel3 extends Model implements \JsonSerializable
 | 
				
			|||||||
        return static::$extraFields;
 | 
					        return static::$extraFields;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function jsonSerialize()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return $this->getAttributes();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class TestModel4 implements \JsonSerializable
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    public $field5 = 'test5';
 | 
				
			||||||
 | 
					    public $field6 = 'test6';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function jsonSerialize()
 | 
					    public function jsonSerialize()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            'customField' => $this->field3.'/'.$this->field4,
 | 
					            'customField2' => $this->field5.'/'.$this->field6,
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestModel4 extends Model
 | 
					class TestModel5 extends Model
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    public static $fields = ['field3', 'field4'];
 | 
					    public static $fields = ['field7', 'field8'];
 | 
				
			||||||
    public static $extraFields = [];
 | 
					    public static $extraFields = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public $field3 = 'test3';
 | 
					    public $field7 = 'test7';
 | 
				
			||||||
    public $field4 = 'test4';
 | 
					    public $field8 = 'test8';
 | 
				
			||||||
    public $extraField4 = 'testExtra2';
 | 
					    public $extraField4 = 'testExtra4';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public function fields()
 | 
					    public function fields()
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -554,8 +573,11 @@ class TestModel4 extends Model
 | 
				
			|||||||
        $fields['testModel3'] = function() {
 | 
					        $fields['testModel3'] = function() {
 | 
				
			||||||
            return $this->getTestModel3();
 | 
					            return $this->getTestModel3();
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					        $fields['testModel4'] = function() {
 | 
				
			||||||
 | 
					            return $this->getTestModel4();
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
        $fields['testModelArray'] = function() {
 | 
					        $fields['testModelArray'] = function() {
 | 
				
			||||||
            return [$this->getTestModel3()];
 | 
					            return [$this->getTestModel3(), $this->getTestModel4()];
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        return $fields;
 | 
					        return $fields;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -569,4 +591,9 @@ class TestModel4 extends Model
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        return new TestModel3();
 | 
					        return new TestModel3();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public function getTestModel4()
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        return new TestModel4();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user