Passed
Branch 4 (f3d551)
by Simon
03:46
created

GoogleAnalyticsReportService::getWhitelistPages()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 2
dl 0
loc 14
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Firesphere\GoogleAPI\Services;
4
5
use Google_Service_AnalyticsReporting;
6
use Google_Service_AnalyticsReporting_DateRange;
7
use Google_Service_AnalyticsReporting_Dimension;
8
use Google_Service_AnalyticsReporting_DimensionFilter;
9
use Google_Service_AnalyticsReporting_DimensionFilterClause;
10
use Google_Service_AnalyticsReporting_GetReportsRequest;
11
use Google_Service_AnalyticsReporting_GetReportsResponse;
12
use Google_Service_AnalyticsReporting_Metric;
13
use Google_Service_AnalyticsReporting_ReportRequest;
14
use Page;
0 ignored issues
show
Bug introduced by
The type Page was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use SilverStripe\CMS\Model\SiteTree;
16
use SilverStripe\Core\Config\Config;
17
use SilverStripe\ORM\DataList;
18
use SilverStripe\SiteConfig\SiteConfig;
19
20
/**
21
 * Class GoogleAnalyticsReportService
22
 *
23
 * Base service for getting the Analytics report per page from Google.
24
 */
25
class GoogleAnalyticsReportService
26
{
27
28
    /**
29
     * @var GoogleClientService
30
     */
31
    protected $client;
32
33
    /**
34
     * @var Google_Service_AnalyticsReporting_DateRange
35
     */
36
    protected $dateRange;
37
38
    /**
39
     * @var Google_Service_AnalyticsReporting
40
     */
41
    protected $analytics;
42
43
    /**
44
     * @var Google_Service_AnalyticsReporting_Metric
45
     */
46
    protected $metrics;
47
48
    /**
49
     * Should the filter being batched
50
     *
51
     * @var bool
52
     */
53
    public $batched = false;
54
55
    /**
56
     * GoogleReportService constructor.
57
     * @param GoogleClientService $client
58
     */
59
    public function __construct($client)
60
    {
61
        $config = SiteConfig::current_site_config();
62
        $this->client = $client;
63
        $this->setDateRange($config->DateRange);
64
        $this->setAnalytics(new Google_Service_AnalyticsReporting($client->getClient()));
65
        $this->setMetrics($config->Metric);
66
    }
67
68
    /**
69
     * @return Google_Service_AnalyticsReporting_GetReportsResponse
70
     */
71
    public function getReport()
72
    {
73
        $request = $this->getReportRequest();
74
75
        $body = new Google_Service_AnalyticsReporting_GetReportsRequest();
76
        $body->setReportRequests([$request]);
77
78
        return $this->analytics->reports->batchGet($body);
79
    }
80
81
    /**
82
     * @return Google_Service_AnalyticsReporting_ReportRequest
83
     */
84
    public function getReportRequest()
85
    {
86
        $config = SiteConfig::current_site_config();
87
88
        $request = new Google_Service_AnalyticsReporting_ReportRequest();
89
        $dimension = $this->getDimensions();
90
        $request->setDimensions($dimension);
91
        $request->setViewId($config->Viewid);
92
        $request->setDimensionFilterClauses($this->getDimensionFilterClauses());
93
        $request->setDateRanges($this->getDateRange());
94
        $request->setMetrics([$this->getMetrics()]);
95
96
        return $request;
97
    }
98
99
    /**
100
     * @return array|Google_Service_AnalyticsReporting_Dimension[]
101
     */
102
    public function getDimensions()
103
    {
104
        $dimension = new Google_Service_AnalyticsReporting_Dimension();
105
        $dimension->setName('ga:pagePath');
106
107
        return [$dimension];
108
    }
109
110
    /**
111
     * @return mixed
112
     */
113
    public function getClient()
114
    {
115
        return $this->client;
116
    }
117
118
    /**
119
     * @param mixed $client
120
     */
121
    public function setClient($client)
122
    {
123
        $this->client = $client;
124
    }
125
126
    /**
127
     * @return Google_Service_AnalyticsReporting_DateRange
128
     */
129
    public function getDateRange()
130
    {
131
        return $this->dateRange;
132
    }
133
134
    /**
135
     * @param int $dateRange
136
     */
137
    public function setDateRange($dateRange)
138
    {
139
        $analyticsRange = new Google_Service_AnalyticsReporting_DateRange();
140
        $analyticsRange->setStartDate($dateRange . 'daysAgo');
141
        $analyticsRange->setEndDate('today');
142
        $this->dateRange = $analyticsRange;
143
    }
144
145
    /**
146
     * @return Google_Service_AnalyticsReporting
147
     */
148
    public function getAnalytics()
149
    {
150
        return $this->analytics;
151
    }
152
153
    /**
154
     * @param Google_Service_AnalyticsReporting $analytics
155
     */
156
    public function setAnalytics($analytics)
157
    {
158
        $this->analytics = $analytics;
159
    }
160
161
    /**
162
     * @return mixed
163
     */
164
    public function getMetrics()
165
    {
166
        return $this->metrics;
167
    }
168
169
    /**
170
     * @param mixed $metrics
171
     */
172
    public function setMetrics($metrics)
173
    {
174
        $metric = new Google_Service_AnalyticsReporting_Metric();
175
        $metric->setExpression($metrics);
176
        $this->metrics = $metric;
177
    }
178
179
    /**
180
     * Set up the Dimension Filters
181
     *
182
     * @return array|Google_Service_AnalyticsReporting_DimensionFilter[]
183
     */
184
    public function getDimensionFilters()
185
    {
186
        $filters = [];
187
        $startWith = config::inst()->get(static::class, 'starts_with');
188
        $endWith = config::inst()->get(static::class, 'ends_with');
189
        if ($startWith) {
190
            return $this->createFilter('BEGINS_WITH', $startWith, $filters);
191
        }
192
        if ($endWith) {
193
            return $this->createFilter('ENDS_WITH', $endWith, $filters);
194
        }
195
196
        return $this->getPageDimensionFilters();
197
    }
198
199
    /**
200
     * @return array|Google_Service_AnalyticsReporting_DimensionFilter[]
201
     */
202
    public function getPageDimensionFilters()
203
    {
204
        $filters = [];
205
        // Operators are not constants, see here: https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/reports/batchGet#Operator
206
        $operator = 'ENDS_WITH';
207
        $pages = $this->getPages();
208
209
        foreach ($pages as $page) {
210
            // Home is recorded as just a slash in GA, we need an
211
            // exception for that
212
            if ($page === 'home') {
213
                $page = '/';
214
                $operator = 'EXACT';
215
            }
216
217
            $filters = $this->createFilter($operator, $page, $filters);
218
            // Reset the operator
219
            if ($operator === 'EXACT') {
220
                $operator = 'ENDS_WITH';
221
            }
222
        }
223
224
        return $filters;
225
    }
226
227
    /**
228
     * @return Google_Service_AnalyticsReporting_DimensionFilterClause
229
     */
230
    public function getDimensionFilterClauses()
231
    {
232
        $dimensionFilters = $this->getDimensionFilters();
233
        $dimensionClauses = new Google_Service_AnalyticsReporting_DimensionFilterClause();
234
        $dimensionClauses->setFilters($dimensionFilters);
235
        $dimensionClauses->setOperator('OR');
236
237
        return $dimensionClauses;
238
    }
239
240
    /**
241
     * Get the pages filtered by optional blacklisting and whitelisting
242
     * Return an array of the URLSegments, to limit memory abuse
243
     * @return array
244
     */
245
    public function getPages()
246
    {
247
        $blacklist = Config::inst()->get(static::class, 'blacklist');
248
        $whitelist = Config::inst()->get(static::class, 'whitelist');
249
        /** @var DataList|Page[] $pages */
250
        $pages = SiteTree::get();
251
        if ($blacklist) {
252
            $pages = $this->getBlacklist($blacklist, $pages);
253
        }
254
        if ($whitelist) {
255
            $pages = $this->getWhitelistPages($whitelist, $pages);
256
        }
257
258
        if ($pages->count() > 20) {
259
            $this->batched = true;
260
        }
261
262
        // Google limits to 20 reports per complex filter setup
263
        return $pages->limit(20)->column('URLSegment');
264
    }
265
266
    /**
267
     * @param array $blacklist
268
     * @param DataList $pages
269
     * @return DataList
270
     */
271
    protected function getBlacklist($blacklist, $pages)
272
    {
273
        $ids = [];
274
        foreach ($blacklist as $class) {
275
            $blacklistpages = $class::get();
276
            $ids = array_merge($ids, $blacklistpages->column('ID'));
277
        }
278
        $pages = $pages->exclude(['ID' => $ids]);
279
280
        return $pages;
281
    }
282
283
    /**
284
     * @param array $whitelist
285
     * @param DataList $pages
286
     * @return DataList
287
     */
288
    protected function getWhitelistPages($whitelist, $pages)
289
    {
290
        $ids = [];
291
        foreach ($whitelist as $class) {
292
            $nowDate = date('Y-m-d');
293
            $whitelistpages = $class::get()
294
                // This needs to be a where because of `IS NULL`
295
                ->where("(`SiteTree`.`LastAnalyticsUpdate` < $nowDate)
296
                        OR (`SiteTree`.`LastAnalyticsUpdate` IS NULL)");
297
            $ids = array_merge($ids, $whitelistpages->column('ID'));
298
        }
299
        $pages = $pages->filter(['ID' => $ids]);
300
301
        return $pages;
302
    }
303
304
    /**
305
     * @param $operator
306
     * @param $page
307
     * @param $filters
308
     * @return array|Google_Service_AnalyticsReporting_DimensionFilter[]
309
     */
310
    protected function createFilter($operator, $page, $filters)
311
    {
312
        $filter = new Google_Service_AnalyticsReporting_DimensionFilter();
313
        $filter->setOperator($operator);
314
        $filter->setCaseSensitive(false);
315
        $filter->setExpressions([$page]);
316
        $filter->setDimensionName('ga:pagePath');
317
        $filters[] = $filter;
318
319
        return $filters;
320
    }
321
}
322