Passed
Push — master ( a343df...d20b40 )
by Tim
10:40
created

XPath::setExpression()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\XMLSecurity\XML\ds;
6
7
use DOMElement;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\XML\Exception\InvalidDOMElementException;
10
use SimpleSAML\XMLSecurity\Exception\InvalidArgumentException;
11
use SimpleSAML\XMLSecurity\Utils\XPath as XPathUtils;
12
13
use function str_replace;
14
15
/**
16
 * Class implementing the XPath element.
17
 *
18
 * @package simplesamlphp/xml-security
19
 */
20
class XPath extends AbstractDsElement
21
{
22
    /**
23
     * Construct an XPath element.
24
     *
25
     * @param string $expression The XPath expression itself.
26
     * @param string[] $namespaces A key - value array with namespace definitions.
27
     */
28
    final public function __construct(
29
        protected string $expression,
30
        protected array $namespaces = [],
31
    ) {
32
        Assert::allString($namespaces, InvalidArgumentException::class);
33
        Assert::allString(array_keys($namespaces, InvalidArgumentException::class));
34
    }
35
36
37
    /**
38
     * Get the actual XPath expression.
39
     *
40
     * @return string
41
     */
42
    public function getExpression(): string
43
    {
44
        return $this->expression;
45
    }
46
47
48
    /**
49
     * Get the list of namespaces used in this XPath expression, with their corresponding prefix as
50
     * the keys of each element in the array.
51
     *
52
     * @return string[]
53
     */
54
    public function getNamespaces(): array
55
    {
56
        return $this->namespaces;
57
    }
58
59
60
    /**
61
     * Convert XML into a class instance
62
     *
63
     * @param DOMElement $xml
64
     * @return static
65
     *
66
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
67
     *   If the qualified name of the supplied element is wrong
68
     */
69
    public static function fromXML(DOMElement $xml): static
70
    {
71
        Assert::same($xml->localName, 'XPath', InvalidDOMElementException::class);
72
        Assert::same($xml->namespaceURI, self::NS, InvalidDOMElementException::class);
73
74
        $namespaces = [];
75
        $xpath = XPathUtils::getXPath($xml->ownerDocument);
0 ignored issues
show
Bug introduced by
It seems like $xml->ownerDocument can also be of type null; however, parameter $node of SimpleSAML\XMLSecurity\Utils\XPath::getXPath() does only seem to accept DOMNode, maybe add an additional type check? ( Ignorable by Annotation )

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

75
        $xpath = XPathUtils::getXPath(/** @scrutinizer ignore-type */ $xml->ownerDocument);
Loading history...
76
        foreach (XPathUtils::xpQuery($xml, './namespace::*', $xpath) as $ns) {
77
            if ($xml->getAttributeNode($ns->nodeName)) {
78
                // only add namespaces when they are defined explicitly in an attribute
79
                $namespaces[$ns->localName] = $xml->getAttribute($ns->nodeName);
80
            }
81
        }
82
83
        return new static($xml->textContent, $namespaces);
84
    }
85
86
87
    /**
88
     * @param DOMElement|null $parent
89
     * @return DOMElement
90
     */
91
    public function toXML(DOMElement $parent = null): DOMElement
92
    {
93
        $e = $this->instantiateParentElement($parent);
94
        $e->textContent = $this->getExpression();
95
96
        foreach ($this->getNamespaces() as $prefix => $namespace) {
97
            $e->setAttribute('xmlns:' . $prefix, $namespace);
98
        }
99
        return $e;
100
    }
101
}
102