Completed
Push — master ( 651e9a...253437 )
by Ivo
03:04
created

SoapClient::__call()   A

Complexity

Conditions 4
Paths 7

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 12
cts 12
cp 1
rs 9.0534
c 0
b 0
f 0
cc 4
eloc 13
nc 7
nop 2
crap 4
1
<?php
2
3
namespace Freshcells\SoapClientBundle\SoapClient;
4
5
use Freshcells\SoapClientBundle\Event\Events;
6
use Freshcells\SoapClientBundle\Event\FaultEvent;
7
use Freshcells\SoapClientBundle\Event\RequestEvent;
8
use Freshcells\SoapClientBundle\Event\ResponseEvent;
9
use Ramsey\Uuid\Uuid;
10
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
11
12
/**
13
 * Class SoapClient
14
 */
15
class SoapClient extends \SoapClient
16
{
17
    /**
18
     * @var array
19
     */
20
    protected $options;
21
    /**
22
     * @var EventDispatcherInterface
23
     */
24
    protected $dispatcher;
25
    /**
26
     * @var array
27
     */
28
    private $mockRequests = [];
29
    /**
30
     * @var array
31
     */
32
    private $mockResponses = [];
33
34
    /**
35
     * SoapClient constructor.
36
     * @param null $wsdl
37
     * @param array|null $options
38
     */
39 6
    public function __construct($wsdl = null, array $options = [])
40
    {
41
42 6
        if(isset($options['mock_requests'])){
43 6
            $this->setMockRequests($options['mock_requests']);
44 6
            unset($options['mock_requests']);
45
        }
46 6
        if(isset($options['mock_responses'])){
47 6
            $this->setMockResponses($options['mock_responses']);
48 6
            unset($options['mock_responses']);
49
        }
50
51
        $defaults = array(
52 6
            'compression'        => (SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP),
53 6
            'cache_wsdl'         => WSDL_CACHE_BOTH,
54 6
            'connection_timeout' => 60,
55
            'exceptions'         => true,
56 6
            'features'           => SOAP_SINGLE_ELEMENT_ARRAYS,
57 6
            'soap_version'       => SOAP_1_2,
58
            'trace'              => true,
59 6
            'user_agent'         => 'freshcells/soap-client-bundle',
60
        );
61
62 6
        $options = array_merge($defaults, $options);
63
64 6
        if (!is_null($wsdl)) {
65
            // if option 'location' not set explicit use WSDL URL as service location
66 6
            if (!isset($options['location'])) {
67 6
                $options['location'] = $this->resolveLocation($wsdl);
68
            }
69
        }
70
71 6
        $this->SoapClient($wsdl, $options);
72 6
        $this->options = $options;
73 6
    }
74
75 6
    public function __call($function_name, $arguments)
76
    {
77
        try {
78 6
            $response = parent::__call($function_name, $arguments);
79
            //works only with 'exceptions' => false, we always throw
80 3
            if (is_soap_fault($response)) {
81 3
                throw $response;
82
            }
83 3
        } catch (\Exception $e) {
84 3
            $request = $this->__getLastRequest();
85 3
            if ($request === null) { //only dispatch this when no request was fired
86 3
                $request = implode(' ', $arguments);
87 3
                $id = Uuid::uuid1();
88 3
                $this->faultCall($id->toString(), $function_name, $request, $e);
89
            }
90
91 3
            throw $e;
92
        }
93
94 3
        return $response;
95
    }
96
97
    /**
98
     * @param string $request
99
     * @param string $location
100
     * @param string $action
101
     * @param int $version
102
     * @param null $one_way
103
     * @return bool|string
104
     */
105 3
    public function __doRequest($request, $location, $action, $version, $one_way = null)
106
    {
107 3
        $id = Uuid::uuid1();
108
109 3
        foreach ($this->mockRequests as $key => $mockRequest) {
110 3
            if (strrpos($action, $key) !== false) {
111 3
                $request = file_get_contents($mockRequest);
112 3
                break;
113
            }
114
        }
115
116 3
        $this->preCall($id->toString(), $action, $request);
117
118 3
        foreach ($this->mockResponses as $key => $mockResponse) {
119 3
            if (strrpos($action, $key) !== false) {
120 3
                $response = file_get_contents($mockResponse);
121
122 3
                $this->postCall($id->toString(), $action, $response);
123
124 3
                return $response;
125
            }
126
        }
127
128
        /* workaround for working timeout */
129
        $socketTimeout = false;
130
        if (isset($this->options['connection_timeout'])
131
            && (int)$this->options['connection_timeout'] > (int)ini_get('default_socket_timeout')
132
        ) {
133
            $socketTimeout = ini_set('default_socket_timeout', $this->options['connection_timeout']);
134
        }
135
136
        $response = parent::__doRequest($request, $location, $action, $version, $one_way);
137
138
        $this->postCall($id->toString(), $action, $response);
139
140
        if ($socketTimeout !== false) {
141
            ini_set('default_socket_timeout', $socketTimeout);
142
        }
143
144
        return $response;
145
    }
146
147
    /**
148
     * Triggered before a request is executed
149
     *
150
     * @param string $id
151
     * @param string $resource
152
     * @param string $requestContent
153
     */
154 3
    protected function preCall(string $id, string $resource, string $requestContent = null)
155
    {
156 3
        if (null !== $this->dispatcher) {
157 3
            $this->dispatcher->dispatch(Events::REQUEST, new RequestEvent($id, $resource, $requestContent));
158
        }
159 3
    }
160
161
    /**
162
     * @param string $id
163
     * @param string $resource
164
     * @param string $response
165
     */
166 3
    protected function postCall(string $id, string $resource, string $response = null)
167
    {
168 3
        if (null !== $this->dispatcher) {
169 3
            $responseEvent = new ResponseEvent(
170 3
                $id,
171 3
                $resource,
172 3
                $this->__getLastRequest(),
173 3
                $this->__getLastRequestHeaders(),
174 3
                $response,
175 3
                $this->__getLastResponseHeaders()
176
            );
177 3
            $this->dispatcher->dispatch(Events::RESPONSE, $responseEvent);
178
        }
179 3
    }
180
181
    /**
182
     * @param string $id
183
     * @param string $resource
184
     * @param string $requestContent
185
     * @param \Exception $Exception
0 ignored issues
show
Documentation introduced by
There is no parameter named $Exception. Did you maybe mean $exception?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
186
     */
187 3
    protected function faultCall(string $id, string $resource, string $requestContent, \Exception $exception)
188
    {
189 3
        if (null !== $this->dispatcher) {
190 3
            $this->dispatcher->dispatch(
191 3
                Events::FAULT,
192 3
                new FaultEvent($id, $exception, new RequestEvent($id, $resource, $requestContent))
193
            );
194
        }
195 3
    }
196
197
    /**
198
     * @param string $wsdl
199
     * @return string
200
     */
201 6
    protected function resolveLocation($wsdl)
202
    {
203 6
        $wsdlUrl = parse_url($wsdl);
204
205 6
        return ((isset($wsdlUrl['scheme'])) ? $wsdlUrl['scheme'].'://' : '')
206 6
            .((isset($wsdlUrl['user'])) ? $wsdlUrl['user']
207 6
                .((isset($wsdlUrl['pass'])) ? ':'.$wsdlUrl['pass'] : '').'@' : '')
208 6
            .((isset($wsdlUrl['host'])) ? $wsdlUrl['host'] : '')
209 6
            .((isset($wsdlUrl['port'])) ? ':'.$wsdlUrl['port'] : '')
210 6
            .((isset($wsdlUrl['path'])) ? $wsdlUrl['path'] : '');
211
    }
212
213
    /**
214
     * @param array $mockRequests
215
     */
216 6
    private function setMockRequests(array $mockRequests)
217
    {
218 6
        $this->mockRequests = $mockRequests;
219 6
    }
220
221
    /**
222
     * @param array $mockResponses
223
     */
224 6
    private function setMockResponses(array $mockResponses)
225
    {
226 6
        $this->mockResponses = $mockResponses;
227 6
    }
228
229
    /**
230
     * @param EventDispatcherInterface $dispatcher
231
     */
232 6
    public function setDispatcher(EventDispatcherInterface $dispatcher)
233
    {
234 6
        $this->dispatcher = $dispatcher;
235 6
    }
236
}
237