Passed
Push — master ( d92bbf...19add9 )
by Simon
01:27
created

getGetReportRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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