Completed
Push — feature/issue-19 ( e5f56f...829c8f )
by Mikaël
01:46
created

AbstractSoapClientBase::saveLastError()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 1
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
     * Constructor
24
     * @uses AbstractSoapClientBase::setLastError()
25
     * @uses AbstractSoapClientBase::initSoapClient()
26
     * @param array $wsdlOptions
27
     * @param bool $resetSoapClient allows to disable the SoapClient redefinition
28
     */
29 130
    public function __construct(array $wsdlOptions = [], $resetSoapClient = true)
30
    {
31 130
        $this->setLastError([]);
32
        /**
33
         * Init soap Client
34
         * Set default values
35
         */
36 130
        if ($resetSoapClient) {
37 130
            $this->initSoapClient($wsdlOptions);
38 78
        }
39 130
    }
40
    /**
41
     * Static method getting current SoapClient
42
     * @return \SoapClient
43
     */
44 120
    public static function getSoapClient()
45
    {
46 120
        return self::$soapClient;
47
    }
48
    /**
49
     * Static method setting current SoapClient
50
     * @param \SoapClient $soapClient
51
     * @return \SoapClient
52
     */
53 120
    public static function setSoapClient(\SoapClient $soapClient)
54
    {
55 120
        return (self::$soapClient = $soapClient);
56
    }
57
    /**
58
     * Method initiating SoapClient
59
     * @uses ApiClassMap::classMap()
60
     * @uses AbstractSoapClientBase::getDefaultWsdlOptions()
61
     * @uses AbstractSoapClientBase::getSoapClientClassName()
62
     * @uses AbstractSoapClientBase::setSoapClient()
63
     * @param array $options WSDL options
64
     * @return void
65
     */
66 130
    public function initSoapClient(array $options)
67
    {
68 130
        $wsdlOptions = [];
69 130
        $defaultWsdlOptions = static::getDefaultWsdlOptions();
70 130
        foreach ($defaultWsdlOptions as $optionName => $optionValue) {
71 130
            if (array_key_exists($optionName, $options) && !is_null($options[$optionName])) {
72 120
                $wsdlOptions[str_replace(self::OPTION_PREFIX, '', $optionName)] = $options[$optionName];
73 130
            } elseif (!is_null($optionValue)) {
74 130
                $wsdlOptions[str_replace(self::OPTION_PREFIX, '', $optionName)] = $optionValue;
75 78
            }
76 78
        }
77 130
        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 120
            $soapClientClassName = $this->getSoapClientClassName();
81 120
            static::setSoapClient(new $soapClientClassName($wsdlUrl, $wsdlOptions));
82 72
        }
83 130
    }
84
    /**
85
     * Returns the SoapClient class name to use to create the instance of the SoapClient.
86
     * The SoapClient class is determined based on the package name.
87
     * If a class is named as {Api}SoapClient, then this is the class that will be used.
88
     * Be sure that this class inherits from the native PHP SoapClient class and this class has been loaded or can be loaded.
89
     * The goal is to allow the override of the SoapClient without having to modify this generated class.
90
     * Then the overridding SoapClient class can override for example the SoapClient::__doRequest() method if it is needed.
91
     * @return string
92
     */
93 130
    public function getSoapClientClassName($soapClientClassName = null)
94
    {
95 130
        $className = self::DEFAULT_SOAP_CLIENT_CLASS;
96 130
        if (!empty($soapClientClassName) && is_subclass_of($soapClientClassName, '\SoapClient')) {
97 125
            $className = $soapClientClassName;
98 75
        }
99 130
        return $className;
100
    }
101
    /**
102
     * Method returning all default options values
103
     * @uses AbstractSoapClientBase::WSDL_CLASSMAP
104
     * @uses AbstractSoapClientBase::WSDL_CACHE_WSDL
105
     * @uses AbstractSoapClientBase::WSDL_COMPRESSION
106
     * @uses AbstractSoapClientBase::WSDL_CONNECTION_TIMEOUT
107
     * @uses AbstractSoapClientBase::WSDL_ENCODING
108
     * @uses AbstractSoapClientBase::WSDL_EXCEPTIONS
109
     * @uses AbstractSoapClientBase::WSDL_FEATURES
110
     * @uses AbstractSoapClientBase::WSDL_LOCATION
111
     * @uses AbstractSoapClientBase::WSDL_LOGIN
112
     * @uses AbstractSoapClientBase::WSDL_PASSWORD
113
     * @uses AbstractSoapClientBase::WSDL_SOAP_VERSION
114
     * @uses AbstractSoapClientBase::WSDL_STREAM_CONTEXT
115
     * @uses AbstractSoapClientBase::WSDL_TRACE
116
     * @uses AbstractSoapClientBase::WSDL_TYPEMAP
117
     * @uses AbstractSoapClientBase::WSDL_URL
118
     * @uses AbstractSoapClientBase::VALUE_WSDL_URL
119
     * @uses AbstractSoapClientBase::WSDL_USER_AGENT
120
     * @uses AbstractSoapClientBase::WSDL_PROXY_HOST
121
     * @uses AbstractSoapClientBase::WSDL_PROXY_PORT
122
     * @uses AbstractSoapClientBase::WSDL_PROXY_LOGIN
123
     * @uses AbstractSoapClientBase::WSDL_PROXY_PASSWORD
124
     * @uses AbstractSoapClientBase::WSDL_LOCAL_CERT
125
     * @uses AbstractSoapClientBase::WSDL_PASSPHRASE
126
     * @uses AbstractSoapClientBase::WSDL_AUTHENTICATION
127
     * @uses AbstractSoapClientBase::WSDL_SSL_METHOD
128
     * @uses SOAP_SINGLE_ELEMENT_ARRAYS
129
     * @uses SOAP_USE_XSI_ARRAY_TYPE
130
     * @return array
131
     */
