Passed
Push — master ( c81a5e...499d21 )
by Simon
01:29
created

GoogleAnalyticsReportService   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 272
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 272
rs 10
c 0
b 0
f 0
wmc 27

17 Methods

Rating   Name   Duplication   Size   Complexity  
A getReport() 0 14 1
A __construct() 0 7 1
A createFilter() 0 10 1
A getMetrics() 0 3 1
A setMetrics() 0 5 1
A getDimensionFilters() 0 13 3
A getWhitelistPages() 0 14 2
A setDateRange() 0 6 1
A setClient() 0 3 1
A getDimensionFilterClauses() 0 8 1
B getPageDimensionFilters() 0 23 4
A getAnalytics() 0 3 1
A setAnalytics() 0 3 1
A getClient() 0 3 1
A getDateRange() 0 3 1
A getBlacklist() 0 10 2
A getPages() 0 19 4
1
<?php
2
3
/**
4
 * Class GoogleAnalyticsReportService
5
 *
6
 * Base service for getting the Analytics report per page from Google.
7
 */
8
class GoogleAnalyticsReportService
1 ignored issue
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
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 mixed
53
     */
54
    public function getReport()
55
    {
56
        $config = SiteConfig::current_site_config();
57
58
        $request = new Google_Service_AnalyticsReporting_ReportRequest();
59
        $request->setDimensions(['name' => 'ga:pagePath']);
60
        $request->setViewId($config->Viewid);
61
        $request->setDimensionFilterClauses($this->getDimensionFilterClauses());
62
        $request->setDateRanges($this->getDateRange());
63
64
        $body = new Google_Service_AnalyticsReporting_GetReportsRequest();
65
        $body->setReportRequests([$request]);
66
67
        return $this->analytics->reports->batchGet($body);
68
    }
69
70
    /**
71
     * @return mixed
72
     */
73
    public function getClient()
74
    {
75
        return $this->client;
76
    }
77
78
    /**
79
     * @param mixed $client
80
     */
81
    public function setClient($client)
82
    {
83
        $this->client = $client;
84
    }
85
86
    /**
87
     * @return Google_Service_AnalyticsReporting_DateRange
88
     */
89
    public function getDateRange()
90
    {
91
        return $this->dateRange;
92
    }
93
94
    /**
95
     * @param int $dateRange
96
     */
97
    public function setDateRange($dateRange)
98
    {
99
        $analyticsRange = new Google_Service_AnalyticsReporting_DateRange();
100
        $analyticsRange->setStartDate($dateRange . 'daysAgo');
101
        $analyticsRange->setEndDate('today');
102
        $this->dateRange = $analyticsRange;
103
    }
104
105
    /**
106
     * @return Google_Service_AnalyticsReporting
107
     */
108
    public function getAnalytics()
109
    {
110
        return $this->analytics;
111
    }
112
113
    /**
114
     * @param Google_Service_AnalyticsReporting $analytics
115
     */
116
    public function setAnalytics($analytics)
117
    {
118
        $this->analytics = $analytics;
119
    }
120
121
    /**
122
     * @return mixed
123
     */
124
    public function getMetrics()
125
    {
126
        return $this->metrics;
127
    }
128
129
    /**
130
     * @param mixed $metrics
131
     */
132
    public function setMetrics($metrics)
133
    {
134
        $metric = new Google_Service_AnalyticsReporting_Metric();
135
        $metric->setExpression($metrics);
136
        $this->metrics = $metric;
137
    }
138
139
    /**
140
     * Set up the Dimension Filters
141
     *
142
     * @return array|Google_Service_AnalyticsReporting_DimensionFilter[]
143
     */
144
    public function getDimensionFilters()
145
    {
146
        $filters = [];
147
        $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...
148
        $endWith = config::inst()->get(static::class, 'ends_with');
149
        if ($startWith) {
150
            return $this->createFilter('BEGINS_WITH', $startWith, $filters);
151
        }
152
        if ($endWith) {
153
            return $this->createFilter('ENDS_WITH', $endWith, $filters);
154
        }
155
156
        return $this->getPageDimensionFilters();
157
    }
