SearchRequest   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 5
dl 0
loc 114
ccs 48
cts 48
cp 1
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
A setMaxTries() 0 6 1
A search() 0 37 4
A doSearch() 0 22 4
A getRefreshedCookieHeader() 0 7 1
1
<?php declare(strict_types=1);
2
3
namespace GSoares\GoogleTrends\Search;
4
5
use GSoares\GoogleTrends\Error\GoogleTrendsException;
6
use GuzzleHttp\Client;
7
use GuzzleHttp\ClientInterface;
8
use GuzzleHttp\Exception\ClientException;
9
use GuzzleHttp\Exception\GuzzleException;
10
use GuzzleHttp\RequestOptions;
11
use Psr\Http\Message\ResponseInterface;
12
use Throwable;
13
14
/**
15
 * @author Gabriel Felipe Soares <[email protected]>
16
 */
17
class SearchRequest
18
{
19
    /**
20
     * @var ClientInterface
21
     */
22
    private $guzzleClient;
23
24
    /**
25
     * @var int
26
     */
27
    private $maxTries;
28
29
    /**
30
     * @var int
31
     */
32
    private $totalTries;
33
34 5
    public function __construct(ClientInterface $guzzleClient = null)
35
    {
36 5
        $this->guzzleClient = $guzzleClient ?: new Client();
37 5
        $this->maxTries = 5;
38 5
        $this->totalTries = 0;
39 5
    }
40
41 1
    public function setMaxTries(int $maxTries): self
42
    {
43 1
        $this->maxTries = $maxTries;
44
45 1
        return $this;
46
    }
47
48
    /**
49
     * @param  string $searchUrl
50
     * @return array
51
     *
52
     * @throws GoogleTrendsException
53
     */
54 5
    public function search(string $searchUrl): array
55
    {
56
        try {
57 5
            $response = $this->doSearch($searchUrl);
58 3
        } catch (ClientException $exception) {
59 2
            throw new GoogleTrendsException(
60 2
                sprintf(
61 2
                    'Request error with status code "%s" for url "%s"',
62 2
                    $exception->getResponse()->getStatusCode(),
63 2
                    $searchUrl
64
                ),
65 2
                $exception
66
            );
67 1
        } catch (Throwable $exception) {
68 1
            throw new GoogleTrendsException(
69 1
                $exception->getMessage(),
70 1
                $exception
71
            );
72 2
        } finally {
73 5
            $this->totalTries = 0;
74
        }
75
76 2
        $responseBody = substr((string)$response->getBody(), 5);
77 2
        $responseDecoded = json_decode($responseBody, true);
78
79 2
        if (json_last_error()) {
80 1
            throw new GoogleTrendsException(
81 1
                sprintf(
82 1
                    'JSON parse error "%s" for JSON "%s"',
83 1
                    json_last_error_msg(),
84 1
                    $responseBody
85
                )
86
            );
87
        }
88
89 1
        return $responseDecoded;
90
    }
91
92
    /**
93
     * @param string $searchUrl
94
     * @param array  $options
95
     *
96
     * @return ResponseInterface
97
     *
98
     * @throws GuzzleException
99
     */
100 5
    private function doSearch(string $searchUrl, array $options = []): ResponseInterface
101
    {
102
        try {
103 5
            $this->totalTries++;
104
105 5
            return $this->guzzleClient
106 5
                ->request('GET', $searchUrl, $options);
107 3
        } catch (ClientException $exception) {
108 2
            if ($exception->getResponse()->getStatusCode() === 429 && $this->totalTries < $this->maxTries) {
109 1
                return $this->doSearch(
110 1
                    $searchUrl,
111
                    [
112 1
                        RequestOptions::HEADERS => [
113 1
                            'cookie' => $this->getRefreshedCookieHeader($exception)
114
                        ]
115
                    ]
116
                );
117
            }
118
119 2
            throw $exception;
120
        }
121
    }
122
123 1
    private function getRefreshedCookieHeader(ClientException $exception): string
124
    {
125 1
        return (string)explode(
126 1
            ';',
127 1
            $exception->getResponse()->getHeaders()['Set-Cookie'][0] ?? []
128 1
        )[0];
129
    }
130
}
131