SamlMessage::fromXML()   B
last analyzed

Complexity

Conditions 8
Paths 11

Size

Total Lines 51

Duplication

Lines 10
Ratio 19.61 %

Code Coverage

Tests 16
CRAP Score 9.8033

Importance

Changes 0
Metric Value
dl 10
loc 51
c 0
b 0
f 0
ccs 16
cts 23
cp 0.6957
rs 7.8246
cc 8
nc 11
nop 2
crap 9.8033

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the LightSAML-Core package.
5
 *
6
 * (c) Milos Tomic <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace LightSaml\Model\Protocol;
13
14
use LightSaml\Error\LightSamlXmlException;
15
use LightSaml\Model\Context\DeserializationContext;
16
use LightSaml\Model\Context\SerializationContext;
17
use LightSaml\Helper;
18
use LightSaml\Model\AbstractSamlModel;
19
use LightSaml\Model\Assertion\Issuer;
20
use LightSaml\Model\SamlElementInterface;
21
use LightSaml\Model\XmlDSig\Signature;
22
use LightSaml\SamlConstants;
23
24
abstract class SamlMessage extends AbstractSamlModel
25
{
26
    /** @var string */
27
    protected $id;
28
29
    /** @var string */
30
    protected $version = SamlConstants::VERSION_20;
31
32
    /** @var int */
33
    protected $issueInstant;
34
35
    /** @var string|null */
36
    protected $destination;
37
38
    /** @var Issuer|null */
39
    protected $issuer;
40
41
    /** @var string|null */
42
    protected $consent;
43
44
    /** @var Signature|null */
45
    protected $signature;
46
47
    /** @var string|null */
48
    protected $relayState;
49
50
    /**
51
     * @param string                 $xml
52
     * @param DeserializationContext $context
53
     *
54
     * @return AuthnRequest|LogoutRequest|LogoutResponse|Response|SamlMessage
55
     *
56
     * @throws \Exception
57
     */
58 11
    public static function fromXML($xml, DeserializationContext $context)
59
    {
60 11
        if (false == is_string($xml)) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
61
            throw new \InvalidArgumentException('Expecting string');
62
        }
63
64 11
        $context->getDocument()->loadXML($xml);
65
66 11
        $node = $context->getDocument()->firstChild;
67 11
        while ($node && $node instanceof \DOMComment) {
68 4
            $node = $node->nextSibling;
69
        }
70 11
        if (null === $node) {
71
            throw new LightSamlXmlException('Empty XML');
72
        }
73
74 11
        if (SamlConstants::NS_PROTOCOL !== $node->namespaceURI) {
75
            throw new LightSamlXmlException(sprintf(
76
                "Invalid namespace '%s' of the root XML element, expected '%s'",
77
                $context->getDocument()->namespaceURI,
78
                SamlConstants::NS_PROTOCOL
79
            ));
80
        }
81
82
        $map = array(
83 11
            'AttributeQuery' => null,
84
            'AuthnRequest' => '\LightSaml\Model\Protocol\AuthnRequest',
85
            'LogoutResponse' => '\LightSaml\Model\Protocol\LogoutResponse',
86
            'LogoutRequest' => '\LightSaml\Model\Protocol\LogoutRequest',
87
            'Response' => '\LightSaml\Model\Protocol\Response',
88
            'ArtifactResponse' => null,
89
            'ArtifactResolve' => null,
90
        );
91
92 11
        $rootElementName = $node->localName;
93
94 11 View Code Duplication
        if (array_key_exists($rootElementName, $map)) {
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...
95 11
            if ($class = $map[$rootElementName]) {
96
                /** @var SamlElementInterface $result */
97 11
                $result = new $class();
98
            } else {
99 11
                throw new \LogicException('Deserialization of %s root element is not implemented');
100
            }
101
        } else {
102
            throw new LightSamlXmlException(sprintf("Unknown SAML message '%s'", $rootElementName));
103
        }
104
105 11
        $result->deserialize($node, $context);
106
107 11
        return $result;
108
    }
109
110
    /**
111
     * @param string $id
112
     *
113
     * @return SamlMessage
114
     */
115 30
    public function setID($id)
116
    {
117 30
        $this->id = (string) $id;
118
119 30
        return $this;
120
    }
121
122
    /**
123
     * @return string
124
     */
125 28
    public function getID()
126
    {
127 28
        return $this->id;
128
    }
129
130
    /**
131
     * @param int|string|\DateTime $issueInstant
132
     *
133
     * @return SamlMessage
134
     */
135 29
    public function setIssueInstant($issueInstant)
136
    {
137 29
        $this->issueInstant = Helper::getTimestampFromValue($issueInstant);
138
139 29
        return $this;
140
    }
141
142
    /**
143
     * @return int|null
144
     */
145 3
    public function getIssueInstantTimestamp()
