Completed
Push — feature/issue-31 ( 91722f )
by Mikaël
14s queued 10s
created

AbstractSoapClientBase::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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