You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
8.1 KiB
PHP
256 lines
8.1 KiB
PHP
<?php
|
|
namespace Isekai\UserPoints\Service;
|
|
|
|
use stdClass;
|
|
use User;
|
|
use MediaWiki\MediaWikiServices;
|
|
|
|
/**
|
|
* @property int $user_id
|
|
* @property string $last_sign_date
|
|
* @property string|array $sign_days_data
|
|
* @property int $total_sign_days
|
|
*/
|
|
class IsekaiUserDailySignData extends stdClass {}
|
|
|
|
/**
|
|
* @property int $userId
|
|
* @property string $lastSignDate
|
|
* @property array $signDaysData
|
|
* @property int $totalSignDays
|
|
*/
|
|
class IsekaiUserDailySign {
|
|
/** @var MediaWikiServices */
|
|
private $services;
|
|
|
|
/** @var User */
|
|
private $user;
|
|
|
|
/** @var array */
|
|
private $pointConfig;
|
|
|
|
/** @var array */
|
|
private $dailySignConfig;
|
|
|
|
private $dataKeysMap = [
|
|
'userId' => 'user_id',
|
|
'lastSignDate' => 'last_sign_date',
|
|
'signDaysData' => 'sign_days_data',
|
|
'totalSignDays' => 'total_sign_days'
|
|
];
|
|
|
|
/** @var IsekaiUserDailySignData|null */
|
|
private $mDailySignData = null;
|
|
|
|
private $recordExists = false;
|
|
|
|
public function __construct(User $user, array $pointConfig, array $dailySignConfig, MediaWikiServices $services) {
|
|
$this->user = $user;
|
|
$this->pointConfig = $pointConfig;
|
|
$this->dailySignConfig = $dailySignConfig;
|
|
$this->services = $services;
|
|
}
|
|
|
|
private function loadDailySignData() {
|
|
if (!$this->mDailySignData) {
|
|
$dbr = $this->services->getDBLoadBalancer()->getConnection(DB_REPLICA);
|
|
$this->mDailySignData = $dbr->selectRow(
|
|
'isekai_user_daily_sign',
|
|
'*',
|
|
[
|
|
'user_id' => $this->user->getId()
|
|
],
|
|
__METHOD__
|
|
);
|
|
|
|
if (!$this->mDailySignData) {
|
|
$this->initDefaultData();
|
|
} else {
|
|
$this->mDailySignData->sign_days_data = json_decode($this->mDailySignData->sign_days_data, true) ?? [];
|
|
|
|
$this->recordExists = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private function initDefaultData() {
|
|
$this->mDailySignData = new IsekaiUserDailySignData();
|
|
$this->mDailySignData->user_id = $this->user->getId();
|
|
$this->mDailySignData->last_sign_date = '1970-01-01';
|
|
$this->mDailySignData->sign_days_data = [];
|
|
$this->mDailySignData->total_sign_days = 0;
|
|
}
|
|
|
|
public function __get($name) {
|
|
$this->loadDailySignData();
|
|
if (isset($this->dataKeysMap[$name])) {
|
|
$key = $this->dataKeysMap[$name];
|
|
return $this->mDailySignData->$key;
|
|
} else {
|
|
throw new \Exception("Invalid property $name");
|
|
}
|
|
}
|
|
|
|
public function doSign() {
|
|
$this->loadDailySignData();
|
|
|
|
$pointDelta = [];
|
|
|
|
$lastSignTime = strtotime($this->mDailySignData->last_sign_date);
|
|
|
|
if (date('Y-m-d', time()) == date('Y-m-d', $lastSignTime)) { // already signed in today
|
|
return [];
|
|
}
|
|
|
|
/** @var IsekaiUserPointsFactory */
|
|
$userPointsFactory = $this->services->getService('IsekaiUserPoints');
|
|
foreach ($this->dailySignConfig as $pointType => $config) {
|
|
if (!isset($this->pointConfig[$pointType])) { // point type not exist, ignore
|
|
continue;
|
|
}
|
|
|
|
if (!isset($config['points'])) { // no points config, ignore
|
|
continue;
|
|
}
|
|
|
|
$signDays = $this->mDailySignData->sign_days_data[$pointType] ?? 0;
|
|
|
|
$continuous_reset = $config['continuous_reset'] ?? false;
|
|
$expireTime = $config['expire_time'] ?? -1;
|
|
$points = $config['points'];
|
|
|
|
if (!is_array($points)) {
|
|
$points = [ $points ];
|
|
}
|
|
|
|
switch ($continuous_reset) {
|
|
case 'day':
|
|
if (date('Y-m-d', strtotime('-1 day')) != date('Y-m-d', $lastSignTime)) {
|
|
$signDays = 0;
|
|
}
|
|
case 'week':
|
|
if (date('Y-W', time()) != date('Y-W', $lastSignTime)) {
|
|
$signDays = 0;
|
|
}
|
|
break;
|
|
case 'month':
|
|
if (date('Y-m', time()) != date('Y-m', $lastSignTime)) {
|
|
$signDays = 0;
|
|
}
|
|
break;
|
|
case 'year':
|
|
if (date('Y', time()) != date('Y', $lastSignTime)) {
|
|
$signDays = 0;
|
|
}
|
|
break;
|
|
}
|
|
|
|
$pointsIndex = min($signDays, count($points) - 1);
|
|
$pointsAdd = $points[$pointsIndex];
|
|
|
|
$pointsService = $userPointsFactory->newFromUser($this->user, $pointType);
|
|
$pointsService->addPoints($pointsAdd, $expireTime, 'daily_sign', 'sign_in');
|
|
|
|
$pointDelta[$pointType] = $pointsAdd;
|
|
|
|
$this->mDailySignData->sign_days_data[$pointType] = $signDays + 1;
|
|
}
|
|
|
|
$this->mDailySignData->last_sign_date = date('Y-m-d H:i:s', time());
|
|
$this->mDailySignData->total_sign_days ++;
|
|
|
|
$this->save();
|
|
$this->saveSignLog($pointDelta);
|
|
|
|
return $pointDelta;
|
|
}
|
|
|
|
private function save() {
|
|
$dbw = $this->services->getDBLoadBalancer()->getConnection(DB_PRIMARY);
|
|
if ($this->recordExists) {
|
|
$dbw->update(
|
|
'isekai_user_daily_sign',
|
|
[
|
|
'last_sign_date' => $this->mDailySignData->last_sign_date,
|
|
'sign_days_data' => json_encode($this->mDailySignData->sign_days_data),
|
|
'total_sign_days' => $this->mDailySignData->total_sign_days,
|
|
],
|
|
[
|
|
'user_id' => $this->user->getId()
|
|
],
|
|
__METHOD__
|
|
);
|
|
} else {
|
|
$dbw->insert(
|
|
'isekai_user_daily_sign',
|
|
[
|
|
'user_id' => $this->mDailySignData->user_id,
|
|
'last_sign_date' => $this->mDailySignData->last_sign_date,
|
|
'sign_days_data' => json_encode($this->mDailySignData->sign_days_data),
|
|
'total_sign_days' => $this->mDailySignData->total_sign_days,
|
|
],
|
|
__METHOD__
|
|
);
|
|
$this->recordExists = true;
|
|
}
|
|
}
|
|
|
|
private function saveSignLog($pointDelta) {
|
|
$dbr = $this->services->getDBLoadBalancer()->getConnection(DB_REPLICA);
|
|
$dbw = $this->services->getDBLoadBalancer()->getConnection(DB_PRIMARY);
|
|
|
|
$currentYear = intval(date('Y', time()));
|
|
$currentMonth = intval(date('m', time()));
|
|
$currentDate = intval(date('d', time()));
|
|
|
|
$logData = $dbr->selectRow(
|
|
'isekai_user_daily_sign_log',
|
|
'*',
|
|
[
|
|
'user_id' => $this->user->getId(),
|
|
'year' => $currentYear,
|
|
'month' => $currentMonth
|
|
],
|
|
__METHOD__
|
|
);
|
|
|
|
if ($logData) {
|
|
$signLog = json_decode($logData->sign_log, true);
|
|
if (!is_array($signLog)) {
|
|
$signLog = [];
|
|
}
|
|
$signLog[] = [
|
|
'date' => $currentDate,
|
|
'delta' => $pointDelta
|
|
];
|
|
$logData->sign_log = json_encode($signLog);
|
|
$dbw->update(
|
|
'isekai_user_daily_sign_log',
|
|
[
|
|
'sign_log' => $logData->sign_log
|
|
],
|
|
[
|
|
'user_id' => $this->user->getId(),
|
|
'year' => $currentYear,
|
|
'month' => $currentMonth
|
|
],
|
|
__METHOD__
|
|
);
|
|
} else {
|
|
$signLog = [[
|
|
'date' => $currentDate,
|
|
'delta' => $pointDelta
|
|
]];
|
|
$dbw->insert(
|
|
'isekai_user_daily_sign_log',
|
|
[
|
|
'user_id' => $this->user->getId(),
|
|
'year' => $currentYear,
|
|
'month' => $currentMonth,
|
|
'sign_log' => json_encode($signLog)
|
|
],
|
|
__METHOD__
|
|
);
|
|
}
|
|
}
|
|
} |