Completed
Push — master ( 646f0b...f3dd30 )
by Arthur
03:05
created

User::keyFobs()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php namespace BB\Entities;
2
3
use BB\Exceptions\AuthenticationException;
4
use BB\Traits\UserRoleTrait;
5
use Carbon\Carbon;
6
use DateTime;
7
use Illuminate\Database\Eloquent\Model;
8
use Laracasts\Presenter\PresentableTrait;
9
use Auth;
10
use Hash;
11
use Illuminate\Auth\Authenticatable;
12
use Illuminate\Auth\Passwords\CanResetPassword;
13
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
14
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
15
16
/**
17
 * Class User
18
 *
19
 * @property integer $id
20
 * @property string $email
21
 * @property string $slack_username
22
 * @property string $name
23
 * @property string $given_name
24
 * @property string $family_name
25
 * @property string $hash
26
 * @property bool $active
27
 * @property bool $key_holder
28
 * @property bool $trusted
29
 * @property bool $banned
30
 * @property bool $email_verified
31
 * @property bool $induction_completed
32
 * @property integer $inducted_by
33
 * @property integer $payment_day
34
 * @property string $status
35
 * @property string $payment_method
36
 * @property string $subscription_id
37
 * @property Carbon $subscription_expires
38
 * @property Carbon $banned_date
39
 * @property string $phone
40
 * @property integer $storage_box_payment_id
41
 * @property ProfileData $profile
42
 * @property string|null secondary_payment_method
43
 * @package BB\Entities
44
 */
45
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
46
47
    use UserRoleTrait, PresentableTrait, Authenticatable, CanResetPassword;
48
49
50
    /**
51
     * The database table used by the model.
52
     *
53
     * @var string
54
     */
55
    protected $table = 'users';
56
57
    /**
58
     * The attributes excluded from the model's JSON form.
59
     *
60
     * @var array
61
     */
62
    protected $hidden = array('password', 'remember_token');
63
64
    protected $auditFields = array('induction_completed', 'trusted', 'key_holder');
65
66
    protected $presenter = 'BB\Presenters\UserPresenter';
67
68
69
    /**
70
     * Fillable fields
71
     *
72
     * @var array
73
     */
74
    protected $fillable = [
75
        'given_name', 'family_name', 'email', 'secondary_email', 'password', 'emergency_contact', 'phone',
76
        'monthly_subscription', 'profile_private', 'hash', 'rules_agreed',
77
        'key_holder', 'key_deposit_payment_id', 'trusted', 'induction_completed', 'payment_method', 'active', 'status'
78
    ];
79
80
81
    protected $attributes = [
82
        'status'                => 'setting-up',
83
        'active'                => 0,
84
        'key_holder'            => 0,
85
        'trusted'               => 0,
86
        'email_verified'        => 0,
87
        'founder'               => 0,
88
        'induction_completed'   => 0,
89
        'payment_day'           => 0,
90
        'profile_private'       => 0,
91
        'cash_balance'          => 0,
92
    ];
93
94
95
    public function getDates()
96
    {
97
        return array('created_at', 'updated_at', 'subscription_expires', 'banned_date', 'rules_agreed');
98
    }
99
100
101
    public static function statuses()
102
    {
103
        return [
104
            'setting-up'        => 'Setting Up',
105
            'active'            => 'Active',
106
            'payment-warning'   => 'Payment Warning',
107
            'suspended'         => 'Suspended',
108
            'leaving'           => 'Leaving',
109
            'on-hold'           => 'On Hold',
110
            'left'              => 'Left',
111
            'honorary'          => 'Honorary'
112
        ];
113
    }
114
115
116
117
    /*
118
    |--------------------------------------------------------------------------
119
    | Relationships
120
    |--------------------------------------------------------------------------
121
    |
122
    | The connections between this model and others
123
    |
124
    */
125
126
    public function payments()
127
    {
128
        return $this->hasMany('\BB\Entities\Payment')->orderBy('created_at', 'desc');
129
    }
130
131
    public function inductions()
132
    {
133
        return $this->hasMany('\BB\Entities\Induction');
134
    }
135
136
    public function keyFob()
137
    {
138
        return $this->hasMany('\BB\Entities\KeyFob')->where('active', true)->first();
139
    }
140
141
    public function keyFobs()
