GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( ce035e...d39658 )
by Jorge
01:55
created

Analytics::hasMinimumRequiredParameters()   C

Complexity

Conditions 7
Paths 12

Size

Total Lines 26
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 15
nc 12
nop 0
1
<?php
2
3
namespace TheIconic\Tracking\GoogleAnalytics;
4
5
use TheIconic\Tracking\GoogleAnalytics\Parameters\SingleParameter;
6
use TheIconic\Tracking\GoogleAnalytics\Parameters\CompoundParameterCollection;
7
use TheIconic\Tracking\GoogleAnalytics\Network\HttpClient;
8
use TheIconic\Tracking\GoogleAnalytics\Network\PrepareUrl;
9
use TheIconic\Tracking\GoogleAnalytics\Exception\InvalidPayloadDataException;
10
11
/**
12
 * Class Analytics
13
 *
14
 * The main interface for the clients, it relies heavily in magic methods exposing
15
 * an interface with method tags.
16
 *
17
 * ==== GETTERS ====
18
 * General
19
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProtocolVersion($value)
20
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTrackingId($value)
21
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setAnonymizeIp($value)
22
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDataSource($value)
23
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setQueueTime($value)
24
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCacheBuster($value)
25
 *
26
 * User
27
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setClientId($value)
28
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserId($value)
29
 *
30
 * Session
31
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSessionControl($value)
32
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setIpOverride($value)
33
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserAgentOverride($value)
34
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGeographicalOverride($value)
35
 *
36
 * Traffic Sources
37
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentReferrer($value)
38
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignName($value)
39
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignSource($value)
40
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignMedium($value)
41
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignKeyword($value)
42
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignContent($value)
43
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignId($value)
44
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGoogleAdwordsId($value)
45
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGoogleDisplayAdsId($value)
46
 *
47
 * System Info
48
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenResolution($value)
49
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setViewportSize($value)
50
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentEncoding($value)
51
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenColors($value)
52
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserLanguage($value)
53
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setJavaEnabled($value)
54
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setFlashVersion($value)
55
 *
56
 * Hit
57
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setHitType($value)
58
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setNonInteractionHit($value)
59
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendPageview()
60
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendEvent()
61
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendScreenview()
62
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendTransaction()
63
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendItem()
64
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendSocial()
65
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendException()
66
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendTiming()
67
 *
68
 * Content Information
69
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentLocationUrl($value)
70
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentHostName($value)
71
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentPath($value)
72
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentTitle($value)
73
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenName($value)
74
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setLinkId($value)
75
 *
76
 * App Tracking
77
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationName($value)
78
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationId($value)
79
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationVersion($value)
80
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationInstallerId($value)
81
 *
82
 * Event Tracking
83
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventCategory($value)
84
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventAction($value)
85
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventLabel($value)
86
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventValue($value)
87
 *
88
 * E-commerce
89
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemName($value)
90
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemPrice($value)
91
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemQuantity($value)
92
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemCode($value)
93
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemCategory($value)
94
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCurrencyCode($value)
95
 *
96
 * Enhanced E-Commerce
97
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTransactionId($value)
98
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setAffiliation($value)
99
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setRevenue($value)
100
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTax($value)
101
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setShipping($value)
102
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCouponCode($value)
103
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionList($value)
104
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCheckoutStep($value)
105
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCheckoutStepOption($value)
106
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics addProduct(array $productData)
107
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductAction($value)
108
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToDetail()
109
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToClick()
110
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToAdd()
111
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToRemove()
112
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToCheckout()
113
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToCheckoutOption()
114
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToPurchase()
115
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToRefund()
116
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductImpressionListName($value, $index)
117
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics addProductImpression(array $productData, $index)
118
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics addPromotion(array $promotionData)
119
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionAction($value)
120
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionActionToClick()
121
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionActionToView()
122
 *
123
 * Social Interactions
124
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialNetwork($value)
125
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialAction($value)
126
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialActionTarget($value)
127
 *
128
 * Timing
129
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingCategory($value)
130
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingVariableName($value)
131
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingTime($value)
132
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingLabel($value)
133
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPageLoadTime($value)
134
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDnsTime($value)
135
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPageDownloadTime($value)
136
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setRedirectResponseTime($value)
137
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTcpConnectTime($value)
138
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setServerResponseTime($value)
139
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDomInteractiveTime($value)
140
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setContentLoadTime($value)
141
 *
142
 * Exceptions
143
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExceptionDescription($value)
144
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setIsExceptionFatal($value)
145
 *
146
 * Custom Dimension / Metrics
147
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCustomDimension($value, $index)
148
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCustomMetric($value, $index)
149
 *
150
 * Content Grouping
151
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setContentGroup($value, $index)
152
 *
153
 * Content Experiments
154
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExperimentId($value)
155
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExperimentVariant($value)
156
 *
157
 * ==== SETTERS ====
158
 * General
159
 * @method string|int|null getProtocolVersion()
160
 * @method string|int|null getTrackingId()
161
 * @method string|int|null getAnonymizeIp()
162
 * @method string|int|null getDataSource()
163
 * @method string|int|null getQueueTime()
164
 * @method string|int|null getCacheBuster()
165
 *
166
 * User
167
 * @method string|int|null getClientId()
168
 * @method string|int|null getUserId()
169
 *
170
 * Session
171
 * @method string|int|null getSessionControl()
172
 * @method string|int|null getIpOverride()
173
 * @method string|int|null getUserAgentOverride()
174
 * @method string|int|null getGeographicalOverride()
175
 *
176
 * Traffic Sources
177
 * @method string|int|null getDocumentReferrer()
178
 * @method string|int|null getCampaignName()
179
 * @method string|int|null getCampaignSource()
180
 * @method string|int|null getCampaignMedium()
181
 * @method string|int|null getCampaignKeyword()
182
 * @method string|int|null getCampaignContent()
183
 * @method string|int|null getCampaignId()
184
 * @method string|int|null getGoogleAdwordsId()
185
 * @method string|int|null getGoogleDisplayAdsId()
186
 *
187
 * System Info
188
 * @method string|int|null getScreenResolution()
189
 * @method string|int|null getViewportSize()
190
 * @method string|int|null getDocumentEncoding()
191
 * @method string|int|null getScreenColors()
192
 * @method string|int|null getUserLanguage()
193
 * @method string|int|null getJavaEnabled()
194
 * @method string|int|null getFlashVersion()
195
 *
196
 * Hit
197
 * @method string|int|null getHitType()
198
 * @method string|int|null getNonInteractionHit()
199
 *
200
 * Content Information
201
 * @method string|int|null getDocumentLocationUrl()
202
 * @method string|int|null getDocumentHostName()
203
 * @method string|int|null getDocumentPath()
204
 * @method string|int|null getDocumentTitle()
205
 * @method string|int|null getScreenName()
206
 * @method string|int|null getLinkId()
207
 *
208
 * App Tracking
209
 * @method string|int|null getApplicationName()
210
 * @method string|int|null getApplicationId()
211
 * @method string|int|null getApplicationVersion()
212
 * @method string|int|null getApplicationInstallerId()
213
 *
214
 * Event Tracking
215
 * @method string|int|null getEventCategory()
216
 * @method string|int|null getEventAction()
217
 * @method string|int|null getEventLabel()
218
 * @method string|int|null getEventValue()
219
 *
220
 * E-commerce
221
 * @method string|int|null getItemName()
222
 * @method string|int|null getItemPrice()
223
 * @method string|int|null getItemQuantity()
224
 * @method string|int|null getItemCode()
225
 * @method string|int|null getItemCategory()
226
 * @method string|int|null getCurrencyCode()
227
 *
228
 * Enhanced E-Commerce
229
 * @method string|int|null getTransactionId()
230
 * @method string|int|null getAffiliation()
231
 * @method string|int|null getRevenue()
232
 * @method string|int|null getTax()
233
 * @method string|int|null getShipping()
234
 * @method string|int|null getCouponCode()
235
 * @method string|int|null getProductActionList()
236
 * @method string|int|null getCheckoutStep()
237
 * @method string|int|null getCheckoutStepOption()
238
 * @method string|int|null getProduct()
239
 * @method string|int|null getProductAction()
240
 * @method string|int|null getProductActionToDetail()
241
 * @method string|int|null getProductActionToClick()
242
 * @method string|int|null getProductActionToAdd()
243
 * @method string|int|null getProductActionToRemove()
244
 * @method string|int|null getProductActionToCheckout()
245
 * @method string|int|null getProductActionToCheckoutOption()
246
 * @method string|int|null getProductActionToPurchase()
247
 * @method string|int|null getProductActionToRefund()
248
 * @method string|int|null getProductImpressionListName($index)
249
 * @method string|int|null getProductImpression($listIndex)
250
 * @method string|int|null getPromotion()
251
 * @method string|int|null getPromotionAction()
252
 * @method string|int|null getPromotionActionToClick()
253
 * @method string|int|null getPromotionActionToView()
254
 *
255
 * Social Interactions
256
 * @method string|int|null getSocialNetwork()
257
 * @method string|int|null getSocialAction()
258
 * @method string|int|null getSocialActionTarget()
259
 *
260
 * Timing
261
 * @method string|int|null getUserTimingCategory()
262
 * @method string|int|null getUserTimingVariableName()
263
 * @method string|int|null getUserTimingTime()
264
 * @method string|int|null getUserTimingLabel()
265
 * @method string|int|null getPageLoadTime()
266
 * @method string|int|null getDnsTime()
267
 * @method string|int|null getPageDownloadTime()
268
 * @method string|int|null getRedirectResponseTime()
269
 * @method string|int|null getTcpConnectTime()
270
 * @method string|int|null getServerResponseTime()
271
 * @method string|int|null getDomInteractiveTime()
272
 * @method string|int|null getContentLoadTime()
273
 *
274
 * Exceptions
275
 * @method string|int|null getExceptionDescription()
276
 * @method string|int|null getIsExceptionFatal()
277
 *
278
 * Custom Dimension / Metrics
279
 * @method string|int|null getCustomDimension($index)
280
 * @method string|int|null getCustomMetric($index)
281
 *
282
 * Content Grouping
283
 * @method string|int|null getContentGroup($index)
284
 *
285
 * Content Experiments
286
 * @method string|int|null getExperimentId()
287
 * @method string|int|null getExperimentVariant()
288
 *
289
 * @package TheIconic\Tracking\GoogleAnalytics
290
 */
