Completed
Push — master ( 0a96b0...e7c95d )
by Alexandre
03:13
created

CurlRule::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
/*
3
 * This file is part of project-quality-inspector.
4
 *
5
 * (c) Alexandre GESLIN <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace ProjectQualityInspector\Rule;
12
13
use ProjectQualityInspector\Application\ProcessHelper;
14
use ProjectQualityInspector\Exception\ExpectationFailedException;
15
use GuzzleHttp\Psr7\Request;
16
use GuzzleHttp\Psr7\Response;
17
18
/**
19
 * Class CurlRule
20
 *
21
 * @package ProjectQualityInspector\Rule
22
 */
23
class CurlRule extends AbstractRule
24
{
25
    private $client;
26
27
    public function __construct(array $config, $baseDir)
28
    {
29
        parent::__construct($config, $baseDir);
30
31
        $this->client = new \GuzzleHttp\Client();
32
    }
33
34
    /**
35
     * @inheritdoc
36
     */
37
    public function evaluate()
38
    {
39
        $expectationsFailedExceptions = [];
0 ignored issues
show
Unused Code introduced by
$expectationsFailedExceptions is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
40
41
        foreach ($this->config['queries'] as $query) {
42
            try {
43
                $this->expectsResponseMatches($query);
44
            } catch (ExpectationFailedException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
45
                
46
            }
47
        }
48
    }
49
50
    /**
51
     * @param  array $query
52
     */
53
    public function expectsResponseMatches($query)
54
    {
55
        $request = $query['request'];
56
        $expectedResponse = $query['expectedResponse'];
57
        $request['url'] = ($request['url']) ? $request['url'] : $this->config['base-url'];
58
        $request['method'] = ($request['method']) ? $request['method'] : 'GET';
59
60
        $response = $this->client->send(new Request($request['method'], $request['url']));
61
62
        try {
63
            $this->expectsHeadersMatches($expectedResponse, $response);
0 ignored issues
show
Compatibility introduced by
$response of type object<Psr\Http\Message\ResponseInterface> is not a sub-type of object<GuzzleHttp\Psr7\Response>. It seems like you assume a concrete implementation of the interface Psr\Http\Message\ResponseInterface to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
64
            $this->addAssertion($request['url']);
65
        } catch (ExpectationFailedException $e) {
66
            $expectationsFailedExceptions[] = $e;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$expectationsFailedExceptions was never initialized. Although not strictly required by PHP, it is generally a good practice to add $expectationsFailedExceptions = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
67
            $this->addAssertion($request['url'], [['message' => $e->getMessage() . $e->getReason(), 'type' => 'expectsHeadersMatches']]);
68
        }
69
70
        if (count($expectationsFailedExceptions)) {
71
            $this->throwRuleViolationException($expectationsFailedExceptions);
0 ignored issues
show
Bug introduced by
The variable $expectationsFailedExceptions does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
72
        }
73
    }
74
75
    /**
76
     * @param  array $expectedResponse
77
     * @param  array $response
78
     *
79
     * @throws ExpectationFailedException
80
     */
81
    private function expectsHeadersMatches($expectedResponse, Response $response)
82
    {
83
        $this->expectsStatusCodeMatches($expectedResponse, $response);
84
85
        foreach ($expectedResponse['headers'] as $expectedHeader => $expectedHeaderValue) {
86
            if (!isset($response->getheaders()[$expectedHeader])) {
87
                $message = sprintf('there is no expected header "%s" in response of url', $expectedHeader);
88
                throw new ExpectationFailedException($mergedBranches, $message);
89
            }
90
91
            if ($response->getheaders()[$expectedHeader][0] != $expectedHeaderValue) {
92
                $message = sprintf('the expected "%s" header\'s value should be "%s". Current value is %s', $expectedHeader, $expectedHeaderValue, $response->getheaders()[$expectedHeader][0]);
93
                throw new ExpectationFailedException($mergedBranches, $message);
94
            }
95
        }
96
    }
97
98
    /**
99
     * @param  array $expectedResponse
100
     * @param  array $response
101
     *
102
     * @throws ExpectationFailedException
103
     */
104
    private function expectsStatusCodeMatches($expectedResponse, Response $response)
105
    {
106
        if (isset($expectedResponse['statusCode']) && $expectedResponse['statusCode'] != $response->getStatusCode()) {
107
            $message = sprintf('the expected status code should be "%s". Current value is "%s"', $expectedResponse['statusCode'], $response->getStatusCode());
108
            throw new ExpectationFailedException($mergedBranches, $message);
109
        }
110
    }
111
}