132 130
    public static function getDefaultWsdlOptions()
133
    {
134
        return [
135 130
            self::WSDL_CLASSMAP => null,
136 130
            self::WSDL_CACHE_WSDL => WSDL_CACHE_NONE,
137 130
            self::WSDL_COMPRESSION => null,
138 130
            self::WSDL_CONNECTION_TIMEOUT => null,
139 130
            self::WSDL_ENCODING => null,
140 130
            self::WSDL_EXCEPTIONS => true,
141 130
            self::WSDL_FEATURES => SOAP_SINGLE_ELEMENT_ARRAYS | SOAP_USE_XSI_ARRAY_TYPE,
142 130
            self::WSDL_LOCATION => null,
143 130
            self::WSDL_LOGIN => null,
144 130
            self::WSDL_PASSWORD => null,
145 130
            self::WSDL_SOAP_VERSION => null,
146 130
            self::WSDL_STREAM_CONTEXT => null,
147 130
            self::WSDL_TRACE => true,
148 130
            self::WSDL_TYPEMAP => null,
149 130
            self::WSDL_URL => null,
150 130
            self::WSDL_USER_AGENT => null,
151 130
            self::WSDL_PROXY_HOST => null,
152 130
            self::WSDL_PROXY_PORT => null,
153 130
            self::WSDL_PROXY_LOGIN => null,
154 130
            self::WSDL_PROXY_PASSWORD => null,
155 130
            self::WSDL_LOCAL_CERT => null,
156 130
            self::WSDL_PASSPHRASE => null,
157 130
            self::WSDL_AUTHENTICATION => null,
158 130
            self::WSDL_SSL_METHOD => null,
159 78
        ];
160
    }
161
    /**
162
     * Allows to set the SoapClient location to call
163
     * @uses AbstractSoapClientBase::getSoapClient()
164
     * @uses SoapClient::__setLocation()
165
     * @param string $location
166
     * @return AbstractSoapClientBase
167
     */
168 5
    public function setLocation($location)
169
    {
170 5
        if (static::getSoapClient() instanceof \SoapClient) {
171 5
            static::getSoapClient()->__setLocation($location);
172 3
        }
173 5
        return $this;
174
    }
175
    /**
176
     * Returns the last request content as a DOMDocument or as a formated XML String
177
     * @see SoapClient::__getLastRequest()
178
     * @uses AbstractSoapClientBase::getSoapClient()
179
     * @uses AbstractSoapClientBase::getFormatedXml()
180
     * @uses SoapClient::__getLastRequest()
181
     * @param bool $asDomDocument
182
     * @return \DOMDocument|string|null
183
     */
184 10
    public function getLastRequest($asDomDocument = false)
185
    {
186 10
        return $this->getLastXml('__getLastRequest', $asDomDocument);
187
    }
188
    /**
189
     * Returns the last response content as a DOMDocument or as a formated XML String
190
     * @see SoapClient::__getLastResponse()
191
     * @uses AbstractSoapClientBase::getSoapClient()
192
     * @uses AbstractSoapClientBase::getFormatedXml()
193
     * @uses SoapClient::__getLastResponse()
194
     * @param bool $asDomDocument
195
     * @return \DOMDocument|string|null
196
     */
197 10
    public function getLastResponse($asDomDocument = false)
198
    {
199 10
        return $this->getLastXml('__getLastResponse', $asDomDocument);
200
    }
201
    /**
202
     * @param string $method
203
     * @param bool $asDomDocument
204
     * @return \DOMDocument|string|null
205
     */
206 20
    protected function getLastXml($method, $asDomDocument = false)
