Passed
Pull Request — master (#50)
by Ronan
10:11
created

User::isActive()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 0
cts 2
cp 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
3
namespace App\Model;
4
5
use App\Model\Finder\UserFinder;
6
use Carbon\Carbon;
7
use Respect\Validation\Validator;
8
use Ronanchilvers\Orm\Model;
9
use Ronanchilvers\Orm\Traits\HasValidationTrait;
10
use Ronanchilvers\Utility\Str;
11
12
/**
13
 * Model representing a project
14
 *
15
 * @property int id
16
 * @property string name
17
 * @property string email
18
 * @property string password
19
 * @property string status
20
 * @property null|string preferences
21
 * @property string level
22
 * @property null|\Carbon\Carbon last_login
23
 * @property null|\Carbon\Carbon created
24
 * @property null|\Carbon\Carbon updated
25
 * @author Ronan Chilvers <[email protected]>
26
 */
27
class User extends Model
28
{
29
    const STATUS_INVITED  = 'invited';
30
    const STATUS_ACTIVE   = 'active';
31
    const STATUS_INACTIVE = 'inactive';
32
33
    const LEVEL_USER      = 'user';
34
    const LEVEL_ADMIN     = 'admin';
35
36
    use HasValidationTrait;
37
38
    static protected $finder       = UserFinder::class;
39
    static protected $columnPrefix = 'user';
40
41
    protected $data = [
42
        'user_status' => 'invited',
43
        'user_level'  => 'user',
44
    ];
45
46
    /**
47
     * @author Ronan Chilvers <[email protected]>
48
     */
49
    protected function boot()
50
    {
51
        $this->addType('datetime', 'last_login');
52
        $this->addType('array', 'preferences');
53
    }
54
55
    /**
56
     * @author Ronan Chilvers <[email protected]>
57
     */
58
    protected function setupValidation()
59
    {
60
        $this->registerRules([
61
            'name'     => Validator::notEmpty(),
62
            'email'    => Validator::notEmpty()->email(),
63
            'password' => Validator::notEmpty(),
64
            'status'   => Validator::notEmpty()->in([
65
                static::STATUS_INVITED,
66
                static::STATUS_INACTIVE,
67
                static::STATUS_ACTIVE,
68
            ]),
69
            'level'   => Validator::notEmpty()->in([
70
                static::LEVEL_USER,
71
                static::LEVEL_ADMIN,
72
            ]),
73
        ]);
74
75
        $this->registerRules([
76
            'name'     => Validator::notEmpty(),
77
            'email'    => Validator::notEmpty()->email(),
78
        ], 'invitation');
79
80
        $this->registerRules([
81
            'password' => Validator::notEmpty(),
82
        ], 'security');
83
    }
84
85
    /**
86
     * Override for beforeCreate model hook
87
     */
88
    public function beforeCreate(): void
89
    {
90
        $this->hash = Str::token(32);
0 ignored issues
show
Bug Best Practice introduced by
The property hash does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
91
    }
92
93
    /**
94
     * Get the user level options for this user
95
     *
96
     * @return array
97
     * @author Ronan Chilvers <[email protected]>
98
     */
99
    public function getLevelOptions(): array
100
    {
101
        return [
102
            static::LEVEL_USER => static::LEVEL_USER,
103
            static::LEVEL_ADMIN => static::LEVEL_ADMIN,
104
        ];
105
    }
106
107
    /**
108
     * Get the status options for this user
109
     *
110
     * @return array
111
     * @author Ronan Chilvers <[email protected]>
112
     */
113
    public function getStatusOptions(): array
114
    {
115
        return [
116
            static::STATUS_INACTIVE => static::STATUS_INACTIVE,
117
            static::STATUS_ACTIVE   => static::STATUS_ACTIVE,
118
        ];
119
    }
120
121
    /**
122
     * Get a preference by key
123
     *
124
     * @param string $key
125
     * @param mixed $default
126
     * @author Ronan Chilvers <[email protected]>
127
     */
128
    public function preference($key, $default = null)
129
    {
130
        $preferences = $this->preferences;
131
        if (is_null($preferences)) {
132
            return $default;
133
        }
134
        if (!isset($preferences[$key])) {
135
            return $default;
136
        }
137
138
        return $preferences[$key];
139
    }
140
141
    /**
142
     * Set a preference value for the user
143
     *
144
     * @param $key
145
     * @param mixed $value
146
     * @author Ronan Chilvers <[email protected]>
147
     */
148
    public function setPreference($key, $value)
149
    {
150
        $preferences       = $this->preferences;
151
        $preferences[$key] = $value;
152
        $this->preferences = $preferences;
153
154
        return $this->save();
155
    }
156
157
    /**
158
     * Verify a password against this user
159
     *
160
     * @param string $password
161
     * @return boolean
162
     * @author Ronan Chilvers <[email protected]>
163
     */
164
    public function verify(string $password): bool
165
    {
166
        if (!$this->isLoaded()) {
167
            return false;
168
        }
169
170
        return password_verify($password, $this->password);
171
    }
172
173
    /**
174
     * Set the password for this user
175
     *
176
     * @param string $password
177
     * @author Ronan Chilvers <[email protected]>
178
     */
179
    public function setPassword(string $password, string $confirm = null): bool
180
    {
181
        if (empty($password)) {
182
            return false;
183
        }
184
        $password = trim($password);
185
        if (!is_null($confirm) && trim($confirm) != $password) {
186
            $this->addError('password', 'Password does not match confirmation');
187
            return false;
188
        }
189
190
        $this->password = password_hash($password, PASSWORD_DEFAULT);
191
192
        return true;
193
    }
194
195
    /**
196
     * Verify and set a new password
197
     *
198
     * @param string $old
199
     * @param string $new
200
     * @param string $confirm
201
     * @return bool
202
     * @author Ronan Chilvers <[email protected]>
203
     */
204
    public function setNewPassword(string $old, string $new, string $confirm): bool
205
    {
206
        foreach (['old', 'new', 'confirm'] as $var) {
207
            $$var = trim($$var);
208
        }
209
        if (!$this->verify($old)) {
210
            return false;
211
        }
212
213
        return $this->setPassword($new, $confirm);
214
    }
215
216
    /**
217
     * Record a last login timestamp
218
     *
219
     * @author Ronan Chilvers <[email protected]>
220
     */
221
    public function recordLogin(): bool
222
    {
223
        $this->last_login = Carbon::now();
224
225
        return $this->save();
226
    }
227
228
    /**
229
     * Is this user active?
230
     *
231
     * @author Ronan Chilvers <[email protected]>
232
     */
233
    public function isActive(): bool
234
    {
235
        return $this->status == static::STATUS_ACTIVE;
236
    }
237
238
    /**
239
     * Is this user inactive?
240
     *
241
     * @author Ronan Chilvers <[email protected]>
242
     */
243
    public function isInvited(): bool
244
    {
245
        return $this->status == static::STATUS_INVITED;
246
    }
247
248
    /**
249
     * Is this user an admin?
250
     *
251
     * @author Ronan Chilvers <[email protected]>
252
     */
253
    public function isAdmin(): bool
254
    {
255
        return static::LEVEL_ADMIN == $this->level;
256
    }
257
258
    /**
259
     * Activate this user
260
     *
261
     * @author Ronan Chilvers <[email protected]>
262
     */
263
    public function activate()
264
    {
265
        $this->status = static::STATUS_ACTIVE;
266
    }
267
268
    /**
269
     * Deactivate this user
270
     *
271
     * @author Ronan Chilvers <[email protected]>
272
     */
273
    public function deactivate()
274
    {
275
        $this->status = static::STATUS_INACTIVE;
276
    }
277
}
278