diff --git a/src/XmlFormatter.php b/src/XmlFormatter.php
index b1b743c..f2c3f38 100644
--- a/src/XmlFormatter.php
+++ b/src/XmlFormatter.php
@@ -4,6 +4,8 @@
use SimpleXMLElement;
use Throwable;
+use function array_walk_recursive;
+use function current;
use function sprintf;
abstract class XmlFormatter implements ResourceFormatter
@@ -36,7 +38,7 @@ public function from(RestResource $resource): string
));
try {
$this->toSimpleXML(
- $resource->body() + $this->linksOf($resource, $this->baseUri),
+ current($this->prepare($resource)),
$xml
);
return (string) $xml->asXML();
@@ -51,4 +53,22 @@ abstract protected function toSimpleXML(
SimpleXMLElement $parent,
bool $alreadySingularized = false
): void;
+
+ private function prepare(RestResource $resource): array
+ {
+ return [$resource->name() =>
+ $this->flatten($resource->body()) +
+ $this->linksOf($resource, $this->baseUri)
+ ];
+ }
+
+ private function flatten(array $body): array
+ {
+ array_walk_recursive($body, function (&$data) {
+ if ($data instanceof RestResource) {
+ $data = $this->prepare($data);
+ }
+ });
+ return $body;
+ }
}
diff --git a/tests/formatting_the_resource_as_condensed_xml.php b/tests/formatting_the_resource_as_condensed_xml.php
index bb10fd2..66ee478 100644
--- a/tests/formatting_the_resource_as_condensed_xml.php
+++ b/tests/formatting_the_resource_as_condensed_xml.php
@@ -145,6 +145,68 @@ function formatting_a_basic_resource_with_a_list_of_people()
);
}
+ /** @test */
+ function formatting_a_nested_resource()
+ {
+ $resource = new BasicResource(
+ 'nested-resource',
+ ['children' => [
+ new BasicResource('child-resource', ['n' => 1], Links::none()),
+ new BasicResource('child-resource', ['n' => 2], Links::none()),
+ new BasicResource('child-resource', ['n' => 3], Links::none()),
+ ]],
+ Links::none()
+ );
+
+ $this->assertXmlStringEqualsXmlString(
+ '
+
+
+
+
+
+
+ ',
+ $this->xml->from($resource)
+ );
+ }
+
+ /** @test */
+ function formatting_a_twice_nested_resource()
+ {
+ $resource = new BasicResource(
+ 'nested-resource',
+ ['children' => [
+ new BasicResource(
+ 'child-resource',
+ ['grandchildren' => [
+ new MinimalResource(['foo' => 'bar'])
+ ]],
+ Links::none()
+ ),
+ ]],
+ Links::none()
+ );
+
+ $this->assertXmlStringEqualsXmlString(
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+ ',
+ $this->xml->from($resource)
+ );
+ }
+
/** @test */
function formatting_a_resource_with_a_link()
{
@@ -442,6 +504,59 @@ function formatting_a_resource_with_a_lot_of_nested_elements()
);
}
+ /** @test */
+ function formatting_a_nested_resource_where_the_children_have_links()
+ {
+ $resource = new BasicResource(
+ 'nested-resource',
+ ['children' => [
+ new BasicResource('child-resource', ['n' => 1], Links::provide(
+ Link::to('foo', Type::get('Foo'))
+ )),
+ new BasicResource('child-resource', ['n' => 2], Links::provide(
+ Link::to('foo', Type::get('Foo'))
+ )),
+ new BasicResource('child-resource', ['n' => 3], Links::provide(
+ Link::to('foo', Type::get('Foo'))
+ )),
+ ]],
+ Links::provide(Link::to('bar', Type::get('Bar')))
+ );
+
+ $this->assertXmlStringEqualsXmlString(
+ '
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ',
+ $this->xml->from($resource)
+ );
+ }
+
/** @test */
function not_formatting_resources_with_circular_references()
{
diff --git a/tests/formatting_the_resource_as_xml.php b/tests/formatting_the_resource_as_xml.php
index 13393e2..f0868c9 100644
--- a/tests/formatting_the_resource_as_xml.php
+++ b/tests/formatting_the_resource_as_xml.php
@@ -158,6 +158,70 @@ function formatting_a_basic_resource_with_a_list_of_people()
);
}
+ /** @test */
+ function formatting_a_nested_resource()
+ {
+ $resource = new BasicResource(
+ 'nested-resource',
+ ['children' => [
+ new BasicResource('child-resource', ['n' => 1], Links::none()),
+ new BasicResource('child-resource', ['n' => 2], Links::none()),
+ new BasicResource('child-resource', ['n' => 3], Links::none()),
+ ]],
+ Links::none()
+ );
+
+ $this->assertXmlStringEqualsXmlString(
+ '
+
+
+ 1
+ 2
+ 3
+
+ ',
+ $this->xml->from($resource)
+ );
+ }
+
+ /** @test */
+ function formatting_a_twice_nested_resource()
+ {
+ $resource = new BasicResource(
+ 'nested-resource',
+ ['children' => [
+ new BasicResource(
+ 'child-resource',
+ ['grandchildren' => [
+ new MinimalResource(['foo' => 'bar'])
+ ]],
+ Links::none()
+ ),
+ ]],
+ Links::none()
+ );
+
+ $this->assertXmlStringEqualsXmlString(
+ '
+
+
+
+
+
+
+
+ bar
+
+
+
+
+
+
+ ',
+ $this->xml->from($resource)
+ );
+ }
+
/** @test */
function formatting_a_resource_with_a_link()
{
@@ -579,6 +643,72 @@ function formatting_a_resource_with_a_lot_of_nested_elements()
);
}
+ /** @test */
+ function formatting_a_nested_resource_where_the_children_have_links()
+ {
+ $resource = new BasicResource(
+ 'nested-resource',
+ ['children' => [
+ new BasicResource('child-resource', ['n' => 1], Links::provide(
+ Link::to('foo', Type::get('Foo'))
+ )),
+ new BasicResource('child-resource', ['n' => 2], Links::provide(
+ Link::to('foo', Type::get('Foo'))
+ )),
+ new BasicResource('child-resource', ['n' => 3], Links::provide(
+ Link::to('foo', Type::get('Foo'))
+ )),
+ ]],
+ Links::provide(Link::to('bar', Type::get('Bar')))
+ );
+
+ $this->assertXmlStringEqualsXmlString(
+ '
+
+
+
+ 1
+
+
+ server/foo
+ Foo
+ GET
+
+
+
+
+ 2
+
+
+ server/foo
+ Foo
+ GET
+
+
+
+
+ 3
+
+
+ server/foo
+ Foo
+ GET
+
+
+
+
+
+
+ server/bar
+ Bar
+ GET
+
+
+ ',
+ $this->xml->from($resource)
+ );
+ }
+
/** @test */
function not_formatting_resources_with_circular_references()
{