Google::validateRequestResult()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 3
nc 2
nop 1
crap 3
1
<?php
0 ignored issues
show
Coding Style introduced by
File has mixed line endings; this may cause incorrect results
Loading history...
2
3
namespace Radowoj\Searcher\SearchProvider;
4
5
use stdClass;
6
7
use GuzzleHttp\Client as GuzzleClient;
8
use Psr\Http\Message\ResponseInterface as Psr7Response;
9
10
use Radowoj\Searcher\SearchResult\Collection;
11
use Radowoj\Searcher\SearchResult\ICollection;
12
use Radowoj\Searcher\SearchResult\Item;
13
use Radowoj\Searcher\SearchResult\IItem;
14
15
use Radowoj\Searcher\Exceptions\Exception;
16
use Radowoj\Searcher\Exceptions\QuotaExceededException;
17
use Radowoj\Searcher\Exceptions\RateLimitExceededException;
18
19
class Google extends SearchProvider implements ISearchProvider
20
{
21
    const URI = 'https://www.googleapis.com/customsearch/v1?';
22
23
    protected $apiKey = null;
24
25
    protected $cx = null;
26
27
    protected $guzzle = null;
28
29 9
    public function __construct(GuzzleClient $guzzle, string $apiKey, string $cx)
30
    {
31 9
        $this->apiKey = $apiKey;
32 9
        $this->cx = $cx;
33 9
        $this->guzzle = $guzzle;
34 9
    }
35
36
37 8
    protected function getSearchQueryString(string $query, int $limit, int $offset)
0 ignored issues
show
Unused Code introduced by
The parameter $limit is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
38
    {
39
        $params = [
40 8
            'key' => $this->apiKey,
41 8
            'q' => urlencode($query),
42 8
            'cx' => $this->cx,
43
        ];
44
45 8
        if ($offset) {
46 1
            $params['start'] = $offset;
47
        }
48
49 8
        $paramsMerged = [];
50
51 8
        foreach($params as $key => $value) {
52 8
            $paramsMerged[] = "{$key}={$value}";
53
        }
54
55 8
        return implode('&', $paramsMerged);
56
    }
57
58
59 8
    protected function searchRequest(string $query, int $limit, int $offset) : stdClass
60
    {
61 8
        $uri = self::URI . $this->getSearchQueryString($query, $limit, $offset);
62
63 8
        $result = $this->guzzle->request(
64 8
            'GET',
65
            $uri, [
66 8
                'http_errors' => false,
67
            ]
68
        );
69
70 8
        return $this->decodeResponse($result);
71
    }
72
73
74
    /**
75
     * Handle response based on HTTP status code (catches 400s - usually quota or rate limit,
76
     * so authorisation errors and other stuff will be thrown as generic Searcher exception)
77
     *
78
     * On status == 200 it simply returns json-decoded response.
79
     *
80
     * @param  Psr7Response $result result from Guzzle
81
     * @return array
82
     */
83 8
    protected function decodeResponse(Psr7Response $result) : stdClass
84
    {
85 8
        $decodedResult = json_decode($result->getBody());
86 8
        switch($result->getStatusCode()) {
87 8
            case 200:
88 6
                return $decodedResult;
89 2
            case 403:
0 ignored issues
show
Coding Style introduced by
The case body in a switch statement must start on the line following the statement.

According to the PSR-2, the body of a case statement must start on the line immediately following the case statement.

switch ($expr) {
case "A":
    doSomething(); //right
    break;
case "B":

    doSomethingElse(); //wrong
    break;

}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
Coding Style introduced by
Terminating statement must be on a line by itself

As per the PSR-2 coding standard, the break (or other terminating) statement must be on a line of its own.

switch ($expr) {
     case "A":
         doSomething();
         break; //wrong
     case "B":
         doSomething();
         break; //right
     case "C:":
         doSomething();
         return true; //right
 }

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
90 1
                throw new QuotaExceededException(
91 1
                    $decodedResult->error->message ?? $result->getReasonPhrase()
92
                );
0 ignored issues
show
Coding Style introduced by
DEFAULT statements must be defined using a colon

As per the PSR-2 coding standard, default statements should not be wrapped in curly braces.

switch ($expr) {
    default: { //wrong
        doSomething();
        break;
    }
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
93
            default:
94 1
                throw new Exception("Google API responded with HTTP status {$result->getStatusCode()} - {$result->getReasonPhrase()}");
95
        }
96
    }
97
98
99 5
    protected function enforceLimit(stdClass $result, int $limit) : stdClass
100
    {
101 5
        if (!isset($result->items)) {
102 1
            return $result;
103
        }
104 4
        $result->items = array_slice($result->items, 0, $limit);
105 4
        return $result;
106
    }
107
108
109 6
    protected function validateRequestResult(stdClass $result)
110
    {
111 6
        if (!isset($result->kind) || $result->kind !== "customsearch#search") {
112 1
            throw new Exception("Invalid Google API response: " . print_r($result, 1));
113
        }
114 5
    }
115
116
117 5
    protected function extractResults(stdClass $result) : array
118
    {
119 5
        return isset($result->items)
120 4
            ? $result->items
121 5
            : [];
122
    }
123
124
125 5
    protected function extractTotalMatches(stdClass $result) : int
126
    {
127 5
        return isset($result->searchInformation->totalResults)
128 4
            ? $result->searchInformation->totalResults
129 5
            : 0;
130
    }
131
132
133 1
    protected function populateItem(stdClass $item) : IItem
134
    {
135 1
        return new Item([
136 1
            'url' => $item->link,
137 1
            'title' => $item->title,
138 1
            'description' => $item->snippet,
139
        ]);
140
    }
141
142
}
143