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 (#13)
by
unknown
02:31
created

Amplitude::getUserId()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
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
     * Flag for if should save the last HTTP response for debugging purposes
63
     *
64
     * @var boolean True to enable saving the last response
65
     */
66
    protected $debugResponse = false;
67
68
    /**
69
     * Last response from logging event
70
     *
71
     * @var array|null
72
     */
73
    protected $lastHttpResponse;
74
75
    /**
76
     * Array of Amplitude instances
77
     *
78
     * @var \Zumba\Amplitude\Amplitude[]
79
     */
80
    private static $instances = [];
81
82
    /**
83
     * Singleton to get named instance
84
     *
85
     * Using this is optional, it depends on the use-case if it is better to use a singleton instance or just create
86
     * a new object directly.
87
     *
88
     * Useful if want to possibly send multiple events for the same user in a single page load, or even keep track
89
     * of multiple named instances, each could track to it's own api key and/or user/device ID.
90
     *
91
     * Each instance maintains it's own:
92
     * - API Key
93
     * - User ID
94
     * - Device ID
95
     * - User Properties
96
     * - Event Queue (if events are queued before the amplitude instance is initialized)
97
     * - Event object - for the next event that will be sent or queued
98
     * - Opt out status
99
     *
100
     * @param string $instanceName Optional, can use to maintain multiple singleton instances of amplitude, each with
101
     *   it's own API key set
102
     * @return \Zumba\Amplitude\Amplitude
103
     */
104
    public static function getInstance($instanceName = 'default')
105
    {
106
        if (empty(self::$instances[$instanceName])) {
107
            self::$instances[$instanceName] = new static();
108
        }
109
        return self::$instances[$instanceName];
110
    }
111
112
    /**
113
     * Constructor, optionally sets the api key
114
     *
115
     * @param string $apiKey
116
     */
117
    public function __construct($apiKey = null)
118
    {
119
        if (!empty($apiKey)) {
120
            $this->apiKey = (string)$apiKey;
121
        }
122
    }
123
124
    /**
125
     * Initialize amplitude
126
     *
127
     * This lets you set the api key, and optionally the user ID.
128
     *
129
     * @param string $apiKey Amplitude API key
130
     * @param string $userId
131
     * @return \Zumba\Amplitude\Amplitude
132
     */
133
    public function init($apiKey, $userId = null)
134
    {
135
        $this->apiKey = (string)$apiKey;
136
        if ($userId !== null) {
137
            $this->setUserId($userId);
138
        }
139
        return $this;
140
    }
141
142
    /**
143
     * Log any events that were queued before amplitude was initialized
144
     *
145
     * Note that api key, and either the user ID or device ID need to be set prior to calling this.
146
     *
147
     * @return \Zumba\Amplitude\Amplitude
148
     * @throws \LogicException
149
     */
150
    public function logQueuedEvents()
151
    {
152
        if (empty($this->queue)) {
153
            return $this;
154
        }
155
        foreach ($this->queue as $event) {
156
            $this->event = $event;
157
            $this->logEvent();
158
        }
159
        return $this->resetEvent()
160
            ->resetQueue();
161
    }
162
163
    /**
164
     * Clear out all events in the queue, without sending them to amplitude
165
     *
166
     * @return \Zumba\Amplitude\Amplitude
167
     */
168
    public function resetQueue()
169
    {
170
        $this->queue = [];
171
        return $this;
172
    }
173
174
    /**
175
     * Gets the event that will be used for the next event logged by call to logEvent() or queueEvent()
176
     *
177
     * You can also pass in an event or array of event properties.  If you pass in an event, it will be set as the
178
     * event to be used for the next call to queueEvent() or logEvent()
179
     *
180
     * @param null|array|\Zumba\Amplitude\Event Can pass in an event to set as the next event to run, or array to set
181
     *   properties on that event
182
     * @return \Zumba\Amplitude\Event
183
     */
184
    public function event($event = null)
185
    {
186
        if (!empty($event) && $event instanceof \Zumba\Amplitude\Event) {
187
            $this->event = $event;
188
        } elseif (empty($this->event)) {
189
            // Set the values that persist between tracking events
190
            $this->event = new Event();
191
        }
192
        if (!empty($event) && is_array($event)) {
193
            // Set properties on the event
194
            $this->event->set($event);
195
        }
196
        return $this->event;
197
    }
198
199
    /**
200
     * Resets the event currently in the process of being set up (what is returned by event())
201
     *
202
     * @return \Zumba\Amplitude\Amplitude
203
     */
204
    public function resetEvent()
205
    {
206
        $this->event = null;
207
        return $this;
208
    }
209
210
    /**
211
     * Log an event immediately
212
     *
213
     * Requires amplitude is already initialized and user ID or device ID is set.  If need to wait until amplitude
214
     * is initialized, use queueEvent() method instead.
215
     *
216
     * Can either pass in information to be logged, or can set up the Event object before hand, see the event()
217
     * method for more information
218
     *
219
     * @param string $eventType Required if not set on event object prior to calling this
220
     * @param array $eventProperties Optional, properties to set on event
221
     * @return \Zumba\Amplitude\Amplitude
222
     * @throws \LogicException Thorws exception if any of the requirments are not met, such as api key set
223
     */
224
    public function logEvent($eventType = '', array $eventProperties = [])
225
    {
226
        if ($this->optOut) {
227
            return $this;
228
        }
229
        // Sanity checking
230
        if (empty($this->apiKey)) {
231
            throw new \LogicException(static::EXCEPTION_MSG_NO_API_KEY);
232
        }
233
        $event = $this->event();
234
        $event->set($eventProperties);
235
        $event->eventType = $eventType ?: $event->eventType;
236
        // Set the persistent options on the event
237
        $this->setPersistentEventData();
238
239
        if (empty($event->eventType)) {
240
            throw new \LogicException(static::EXCEPTION_MSG_NO_EVENT_TYPE);
241
        }
242
        if (empty($event->userId) && empty($event->deviceId)) {
243
            throw new \LogicException(static::EXCEPTION_MSG_NO_USER_OR_DEVICE);
244
        }
245
246
        $this->sendEvent();
247
248
        // Reset the event for next call
249
        $this->resetEvent();
250
251
        return $this;
252
    }
253
254
    /**
255
     * Set the persistent data on the event object
256
     *
257
     * @return void
258
     */
259
    protected function setPersistentEventData()
260
    {
261
        $event = $this->event();
262
        if (!empty($this->userId)) {
263
            $event->userId = $this->userId;
264
        }
265
        if (!empty($this->deviceId)) {
266
            $event->deviceId = $this->deviceId;
267
        }
268
        if (!empty($this->userProperties)) {
269
            $event->setUserProperties($this->userProperties);
270
            $this->resetUserProperties();
271
        }
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.  Note that having
284
     * the userId or deviceId set on the event itself does not affect if it queues the event or not, only if set on
285
     * the Amplitude instance.
286
     *
287
     * Otherwise it will queue the event, and will be run after the amplitude instance is initialized and
288
     * logQueuedEvents() method is run
289
     *
290
     * @param string $eventType
291
     * @param array $eventProperties
292
     * @return \Zumba\Amplitude\Amplitude
293
     * @throws \LogicException
294
     */
295
    public function queueEvent($eventType = '', array $eventProperties = [])
296
    {
297
        if ($this->optOut) {
298
            return $this;
299
        }
300
        $event = $this->event();
301
        $event->set($eventProperties);
302
        $event->eventType = $eventType ?: $event->eventType;
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
     * Any set with this will take precedence over any set on the Event object
322
     *
323
     * @param string $userId
324
     * @return \Zumba\Amplitude\Amplitude
325
     */
326
    public function setUserId($userId)
327
    {
328
        $this->userId = (string)$userId;
329
        return $this;
330
    }
331
332
    /**
333
     * Set the device ID for future events logged
334
     *
335
     * Any set with this will take precedence over any set on the Event object
336
     *
337
     * @param string $deviceId
338
     * @return \Zumba\Amplitude\Amplitude
339
     */
340
    public function setDeviceId($deviceId)
341
    {
342
        $this->deviceId = (string)$deviceId;
343
        return $this;
344
    }
345
346
    /**
347
     * Set the user properties, will be sent with the next event sent to Amplitude
348
     *
349
     * Any set with this will take precedence over any set on the Event object
350
     *
351
     * If no events are logged, it will not get sent to Amplitude
352
     *
353
     * @param array $userProperties
354
     */
355
    public function setUserProperties(array $userProperties)
356
    {
357
        $this->userProperties = array_merge($this->userProperties, $userProperties);
358
        return $this;
359
    }
360
361
    /**
362
     * Resets user properties added with setUserProperties() if they have not already been sent in an event to Amplitude
363
     *
364
     * @return \Zumba\Amplitude\Amplitude
365
     */
366
    public function resetUserProperties()
367
    {
368
        $this->userProperties = [];
369
        return $this;
370
    }
371
372
    /**
373
     * Check if there are events in the queue that have not been sent
374
     *
375
     * @return boolean
376
     */
377
    public function hasQueuedEvents()
378
    {
379
        return !empty($this->queue);
380
    }
381
382
    /**
383
     * Resets all user information
384
     *
385
     * This resets the user ID, device ID previously set using setUserId or setDeviceId.
386
     *
387
     * If additional information was previously set using setUserProperties() method, and the event has not already
388
     * been sent to Amplitude, it will reset that information as well.
389
     *
390
     * Does not reset user information if set manually on an individual event in the queue.
391
     *
392
     * @return \Zumba\Amplitude\Amplitude
393
     */
394
    public function resetUser()
395
    {
396
        $this->setUserId(null);
397
        $this->setDeviceId(null);
398
        $this->resetUserProperties();
399
        return $this;
400
    }
401
402
    /**
403
     * Set opt out for the current user.
404
     *
405
     * If set to true, will not send any future events to amplitude for this amplitude instance.
406
     *
407
     * @param boolean $optOut
408
     * @return \Zumba\Amplitude\Amplitude
409
     */
410
    public function setOptOut($optOut)
411
    {
412
        $this->optOut = (bool)$optOut;
413
        return $this;
414
    }
415
416
    /**
417
     * Getter for currently set api key
418
     *
419
     * @return string|null
420
     */
421
    public function getApiKey()
422
    {
423
        return $this->apiKey;
424
    }
425
426
    /**
427
     * Getter for currently set user ID
428
     *
429
     * @return string|null
430
     */
431
    public function getUserId()
432
    {
433
        return $this->userId;
434
    }
435
436
    /**
437
     * Getter for currently set device ID
438
     *
439
     * @return string|null
440
     */
441
    public function getDeviceId()
442
    {
443
        return $this->deviceId;
444
    }
445
446
    /**
447
     * Getter for all currently set user properties, that will be automatically sent on next Amplitude event
448
     *
449
     * Once the properties have been sent in an Amplitude event, they will be cleared.
450
     *
451
     * @return array
452
     */
453
    public function getUserProperties()
454
    {
455
        return $this->userProperties;
456
    }
457
458
    /**
459
     * Get the current value for opt out.
460
     *
461
     * @return boolean
462
     */
463
    public function getOptOut()
464
    {
465
        return $this->optOut;
466
    }
467
468
    /**
469
     * Sets flag for debugging responses
470
     *
471
     * See getLastHttpResponse() for getting the last response
472
     *
473
     * @param boolean $debug If true, will keep track of last response from Amplitude for debugging purposes
474
     * @return \Zumba\Amplitude\Amplitude
475
     */
476
    public function setDebugResponse($debug)
477
    {
478
        $this->debugResponse = (bool)$debug;
479
        return $this;
480
    }
481
482
    /**
483
     * Gets current flag value for whether to record the last response from Amplitude when sending events
484
     *
485
     * @return boolean
486
     */
487
    public function getDebugResponse()
488
    {
489
        return $this->debugResponse;
490
    }
491
492
    /**
493
     * For debugging new connections - returns array with details of the last log, or null if no logs sent.
494
     *
495
     * Returned array will be in the format:
496
     * <code>
497
     * $lastHttpResponse = [
498
     *     'code' => 100, // HTTP Response Code
499
     *     'message' => 'success', // Response received
500
     *     'curl_error' => '...', // Only set if there was some error when attempting to send the request
501
     * ];
502
     * </code>
503
     *
504
     * @return array|null Returns null if debug response is disabled, or if no events sent to Amplitude yet
505
     */
506
    public function getLastHttpResponse()
507
    {
508
        return $this->lastHttpResponse;
509
    }
510
511
    /**
512
     * Send the event currently set in $this->event to amplitude
513
     *
514
     * Requres $this->event and $this->apiKey to be set, otherwise it throws an exception.
515
     *
516
     * @return void
517
     * @throws \InternalErrorException If event or api key not set
518
     */
519
    protected function sendEvent()
520
    {
521
        if (empty($this->event) || empty($this->apiKey)) {
522
            throw new \InternalErrorException('Event or api key not set, cannot send event');
523
        }
524
        $postFields = [
525
            'api_key' => $this->apiKey,
526
            'event' => json_encode($this->event),
527
        ];
528
        $ch = curl_init(static::AMPLITUDE_API_URL);
529
        if (!$ch) {
530
            return false;
531
        }
532
        curl_setopt($ch, \CURLOPT_POSTFIELDS, $postFields);
533
        // Always return instead of outputting response!
534
        curl_setopt($ch, \CURLOPT_RETURNTRANSFER, true);
535
        $response = curl_exec($ch);
536
        if ($this->debugResponse) {
537
            $this->lastHttpResponse = [
538
                'code' => curl_getinfo($ch, \CURLINFO_HTTP_CODE),
539
                'message' => $response,
540
            ];
541
            if ($response === false) {
542
                $this->lastHttpResponse['curl_error'] = curl_error($ch);
543
            }
544
        }
545
        curl_close($ch);
546
    }
547
}
548