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

XmlFormatter   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 62
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 23
dl 0
loc 62
rs 10
c 1
b 0
f 0
wmc 8

5 Methods

Rating   Name   Duplication   Size   Complexity  
A from() 0 14 2
A flatten() 0 8 2
A __construct() 0 4 2
A prepare() 0 5 1
A in() 0 5 1
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