Skip to content

Commit

Permalink
Enable formatting nested resources as xml
Browse files Browse the repository at this point in the history
  • Loading branch information
Stratadox committed Feb 2, 2020
1 parent 8d91e2a commit 9f73720
Show file tree
Hide file tree
Showing 3 changed files with 266 additions and 1 deletion.
22 changes: 21 additions & 1 deletion src/XmlFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use SimpleXMLElement;
use Throwable;
use function array_walk_recursive;
use function current;
use function sprintf;

abstract class XmlFormatter implements ResourceFormatter
Expand Down Expand Up @@ -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();
Expand All @@ -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;
}
}
115 changes: 115 additions & 0 deletions tests/formatting_the_resource_as_condensed_xml.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
'<?xml version="1.0"?>
<nested-resource>
<children>
<child><child-resource n="1" /></child>
<child><child-resource n="2" /></child>
<child><child-resource n="3" /></child>
</children>
</nested-resource>',
$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(
'<?xml version="1.0"?>
<nested-resource>
<children>
<child>
<child-resource>
<grandchildren>
<grandchild>
<minimal-resource foo="bar"/>
</grandchild>
</grandchildren>
</child-resource>
</child>
</children>
</nested-resource>',
$this->xml->from($resource)
);
}

/** @test */
function formatting_a_resource_with_a_link()
{
Expand Down Expand Up @@ -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(
'<?xml version="1.0"?>
<nested-resource>
<children>
<child>
<child-resource n="1">
<links>
<link href="http://foo/foo" rel="Foo" type="GET"/>
</links>
</child-resource>
</child>
<child>
<child-resource n="2">
<links>
<link href="http://foo/foo" rel="Foo" type="GET"/>
</links>
</child-resource>
</child>
<child>
<child-resource n="3">
<links>
<link href="http://foo/foo" rel="Foo" type="GET"/>
</links>
</child-resource>
</child>
</children>
<links>
<link href="http://foo/bar" rel="Bar" type="GET"/>
</links>
</nested-resource>',
$this->xml->from($resource)
);
}

/** @test */
function not_formatting_resources_with_circular_references()
{
Expand Down
130 changes: 130 additions & 0 deletions tests/formatting_the_resource_as_xml.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
'<?xml version="1.0"?>
<nested-resource>
<children>
<child><child-resource><n>1</n></child-resource></child>
<child><child-resource><n>2</n></child-resource></child>
<child><child-resource><n>3</n></child-resource></child>
</children>
</nested-resource>',
$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(
'<?xml version="1.0"?>
<nested-resource>
<children>
<child>
<child-resource>
<grandchildren>
<grandchild>
<minimal-resource>
<foo>bar</foo>
</minimal-resource>
</grandchild>
</grandchildren>
</child-resource>
</child>
</children>
</nested-resource>',
$this->xml->from($resource)
);
}

/** @test */
function formatting_a_resource_with_a_link()
{
Expand Down Expand Up @@ -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(
'<?xml version="1.0"?>
<nested-resource>
<children>
<child><child-resource>
<n>1</n>
<links>
<link>
<href>server/foo</href>
<rel>Foo</rel>
<type>GET</type>
</link>
</links>
</child-resource></child>
<child><child-resource>
<n>2</n>
<links>
<link>
<href>server/foo</href>
<rel>Foo</rel>
<type>GET</type>
</link>
</links>
</child-resource></child>
<child><child-resource>
<n>3</n>
<links>
<link>
<href>server/foo</href>
<rel>Foo</rel>
<type>GET</type>
</link>
</links>
</child-resource></child>
</children>
<links>
<link>
<href>server/bar</href>
<rel>Bar</rel>
<type>GET</type>
</link>
</links>
</nested-resource>',
$this->xml->from($resource)
);
}

/** @test */
function not_formatting_resources_with_circular_references()
{
Expand Down

0 comments on commit 9f73720

Please sign in to comment.