207
    {
208 20
        $xml = null;
209 20
        if (static::getSoapClient() instanceof \SoapClient) {
210 20
            $xml = static::getFormatedXml(static::getSoapClient()->$method(), $asDomDocument);
211 12
        }
212 20
        return $xml;
213
    }
214
    /**
215
     * Returns the last request headers used by the SoapClient object as the original value or an array
216
     * @see SoapClient::__getLastRequestHeaders()
217
     * @uses AbstractSoapClientBase::getSoapClient()
218
     * @uses AbstractSoapClientBase::convertStringHeadersToArray()
219
     * @uses SoapClient::__getLastRequestHeaders()
220
     * @param bool $asArray allows to get the headers in an associative array
221
     * @return null|string|array
222
     */
223 10
    public function getLastRequestHeaders($asArray = false)
224
    {
225 10
        return $this->getLastHeaders('__getLastRequestHeaders', $asArray);
226
    }
227
    /**
228
     * Returns the last response headers used by the SoapClient object as the original value or an array
229
     * @see SoapClient::__getLastResponseHeaders()
230
     * @uses AbstractSoapClientBase::getSoapClient()
231
     * @uses AbstractSoapClientBase::convertStringHeadersToArray()
232
     * @uses SoapClient::__getLastRequestHeaders()
233
     * @param bool $asArray allows to get the headers in an associative array
234
     * @return null|string|array
235
     */
236 10
    public function getLastResponseHeaders($asArray = false)
237
    {
238 10
        return $this->getLastHeaders('__getLastResponseHeaders', $asArray);
239
    }
240
    /**
241
     * @param string $method
242
     * @param bool $asArray allows to get the headers in an associative array
243
     * @return string[]|null
244
     */
245 20
    protected function getLastHeaders($method, $asArray)
246
    {
247 20
        $headers = static::getSoapClient() instanceof \SoapClient ? static::getSoapClient()->$method() : null;
248 20
        if (is_string($headers) && $asArray) {
249 10
            return static::convertStringHeadersToArray($headers);
250
        }
251 10
        return $headers;
252
    }
253
    /**
254
     * Returns a XML string content as a DOMDocument or as a formated XML string
255
     * @uses \DOMDocument::loadXML()
256
     * @uses \DOMDocument::saveXML()
257
     * @param string $string
258
     * @param bool $asDomDocument
259
     * @return \DOMDocument|string|null
260
     */
261 20
    public static function getFormatedXml($string, $asDomDocument = false)
262
    {
263 20
        return Utils::getFormatedXml($string, $asDomDocument);
264
    }
265
    /**
266
     * Returns an associative array between the headers name and their respective values
267
     * @param string $headers
268
     * @return string[]
269
     */
270 10
    public static function convertStringHeadersToArray($headers)
271
    {
272 10
        $lines = explode("\r\n", $headers);
273 10
        $headers = [];
274 10
        foreach ($lines as $line) {
275 10
            if (strpos($line, ':')) {
276 10
                $headerParts = explode(':', $line);
277 10
                $headers[$headerParts[0]] = trim(implode(':', array_slice($headerParts, 1)));
278 6
            }
279 6
        }
280 10
        return $headers;
281
    }
282
    /**
283
     * Sets a SoapHeader to send
284
     * For more information, please read the online documentation on {@link http://www.php.net/manual/en/class.soapheader.php}
285
     * @uses AbstractSoapClientBase::getSoapClient()
286
     * @uses SoapClient::__setSoapheaders()
287
     * @param string $nameSpace SoapHeader namespace
288
     * @param string $name SoapHeader name
289
     * @param mixed $data SoapHeader data
290
     * @param bool $mustUnderstand
291
     * @param string $actor
292
     * @return AbstractSoapClientBase
293
     */
294 15
    public function setSoapHeader($nameSpace, $name, $data, $mustUnderstand = false, $actor = null)
295
    {
296 15
        if (static::getSoapClient()) {
297 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 in SoapClient.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
298 15
            foreach ($defaultHeaders as $index => $soapHeader) {
299 5
                if ($soapHeader->name === $name) {
300 5
                    unset($defaultHeaders[$index]);
301 5
                    break;
302
                }
303 9
            }
304 15
            static::getSoapClient()->__setSoapheaders(null);
305 15
            if (!empty($actor)) {
306 5
                array_push($defaultHeaders, new \SoapHeader($nameSpace, $name, $data, $mustUnderstand, $actor));
307 3
            } else {
308 10
                array_push($defaultHeaders, new \SoapHeader($nameSpace, $name, $data, $mustUnderstand));
309
            }
310 15
            static::getSoapClient()->__setSoapheaders($defaultHeaders);
311 9
        }
312 15
        return $this;
313
    }
