Completed
Push — master ( f997f4...30dd7b )
by Felix
07:04
created

AdWords::searchVolumes()   D

Complexity

Conditions 10
Paths 16

Size

Total Lines 37
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 37
rs 4.8196
c 0
b 0
f 0
cc 10
eloc 22
nc 16
nop 1

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace SchulzeFelix\AdWords;
4
5
use Google\AdsApi\AdWords\v201705\o\AttributeType;
6
use Google\AdsApi\AdWords\v201705\o\RequestType;
7
use Google\AdsApi\AdWords\v201705\o\TargetingIdeaService;
8
use Google\AdsApi\Common\Util\MapEntries;
9
use Illuminate\Support\Collection;
10
use SchulzeFelix\AdWords\Responses\Keyword;
11
use SchulzeFelix\AdWords\Responses\MonthlySearchVolume;
12
13
class AdWords
14
{
15
    const CHUNK_SIZE = 700;
16
17
    /**
18
     * @var TargetingIdeaService
19
     */
20
    private $service;
21
22
    /** @var bool */
23
    protected $withTargetedMonthlySearches = false;
24
25
    /** @var bool */
26
    protected $convertNullToZero = false;
27
28
    /** @var int|null */
29
    protected $language = null;
30
31
    /** @var int|null */
32
    protected $location = null;
33
34
    /** @var array|null */
35
    protected $include = null;
36
37
    /** @var array|null */
38
    protected $exclude = null;
39
40
    /**
41
     * AdWords constructor.
42
     *
43
     * @param AdWordsService $service
44
     */
45
    public function __construct(AdWordsService $service)
46
    {
47
        $this->service = $service;
0 ignored issues
show
Documentation Bug introduced by
It seems like $service of type object<SchulzeFelix\AdWords\AdWordsService> is incompatible with the declared type object<Google\AdsApi\AdW...o\TargetingIdeaService> of property $service.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
48
    }
49
50
    /**
51
     * @param array $keywords
52
     *
53
     * @return Collection
54
     */
55
    public function searchVolumes(array $keywords)
56
    {
57
        $keywords = $this->prepareKeywords($keywords);
58
        $requestType = RequestType::STATS;
59
60
        $searchVolumes = new Collection();
61
        $chunks = array_chunk($keywords, self::CHUNK_SIZE);
62
63
        foreach ($chunks as $index => $keywordChunk) {
64
            $results = $this->service->performQuery($keywordChunk, $requestType, $this->language, $this->location, $this->withTargetedMonthlySearches);
65
            if ($results->getEntries() !== null) {
66
                foreach ($results->getEntries() as $targetingIdea) {
67
                    $keyword = $this->extractKeyword($targetingIdea);
68
                    $searchVolumes->push($keyword);
69
                }
70
            }
71
        }
72
73
        $missingKeywords = array_diff($keywords, $searchVolumes->pluck('keyword')->toArray());
74
75
        foreach ($missingKeywords as $missingKeyword) {
76
            $missingKeywordInstance = new Keyword([
77
                'keyword'       => $missingKeyword,
78
                'search_volume' => $this->convertNullToZero ? 0 : null,
79
                'cpc'           => $this->convertNullToZero ? 0 : null,
80
                'competition'   => $this->convertNullToZero ? 0 : null,
81
            ]);
82
83
            if ($this->withTargetedMonthlySearches) {
84
                $missingKeywordInstance->targeted_monthly_searches = $this->convertNullToZero ? collect() : null;
85
            }
86
87
            $searchVolumes->push($missingKeywordInstance);
88
        }
89
90
        return $searchVolumes;
91
    }
92
93
    public function keywordIdeas($keyword)
94
    {
95
        $keyword = $this->prepareKeywords([$keyword]);
96
        $requestType = RequestType::IDEAS;
97
98
        $keywordIdeas = new Collection();
99
100
        $results = $this->service->performQuery($keyword, $requestType, $this->language, $this->location, $this->withTargetedMonthlySearches, $this->include, $this->exclude);
101
        if ($results->getEntries() !== null) {
102
            foreach ($results->getEntries() as $targetingIdea) {
103
                $keyword = $this->extractKeyword($targetingIdea);
104
                $keywordIdeas->push($keyword);
105
            }
106
        }
107
108
        return $keywordIdeas;
109
    }
110
111
    /**
112
     * Include Targeted Monthly Searches.
113
     *
114
     * @return $this
115
     */
116
    public function withTargetedMonthlySearches()
117
    {
118
        $this->withTargetedMonthlySearches = true;
119
120
        return $this;
121
    }
122
123
    /**
124
     * Convert Null Values To Zero.
125
     *
126
     * @return $this
127
     */
128
    public function convertNullToZero()
129
    {
130
        $this->convertNullToZero = true;
131
132
        return $this;
133
    }
134
135
    /**
136
     * Add Language Search Parameter.
137
     *
138
     * @return $this
139
     */
140
    public function language($language = null)
141
    {
142
        $this->language = $language;
143
144
        return $this;
145
    }
146
147
    /**
148
     * Add Location Search Parameter.
149
     *
150
     * @return $this
151
     */
152
    public function location($location = null)
153
    {
154
        $this->location = $location;
155
156
        return $this;
157
    }
158
159
    public function include(array $words)
160
    {
161
        $this->include = $this->prepareKeywords($words);
162
163
        return $this;
164
    }
165
166
    public function exclude(array $words)
167
    {
168
        $this->exclude = $this->prepareKeywords($words);
169
170
        return $this;
171
    }
172
173
    /**
174
     * @return TargetingIdeaService
175
     */
176
    public function getTargetingIdeaService(): TargetingIdeaService
177
    {
178
        return $this->service->getTargetingIdeaService();
179
    }
180
181
    /**
182
     * Private Functions.
183
     */
184
    private function prepareKeywords(array $keywords)
185
    {
186
        $keywords = array_map('trim', $keywords);
187
        $keywords = array_map('mb_strtolower', $keywords);
188
        $keywords = array_filter($keywords);
189
        $keywords = array_unique($keywords);
190
        $keywords = array_values($keywords);
191
192
        return $keywords;
193
    }
194
195
    /**
196
     * @param $targetingIdea
197
     *
198
     * @return Keyword
199
     */
200
    private function extractKeyword($targetingIdea)
201
    {
202
        $data = MapEntries::toAssociativeArray($targetingIdea->getData());
203
        $keyword = $data[AttributeType::KEYWORD_TEXT]->getValue();
204
        $search_volume =
205
            ($data[AttributeType::SEARCH_VOLUME]->getValue() !== null)
206
                ? $data[AttributeType::SEARCH_VOLUME]->getValue() : 0;
207
208
        $average_cpc =
209
            ($data[AttributeType::AVERAGE_CPC]->getValue() !== null)
210
                ? $data[AttributeType::AVERAGE_CPC]->getValue()->getMicroAmount() : 0;
211
        $competition =
212
            ($data[AttributeType::COMPETITION]->getValue() !== null)
213
                ? $data[AttributeType::COMPETITION]->getValue() : 0;
214
215
        $result = new Keyword([
216
            'keyword'                   => $keyword,
217
            'search_volume'             => $search_volume,
218
            'cpc'                       => $average_cpc,
219
            'competition'               => $competition,
220
            'targeted_monthly_searches' => null,
221
        ]);
222
223
        if ($this->withTargetedMonthlySearches) {
224
            $targeted_monthly_searches =
225
                ($data[AttributeType::TARGETED_MONTHLY_SEARCHES]->getValue() !== null)
226
                    ? $data[AttributeType::TARGETED_MONTHLY_SEARCHES]->getValue() : 0;
227
            $targetedMonthlySearches = collect($targeted_monthly_searches)
228
                ->transform(function ($item, $key) {
0 ignored issues
show
Unused Code introduced by
The parameter $key 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...
229
                    return new MonthlySearchVolume([
230
                        'year'  => $item->getYear(),
231
                        'month' => $item->getMonth(),
232
                        'count' => $item->getCount(),
233
                    ]);
234
                });
235
236
            $result->targeted_monthly_searches = $targetedMonthlySearches;
237
        }
238
239
        return $result;
240
    }
241
}
242