291
class Analytics
292
{
293
    /**
294
     * URI scheme for the GA API.
295
     *
296
     * @var string
297
     */
298
    protected $uriScheme = 'http';
299
300
    /**
301
     * Indicates if the request to GA will be asynchronous (non-blocking).
302
     *
303
     * @var boolean
304
     */
305
    protected $isAsyncRequest = false;
306
307
    /**
308
     * Endpoint to connect to when sending data to GA.
309
     *
310
     * @var string
311
     */
312
    protected $endpoint = '://www.google-analytics.com/collect';
313
314
    /**
315
     * Endpoint to connect to when validating hits.
316
     * @link https://developers.google.com/analytics/devguides/collection/protocol/v1/validating-hits
317
     *
318
     * @var string
319
     */
320
    protected $debugEndpoint = '://www.google-analytics.com/debug/collect';
321
322
    /**
323
     * Indicates if the request is in debug mode(validating hits).
324
     *
325
     * @var boolean
326
     */
327
    protected $isDebug = false;
328
329
    /**
330
     * Holds the single parameters added to the hit.
331
     *
332
     * @var SingleParameter[]
333
     */
334
    protected $singleParameters = [];
335
336
    /**
337
     * Holds the compound parameters collections added to the hit.
338
     *
339
     * @var  CompoundParameterCollection[]
340
     */
341
    protected $compoundParametersCollections = [];
342
343
    /**
344
     * Holds the HTTP client used to connect to GA.
345
     *
346
     * @var HttpClient
347
     */
348
    protected $httpClient;
349
350
    /**
351
     * Initializes to a list of all the available parameters to be sent in a hit.
352
     *
353
     * @var array
354
     */
355
    protected $availableParameters = [
356
        'ApplicationId' => 'AppTracking\\ApplicationId',
357
        'ApplicationInstallerId' => 'AppTracking\\ApplicationInstallerId',
358
        'ApplicationName' => 'AppTracking\\ApplicationName',
359
        'ApplicationVersion' => 'AppTracking\\ApplicationVersion',
360
        'ExperimentId' => 'ContentExperiments\\ExperimentId',
361
        'ExperimentVariant' => 'ContentExperiments\\ExperimentVariant',
362
        'ContentGroup' => 'ContentGrouping\\ContentGroup',
363
        'DocumentHostName' => 'ContentInformation\\DocumentHostName',
364
        'DocumentLocationUrl' => 'ContentInformation\\DocumentLocationUrl',
365
        'DocumentPath' => 'ContentInformation\\DocumentPath',
366
        'DocumentTitle' => 'ContentInformation\\DocumentTitle',
367
        'LinkId' => 'ContentInformation\\LinkId',
368
        'ScreenName' => 'ContentInformation\\ScreenName',
369
        'CustomDimension' => 'CustomDimensionsMetrics\\CustomDimension',
370
        'CustomMetric' => 'CustomDimensionsMetrics\\CustomMetric',
371
        'CurrencyCode' => 'Ecommerce\\CurrencyCode',
372
        'ItemCategory' => 'Ecommerce\\ItemCategory',
373
        'ItemCode' => 'Ecommerce\\ItemCode',
374
        'ItemName' => 'Ecommerce\\ItemName',
375
        'ItemPrice' => 'Ecommerce\\ItemPrice',
376
        'ItemQuantity' => 'Ecommerce\\ItemQuantity',
377
        'Affiliation' => 'EnhancedEcommerce\\Affiliation',
378
        'CheckoutStep' => 'EnhancedEcommerce\\CheckoutStep',
379
        'CheckoutStepOption' => 'EnhancedEcommerce\\CheckoutStepOption',
380
        'CouponCode' => 'EnhancedEcommerce\\CouponCode',
381
        'Product' => 'EnhancedEcommerce\\Product',
382
        'ProductAction' => 'EnhancedEcommerce\\ProductAction',
383
        'ProductActionList' => 'EnhancedEcommerce\\ProductActionList',
384
        'ProductCollection' => 'EnhancedEcommerce\\ProductCollection',
385
        'ProductImpression' => 'EnhancedEcommerce\\ProductImpression',
386
        'ProductImpressionCollection' => 'EnhancedEcommerce\\ProductImpressionCollection',
387
        'ProductImpressionListName' => 'EnhancedEcommerce\\ProductImpressionListName',
388
        'Promotion' => 'EnhancedEcommerce\\Promotion',
389
        'PromotionAction' => 'EnhancedEcommerce\\PromotionAction',
390
        'PromotionCollection' => 'EnhancedEcommerce\\PromotionCollection',
391
        'Revenue' => 'EnhancedEcommerce\\Revenue',
392
        'Shipping' => 'EnhancedEcommerce\\Shipping',
393
        'Tax' => 'EnhancedEcommerce\\Tax',
394
        'TransactionId' => 'EnhancedEcommerce\\TransactionId',
395
        'EventAction' => 'Event\\EventAction',
396
        'EventCategory' => 'Event\\EventCategory',
397
        'EventLabel' => 'Event\\EventLabel',
398
        'EventValue' => 'Event\\EventValue',
399
        'ExceptionDescription' => 'Exceptions\\ExceptionDescription',
400
        'IsExceptionFatal' => 'Exceptions\\IsExceptionFatal',
401
        'AnonymizeIp' => 'General\\AnonymizeIp',
402
        'CacheBuster' => 'General\\CacheBuster',
403
        'DataSource' => 'General\\DataSource',
404
        'ProtocolVersion' => 'General\\ProtocolVersion',
405
        'QueueTime' => 'General\\QueueTime',
406
        'TrackingId' => 'General\\TrackingId',
407
        'HitType' => 'Hit\\HitType',
408
        'NonInteractionHit' => 'Hit\\NonInteractionHit',
409
        'GeographicalOverride' => 'Session\\GeographicalOverride',
410
        'IpOverride' => 'Session\\IpOverride',
411
        'SessionControl' => 'Session\\SessionControl',
412
        'UserAgentOverride' => 'Session\\UserAgentOverride',
413
        'SocialAction' => 'SocialInteractions\\SocialAction',
414
        'SocialActionTarget' => 'SocialInteractions\\SocialActionTarget',
415
        'SocialNetwork' => 'SocialInteractions\\SocialNetwork',
416
        'DocumentEncoding' => 'SystemInfo\\DocumentEncoding',
417
        'FlashVersion' => 'SystemInfo\\FlashVersion',
418
        'JavaEnabled' => 'SystemInfo\\JavaEnabled',
419
        'ScreenColors' => 'SystemInfo\\ScreenColors',
420
        'ScreenResolution' => 'SystemInfo\\ScreenResolution',
421
        'UserLanguage' => 'SystemInfo\\UserLanguage',
422
        'ViewportSize' => 'SystemInfo\\ViewportSize',
423
        'ContentLoadTime' => 'Timing\\ContentLoadTime',
424
        'DnsTime' => 'Timing\\DnsTime',
425
        'DomInteractiveTime' => 'Timing\\DomInteractiveTime',
426
        'PageDownloadTime' => 'Timing\\PageDownloadTime',
427
        'PageLoadTime' => 'Timing\\PageLoadTime',
428
        'RedirectResponseTime' => 'Timing\\RedirectResponseTime',
429
        'ServerResponseTime' => 'Timing\\ServerResponseTime',
430
        'TcpConnectTime' => 'Timing\\TcpConnectTime',
431
        'UserTimingCategory' => 'Timing\\UserTimingCategory',
432
        'UserTimingLabel' => 'Timing\\UserTimingLabel',
433
        'UserTimingTime' => 'Timing\\UserTimingTime',
434
        'UserTimingVariableName' => 'Timing\\UserTimingVariableName',
435
        'CampaignContent' => 'TrafficSources\\CampaignContent',
436
        'CampaignId' => 'TrafficSources\\CampaignId',
437
        'CampaignKeyword' => 'TrafficSources\\CampaignKeyword',
438
        'CampaignMedium' => 'TrafficSources\\CampaignMedium',
439
        'CampaignName' => 'TrafficSources\\CampaignName',
440
        'CampaignSource' => 'TrafficSources\\CampaignSource',
441
        'DocumentReferrer' => 'TrafficSources\\DocumentReferrer',
442
        'GoogleAdwordsId' => 'TrafficSources\\GoogleAdwordsId',
443
        'GoogleDisplayAdsId' => 'TrafficSources\\GoogleDisplayAdsId',
444
        'ClientId' => 'User\\ClientId',
445
        'UserId' => 'User\\UserId',
446
    ];
447
448
    /**
449
     * When passed with an argument of TRUE, it will send the hit using HTTPS instead of plain HTTP.
450
     * It parses the available parameters.
451
     *
452
     * @param bool $isSsl
453
     * @throws \InvalidArgumentException
454
     */
455
    public function __construct($isSsl = false)
456
    {
457
        if (!is_bool($isSsl)) {
458
            throw new \InvalidArgumentException('First constructor argument "isSSL" must be boolean');
459
        }
460
461
        if ($isSsl) {
462
            $this->uriScheme .= 's';
463
            $this->endpoint = str_replace('www', 'ssl', $this->endpoint);
464
        }
465
    }
466
467
    /**
468
     * Sets a request to be either synchronous or asynchronous (non-blocking).
469
     *
470
     * @api
471
     * @param boolean $isAsyncRequest
472
     * @return $this
473
     */
474
    public function setAsyncRequest($isAsyncRequest)
475
    {
476
        $this->isAsyncRequest = $isAsyncRequest;
477
478
        return $this;
479
    }
480
481
    /**
482
     * Makes the request to GA asynchronous (non-blocking).
483
     *
484
     * @deprecated Use setAsyncRequest(boolean $isAsyncRequest) instead. To be removed in next major version.
485
     *
486
     * @return $this
487
     */
488
    public function makeNonBlocking()
489
    {
490
        $this->isAsyncRequest = true;
491
492
        return $this;
493
    }
494
495
    /**
496
     * Sets the HttpClient.
497
     *
498
     * @internal
499
     * @param HttpClient $httpClient
500
     * @return $this
501
     */
502
    public function setHttpClient(HttpClient $httpClient)
503
    {
504
        $this->httpClient = $httpClient;
505
506
        return $this;
507
    }
508
509
    /**
510
     * Gets the HttpClient.
511
     *
512
     * @return HttpClient
513
     */
514
    protected function getHttpClient()
515
    {
516
        if ($this->httpClient === null) {
517
            // @codeCoverageIgnoreStart
518
            $this->setHttpClient(new HttpClient());
519
        }
520
        // @codeCoverageIgnoreEnd
521
522
        return $this->httpClient;
523
    }
524
525
    /**
526
     * Gets the full endpoint to GA.
527
     *
528
     * @return string
529
     */
530
    protected function getEndpoint()
531
    {
532
        return ($this->isDebug) ? $this->uriScheme . $this->debugEndpoint : $this->uriScheme . $this->endpoint;
533
    }
534
535
    /**
536
     * Sets debug mode to true or false.
537
     *
538
     * @api
539
     * @param bool $value
540
     * @return \TheIconic\Tracking\GoogleAnalytics\Analytics
541
     */
542
    public function setDebug($value)
543
    {
544
        $this->isDebug = $value;
545
546
        return $this;
547
    }
548
549
    /**
550
     * Sends a hit to GA. The hit will contain in the payload all the parameters added before.
551
     *
552
     * @param $methodName
553
     * @return AnalyticsResponse
554
     * @throws Exception\InvalidPayloadDataException
555
     */
556
    protected function sendHit($methodName)
557
    {
558
        $hitType = strtoupper(substr($methodName, 4));
559
560
        $hitConstant = $this->getParameterClassConstant(
561
            'TheIconic\Tracking\GoogleAnalytics\Parameters\Hit\HitType::HIT_TYPE_' . $hitType,
562
            'Hit type ' . $hitType . ' is not defined, check spelling'
563
        );
564
565
        $this->setHitType($hitConstant);
566
567
        if (!$this->hasMinimumRequiredParameters()) {
568
            throw new InvalidPayloadDataException();
569
        }
570
571
        return $this->getHttpClient()->post(
572
            $this->getUrl(),
573
            $this->isAsyncRequest
574
        );
575
    }
576
577
    /**
578
     * Build and returns URL used to send to Google Analytics.
579
     *
580
     * @api
581
     * @return string
582
     */
583
    public function getUrl()
584
    {
585
        $prepareUrl = new PrepareUrl;
586
587
        return $prepareUrl->build(
588
            $this->getEndpoint(),
589
            $this->singleParameters,
590
            $this->compoundParametersCollections
591
        );
592
    }
593
594
    /**
595
     * Validates the minimum required parameters for every GA hit are being sent.
596
     *
597
     * @SuppressWarnings(PHPMD.LongVariable)
598
     *
599
     * @return bool
600
     */
601
    protected function hasMinimumRequiredParameters()
602
    {
603
        $minimumRequiredParameters = [
604
            'v' => false,
605
            'tid' => false,
606
            'cid' => false,
607
            'uid' => false,
608
            't' => false,
609
        ];
610
611
        foreach ($minimumRequiredParameters as $parameterName => $isParamPresent) {
612
            if (in_array($parameterName, array_keys($this->singleParameters))) {
613
                $minimumRequiredParameters[$parameterName] = true;
614
            }
615
        }
616
617
        if ((!$minimumRequiredParameters['cid'] && $minimumRequiredParameters['uid'])) {
618
            $minimumRequiredParameters['cid'] = true;
619
        }
620
621
        if ((!$minimumRequiredParameters['uid'] && $minimumRequiredParameters['cid'])) {
622
            $minimumRequiredParameters['uid'] = true;
623
        }
624
625
        return !in_array(false, $minimumRequiredParameters, true);
626
    }
627
628
    /**
629
     * Sets a parameter action to the value specified by the method call.
630
     *
631
     * @param $parameter
632
     * @param $action
633
     * @return $this
634
     */
635
    protected function setParameterActionTo($parameter, $action)
636
    {
637
        $actionConstant = $this->getParameterClassConstant(
638
            'TheIconic\Tracking\GoogleAnalytics\Parameters\EnhancedEcommerce\\'
639
            . $parameter . 'Action::ACTION_' . strtoupper($action),
640
            $parameter . ' action ' . $action . ' does not exist, check spelling'
641
        );
642
643
        $function = 'set' . $parameter . 'Action';
644
645
        $this->$function($actionConstant);
646
647
        return $this;
648
    }
649
650
    /**
651
     * Gets a contant from a class dynamically.
652
     *
653
     * @param $constant
654
     * @param $exceptionMsg
655
     * @return mixed
656
     * @throws \BadMethodCallException
657
     */
658
    protected function getParameterClassConstant($constant, $exceptionMsg)
659
    {
660
        if (defined($constant)) {
661
            return constant($constant);
662
        } else {
663
            throw new \BadMethodCallException($exceptionMsg);
664
        }
665
    }
666
667
    /**
668
     * Sets the value for a parameter.
669
     *
670
     * @param $methodName
671
     * @param array $methodArguments
672
     * @return $this
673
     * @throws \InvalidArgumentException
674
     */
675
    protected function setParameter($methodName, array $methodArguments)
676
    {
677
        $parameterClass = substr($methodName, 3);
678
679
        $fullParameterClass = $this->getFullParameterClass($parameterClass, $methodName);
680
681
        $parameterIndex = $this->getIndexFromArguments($methodArguments);
682
683
        /** @var SingleParameter $parameterObject */
684
        $parameterObject = new $fullParameterClass($parameterIndex);
685
686
        if (!isset($methodArguments[0])) {
687
            throw new \InvalidArgumentException(
688
                'For Analytics object, you must specify a value to be set for ' . $methodName
689
            );
690
        } else {
691
            $parameterObject->setValue($methodArguments[0]);
692
        }
693
694
        $this->singleParameters[$parameterObject->getName()] = $parameterObject;
695
696
        return $this;
697
    }
698
699
    /**
700
     * Adds an item to a compund parameter collection.
701
     *
702
     * @SuppressWarnings(PHPMD.LongVariable)
703
     *
704
     * @param $methodName
705
     * @param array $methodArguments
706
     * @return $this
707
     * @throws \InvalidArgumentException
708
     */
709
    protected function addItem($methodName, array $methodArguments)
710
    {
711
        $parameterClass = substr($methodName, 3);
712
713
        $fullParameterClass = $this->getFullParameterClass($parameterClass, $methodName);
714
715
        if (!isset($methodArguments[0])) {
716
            throw new \InvalidArgumentException(
717
                'You must specify a ' . $parameterClass . ' to be add for ' . $methodName
718
            );
719
        } else {
720
            $parameterObject = new $fullParameterClass($methodArguments[0]);
721
        }
722
723
        $collectionIndex = $this->getIndexFromArguments($methodArguments);
724
725
        if (isset($this->compoundParametersCollections[$parameterClass . $collectionIndex])) {
726
            $this->compoundParametersCollections[$parameterClass . $collectionIndex]->add($parameterObject);
727
        } else {
728
            $fullParameterCollectionClass = $fullParameterClass . 'Collection';
729
730
            /** @var CompoundParameterCollection $parameterObjectCollection */
731
            $parameterObjectCollection = new $fullParameterCollectionClass($collectionIndex);
732
733
            $parameterObjectCollection->add($parameterObject);
734
735
            $this->compoundParametersCollections[$parameterClass . $collectionIndex] = $parameterObjectCollection;
736
        }
737
738
        return $this;
739
    }
740
741
    /**
742
     * Gets the value for a parameter.
743
     *
744
     * @SuppressWarnings(PHPMD.LongVariable)
745
     *
746
     * @param $methodName
747
     * @param array $methodArguments
748
     * @return string
749
     * @throws \InvalidArgumentException
750
     */
751
    protected function getParameter($methodName, array $methodArguments)
752
    {
753
        $parameterClass = substr($methodName, 3);
754
755
        $fullParameterClass = $this->getFullParameterClass($parameterClass, $methodName);
756
757
        // Handle index arguments
758
        $parameterIndex = '';
759
        if (isset($methodArguments[0]) && is_numeric($methodArguments[0])) {
760
            $parameterIndex = $methodArguments[0];
761
        }
762
763
        // Handle compoundParametersCollections
764
        if (isset($this->compoundParametersCollections[$parameterClass . $parameterIndex])) {
765
            // If compoundParametersCollections contains our Objects, return them well-formatted
766
            return $this->compoundParametersCollections[$parameterClass . $parameterIndex]->getReadableItems();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->compoundPa...x]->getReadableItems(); (array) is incompatible with the return type documented by TheIconic\Tracking\Googl...Analytics::getParameter of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
767
        } else {
768
            $fullParameterCollectionClass = $fullParameterClass . 'Collection';
769
770
            // Test if the class Collection exist
771
            if (class_exists($fullParameterCollectionClass)) {
772
                return null;
773
            }
774
            // If not, it's a SingleParameter Object, continue the magic
775
        }
776
777
        /** @var SingleParameter $parameterObject */
778
        $parameterObject = new $fullParameterClass($parameterIndex);
779
780
        if (!array_key_exists($parameterObject->getName(), $this->singleParameters)) {
781
            return null;
782
        }
783
784
        $currentParameterObject = $this->singleParameters[$parameterObject->getName()];
785
786
        return $currentParameterObject->getValue();
787
788
    }
