Completed
Push — master ( da4b66...3ae217 )
by Tim
19s queued 15s
created

AbstractSubjectQuery   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 6
eloc 39
c 1
b 0
f 0
dl 0
loc 99
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A toXML() 0 18 1
A fromXML() 0 42 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML11\XML\samlp;
6
7
use DOMElement;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\SAML11\Constants as C;
10
use SimpleSAML\SAML11\Utils;
11
use SimpleSAML\SAML11\XML\ExtensionPointInterface;
12
use SimpleSAML\SAML11\XML\ExtensionPointTrait;
13
use SimpleSAML\SAML11\XML\saml\Subject;
14
use SimpleSAML\XML\Attribute as XMLAttribute;
15
use SimpleSAML\XML\Chunk;
16
use SimpleSAML\XML\Exception\InvalidDOMElementException;
17
use SimpleSAML\XML\Exception\MissingElementException;
18
use SimpleSAML\XML\Exception\SchemaViolationException;
19
use SimpleSAML\XML\Exception\TooManyElementsException;
20
21
use function array_pop;
22
use function count;
23
use function explode;
24
25
/**
26
 * SAMLP Query data type.
27
 *
28
 * @package simplesamlphp/saml11
29
 */
30
abstract class AbstractSubjectQuery extends AbstractSubjectQueryAbstractType implements ExtensionPointInterface
31
{
32
    use ExtensionPointTrait;
33
34
    /** @var string */
35
    public const LOCALNAME = 'SubjectQuery';
36
37
38
    /**
39
     * Initialize a custom samlp:SubjectQuery element.
40
     *
41
     * @param string $type
42
     */
43
    protected function __construct(
44
        protected string $type,
45
        Subject $subject,
46
    ) {
47
        parent::__construct($subject);
48
    }
49
50
51
    /**
52
     * Convert an XML element into a SubjectQuery.
53
     *
54
     * @param \DOMElement $xml The root XML element
55
     * @return static
56
     *
57
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
58
     *   if the qualified name of the supplied element is wrong
59
     */
60
    public static function fromXML(DOMElement $xml): static
61
    {
62
        Assert::same($xml->localName, 'SubjectQuery', InvalidDOMElementException::class);
63
        Assert::same($xml->namespaceURI, C::NS_SAMLP, InvalidDOMElementException::class);
64
        Assert::true(
65
            $xml->hasAttributeNS(C::NS_XSI, 'type'),
66
            'Missing required xsi:type in <samlp:SubjectQuery> element.',
67
            SchemaViolationException::class,
68
        );
69
70
        $type = $xml->getAttributeNS(C::NS_XSI, 'type');
71
        Assert::validQName($type, SchemaViolationException::class);
72
73
        // first, try to resolve the type to a full namespaced version
74
        $qname = explode(':', $type, 2);
75
        if (count($qname) === 2) {
76
            list($prefix, $element) = $qname;
77
        } else {
78
            $prefix = null;
79
            list($element) = $qname;
80
        }
81
        $ns = $xml->lookupNamespaceUri($prefix);
82
        $type = ($ns === null) ? $element : implode(':', [$ns, $element]);
83
84
        // now check if we have a handler registered for it
85
        $handler = Utils::getContainer()->getExtensionHandler($type);
86
        if ($handler === null) {
87
            $subject = Subject::getChildrenOfClass($xml);
88
            Assert::minCount($subject, 1, MissingElementException::class);
89
            Assert::maxCount($subject, 1, TooManyElementsException::class);
90
91
            // we don't have a handler, proceed with unknown query
92
            return new UnknownSubjectQuery(new Chunk($xml), $type, array_pop($subject));
93
        }
94
95
        Assert::subclassOf(
96
            $handler,
97
            AbstractSubjectQuery::class,
98
            'Elements implementing SubjectQuery must extend \SimpleSAML\SAML11\XML\samlp\AbstractSubjectQuery.',
99
        );
100
101
        return $handler::fromXML($xml);
102
    }
103
104
105
    /**
106
     * Convert this SubjectQuery to XML.
107
     *
108
     * @param \DOMElement $parent The element we are converting to XML.
109
     * @return \DOMElement The XML element after adding the data corresponding to this SubjectQuery.
110
     */
111
    public function toXML(?DOMElement $parent = null): DOMElement
112
    {
113
        // This unfortunately doesn't work because namespace attributes get messed up
114
        //$e = parent::toXML($parent);
115
116
        $e = $this->instantiateParentElement($parent);
117
        $e->setAttributeNS(
118
            'http://www.w3.org/2000/xmlns/',
119
            'xmlns:' . static::getXsiTypePrefix(),
120
            static::getXsiTypeNamespaceURI(),
121
        );
122
123
        $type = new XMLAttribute(C::NS_XSI, 'xsi', 'type', $this->getXsiType());
124
        $type->toXML($e);
125
126
        $this->getSubject()->toXML($e);
127
128
        return $e;
129
    }
130
}
131