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 ( c07429...94f336 )
by Juan
9s
created

Amplitude::setPersistentEventData()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 14
rs 9.2
cc 4
eloc 9
nc 8
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/device ID.
76
     *
77
     * Each instance maintains it's own:
78
     * - API Key
79
     * - User ID
80
     * - Device ID
81
     * - User Properties
82
     * - Event Queue (if events are queued before the amplitude instance is initialized)
83
     * - Event object - for the next event that will be sent or queued
84
     * - Opt out status
85
     *
86
     * @param string $instanceName Optional, can use to maintain multiple singleton instances of amplitude, each with
87
     *   it's own API key set
88
     * @return \Zumba\Amplitude\Amplitude
89
     */
90
    public static function getInstance($instanceName = 'default')
91
    {
92
        if (empty(self::$instances[$instanceName])) {
93
            self::$instances[$instanceName] = new static();
94
        }
95
        return self::$instances[$instanceName];
96
    }
97
98
    /**
99
     * Constructor, optionally sets the api key
100
     *
101
     * @param string $apiKey
102
     */
103
    public function __construct($apiKey = null)
104
    {
105
        if (!empty($apiKey)) {
106
            $this->apiKey = (string)$apiKey;
107
        }
108
    }
109
110
    /**
111
     * Initialize amplitude
112
     *
113
     * This lets you set the api key, and optionally the user ID.
114
     *
115
     * @param string $apiKey Amplitude API key
116
     * @param string $userId
117
     * @return \Zumba\Amplitude\Amplitude
118
     */
119
    public function init($apiKey, $userId = null)
120
    {
121
        $this->apiKey = (string)$apiKey;
122
        if ($userId !== null) {
123
            $this->setUserId($userId);
124
        }
125
        return $this;
126
    }
127
128
    /**
129
     * Log any events that were queued before amplitude was initialized
130
     *
131
     * Note that api key, and either the user ID or device ID need to be set prior to calling this.
132
     *
133
     * @return \Zumba\Amplitude\Amplitude
134
     * @throws \LogicException
135
     */
136
    public function logQueuedEvents()
137
    {
138
        if (empty($this->queue)) {
139
            return $this;
140
        }
141
        foreach ($this->queue as $event) {
142
            $this->event = $event;
143
            $this->logEvent();
144
        }
145
        return $this->resetEvent()
146
            ->resetQueue();
147
    }
148
149
    /**
150
     * Clear out all events in the queue, without sending them to amplitude
151
     *
152
     * @return \Zumba\Amplitude\Amplitude
153
     */
154
    public function resetQueue()
155
    {
156
        $this->queue = [];
157
        return $this;
158
    }
159
160
    /**
161
     * Gets the event that will be used for the next event logged by call to logEvent() or queueEvent()
162
     *
163
     * You can also pass in an event or array of event properties.  If you pass in an event, it will be set as the
164
     * event to be used for the next call to queueEvent() or logEvent()
165
     *
166
     * @param null|array|\Zumba\Amplitude\Event Can pass in an event to set as the next event to run, or array to set
167
     *   properties on that event
168
     * @return \Zumba\Amplitude\Event
169
     */
170
    public function event($event = null)
171
    {
172
        if (!empty($event) && $event instanceof \Zumba\Amplitude\Event) {
173
            $this->event = $event;
174
        } elseif (empty($this->event)) {
175
            // Set the values that persist between tracking events
176
            $this->event = new Event();
177
        }
178
        if (!empty($event) && is_array($event)) {
179
            // Set properties on the event
180
            $this->event->set($event);
181
        }
182
        return $this->event;
183
    }
184
185
    /**
186
     * Resets the event currently in the process of being set up (what is returned by event())
187
     *
188
     * @return \Zumba\Amplitude\Amplitude
189
     */
190
    public function resetEvent()
191
    {
192
        $this->event = null;
193
        return $this;
194
    }
195
196
    /**
197
     * Log an event immediately
198
     *
199
     * Requires amplitude is already initialized and user ID or device ID is set.  If need to wait until amplitude
200
     * is initialized, use queueEvent() method instead.
201
     *
202
     * Can either pass in information to be logged, or can set up the Event object before hand, see the event()
203
     * method for more information
204
     *
205
     * @param string $eventType Required if not set on event object prior to calling this
206
     * @param array $eventProperties Optional, properties to set on event
207
     * @return \Zumba\Amplitude\Amplitude
208
     * @throws \LogicException Thorws exception if any of the requirments are not met, such as api key set
209
     */
