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
Pull Request — master (#9)
by
unknown
02:23
created

Amplitude::logEvent()   C

Complexity

Conditions 13
Paths 98

Size

Total Lines 41
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 41
rs 5.1234
cc 13
eloc 24
nc 98
nop 2

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace Zumba\Amplitude;
3
4
class Amplitude
5
{
6
    const AMPLITUDE_API_URL = 'https://api.amplitude.com/httpapi';
7
8
    const EXCEPTION_MSG_NO_API_KEY = 'API Key is required to log an event';
9
    const EXCEPTION_MSG_NO_EVENT_TYPE = 'Event Type is required to log or queue an event';
10
    const EXCEPTION_MSG_NO_USER_OR_DEVICE = 'Either user_id or device_id required to log an event';
11
12
    /**
13
     * The API key to use for all events generated by this instance
14
     *
15
     * @var string
16
     */
17
    protected $apiKey;
18
19
    /**
20
     * The event that will be used for the next event being tracked
21
     *
22
     * @var \Zumba\Amplitude\Event
23
     */
24
    protected $event;
25
26
    /**
27
     * The user ID to use for events generated by this instance
28
     *
29
     * @var string
30
     */
31
    protected $userId;
32
33
    /**
34
     * The user data to set on the next event logged to Amplitude
35
     *
36
     * @var array
37
     */
38
    protected $userProperties = [];
39
40
    /**
41
     * The device ID to use for events generated by this instance
42
     *
43
     * @var string
44
     */
45
    protected $deviceId;
46
47
    /**
48
     * Queue of events, used to allow generating events that might happen prior to amplitude being fully initialized
49
     *
50
     * @var \Zumba\Amplitude\Event[]
51
     */
52
    protected $queue = [];
53
54
    /**
55
     * Flag for if user is opted out of tracking
56
     *
57
     * @var boolean
58
     */
59
    protected $optOut = false;
60
61
    /**
62
     * Array of Amplitude instances
63
     *
64
     * @var \Zumba\Amplitude\Amplitude[]
65
     */
66
    private static $instances = [];
67
68
    /**
69
     * Singleton to get named instance
70
     *
71
     * Using this is optional, it depends on the use-case if it is better to use a singleton instance or just create
72
     * a new object directly.
73
     *
74
     * Useful if want to possibly send multiple events for the same user in a single page load, or even keep track
75
     * of multiple named instances, each could track to it's own api key and/or user.
76
     *
77
     * Example:
78
     * <code>
79
     * // In user initialization section of app...
80
     * Zumba\Amplitude\Amplitude::getInstance()->init('APIKEY','[email protected]')
81
     *     ->addUserProperties(['name' => 'Johnny 5'])
82
     *     ->logQueuedEvents();
83
     *
84
     * // Elsewhere in your app, this could happen before OR after the above initialization...
85
     * // See queueEvent() for more info
86
     * Zumba\Amplitude\Amplitude::getInstance()->queueEvent(
87
     *     'VEHICLE CREATED EVENT',
88
     *     ['wheels' => '2', 'name' => 'bicycle']
89
     * );
90
     * </code>
91
     *
92
     * @param string $instanceName Optional, can use to maintain multiple singleton instances of amplitude
93
     * @return \Zumba\Amplitude\Amplitude
94
     */
95
    public static function getInstance($instanceName = 'default')
96
    {
97
        if (empty(self::$instances[$instanceName])) {
98
            self::$instances[$instanceName] = new static();
99
        }
100
        return self::$instances[$instanceName];
101
    }
102
103
    /**
104
     * Constructor, optionally sets the api key
105
     *
106
     * @param string $apiKey
107
     */
108
    public function __construct($apiKey = null)
109
    {
110
        if (!empty($apiKey)) {
111
            $this->apiKey = $apiKey;
112
        }
113
    }
114
115
    /**
116
     * Initialize amplitude
117
     *
118
     * This lets you set the api key, and optionally the user ID.
119
     *
120
     * @param string $apiKey Amplitude API key
121
     * @param string $userId
122
     * @return \Zumba\Amplitude\Amplitude
123
     */
124
    public function init($apiKey, $userId = null)
125
    {
126
        $this->apiKey = $apiKey;
127
        if ($userId !== null) {
128
            $this->setUserId($userId);
129
        }
130
        return $this;
131
    }
132
133
    /**
134
     * Log any events that were queued before amplitude was initialized
135
     *
136
     * Note that api key, and either the user ID or device ID need to be set prior to calling this.
137
     *
138
     * @return \Zumba\Amplitude\Amplitude
139
     * @throws \LogicException
140
     */
141
    public function logQueuedEvents()
142
    {
143
        if (empty($this->queue)) {
144
            return $this;
145
        }
146
        foreach ($this->queue as $event) {
147
            $this->event = $event;
148
            $this->logEvent();
149
        }
150
        return $this->resetEvent()
151
            ->resetQueue();
152
    }
153
154
    /**
155
     * Clear out all events in the queue, without sending them to amplitude
156
     *
157
     * @return \Zumba\Amplitude\Amplitude
158
     */
159
    public function resetQueue()
160
    {
161
        $this->queue = [];
162
        return $this;
163
    }
164
165
    /**
166
     * Gets the event that will be used for the next event logged by call to logEvent() or queueEvent()
167
     *
168
     * If this style suites your project, you can do something like this:
169
     *
170
     * <code>
171
     * $event = $amplitude->event();
172
     * // Set up event here...
173
     * $event->set('event_type', 'EVENT TYPE')
174
     *     ->set('custom property', 'Some Value');
175
     *
176
     * // Calling this will log the event we just set up
177
     * $amplitude->logEvent();
178
     * </code>
179
     *
180
     * That would be the equivelent of this:
181
     * <code>
182
     * $amplitude->logEvent('EVENT TYPE', ['custom property' => 'Some Value']);
183
     * </code>
184
     *
185
     * Note that either use above requires amplitude to be set up first with all the required things set (like api
186
     * key and either user ID or device ID).  You can replace logEvent with queueEvent if you may need to run it before
187
     * amplitude is fully initialized.
188
     *
189
     * You can also pass in an event to set as the next event to run.
190
     *
191
     * @param null|\Zumba\Amplitude\Event Can pass in an event to set as the next event to run
192
     * @return \Zumba\Amplitude\Event
193
     */
194
    public function event($event = null)
195
    {
196
        if (!empty($event) && $event instanceof \Zumba\Amplitude\Event) {
197
            $this->event = $event;
198
        } elseif (empty($this->event)) {
199
            // Set the values that persist between tracking events
200
            $this->event = new Event();
201
        }
202
        return $this->event;
203
    }
204
205
    /**
206
     * Resets the event currently in the process of being set up (what is returned by event())
207
     *
208
     * This could end up clearing user data set.
209
     *
210
     * @return \Zumba\Amplitude\Amplitude
211
     */
212
    public function resetEvent()
213
    {
214
        $this->event = null;
215
        return $this;
216
    }
217
218
    /**
219
     * Log an event immediately
220
     *
221
     * Requires amplitude is already initialized and user ID or device ID is set.  If need to wait until amplitude
222
     * is initialized, use queueEvent method instead.
223
     *
224
     * Can either pass in information to be logged, or can set up the event using OOP, see the event() method for more
225
     * information
226
     *
227
     * @param string $eventType Required if not set on event object prior to calling this
228
     * @param array $eventProperties Optional, properties to set on event
229
     * @return \Zumba\Amplitude\Amplitude
230
     * @throws \LogicException Thorws exception if any of the requirments are not met, such as api key set
231
     */
232
    public function logEvent($eventType = '', array $eventProperties = [])
233
    {
234
        if ($this->optOut) {
235
            return $this;
236
        }
237
        // Sanity checking
238
        if (empty($this->apiKey)) {
239
            throw new \LogicException(static::EXCEPTION_MSG_NO_API_KEY);
240
        }
241
        $event = $this->event();
242
        if (!empty($eventProperties)) {
243
            $event->set($eventProperties);
244
        }
245
        if (!empty($eventType)) {
246
            $event->eventType = $eventType;
247
        }
248
        if (!empty($this->userId) && empty($event->userId)) {
249
            $event->userId = $this->userId;
250
        }
251
        if (!empty($this->deviceId) && empty($event->deviceId)) {
252
            $event->deviceId = $this->deviceId;
253
        }
254
        if (!empty($this->userProperties)) {
255
            $event->addUserProperties($this->userProperties);
256
            $this->resetUserProperties();
257
        }
258
259
        if (empty($event->eventType)) {
260
            throw new \LogicException(static::EXCEPTION_MSG_NO_EVENT_TYPE);
261
        }
262
        if (empty($event->userId) && empty($event->deviceId)) {
263
            throw new \LogicException(static::EXCEPTION_MSG_NO_USER_OR_DEVICE);
264
        }
265
266
        $this->sendEvent();
267
268
        // Reset the event for next call
269
        $this->resetEvent();
270
271
        return $this;
272
    }
273
274
    /**
275
     * Log or queue the event, depending on if amplitude instance is already set up or not
276
     *
277
     * Note that this is an internal queue, the queue is lost between page loads.
278
     *
279
     * This functions identically to logEvent, with the exception that if Amplitude is not yet set up, it queues the
280
     * event to be logged later (during same page load).
281
     *
282
     * If the API key, and either user ID or device ID are already set in the amplitude instance, and there is not
283
     * already events in the queue that have not been run, this will log the event immediately.
284
     *
285
     * Otherwise it will queue the event, and will be run after the amplitude instance is initialized and
286
     * logQueuedEvents() method is run
287
     *
288
     * @param string $eventType
289
     * @param array $eventProperties
290
     * @return \Zumba\Amplitude\Amplitude
291
     * @throws \LogicException
292
     */
293
    public function queueEvent($eventType = '', array $eventProperties = [])
294
    {
295
        if ($this->optOut) {
296
            return $this;
297
        }
298
        $event = $this->event();
299
        $event->set($eventProperties);
300
        if (!empty($eventType)) {
301
            $event->eventType = $eventType;
302
        }
303
304
        // Sanity checking
305
        if (empty($event->eventType)) {
306
            throw new \LogicException(static::EXCEPTION_MSG_NO_EVENT_TYPE);
307
        }
308
        if (empty($this->queue) && !empty($this->apiKey) && (!empty($this->userId) || !empty($this->deviceId))) {
309
            // No need to queue, everything seems to be initialized already and queue has already been processed
310
            return $this->logEvent();
311
        }
312
        $this->queue[] = $event;
313
        $this->resetEvent();
314
315
        return $this;
316
    }
317
318
    /**
319
     * Set the user ID for future events logged
320
     *
321
     * Note that setting the user ID directly on an individual Event object will take precedence over one set with this
322
     * method.
323
     *
324
     * @param string $userId
325
     * @return \Zumba\Amplitude\Amplitude
326
     */
327
    public function setUserId($userId)
328
    {
329
        $this->userId = $userId;
330
        return $this;
331
    }
332
333
    /**
334
     * Set the device ID for future events logged
335
     *
336
     * Note that setting the device ID directly on an individual Event object will take precedence over one set with
337
     * this method.
338
     *
339
     * @param string $deviceId
340
     * @return \Zumba\Amplitude\Amplitude
341
     */
342
    public function setDeviceId($deviceId)
343
    {
344
        $this->deviceId = $deviceId;
345
        return $this;
346
    }
347
348
    /**
349
     * Add user properties, will be sent with the next event sent to Amplitude
350
     *
351
     * If user properties are added to the event directly, these will be added on top, so the properties set directly
352
     * on the Event object would take precedence.
353
     *
354
     * If this is called multiple times before an event is sent, later calls will only add to the array, it will not
355
     * overwrite values already set if no events have been sent yet.
356
     *
357
     * Note that if no events are logged after this point, it will not get sent to Amplitude
358
     *
359
     * @param array $userProperties
360
     */
361
    public function addUserProperties(array $userProperties)
362
    {
363
        $this->userProperties = $this->userProperties + $userProperties;
364
        return $this;
365
    }
366
367
    /**
368
     * Resets user properties added with addUserProperties() if they have not already been sent in an event to Amplitude
369
     *
370
     * @return \Zumba\Amplitude\Amplitude
371
     */
372
    public function resetUserProperties()
373
    {
374
        $this->userProperties = [];
375
        return $this;
376
    }
377
378
    /**
379
     * Check if there are events in the queue that have not been sent
380
     *
381
     * @return boolean
382
     */
383
    public function hasQueuedEvents()
384
    {
385
        return !empty($this->queue);
386
    }
387
388
    /**
389
     * Resets all user information
390
     *
391
     * This resets the user ID, device ID previously set using setUserId or setDeviceId.
392
     *
393
     * If additional information was previously set using addUserProperties() method, and the event has not already
394
     * been sent to Amplitude, it will reset that information as well.
395
     *
396
     * Does not reset user information if set manually on an individual event in the queue.
397
     *
398
     * @return \Zumba\Amplitude\Amplitude
399
     */
400
    public function resetUser()
401
    {
402
        $this->setUserId(null);
403
        $this->setDeviceId(null);
404
        $this->resetUserProperties();
405
        return $this;
406
    }
407
408
    /**
409
     * Set opt out for the current user.
410
     *
411
     * If set to true, will not send any future events to amplitude for this amplitude instance.
412
     *
413
     * @param boolean $optOut
414
     * @return \Zumba\Amplitude\Amplitude
415
     */
416
    public function setOptOut($optOut)
417
    {
418
        $this->optOut = (bool)$optOut;
419
        return $this;
420
    }
421
422
    /**
423
     * Getter for currently set api key
424
     *
425
     * @return string|null
426
     */
427
    public function getApiKey()
428
    {
429
        return $this->apiKey;
430
    }
431
432
    /**
433
     * Getter for currently set user ID
434
     *
435
     * @return string|null
436
     */
437
    public function getUserId()
438
    {
439
        return $this->userId;
440
    }
441
442
    /**
443
     * Getter for currently set device ID
444
     *
445
     * @return string|null
446
     */
447
    public function getDeviceId()
448
    {
449
        return $this->deviceId;
450
    }
451
452
    /**
453
     * Getter for all currently set user properties, that will be automatically sent on next Amplitude event
454
     *
455
     * Once the properties have been sent in an Amplitude event, they will be cleared.
456
     *
457
     * @return array
458
     */
459
    public function getUserProperties()
460
    {
461
        return $this->userProperties;
462
    }
463
464
    /**
465
     * Get the current value for opt out.
466
     *
467
     * @return boolean
468
     */
469
    public function getOptOut()
470
    {
471
        return $this->optOut;
472
    }
473
474
    /**
475
     * Send the event currently set in $this->event to amplitude
476
     *
477
     * Requres $this->event and $this->apiKey to be set, otherwise it throws an exception.
478
     *
479
     * @return integer|boolean HTTP Status code or boolean false if problem making connection
480
     * @throws \InternalErrorException If event or api key not set
481
     */
482
    protected function sendEvent()
483
    {
484
        if (empty($this->event) || empty($this->apiKey)) {
485
            throw new \InternalErrorException('Event or api key not set, cannot send event');
486
        }
487
        $postFields = [
488
            'api_key' => $this->apiKey,
489
            'event' => json_encode($this->event),
490
        ];
491
        $ch = curl_init(static::AMPLITUDE_API_URL);
492
        if (!$ch) {
493
            return false;
494
        }
495
        curl_setopt($ch, \CURLOPT_POSTFIELDS, $postFields);
496
        curl_exec($ch);
497
498
        $status = curl_getinfo($ch, \CURLINFO_HTTP_CODE);
499
        curl_close($ch);
500
        return (int)$status;
501
    }
502
}
503