314
    /**
315
     * Sets the SoapClient Stream context HTTP Header name according to its value
316
     * If a context already exists, it tries to modify it
317
     * It the context does not exist, it then creates it with the header name and its value
318
     * @uses AbstractSoapClientBase::getSoapClient()
319
     * @param string $headerName
320
     * @param mixed $headerValue
321
     * @return bool
322
     */
323 30
    public function setHttpHeader($headerName, $headerValue)
324
    {
325 30
        $state = false;
326 30
        if (static::getSoapClient() && !empty($headerName)) {
327 30
            $streamContext = $this->getStreamContext();
328 30
            if ($streamContext === null) {
329 9
                $options = [];
330 9
                $options['http'] = [];
331 9
                $options['http']['header'] = '';
332 9
            } else {
333 24
                $options = stream_context_get_options($streamContext);
334 24
                if (!array_key_exists('http', $options) || !is_array($options['http'])) {
335
                    $options['http'] = [];
336
                    $options['http']['header'] = '';
337 24
                } elseif (!array_key_exists('header', $options['http'])) {
338
                    $options['http']['header'] = '';
339
                }
340
            }
341 30
            if (count($options) && array_key_exists('http', $options) && is_array($options['http']) && array_key_exists('header', $options['http']) && is_string($options['http']['header'])) {
342 30
                $lines = explode("\r\n", $options['http']['header']);
343
                /**
344
                 * Ensure there is only one header entry for this header name
345
                 */
346 30
                $newLines = [];
347 30
                foreach ($lines as $line) {
348 30
                    if (!empty($line) && strpos($line, $headerName) === false) {
349 24
                        array_push($newLines, $line);
350 12
                    }
351 18
                }
352
                /**
353
                 * Add new header entry
354
                 */
355 30
                array_push($newLines, "$headerName: $headerValue");
356
                /**
357
                 * Set the context http header option
358
                 */
359 30
                $options['http']['header'] = implode("\r\n", $newLines);
360
                /**
361
                 * Create context if it does not exist
362
                 */
363 30
                if ($streamContext === null) {
364 9
                    $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 in SoapClient.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
365 9
                } else {
366
                    /**
367
                     * Set the new context http header option
368
                     */
369 24
                    $state = stream_context_set_option(static::getSoapClient()->_stream_context, 'http', 'header', $options['http']['header']);
370
                }
371 18
            }
372 18
        }
373 30
        return $state;
374
    }
375
    /**
376
     * Returns current \SoapClient::_stream_context resource or null
377
     * @return resource|null
378
     */
379 35
    public function getStreamContext()
380
    {
381 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 in SoapClient.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
382
    }
383
    /**
384
     * Returns current \SoapClient::_stream_context resource options or empty array
385
     * @return array
386
     */
387 5
    public function getStreamContextOptions()
388
    {
389 5
        $options = [];
390 5
        $context = $this->getStreamContext();
391 5
        if ($context !== null) {
392 5
            $options = stream_context_get_options($context);
393 3
        }
394 5
        return $options;
395
    }
396
    /**
397
     * Method returning last errors occured during the calls
398
     * @return array
399
     */
400 5
    public function getLastError()
401
    {
402 5
        return $this->lastError;
403
    }
404
    /**
405
     * Method setting last errors occured during the calls
406
     * @param array $lastError
407
     * @return AbstractSoapClientBase
408
     */
409 130
    private function setLastError($lastError)
410
    {
411 130
        $this->lastError = $lastError;
412 130
        return $this;
413
    }
414
    /**
415
     * Method saving the last error returned by the SoapClient
416
     * @param string $methodName the method called when the error occurred
417
     * @param \SoapFault $soapFault l'objet de l'erreur
418
     * @return AbstractSoapClientBase
419
     */
420 15
    public function saveLastError($methodName, \SoapFault $soapFault)
421
    {
422 15
        $this->lastError[$methodName] = $soapFault;
423 15
        return $this;
424
    }
425
    /**
426
     * Method getting the last error for a certain method
427
     * @param string $methodName method name to get error from
428
     * @return \SoapFault|null
429
     */
430 5
    public function getLastErrorForMethod($methodName)
431
    {
432 5
        return array_key_exists($methodName, $this->lastError) ? $this->lastError[$methodName] : null;
433
    }
434
    /**
435
     * Method returning current result from Soap call
436
     * @return mixed
437
     */
438 5
    public function getResult()
439
    {
440 5
        return $this->result;
441
    }
442
    /**
443
     * Method setting current result from Soap call
444
     * @param mixed $result
445
     * @return AbstractSoapClientBase
446
     */
447 15
    public function setResult($result)
448
    {
449 15
        $this->result = $result;
450 15
        return $this;
451
    }
452
}
453