Passed
Push — master ( bd21f0...7cad03 )
by Tim
01:40
created

ExtendableElementTrait::isEmptyElement()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 6
c 0
b 0
f 0
nc 4
nop 0
dl 0
loc 12
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\XML;
6
7
use DOMElement;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\XML\Constants;
10
11
/**
12
 * Trait grouping common functionality for elements implementing the xs:any element.
13
 *
14
 * @package simplesamlphp/xml-common
15
 */
16
trait ExtendableElementTrait
17
{
18
    /** @var \SimpleSAML\XML\XMLElementInterface[] */
19
    protected array $elements = [];
20
21
    /** @var string|array */
22
    protected $namespace = Constants::XS_ANY_NS_ANY;
23
24
25
    /**
26
     * Set an array with all elements present.
27
     *
28
     * @param array \SimpleSAML\XML\XMLElementInterface[]
29
     */
30
    public function setElements(array $elements): void
31
    {
32
        Assert::allIsInstanceOf($elements, XMLElementInterface::class);
33
34
        // Get namespaces for all elements
35
        $actual_namespaces = array_map(
36
            function($elt) {
37
                return $elt->getNamespaceURI();
38
            },
39
            $elements
40
        );
41
42
        if ($this->namespace === Constants::XS_ANY_NS_LOCAL) {
43
            // If ##local then all namespaces must be null
44
            Assert::allNull($actual_namespaces);
45
        } elseif (is_array($this->namespace)) {
46
            // Make a local copy of the property that we can edit
47
            $allowed_namespaces = $this->namespace;
48
49
            // Replace the ##targetedNamespace with the actual namespace
50
            if (($key = array_search(Constants::XS_ANY_NS_TARGET, $allowed_namespaces)) !== false) {
51
                $allowed_namespaces[$key] = static::NS;
1 ignored issue
show
Bug introduced by
The constant SimpleSAML\XML\ExtendableElementTrait::NS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
52
            }
53
54
            // Replace the ##local with null
55
            if (($key = array_search(Constants::XS_ANY_NS_LOCAL, $allowed_namespaces)) !== false) {
56
                $allowed_namespaces[$key] = null;
57
            }
58
59
            $diff = array_diff($actual_namespaces, $allowed_namespaces);
60
            Assert::isEmpty(
61
                $diff,
62
                sprintf(
63
                    'Elements from namespaces [ %s ] are not allowed inside a %s element.',
64
                    rtrim(implode(', ', $diff)),
65
                    static::NS
66
                )
67
            );
68
        } else {
69
            // All elements must be namespaced, ergo non-null
70
            Assert::allNotNull($actual_namespaces);
71
72
            if ($this->namespace === Constants::XS_ANY_NS_OTHER) {
73
                // Must be any namespace other than the parent element
74
                Assert::allNotSame($actual_namespaces, static::NS);
75
            } elseif ($this->namespace === Constants::XS_ANY_NS_TARGET) {
76
                // Must be the same namespace as the one of the parent element
77
                Assert::allSame($actual_namespaces, static::NS);
78
            }
79
        }
80
81
        $this->elements = $elements;
82
    }
83
84
85
    /**
86
     * Get an array with all elements present.
87
     *
88
     * @return \SimpleSAML\XML\XMLElementInterface[]
89
     */
90
    public function getElements(): array
91
    {
92
        return $this->elements;
93
    }
94
95
96
    /**
97
     * Set the value of the namespace-property
98
     *
99
     * @param string|array $namespace
100
     */
101
    public function setNamespace($namespace): void
102
    {
103
        Assert::true(is_array($namespace) || is_string($namespace));
104
105
        if (!is_array($namespace)) {
106
            // Must be one of the predefined values
107
            Assert::oneOf($namespace, Constants::XS_ANY_NS);
108
        } else {
109
            // Array must be non-empty and cannot contain ##any or ##other
110
            Assert::notEmpty($namespace);
111
            Assert::allNotSame($namespace, Constants::XS_ANY_NS_ANY);
112
            Assert::allNotSame($namespace, Constants::XS_ANY_NS_OTHER);
113
        }
114
115
        $this->namespace = $namespace;
116
    }
117
}
118