210
    public function logEvent($eventType = '', array $eventProperties = [])
211
    {
212
        if ($this->optOut) {
213
            return $this;
214
        }
215
        // Sanity checking
216
        if (empty($this->apiKey)) {
217
            throw new \LogicException(static::EXCEPTION_MSG_NO_API_KEY);
218
        }
219
        $event = $this->event();
220
        $event->set($eventProperties);
221
        $event->eventType = $eventType ?: $event->eventType;
222
        // Set the persistent options on the event
223
        $this->setPersistentEventData();
224
225
        if (empty($event->eventType)) {
226
            throw new \LogicException(static::EXCEPTION_MSG_NO_EVENT_TYPE);
227
        }
228
        if (empty($event->userId) && empty($event->deviceId)) {
229
            throw new \LogicException(static::EXCEPTION_MSG_NO_USER_OR_DEVICE);
230
        }
231
232
        $this->sendEvent();
233
234
        // Reset the event for next call
235
        $this->resetEvent();
236
237
        return $this;
238
    }
239
240
    /**
241
     * Set the persistent data on the event object
242
     *
243
     * @return void
244
     */
245
    protected function setPersistentEventData()
246
    {
247
        $event = $this->event();
248
        if (!empty($this->userId)) {
249
            $event->userId = $this->userId;
250
        }
251
        if (!empty($this->deviceId)) {
252
            $event->deviceId = $this->deviceId;
253
        }
254
        if (!empty($this->userProperties)) {
255
            $event->setUserProperties($this->userProperties);
256
            $this->resetUserProperties();
257
        }
258
    }
259
260
    /**
261
     * Log or queue the event, depending on if amplitude instance is already set up or not
262
     *
263
     * Note that this is an internal queue, the queue is lost between page loads.
264
     *
265
     * This functions identically to logEvent, with the exception that if Amplitude is not yet set up, it queues the
266
     * event to be logged later (during same page load).
267
     *
268
     * If the API key, and either user ID or device ID are already set in the amplitude instance, and there is not
269
     * already events in the queue that have not been run, this will log the event immediately.  Note that having
270
     * the userId or deviceId set on the event itself does not affect if it queues the event or not, only if set on
271
     * the Amplitude instance.
272
     *
273
     * Otherwise it will queue the event, and will be run after the amplitude instance is initialized and
274
     * logQueuedEvents() method is run
275
     *
276
     * @param string $eventType
277
     * @param array $eventProperties
278
     * @return \Zumba\Amplitude\Amplitude
279
     * @throws \LogicException
280
     */
281
    public function queueEvent($eventType = '', array $eventProperties = [])
282
    {
283
        if ($this->optOut) {
284
            return $this;
285
        }
286
        $event = $this->event();
287
        $event->set($eventProperties);
288
        $event->eventType = $eventType ?: $event->eventType;
289
290
        // Sanity checking
291
        if (empty($event->eventType)) {
292
            throw new \LogicException(static::EXCEPTION_MSG_NO_EVENT_TYPE);
293
        }
294
        if (empty($this->queue) && !empty($this->apiKey) && (!empty($this->userId) || !empty($this->deviceId))) {
295
            // No need to queue, everything seems to be initialized already and queue has already been processed
296
            return $this->logEvent();
297
        }
298
        $this->queue[] = $event;
299
        $this->resetEvent();
300
301
        return $this;
302
    }
303
304
    /**
305
     * Set the user ID for future events logged
306
     *
307
     * Any set with this will take precedence over any set on the Event object
308
     *
309
     * @param string $userId
310
     * @return \Zumba\Amplitude\Amplitude
311
     */
312
    public function setUserId($userId)
313
    {
314
        $this->userId = (string)$userId;
315
        return $this;
316
    }
317
318
    /**
319
     * Set the device 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 $deviceId
324
     * @return \Zumba\Amplitude\Amplitude
325
     */
326
    public function setDeviceId($deviceId)
327
    {
328
        $this->deviceId = (string)$deviceId;
329
        return $this;
330
    }
