Passed
Push — develop ( 047bfd...b0429f )
by Mikaël
03:07 queued 36s
created

AbstractSoapClientBase::getOutputHeaders()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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