Completed
Push — master ( b63f4d...9f7372 )
by Jesse
01:49
created

XmlFormatter::prepare()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Stratadox\RestResource;
4
5
use SimpleXMLElement;
6
use Throwable;
7
use function array_walk_recursive;
8
use function current;
9
use function sprintf;
10
11
abstract class XmlFormatter implements ResourceFormatter
12
{
13
    use LinkRetrieval;
14
15
    /** @var string */
16
    private $baseUri;
17
    /** @var Singularizer */
18
    protected $singularizer;
19
20
    public function __construct(string $baseUri, Singularizer $singularizer = null)
21
    {
22
        $this->baseUri = $baseUri;
23
        $this->singularizer = $singularizer ?: BoogieSingularizer::default();
24
    }
25
26
    public static function in(
27
        string $locale,
28
        string $baseUri
29
    ): ResourceFormatter {
30
        return new static($baseUri, BoogieSingularizer::in($locale));
31
    }
32
33
    public function from(RestResource $resource): string
34
    {
35
        $xml = new SimpleXMLElement(sprintf(
36
            '<?xml version="1.0"?><%s />',
37
            $resource->name()
38
        ));
39
        try {
40
            $this->toSimpleXML(
41
                current($this->prepare($resource)),
42
                $xml
43
            );
44
            return (string) $xml->asXML();
45
        } catch (Throwable $exception) {
46
            throw CannotFormatXml::because($resource, $exception);
47
        }
48
    }
49
50
    // @todo inject serializer instead
51
    abstract protected function toSimpleXML(
52
        array $input,
53
        SimpleXMLElement $parent,
54
        bool $alreadySingularized = false
55
    ): void;
56
57
    private function prepare(RestResource $resource): array
58
    {
59
        return [$resource->name() =>
60
            $this->flatten($resource->body()) +
61
            $this->linksOf($resource, $this->baseUri)
62
        ];
63
    }
64
65
    private function flatten(array $body): array
66
    {
67
        array_walk_recursive($body, function (&$data) {
68
            if ($data instanceof RestResource) {
69
                $data = $this->prepare($data);
70
            }
71
        });
72
        return $body;
73
    }
74
}
75