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 ( 6a5cb5...bf5e8a )
by Jorge
11s
created

Analytics::getUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 10
rs 9.4285
cc 1
eloc 6
nc 1
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
 * General
18
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProtocolVersion($value)
19
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTrackingId($value)
20
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setAnonymizeIp($value)
21
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDataSource($value)
22
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setQueueTime($value)
23
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCacheBuster($value)
24
 *
25
 * User
26
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setClientId($value)
27
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserId($value)
28
 *
29
 * Session
30
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSessionControl($value)
31
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setIpOverride($value)
32
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserAgentOverride($value)
33
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGeographicalOverride($value)
34
 *
35
 * Traffic Sources
36
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentReferrer($value)
37
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignName($value)
38
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignSource($value)
39
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignMedium($value)
40
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignKeyword($value)
41
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignContent($value)
42
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignId($value)
43
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGoogleAdwordsId($value)
44
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGoogleDisplayAdsId($value)
45
 *
46
 * System Info
47
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenResolution($value)
48
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setViewportSize($value)
49
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentEncoding($value)
50
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenColors($value)
51
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserLanguage($value)
52
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setJavaEnabled($value)
53
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setFlashVersion($value)
54
 *
55
 * Hit
56
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setHitType($value)
57
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setNonInteractionHit($value)
58
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendPageview()
59
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendEvent()
60
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendScreenview()
61
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendTransaction()
62
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendItem()
63
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendSocial()
64
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendException()
65
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendTiming()
66
 *
67
 * Content Information
68
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentLocationUrl($value)
69
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentHostName($value)
70
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentPath($value)
71
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentTitle($value)
72
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenName($value)
73
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setLinkId($value)
74
 *
75
 * App Tracking
76
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationName($value)
77
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationId($value)
78
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationVersion($value)
79
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationInstallerId($value)
80
 *
81
 * Event Tracking
82
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventCategory($value)
83
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventAction($value)
84
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventLabel($value)
85
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventValue($value)
86
 *
87
 * E-commerce
88
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemName($value)
89
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemPrice($value)
90
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemQuantity($value)
91
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemCode($value)
92
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemCategory($value)
93
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCurrencyCode($value)
94
 *
95
 * Enhanced E-Commerce
96
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTransactionId($value)
97
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setAffiliation($value)
98
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setRevenue($value)
99
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTax($value)
100
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setShipping($value)
101
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCouponCode($value)
102
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionList($value)
103
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCheckoutStep($value)
104
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCheckoutStepOption($value)
105
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics addProduct(array $productData)
106
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductAction($value)
107
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToDetail()
108
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToClick()
109
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToAdd()
110
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToRemove()
111
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToCheckout()
112
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToCheckoutOption()
113
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToPurchase()
114
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToRefund()
115
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductImpressionListName($value, $index)
116
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics addProductImpression(array $productData, $index)
117
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics addPromotion(array $promotionData)
118
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionAction($value)
119
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionActionToClick()
120
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionActionToView()
121
 *
122
 * Social Interactions
123
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialNetwork($value)
124
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialAction($value)
125
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialActionTarget($value)
126
 *
127
 * Timing
128
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingCategory($value)
129
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingVariableName($value)
130
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingTime($value)
131
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingLabel($value)
132
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPageLoadTime($value)
133
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDnsTime($value)
134
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPageDownloadTime($value)
135
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setRedirectResponseTime($value)
136
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTcpConnectTime($value)
137
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setServerResponseTime($value)
138
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDomInteractiveTime($value)
139
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setContentLoadTime($value)
140
 *
141
 * Exceptions
142
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExceptionDescription($value)
143
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setIsExceptionFatal($value)
144
 *
145
 * Custom Dimension / Metrics
146
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCustomDimension($value, $index)
147
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCustomMetric($value, $index)
148
 *
149
 * Content Grouping
150
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setContentGroup($value, $index)
151
 *
152
 * Content Experiments
153
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExperimentId($value)
154
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExperimentVariant($value)
155
 *
156
 *
