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 ( 922c18...c07429 )
by Juan
8s
created

Amplitude::getUserProperties()   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
     * 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
     *     ->setUserProperties(['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|array|\Zumba\Amplitude\Event Can pass in an event to set as the next event to run, or array to set
192
     *   properties on that event
193
     * @return \Zumba\Amplitude\Event
194
     */
195
    public function event($event = null)
196
    {
197
        if (!empty($event) && $event instanceof \Zumba\Amplitude\Event) {
198
            $this->event = $event;
199
        } elseif (empty($this->event)) {
200
            // Set the values that persist between tracking events
201
            $this->event = new Event();
202
        }
203
        if (!empty($event) && is_array($event)) {
204
            // Set properties on the event
205
            $this->event->set($event);
206
        }
207
        return $this->event;
208
    }
209
210
    /**
211
     * Resets the event currently in the process of being set up (what is returned by event())
212
     *
213
     * This could end up clearing user data set.
214
     *
215
     * @return \Zumba\Amplitude\Amplitude
216
     */
217
    public function resetEvent()
218
    {
219
        $this->event = null;
220
        return $this;
221
    }
222
223
    /**
224
     * Log an event immediately
225
     *
226
     * Requires amplitude is already initialized and user ID or device ID is set.  If need to wait until amplitude
227
     * is initialized, use queueEvent method instead.
228
     *
229
     * Can either pass in information to be logged, or can set up the event using OOP, see the event() method for more
230
     * information
231
     *
232
     * @param string $eventType Required if not set on event object prior to calling this
233
     * @param array $eventProperties Optional, properties to set on event
234
     * @return \Zumba\Amplitude\Amplitude
235
     * @throws \LogicException Thorws exception if any of the requirments are not met, such as api key set
236
     */
237
    public function logEvent($eventType = '', array $eventProperties = [])
238
    {
239
        if ($this->optOut) {
240
            return $this;
241
        }
242
        // Sanity checking
243
        if (empty($this->apiKey)) {
244
            throw new \LogicException(static::EXCEPTION_MSG_NO_API_KEY);
245
        }
246
        $event = $this->event();
247
        if (!empty($eventProperties)) {
248
            $event->set($eventProperties);
249
        }
250
        if (!empty($eventType)) {
251
            $event->eventType = $eventType;
252
        }
253
        if (!empty($this->userId) && empty($event->userId)) {
254
            $event->userId = $this->userId;
255
        }
256
        if (!empty($this->deviceId) && empty($event->deviceId)) {
257
            $event->deviceId = $this->deviceId;
258
        }
259
        if (!empty($this->userProperties)) {
260
            $event->setUserProperties($this->userProperties);
261
            $this->resetUserProperties();
262
        }
263
264
        if (empty($event->eventType)) {
265
            throw new \LogicException(static::EXCEPTION_MSG_NO_EVENT_TYPE);
266
        }
267
        if (empty($event->userId) && empty($event->deviceId)) {
268
            throw new \LogicException(static::EXCEPTION_MSG_NO_USER_OR_DEVICE);
269
        }
270
271
        $this->sendEvent();
272
273
        // Reset the event for next call
274
        $this->resetEvent();
275
276
        return $this;
277
    }
278
279
    /**
280
     * Log or queue the event, depending on if amplitude instance is already set up or not
281
     *
282
     * Note that this is an internal queue, the queue is lost between page loads.
283
     *
284
     * This functions identically to logEvent, with the exception that if Amplitude is not yet set up, it queues the
285
     * event to be logged later (during same page load).
286
     *
287
     * If the API key, and either user ID or device ID are already set in the amplitude instance, and there is not
288
     * already events in the queue that have not been run, this will log the event immediately.
289
     *
290
     * Otherwise it will queue the event, and will be run after the amplitude instance is initialized and
291
     * logQueuedEvents() method is run
292
     *
293
     * @param string $eventType
294
     * @param array $eventProperties
295
     * @return \Zumba\Amplitude\Amplitude
296
     * @throws \LogicException
297
     */
298
    public function queueEvent($eventType = '', array $eventProperties = [])
299
    {
300
        if ($this->optOut) {
301
            return $this;
302
        }
303
        $event = $this->event();
304
        $event->set($eventProperties);
305
        if (!empty($eventType)) {
306
            $event->eventType = $eventType;
307
        }
308
309
        // Sanity checking
310
        if (empty($event->eventType)) {
311
            throw new \LogicException(static::EXCEPTION_MSG_NO_EVENT_TYPE);
312
        }
313
        if (empty($this->queue) && !empty($this->apiKey) && (!empty($this->userId) || !empty($this->deviceId))) {
314
            // No need to queue, everything seems to be initialized already and queue has already been processed
315
            return $this->logEvent();
316
        }
317
        $this->queue[] = $event;
318
        $this->resetEvent();
319
320
        return $this;
321
    }
322
323
    /**
324
     * Set the user ID for future events logged
325
     *
326
     * Note that setting the user ID directly on an individual Event object will take precedence over one set with this
327
     * method.
328
     *
329
     * @param string $userId
330
     * @return \Zumba\Amplitude\Amplitude
331
     */
332
    public function setUserId($userId)
333
    {
334
        $this->userId = $userId;
335
        return $this;
336
    }
337
338
    /**
339
     * Set the device ID for future events logged
340
     *
341
     * Note that setting the device ID directly on an individual Event object will take precedence over one set with
342
     * this method.
343
     *
344
     * @param string $deviceId
345
     * @return \Zumba\Amplitude\Amplitude
346
     */
347
    public function setDeviceId($deviceId)
348
    {
349
        $this->deviceId = $deviceId;
350
        return $this;
351
    }
352
353
    /**
354
     * Set the user properties, will be sent with the next event sent to Amplitude
355
     *
356
     * Any set with this will take precedence over any set on the Event object
357
     *
358
     * If no events are logged, it will not get sent to Amplitude
359
     *
360
     * @param array $userProperties
361
     */
362
    public function setUserProperties(array $userProperties)
363
    {
364
        $this->userProperties = array_merge($this->userProperties, $userProperties);
365
        return $this;
366
    }
367
368
    /**
369
     * Resets user properties added with setUserProperties() if they have not already been sent in an event to Amplitude
370
     *
371
     * @return \Zumba\Amplitude\Amplitude
372
     */
373
    public function resetUserProperties()
374
    {
375
        $this->userProperties = [];
376
        return $this;
377
    }
378
379
    /**
380
     * Check if there are events in the queue that have not been sent
381
     *
382
     * @return boolean
383
     */
384
    public function hasQueuedEvents()
385
    {
386
        return !empty($this->queue);
387
    }
388
389
    /**
390
     * Resets all user information
391
     *
392
     * This resets the user ID, device ID previously set using setUserId or setDeviceId.
393
     *
394
     * If additional information was previously set using setUserProperties() method, and the event has not already
395
     * been sent to Amplitude, it will reset that information as well.
396
     *
397
     * Does not reset user information if set manually on an individual event in the queue.
398
     *
399
     * @return \Zumba\Amplitude\Amplitude
400
     */
401
    public function resetUser()
402
    {
403
        $this->setUserId(null);
404
        $this->setDeviceId(null);
405
        $this->resetUserProperties();
406
        return $this;
407
    }
408
409
    /**
410
     * Set opt out for the current user.
411
     *
412
     * If set to true, will not send any future events to amplitude for this amplitude instance.
413
     *
414
     * @param boolean $optOut
415
     * @return \Zumba\Amplitude\Amplitude
416
     */
417
    public function setOptOut($optOut)
418
    {
419
        $this->optOut = (bool)$optOut;
420
        return $this;
421
    }
422
423
    /**
424
     * Getter for currently set api key
425
     *
426
     * @return string|null
427
     */
428
    public function getApiKey()
429
    {
430
        return $this->apiKey;
431
    }
432
433
    /**
434
     * Getter for currently set user ID
435
     *
436
     * @return string|null
437
     */
438
    public function getUserId()
439
    {
440
        return $this->userId;
441
    }
442
443
    /**
444
     * Getter for currently set device ID
445
     *
446
     * @return string|null
447
     */
448
    public function getDeviceId()
449
    {
450
        return $this->deviceId;
451
    }
452
453
    /**
454
     * Getter for all currently set user properties, that will be automatically sent on next Amplitude event
455
     *
456
     * Once the properties have been sent in an Amplitude event, they will be cleared.
457
     *
458
     * @return array
459
     */
460
    public function getUserProperties()
461
    {
462
        return $this->userProperties;
463
    }
464
465
    /**
466
     * Get the current value for opt out.
467
     *
468
     * @return boolean
469
     */
470
    public function getOptOut()
471
    {
472
        return $this->optOut;
473
    }
474
475
    /**
476
     * Send the event currently set in $this->event to amplitude
477
     *
478
     * Requres $this->event and $this->apiKey to be set, otherwise it throws an exception.
479
     *
480
     * @return integer|boolean HTTP Status code or boolean false if problem making connection
481
     * @throws \InternalErrorException If event or api key not set
482
     */
483
    protected function sendEvent()
484
    {
485
        if (empty($this->event) || empty($this->apiKey)) {
486
            throw new \InternalErrorException('Event or api key not set, cannot send event');
487
        }
488
        $postFields = [
489
            'api_key' => $this->apiKey,
490
            'event' => json_encode($this->event),
491
        ];
492
        $ch = curl_init(static::AMPLITUDE_API_URL);
493
        if (!$ch) {
494
            return false;
495
        }
496
        curl_setopt($ch, \CURLOPT_POSTFIELDS, $postFields);
497
        curl_exec($ch);
498
499
        $status = curl_getinfo($ch, \CURLINFO_HTTP_CODE);
500
        curl_close($ch);
501
        return (int)$status;
502
    }
503
}
504