Passed
Push — master ( 204a50...e241be )
by Martin
01:09
created

MarshalXml::castValueToString()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 2
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 2
eloc 1
nc 2
nop 1
crap 2
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace KingsonDe\Marshal;
6
7
use KingsonDe\Marshal\Data\Collection;
8
use KingsonDe\Marshal\Data\CollectionCallable;
9
use KingsonDe\Marshal\Data\DataStructure;
10
use KingsonDe\Marshal\Exception\XmlSerializeException;
11
12
/**
13
 * @method static string serializeItem(AbstractMapper $mapper, ...$data)
14
 * @method static string serializeItemCallable(callable $mappingFunction, ...$data)
15
 */
16
class MarshalXml extends Marshal {
17
18
    const ATTRIBUTES_KEY = '@attributes';
19
    const DATA_KEY       = '@data';
20
    const CDATA_KEY      = '@cdata';
21
22
    /**
23
     * @var string
24
     */
25
    protected static $version = '1.0';
26
27
    /**
28
     * @var string
29
     */
30
    protected static $encoding = 'UTF-8';
31
32 1
    public static function setVersion(string $version) {
33 1
        static::$version = $version;
34 1
    }
35
36 1
    public static function setEncoding(string $encoding) {
37 1
        static::$encoding = $encoding;
38 1
    }
39
40
    /**
41
     * @param DataStructure $dataStructure
42
     * @return string
43
     * @throws \KingsonDe\Marshal\Exception\XmlSerializeException
44
     */
45 8
    public static function serialize(DataStructure $dataStructure) {
46 8
        if ($dataStructure instanceof Collection || $dataStructure instanceof CollectionCallable) {
47 1
            throw new XmlSerializeException('Collections in XML cannot be generated at root level.');
48
        }
49
50 7
        $data = static::buildDataStructure($dataStructure);
51
52
        if (null === $data) {
53 7
            throw new XmlSerializeException('No data structure.');
54
        }
55 7
56 1
        try {
57 1
            $xml = new \DOMDocument(static::$version, static::$encoding);
58
59 1
            static::processNodes($data, $xml);
60
61
            return $xml->saveXML();
62 6
        } catch (\Exception $e) {
63 6
            throw new XmlSerializeException($e->getMessage(), $e->getCode(), $e);
64
        }
65 6
    }
66 1
67 1
    public static function serializeCollection(AbstractMapper $mapper, ...$data) {
68 5
        throw new XmlSerializeException('Collections in XML cannot be generated at root level.');
69 1
    }
70 1
71 1
    public static function serializeCollectionCallable(callable $mappingFunction, ...$data) {
72 1
        throw new XmlSerializeException('Collections in XML cannot be generated at root level.');
73
    }
74 4
75
    /**
76
     * @param array $nodes
77 6
     * @param \DOMElement|\DOMDocument $parentXmlNode
78 3
     */
79 3
    protected static function processNodes(array $nodes, $parentXmlNode) {
80
        $dom = $parentXmlNode->ownerDocument ?? $parentXmlNode;
81 6
82
        foreach ($nodes as $name => $data) {
83 6
            $node = XmlNodeParser::parseNode($name, $data);
84
85 5
            // new node with scalar value
86 1
            if ($node->hasNodeValue()) {
87 1
                if ($node->isCData()) {
88
                    $xmlNode      = $dom->createElement($node->getName());
0 ignored issues
show
Bug introduced by
The method createElement() does not exist on DOMElement. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

88
                    /** @scrutinizer ignore-call */ 
89
                    $xmlNode      = $dom->createElement($node->getName());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
89
                    $cdataSection = $dom->createCDATASection($node->getNodeValue());
0 ignored issues
show
Bug introduced by
The method createCDATASection() does not exist on DOMElement. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

89
                    /** @scrutinizer ignore-call */ 
90
                    $cdataSection = $dom->createCDATASection($node->getNodeValue());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
90
                    $xmlNode->appendChild($cdataSection);
91 1
                } else {
92 1
                    $xmlNode = $dom->createElement($node->getName(), $node->getNodeValue());
93
                }
94
                static::addAttributes($node, $xmlNode);
95 1
                $parentXmlNode->appendChild($xmlNode);
96 1
                continue;
97
            }
98
99 6
            // node collection of the same type
100 6
            if ($node->isCollection()) {
101 4
                static::processNodes($node->getChildrenNodes(), $parentXmlNode);
102 4
                continue;
103
            }
104 4
105 2
            // new node that might contain other nodes
106 2
            $xmlNode = $dom->createElement($node->getName());
107
            static::addAttributes($node, $xmlNode);
108
            $parentXmlNode->appendChild($xmlNode);
109 4
            if ($node->hasChildrenNodes()) {
110 2
                static::processNodes($node->getChildrenNodes(), $xmlNode);
111 4
            }
112 2
        }
113 2
    }
114
115
    protected static function addAttributes(XmlNode $node, \DOMElement $xmlNode) {
116
        foreach ($node->getAttributes() as $name => $value) {
117 4
            $xmlNode->setAttribute($name, $value);
118 4
        }
119 2
    }
120
}
121