1
|
|
|
<?php |
2
|
|
|
namespace common\models; |
3
|
|
|
|
4
|
|
|
use yii; |
5
|
|
|
use yii\base\NotSupportedException; |
6
|
|
|
use yii\db\Query; |
7
|
|
|
use yii\web\IdentityInterface; |
8
|
|
|
use \common\components\ActiveRecord; |
9
|
|
|
use \common\interfaces\UserInterface; |
10
|
|
|
use \common\interfaces\UserBehaviorInterface; |
11
|
|
|
use \common\interfaces\TimeInterface; |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* User model |
15
|
|
|
* |
16
|
|
|
* @property integer $id |
17
|
|
|
* @property string $password_hash |
18
|
|
|
* @property string $password_reset_token |
19
|
|
|
* @property string $verify_email_token |
20
|
|
|
* @property string $email |
21
|
|
|
* @property string $auth_key |
22
|
|
|
* @property integer $role |
23
|
|
|
* @property integer $status |
24
|
|
|
* @property integer $created_at |
25
|
|
|
* @property integer $updated_at |
26
|
|
|
* @property string $password write-only password |
27
|
|
|
* @property string $timezone |
28
|
|
|
* @property boolean $send_email |
29
|
|
|
* @property integer $email_category |
30
|
|
|
* @property string $partner_email1 |
31
|
|
|
* @property string $partner_email2 |
32
|
|
|
* @property string $partner_email3 |
33
|
|
|
* @property boolean $expose_graph |
34
|
|
|
* @property string $desired_email |
35
|
|
|
* @property string $change_emaiL_token |
36
|
|
|
*/ |
37
|
|
|
class User extends ActiveRecord implements IdentityInterface, UserInterface |
38
|
|
|
{ |
39
|
|
|
const STATUS_DELETED = 0; |
40
|
|
|
const STATUS_ACTIVE = 10; |
41
|
|
|
|
42
|
|
|
const ROLE_USER = 10; |
43
|
|
|
|
44
|
|
|
const CONFIRMED_STRING = '_confirmed'; |
45
|
|
|
|
46
|
|
|
public $user_behavior; |
47
|
|
|
public $time; |
48
|
|
|
|
49
|
|
|
private $export_order = [ |
50
|
|
|
"date" => 0, |
51
|
|
|
"behavior" => 1, |
52
|
|
|
"category" => 2, |
53
|
|
|
"question1" => 3, |
54
|
|
|
"question2" => 4, |
55
|
|
|
"question3" => 5, |
56
|
|
|
]; |
57
|
|
|
|
58
|
|
|
public function __construct(UserBehaviorInterface $user_behavior, TimeInterface $time, $config = []) { |
59
|
|
|
$this->time = $time; |
60
|
|
|
parent::__construct($config); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
public function afterFind() { |
64
|
|
|
$this->time->timezone = $this->timezone; |
|
|
|
|
65
|
|
|
parent::afterFind(); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
public function afterRefresh() { |
69
|
|
|
$this->time->timezone = $this->timezone; |
|
|
|
|
70
|
|
|
parent::afterRefresh(); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
//public function afterSave() { |
74
|
|
|
// $this->time = new \common\components\Time($this->timezone); |
75
|
|
|
// parent::afterSave(); |
76
|
|
|
//} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* @inheritdoc |
80
|
|
|
* @codeCoverageIgnore |
81
|
|
|
*/ |
82
|
|
|
|
83
|
|
|
public function behaviors() |
84
|
|
|
{ |
85
|
|
|
return [ |
86
|
|
|
'timestamp' => [ |
87
|
|
|
'class' => yii\behaviors\TimestampBehavior::class, |
88
|
|
|
'attributes' => [ |
89
|
|
|
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'], |
90
|
|
|
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'], |
91
|
|
|
], |
92
|
|
|
], |
93
|
|
|
]; |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* @inheritdoc |
98
|
|
|
*/ |
99
|
|
|
public function rules() |
100
|
|
|
{ |
101
|
|
|
return [ |
102
|
|
|
['status', 'default', 'value' => self::STATUS_ACTIVE], |
103
|
|
|
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]], |
104
|
|
|
|
105
|
|
|
['role', 'default', 'value' => self::ROLE_USER], |
106
|
|
|
['role', 'in', 'range' => [self::ROLE_USER]], |
107
|
|
|
]; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
public function getPartnerEmails() { |
111
|
|
|
return [ |
112
|
|
|
$this->partner_email1, |
113
|
|
|
$this->partner_email2, |
114
|
|
|
$this->partner_email3, |
115
|
|
|
]; |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* @inheritdoc |
120
|
|
|
* @codeCoverageIgnore |
121
|
|
|
*/ |
122
|
|
|
public static function findIdentity($id) |
123
|
|
|
{ |
124
|
|
|
return static::findOne($id); |
|
|
|
|
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
/** |
128
|
|
|
* @inheritdoc |
129
|
|
|
* @codeCoverageIgnore |
130
|
|
|
*/ |
131
|
|
|
public static function findIdentityByAccessToken($token, $type = null) |
132
|
|
|
{ |
133
|
|
|
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.'); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Finds user by email |
138
|
|
|
* |
139
|
|
|
* @param string $email |
140
|
|
|
* @return static|null |
141
|
|
|
*/ |
142
|
|
|
public function findByEmail($email) |
143
|
|
|
{ |
144
|
|
|
return $this->find()->where(['email' => $email, 'status' => self::STATUS_ACTIVE])->one(); |
|
|
|
|
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
/** |
148
|
|
|
* Finds user by password reset token |
149
|
|
|
* |
150
|
|
|
* @param string $token password reset token |
151
|
|
|
* @return static|null |
152
|
|
|
*/ |
153
|
|
|
public function findByPasswordResetToken($token) |
154
|
|
|
{ |
155
|
|
|
if(!$this->isTokenCurrent($token)) { |
156
|
|
|
return null; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
return $this->find()->where([ |
|
|
|
|
160
|
|
|
'password_reset_token' => $token, |
161
|
|
|
'status' => self::STATUS_ACTIVE, |
162
|
|
|
])->one(); |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Finds user by email verification token |
167
|
|
|
* |
168
|
|
|
* @param string $token email verification token |
169
|
|
|
* @return static|null |
170
|
|
|
*/ |
171
|
|
|
public function findByVerifyEmailToken($token) |
172
|
|
|
{ |
173
|
|
|
if($this->isTokenConfirmed($token)) return null; |
174
|
|
|
|
175
|
|
|
$user = $this->find()->where([ |
176
|
|
|
'verify_email_token' => [$token, $token . self::CONFIRMED_STRING], |
177
|
|
|
'status' => self::STATUS_ACTIVE, |
178
|
|
|
])->one(); |
179
|
|
|
|
180
|
|
|
if($user) { |
181
|
|
|
if(!$this->isTokenConfirmed($token) && |
182
|
|
|
!$this->isTokenCurrent($token, 'user.verifyAccountTokenExpire')) { |
183
|
|
|
return null; |
184
|
|
|
} |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
return $user; |
|
|
|
|
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* Finds user by email change token |
192
|
|
|
* |
193
|
|
|
* @param string $token email change token |
194
|
|
|
* @return static|null |
195
|
|
|
*/ |
196
|
|
|
public function findByChangeEmailToken($token) |
197
|
|
|
{ |
198
|
|
|
$user = static::find()->where([ |
199
|
|
|
'change_email_token' => $token, |
200
|
|
|
'status' => self::STATUS_ACTIVE, |
201
|
|
|
])->one(); |
202
|
|
|
|
203
|
|
|
if($user) { |
204
|
|
|
if(!$user->isTokenCurrent($token, 'user.verifyAccountTokenExpire')) { |
205
|
|
|
return null; |
206
|
|
|
} |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
return $user; |
|
|
|
|
210
|
|
|
} |
211
|
|
|
|
212
|
|
|
/** |
213
|
|
|
* Finds out if a token is current or expired |
214
|
|
|
* |
215
|
|
|
* @param string $token verification token |
216
|
|
|
* @param string $paramPath Yii app param path |
217
|
|
|
* @return boolean |
218
|
|
|
*/ |
219
|
|
|
public function isTokenCurrent($token, String $paramPath = 'user.passwordResetTokenExpire') { |
220
|
|
|
$expire = \Yii::$app->params[$paramPath]; |
221
|
|
|
$parts = explode('_', $token); |
222
|
|
|
$timestamp = (int) end($parts); |
223
|
|
|
if ($timestamp + $expire < time()) { |
224
|
|
|
// token expired |
225
|
|
|
return false; |
226
|
|
|
} |
227
|
|
|
return true; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
/* |
231
|
|
|
* Checks if $token ends with the $match string |
232
|
|
|
* |
233
|
|
|
* @param string $token verification token (the haystack) |
234
|
|
|
* @param string $match the needle to search for |
235
|
|
|
*/ |
236
|
|
|
public function isTokenConfirmed($token = null, String $match = self::CONFIRMED_STRING) { |
237
|
|
|
if(is_null($token)) $token = $this->verify_email_token; |
238
|
|
|
return substr($token, -strlen($match)) === $match; |
239
|
|
|
} |
240
|
|
|
|
241
|
|
|
/** |
242
|
|
|
* @inheritdoc |
243
|
|
|
* @codeCoverageIgnore |
244
|
|
|
*/ |
245
|
|
|
public function getId() |
246
|
|
|
{ |
247
|
|
|
return $this->getPrimaryKey(); |
|
|
|
|
248
|
|
|
} |
249
|
|
|
|
250
|
|
|
/** |
251
|
|
|
* @inheritdoc |
252
|
|
|
* @codeCoverageIgnore |
253
|
|
|
*/ |
254
|
|
|
public function getAuthKey() |
255
|
|
|
{ |
256
|
|
|
return $this->auth_key; |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
public function getTimezone() { |
260
|
|
|
return $this->timezone; |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
public function isVerified() { |
264
|
|
|
if(is_null($this->verify_email_token)) { |
|
|
|
|
265
|
|
|
// for old users who verified their accounts before the addition of |
266
|
|
|
// '_confirmed' to the token |
267
|
|
|
return true; |
268
|
|
|
} else { |
269
|
|
|
return !!$this->verify_email_token && $this->isTokenConfirmed($this->verify_email_token); |
270
|
|
|
} |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* @inheritdoc |
275
|
|
|
*/ |
276
|
|
|
public function validateAuthKey($authKey) |
277
|
|
|
{ |
278
|
|
|
return $this->getAuthKey() === $authKey; |
279
|
|
|
} |
280
|
|
|
|
281
|
|
|
/** |
282
|
|
|
* Validates password |
283
|
|
|
* |
284
|
|
|
* @param string $password password to validate |
285
|
|
|
* @return boolean if password provided is valid for current user |
286
|
|
|
*/ |
287
|
|
|
public function validatePassword($password) |
288
|
|
|
{ |
289
|
|
|
return Yii::$app |
290
|
|
|
->getSecurity() |
291
|
|
|
->validatePassword($password, $this->password_hash); |
292
|
|
|
} |
293
|
|
|
|
294
|
|
|
/** |
295
|
|
|
* Generates password hash from password and sets it to the model |
296
|
|
|
* |
297
|
|
|
* @param string $password |
298
|
|
|
*/ |
299
|
|
|
public function setPassword($password) |
300
|
|
|
{ |
301
|
|
|
$this->password_hash = Yii::$app |
302
|
|
|
->getSecurity() |
303
|
|
|
->generatePasswordHash($password); |
304
|
|
|
} |
305
|
|
|
|
306
|
|
|
/** |
307
|
|
|
* Generates email verification token |
308
|
|
|
*/ |
309
|
|
|
public function generateVerifyEmailToken() |
310
|
|
|
{ |
311
|
|
|
$this->verify_email_token = $this->getRandomVerifyString(); |
312
|
|
|
} |
313
|
|
|
|
314
|
|
|
/** |
315
|
|
|
* Confirms email verification token |
316
|
|
|
*/ |
317
|
|
|
public function confirmVerifyEmailToken() |
318
|
|
|
{ |
319
|
|
|
$this->verify_email_token .= self::CONFIRMED_STRING; |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
/** |
323
|
|
|
* Removes email verification token |
324
|
|
|
*/ |
325
|
|
|
public function removeVerifyEmailToken() |
326
|
|
|
{ |
327
|
|
|
$this->verify_email_token = null; |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
/** |
331
|
|
|
* Generates email change tokens |
332
|
|
|
*/ |
333
|
|
|
public function generateChangeEmailToken() { |
334
|
|
|
$this->change_email_token = $this->getRandomVerifyString(); |
|
|
|
|
335
|
|
|
} |
336
|
|
|
|
337
|
|
|
/** |
338
|
|
|
* Removes change email token |
339
|
|
|
*/ |
340
|
|
|
public function removeChangeEmailToken() |
341
|
|
|
{ |
342
|
|
|
$this->change_email_token = null; |
|
|
|
|
343
|
|
|
} |
344
|
|
|
|
345
|
|
|
/** |
346
|
|
|
* Generates "remember me" authentication key |
347
|
|
|
*/ |
348
|
|
|
public function generateAuthKey() |
349
|
|
|
{ |
350
|
|
|
$this->auth_key = Yii::$app |
351
|
|
|
->getSecurity() |
352
|
|
|
->generateRandomString(); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
/** |
356
|
|
|
* Generates new password reset token |
357
|
|
|
*/ |
358
|
|
|
public function generatePasswordResetToken() |
359
|
|
|
{ |
360
|
|
|
$this->password_reset_token = $this->getRandomVerifyString(); |
361
|
|
|
} |
362
|
|
|
|
363
|
|
|
/** |
364
|
|
|
* Removes password reset token |
365
|
|
|
*/ |
366
|
|
|
public function removePasswordResetToken() |
367
|
|
|
{ |
368
|
|
|
$this->password_reset_token = null; |
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
/* |
372
|
|
|
* sendEmailReport() |
373
|
|
|
* |
374
|
|
|
* @param $date String a date string in YYYY-mm-dd format. The desired check-in date to send an email report of. Normally just today. |
375
|
|
|
* @return boolean whether or not it succeeds. It will return false if the user's specified criteria are not met (or if the user did not select any behaviors for the given day) |
376
|
|
|
* |
377
|
|
|
* This is the function that sends email reports. It can send an email report |
378
|
|
|
* for whichever `$date` is passed in. It checks if the user's specified |
379
|
|
|
* criteria are met before it sends any email. It sends email to every |
380
|
|
|
* partner email address the user has set. |
381
|
|
|
*/ |
382
|
|
|
public function sendEmailReport($date) { |
383
|
|
|
if(!$this->send_email) return false; // no partner emails set |
384
|
|
|
list($start, $end) = $this->time->getUTCBookends($date); |
|
|
|
|
385
|
|
|
|
386
|
|
|
$user_behavior = Yii::$container->get(UserBehaviorInterface::class); |
387
|
|
|
$checkins_last_month = $user_behavior->getCheckInBreakdown(); |
388
|
|
|
|
389
|
|
|
// we should only proceed with sending the email if the user |
390
|
|
|
// scored above their set email threshold (User::email_category) |
391
|
|
|
$this_checkin = $checkins_last_month[$date]; // gets the check-in |
392
|
|
|
if(!$this_checkin) return false; // sanity check |
393
|
|
|
$highest_cat_data = end($this_checkin); // gets the data for the highest category from the check-in |
394
|
|
|
if(!$highest_cat_data) return false; // another sanity check |
395
|
|
|
$highest_cat_idx = key($this_checkin); // gets the key of the highest category |
396
|
|
|
|
397
|
|
|
// if the highest category they reached today was less than |
398
|
|
|
// the category threshold they have set, don't send the email |
399
|
|
|
if($highest_cat_idx < $this->email_category) return false; |
400
|
|
|
|
401
|
|
|
$user_behaviors = $user_behavior->getByDate(Yii::$app->user->id, $date); |
402
|
|
|
|
403
|
|
|
$question = Yii::$container->get(\common\interfaces\QuestionInterface::class); |
404
|
|
|
$user_questions = $question->getByUser(Yii::$app->user->id, $date); |
405
|
|
|
|
406
|
|
|
$graph = Yii::$container |
407
|
|
|
->get(\common\components\Graph::class) |
408
|
|
|
->create($checkins_last_month); |
409
|
|
|
|
410
|
|
|
$messages = []; |
411
|
|
|
foreach($this->getPartnerEmails() as $email) { |
412
|
|
|
if($email) { |
413
|
|
|
$messages[] = Yii::$app->mailer->compose('checkinReport', [ |
414
|
|
|
'user' => $this, |
415
|
|
|
'email' => $email, |
416
|
|
|
'date' => $date, |
417
|
|
|
'user_behaviors' => $user_behaviors, |
418
|
|
|
'questions' => $user_questions, |
419
|
|
|
'chart_content' => $graph, |
420
|
|
|
'categories' => \common\models\Category::$categories, |
421
|
|
|
'behaviors_list' => \common\models\Behavior::$behaviors, |
422
|
|
|
])->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name]) |
423
|
|
|
->setReplyTo($this->email) |
424
|
|
|
->setSubject($this->email." has completed a Faster Scale check-in") |
425
|
|
|
->setTo($email); |
426
|
|
|
} |
427
|
|
|
} |
428
|
|
|
|
429
|
|
|
return Yii::$app->mailer->sendMultiple($messages); |
|
|
|
|
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
public function getExportData() { |
433
|
|
|
$query = (new Query) |
434
|
|
|
->select( |
435
|
|
|
'l.id, |
436
|
|
|
l.date AS "date", |
437
|
|
|
l.custom_behavior AS "custom_behavior", |
438
|
|
|
l.behavior_id AS "behavior_id", |
439
|
|
|
l.category_id AS "category_id", |
440
|
|
|
(SELECT q1.answer |
441
|
|
|
FROM question q1 |
442
|
|
|
WHERE q1.question = 1 |
443
|
|
|
AND q1.user_behavior_id = l.id) AS "question1", |
444
|
|
|
(SELECT q1.answer |
445
|
|
|
FROM question q1 |
446
|
|
|
WHERE q1.question = 2 |
447
|
|
|
AND q1.user_behavior_id = l.id) AS "question2", |
448
|
|
|
(SELECT q1.answer |
449
|
|
|
FROM question q1 |
450
|
|
|
WHERE q1.question = 3 |
451
|
|
|
AND q1.user_behavior_id = l.id) AS "question3"') |
452
|
|
|
->from('user_behavior_link l') |
453
|
|
|
->join("LEFT JOIN", "question q", "l.id = q.user_behavior_id") |
454
|
|
|
->where('l.user_id=:user_id', ["user_id" => Yii::$app->user->id]) |
455
|
|
|
->groupBy('l.id, |
456
|
|
|
l.date, |
457
|
|
|
"question1", |
458
|
|
|
"question2", |
459
|
|
|
"question3"') |
460
|
|
|
->orderBy('l.date DESC'); |
461
|
|
|
|
462
|
|
|
return $query |
463
|
|
|
->createCommand() |
464
|
|
|
->query(); |
465
|
|
|
|
466
|
|
|
/* Plaintext Query |
467
|
|
|
SELECT l.id, |
468
|
|
|
l.date AS "date", |
469
|
|
|
l.custom_behavior AS "custom_behavior", |
470
|
|
|
l.behavior_id AS "behavior_id", |
471
|
|
|
(SELECT q1.answer |
472
|
|
|
FROM question q1 |
473
|
|
|
WHERE q1.question = 1 |
474
|
|
|
AND q1.user_behavior_id = l.id) AS "question1", |
475
|
|
|
(SELECT q1.answer |
476
|
|
|
FROM question q1 |
477
|
|
|
WHERE q1.question = 2 |
478
|
|
|
AND q1.user_behavior_id = l.id) AS "question2", |
479
|
|
|
(SELECT q1.answer |
480
|
|
|
FROM question q1 |
481
|
|
|
WHERE q1.question = 3 |
482
|
|
|
AND q1.user_behavior_id = l.id) AS "question3" |
483
|
|
|
FROM user_behavior_link l |
484
|
|
|
LEFT JOIN question q |
485
|
|
|
ON l.id = q.user_behavior_id |
486
|
|
|
WHERE l.user_id = 1 |
487
|
|
|
GROUP BY l.id, |
488
|
|
|
l.date, |
489
|
|
|
l.custom_behavior, |
490
|
|
|
"question1", |
491
|
|
|
"question2", |
492
|
|
|
"question3", |
493
|
|
|
ORDER BY l.date DESC; |
494
|
|
|
*/ |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
public function sendSignupNotificationEmail() { |
498
|
|
|
return \Yii::$app->mailer->compose('signupNotification') |
499
|
|
|
->setFrom([\Yii::$app->params['supportEmail'] => \Yii::$app->name]) |
500
|
|
|
->setTo(\Yii::$app->params['adminEmail']) |
501
|
|
|
->setSubject('A new user has signed up for '.\Yii::$app->name) |
502
|
|
|
->send(); |
503
|
|
|
} |
504
|
|
|
|
505
|
|
|
public function sendVerifyEmail() { |
506
|
|
|
return \Yii::$app->mailer->compose('verifyEmail', ['user' => $this]) |
507
|
|
|
->setFrom([\Yii::$app->params['supportEmail'] => \Yii::$app->name]) |
508
|
|
|
->setTo($this->email) |
509
|
|
|
->setSubject('Please verify your '.\Yii::$app->name .' account') |
510
|
|
|
->send(); |
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
public function sendDeleteNotificationEmail() { |
514
|
|
|
$messages = []; |
515
|
|
|
foreach(array_merge([$this->email], $this->getPartnerEmails()) as $email) { |
516
|
|
|
if($email) { |
517
|
|
|
$messages[] = Yii::$app->mailer->compose('deleteNotification', [ |
518
|
|
|
'user' => $this, |
519
|
|
|
'email' => $email |
520
|
|
|
])->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name]) |
521
|
|
|
->setReplyTo($this->email) |
522
|
|
|
->setSubject($this->email." has deleted their The Faster Scale App account") |
523
|
|
|
->setTo($email); |
524
|
|
|
} |
525
|
|
|
} |
526
|
|
|
|
527
|
|
|
return Yii::$app->mailer->sendMultiple($messages); |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
public function cleanExportRow($row) { |
531
|
|
|
// change timestamp to local time (for the user) |
532
|
|
|
$row['date'] = $this->time->convertUTCToLocal($row['date'], false); |
533
|
|
|
|
534
|
|
|
// clean up things we don't need |
535
|
|
|
$row['category'] = $row['category']['name']; |
536
|
|
|
if(array_key_exists('behavior', $row)) { |
537
|
|
|
$row['behavior'] = $row['behavior']['name']; |
538
|
|
|
} else { |
539
|
|
|
$row['behavior'] = $row['custom_behavior']; |
540
|
|
|
} |
541
|
|
|
unset($row['id']); |
542
|
|
|
unset($row['behavior_id']); |
543
|
|
|
unset($row['category_id']); |
544
|
|
|
unset($row['custom_behavior']); |
545
|
|
|
|
546
|
|
|
// sort the array into a sensible order |
547
|
|
|
uksort($row, function($a, $b) { |
548
|
|
|
return $this->export_order[$a] <=> $this->export_order[$b]; |
549
|
|
|
}); |
550
|
|
|
return $row; |
551
|
|
|
} |
552
|
|
|
|
553
|
|
|
/* |
554
|
|
|
* getIdHash() |
555
|
|
|
* |
556
|
|
|
* @return String a user-identifying hash |
557
|
|
|
* |
558
|
|
|
* After generating the hash, we run it through a url-safe base64 encoding to |
559
|
|
|
* shorten it. This generated string is currently used as an identifier in |
560
|
|
|
* URLs, so the shorter the better. the url-safe version has been ripped from |
561
|
|
|
* https://secure.php.net/manual/en/function.base64-encode.php#103849 |
562
|
|
|
* |
563
|
|
|
* It does NOT take into account the user's email address. The email address |
564
|
|
|
* is changeable by the user. If that was used for this function, the |
565
|
|
|
* returned hash would change when the user updates their email. That would |
566
|
|
|
* obviously not be desirable. |
567
|
|
|
*/ |
568
|
|
|
public function getIdHash() { |
569
|
|
|
return rtrim( |
570
|
|
|
strtr( |
571
|
|
|
base64_encode( |
572
|
|
|
hash('sha256', $this->id."::".$this->created_at, true) |
573
|
|
|
), |
574
|
|
|
'+/', '-_'), |
575
|
|
|
'='); |
576
|
|
|
} |
577
|
|
|
|
578
|
|
|
/* |
579
|
|
|
* getRandomVerifyString() |
580
|
|
|
* |
581
|
|
|
* @return String a randomly generated string with a timestamp appended |
582
|
|
|
* |
583
|
|
|
* This is generally used for verification purposes: verifying an email, password change, or email address change. |
584
|
|
|
*/ |
585
|
|
|
private function getRandomVerifyString() { |
586
|
|
|
return Yii::$app |
587
|
|
|
->getSecurity() |
588
|
|
|
->generateRandomString() . '_' . time(); |
589
|
|
|
} |
590
|
|
|
} |
591
|
|
|
|