Completed
Pull Request — master (#22)
by Dave
03:31
created

RawGuzzleContext::executeCommand()   B

Complexity

Conditions 4
Paths 2

Size

Total Lines 35
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 4.686

Importance

Changes 0
Metric Value
dl 0
loc 35
ccs 13
cts 20
cp 0.65
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 21
nc 2
nop 2
crap 4.686
1
<?php
2
/**
3
 * Behat Guzzle Extension
4
 *
5
 * PHP version 5
6
 *
7
 * @package Behat\GuzzleExtension
8
 * @author  Dave Nash <[email protected]>
9
 * @license http://opensource.org/licenses/MIT The MIT License
10
 * @version GIT: $Id$
11
 * @link    https://github.com/teaandcode/behat-guzzle-extension GuzzleExtension
12
 */
13
14
namespace Behat\GuzzleExtension\Context;
15
16
use Guzzle\Common\Exception\RuntimeException;
17
use Guzzle\Http\Exception\BadResponseException;
18
use Guzzle\Http\Exception\ClientErrorResponseException;
19
use Guzzle\Http\Message\Response;
20
use Guzzle\Service\Client;
21
22
/**
23
 * Raw Guzzle context for Behat BDD tool
24
 * Provides raw Guzzle integration (without step definitions) and web assertions
25
 *
26
 * @package Behat\GuzzleExtension\Context
27
 * @author  Dave Nash <[email protected]>
28
 * @license http://opensource.org/licenses/MIT The MIT License
29
 * @version Release: @package_version@
30
 * @link    https://github.com/teaandcode/behat-guzzle-extension GuzzleExtension
31
 */
32
class RawGuzzleContext implements GuzzleAwareContext
33
{
34
    /**
35
     * @var string
36
     */
37
    const GUZZLE_EXTENSION_NAME = 'Behat Guzzle Extension';
38
39
    /**
40
     * @var string
41
     */
42
    const GUZZLE_EXTENSION_VERSION = '0.4.1';
43
44
    /**
45
     * @var Client
46
     *
47
     * @access private
48
     */
49
    private $client;
50
51
    /**
52
     * @var array
53
     *
54
     * @access private
55
     */
56
    private $parameters;
57
58
    /**
59
     * @var Response
60
     *
61
     * @access private
62
     */
63
    private $response;
64
65
    /**
66
     * @var mixed
67
     *
68
     * @access private
69
     */
70
    private $result;
71
72
    /**
73
     * Execute command
74
     *
75
     * @param string $command Command to execute
76
     * @param array  $data    Data to send
77
     *
78
     * @access protected
79
     * @return void
80
     */
81 13
    public function executeCommand($command, array $data = array())
82
    {
83 13
        $this->getGuzzleClient()->setUserAgent(
84 13
            self::GUZZLE_EXTENSION_NAME . '/' . self::GUZZLE_EXTENSION_VERSION
85 13
        );
86
87 13
        $command = $this->getGuzzleClient()->getCommand($command, $data);
88
89
        try {
90 13
            $result = $this->getGuzzleClient()->execute($command);
91 13
        } catch (BadResponseException $e) {
92 1
            $this->response = $e->getResponse();
93
94
            try {
95 1
                $this->result = $this->response->json();
96
97 1
                return;
98
            } catch (RuntimeException $e) {
99
                continue;
100
            }
101
102
            try {
0 ignored issues
show
Unused Code introduced by
try { $this->result ...n $e) { continue; } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
103
                $this->result = $this->response->xml();
104
105
                return;
106
            } catch (RuntimeException $e) {
107
                continue;
108
            }
109
110
            return;
0 ignored issues
show
Unused Code introduced by
return; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
111
        }
112
113 12
        $this->response = $command->getResponse();
114 12
        $this->result = $result;
115 12
    }
116
117
    /**
118
     * Returns Client instance
119
     *
120
     * @access public
121
     * @return Client
122
     */
123 16
    public function getGuzzleClient()
124
    {
125 16
        if ($this->client === null) {
126 1
            throw new \RuntimeException(
127
                'Guzzle client instance has not been set on Guzzle context ' .
128 1
                'class.' . chr(10) . 'Have you enabled the Guzzle Extension?'
129 1
            );
130
        }
131
132 15
        return $this->client;
133
    }
134
135
    /**
136
     * Sets Client instance
137
     *
138
     * @param Client $client Guzzle client
139
     *
140
     * @access public
141
     * @return void
142
     */
143 15
    public function setGuzzleClient(Client $client)
144
    {
145 15
        $this->client = $client;
146 15
    }
147
148
    /**
149
     * Add Guzzle header
150
     *
151
     * @param string $field Field name
152
     * @param string $value Header value
153
     *
154
     * @access public
155
     * @return void
156
     */
157 2
    public function addGuzzleHeader($field, $value)
158
    {
159 2
        $this->updateHeader($field, $value);
160 2
    }
161
162
    /**
163
     * Remove Guzzle header
164
     *
165
     * @param string $field Field name
166
     *
167
     * @access public
168
     * @return void
169
     */
170 1
    public function removeGuzzleHeader($field)
171
    {
172 1
        $this->updateHeader($field);
173 1
    }
174
175
    /**
176
     * Returns specific Guzzle parameter
177
     *
178
     * @param string $name
179
     *
180
     * @access public
181
     * @return mixed
182
     */
183 1
    public function getGuzzleParameter($name)
184
    {
185 1
        if (isset($this->parameters[$name])) {
186 1
            return $this->parameters[$name];
187
        }
188 1
    }
189
190
    /**
191
     * Applies the given parameter to the Guzzle configuration. Consider that
192
     * all parameters get reset for each feature context
193
     *
194
     * @param string $name  The key of the parameter
195
     * @param string $value The value of the parameter
196
     *
197
     * @access public
198
     * @return void
199
     */
200 1
    public function setGuzzleParameter($name, $value)
201
    {
202 1
        $this->parameters[$name] = $value;
203 1
    }
204
205
    /**
206
     * Returns the parameters provided for Guzzle
207
     *
208
     * @access public
209
     * @return array
210
     */
211 1
    public function getGuzzleParameters()
212
    {
213 1
        return $this->parameters;
214
    }
215
216
    /**
217
     * Sets parameters provided for Guzzle
218
     *
219
     * @param array $parameters
220
     *
221
     * @access public
222
     * @return void
223
     */
224 1
    public function setGuzzleParameters(array $parameters)
225
    {
226 1
        $this->parameters = $parameters;
227 1
    }
228
229
    /**
230
     * Returns Response instance
231
     *
232
     * @access public
233
     * @return Response
234
     */
235 5
    public function getGuzzleResponse()
236
    {
237 5
        return $this->response;
238
    }
239
240
    /**
241
     * Returns result
242
     *
243
     * @access public
244
     * @return mixed
245
     */
246 8
    public function getGuzzleResult()
247
    {
248 8
        return $this->result;
249
    }
250
251
    /**
252
     * Compare array values
253
     *
254
     * @param array $input   Array with values to compare
255
     * @param array $control Array with correct values
256
     *
257
     * @access protected
258
     * @return void
259
     */
260 7
    protected function compareArrays(array $input, array $control)
261
    {
262 7
        foreach ($control as $field => $expected) {
263 7
            if (!array_key_exists($field, $input)) {
264 2
                throw new ClientErrorResponseException(
265 2
                    sprintf(
266
                        'Expected value %s is missing from array ' .
267 2
                        'of actual values at position %s',
268 2
                        is_array($expected) ?
269 2
                        json_encode($expected) :
270 2
                        $expected,
271
                        $field
272 2
                    )
273 2
                );
274
            }
275 7
            $this->compareValues($input[$field], $expected);
276 6
        }
277 5
    }
278
279
    /**
280
     * Compare array values
281
     *
282
     * @param mixed $input   Input value
283
     * @param mixed $control Correct control value
284
     *
285
     * @throws Exception When two field values do not match
286
     *
287
     * @access protected
288
     * @return void
289
     */
290 8
    protected function compareValues($input, $control)
291
    {
292 8
        if (is_array($input) && is_array($control)) {
293 7
            $this->compareArrays($input, $control);
294 5
        } else {
295 8
            if ($input != $control) {
296 1
                throw new ClientErrorResponseException(
297 1
                    'Actual value ' . $input . ' does not match expected ' .
298 1
                    'value ' . $control
299 1
                );
300
            }
301
        }
302 7
    }
303
304
    /**
305
     * Get request options
306
     *
307
     * @access private
308
     * @return array
309
     */
310 2
    private function getRequestOptions()
311
    {
312 2
        $options = $this->getGuzzleClient()
313 2
            ->getConfig()
314 2
            ->get(Client::REQUEST_OPTIONS);
315
316 2
        if (!is_array($options)) {
317 2
            $options = array();
318 2
        }
319
320 2
        return $options;
321
    }
322
323
    /**
324
     * Set request options
325
     *
326
     * @param array $options Request options
327
     *
328
     * @access private
329
     * @return void
330
     */
331 2
    private function setRequestOptions(array $options)
332
    {
333 2
        $config = $this->getGuzzleClient()->getConfig();
334 2
        $config->set(Client::REQUEST_OPTIONS, $options);
335
336 2
        $this->getGuzzleClient()->setConfig($config);
337 2
    }
338
339
    /**
340
     * Update header
341
     *
342
     * Adds, updates or removes header (if no value is provided)
343
     *
344
     * @param string $field Field name
345
     * @param string $value Header value
0 ignored issues
show
Documentation introduced by
Should the type for parameter $value not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
346
     *
347
     * @access private
348
     * @return void
349
     */
350 2
    private function updateHeader($field, $value = null)
351
    {
352 2
        $options = $this->getRequestOptions();
353
354 2
        if (!isset($options['headers'])) {
355 2
            $options['headers'] = array();
356 2
        }
357
358 2
        $options['headers'][$field] = $value;
359
360 2
        $this->setRequestOptions($options);
361 2
    }
362
}
363