Issues (493)

lib/SP/Http/XMLRPCResponseParse.php (1 issue)

1
<?php
2
/**
3
 * sysPass
4
 *
5
 * @author    nuxsmin
6
 * @link      https://syspass.org
7
 * @copyright 2012-2019, Rubén Domínguez nuxsmin@$syspass.org
8
 *
9
 * This file is part of sysPass.
10
 *
11
 * sysPass is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation, either version 3 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * sysPass is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 *  along with sysPass.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24
25
namespace SP\Http;
26
27
use DOMDocument;
28
use DOMElement;
29
use DOMException;
30
use DOMNode;
31
use DOMNodeList;
32
use InvalidArgumentException;
33
34
/**
35
 * Class XMLRPCResponseParse para el parseo de respuestas HTTP en formato XML-RPC
36
 *
37
 * @package SP\Http
38
 */
39
abstract class XMLRPCResponseParse
40
{
41
    /**
42
     * @var DOMElement
43
     */
44
    private $root;
45
    /**
46
     * @var string
47
     */
48
    private $xml;
49
    /**
50
     * @var array
51
     */
52
    private $data = [];
53
54
    /**
55
     * Constructor
56
     *
57
     * @param string $xml El documento XML
58
     *
59
     * @throws InvalidArgumentException
60
     */
61
    public function __construct($xml)
62
    {
63
        try {
64
            $this->xml = $xml;
65
66
            $dom = new DOMDocument();
67
            $dom->loadXML($xml);
68
69
            if ($dom->getElementsByTagName('methodResponse')->length === 0) {
70
                throw new DOMException(__u('Invalid XML-RPC response'));
71
            }
72
73
            $this->root = $dom->documentElement;
74
        } catch (DOMException $e) {
75
            throw new InvalidArgumentException($e->getMessage(), $e->getCode());
76
        }
77
    }
78
79
    /**
80
     * Obtener los datos del error
81
     *
82
     * @return array
83
     */
84
    public function getError()
85
    {
86
        return $this->parseNodes($this->root->getElementsByTagName('fault'));
87
    }
88
89
    /**
90
     * Obtener los nodos recursivamente y almacenar los datos en el atributo
91
     * de la clase _data
92
     *
93
     * @param DOMNodeList $nodes
94
     *
95
     * @return array
96
     */
97
    private function parseNodes(DOMNodeList $nodes)
98
    {
99
        if ($nodes->length > 0) {
100
            foreach ($nodes as $node) {
101
                if ($node instanceof DOMElement) {
102
                    /**
103
                     * @var $node DOMElement
104
                     */
105
                    switch ($node->nodeName) {
106
                        case 'struct':
107
                            return $this->parseStruct($node);
108
                        case 'array':
109
                            return $this->parseArray($node);
110
                        case 'fault':
111
                            return $this->parseFault($node);
112
                        case 'value':
113
                            $this->data = $this->parseValues($node);
114
                            break;
115
                        default:
116
                            $this->parseNodes($node->childNodes);
117
                    }
118
                }
119
            }
120
        }
121
122
        return [];
123
    }
124
125
    /**
126
     * Procesar nodos del tipo struct
127
     *
128
     * @param DOMElement $xmlStruct
129
     *
130
     * @return array
131
     */
132
    private function parseStruct(DOMElement $xmlStruct)
133
    {
134
        $dataStruct = [];
135
        $nStruct = 0;
136
137
        foreach ($xmlStruct->childNodes as $struct) {
138
            if ($struct instanceof DOMElement) {
139
                foreach ($struct->childNodes as $member) {
140
                    /**
141
                     * @var $member DOMNode
142
                     */
143
                    switch ($member->nodeName) {
144
                        case 'name':
145
                            $name = $member->nodeValue;
146
                            break;
147
                        case 'value':
148
                            $dataStruct[$name] = $this->parseNodeType($member->firstChild);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $name does not seem to be defined for all execution paths leading up to this point.
Loading history...
149
                            break;
150
                    }
151
                }
152
                $nStruct++;
153
            }
154
        }
155
156
        return $dataStruct;
157
    }
158
159
    /**
160
     * @param DOMNode $node
161
     *
162
     * @return bool|int|string|null
163
     */
164
    private function parseNodeType(DOMNode $node)
165
    {
166
        switch ($node->nodeName) {
167
            case 'int' :
168
            case 'i4' :
169
                return (int)$node->nodeValue;
170
            case 'string' :
171
                return $node->nodeValue;
172
            case 'dateTime.iso8601' :
173
                return date('d M y H:i:s', strtotime($node->nodeValue));
174
            case 'boolean' :
175
                return (bool)$node->nodeValue;
176
            default :
177
                return null;
178
        }
179
    }
180
181
    /**
182
     * Procesar nodos del tipo array
183
     *
184
     * @param DOMElement $xmlArray
185
     *
186
     * @return array
187
     */
188
    private function parseArray(DOMElement $xmlArray)
189
    {
190
        $arrayData = [];
191
192
        foreach ($xmlArray->childNodes as $array) {
193
            foreach ($array->childNodes as $data) {
194
                /**
195
                 * @var $data DOMElement
196
                 */
197
                if ($data instanceof DOMElement && $data->nodeName === 'value') {
198
                    $values = $this->parseValues($data);
199
200
                    if (is_array($values)) {
201
                        $arrayData[] = $values;
202
                    }
203
                }
204
            }
205
        }
206
207
        return $arrayData;
208
    }
209
210
    /**
211
     * Procesar nodos del tipo value
212
     *
213
     * @param DOMElement $xmlValues
214
     *
215
     * @return array
216
     */
217
    private function parseValues(DOMElement $xmlValues)
218
    {
219
        $valuesData = [];
220
221
        foreach ($xmlValues->childNodes as $xmlValue) {
222
            if ($xmlValue instanceof DOMElement) {
223
                $val = $this->parseNodeType($xmlValue);
224
225
                if (null === $val) {
226
                    return $this->parseNodes($xmlValues->childNodes);
227
                } else {
228
                    $valuesData[] = $val;
229
                }
230
            }
231
        }
232
233
        return $valuesData;
234
    }
235
236
    /**
237
     * Procesar nodos del tipo fault
238
     *
239
     * @param DOMElement $xmlFault
240
     *
241
     * @return array
242
     */
243
    private function parseFault(DOMElement $xmlFault)
244
    {
245
        $faultData = [];
246
247
        foreach ($xmlFault->childNodes as $fault) {
248
            /**
249
             * @var $fault DOMElement
250
             */
251
            if ($fault instanceof DOMElement && $fault->nodeName === 'value') {
252
                $values = $this->parseValues($fault);
253
254
                if (is_array($values)) {
255
                    return $values;
256
                }
257
            }
258
        }
259
260
        return $faultData;
261
    }
262
263
    /**
264
     * Obtener los datos de la respuesta
265
     */
266
    public function parseParams()
267
    {
268
        $this->parseNodes($this->root->getElementsByTagName('params'));
269
270
        return $this->data;
271
    }
272
273
    /**
274
     * Devolver el documento XML
275
     *
276
     * @return string
277
     */
278
    public function getXml()
279
    {
280
        return $this->xml;
281
    }
282
}