Passed
Push — 2.x ( 46eeaf...76eded )
by Mikaël
49:59 queued 47:23
created

AbstractSoapClientBase::setLastError()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

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