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 — feature/release-2016-1 ( df00f4 )
by Jorge
04:36
created

Analytics::fixTypos()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 9
rs 9.6666
cc 2
eloc 4
nc 2
nop 1
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\Exception\InvalidPayloadDataException;
9
10
/**
11
 * Class Analytics
12
 *
13
 * The main interface for the clients, it relies heavily in magic methods exposing
14
 * an interface with method tags.
15
 *
16
 * General
17
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProtocolVersion($value)
18
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTrackingId($value)
19
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setAnonymizeIp($value)
20
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDataSource($value)
21
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setQueueTime($value)
22
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCacheBuster($value)
23
 *
24
 * User
25
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setClientId($value)
26
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserId($value)
27
 *
28
 * Session
29
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSessionControl($value)
30
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setIpOverride($value)
31
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserAgentOverride($value)
32
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGeographicalOverride($value)
33
 *
34
 * Traffic Sources
35
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentReferrer($value)
36
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignName($value)
37
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignSource($value)
38
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignMedium($value)
39
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignKeyword($value)
40
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignContent($value)
41
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCampaignId($value)
42
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGoogleAdwordsId($value)
43
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setGoogleDisplayAdsId($value)
44
 *
45
 * System Info
46
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenResolution($value)
47
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setViewportSize($value)
48
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentEncoding($value)
49
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenColors($value)
50
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserLanguage($value)
51
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setJavaEnabled($value)
52
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setFlashVersion($value)
53
 *
54
 * Hit
55
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setHitType($value)
56
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setNonInteractionHit($value)
57
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendPageview()
58
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendEvent()
59
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendScreenview()
60
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendTransaction()
61
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendItem()
62
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendSocial()
63
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendException()
64
 * @method \TheIconic\Tracking\GoogleAnalytics\AnalyticsResponse sendTiming()
65
 *
66
 * Content Information
67
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentLocationUrl($value)
68
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentHostName($value)
69
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentPath($value)
70
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDocumentTitle($value)
71
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setScreenName($value)
72
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setLinkId($value)
73
 *
74
 * App Tracking
75
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationName($value)
76
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationId($value)
77
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationVersion($value)
78
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setApplicationInstallerId($value)
79
 *
80
 * Event Tracking
81
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventCategory($value)
82
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventAction($value)
83
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventLabel($value)
84
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setEventValue($value)
85
 *
86
 * E-commerce
87
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemName($value)
88
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemPrice($value)
89
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemQuantity($value)
90
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemCode($value)
91
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setItemCategory($value)
92
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCurrencyCode($value)
93
 *
94
 * Enhanced E-Commerce
95
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTransactionId($value)
96
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setAffiliation($value)
97
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setRevenue($value)
98
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTax($value)
99
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setShipping($value)
100
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCouponCode($value)
101
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionList($value)
102
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCheckoutStep($value)
103
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCheckoutStepOption($value)
104
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics addProduct(array $productData)
105
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductAction($value)
106
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToDetail()
107
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToClick()
108
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToAdd()
109
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToRemove()
110
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToCheckout()
111
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToCheckoutOption()
112
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToPurchase()
113
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductActionToRefund()
114
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setProductImpressionListName($value, $index)
115
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics addProductImpression(array $productData, $index)
116
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics addPromotion(array $promotionData)
117
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionAction($value)
118
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionActionToClick()
119
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPromotionActionToView()
120
 *
121
 * Social Interactions
122
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialNetwork($value)
123
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialAction($value)
124
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setSocialActionTarget($value)
125
 *
126
 * Timing
127
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingCategory($value)
128
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingVariableName($value)
129
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingTime($value)
130
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setUserTimingLabel($value)
131
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPageLoadTime($value)
132
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDnsTime($value)
133
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setPageDownloadTime($value)
134
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setRedirectResponseTime($value)
135
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setTcpConnectTime($value)
136
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setServerResponseTime($value)
137
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setDomInteractiveTime($value)
138
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setContentLoadTime($value)
139
 *
140
 * Exceptions
141
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExceptionDescription($value)
142
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setIsExceptionFatal($value)
143
 *
144
 * Custom Dimension / Metrics
145
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCustomDimension($value, $index)
146
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setCustomMetric($value, $index)
147
 *
148
 * Content Grouping
149
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setContentGroup($value, $index)
150
 *
151
 * Content Experiments
152
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExperimentId($value)
153
 * @method \TheIconic\Tracking\GoogleAnalytics\Analytics setExperimentVariant($value)
154
 *
155
 *
156
 * @package TheIconic\Tracking\GoogleAnalytics
157
 */
