Passed
Push — 1.x ( 91722f...1128db )
by Mikaël
04:44 queued 02:24
created

AbstractSoapClientBase::getFormatedXml()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace WsdlToPhp\PackageBase;
4
5
abstract class AbstractSoapClientBase implements SoapClientInterface
6
{
7
    /**
8
     * Soapclient called to communicate with the actual SOAP Service
9
     * @var \SoapClient
10
     */
11
    private static $soapClient;
12
    /**
13
     * Contains Soap call result
14
     * @var mixed
15
     */
16
    private $result;
17
    /**
18
     * Contains last errors
19
     * @var array
20
     */
21
    private $lastError;
22
    /**
23
     * Contains output headers
24
     * @var array
25
     */
26
    protected $outputHeaders = [];
27
    /**
28
     * Constructor
29
     * @uses AbstractSoapClientBase::setLastError()
30
     * @uses AbstractSoapClientBase::initSoapClient()
31
     * @param array $wsdlOptions
32
     * @param bool $resetSoapClient allows to disable the SoapClient redefinition
33
     */
34 155
    public function __construct(array $wsdlOptions = [], $resetSoapClient = true)
35
    {
36 155
        $this->setLastError([]);
37
        /**
38
         * Init soap Client
39
         * Set default values
40
         */
41 155
        if ($resetSoapClient) {
42 155
            $this->initSoapClient($wsdlOptions);
43 62
        }
44 155
    }
45
    /**
46
     * Static method getting current SoapClient
47
     * @return \SoapClient
48
     */
49 140
    public static function getSoapClient()
50
    {
51 140
        return self::$soapClient;
52
    }
53
    /**
54
     * Static method setting current SoapClient
55
     * @param \SoapClient $soapClient
56
     * @return \SoapClient
57
     */
58 130
    public static function setSoapClient(\SoapClient $soapClient)
59
    {
60 130
        return (self::$soapClient = $soapClient);
61
    }
62
    /**
63
     * Method initiating SoapClient
64
     * @uses ApiClassMap::classMap()
65
     * @uses AbstractSoapClientBase::getDefaultWsdlOptions()
66
     * @uses AbstractSoapClientBase::getSoapClientClassName()
67
     * @uses AbstractSoapClientBase::setSoapClient()
68
     * @uses AbstractSoapClientBase::OPTION_PREFIX
69
     * @param array $options WSDL options
70
     * @return void
71
     */
72 155
    public function initSoapClient(array $options)
73
    {
74 155
        self::$soapClient = null;
75 155
        $wsdlOptions = [];
76 155
        $defaultWsdlOptions = static::getDefaultWsdlOptions();
77 155
        foreach ($defaultWsdlOptions as $optionName => $optionValue) {
78 155
            if (array_key_exists($optionName, $options) && !is_null($options[$optionName])) {
79 140
                $wsdlOptions[str_replace(self::OPTION_PREFIX, '', $optionName)] = $options[$optionName];
80 155
            } elseif (!is_null($optionValue)) {
81 155
                $wsdlOptions[str_replace(self::OPTION_PREFIX, '', $optionName)] = $optionValue;
82 62
            }
83 62
        }
84 155
        if (self::canInstantiateSoapClientWithOptions($wsdlOptions)) {
85 130
            $wsdlUrl = null;
86 130
            if (array_key_exists(str_replace(self::OPTION_PREFIX, '', self::WSDL_URL), $wsdlOptions)) {
87 120
                $wsdlUrl = $wsdlOptions[str_replace(self::OPTION_PREFIX, '', self::WSDL_URL)];
88 120
                unset($wsdlOptions[str_replace(self::OPTION_PREFIX, '', self::WSDL_URL)]);
89 48
            }
90 130
            $soapClientClassName = $this->getSoapClientClassName();
91 130
            static::setSoapClient(new $soapClientClassName($wsdlUrl, $wsdlOptions));
92 52
        }
93 155
    }
94
    /**
95
     * Checks if the provided options are sufficient to instantiate a SoapClient:
96
     *  - WSDL-mode : only the WSDL is required
97
     *  - non-WSDL-mode : URI and LOCATION are required, WSDL url can be empty then
98
     * @uses AbstractSoapClientBase::OPTION_PREFIX
99
     * @param $wsdlOptions
100
     * @return bool
101
     */
102 155
    protected static function canInstantiateSoapClientWithOptions($wsdlOptions)
103
    {
104
        return (
105 155
            array_key_exists(str_replace(self::OPTION_PREFIX, '', self::WSDL_URL), $wsdlOptions) ||
106
            (
107 35
                array_key_exists(str_replace(self::OPTION_PREFIX, '', self::WSDL_URI), $wsdlOptions) &&
108 99
                array_key_exists(str_replace(self::OPTION_PREFIX, '', self::WSDL_LOCATION), $wsdlOptions)
109 6
            )
110 62
        );
111
    }
112
    /**
113
     * Returns the SoapClient class name to use to create the instance of the SoapClient.
114
     * The SoapClient class is determined based on the package name.
115
     * If a class is named as {Api}SoapClient, then this is the class that will be used.
116
     * Be sure that this class inherits from the native PHP SoapClient class and this class has been loaded or can be loaded.
117
     * The goal is to allow the override of the SoapClient without having to modify this generated class.
118
     * Then the overridding SoapClient class can override for example the SoapClient::__doRequest() method if it is needed.
119
     * @uses AbstractSoapClientBase::DEFAULT_SOAP_CLIENT_CLASS
120
     * @return string
121
     */
122 140
    public function getSoapClientClassName($soapClientClassName = null)
123
    {
124 140
        $className = self::DEFAULT_SOAP_CLIENT_CLASS;
125 140
        if (!empty($soapClientClassName) && is_subclass_of($soapClientClassName, '\SoapClient')) {
126 135
            $className = $soapClientClassName;
127 54
        }
128 140
        return $className;
129
    }
130
    /**
131
     * Method returning all default options values
132
     * @uses AbstractSoapClientBase::WSDL_AUTHENTICATION
133
     * @uses AbstractSoapClientBase::WSDL_CACHE_WSDL
134
     * @uses AbstractSoapClientBase::WSDL_CLASSMAP
135
     * @uses AbstractSoapClientBase::WSDL_COMPRESSION
136
     * @uses AbstractSoapClientBase::WSDL_CONNECTION_TIMEOUT
137
     * @uses AbstractSoapClientBase::WSDL_ENCODING
138
     * @uses AbstractSoapClientBase::WSDL_EXCEPTIONS
139
     * @uses AbstractSoapClientBase::WSDL_FEATURES
140
     * @uses AbstractSoapClientBase::WSDL_LOCAL_CERT
141
     * @uses AbstractSoapClientBase::WSDL_LOCATION
142
     * @uses AbstractSoapClientBase::WSDL_LOGIN
143
     * @uses AbstractSoapClientBase::WSDL_PASSPHRASE
144
     * @uses AbstractSoapClientBase::WSDL_PASSWORD
145
     * @uses AbstractSoapClientBase::WSDL_PROXY_HOST
146
     * @uses AbstractSoapClientBase::WSDL_PROXY_LOGIN
147
     * @uses AbstractSoapClientBase::WSDL_PROXY_PASSWORD
148
     * @uses AbstractSoapClientBase::WSDL_PROXY_PORT
149
     * @uses AbstractSoapClientBase::WSDL_SOAP_VERSION
150
     * @uses AbstractSoapClientBase::WSDL_SSL_METHOD
151
     * @uses AbstractSoapClientBase::WSDL_STREAM_CONTEXT
152
     * @uses AbstractSoapClientBase::WSDL_STYLE
153
     * @uses AbstractSoapClientBase::WSDL_TRACE
154
     * @uses AbstractSoapClientBase::WSDL_TYPEMAP
155
     * @uses AbstractSoapClientBase::WSDL_URL
156
     * @uses AbstractSoapClientBase::WSDL_URI
157
     * @uses AbstractSoapClientBase::WSDL_USE
158
     * @uses AbstractSoapClientBase::WSDL_USER_AGENT
159
     * @uses WSDL_CACHE_NONE
160
     * @uses SOAP_SINGLE_ELEMENT_ARRAYS
161
     * @uses SOAP_USE_XSI_ARRAY_TYPE
162
     * @return array
163
     */
164 155
    public static function getDefaultWsdlOptions()
165
    {
166
        return [
167 155
            self::WSDL_AUTHENTICATION => null,
168 155
            self::WSDL_CACHE_WSDL => WSDL_CACHE_NONE,
169 155
            self::WSDL_CLASSMAP => null,
170 155
            self::WSDL_COMPRESSION => null,
171 155
            self::WSDL_CONNECTION_TIMEOUT => null,
172 155
            self::WSDL_ENCODING => null,
173 155
            self::WSDL_EXCEPTIONS => true,
174 155
            self::WSDL_FEATURES => SOAP_SINGLE_ELEMENT_ARRAYS | SOAP_USE_XSI_ARRAY_TYPE,
175 155
            self::WSDL_LOCAL_CERT => null,
176 155
            self::WSDL_LOCATION => null,
177 155
            self::WSDL_LOGIN => null,
178 155
            self::WSDL_PASSPHRASE => null,
179 155
            self::WSDL_PASSWORD => null,
180 155
            self::WSDL_PROXY_HOST => null,
181 155
            self::WSDL_PROXY_LOGIN => null,
182 155
            self::WSDL_PROXY_PASSWORD => null,
183 155
            self::WSDL_PROXY_PORT => null,
184 155
            self::WSDL_SOAP_VERSION => null,
185 155
            self::WSDL_SSL_METHOD => null,
186 155
            self::WSDL_STREAM_CONTEXT => null,
187 155
            self::WSDL_STYLE => null,
188 155
            self::WSDL_TRACE => true,
189 155
            self::WSDL_TYPEMAP => null,
190 155
            self::WSDL_URL => null,
191 155
            self::WSDL_URI => null,
192 155
            self::WSDL_USE => null,
193 155
            self::WSDL_USER_AGENT => null,
194 62
        ];
195
    }
196
    /**
197
     * Allows to set the SoapClient location to call
198
     * @uses AbstractSoapClientBase::getSoapClient()
199
     * @uses SoapClient::__setLocation()
200
     * @param string $location
201
     * @return AbstractSoapClientBase
202
     */
203 5
    public function setLocation($location)
204
    {
205 5
        if (static::getSoapClient() instanceof \SoapClient) {
0 ignored issues
show
introduced by
static::getSoapClient() is always a sub-type of SoapClient.
Loading history...
206 5
            static::getSoapClient()->__setLocation($location);
207 2
        }
208 5
        return $this;
209
    }
210
    /**
211
     * Returns the last request content as a DOMDocument or as a formated XML String
212
     * @see SoapClient::__getLastRequest()
213
     * @uses AbstractSoapClientBase::getSoapClient()
214
     * @uses AbstractSoapClientBase::getFormatedXml()
215
     * @uses SoapClient::__getLastRequest()
216
     * @param bool $asDomDocument
217
     * @return \DOMDocument|string|null
218
     */
219 10
    public function getLastRequest($asDomDocument = false)
220
    {
221 10
        return $this->getLastXml('__getLastRequest', $asDomDocument);
222
    }
223
    /**
224
     * Returns the last response content as a DOMDocument or as a formated XML String
225
     * @see SoapClient::__getLastResponse()
226
     * @uses AbstractSoapClientBase::getSoapClient()
227
     * @uses AbstractSoapClientBase::getFormatedXml()
228
     * @uses SoapClient::__getLastResponse()
229
     * @param bool $asDomDocument
230
     * @return \DOMDocument|string|null
231
     */
232 10
    public function getLastResponse($asDomDocument = false)
233
    {
234 10
        return $this->getLastXml('__getLastResponse', $asDomDocument);
235
    }
236
    /**
237
     * @param string $method
238
     * @param bool $asDomDocument
239
     * @return \DOMDocument|string|null
240
     */
241 20
    protected function getLastXml($method, $asDomDocument = false)
242
    {
243 20
        $xml = null;
244 20
        if (static::getSoapClient() instanceof \SoapClient) {
0 ignored issues
show
introduced by
static::getSoapClient() is always a sub-type of SoapClient.
Loading history...
245 20
            $xml = static::getFormatedXml(static::getSoapClient()->$method(), $asDomDocument);
246 8
        }
247 20
        return $xml;
248
    }
249
    /**
250
     * Returns the last request headers used by the SoapClient object as the original value or an array
251
     * @see SoapClient::__getLastRequestHeaders()
252
     * @uses AbstractSoapClientBase::getSoapClient()
253
     * @uses AbstractSoapClientBase::convertStringHeadersToArray()
254
     * @uses SoapClient::__getLastRequestHeaders()
255
     * @param bool $asArray allows to get the headers in an associative array
256
     * @return null|string|array
257
     */
258 10
    public function getLastRequestHeaders($asArray = false)
259
    {
260 10
        return $this->getLastHeaders('__getLastRequestHeaders', $asArray);
261
    }
262
    /**
263
     * Returns the last response headers used by the SoapClient object as the original value or an array
264
     * @see SoapClient::__getLastResponseHeaders()
265
     * @uses AbstractSoapClientBase::getSoapClient()
266
     * @uses AbstractSoapClientBase::convertStringHeadersToArray()
267
     * @uses SoapClient::__getLastRequestHeaders()
268
     * @param bool $asArray allows to get the headers in an associative array
269
     * @return null|string|array
270
     */
271 10
    public function getLastResponseHeaders($asArray = false)
272
    {
273 10
        return $this->getLastHeaders('__getLastResponseHeaders', $asArray);
274
    }
275
    /**
276
     * @param string $method
277
     * @param bool $asArray allows to get the headers in an associative array
278
     * @return string[]|null
279
     */
280 20
    protected function getLastHeaders($method, $asArray)
281
    {
282 20
        $headers = static::getSoapClient() instanceof \SoapClient ? static::getSoapClient()->$method() : null;
0 ignored issues
show
introduced by
static::getSoapClient() is always a sub-type of SoapClient.
Loading history...
283 20
        if (is_string($headers) && $asArray) {
284 10
            return static::convertStringHeadersToArray($headers);
285
        }
286 10
        return $headers;
287
    }
288
    /**
289
     * Returns a XML string content as a DOMDocument or as a formated XML string
290
     * @uses \DOMDocument::loadXML()
291
     * @uses \DOMDocument::saveXML()
292
     * @param string $string
293
     * @param bool $asDomDocument
294
     * @return \DOMDocument|string|null
295
     */
296 20
    public static function getFormatedXml($string, $asDomDocument = false)
297
    {
298 20
        return Utils::getFormatedXml($string, $asDomDocument);
299
    }
300
    /**
301
     * Returns an associative array between the headers name and their respective values
302
     * @param string $headers
303
     * @return string[]
304
     */
305 10
    public static function convertStringHeadersToArray($headers)
306
    {
307 10
        $lines = explode("\r\n", $headers);
308 10
        $headers = [];
309 10
        foreach ($lines as $line) {
310 10
            if (strpos($line, ':')) {
311 10
                $headerParts = explode(':', $line);
312 10
                $headers[$headerParts[0]] = trim(implode(':', array_slice($headerParts, 1)));
313 4
            }
314 4
        }
315 10
        return $headers;
316
    }
317
    /**
318
     * Sets a SoapHeader to send
319
     * For more information, please read the online documentation on {@link http://www.php.net/manual/en/class.soapheader.php}
320
     * @uses AbstractSoapClientBase::getSoapClient()
321
     * @uses SoapClient::__setSoapheaders()
322
     * @param string $nameSpace SoapHeader namespace
323
     * @param string $name SoapHeader name
324
     * @param mixed $data SoapHeader data
325
     * @param bool $mustUnderstand
326
     * @param string $actor
327
     * @return AbstractSoapClientBase
328
     */
329 15
    public function setSoapHeader($nameSpace, $name, $data, $mustUnderstand = false, $actor = null)
330
    {
331 15
        if (static::getSoapClient()) {
332 15
            $defaultHeaders = (isset(static::getSoapClient()->__default_headers) && is_array(static::getSoapClient()->__default_headers)) ? static::getSoapClient()->__default_headers : [];
0 ignored issues
show
Bug introduced by
The property __default_headers does not seem to exist on SoapClient.
Loading history...
333 15
            foreach ($defaultHeaders as $index => $soapHeader) {
334 5
                if ($soapHeader->name === $name) {
335 5
                    unset($defaultHeaders[$index]);
336 5
                    break;
337
                }
338 6
            }
339 15
            static::getSoapClient()->__setSoapheaders(null);
340 15
            if (!empty($actor)) {
341 5
                array_push($defaultHeaders, new \SoapHeader($nameSpace, $name, $data, $mustUnderstand, $actor));
342 2
            } else {
343 10
                array_push($defaultHeaders, new \SoapHeader($nameSpace, $name, $data, $mustUnderstand));
344
            }
345 15
            static::getSoapClient()->__setSoapheaders($defaultHeaders);
346 6
        }
347 15
        return $this;
348
    }
349
    /**
350
     * Sets the SoapClient Stream context HTTP Header name according to its value
351
     * If a context already exists, it tries to modify it
352
     * It the context does not exist, it then creates it with the header name and its value
353
     * @uses AbstractSoapClientBase::getSoapClient()
354
     * @param string $headerName
355
     * @param mixed $headerValue
356
     * @return bool
357
     */
358 30
    public function setHttpHeader($headerName, $headerValue)
359
    {
360 30
        $state = false;
361 30
        if (static::getSoapClient() && !empty($headerName)) {
362 30
            $streamContext = $this->getStreamContext();
363 30
            if ($streamContext === null) {
364 6
                $options = [];
365 6
                $options['http'] = [];
366 6
                $options['http']['header'] = '';
367 6
            } else {
368 26
                $options = stream_context_get_options($streamContext);
369 26
                if (!array_key_exists('http', $options) || !is_array($options['http'])) {
370
                    $options['http'] = [];
371
                    $options['http']['header'] = '';
372 26
                } elseif (!array_key_exists('header', $options['http'])) {
373
                    $options['http']['header'] = '';
374
                }
375
            }
376 30
            if (count($options) && array_key_exists('http', $options) && is_array($options['http']) && array_key_exists('header', $options['http']) && is_string($options['http']['header'])) {
377 30
                $lines = explode("\r\n", $options['http']['header']);
378
                /**
379
                 * Ensure there is only one header entry for this header name
380
                 */
381 30
                $newLines = [];
382 30
                foreach ($lines as $line) {
383 30
                    if (!empty($line) && strpos($line, $headerName) === false) {
384 26
                        array_push($newLines, $line);
385 8
                    }
386 12
                }
387
                /**
388
                 * Add new header entry
389
                 */
390 30
                array_push($newLines, "$headerName: $headerValue");
391
                /**
392
                 * Set the context http header option
393
                 */
394 30
                $options['http']['header'] = implode("\r\n", $newLines);
395
                /**
396
                 * Create context if it does not exist
397
                 */
398 30
                if ($streamContext === null) {
399 6
                    $state = (static::getSoapClient()->_stream_context = stream_context_create($options)) ? true : false;
0 ignored issues
show
Bug introduced by
The property _stream_context does not seem to exist on SoapClient.
Loading history...
400 6
                } else {
401
                    /**
402
                     * Set the new context http header option
403
                     */
404 26
                    $state = stream_context_set_option(static::getSoapClient()->_stream_context, 'http', 'header', $options['http']['header']);
405
                }
406 12
            }
407 12
        }
408 30
        return $state;
409
    }
410
    /**
411
     * Returns current \SoapClient::_stream_context resource or null
412
     * @return resource|null
413
     */
414 35
    public function getStreamContext()
415
    {
416 35
        return (static::getSoapClient() && isset(static::getSoapClient()->_stream_context) && is_resource(static::getSoapClient()->_stream_context)) ? static::getSoapClient()->_stream_context : null;
0 ignored issues
show
Bug introduced by
The property _stream_context does not seem to exist on SoapClient.
Loading history...
417
    }
418
    /**
419
     * Returns current \SoapClient::_stream_context resource options or empty array
420
     * @return array
421
     */
422 5
    public function getStreamContextOptions()
423
    {
424 5
        $options = [];
425 5
        $context = $this->getStreamContext();
426 5
        if ($context !== null) {
427 5
            $options = stream_context_get_options($context);
428 5
            if (isset($options['http']['header']) && is_string($options['http']['header'])) {
429 5
                $options['http']['header'] = array_filter(array_map('trim', explode(PHP_EOL, $options['http']['header'])));
430 2
            }
431 2
        }
432 5
        return $options;
433
    }
434
    /**
435
     * Method returning last errors occured during the calls
436
     * @return array
437
     */
438 5
    public function getLastError()
439
    {
440 5
        return $this->lastError;
441
    }
442
    /**
443
     * Method setting last errors occured during the calls
444
     * @param array $lastError
445
     * @return AbstractSoapClientBase
446
     */
447 155
    private function setLastError($lastError)
448
    {
449 155
        $this->lastError = $lastError;
450 155
        return $this;
451
    }
452
    /**
453
     * Method saving the last error returned by the SoapClient
454
     * @param string $methodName the method called when the error occurred
455
     * @param \SoapFault $soapFault l'objet de l'erreur
456
     * @return AbstractSoapClientBase
457
     */
458 15
    public function saveLastError($methodName, \SoapFault $soapFault)
459
    {
460 15
        $this->lastError[$methodName] = $soapFault;
461 15
        return $this;
462
    }
463
    /**
464
     * Method getting the last error for a certain method
465
     * @param string $methodName method name to get error from
466
     * @return \SoapFault|null
467
     */
468 5
    public function getLastErrorForMethod($methodName)
469
    {
470 5
        return array_key_exists($methodName, $this->lastError) ? $this->lastError[$methodName] : null;
471
    }
472
    /**
473
     * Method returning current result from Soap call
474
     * @return mixed
475
     */
476 5
    public function getResult()
477
    {
478 5
        return $this->result;
479
    }
480
    /**
481
     * Method setting current result from Soap call
482
     * @param mixed $result
483
     * @return AbstractSoapClientBase
484
     */
485 15
    public function setResult($result)
486
    {
487 15
        $this->result = $result;
488 15
        return $this;
489
    }
490
    /**
491
     * @return array
492
     */
493 5
    public function getOutputHeaders()
494
    {
495 5
        return $this->outputHeaders;
496
    }
497
}
498