142
    {
143
        return $this->hasMany('\BB\Entities\KeyFob')->where('active', true);
144
    }
145
146
    public function profile()
147
    {
148
        return $this->hasOne('\BB\Entities\ProfileData');
149
    }
150
151
    public function address()
152
    {
153
        return $this->hasOne('\BB\Entities\Address')->orderBy('approved', 'asc');
154
    }
155
156
    public function notifications()
157
    {
158
        return $this->hasMany(Notification::class)->orderBy('created_at', 'desc');
159
    }
160
161
162
163
    /*
164
    |--------------------------------------------------------------------------
165
    | Attribute Getters and Setters and Model Extensions
166
    |--------------------------------------------------------------------------
167
    |
168
    | Useful properties and methods to have on a user model
169
    |
170
    */
171
172
    public function getNameAttribute()
173
    {
174
        return $this->attributes['given_name'] . ' ' . $this->attributes['family_name'];
175
    }
176
177
    public function setPasswordAttribute($password)
178
    {
179
        $this->attributes['password'] = Hash::make($password);
180
    }
181
182
    public function setPaymentDayAttribute($value)
183
    {
184
        //Ensure the payment date will always exist on any month payment_date
185
        if ($value > 28) {
186
            $value = 1;
187
        }
188
        $this->attributes['payment_day'] = $value;
189
    }
190
191
    /**
192
     * Can the user see protected member photos?
193
     * Only available to active members
194
     *
195
     * @return bool
196
     */
197
    public function shouldMemberSeeProtectedPhoto()
198
    {
199
        switch ($this->attributes['status']) {
200
            case 'active':
201
            case 'payment-warning':
202
            case 'honorary':
203
                return true;
204
            default:
205
                return false;
206
        }
207
    }
208
209
    /**
210
     * Is the user on a payment method that allows their subscription amount to be changed
211
     *
212
     * @return bool
213
     */
214
    public function canMemberChangeSubAmount()
215
    {
216
        return in_array($this->attributes['payment_method'], ['gocardless-variable', 'balance']);
217
    }
218
219
    /**
220
     * Is this user considered a keyholder - can they use the space on their own
221
     * This may have been replaced by a repo method which checks the photo as well
222
     *
223
     * @return bool
224
     */
225
    public function keyholderStatus()
226
    {
227
        return ($this->active && $this->key_holder && $this->trusted);
228
    }
229
230
    /**
231
     * Is the user part of the admin group
232
     *
233
     * @return bool
234
     */
235
    public function isAdmin()
236
    {
237
        return Auth::user()->hasRole('admin');
238
    }
239
240
    /**
241
     * Should GoCardless be promoted to the user
242
     *
243
     * @return bool
244
     */
245
    public function promoteGoCardless()
246
    {
247
        return (($this->payment_method != 'balance' && $this->payment_method != 'gocardless' && $this->payment_method != 'gocardless-variable') && ($this->status == 'active'));
248
    }
249
250
    /**
251
     * Should we be promoting the new variable gocardless to users?
252
     *
253
     * @return bool
254
     */
255
    public function promoteVariableGoCardless()
256
    {
257
        return (($this->status == 'active') && ($this->payment_method == 'gocardless'));
258
    }
259
260
    /**
261
     * Is the user eligible for a key?
262
     *
263
     * @return bool
264
     */
265
    public function promoteGetAKey()
266
    {
267
        return ($this->trusted && ! $this->key_holder && ($this->status == 'active'));
268
    }
269
270
    /**
271
     * Get an array of alerts for the user
272
     *
273
     * @return array
274
     */
275
    public function getAlerts()
276
    {
277
        $alerts = [];
278
        if ( ! $this->profile->profile_photo && ! $this->profile->new_profile_photo) {
279
            $alerts[] = 'missing-profile-photo';
280
        }
281
        if (empty($this->phone)) {
282
            $alerts[] = 'missing-phone';
283
        }
284
        return $alerts;
285
    }
286
287
    /**
288
     * @return bool
289
     */
290
    public function isBanned()
291
    {
292
        return $this->banned;
293
    }
294
295
    /**
296
     * @return bool
297
     */
298
    public function isSuspended()
299
    {
300
        return ($this->status == 'suspended');
301
    }
302
303
    /**
304
     * @return bool
305
     */