146
    {
147 3
        return $this->issueInstant;
148
    }
149
150
    /**
151
     * @return string|null
152
     */
153 27
    public function getIssueInstantString()
154
    {
155 27
        if ($this->issueInstant) {
156 26
            return Helper::time2string($this->issueInstant);
157
        }
158
159 1
        return null;
160
    }
161
162
    /**
163
     * @return \DateTime|null
164
     */
165
    public function getIssueInstantDateTime()
166
    {
167
        if ($this->issueInstant) {
168
            return new \DateTime('@'.$this->issueInstant);
169
        }
170
171
        return null;
172
    }
173
174
    /**
175
     * @param string $version
176
     *
177
     * @return SamlMessage
178
     */
179 16
    public function setVersion($version)
180
    {
181 16
        $this->version = (string) $version;
182
183 16
        return $this;
184
    }
185
186
    /**
187
     * @return string
188
     */
189 26
    public function getVersion()
190
    {
191 26
        return $this->version;
192
    }
193
194
    /**
195
     * @param null|string $destination
196
     *
197
     * @return SamlMessage
198
     */
199 27
    public function setDestination($destination)
200
    {
201 27
        $this->destination = $destination;
202
203 27
        return $this;
204
    }
205
206
    /**
207
     * @return null|string
208
     */
209 33
    public function getDestination()
210
    {
211 33
        return $this->destination;
212
    }
213
214
    /**
215
     * @param Issuer|null $issuer
216
     *
217
     * @return SamlMessage
218
     */
219 30
    public function setIssuer(Issuer $issuer = null)
220
    {
221 30
        $this->issuer = $issuer;
222
223 30
        return $this;
224
    }
225
226
    /**
227
     * @return \LightSaml\Model\Assertion\NameID|null
228
     */
229 36
    public function getIssuer()
230
    {
231 36
        return $this->issuer;
232
    }
233
234
    /**
235
     * @param null|string $consent
236
     *
237
     * @return StatusResponse
238
     */
239 4
    public function setConsent($consent)
240
    {
241 4
        $this->consent = $consent;
242
243 4
        return $this;
244
    }
245
246
    /**
247
     * @return null|string
248
     */
249 22
    public function getConsent()
250
    {
251 22
        return $this->consent;
252
    }
253
254
    /**
255
     * @param Signature|null $signature
256
     *
257
     * @return SamlMessage
258
     */
259 24
    public function setSignature(Signature $signature = null)
260
    {
261 24
        $this->signature = $signature;
262
263 24
        return $this;
264
    }
265
266
    /**
267
     * @return Signature|null
268
     */
269 30
    public function getSignature()
270
    {
271 30
        return $this->signature;
272
    }
273
274
    /**
275
     * @param null|string $relayState
276
     *
277
     * @return SamlMessage
278
     */
279 6
    public function setRelayState($relayState)
280
    {
281 6
        $this->relayState = $relayState;
282
283 6
        return $this;
284
    }
285
286
    /**
287
     * @return null|string
288
     */
289 10
    public function getRelayState()
290
    {
291 10
        return $this->relayState;
292
    }
293
294
    /**
295
     * @param \DOMNode             $parent
296
     * @param SerializationContext $context
297
     *
298
     * @return void
299
     */
300 21
    public function serialize(\DOMNode $parent, SerializationContext $context)
301
    {
302 21
        $this->attributesToXml(array('ID', 'Version', 'IssueInstant', 'Destination', 'Consent'), $parent);
0 ignored issues
show
Compatibility introduced by
$parent of type object<DOMNode> is not a sub-type of object<DOMElement>. It seems like you assume a child class of the class DOMNode to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
303
304 21
        $this->singleElementsToXml(array('Issuer'), $parent, $context);
305 21
    }
306
307
    /**
308
     * @param \DOMNode               $node
309
     * @param DeserializationContext $context
310
     */
311 22 View Code Duplication
    public function deserialize(\DOMNode $node, DeserializationContext $context)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
312
    {
313 22
        $this->attributesFromXml($node, array('ID', 'Version', 'IssueInstant', 'Destination', 'Consent'));
0 ignored issues
show
Compatibility introduced by
$node of type object<DOMNode> is not a sub-type of object<DOMElement>. It seems like you assume a child class of the class DOMNode to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
314
315 22
        $this->singleElementsFromXml($node, $context, array(
0 ignored issues
show
Compatibility introduced by
$node of type object<DOMNode> is not a sub-type of object<DOMElement>. It seems like you assume a child class of the class DOMNode to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
316 22
            'Issuer' => array('saml', 'LightSaml\Model\Assertion\Issuer'),
317
            'Signature' => array('ds', 'LightSaml\Model\XmlDSig\SignatureXmlReader'),
318
        ));
319 22
    }
320
}
321