XmlFormatter::withSingularizer()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
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
    private function __construct(string $baseUri, Singularizer $singularizer = null)
21
    {
22
        $this->baseUri = $baseUri;
23
        $this->singularizer = $singularizer ?: BoogieSingularizer::default();
24
    }
25
26
    public static function fromBaseUri(string $baseUri): ResourceFormatter
27
    {
28
        return new static($baseUri, BoogieSingularizer::default());
29
    }
30
31
    public static function in(
32
        string $locale,
33
        string $baseUri
34
    ): ResourceFormatter {
35
        return new static($baseUri, BoogieSingularizer::in($locale));
36
    }
37
38
    public static function withSingularizer(
39
        string $baseUri,
40
        Singularizer $singularizer
41
    ): ResourceFormatter {
42
        return new static($baseUri, $singularizer);
43
    }
44
45
    public function from(RestResource $resource): string
46
    {
47
        $xml = new SimpleXMLElement(sprintf(
48
            '<?xml version="1.0"?><%s />',
49
            $resource->name()
50
        ));
51
        try {
52
            $this->toSimpleXML(
53
                current($this->prepare($resource)),
54
                $xml
55
            );
56
            return (string) $xml->asXML();
57
        } catch (Throwable $exception) {
58
            throw CannotFormatXml::because($resource, $exception);
59
        }
60
    }
61
62
    // @todo inject serializer instead
63
    abstract protected function toSimpleXML(
64
        array $input,
65
        SimpleXMLElement $parent,
66
        bool $alreadySingularized = false
67
    ): void;
68
69
    private function prepare(RestResource $resource): array
70
    {
71
        return [$resource->name() =>
72
            $this->flatten($resource->body()) +
73
            $this->linksOf($resource, $this->baseUri)
74
        ];
75
    }
76
77
    private function flatten(array $body): array
78
    {
79
        array_walk_recursive($body, function (&$data) {
80
            if ($data instanceof RestResource) {
81
                $data = $this->prepare($data);
82
            }
83
        });
84
        return $body;
85
    }
86
}
87