158
class Analytics
159
{
160
    /**
161
     * URI scheme for the GA API.
162
     *
163
     * @var string
164
     */
165
    private $uriScheme = 'http';
166
167
    /**
168
     * Indicates if the request to GA will be asynchronous (non-blocking).
169
     *
170
     * @var boolean
171
     */
172
    private $isAsyncRequest = false;
173
174
    /**
175
     * Endpoint to connect to when sending data to GA.
176
     *
177
     * @var string
178
     */
179
    private $endpoint = '://www.google-analytics.com/collect';
180
181
    /**
182
     * Holds the single parameters added to the hit.
183
     *
184
     * @var SingleParameter[]
185
     */
186
    private $singleParameters = [];
187
188
    /**
189
     * Holds the compound parameters collections added to the hit.
190
     *
191
     * @var  CompoundParameterCollection[]
192
     */
193
    private $compoundParametersCollections = [];
194
195
    /**
196
     * Holds the HTTP client used to connect to GA.
197
     *
198
     * @var HttpClient
199
     */
200
    private $httpClient;
201
202
    /**
203
     * Initializes to a list of all the available parameters to be sent in a hit.
204
     *
205
     * @var array
206
     */
207
    private $availableParameters = [
208
        'ApplicationId' => 'AppTracking\\ApplicationId',
209
        'ApplicationInstallerId' => 'AppTracking\\ApplicationInstallerId',
210
        'ApplicationName' => 'AppTracking\\ApplicationName',
211
        'ApplicationVersion' => 'AppTracking\\ApplicationVersion',
212
        'ExperimentId' => 'ContentExperiments\\ExperimentId',
213
        'ExperimentVariant' => 'ContentExperiments\\ExperimentVariant',
214
        'ContentGroup' => 'ContentGrouping\\ContentGroup',
215
        'DocumentHostName' => 'ContentInformation\\DocumentHostName',
216
        'DocumentLocationUrl' => 'ContentInformation\\DocumentLocationUrl',
217
        'DocumentPath' => 'ContentInformation\\DocumentPath',
218
        'DocumentTitle' => 'ContentInformation\\DocumentTitle',
219
        'LinkId' => 'ContentInformation\\LinkId',
220
        'ScreenName' => 'ContentInformation\\ScreenName',
221
        'CustomDimension' => 'CustomDimensionsMetrics\\CustomDimension',
222
        'CustomMetric' => 'CustomDimensionsMetrics\\CustomMetric',
223
        'CurrencyCode' => 'Ecommerce\\CurrencyCode',
224
        'ItemCategory' => 'Ecommerce\\ItemCategory',
225
        'ItemCode' => 'Ecommerce\\ItemCode',
226
        'ItemName' => 'Ecommerce\\ItemName',
227
        'ItemPrice' => 'Ecommerce\\ItemPrice',
228
        'ItemQuantity' => 'Ecommerce\\ItemQuantity',
229
        'Affiliation' => 'EnhancedEcommerce\\Affiliation',
230
        'CheckoutStep' => 'EnhancedEcommerce\\CheckoutStep',
231
        'CheckoutStepOption' => 'EnhancedEcommerce\\CheckoutStepOption',
232
        'CouponCode' => 'EnhancedEcommerce\\CouponCode',
233
        'Product' => 'EnhancedEcommerce\\Product',
234
        'ProductAction' => 'EnhancedEcommerce\\ProductAction',
235
        'ProductActionList' => 'EnhancedEcommerce\\ProductActionList',
236
        'ProductCollection' => 'EnhancedEcommerce\\ProductCollection',
237
        'ProductImpression' => 'EnhancedEcommerce\\ProductImpression',
238
        'ProductImpressionCollection' => 'EnhancedEcommerce\\ProductImpressionCollection',
239
        'ProductImpressionListName' => 'EnhancedEcommerce\\ProductImpressionListName',
240
        'Promotion' => 'EnhancedEcommerce\\Promotion',
241
        'PromotionAction' => 'EnhancedEcommerce\\PromotionAction',
242
        'PromotionCollection' => 'EnhancedEcommerce\\PromotionCollection',
243
        'Revenue' => 'EnhancedEcommerce\\Revenue',
244
        'Shipping' => 'EnhancedEcommerce\\Shipping',
245
        'Tax' => 'EnhancedEcommerce\\Tax',
246
        'TransactionId' => 'EnhancedEcommerce\\TransactionId',
247
        'EventAction' => 'Event\\EventAction',
248
        'EventCategory' => 'Event\\EventCategory',
249
        'EventLabel' => 'Event\\EventLabel',
250
        'EventValue' => 'Event\\EventValue',
251
        'ExceptionDescription' => 'Exceptions\\ExceptionDescription',
252
        'IsExceptionFatal' => 'Exceptions\\IsExceptionFatal',
253
        'AnonymizeIp' => 'General\\AnonymizeIp',
254
        'CacheBuster' => 'General\\CacheBuster',
255
        'DataSource' => 'General\\DataSource',
256
        'ProtocolVersion' => 'General\\ProtocolVersion',
257
        'QueueTime' => 'General\\QueueTime',
258
        'TrackingId' => 'General\\TrackingId',
259
        'HitType' => 'Hit\\HitType',
260
        'NonInteractionHit' => 'Hit\\NonInteractionHit',
261
        'GeographicalOverride' => 'Session\\GeographicalOverride',
262
        'IpOverride' => 'Session\\IpOverride',
263
        'SessionControl' => 'Session\\SessionControl',
264
        'UserAgentOverride' => 'Session\\UserAgentOverride',
265
        'SocialAction' => 'SocialInteractions\\SocialAction',
266
        'SocialActionTarget' => 'SocialInteractions\\SocialActionTarget',
267
        'SocialNetwork' => 'SocialInteractions\\SocialNetwork',
268
        'DocumentEncoding' => 'SystemInfo\\DocumentEncoding',
269
        'FlashVersion' => 'SystemInfo\\FlashVersion',
270
        'JavaEnabled' => 'SystemInfo\\JavaEnabled',
271
        'ScreenColors' => 'SystemInfo\\ScreenColors',
272
        'ScreenResolution' => 'SystemInfo\\ScreenResolution',
273
        'UserLanguage' => 'SystemInfo\\UserLanguage',
274
        'ViewportSize' => 'SystemInfo\\ViewportSize',
275
        'ContentLoadTime' => 'Timing\\ContentLoadTime',
276
        'DnsTime' => 'Timing\\DnsTime',
277
        'DomInteractiveTime' => 'Timing\\DomInteractiveTime',
278
        'PageDownloadTime' => 'Timing\\PageDownloadTime',
279
        'PageLoadTime' => 'Timing\\PageLoadTime',
280
        'RedirectResponseTime' => 'Timing\\RedirectResponseTime',
281
        'ServerResponseTime' => 'Timing\\ServerResponseTime',
282
        'TcpConnectTime' => 'Timing\\TcpConnectTime',
283
        'UserTimingCategory' => 'Timing\\UserTimingCategory',
284
        'UserTimingLabel' => 'Timing\\UserTimingLabel',
285
        'UserTimingTime' => 'Timing\\UserTimingTime',
286
        'UserTimingVariableName' => 'Timing\\UserTimingVariableName',
287
        'CampaignContent' => 'TrafficSources\\CampaignContent',
288
        'CampaignId' => 'TrafficSources\\CampaignId',
289
        'CampaignKeyword' => 'TrafficSources\\CampaignKeyword',
290
        'CampaignMedium' => 'TrafficSources\\CampaignMedium',
291
        'CampaignName' => 'TrafficSources\\CampaignName',
292
        'CampaignSource' => 'TrafficSources\\CampaignSource',
293
        'DocumentReferrer' => 'TrafficSources\\DocumentReferrer',
294
        'GoogleAdwordsId' => 'TrafficSources\\GoogleAdwordsId',
295
        'GoogleDisplayAdsId' => 'TrafficSources\\GoogleDisplayAdsId',
296
        'ClientId' => 'User\\ClientId',
297
        'UserId' => 'User\\UserId',
298
    ];
299
300
    /**
301
     * When passed with an argument of TRUE, it will send the hit using HTTPS instead of plain HTTP.
302
     * It parses the available parameters.
303
     *
304
     * @param bool $isSsl
305
     * @throws \InvalidArgumentException
306
     */
307
    public function __construct($isSsl = false)
308
    {
309
        if (!is_bool($isSsl)) {
310
            throw new \InvalidArgumentException('First constructor argument "isSSL" must be boolean');
311
        }
312
313
        if ($isSsl) {
314
            $this->uriScheme .= 's';
315
            $this->endpoint = str_replace('www', 'ssl', $this->endpoint);
316
        }
317
    }
318
319
    /**
320
     * Sets a request to be either synchronous or asynchronous (non-blocking).
321
     *
322
     * @param boolean $isAsyncRequest
323
     * @return $this
324
     */
325
    public function setAsyncRequest($isAsyncRequest)
326
    {
327
        $this->isAsyncRequest = $isAsyncRequest;
328
329
        return $this;
330
    }
331
332
    /**
333
     * Makes the request to GA asynchronous (non-blocking).
334
     *
335
     * @deprecated Use setAsyncRequest(boolean $isAsyncRequest) instead. To be removed in next major version.
336
     *
337
     * @return $this
338
     */
339
    public function makeNonBlocking()
340
    {
341
        $this->isAsyncRequest = true;
342
343
        return $this;
344
    }
345
346
    /**
347
     * Sets the HttpClient.
348
     *
349
     * @param HttpClient $httpClient
350
     * @return $this
351
     */
352
    public function setHttpClient(HttpClient $httpClient)
353
    {
354
        $this->httpClient = $httpClient;
355
356
        return $this;
357
    }
358
359
    /**
360
     * Gets the HttpClient.
361
     *
362
     * @return HttpClient
363
     */
364
    private function getHttpClient()
365
    {
366
        if ($this->httpClient === null) {
367
            // @codeCoverageIgnoreStart
368
            $this->setHttpClient(new HttpClient());
369
        }
370
        // @codeCoverageIgnoreEnd
371
372
        return $this->httpClient;
373
    }
374
375
    /**
376
     * Gets the full endpoint to GA.
377
     *
378
     * @return string
379
     */
380
    private function getEndpoint()
381
    {
382
        return $this->uriScheme . $this->endpoint;
383
    }
384
385
    /**
386
     * Sends a hit to GA. The hit will contain in the payload all the parameters added before.
387
     *
388
     * @param $methodName
389
     * @return AnalyticsResponse
390
     * @throws Exception\InvalidPayloadDataException
391
     */
392
    private function sendHit($methodName)
393
    {
394
        $hitType = strtoupper(substr($methodName, 4));
395
396
        $hitConstant = $this->getParameterClassConstant(
397
            'TheIconic\Tracking\GoogleAnalytics\Parameters\Hit\HitType::HIT_TYPE_' . $hitType,
398
            'Hit type ' . $hitType . ' is not defined, check spelling'
399
        );
400
401
        $this->setHitType($hitConstant);
402
403
        if (!$this->hasMinimumRequiredParameters()) {
404
            throw new InvalidPayloadDataException();
405
        }
406
407
        return $this->getHttpClient()->post(
408
            $this->getEndpoint(),
409
            $this->singleParameters,
410
            $this->compoundParametersCollections,
411
            $this->isAsyncRequest
412
        );
413
    }
414
415
    /**
416
     * Validates the minimum required parameters for every GA hit are being sent.
417
     *
418
     * @SuppressWarnings(PHPMD.LongVariable)
419
     *
420
     * @return bool
421
     */
422
    private function hasMinimumRequiredParameters()
423
    {
424
        $minimumRequiredParameters = [
425
            'v' => false,
426
            'tid' => false,
427
            'cid' => false,
428
            't' => false,
429
        ];
430
431
        foreach ($minimumRequiredParameters as $parameterName => $isParamPresent) {
432
            if (in_array($parameterName, array_keys($this->singleParameters))) {
433
                $minimumRequiredParameters[$parameterName] = true;
434
            }
435
        }
436
437
        return !in_array(false, $minimumRequiredParameters, true);
438
    }
439
440
    /**
441
     * Sets a parameter action to the value specified by the method call.
442
     *
443
     * @param $parameter
444
     * @param $action
445
     * @return $this
446
     */
447
    private function setParameterActionTo($parameter, $action)
448
    {
449
        $actionConstant = $this->getParameterClassConstant(
450
            'TheIconic\Tracking\GoogleAnalytics\Parameters\EnhancedEcommerce\\'
451
            . $parameter . 'Action::ACTION_' . strtoupper($action),
452
            $parameter . ' action ' . $action . ' does not exist, check spelling'
453
        );
454
455
        $function = 'set' . $parameter . 'Action';
456
457
        $this->$function($actionConstant);
458
459
        return $this;
460
    }
461
462
    /**
463
     * Gets a contant from a class dynamically.
464
     *
465
     * @param $constant
466
     * @param $exceptionMsg
467
     * @return mixed
468
     * @throws \BadMethodCallException
469
     */
470
    private function getParameterClassConstant($constant, $exceptionMsg)
471
    {
472
        if (defined($constant)) {
473
            return constant($constant);
474
        } else {
475
            throw new \BadMethodCallException($exceptionMsg);
476
        }
477
    }
478
479
    /**
480
     * Sets the value for a parameter.
481
     *
482
     * @param $methodName
483
     * @param array $methodArguments
484
     * @return $this
485
     * @throws \InvalidArgumentException
486
     */
487
    private function setParameter($methodName, array $methodArguments)
488
    {
489
        $parameterClass = substr($methodName, 3);
490
491
        $fullParameterClass = $this->getFullParameterClass($parameterClass, $methodName);
492
493
        $parameterIndex = $this->getIndexFromArguments($methodArguments);
494
495
        /** @var SingleParameter $parameterObject */
496
        $parameterObject = new $fullParameterClass($parameterIndex);
497
498
        if (!isset($methodArguments[0])) {
499
            throw new \InvalidArgumentException(
500
                'For Analytics object, you must specify a value to be set for ' . $methodName
501
            );
502
        } else {
503
            $parameterObject->setValue($methodArguments[0]);
504
        }
505
506
        $this->singleParameters[$parameterObject->getName()] = $parameterObject;
507
508
        return $this;
509
    }
510
511
    /**
512
     * Adds an item to a compund parameter collection.
513
     *
514
     * @SuppressWarnings(PHPMD.LongVariable)
515
     *
516
     * @param $methodName
517
     * @param array $methodArguments
518
     * @return $this
519
     * @throws \InvalidArgumentException
520
     */
521
    private function addItem($methodName, array $methodArguments)
522
    {
523
        $parameterClass = substr($methodName, 3);
524
525
        $fullParameterClass = $this->getFullParameterClass($parameterClass, $methodName);
526
527
        if (!isset($methodArguments[0])) {
528
            throw new \InvalidArgumentException(
529
                'You must specify a ' . $parameterClass . ' to be add for ' . $methodName
530
            );
531
        } else {
532
            $parameterObject = new $fullParameterClass($methodArguments[0]);
533
        }
534
535
        $collectionIndex = $this->getIndexFromArguments($methodArguments);
536
537
        if (isset($this->compoundParametersCollections[$parameterClass . $collectionIndex])) {
538
            $this->compoundParametersCollections[$parameterClass . $collectionIndex]->add($parameterObject);
539
        } else {
540
            $fullParameterCollectionClass = $fullParameterClass . 'Collection';
541
542
            /** @var CompoundParameterCollection $parameterObjectCollection */
543
            $parameterObjectCollection = new $fullParameterCollectionClass($collectionIndex);
544
545
            $parameterObjectCollection->add($parameterObject);
546
547
            $this->compoundParametersCollections[$parameterClass . $collectionIndex] = $parameterObjectCollection;
548
        }
549
550
        return $this;
551
    }
552
553
    /**
554
     * Gets the index value from the arguments.
555
     *
556
     * @param $methodArguments
557
     * @return string
558
     */
559
    private function getIndexFromArguments($methodArguments)
560
    {
561
        $index = '';
562
        if (isset($methodArguments[1]) && is_numeric($methodArguments[1])) {
563
            $index = $methodArguments[1];
564
        }
565
566
        return $index;
567
    }
568
569
    /**
570
     * Gets the fully qualified name for a parameter.
571
     *
572
     * @param $parameterClass
573
     * @param $methodName
574
     * @return string
575
     * @throws \BadMethodCallException
576
     */
577
    private function getFullParameterClass($parameterClass, $methodName)
578
    {
579
        if (empty($this->availableParameters[$parameterClass])) {
580
            throw new \BadMethodCallException('Method ' . $methodName . ' not defined for Analytics class');
581
        } else {
582
            return '\\TheIconic\\Tracking\\GoogleAnalytics\\Parameters\\' . $this->availableParameters[$parameterClass];
583
        }
584
    }
585
586
    /**
587
     * Routes the method call to the adequate private method.
588
     *
589
     * @param $methodName
590
     * @param array $methodArguments
591
     * @return $this|AnalyticsResponse
592
     * @throws \BadMethodCallException
593
     */
594
    public function __call($methodName, array $methodArguments)
595
    {
596
        $methodName = $this->fixTypos($methodName);
597
598
        if (preg_match('/^set(Product|Promotion)ActionTo(\w+)/', $methodName, $matches)) {
599
            return $this->setParameterActionTo($matches[1], $matches[2]);
600
        }
601
602
        if (preg_match('/^(set)(\w+)/', $methodName, $matches)) {
603
            return $this->setParameter($methodName, $methodArguments);
604
        }
605
606
        if (preg_match('/^(add)(\w+)/', $methodName, $matches)) {
607
            return $this->addItem($methodName, $methodArguments);
608
        }
609
610
        if (preg_match('/^(send)(\w+)/', $methodName, $matches)) {
611
            return $this->sendHit($methodName);
612
        }
613
614
        throw new \BadMethodCallException('Method ' . $methodName . ' not defined for Analytics class');
615
    }
616
617
    /**
618
     * Fix typos that went into releases, this way we ensure we don't break scripts in production.
619
     *
620
     * @param string $methodName
621
     * @return string
622
     */
623
    private function fixTypos($methodName)
624
    {
625
        // deprecated in v2, to be removed in v3
626
        if ($methodName === 'setUserTiminCategory') {
627
            $methodName = 'setUserTimingCategory';
628
        }
629
630
        return $methodName;
631
    }
632
}
633