• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

miaoxing / plugin / 7322930040

25 Dec 2023 04:02PM UTC coverage: 37.918% (-1.7%) from 39.661%
7322930040

push

github

twinh
ci: add PHP 8, remove PHP 7.2, 7.3

907 of 2392 relevant lines covered (37.92%)

5.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

54.65
/src/Service/User.php
1
<?php
2

3
namespace Miaoxing\Plugin\Service;
4

5
use Miaoxing\Plugin\Auth\BaseAuth;
6
use Miaoxing\Plugin\Auth\JwtAuth;
7
use Miaoxing\Plugin\BaseService;
8
use Miaoxing\Plugin\ConfigTrait;
9
use Wei\Ret;
10

11
/**
12
 * 用户
13
 *
14
 * @property bool $enableRegister
15
 * @property string $disableRegisterTips
16
 * @property bool $enableLoginCaptcha
17
 * @property int $defaultGroupId
18
 * @property bool $enablePasswordRest
19
 * @property bool $enableMobileVerify
20
 * @property bool $enableLogin
21
 * @property string $disableLoginTips
22
 * @property string $bgImage
23
 * @property int $defaultTagId
24
 * @property int $agreementArticleId
25
 * @property bool $enableExport
26
 * @property bool $enableCreate
27
 * @property string $defaultAvatar
28
 * @property bool $enablePinCode
29
 * @mixin \EventMixin
30
 * @mixin \ReqMixin
31
 */