789
790
    /**
791
     * Gets the index value from the arguments.
792
     *
793
     * @param $methodArguments
794
     * @return string
795
     */
796
    protected function getIndexFromArguments($methodArguments)
797
    {
798
        $index = '';
799
        if (isset($methodArguments[1]) && is_numeric($methodArguments[1])) {
800
            $index = $methodArguments[1];
801
        }
802
803
        return $index;
804
    }
805
806
    /**
807
     * Gets the fully qualified name for a parameter.
808
     *
809
     * @param $parameterClass
810
     * @param $methodName
811
     * @return string
812
     * @throws \BadMethodCallException
813
     */
814
    protected function getFullParameterClass($parameterClass, $methodName)
815
    {
816
        if (empty($this->availableParameters[$parameterClass])) {
817
            throw new \BadMethodCallException('Method ' . $methodName . ' not defined for Analytics class');
818
        } else {
819
            return '\\TheIconic\\Tracking\\GoogleAnalytics\\Parameters\\' . $this->availableParameters[$parameterClass];
820
        }
821
    }
822
823
    /**
824
     * Routes the method call to the adequate protected method.
825
     *
826
     * @param $methodName
827
     * @param array $methodArguments
828
     * @return mixed
829
     * @throws \BadMethodCallException
830
     */
