Passed
Push — develop ( 479492...2f2e47 )
by Mikaël
03:12
created

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