Completed
Push — master ( 4e360d...80bc96 )
by Daan van
07:27
created

SAML2_XML_md_EntityDescriptor   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 238
Duplicated Lines 5.46 %

Coupling/Cohesion

Components 1
Dependencies 14
Metric Value
wmc 35
lcom 1
cbo 14
dl 13
loc 238
rs 9

1 Method

Rating   Name   Duplication   Size   Complexity  
F EntityDescriptor::__construct() 5 84 25

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace SAML2\XML\md;
4
5
use SAML2\Constants;
6
use SAML2\DOMDocumentFactory;
7
use SAML2\SignedElementHelper;
8
use SAML2\Utils;
9
10
/**
11
 * Class representing SAML 2 EntityDescriptor element.
12
 *
13
 * @package SimpleSAMLphp
14
 */
15
class EntityDescriptor extends SignedElementHelper
16
{
17
    /**
18
     * The entityID this EntityDescriptor represents.
19
     *
20
     * @var string
21
     */
22
    public $entityID;
23
24
    /**
25
     * The ID of this element.
26
     *
27
     * @var string|null
28
     */
29
    public $ID;
30
31
    /**
32
     * How long this element is valid, as a unix timestamp.
33
     *
34
     * @var int|null
35
     */
36
    public $validUntil;
37
38
    /**
39
     * The length of time this element can be cached, as string.
40
     *
41
     * @var string|null
42
     */
43
    public $cacheDuration;
44
45
    /**
46
     * Extensions on this element.
47
     *
48
     * Array of extension elements.
49
     *
50
     * @var array
51
     */
52
    public $Extensions = array();
53
54
    /**
55
     * Array with all roles for this entity.
56
     *
57
     * Array of \SAML2\XML\md\RoleDescriptor objects (and subclasses of RoleDescriptor).
58
     *
59
     * @var (\SAML2\XML\md\UnknownRoleDescriptor|\SAML2\XML\md\IDPSSODescriptor|\SAML2\XML\md\SPSSODescriptor|\SAML2\XML\md\AuthnAuthorityDescriptor|\SAML2\XML\md\AttributeAuthorityDescriptor|\SAML2\XML\md\PDPDescriptor)[]
60
     */
61
    public $RoleDescriptor = array();
62
63
    /**
64
     * AffiliationDescriptor of this entity.
65
     *
66
     * @var \SAML2\XML\md\AffiliationDescriptor|null
67
     */
68
    public $AffiliationDescriptor = null;
69
70
    /**
71
     * Organization of this entity.
72
     *
73
     * @var \SAML2\XML\md\Organization|null
74
     */
75
    public $Organization = null;
76
77
    /**
78
     * ContactPerson elements for this entity.
79
     *
80
     * @var \SAML2\XML\md\ContactPerson[]
81
     */
82
    public $ContactPerson = array();
83
84
    /**
85
     * AdditionalMetadataLocation elements for this entity.
86
     *
87
     * @var \SAML2\XML\md\AdditionalMetadataLocation[]
88
     */
89
    public $AdditionalMetadataLocation = array();
90
91
    /**
92
     * Initialize an EntitiyDescriptor.
93
     *
94
     * @param \DOMElement|null $xml The XML element we should load.
95
     * @throws \Exception
96
     */
97
    public function __construct(\DOMElement $xml = null)
98
    {
99
        parent::__construct($xml);
100
101
        if ($xml === null) {
102
            return;
103
        }
104
105
        if (!$xml->hasAttribute('entityID')) {
106
            throw new \Exception('Missing required attribute entityID on EntityDescriptor.');
107
        }
108
        $this->entityID = $xml->getAttribute('entityID');
109
110
        if ($xml->hasAttribute('ID')) {
111
            $this->ID = $xml->getAttribute('ID');
112
        }
113
        if ($xml->hasAttribute('validUntil')) {
114
            $this->validUntil = Utils::xsDateTimeToTimestamp($xml->getAttribute('validUntil'));
115
        }
116
        if ($xml->hasAttribute('cacheDuration')) {
117
            $this->cacheDuration = $xml->getAttribute('cacheDuration');
118
        }
119
120
        $this->Extensions = Extensions::getList($xml);
121
122
        for ($node = $xml->firstChild; $node !== null; $node = $node->nextSibling) {
123
            if (!($node instanceof \DOMElement)) {
124
                continue;
125
            }
126
127
            if ($node->namespaceURI !== Constants::NS_MD) {
128
                continue;
129
            }
130
131
            switch ($node->localName) {
132
                case 'RoleDescriptor':
133
                    $this->RoleDescriptor[] = new UnknownRoleDescriptor($node);
134
                    break;
135
                case 'IDPSSODescriptor':
136
                    $this->RoleDescriptor[] = new IDPSSODescriptor($node);
137
                    break;
138
                case 'SPSSODescriptor':
139
                    $this->RoleDescriptor[] = new SPSSODescriptor($node);
140
                    break;
141
                case 'AuthnAuthorityDescriptor':
142
                    $this->RoleDescriptor[] = new AuthnAuthorityDescriptor($node);
143
                    break;
144
                case 'AttributeAuthorityDescriptor':
145
                    $this->RoleDescriptor[] = new AttributeAuthorityDescriptor($node);
146
                    break;
147
                case 'PDPDescriptor':
148
                    $this->RoleDescriptor[] = new PDPDescriptor($node);
149
                    break;
150
            }
151
        }
152
153
        $affiliationDescriptor = Utils::xpQuery($xml, './saml_metadata:AffiliationDescriptor');
154
        if (count($affiliationDescriptor) > 1) {
155
            throw new \Exception('More than one AffiliationDescriptor in the entity.');
156
        } elseif (!empty($affiliationDescriptor)) {
157
            $this->AffiliationDescriptor = new AffiliationDescriptor($affiliationDescriptor[0]);
158
        }
159
160
        if (empty($this->RoleDescriptor) && is_null($this->AffiliationDescriptor)) {
161
            throw new \Exception('Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.');
162
        } elseif (!empty($this->RoleDescriptor) && !is_null($this->AffiliationDescriptor)) {
163
            throw new \Exception('AffiliationDescriptor cannot be combined with other RoleDescriptor elements in EntityDescriptor.');
164
        }
165
166
        $organization = Utils::xpQuery($xml, './saml_metadata:Organization');
167 View Code Duplication
        if (count($organization) > 1) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
168
            throw new \Exception('More than one Organization in the entity.');
169
        } elseif (!empty($organization)) {
170
            $this->Organization = new Organization($organization[0]);
171
        }
172
173
        foreach (Utils::xpQuery($xml, './saml_metadata:ContactPerson') as $cp) {
174
            $this->ContactPerson[] = new ContactPerson($cp);
175
        }
176
177
        foreach (Utils::xpQuery($xml, './saml_metadata:AdditionalMetadataLocation') as $aml) {
178
            $this->AdditionalMetadataLocation[] = new AdditionalMetadataLocation($aml);
179
        }
180
    }
