Completed
Push — master ( e7e845...1ac605 )
by Felix
01:51
created

AdWords::include()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
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 int|null */
26
    protected $language = null;
27
28
    /** @var int|null */
29
    protected $location = null;
30
31
    /** @var array|null */
32
    protected $include = null;
33
34
    /** @var array|null */
35
    protected $exclude = null;
36
37
    /**
38
     * AdWords constructor.
39
     *
40
     * @param AdWordsService $service
41
     */
42
    public function __construct(AdWordsService $service)
43
    {
44
        $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...
45
    }
46
47
    /**
48
     * @param array $keywords
49
     *
50
     * @return Collection
51
     */
52
    public function searchVolumes(array $keywords)
53
    {
54
        $keywords = $this->prepareKeywords($keywords);
55
        $requestType = RequestType::STATS;
56
57
        $searchVolumes = new Collection();
58
        $chunks = array_chunk($keywords, self::CHUNK_SIZE);
59
60
        foreach ($chunks as $index => $keywordChunk) {
61
            $results = $this->service->performQuery($keywordChunk, $requestType, $this->language, $this->location, $this->withTargetedMonthlySearches);
62
            if ($results->getEntries() !== null) {
63
                foreach ($results->getEntries() as $targetingIdea) {
64
                    $keyword = $this->extractKeyword($targetingIdea);
65
                    $searchVolumes->push($keyword);
66
                }
67
            }
68
        }
69
70
        $missingKeywords = array_diff($keywords, $searchVolumes->pluck('keyword')->toArray());
71
72
        foreach ($missingKeywords as $missingKeyword) {
73
            $missingKeywordInstance = new Keyword([
74
                'keyword'       => $missingKeyword,
75
                'search_volume' => null,
76
                'cpc'           => null,
77
                'competition'   => null,
78
            ]);
79
80
            if ($this->withTargetedMonthlySearches) {
81
                $missingKeywordInstance->targeted_monthly_searches = null;
82
            }
83
84
            $searchVolumes->push($missingKeywordInstance);
85
        }
86
87
        return $searchVolumes;
88
    }
89
90
    public function keywordIdeas($keyword)
91
    {
92
        $keyword = $this->prepareKeywords([$keyword]);
93
        $requestType = RequestType::IDEAS;
94
95
        $keywordIdeas = new Collection();
96
97
        $results = $this->service->performQuery($keyword, $requestType, $this->language, $this->location, $this->withTargetedMonthlySearches, $this->include, $this->exclude);
98
        if ($results->getEntries() !== null) {
99
            foreach ($results->getEntries() as $targetingIdea) {
100
                $keyword = $this->extractKeyword($targetingIdea);
101
                $keywordIdeas->push($keyword);
102
            }
103
        }
104
105
        return $keywordIdeas;
106
107
    }
108
    /**
109
     * Include Targeted Monthly Searches.
110
     *
111
     * @return $this
112
     */
113
    public function withTargetedMonthlySearches()
114
    {
115
        $this->withTargetedMonthlySearches = true;
116
117
        return $this;
118
    }
119
120
    /**
121
     * Add Language Search Parameter.
122
     *
123
     * @return $this
124
     */
125
    public function language($language = null)
126
    {
127
        $this->language = $language;
128
129
        return $this;
130
    }
131
132
    /**
133
     * Add Location Search Parameter.
134
     *
135
     * @return $this
136
     */
137
    public function location($location = null)
138
    {
139
        $this->location = $location;
140
141
        return $this;
142
    }
143
144
    public function include(array $words)
145
    {
146
        $this->include = $this->prepareKeywords($words);
147
148
        return $this;
149
    }
150
151
    public function exclude(array $words)
152
    {
153
        $this->exclude = $this->prepareKeywords($words);
154
155
        return $this;
156
    }
157
158
    /**
159
     * @return TargetingIdeaService
160
     */
161
    public function getTargetingIdeaService(): TargetingIdeaService
162
    {
163
        return $this->service->getTargetingIdeaService();
164
    }
165
166
    /**
167
     * Private Functions.
168
     */
169
    private function prepareKeywords(array $keywords)
170
    {
171
        $keywords = array_map('trim', $keywords);
172
        $keywords = array_map('mb_strtolower', $keywords);
173
        $keywords = array_filter($keywords);
174
        $keywords = array_unique($keywords);
175
        $keywords = array_values($keywords);
176
177
        return $keywords;
178
    }
179
180
    /**
181
     * @param $targetingIdea
182
     *
183
     * @return Keyword
184
     */
185
    private function extractKeyword($targetingIdea)
186
    {
187
        $data = MapEntries::toAssociativeArray($targetingIdea->getData());
188
        $keyword = $data[AttributeType::KEYWORD_TEXT]->getValue();
189
        $search_volume =
190
            ($data[AttributeType::SEARCH_VOLUME]->getValue() !== null)
191
                ? $data[AttributeType::SEARCH_VOLUME]->getValue() : 0;
192
193
        $average_cpc =
194
            ($data[AttributeType::AVERAGE_CPC]->getValue() !== null)
195
                ? $data[AttributeType::AVERAGE_CPC]->getValue()->getMicroAmount() : 0;
196
        $competition =
197
            ($data[AttributeType::COMPETITION]->getValue() !== null)
198
                ? $data[AttributeType::COMPETITION]->getValue() : 0;
199
200
        $result = new Keyword([
201
            'keyword'                   => $keyword,
202
            'search_volume'             => $search_volume,
203
            'cpc'                       => $average_cpc,
204
            'competition'               => $competition,
205
            'targeted_monthly_searches' => null,
206
        ]);
207
208
        if ($this->withTargetedMonthlySearches) {
209
            $targeted_monthly_searches =
210
                ($data[AttributeType::TARGETED_MONTHLY_SEARCHES]->getValue() !== null)
211
                    ? $data[AttributeType::TARGETED_MONTHLY_SEARCHES]->getValue() : 0;
212
            $targetedMonthlySearches = collect($targeted_monthly_searches)
213
                ->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...
214
                    return new MonthlySearchVolume([
215
                        'year'  => $item->getYear(),
216
                        'month' => $item->getMonth(),
217
                        'count' => $item->getCount(),
218
                    ]);
219
                });
220
221
            $result->targeted_monthly_searches = $targetedMonthlySearches;
222
        }
223
224
        return $result;
225
    }
226
}
227