831
    public function __call($methodName, array $methodArguments)
832
    {
833
        $methodName = $this->fixTypos($methodName);
834
835
        if (preg_match('/^set(Product|Promotion)ActionTo(\w+)/', $methodName, $matches)) {
836
            return $this->setParameterActionTo($matches[1], $matches[2]);
837
        }
838
839
        if (preg_match('/^(set)(\w+)/', $methodName, $matches)) {
840
            return $this->setParameter($methodName, $methodArguments);
841
        }
842
843
        if (preg_match('/^(add)(\w+)/', $methodName, $matches)) {
844
            return $this->addItem($methodName, $methodArguments);
845
        }
846
847
        if (preg_match('/^(send)(\w+)/', $methodName, $matches)) {
848
            return $this->sendHit($methodName);
849
        }
850
851
        // Get Parameters
852
        if (preg_match('/^(get)(\w+)/', $methodName, $matches)) {
853
            return $this->getParameter($methodName, $methodArguments);
854
        }
855
856
        throw new \BadMethodCallException('Method ' . $methodName . ' not defined for Analytics class');
857
    }
858
859
    /**
860
     * Fix typos that went into releases, this way we ensure we don't break scripts in production.
861
     *
862
     * @param string $methodName
863
     * @return string
864
     */
865
    protected function fixTypos($methodName)
866
    {
867
        // @TODO deprecated in v2, to be removed in v3
868
        if ($methodName === 'setUserTiminCategory') {
869
            $methodName = 'setUserTimingCategory';
870
        }
871
872
        return $methodName;
873
    }
874
}
875