331
332
    /**
333
     * Set the user properties, will be sent with the next event sent to Amplitude
334
     *
335
     * Any set with this will take precedence over any set on the Event object
336
     *
337
     * If no events are logged, it will not get sent to Amplitude
338
     *
339
     * @param array $userProperties
340
     */
341
    public function setUserProperties(array $userProperties)
342
    {
343
        $this->userProperties = array_merge($this->userProperties, $userProperties);
344
        return $this;
345
    }
346
347
    /**
348
     * Resets user properties added with setUserProperties() if they have not already been sent in an event to Amplitude
349
     *
350
     * @return \Zumba\Amplitude\Amplitude
351
     */
352
    public function resetUserProperties()
353
    {
354
        $this->userProperties = [];
355
        return $this;
356
    }
357
358
    /**
359
     * Check if there are events in the queue that have not been sent
360
     *
361
     * @return boolean
362
     */
363
    public function hasQueuedEvents()
364
    {
365
        return !empty($this->queue);
366
    }
367
368
    /**
369
     * Resets all user information
370
     *
371
     * This resets the user ID, device ID previously set using setUserId or setDeviceId.
372
     *
373
     * If additional information was previously set using setUserProperties() method, and the event has not already
374
     * been sent to Amplitude, it will reset that information as well.
375
     *
376
     * Does not reset user information if set manually on an individual event in the queue.
377
     *
378
     * @return \Zumba\Amplitude\Amplitude
379
     */
380
    public function resetUser()
381
    {
382
        $this->setUserId(null);
383
        $this->setDeviceId(null);
384
        $this->resetUserProperties();
385
        return $this;
386
    }
387
388
    /**
389
     * Set opt out for the current user.
390
     *
391
     * If set to true, will not send any future events to amplitude for this amplitude instance.
392
     *
393
     * @param boolean $optOut
394
     * @return \Zumba\Amplitude\Amplitude
395
     */
396
    public function setOptOut($optOut)
397
    {
398
        $this->optOut = (bool)$optOut;
399
        return $this;
400
    }
401
402
    /**
403
     * Getter for currently set api key
404
     *
405
     * @return string|null
406
     */
407
    public function getApiKey()
408
    {
409
        return $this->apiKey;
410
    }
411
412
    /**
413
     * Getter for currently set user ID
414
     *
415
     * @return string|null
416
     */
417
    public function getUserId()
418
    {
419
        return $this->userId;
420
    }
421
422
    /**
423
     * Getter for currently set device ID
424
     *
425
     * @return string|null
426
     */
427
    public function getDeviceId()
428
    {
429
        return $this->deviceId;
430
    }
431
432
    /**
433
     * Getter for all currently set user properties, that will be automatically sent on next Amplitude event
434
     *
435
     * Once the properties have been sent in an Amplitude event, they will be cleared.
436
     *
437
     * @return array
438
     */
439
    public function getUserProperties()
440
    {
441
        return $this->userProperties;
442
    }
443
444
    /**
445
     * Get the current value for opt out.
446
     *
447
     * @return boolean
448
     */
449
    public function getOptOut()
450
    {
451
        return $this->optOut;
452
    }
453
454
    /**
455
     * Send the event currently set in $this->event to amplitude
456
     *
457
     * Requres $this->event and $this->apiKey to be set, otherwise it throws an exception.
458
     *
459
     * @return integer|boolean HTTP Status code or boolean false if problem making connection
460
     * @throws \InternalErrorException If event or api key not set
461
     */
462
    protected function sendEvent()
463
    {
464
        if (empty($this->event) || empty($this->apiKey)) {
465
            throw new \InternalErrorException('Event or api key not set, cannot send event');
466
        }
467
        $postFields = [
468
            'api_key' => $this->apiKey,
469
            'event' => json_encode($this->event),
470
        ];
471
        $ch = curl_init(static::AMPLITUDE_API_URL);
472
        if (!$ch) {
473
            return false;
474
        }
475
        curl_setopt($ch, \CURLOPT_POSTFIELDS, $postFields);
476
        curl_exec($ch);
477
478
        $status = curl_getinfo($ch, \CURLINFO_HTTP_CODE);
479
        curl_close($ch);
480
        return (int)$status;
481
    }
482
}
483