Passed
Push — master ( df2e7d...4ffc8b )
by Gabriel Felipe
01:40 queued 10s
created

InterestOverTimeSearch::search()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 41

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 41
ccs 24
cts 24
cp 1
rs 9.264
c 0
b 0
f 0
cc 4
nc 4
nop 1
crap 4
1
<?php declare(strict_types=1);
2
3
namespace GSoares\GoogleTrends\Search;
4
5
use DateTimeImmutable;
6
use GSoares\GoogleTrends\Error\GoogleTrendsException;
7
use GSoares\GoogleTrends\Result\InterestOverTimeCollection;
8
use GSoares\GoogleTrends\Result\InterestOverTimeResult;
9
10
/**
11
 * @author Gabriel Felipe Soares <[email protected]>
12
 */
13
class InterestOverTimeSearch
14
{
15
    private const SEARCH_URL = 'https://trends.google.com/trends/api/widgetdata/multiline';
16
17
    /**
18
     * @var ExploreSearch
19
     */
20
    protected $exploreSearch;
21
22
    /**
23
     * @var SearchRequest
24
     */
25
    protected $searchRequest;
26
27 3
    public function __construct(ExploreSearch $exploreSearch = null, SearchRequest $searchRequest = null)
28
    {
29 3
        $this->searchRequest = $searchRequest ?: new SearchRequest();
30 3
        $this->exploreSearch = $exploreSearch ?: new ExploreSearch($this->searchRequest);
31 3
    }
32
33
    /**
34
     * @param SearchFilter $searchFilter
35
     *
36
     * @return InterestOverTimeCollection
37
     *
38
     * @throws GoogleTrendsException
39
     */
40 3
    public function search(SearchFilter $searchFilter): InterestOverTimeCollection
41
    {
42 3
        $token = $this->exploreSearch
43 3
            ->search($searchFilter)
44 3
            ->getInterestOverTimeResult()
45 3
            ->getToken();
46
47 3
        $searchUrl = $this->buildQuery($searchFilter->withToken($token));
48
49 3
        $responseDecoded = $this->searchRequest->search($searchUrl);
50
51 3
        if (!isset($responseDecoded['default']['timelineData'])) {
52 1
            throw new GoogleTrendsException(
53 1
                sprintf(
54 1
                    'Invalid google response body "%s"...',
55 1
                    substr(var_export($responseDecoded, true), 100)
56
                )
57
            );
58
        }
59
60 2
        $results = [];
61
62 2
        foreach ($responseDecoded['default']['timelineData'] ?? [] as $row) {
63 2
            if (!isset($row['time'], $row['value'])) {
64 1
                throw new GoogleTrendsException(
65 1
                    sprintf(
66 1
                        'Google timeline list does not contain all keys. Only has: %s',
67 1
                        implode(', ', array_keys($row))
68
                    )
69
                );
70
            }
71
72 1
            $results[] = new InterestOverTimeResult(
73 1
                (new DateTimeImmutable(date('Y-m-d H:i:s', (int)$row['time']))),
74 1
                $row['value'],
75 1
                (bool)($row['hasData'] ?? false)
76
            );
77
        }
78
79 1
        return new InterestOverTimeCollection($searchUrl, ...$results);
80
    }
81
82 3
    private function buildQuery(SearchFilter $searchFilter): string
83
    {
84
        $request = [
85 3
            'time' => $searchFilter->getTime(),
86 3
            'resolution' => 'DAY',
87 3
            'locale' => $searchFilter->getLanguage(),
88
            'comparisonItem' => [
89
                [
90
                    'geo' => [
91 3
                        'country' => $searchFilter->getLocation(),
92
                    ],
93
                    'complexKeywordsRestriction' => [
94
                        'keyword' => [
95
                            [
96 3
                                'type' => 'BROAD',
97 3
                                'value' => $searchFilter->getSearchTerm(),
98
                            ],
99
                        ],
100
                    ]
101
                ],
102
            ],
103
            'requestOptions' => [
104 3
                'property' => '',
105 3
                'backend' => 'IZG',
106 3
                'category' => $searchFilter->getCategory(),
107
            ]
108
        ];
109
110
        $query = [
111 3
            'hl' => $searchFilter->getLanguage(),
112 3
            'tz' => '-60',
113 3
            'req' => json_encode($request),
114 3
            'token' => $searchFilter->getToken()
115
        ];
116
117 3
        $queryString = str_replace(
118
            [
119 3
                '%3A',
120
                '%2C',
121
                '%2B'
122
            ],
123
            [
124 3
                ':',
125
                ',',
126
                '+',
127
            ],
128 3
            http_build_query($query)
129
        );
130
131 3
        return self::SEARCH_URL . '?' . $queryString;
132
    }
133
}
134