Passed
Pull Request — master (#337)
by Tim
02:05
created

Publication::validateArray()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 13
nc 4
nop 1
dl 0
loc 22
rs 9.8333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\mdrpi;
6
7
use DateTimeImmutable;
8
use DOMElement;
9
use SimpleSAML\Assert\Assert;
10
use SimpleSAML\SAML2\Constants as C;
11
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
12
use SimpleSAML\XML\ArrayizableElementInterface;
13
use SimpleSAML\XML\Exception\InvalidDOMElementException;
14
15
use function preg_replace;
16
17
/**
18
 * Class for handling the mdrpi:Publication element.
19
 *
20
 * @link: http://docs.oasis-open.org/security/saml/Post2.0/saml-metadata-rpi/v1.0/saml-metadata-rpi-v1.0.pdf
21
 * @package simplesamlphp/saml2
22
 */
23
final class Publication extends AbstractMdrpiElement implements ArrayizableElementInterface
24
{
25
    /**
26
     * Create/parse a mdrpi:PublicationInfo element.
27
     *
28
     * @param string $publisher
29
     * @param \DateTimeImmutable|null $creationInstant
30
     * @param string|null $publicationId
31
     */
32
    public function __construct(
33
        protected string $publisher,
34
        protected ?DateTimeImmutable $creationInstant = null,
35
        protected ?string $publicationId = null,
36
    ) {
37
        Assert::nullOrSame($creationInstant?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class);
38
    }
39
40
41
    /**
42
     * Collect the value of the publisher-property
43
     *
44
     * @return string
45
     */
46
    public function getPublisher(): string
47
    {
48
        return $this->publisher;
49
    }
50
51
52
    /**
53
     * Collect the value of the creationInstant-property
54
     *
55
     * @return \DateTimeImmutable|null
56
     */
57
    public function getCreationInstant(): ?DateTimeImmutable
58
    {
59
        return $this->creationInstant;
60
    }
61
62
63
    /**
64
     * Collect the value of the publicationId-property
65
     *
66
     * @return string|null
67
     */
68
    public function getPublicationId(): ?string
69
    {
70
        return $this->publicationId;
71
    }
72
73
74
    /**
75
     * Convert XML into a Publication
76
     *
77
     * @param \DOMElement $xml The XML element we should load
78
     * @return static
79
     *
80
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
81
     *   if the qualified name of the supplied element is wrong
82
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
83
     *   if the supplied element is missing one of the mandatory attributes
84
     */
85
    public static function fromXML(DOMElement $xml): static
86
    {
87
        Assert::same($xml->localName, 'Publication', InvalidDOMElementException::class);
88
        Assert::same($xml->namespaceURI, Publication::NS, InvalidDOMElementException::class);
89
90
        $publisher = self::getAttribute($xml, 'publisher');
91
        $creationInstant = self::getOptionalAttribute($xml, 'creationInstant', null);
92
93
        // 2.2.1:  Time values MUST be expressed in the UTC timezone using the 'Z' timezone identifier
94
        if ($creationInstant !== null) {
95
            // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
96
            $creationInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $creationInstant, 1);
97
98
            Assert::validDateTimeZulu($creationInstant, ProtocolViolationException::class);
99
            $creationInstant = new DateTimeImmutable($creationInstant);
100
        }
101
102
        $publicationId = self::getOptionalAttribute($xml, 'publicationId', null);
103
104
        return new static($publisher, $creationInstant, $publicationId);
105
    }
106
107
108
    /**
109
     * Convert this element to XML.
110
     *
111
     * @param \DOMElement|null $parent The element we should append to.
112
     * @return \DOMElement
113
     */
114
    public function toXML(DOMElement $parent = null): DOMElement
115
    {
116
        $e = $this->instantiateParentElement($parent);
117
        $e->setAttribute('publisher', $this->getPublisher());
118
119
        if ($this->getCreationInstant() !== null) {
120
            $e->setAttribute('creationInstant', $this->getCreationInstant()->format(C::DATETIME_FORMAT));
121
        }
122
123
        if ($this->getPublicationId() !== null) {
124
            $e->setAttribute('publicationId', $this->getPublicationId());
125
        }
126
127
        return $e;
128
    }
129
130
131
    /**
132
     * Create a class from an array
133
     *
134
     * @param array $data
135
     * @return static
136
     */
137
    public static function fromArray(array $data): static
138
    {
139
        $data = self::validateArray($data);
140
141
        return new static(
142
            $data['publisher'],
143
            $data['creationInstant'] ?? null,
144
            $data['publicationId'] ?? null,
145
        );
146
    }
147
148
149
    /**
150
     * Validates an array representation of this object and returns the same array with
151
     * rationalized keys (casing) and parsed sub-elements.
152
     *
153
     * @param array $data
154
     * @return array $data
155
     */
156
    private static function validateArray(array $data): array
157
    {
158
        $data = array_change_key_case($data, CASE_LOWER);
159
160
        Assert::allOneOf(array_keys($data), ['publisher', 'creationinstant', 'publicationid']);
161
162
        Assert::keyExists($data, 'publisher');
163
        Assert::string($data['publisher']);
164
        $retval = ['publisher' => $data['publisher']];
165
166
        if (array_key_exists('creationinstant', $data)) {
167
            Assert::string($data['creationinstant']);
168
            Assert::validDateTimeZulu($data['creationinstant']);
169
            $retval['creationInstant'] = new DateTimeImmutable($data['creationinstant']);
170
        }
171
172
        if (array_key_exists('publicationid', $data)) {
173
            Assert::string($data['publicationid']);
174
            $retval['publicationId'] = $data['publicationid'];
175
        }
176
177
        return $retval;
178
    }
179
180
181
    /**
182
     * Create an array from this class
183
     *
184
     * @return array
185
     */
186
    public function toArray(): array
187
    {
188
        $data = [];
189
        $data['publisher'] = $this->getPublisher();
190
191
        if ($this->getCreationInstant() !== null) {
192
            $data['creationInstant'] = $this->getCreationInstant()->format(C::DATETIME_FORMAT);
193
        }
194
195
        if ($this->getPublicationId() !== null) {
196
            $data['publicationId'] = $this->getPublicationId();
197
        }
198
199
        return $data;
200
    }
201
}
202