Passed
Push — master ( e44a5e...8f8314 )
by Gabriel Felipe
02:37 queued 11s
created

AbstractRelatedSearch::isRisingMetric()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php declare(strict_types=1);
2
3
namespace GSoares\GoogleTrends\Search;
4
5
use GSoares\GoogleTrends\Error\GoogleTrendsException;
6
use GSoares\GoogleTrends\Result\RelatedResult;
7
use GSoares\GoogleTrends\Result\ExploreResultCollection;
8
use GSoares\GoogleTrends\Result\RelatedResultCollection;
9
10
/**
11
 * @author Gabriel Felipe Soares <[email protected]>
12
 */
13
abstract class AbstractRelatedSearch
14
{
15
    protected const TRENDS_URL = 'https://trends.google.com';
16
    protected const RELATED_SEARCH_URL = 'https://trends.google.com/trends/api/widgetdata/relatedsearches';
17
18
    /**
19
     * @var ExploreSearch
20
     */
21
    protected $exploreSearch;
22
23
    /**
24
     * @var SearchRequest
25
     */
26
    protected $searchRequest;
27
28 9
    public function __construct(ExploreSearch $exploreSearch = null, SearchRequest $searchRequest = null)
29
    {
30 9
        $this->searchRequest = $searchRequest ?: new SearchRequest();
31 9
        $this->exploreSearch = $exploreSearch ?: new ExploreSearch($this->searchRequest);
32 9
    }
33
34
    /**
35
     * @param SearchFilter $searchFilter
36
     *
37
     * @return RelatedResultCollection
38
     *
39
     * @throws GoogleTrendsException
40
     */
41 9
    public function search(SearchFilter $searchFilter): RelatedResultCollection
42
    {
43 9
        if (!$searchFilter->isConsideringRisingMetrics() && !$searchFilter->isConsideringTopMetrics()) {
44 1
            return new RelatedResultCollection('', ...[]);
45
        }
46
47 8
        $searchFilter->withToken($this->getToken($this->exploreSearch->search($searchFilter)));
48
49 8
        $searchUrl = $this->buildQuery($searchFilter);
50
51 8
        $responseDecoded = $this->searchRequest->search($searchUrl);
52
53 8
        if (!isset($responseDecoded['default']['rankedList'])) {
54 2
            throw new GoogleTrendsException(
55 2
                sprintf(
56 2
                    'Invalid google response body "%s"...',
57 2
                    substr(var_export($responseDecoded, true), 100)
58
                )
59
            );
60
        }
61
62 6
        $results = [];
63
64 6
        foreach ($responseDecoded['default']['rankedList'] as $row) {
65 6
            foreach ($row['rankedKeyword'] ?? [] as $rank) {
66 6
                if (!$searchFilter->isConsideringRisingMetrics() && $this->isRisingMetric($rank)) {
67 1
                    continue;
68
                }
69
70 6
                if (!$searchFilter->isConsideringTopMetrics() && !$this->isRisingMetric($rank)) {
71 1
                    continue;
72
                }
73
74 6
                $results[] = $this->createResult($rank);
75
            }
76
        }
77
78 4
        return new RelatedResultCollection($searchUrl, ...$results);
79
    }
80
81
    /**
82
     * @param array $data
83
     *
84
     * @return RelatedResult
85
     *
86
     * @throws GoogleTrendsException
87
     */
88
    abstract protected function createResult(array $data): RelatedResult;
89
90
    /**
91
     * @param ExploreResultCollection $resultCollection
92
     *
93
     * @return string
94
     *
95
     * @throws GoogleTrendsException
96
     */
97
    abstract protected function getToken(ExploreResultCollection $resultCollection): string;
98
99
    abstract protected function getKeywordType(): string;
100
101 4
    protected function isRisingMetric(array $row): bool
102
    {
103 4
        return strpos(($row['formattedValue'] ?? ''), '+') === 0;
104
    }
105
106 8
    private function buildQuery(SearchFilter $searchFilter): string
107
    {
108
        $request = [
109 8
            'restriction' => [
110
                'geo' => [
111 8
                    'country' => $searchFilter->getLocation(),
112
                ],
113 8
                'time' => $searchFilter->getTime(),
114 8
                'originalTimeRangeForExploreUrl' => $searchFilter->getTime(),
115
                'complexKeywordsRestriction' => [
116
                    'keyword' => [
117
                        [
118 8
                            'type' => 'BROAD',
119 8
                            'value' => $searchFilter->getSearchTerm(),
120
                        ],
121
                    ],
122
                ],
123
            ],
124 8
            'keywordType' => $this->getKeywordType(),
125
            'metric' => [
126
                'TOP',
127
                'RISING',
128
            ],
129
            'trendinessSettings' => [
130 8
                'compareTime' => $searchFilter->getCompareTime(),
131
            ],
132
            'requestOptions' => [
133 8
                'property' => $searchFilter->getSearchType(),
134 8
                'backend' => 'IZG',
135 8
                'category' => $searchFilter->getCategory(),
136
            ],
137 8
            'language' => 'en',
138
        ];
139
140
        $query = [
141 8
            'hl' => $searchFilter->getLanguage(),
142 8
            'tz' => '-60',
143 8
            'req' => json_encode($request),
144 8
            'token' => $searchFilter->getToken()
145
        ];
146
147 8
        $queryString = str_replace(
148
            [
149 8
                '%3A',
150
                '%2C',
151
                '%2B'
152
            ],
153
            [
154 8
                ':',
155
                ',',
156
                '+',
157
            ],
158 8
            http_build_query($query)
159
        );
160
161 8
        return self::RELATED_SEARCH_URL . '?' . $queryString;
162
    }
163
}
164