32
class User extends BaseService
33
{
34
    use ConfigTrait {
35
        __get as getConfig;
36
    }
37

38
    /**
39
     * 用户服务是唯一的
40
     *
41
     * @var bool
42
     */
43
    protected static $createNewInstance = false;
44

45
    /**
46
     * @var UserModel|null
47
     */
48
    protected $cur;
49

50
    /**
51
     * @experimental expected to change
52
     */
53
    protected $configs = [
54
        'enablePinCode' => [
55
            'default' => false,
56
        ],
57
        'checkMobileUnique' => [
58
            'default' => false,
59
        ],
60
        'defaultAvatar' => [
61
            'default' => '',
62
        ],
63
        'enableLogin' => [
64
            'default' => true,
65
        ],
66
        'enableRegister' => [
67
            'default' => true,
68
        ],
69
        'disableRegisterTips' => [
70
            'default' => '注册功能未启用',
71
        ],
72
        'enableLoginCaptcha' => [
73
            'default' => false,
74
        ],
75
        'defaultGroupId' => [
76
            'default' => 0,
77
        ],
78
        'enablePasswordRest' => [
79
            'default' => false,
80
        ],
81
        'enableMobileVerify' => [
82
            'default' => false,
83
        ],
84
        'disableLoginTips' => [
85
            'default' => '登录功能未启用',
86
        ],
87
        'bgImage' => [
88
            'default' => '',
89
        ],
90
        'defaultTagId' => [],
91
        'agreementArticleId' => [],
92
        'enableExport' => [
93
            'default' => false,
94
        ],
95
        'enableCreate' => [
96
            'default' => false,
97
        ],
98
    ];
99

100
    /**
101
     * @var string
102
     */
103
    protected $authClass = JwtAuth::class;
104

105
    /**
106
     * @var BaseAuth|null
107
     */
108
    protected $auth;
109

110
    /**
111
     * @var array
112
     * @internal
113
     */
114
    protected $columns = [];
115

116
    /**
117
     * @param string $name
118
     * @return mixed
119
     */
120
    public function __get($name)
121
    {
122
        if (!$this->columns) {
85✔
123
            $this->columns = UserModel::getColumns();
3✔
124
        }
125
        if (isset($this->columns[$name])) {
85✔
126
            return $this->get($name);
84✔
127
        }
128

129
        return $this->getConfig($name);
2✔
130
    }
131

132
    /**
133
     * @param array|callable $returnFields
134
     * @param callable|null $prepend
135
     * @return array
136
     * @experimental may be remove
137
     * @svc
138
     */
139
    protected function toArray($returnFields = [], callable $prepend = null): array
140
    {
141
        return $this->cur()->toArray($returnFields, $prepend);
1✔
142
    }
143

144
    /**
145
     * @param iterable $attributes
146
     * @return UserModel
147
     * @experimental may be remove
148
     * @svc
149
     */
150
    protected function save(iterable $attributes = []): UserModel
151
    {
152
        return $this->cur()->save($attributes);
1✔
153
    }
154

155
    /**
156
     * 获取用户资料,优先从认证服务中获取
157
     *
158
     * @param string $name
159
     * @return mixed
160
     * @svc
161
     */
162
    protected function get(string $name)
163
    {
164
        $data = $this->getAuth()->getData();
89✔
165
        if (isset($data[$name])) {
89✔
166
            return $data[$name];
87✔
167
        }
168

169
        $user = $this->cur();
7✔
170
        if ($user) {
7✔
171
            return $user->get($name);
2✔
172
        }
173

174
        return null;
6✔
175
    }
176

177
    /**
178
     * Return the current user id
179
     *
180
     * @return int|string|null
181
     * @svc
182
     */
183
    protected function id()
184
    {
185
        return $this->get('id');
7✔
186
    }
187

188
    /**
189
     * Return the current user model
190
     *
191
     * @return UserModel
192
     * @svc
193
     */
194
    protected function cur(): ?UserModel
195
    {
196
        if (!$this->cur) {
10✔
197
            $this->loadDbUser();
8✔
198
        }
199
        return $this->cur;
10✔
200
    }
201

202
    /**
203
     * 判断用户是否登录
204
     *
205
     * @return bool
206
     * @svc
207
     */
208
    protected function isLogin(): bool
209
    {
210
        return $this->getAuth()->isLogin();
8✔
211
    }
212

213
    /**
214
     * 检查用户是否登录
215
     *
216
     * @return Ret
217
     * @svc
218
     */
219
    protected function checkLogin(): Ret
220
    {
221
        return $this->getAuth()->checkLogin();
×
222
    }
223

224
    /**
225
     * 根据用户账号密码,登录用户
226
     *
227
     * @param mixed $data
228
     * @return Ret
229
     * @svc
230
     */
231
    protected function login($data): Ret
232
    {
233
        // 1. 校验用户账号密码是否符合规则
234
        $validator = wei()->validate([
×
235
            'data' => $data,
×
236
            'rules' => [
×
237
                'username' => [
×
238
                    'required' => true,
×
239
                ],
×
240
                'password' => [
×
241
                    'required' => true,
×
242
                ],
×
243
            ],
×
244
            'names' => [
×
245
                'username' => '帐号',
×
246
                'password' => '密码',
×
247
            ],
×
248
        ]);
×
249

250
        if (!$validator->isValid()) {
×
251
            return err($validator->getFirstMessage());
×
252
        }
253

254
        // 2. 检查手机/邮箱/用户名是否存在
255
        $user = UserModel::new();
×
256
        switch (true) {
257
            case wei()->isMobileCn($data['username']):
×
258
                $column = 'mobile';
×
259
                $user->whereNotNULL('mobile_verified_at');
×
260
                break;
×
261

262
            case wei()->isEmail($data['username']):
×
263
                $column = 'email';
×
264
                break;
×
265

266
            default:
267
                $column = 'username';
×
268
        }
269

270
        $user = $user->findBy($column, $data['username']);
×
271

272
        if (!$user) {
×
273
            return err('用户名不存在或密码错误');
×
274
        }
275

276
        // 3. 检查用户是否有效
277
        if (!$user->isEnabled) {
×
278
            return err('用户未启用,无法登录');
×
279
        }
280

281
        // 4. 验证密码是否正确
282
        if (!$user->verifyPassword($data['password'])) {
×
283
            return err('用户不存在或密码错误');
×
284
        }
285

286
        // 5. 验证通过,登录用户
287
        return $this->loginByModel($user);
×
288
    }
289

290
    /**
291
     * 根据用户ID直接登录用户
292
     *
293
     * @param string|int $id
294
     * @return Ret
295
     * @svc
296
     */
297
    protected function loginById($id): Ret
298
    {
299
        $user = UserModel::find($id);
18✔
300
        if (!$user) {
18✔
301
            return err('用户不存在');
×
302
        } else {
303
            return $this->loginByModel($user);
18✔
304
        }
305
    }
306

307
    /**
308
     * 根据条件查找或创建用户,并登录
309
     *
310
     * @param array $conditions
311
     * @param array|object $data
312
     * @return $this
313
     * @svc
314
     */
315
    protected function loginBy(array $conditions, $data = []): self
316
    {
317
        $user = UserModel::findOrInitBy($conditions, $data);
×
318
        $this->loginByModel($user);
×
319

320
        return $this;
×
321
    }
322

323
    /**
324
     * 根据用户对象登录用户
325
     *
326
     * @param UserModel $user
327
     * @return Ret
328
     * @svc
329
     */
330
    protected function loginByModel(UserModel $user): Ret
331
    {
332
        $ret = $this->getAuth()->login($user);
24✔
333
        if ($ret->isSuc()) {
24✔
334
            $this->setCur($user);
24✔
335
            $this->event->trigger('userLogin', [$user]);
24✔
336
        }
337

338
        return $ret;
24✔
339
    }
340

341
    /**
342
     * 销毁用户会话,退出登录
343
     *
344
     * @return Ret
345
     * @svc
346
     */
347
    protected function logout(): Ret
348
    {
349
        if (!$this->isLogin()) {
4✔
350
            return err('用户未登录');
2✔
351
        }
352

353
        $this->getAuth()->logout();
2✔
354
        $this->event->trigger('beforeUserLogout', [$this->cur()]);
2✔
355
        $this->setCur(null);
2✔
356

357
        return suc();
2✔
358
    }
359

360
    /**
361
     * 当用户信息更改后,可以主动调用该方法,刷新会话中的数据
362
     *
363
     * @param UserModel $user
364
     * @return $this
365
     * @svc
366
     */
367
    protected function refresh(UserModel $user): self
368
    {
369
        if ($user->id === ($this->getAuth()->getData()['id'] ?? null)) {
9✔
370
            $this->loginByModel($user);
3✔
371
        }
372

373
        return $this;
9✔
374
    }
375

376
    /**
377
     * @return BaseAuth
378
     */
379
    protected function getAuth(): BaseAuth
380
    {
381
        if (!$this->auth) {
102✔
382
            $this->auth = new $this->authClass();
3✔
383
        }
384
        return $this->auth;
102✔
385
    }
386

387
    /**
388
     * Set the current user model
389
     *
390
     * @param UserModel|null $user
391
     * @return $this
392
     */
393
    protected function setCur(?UserModel $user): self
394
    {
395
        $this->cur = $user;
26✔
396
        return $this;
26✔
397
    }
398

399
    /**
400
     * 从数据库中查找用户加载到当前记录中
401
     *
402
     * @internal
403
     */
404
    protected function loadDbUser()
405
    {
406
        if (!$this->isLogin()) {
8✔
407
            return;
6✔
408
        }
409

410
        $id = $this->getAuth()->getData()['id'] ?? null;
3✔
411
        $user = UserModel::new();
3✔
412
        $user->setCacheKey($user->getModelCacheKey($id))->findOrInit($id);
3✔
413
        $this->setCur($user);
3✔
414
    }
415
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc