248 lines
8.0 KiB
PHP
248 lines
8.0 KiB
PHP
<?php
|
||
|
||
namespace Modules\User\Models\Traits;
|
||
|
||
use Carbon\Carbon;
|
||
use Exception;
|
||
use Illuminate\Database\Eloquent\Model;
|
||
use Illuminate\Support\Arr;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Modules\User\Events\UserJoinIdentity;
|
||
use Modules\User\Events\UserRemoveIdentity;
|
||
use Modules\User\Events\UserUpdateIdentity;
|
||
use Modules\User\Models\Identity;
|
||
use Modules\User\Models\IdentityLog;
|
||
use Modules\User\Models\IdentityMiddle;
|
||
|
||
trait JoinIdentity
|
||
{
|
||
|
||
/**
|
||
* 用户加入身份
|
||
*
|
||
* @param int $identity_id 身份ID
|
||
* @param string $channel 加入渠道
|
||
* @param array $source 其他溯源信息
|
||
* @throws Exception
|
||
*/
|
||
public function joinIdentity(
|
||
int $identity_id = 0,
|
||
string $channel = IdentityLog::CHANNEL_AUTO,
|
||
array $source = []
|
||
) {
|
||
|
||
// 单身份,并且已经开通身份
|
||
if (config('identity.can_has_many_identity') == false && $this->identityMiddle->count() >= 1) {
|
||
//续费
|
||
if ($this->hasIdentity($identity_id)) {
|
||
$this->renewIdentity($identity_id);
|
||
} else {
|
||
//升级
|
||
self::updateIdentity($identity_id, $channel, $source);
|
||
}
|
||
} else {
|
||
$identity = Identity::find($identity_id);
|
||
if ($identity) {
|
||
//未开通此身份
|
||
if ($this->hasIdentity($identity_id) == false) {
|
||
$remark = Arr::get($source, 'remark', '加入身份');
|
||
$res = self::identityLog(0, $identity_id, $channel, $remark, $source);
|
||
if ($res) {
|
||
$serial = $source['serial'] ?? '';
|
||
if ($identity->serial_open && empty($serial)) {
|
||
$serial = self::getNewSerial($identity->serial_places);
|
||
}
|
||
|
||
$value = [];
|
||
if ($identity->years) {
|
||
$value = [
|
||
'started_at' => now(),
|
||
'ended_at' => now()->addMonths($identity->years),
|
||
];
|
||
}
|
||
|
||
$this->identityMiddle()
|
||
->updateOrCreate([
|
||
'identity_id' => $identity_id,
|
||
'serial' => $serial,
|
||
], $value);
|
||
|
||
event(new UserJoinIdentity($this, $identity));
|
||
} else {
|
||
throw new Exception('添加日志失败');
|
||
}
|
||
} else {
|
||
//已开通此身份
|
||
$this->renewIdentity($identity_id);
|
||
}
|
||
} else {
|
||
throw new Exception('身份信息不存在');
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Notes: 续费
|
||
*
|
||
* @Author: 玄尘
|
||
* @Date : 2021/6/8 9:49
|
||
* @param int $identity_id
|
||
*/
|
||
public function renewIdentity(int $identity_id)
|
||
{
|
||
$identity = Identity::find($identity_id);
|
||
$before = $this->identityMiddle()->where('identity_id', $identity_id)->first();
|
||
|
||
//vip
|
||
if ($identity->years) {
|
||
IdentityMiddle::where('user_id', $this->id)
|
||
->where('identity_id', $identity_id)
|
||
->update([
|
||
'ended_at' => Carbon::parse($before->ended_at)->addMonths($identity->years),
|
||
]);
|
||
} else {
|
||
IdentityMiddle::where('user_id', $this->id)
|
||
->where('identity_id', $identity_id)
|
||
->update([
|
||
'started_at' => null,
|
||
'ended_at' => null,
|
||
]);
|
||
}
|
||
|
||
event(new UserJoinIdentity($this, $before->identity));
|
||
}
|
||
|
||
/**
|
||
* 用户身份调整,当多身份关闭时由join触发
|
||
*
|
||
* @param int $identity_id
|
||
* @param string $channel
|
||
* @param array $source
|
||
* @throws Exception
|
||
*/
|
||
public function updateIdentity(
|
||
int $identity_id = 0,
|
||
string $channel = IdentityLog::CHANNEL_AUTO,
|
||
array $source = []
|
||
) {
|
||
$before = $this->identityMiddle()->first();
|
||
if ($this->identityMiddle()->count() > 1) {
|
||
$this->identityMiddle()->where('identity_id', '!=', $before->identity_id)->delete();
|
||
}
|
||
$identity = Identity::find($identity_id);
|
||
if ($identity) {
|
||
$remark = Arr::get($source, 'remark', '身份变更');
|
||
$res = self::identityLog($before->identity_id, $identity_id, $channel, $remark, $source);
|
||
if ($res) {
|
||
$serial = $source['serial'] ?? '';
|
||
if ($identity->serial_open && empty($serial)) {
|
||
$serial = self::getNewSerial($identity->serial_places);
|
||
}
|
||
|
||
$data = [
|
||
'identity_id' => $identity_id,
|
||
'serial' => $serial,
|
||
'started_at' => null,
|
||
'ended_at' => null,
|
||
];
|
||
|
||
if ($identity->years) {
|
||
$data['started_at'] = now();
|
||
$data['ended_at'] = now()->addMonths($identity->years);
|
||
}
|
||
|
||
IdentityMiddle::where('user_id', $this->id)
|
||
->where('identity_id', $before->identity_id)
|
||
->update($data);
|
||
|
||
event(new UserUpdateIdentity($this, $before->identity, $identity));
|
||
} else {
|
||
throw new Exception('调整身份');
|
||
}
|
||
} else {
|
||
throw new Exception('身份信息不存在');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 判断用户是否参与身份
|
||
*
|
||
* @param int $identity_id
|
||
* @return bool
|
||
*/
|
||
public function hasIdentity(int $identity_id = 0): bool
|
||
{
|
||
if ($identity_id) {
|
||
$res = $this->identityMiddle()->where('identity_id', $identity_id)->first();
|
||
|
||
return (bool) $res;
|
||
} else {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 用户移除身份
|
||
*
|
||
* @param int $identity_id 身份ID
|
||
* @param string $channel 移除渠道
|
||
* @param array $source 其他溯源信息
|
||
* @throws Exception
|
||
*/
|
||
public function removeIdentity(
|
||
int $identity_id = 0,
|
||
string $channel = IdentityLog::CHANNEL_AUTO,
|
||
array $source = []
|
||
) {
|
||
if ($this->identityMiddle()->where('identity_id', $identity_id)->first()) {
|
||
$remark = Arr::get($source, 'remark', '身份移除');
|
||
$res = self::identityLog($identity_id, 0, $channel, $remark, $source);
|
||
if ($res) {
|
||
$this->identityMiddle()->where('identity_id', $identity_id)->delete();
|
||
event(new UserRemoveIdentity($this, Identity::find($identity_id)));
|
||
} else {
|
||
throw new Exception('移除记录失败');
|
||
}
|
||
} else {
|
||
throw new Exception('用户不在身份组中');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 生成数据库中部存在的号码
|
||
*
|
||
* @return int
|
||
*/
|
||
public function getNewSerial($places = 8)
|
||
{
|
||
try {
|
||
$min = pow(10, $places - 1);
|
||
$max = 9 * $min;
|
||
$query = 'SELECT code FROM (SELECT CEILING(RAND()*'.$max.'+'.$min.') AS code FROM user_identity UNION SELECT CEILING(RAND()*'.$max.'+'.$min.') AS code) AS ss WHERE "code" NOT IN (SELECT serial FROM user_identity where serial !=null) LIMIT 1';
|
||
$res = DB::select($query);
|
||
|
||
return (int) $res[0]->code;
|
||
} catch (Exception $e) {
|
||
return '';
|
||
}
|
||
}
|
||
|
||
public function identityLog(
|
||
$before = 0,
|
||
$after = 0,
|
||
$channel = '',
|
||
$remark = '',
|
||
$source = []
|
||
): Model {
|
||
return $this->identity_logs()->create([
|
||
'before' => $before,
|
||
'after' => $after,
|
||
'channel' => $channel,
|
||
'remark' => $remark,
|
||
'source' => $source,
|
||
]);
|
||
}
|
||
|
||
}
|