306
    public function isInducted()
307
    {
308
        return $this->induction_completed && $this->inducted_by;
309
    }
310
311
    public function inductedBy()
312
    {
313
        return User::findOrFail($this->inducted_by);
314
    }
315
316
317
    /*
318
    |--------------------------------------------------------------------------
319
    | Scopes
320
    |--------------------------------------------------------------------------
321
    */
322
323
    public function scopeActive($query)
324
    {
325
        return $query->whereActive(true);
326
    }
327
328
    public function scopeNotSpecialCase($query)
329
    {
330
        return $query->where('status', '!=', 'honorary');
331
    }
332
333
    public function scopeLeaving($query)
334
    {
335
        return $query->where('status', '=', 'leaving');
336
    }
337
338
    public function scopePaymentWarning($query)
339
    {
340
        return $query->where('status', '=', 'payment-warning');
341
    }
342
343
    public function scopeSuspended($query)
344
    {
345
        return $query->where('status', '=', 'suspended');
346
    }
347
348
349
    /*
350
    |--------------------------------------------------------------------------
351
    | Methods
352
    |--------------------------------------------------------------------------
353
    */
354
355
    /**
356
     * @param $paymentMethod
357
     * @param $paymentDay
358
     * @deprecated
359
     */
360
    public function updateSubscription($paymentMethod, $paymentDay)
361
    {
362
        if ($paymentDay > 28) {
363
            $paymentDay = 1;
364
        }
365
366
        $this->attributes['payment_method'] = $paymentMethod;
367
        $this->attributes['payment_day']    = $paymentDay;
368
369
        $this->save();
370
    }
371
372
    /**
373
     * @param $amount
374
     * @deprecated
375
     */
376
    public function updateSubAmount($amount)
377
    {
378
        $this->attributes['monthly_subscription'] = $amount;
379
        $this->save();
380
    }
381
382
    /**
383
     * @deprecated
384
     */
385
    public function cancelSubscription()
386
    {
387
        $this->payment_method = '';
388
        $this->subscription_id = '';
389
        $this->payment_day = '';
390
        $this->status = 'leaving';
391
        $this->save();
392
    }
393
394
    /**
395
     * @deprecated
396
     */
397
    public function setLeaving()
398
    {
399
        $this->status = 'leaving';
400
        $this->save();
401
    }
402
403
    /**
404
     * @deprecated
405
     */
406
    public function setSuspended()
407
    {
408
        $this->status = 'suspended';
409
        $this->active = false;
410
        $this->save();
411
    }
412
413
    /**
414
     * @deprecated
415
     */
416
    public function rejoin()
417
    {
418
        $this->status = 'setting-up';
419
        $this->save();
420
    }
421
422
    public function emailConfirmed()
423
    {
424
        $this->email_verified = true;
425
        $this->save();
426
    }
427
428
    /**
429
     * Fetch a user record, performs a permission check
430
     *
431
     * @param integer|null $id
432
     * @param string       $role
433
     *
434
     * @return User
435
     * @throws AuthenticationException
436
     */
437
    public static function findWithPermission($id = null, $role = 'admin')
438
    {
439
        if (empty($id)) {
440
            //Return the logged in user
441
            return Auth::user();
442
        }
443
444
        $requestedUser = self::findOrFail($id);
445
        if (Auth::user()->id == $requestedUser->id) {
446
            //The user they are after is themselves
447
            return $requestedUser;
448
        }
449
450
        //They are requesting a user that isn't them
451
        if (Auth::user()->hasRole($role)) {
452
            //They are an admin so that's alright
453
            return $requestedUser;
454
        }
455
456
        throw new AuthenticationException();
457
    }
458
459
    public function extendMembership($paymentMethod = null, DateTime $expiry = null)
460
    {
461
        if (empty($expiry)) {
462
            $expiry = Carbon::now()->addMonth();
463
        }
464
        $this->status = 'active';
465
        $this->active = true;
466
        if ($paymentMethod) {
467
            $this->payment_method = $paymentMethod;
468
        }
469
        $this->subscription_expires = $expiry;
470
        $this->save();
471
    }
472
473
    /**
474
     * @return array
475
     */
476
    public function getAuditFields()
477
    {
478
        return $this->auditFields;
479
    }
480
481
482
}
483