Test Failed
Pull Request — master (#3)
by MediaCT
03:44
created

XmlAccessor::getChild()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 3
dl 0
loc 16
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Copyright MediaCT. All rights reserved.
4
 * https://www.mediact.nl
5
 */
6
7
namespace Mediact\CodingStandard\PhpStorm;
8
9
use InvalidArgumentException;
10
use SimpleXMLElement;
11
12
class XmlAccessor implements XmlAccessorInterface
13
{
14
    /**
15
     * Get a child node, create it when it does not exist.
16
     *
17
     * @param SimpleXMLElement $element
18
     * @param string           $name
19
     * @param array            $attributes
20
     *
21
     * @return SimpleXMLElement
22
     */
23
    public function getChild(
24
        SimpleXMLElement $element,
25
        $name,
26
        array $attributes = []
27
    ) {
28
        $xpath = $name . $this->getAttributesXpath($attributes);
29
30
        $result = $element->xpath($xpath);
31
        if (empty($result)) {
32
            $node = $element->addChild($name);
33
            $this->setAttributes($node, $attributes);
34
        } else {
35
            $node = reset($result);
36
        }
37
38
        return $node;
39
    }
40
41
    /**
42
     * Get a descendant, create it when it does not exist.
43
     *
44
     * @param SimpleXMLElement $element
45
     * @param array            $path
46
     *
47
     * @return SimpleXMLElement
48
     *
49
     * @throws InvalidArgumentException When the descendant path is invalid.
50
     */
51
    public function getDescendant(
52
        SimpleXMLElement $element,
53
        array $path
54
    ) {
55
        foreach ($path as $childProperties) {
56
            if (!is_array($childProperties)
57
                || empty($childProperties)
58
            ) {
59
                throw new InvalidArgumentException('Invalid descendant path');
60
            }
61
            $name       = array_shift($childProperties);
62
            $attributes = count($childProperties)
63
                ? array_shift($childProperties)
64
                : [];
65
66
            $element = $this->getChild($element, $name, $attributes);
67
        }
68
        return $element;
69
    }
70
71
    /**
72
     * Set the attributes of a node.
73
     *
74
     * @param SimpleXMLElement $element
75
     * @param array            $attributes
76
     *
77
     * @return void
78
     */
79
    public function setAttributes(
80
        SimpleXMLElement $element,
81
        array $attributes
82
    ) {
83
        $storage = $element->attributes();
84
        foreach ($attributes as $key => $value) {
85
            if (isset($storage->{$key})) {
86
                $storage->{$key} = $value;
87
            } else {
88
                $element->addAttribute($key, $value);
89
            }
90
        }
91
    }
92
93
    /**
94
     * Get an xpath for attributes.
95
     *
96
     * @param array $attributes
97
     *
98
     * @return string
99
     */
100
    private function getAttributesXpath(array $attributes)
101
    {
102
        $xpath = '';
103
        if (!empty($attributes)) {
104
            $parts = [];
105
            foreach ($attributes as $key => $value) {
106
                $parts[] = '@' . $key . '="' . $value . '"';
107
            }
108
            $xpath .= '[' . implode(' and ', $parts) . ']';
109
        }
110
        return $xpath;
111
    }
112
}
113