Completed
Push — master ( fe0dfb...2709b3 )
by Bas
03:25
created

SoapDeserializationVisitor::throwSoap11Fault()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace DMT\Soap\Serializer;
4
5
use JMS\Serializer\Exception\InvalidArgumentException;
6
use JMS\Serializer\XmlDeserializationVisitor;
7
8
/**
9
 * Class SoapDeserializationVisitor
10
 *
11
 * @package DMT\Soap
12
 */
13
class SoapDeserializationVisitor extends XmlDeserializationVisitor implements SoapNamespaceInterface
14
{
15
    /**
16
     * @param string $data3
17
     *
18
     * @return mixed|\SimpleXMLElement
19
     * @throws InvalidArgumentException
20
     * @throws SoapFaultException
21
     */
22 10
    public function prepare($data3)
23
    {
24
        /** @var \SimpleXMLElement $element */
25 10
        $element = parent::prepare($data3);
26
27 10
        $version = array_search(current($element->getNamespaces()), static::SOAP_NAMESPACES);
28 10
        if (!$version) {
29 1
            throw new InvalidArgumentException('Unsupported SOAP version');
30
        }
31
32 9
        $messages = $element->xpath('*[local-name()="Body"]/*');
33 9
        if (count($messages) === 1) {
34 9
            $element = $messages[0];
35
        }
36
37 9
        if ($element->getName() === 'Fault') {
38 5
            if ($version == static::SOAP_1_1) {
39 2
                $this->throwSoap11Fault($element);
40
            } else {
41 3
                $this->throwSoap12Fault($element);
42
            }
43
        }
44
45 4
        return $element;
46
    }
47
48
    /**
49
     * @param \SimpleXMLElement $fault
50
     *
51
     * @throws SoapFaultException
52
     */
53 2
    protected function throwSoap11Fault(\SimpleXMLElement $fault)
54
    {
55 2
        $faultcode = $faultstring = '';
56 2
        $faultactor = $detail = null;
57
58 2
        extract($this->elementToArray($fault), EXTR_IF_EXISTS);
59
60 2
        throw new SoapFaultException($this->removePrefix($faultcode), $faultstring, $faultactor, $detail);
61
    }
62
63
    /**
64
     * @param \SimpleXMLElement $fault
65
     *
66
     * @throws SoapFaultException
67
     */
68 3
    protected function throwSoap12Fault(\SimpleXMLElement $fault)
69
    {
70 3
        $lang = substr(locale_get_default(), 0, 2);
71 3
        $path = '*[local-name()="Reason"]/*[local-name()="Text" and @xml:lang="' . $lang . '"]';
72
73 3
        $messages = $fault->xpath($path);
74 3
        if (count($messages) === 0) {
75 1
            $messages = $fault->xpath('*[local-name()="Reason"]/*[local-name()="Text"]');
76
        }
77
78 3
        $code = array_map(
79 3
            [$this, 'removePrefix'],
80 3
            $fault->xpath('//*[local-name()="Code" or local-name()="Subcode"]/*[local-name()="Value"]')
81
        );
82
83 3
        $node = $fault->xpath('*[local-name()="Node"]')[0] ?? null;
84 3
        $detail = $fault->xpath('*[local-name()="Detail"]')[0] ?? null;
85
86 3
        if ($detail !== null) {
87 3
            $detail = $this->elementToArray($detail);
88
        }
89
90 3
        throw new SoapFaultException(implode('.', $code), $messages[0], $node, $detail);
91
    }
92
93
    /**
94
     * @param \SimpleXMLElement $element
95
     *
96
     * @return array
97
     */
98 5
    protected function elementToArray(\SimpleXMLElement $element): array
99
    {
100 5
        $result = [];
101 5
        foreach ($element->xpath('*') as $node) {
102 5
            if (count($node->xpath('*')) > 0) {
103 2
                $value = $this->elementToArray($node);
104
            } else {
105 5
                $value = strval($node);
106
            }
107 5
            $result = array_merge_recursive($result, [$node->getName() => $value]);
108
        }
109
110 5
        return $result;
111
    }
112
113
    /**
114
     * Remove a prefix from text node.
115
     *
116
     * @param string $value A node value containing a namespace prefix, eg SOAP-ENV:Client.
117
     *
118
     * @return string
119
     */
120 5
    protected function removePrefix(string $value): string
121
    {
122 5
        return preg_replace('~^(.+:)?(.*)$~', "$2", $value);
123
    }
124
}
125