158
159
    /**
160
     * @return array|Google_Service_AnalyticsReporting_DimensionFilter[]
161
     */
162
    public function getPageDimensionFilters()
163
    {
164
        $filters = [];
165
        // Operators are not constants, see here: https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/reports/batchGet#Operator
166
        $operator = 'ENDS_WITH';
167
        $pages = $this->getPages();
168
169
        foreach ($pages as $page) {
170
            // Home is recorded as just a slash in GA, we need an
171
            // exception for that
172
            if ($page === 'home') {
173
                $page = '/';
174
                $operator = 'EXACT';
175
            }
176
177
            $filters = $this->createFilter($operator, $page, $filters);
178
            // Reset the operator
179
            if ($operator === 'EXACT') {
180
                $operator = 'ENDS_WITH';
181
            }
182
        }
183
184
        return $filters;
185
    }
186
187
    /**
188
     * @return Google_Service_AnalyticsReporting_DimensionFilterClause
189
     */
190
    public function getDimensionFilterClauses()
191
    {
192
        $dimensionFilters = $this->getDimensionFilters();
193
        $dimensionClauses = new Google_Service_AnalyticsReporting_DimensionFilterClause();
194
        $dimensionClauses->setFilters($dimensionFilters);
195
        $dimensionClauses->setOperator('OR');
196
197
        return $dimensionClauses;
198
    }
199
200
    /**
201
     * Get the pages filtered by optional blacklisting and whitelisting
202
     * Return an array of the URLSegments, to limit memory abuse
203
     * @return array
204
     */
205
    public function getPages()
206
    {
207
        $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...
208
        $whitelist = Config::inst()->get(static::class, 'whitelist');
209
        /** @var DataList|Page[] $pages */
210
        $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...
211
        if ($blacklist) {
212
            $pages = $this->getBlacklist($blacklist, $pages);
213
        }
214
        if ($whitelist) {
215
            $pages = $this->getWhitelistPages($whitelist, $pages);
216
        }
217
218
        if ($pages->count() > 20) {
219
            $this->batched = true;
220
        }
221
222
        // Google limits to 20 reports per complex filter setup
223
        return $pages->limit(20)->column('URLSegment');
224
    }
225
226
    /**
227
     * @param array $blacklist
228
     * @param DataList $pages
229
     * @return DataList
230
     */
231
    protected function getBlacklist($blacklist, $pages)
232
    {
233
        $ids = [];
234
        foreach ($blacklist as $class) {
235
            $blacklistpages = $class::get();
236
            $ids = array_merge($ids, $blacklistpages->column('ID'));
237
        }
238
        $pages = $pages->exclude(['ID' => $ids]);
239
240
        return $pages;
241
    }
242
243
    /**
244
     * @param array $whitelist
245
     * @param DataList $pages
246
     * @return DataList
247
     */
248
    protected function getWhitelistPages($whitelist, $pages)
249
    {
250
        $ids = [];
251
        foreach ($whitelist as $class) {
252
            $nowDate = date('Y-m-d');
253
            $whitelistpages = $class::get()
254
                // This needs to be a where because of `IS NULL`
255
                ->where("(`Page`.`LastAnalyticsUpdate` < $nowDate)
256
                        OR (`Page`.`LastAnalyticsUpdate` IS NULL)");
257
            $ids = array_merge($ids, $whitelistpages->column('ID'));
258
        }
259
        $pages = $pages->filter(['ID' => $ids]);
260
261
        return $pages;
262
    }
263
264
    /**
265
     * @param $operator
266
     * @param $page
267
     * @param $filters
268
     * @return array|Google_Service_AnalyticsReporting_DimensionFilter[]
269
     */
270
    protected function createFilter($operator, $page, $filters)
271
    {
272
        $filter = new Google_Service_AnalyticsReporting_DimensionFilter();
273
        $filter->setOperator($operator);
274
        $filter->setCaseSensitive(false);
275
        $filter->setExpressions([$page]);
276
        $filter->setDimensionName('ga:pagePath');
277
        $filters[] = $filter;
278
279
        return $filters;
280
    }
281
}
282