diff --git a/system/Entity.php b/system/Entity.php index a47995bae3dc..f49c37db6f92 100644 --- a/system/Entity.php +++ b/system/Entity.php @@ -140,11 +140,12 @@ public function fill(array $data = null) * * @param boolean $onlyChanged If true, only return values that have changed since object creation * @param boolean $cast If true, properties will be casted. + * @param boolean $recursive If true, inner entities will be casted as array as well. * * @return array * @throws \Exception */ - public function toArray(bool $onlyChanged = false, bool $cast = true): array + public function toArray(bool $onlyChanged = false, bool $cast = true, bool $recursive = false): array { $this->_cast = $cast; $return = []; @@ -164,6 +165,18 @@ public function toArray(bool $onlyChanged = false, bool $cast = true): array } $return[$key] = $this->__get($key); + + if ($recursive) + { + if ($return[$key] instanceof Entity) + { + $return[$key] = $return[$key]->toArray($onlyChanged, $cast, $recursive); + } + elseif (is_callable([$return[$key], 'toArray'])) + { + $return[$key] = $return[$key]->toArray(); + } + } } // Loop over our mapped properties and add them to the list... @@ -174,6 +187,18 @@ public function toArray(bool $onlyChanged = false, bool $cast = true): array if (array_key_exists($to, $return)) { $return[$from] = $this->__get($to); + + if ($recursive) + { + if ($return[$from] instanceof Entity) + { + $return[$from] = $return[$from]->toArray($onlyChanged, $cast, $recursive); + } + elseif (is_callable([$return[$from], 'toArray'])) + { + $return[$from] = $return[$from]->toArray(); + } + } } } } @@ -187,16 +212,32 @@ public function toArray(bool $onlyChanged = false, bool $cast = true): array /** * Returns the raw values of the current attributes. * - * @param boolean $onlyChanged + * @param boolean $onlyChanged If true, only return values that have changed since object creation + * @param boolean $recursive If true, inner entities will be casted as array as well. * * @return array */ - public function toRawArray(bool $onlyChanged = false): array + public function toRawArray(bool $onlyChanged = false, bool $recursive = false): array { $return = []; if (! $onlyChanged) { + if ($recursive) + { + return array_map(function ($value) use ($onlyChanged, $recursive) { + if ($value instanceof Entity) + { + $value = $value->toRawArray($onlyChanged, $recursive); + } + elseif (is_callable([$value, 'toRawArray'])) + { + $value = $value->toRawArray(); + } + return $value; + }, $this->attributes); + } + return $this->attributes; } @@ -207,7 +248,19 @@ public function toRawArray(bool $onlyChanged = false): array continue; } - $return[$key] = $this->attributes[$key]; + if ($recursive) + { + if ($value instanceof Entity) + { + $value = $value->toRawArray($onlyChanged, $recursive); + } + elseif (is_callable([$value, 'toRawArray'])) + { + $value = $value->toRawArray(); + } + } + + $return[$key] = $value; } return $return; diff --git a/tests/system/EntityTest.php b/tests/system/EntityTest.php index 71701e79349f..9c2928943bbc 100644 --- a/tests/system/EntityTest.php +++ b/tests/system/EntityTest.php @@ -636,6 +636,29 @@ public function testAsArray() ]); } + public function testAsArrayRecursive() + { + $entity = $this->getEntity(); + $entity->entity = $this->getEntity(); + + $result = $entity->toArray(false, true, true); + + $this->assertEquals($result, [ + 'foo' => null, + 'bar' => ':bar', + 'default' => 'sumfin', + 'created_at' => null, + 'createdAt' => null, + 'entity' => [ + 'foo' => null, + 'bar' => ':bar', + 'default' => 'sumfin', + 'created_at' => null, + 'createdAt' => null, + ], + ]); + } + public function testAsArrayMapped() { $entity = $this->getMappedEntity(); @@ -694,6 +717,27 @@ public function testToRawArray() ]); } + public function testToRawArrayRecursive() + { + $entity = $this->getEntity(); + $entity->entity = $this->getEntity(); + + $result = $entity->toRawArray(false, true); + + $this->assertEquals($result, [ + 'foo' => null, + 'bar' => null, + 'default' => 'sumfin', + 'created_at' => null, + 'entity' => [ + 'foo' => null, + 'bar' => null, + 'default' => 'sumfin', + 'created_at' => null, + ], + ]); + } + public function testToRawArrayOnlyChanged() { $entity = $this->getEntity(); @@ -799,7 +843,7 @@ public function testJsonSerializableEntity() $this->assertEquals(json_encode($entity->toArray()), json_encode($entity)); } - protected function getEntity() + protected function getEntity() : Entity { return new class extends Entity { @@ -840,7 +884,7 @@ public function getFakeBar() }; } - protected function getMappedEntity() + protected function getMappedEntity() : Entity { return new class extends Entity { @@ -872,7 +916,7 @@ protected function getSimple() }; } - protected function getCastEntity($data = null) + protected function getCastEntity($data = null) : Entity { return new class($data) extends Entity { @@ -926,7 +970,7 @@ public function setSeventh($seventh) }; } - protected function getCastNullableEntity() + protected function getCastNullableEntity() : Entity { return new class extends Entity { @@ -937,7 +981,8 @@ protected function getCastNullableEntity() 'integer_0' => null, 'string_value_not_null' => 'value', ]; - protected $_original = [ + + protected $_original = [ 'string_null' => null, 'string_empty' => null, 'integer_null' => null, diff --git a/tests/system/View/ParserTest.php b/tests/system/View/ParserTest.php index 28a02c9260d2..bc3aca275bde 100644 --- a/tests/system/View/ParserTest.php +++ b/tests/system/View/ParserTest.php @@ -256,7 +256,7 @@ public function testParseLoopEntityProperties() $power = new class extends \CodeIgniter\Entity { public $foo = 'bar'; protected $bar = 'baz'; - public function toArray(bool $onlyChanged = false, bool $cast = true): array + public function toArray(bool $onlyChanged = false, bool $cast = true, bool $recursive = false): array { return [ 'foo' => $this->foo,