181
182
    /**
183
     * Create this EntityDescriptor.
184
     *
185
     * @param \DOMElement|null $parent The EntitiesDescriptor we should append this EntityDescriptor to.
186
     * @return \DOMElement
187
     */
188
    public function toXML(\DOMElement $parent = null)
189
    {
190
        assert('is_string($this->entityID)');
191
        assert('is_null($this->ID) || is_string($this->ID)');
192
        assert('is_null($this->validUntil) || is_int($this->validUntil)');
193
        assert('is_null($this->cacheDuration) || is_string($this->cacheDuration)');
194
        assert('is_array($this->Extensions)');
195
        assert('is_array($this->RoleDescriptor)');
196
        assert('is_null($this->AffiliationDescriptor) || $this->AffiliationDescriptor instanceof \SAML2\XML\md\AffiliationDescriptor');
197
        assert('is_null($this->Organization) || $this->Organization instanceof \SAML2\XML\md\Organization');
198
        assert('is_array($this->ContactPerson)');
199
        assert('is_array($this->AdditionalMetadataLocation)');
200
201 View Code Duplication
        if ($parent === null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
202
            $doc = DOMDocumentFactory::create();
203
            $e = $doc->createElementNS(Constants::NS_MD, 'md:EntityDescriptor');
204
            $doc->appendChild($e);
205
        } else {
206
            $e = $parent->ownerDocument->createElementNS(Constants::NS_MD, 'md:EntityDescriptor');
207
            $parent->appendChild($e);
208
        }
209
210
        $e->setAttribute('entityID', $this->entityID);
211
212
        if (isset($this->ID)) {
213
            $e->setAttribute('ID', $this->ID);
214
        }
215
216
        if (isset($this->validUntil)) {
217
            $e->setAttribute('validUntil', gmdate('Y-m-d\TH:i:s\Z', $this->validUntil));
218
        }
219
220
        if (isset($this->cacheDuration)) {
221
            $e->setAttribute('cacheDuration', $this->cacheDuration);
222
        }
223
224
        Extensions::addList($e, $this->Extensions);
225
226
        /** @var \SAML2\XML\md\UnknownRoleDescriptor|\SAML2\XML\md\IDPSSODescriptor|\SAML2\XML\md\SPSSODescriptor|\SAML2\XML\md\AuthnAuthorityDescriptor|\SAML2\XML\md\AttributeAuthorityDescriptor|\SAML2\XML\md\PDPDescriptor $n */
227
        foreach ($this->RoleDescriptor as $n) {
228
            $n->toXML($e);
229
        }
230
231
        if (isset($this->AffiliationDescriptor)) {
232
            $this->AffiliationDescriptor->toXML($e);
233
        }
234
235
        if (isset($this->Organization)) {
236
            $this->Organization->toXML($e);
237
        }
238
239
        foreach ($this->ContactPerson as $cp) {
240
            $cp->toXML($e);
241
        }
242
243
        foreach ($this->AdditionalMetadataLocation as $n) {
244
            $n->toXML($e);
245
        }
246
247
        $this->signElement($e, $e->firstChild);
0 ignored issues
show
Documentation introduced by
$e->firstChild is of type object<DOMNode>, but the function expects a null|object<DOMElement>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
248
249
        return $e;
250
    }
251
}
252