157
 * @package TheIconic\Tracking\GoogleAnalytics
158
 */
159
class Analytics
160
{
161
    /**
162
     * URI scheme for the GA API.
163
     *
164
     * @var string
165
     */
166
    private $uriScheme = 'http';
167
168
    /**
169
     * Indicates if the request to GA will be asynchronous (non-blocking).
170
     *
171
     * @var boolean
172
     */
173
    private $isAsyncRequest = false;
174
175
    /**
176
     * Endpoint to connect to when sending data to GA.
177
     *
178
     * @var string
179
     */
180
    private $endpoint = '://www.google-analytics.com/collect';
181
182
    /**
183
     * Endpoint to connect to when validating hits.
184
     * @link https://developers.google.com/analytics/devguides/collection/protocol/v1/validating-hits
185
     *
186
     * @var string
187
     */
188
    private $debugEndpoint = '://www.google-analytics.com/debug/collect';
189
190
    /**
191
     * Indicates if the request is in debug mode(validating hits).
192
     *
193
     * @var boolean
194
     */
195
    private $isDebug = false;
196
197
    /**
198
     * Holds the single parameters added to the hit.
199
     *
200
     * @var SingleParameter[]
201
     */
202
    private $singleParameters = [];
203
204
    /**
205
     * Holds the compound parameters collections added to the hit.
206
     *
207
     * @var  CompoundParameterCollection[]
208
     */
209
    private $compoundParametersCollections = [];
210
211
    /**
212
     * Holds the HTTP client used to connect to GA.
213
     *
214
     * @var HttpClient
215
     */
216
    private $httpClient;
217
218
    /**
219
     * Initializes to a list of all the available parameters to be sent in a hit.
220
     *
221
     * @var array
222
     */
223
    private $availableParameters = [
224
        'ApplicationId' => 'AppTracking\\ApplicationId',
225
        'ApplicationInstallerId' => 'AppTracking\\ApplicationInstallerId',
226
        'ApplicationName' => 'AppTracking\\ApplicationName',
227
        'ApplicationVersion' => 'AppTracking\\ApplicationVersion',
228
        'ExperimentId' => 'ContentExperiments\\ExperimentId',
229
        'ExperimentVariant' => 'ContentExperiments\\ExperimentVariant',
230
        'ContentGroup' => 'ContentGrouping\\ContentGroup',
231
        'DocumentHostName' => 'ContentInformation\\DocumentHostName',
232
        'DocumentLocationUrl' => 'ContentInformation\\DocumentLocationUrl',
233
        'DocumentPath' => 'ContentInformation\\DocumentPath',
234
        'DocumentTitle' => 'ContentInformation\\DocumentTitle',
235
        'LinkId' => 'ContentInformation\\LinkId',
236
        'ScreenName' => 'ContentInformation\\ScreenName',
237
        'CustomDimension' => 'CustomDimensionsMetrics\\CustomDimension',
238
        'CustomMetric' => 'CustomDimensionsMetrics\\CustomMetric',
239
        'CurrencyCode' => 'Ecommerce\\CurrencyCode',
240
        'ItemCategory' => 'Ecommerce\\ItemCategory',
241
        'ItemCode' => 'Ecommerce\\ItemCode',
242
        'ItemName' => 'Ecommerce\\ItemName',
243
        'ItemPrice' => 'Ecommerce\\ItemPrice',
244
        'ItemQuantity' => 'Ecommerce\\ItemQuantity',
245
        'Affiliation' => 'EnhancedEcommerce\\Affiliation',
246
        'CheckoutStep' => 'EnhancedEcommerce\\CheckoutStep',
247
        'CheckoutStepOption' => 'EnhancedEcommerce\\CheckoutStepOption',
248
        'CouponCode' => 'EnhancedEcommerce\\CouponCode',
249
        'Product' => 'EnhancedEcommerce\\Product',
250
        'ProductAction' => 'EnhancedEcommerce\\ProductAction',
251
        'ProductActionList' => 'EnhancedEcommerce\\ProductActionList',
252
        'ProductCollection' => 'EnhancedEcommerce\\ProductCollection',
253
        'ProductImpression' => 'EnhancedEcommerce\\ProductImpression',
254
        'ProductImpressionCollection' => 'EnhancedEcommerce\\ProductImpressionCollection',
255
        'ProductImpressionListName' => 'EnhancedEcommerce\\ProductImpressionListName',
256
        'Promotion' => 'EnhancedEcommerce\\Promotion',
257
        'PromotionAction' => 'EnhancedEcommerce\\PromotionAction',
258
        'PromotionCollection' => 'EnhancedEcommerce\\PromotionCollection',
259
        'Revenue' => 'EnhancedEcommerce\\Revenue',
260
        'Shipping' => 'EnhancedEcommerce\\Shipping',
261
        'Tax' => 'EnhancedEcommerce\\Tax',
262
        'TransactionId' => 'EnhancedEcommerce\\TransactionId',
263
        'EventAction' => 'Event\\EventAction',
264
        'EventCategory' => 'Event\\EventCategory',
265
        'EventLabel' => 'Event\\EventLabel',
266
        'EventValue' => 'Event\\EventValue',
267
        'ExceptionDescription' => 'Exceptions\\ExceptionDescription',
268
        'IsExceptionFatal' => 'Exceptions\\IsExceptionFatal',
269
        'AnonymizeIp' => 'General\\AnonymizeIp',
270
        'CacheBuster' => 'General\\CacheBuster',
271
        'DataSource' => 'General\\DataSource',
272
        'ProtocolVersion' => 'General\\ProtocolVersion',
273
        'QueueTime' => 'General\\QueueTime',
274
        'TrackingId' => 'General\\TrackingId',
275
        'HitType' => 'Hit\\HitType',
276
        'NonInteractionHit' => 'Hit\\NonInteractionHit',
277
        'GeographicalOverride' => 'Session\\GeographicalOverride',
278
        'IpOverride' => 'Session\\IpOverride',
279
        'SessionControl' => 'Session\\SessionControl',
280
        'UserAgentOverride' => 'Session\\UserAgentOverride',
281
        'SocialAction' => 'SocialInteractions\\SocialAction',
282
        'SocialActionTarget' => 'SocialInteractions\\SocialActionTarget',
283
        'SocialNetwork' => 'SocialInteractions\\SocialNetwork',
284
        'DocumentEncoding' => 'SystemInfo\\DocumentEncoding',
285
        'FlashVersion' => 'SystemInfo\\FlashVersion',
286
        'JavaEnabled' => 'SystemInfo\\JavaEnabled',
287
        'ScreenColors' => 'SystemInfo\\ScreenColors',
288
        'ScreenResolution' => 'SystemInfo\\ScreenResolution',
289
        'UserLanguage' => 'SystemInfo\\UserLanguage',
290
        'ViewportSize' => 'SystemInfo\\ViewportSize',
291
        'ContentLoadTime' => 'Timing\\ContentLoadTime',
292
        'DnsTime' => 'Timing\\DnsTime',
293
        'DomInteractiveTime' => 'Timing\\DomInteractiveTime',
294
        'PageDownloadTime' => 'Timing\\PageDownloadTime',
295
        'PageLoadTime' => 'Timing\\PageLoadTime',
296
        'RedirectResponseTime' => 'Timing\\RedirectResponseTime',
297
        'ServerResponseTime' => 'Timing\\ServerResponseTime',
298
        'TcpConnectTime' => 'Timing\\TcpConnectTime',
299
        'UserTimingCategory' => 'Timing\\UserTimingCategory',
300
        'UserTimingLabel' => 'Timing\\UserTimingLabel',
301
        'UserTimingTime' => 'Timing\\UserTimingTime',
302
        'UserTimingVariableName' => 'Timing\\UserTimingVariableName',
303
        'CampaignContent' => 'TrafficSources\\CampaignContent',
304
        'CampaignId' => 'TrafficSources\\CampaignId',
305
        'CampaignKeyword' => 'TrafficSources\\CampaignKeyword',
306
        'CampaignMedium' => 'TrafficSources\\CampaignMedium',
307
        'CampaignName' => 'TrafficSources\\CampaignName',
308
        'CampaignSource' => 'TrafficSources\\CampaignSource',
309
        'DocumentReferrer' => 'TrafficSources\\DocumentReferrer',
310
        'GoogleAdwordsId' => 'TrafficSources\\GoogleAdwordsId',
311
        'GoogleDisplayAdsId' => 'TrafficSources\\GoogleDisplayAdsId',
312
        'ClientId' => 'User\\ClientId',
313
        'UserId' => 'User\\UserId',
314
    ];
315
316
    /**
317
     * When passed with an argument of TRUE, it will send the hit using HTTPS instead of plain HTTP.
318
     * It parses the available parameters.
319
     *
320
     * @param bool $isSsl
321
     * @throws \InvalidArgumentException
322
     */
323
    public function __construct($isSsl = false)
324
    {
325
        if (!is_bool($isSsl)) {
326
            throw new \InvalidArgumentException('First constructor argument "isSSL" must be boolean');
327
        }
328
329
        if ($isSsl) {
330
            $this->uriScheme .= 's';
331
            $this->endpoint = str_replace('www', 'ssl', $this->endpoint);
332
        }
333
    }
334
335
    /**
336
     * Sets a request to be either synchronous or asynchronous (non-blocking).
337
     *
338
     * @param boolean $isAsyncRequest
339
     * @return $this
340
     */
341
    public function setAsyncRequest($isAsyncRequest)
342
    {
343
        $this->isAsyncRequest = $isAsyncRequest;
344
345
        return $this;
346
    }
347
348
    /**
349
     * Makes the request to GA asynchronous (non-blocking).
350
     *
351
     * @deprecated Use setAsyncRequest(boolean $isAsyncRequest) instead. To be removed in next major version.
352
     *
353
     * @return $this
354
     */
355
    public function makeNonBlocking()
356
    {
357
        $this->isAsyncRequest = true;
358
359
        return $this;
360
    }
361
362
    /**
363
     * Sets the HttpClient.
364
     *
365
     * @param HttpClient $httpClient
366
     * @return $this
367
     */
368
    public function setHttpClient(HttpClient $httpClient)
369
    {
370
        $this->httpClient = $httpClient;
371
372
        return $this;
373
    }
374
375
    /**
376
     * Gets the HttpClient.
377
     *
378
     * @return HttpClient
379
     */
380
    private function getHttpClient()
381
    {
382
        if ($this->httpClient === null) {
383
            // @codeCoverageIgnoreStart
384
            $this->setHttpClient(new HttpClient());
385
        }
386
        // @codeCoverageIgnoreEnd
387
388
        return $this->httpClient;
389
    }
390
391
    /**
392
     * Gets the full endpoint to GA.
393
     *
394
     * @return string
395
     */
396
    private function getEndpoint()
397
    {
398
        return ($this->isDebug) ? $this->uriScheme . $this->debugEndpoint : $this->uriScheme . $this->endpoint;
399
    }
400
401
    /**
402
     * Sets debug mode to true or false.
403
     *
404
     * @param bool $value
405
     * @return \TheIconic\Tracking\GoogleAnalytics\Analytics
406
     */
407
    public function setDebug($value)
408
    {
409
        $this->isDebug = $value;
410
411
        return $this;
412
    }
413
    
414
    /**
415
     * Sends a hit to GA. The hit will contain in the payload all the parameters added before.
416
     *
417
     * @param $methodName
418
     * @return AnalyticsResponse
419
     * @throws Exception\InvalidPayloadDataException
420
     */
421
    private function sendHit($methodName)
422
    {
423
        $hitType = strtoupper(substr($methodName, 4));
424
425
        $hitConstant = $this->getParameterClassConstant(
426
            'TheIconic\Tracking\GoogleAnalytics\Parameters\Hit\HitType::HIT_TYPE_' . $hitType,
427
            'Hit type ' . $hitType . ' is not defined, check spelling'
428
        );
429
430
        $this->setHitType($hitConstant);
431
432
        if (!$this->hasMinimumRequiredParameters()) {
433
            throw new InvalidPayloadDataException();
434
        }
435
436
        return $this->getHttpClient()->post(
437
            $this->getUrl(),
438
            $this->isAsyncRequest
439
        );
440
    }
441
442
    /**
443
     * Build URL used to send to Google Analytics
444
     *
445
     * @return string
446
     */
447
    public function getUrl()
448
    {
449
        $prepareUrl = new PrepareUrl;
450
451
        return $prepareUrl->build(
452
            $this->getEndpoint(),
453
            $this->singleParameters,
0 ignored issues
show
Documentation introduced by
$this->singleParameters is of type array<integer,object<The...eters\SingleParameter>>, but the function expects a array<integer,object<The...twork\SingleParameter>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
454
            $this->compoundParametersCollections
0 ignored issues
show
Documentation introduced by
$this->compoundParametersCollections is of type array<integer,object<The...ndParameterCollection>>, but the function expects a array<integer,object<The...ndParameterCollection>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
455
        );
456
    }
457
458
    /**
459
     * Validates the minimum required parameters for every GA hit are being sent.
460
     *
461
     * @SuppressWarnings(PHPMD.LongVariable)
462
     *
463
     * @return bool
464
     */
465
    private function hasMinimumRequiredParameters()
466
    {
467
        $minimumRequiredParameters = [
468
            'v' => false,
469
            'tid' => false,
470
            'cid' => false,
471
            't' => false,
472
        ];
473
474
        foreach ($minimumRequiredParameters as $parameterName => $isParamPresent) {
475
            if (in_array($parameterName, array_keys($this->singleParameters))) {
476
                $minimumRequiredParameters[$parameterName] = true;
477
            }
478
        }
479
480
        return !in_array(false, $minimumRequiredParameters, true);
481
    }
482
483
    /**
484
     * Sets a parameter action to the value specified by the method call.
485
     *
486
     * @param $parameter
487
     * @param $action
488
     * @return $this
489
     */
490
    private function setParameterActionTo($parameter, $action)
491
    {
492
        $actionConstant = $this->getParameterClassConstant(
493
            'TheIconic\Tracking\GoogleAnalytics\Parameters\EnhancedEcommerce\\'
494
            . $parameter . 'Action::ACTION_' . strtoupper($action),
495
            $parameter . ' action ' . $action . ' does not exist, check spelling'
496
        );
497
498
        $function = 'set' . $parameter . 'Action';
499
500
        $this->$function($actionConstant);
501
502
        return $this;
503
    }
504
505
    /**
506
     * Gets a contant from a class dynamically.
507
     *
508
     * @param $constant
509
     * @param $exceptionMsg
510
     * @return mixed
511
     * @throws \BadMethodCallException
512
     */
513
    private function getParameterClassConstant($constant, $exceptionMsg)
514
    {
515
        if (defined($constant)) {
516
            return constant($constant);
517
        } else {
518
            throw new \BadMethodCallException($exceptionMsg);
519
        }
520
    }
521
522
    /**
523
     * Sets the value for a parameter.
524
     *
525
     * @param $methodName
526
     * @param array $methodArguments
527
     * @return $this
528
     * @throws \InvalidArgumentException
529
     */
530
    private function setParameter($methodName, array $methodArguments)
531
    {
532
        $parameterClass = substr($methodName, 3);
533
534
        $fullParameterClass = $this->getFullParameterClass($parameterClass, $methodName);
535
536
        $parameterIndex = $this->getIndexFromArguments($methodArguments);
537
538
        /** @var SingleParameter $parameterObject */
539
        $parameterObject = new $fullParameterClass($parameterIndex);
540
541
        if (!isset($methodArguments[0])) {
542
            throw new \InvalidArgumentException(
543
                'For Analytics object, you must specify a value to be set for ' . $methodName
544
            );
545
        } else {
546
            $parameterObject->setValue($methodArguments[0]);
547
        }
548
549
        $this->singleParameters[$parameterObject->getName()] = $parameterObject;
550
551
        return $this;
552
    }
553
554
    /**
555
     * Adds an item to a compund parameter collection.
556
     *
557
     * @SuppressWarnings(PHPMD.LongVariable)
558
     *
559
     * @param $methodName
560
     * @param array $methodArguments
561
     * @return $this
562
     * @throws \InvalidArgumentException
563
     */
564
    private function addItem($methodName, array $methodArguments)
565
    {
566
        $parameterClass = substr($methodName, 3);
567
568
        $fullParameterClass = $this->getFullParameterClass($parameterClass, $methodName);
569
570
        if (!isset($methodArguments[0])) {
571
            throw new \InvalidArgumentException(
572
                'You must specify a ' . $parameterClass . ' to be add for ' . $methodName
573
            );
574
        } else {
575
            $parameterObject = new $fullParameterClass($methodArguments[0]);
576
        }
577
578
        $collectionIndex = $this->getIndexFromArguments($methodArguments);
579
580
        if (isset($this->compoundParametersCollections[$parameterClass . $collectionIndex])) {
581
            $this->compoundParametersCollections[$parameterClass . $collectionIndex]->add($parameterObject);
582
        } else {
583
            $fullParameterCollectionClass = $fullParameterClass . 'Collection';
584
585
            /** @var CompoundParameterCollection $parameterObjectCollection */
586
            $parameterObjectCollection = new $fullParameterCollectionClass($collectionIndex);
587
588
            $parameterObjectCollection->add($parameterObject);
589
590
            $this->compoundParametersCollections[$parameterClass . $collectionIndex] = $parameterObjectCollection;
591
        }
592
593
        return $this;
594
    }
595
596
    /**
597
     * Gets the index value from the arguments.
598
     *
599
     * @param $methodArguments
600
     * @return string
601
     */
602
    private function getIndexFromArguments($methodArguments)
603
    {
604
        $index = '';
605
        if (isset($methodArguments[1]) && is_numeric($methodArguments[1])) {
606
            $index = $methodArguments[1];
607
        }
608
609
        return $index;
610
    }
611
612
    /**
613
     * Gets the fully qualified name for a parameter.
614
     *
615
     * @param $parameterClass
616
     * @param $methodName
617
     * @return string
618
     * @throws \BadMethodCallException
619
     */
620
    private function getFullParameterClass($parameterClass, $methodName)
621
    {
622
        if (empty($this->availableParameters[$parameterClass])) {
623
            throw new \BadMethodCallException('Method ' . $methodName . ' not defined for Analytics class');
624
        } else {
625
            return '\\TheIconic\\Tracking\\GoogleAnalytics\\Parameters\\' . $this->availableParameters[$parameterClass];
626
        }
627
    }
628
629
    /**
630
     * Routes the method call to the adequate private method.
631
     *
632
     * @param $methodName
633
     * @param array $methodArguments
634
     * @return $this|AnalyticsResponse
635
     * @throws \BadMethodCallException
636
     */
637
    public function __call($methodName, array $methodArguments)
638
    {
639
        $methodName = $this->fixTypos($methodName);
640
641
        if (preg_match('/^set(Product|Promotion)ActionTo(\w+)/', $methodName, $matches)) {
642
            return $this->setParameterActionTo($matches[1], $matches[2]);
643
        }
644
645
        if (preg_match('/^(set)(\w+)/', $methodName, $matches)) {
646
            return $this->setParameter($methodName, $methodArguments);
647
        }
648
649
        if (preg_match('/^(add)(\w+)/', $methodName, $matches)) {
650
            return $this->addItem($methodName, $methodArguments);
651
        }
652
653
        if (preg_match('/^(send)(\w+)/', $methodName, $matches)) {
654
            return $this->sendHit($methodName);
655
        }
656
657
        throw new \BadMethodCallException('Method ' . $methodName . ' not defined for Analytics class');
658
    }
659
660
    /**
661
     * Fix typos that went into releases, this way we ensure we don't break scripts in production.
662
     *
663
     * @param string $methodName
664
     * @return string
665
     */
666
    private function fixTypos($methodName)
667
    {
668
        // deprecated in v2, to be removed in v3
669
        if ($methodName === 'setUserTiminCategory') {
670
            $methodName = 'setUserTimingCategory';
671
        }
672
673
        return $methodName;
674
    }
675
}
676