fix(user): serialize level experience awards
This commit is contained in:
@@ -232,6 +232,21 @@ class Level {
|
||||
* @return int|false Granted amount or false.
|
||||
*/
|
||||
public static function add(int $user_id, string $key, int $points = 0, bool $bypass_day_max = false) {
|
||||
if ($user_id <= 0) {
|
||||
return false;
|
||||
}
|
||||
$lock = self::acquire_lock('user:' . $user_id);
|
||||
if ($lock === '') {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return self::add_locked($user_id, $key, $points, $bypass_day_max);
|
||||
} finally {
|
||||
self::release_lock($lock);
|
||||
}
|
||||
}
|
||||
|
||||
private static function add_locked(int $user_id, string $key, int $points, bool $bypass_day_max) {
|
||||
$cfg = self::settings();
|
||||
$key = sanitize_key($key);
|
||||
if ($user_id <= 0 || !$cfg['enabled'] || $key === '' || $key === 'day_max') {
|
||||
@@ -282,10 +297,34 @@ class Level {
|
||||
return $points;
|
||||
}
|
||||
|
||||
private static function acquire_lock(string $scope): string {
|
||||
global $wpdb;
|
||||
$name = substr($wpdb->prefix . 'aksrt_level_' . md5($scope), 0, 64);
|
||||
$acquired = (int) $wpdb->get_var($wpdb->prepare('SELECT GET_LOCK(%s, %d)', $name, 5));
|
||||
return $acquired === 1 ? $name : '';
|
||||
}
|
||||
|
||||
private static function release_lock(string $name): void {
|
||||
global $wpdb;
|
||||
$wpdb->get_var($wpdb->prepare('SELECT RELEASE_LOCK(%s)', $name));
|
||||
}
|
||||
|
||||
private static function award_once(int $user_id, string $key, string $meta_type, int $entity_id, string $marker, int $limit = 1, int $actor_id = 0): void {
|
||||
if ($user_id <= 0 || $entity_id <= 0) {
|
||||
return;
|
||||
}
|
||||
$lock = self::acquire_lock($meta_type . ':' . $entity_id . ':' . $marker);
|
||||
if ($lock === '') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
self::award_once_locked($user_id, $key, $meta_type, $entity_id, $marker, $limit, $actor_id);
|
||||
} finally {
|
||||
self::release_lock($lock);
|
||||
}
|
||||
}
|
||||
|
||||
private static function award_once_locked(int $user_id, string $key, string $meta_type, int $entity_id, string $marker, int $limit, int $actor_id): void {
|
||||
$get = $meta_type === 'comment' ? 'get_comment_meta' : 'get_post_meta';
|
||||
$update = $meta_type === 'comment' ? 'update_comment_meta' : 'update_post_meta';
|
||||
$awarded = $get($entity_id, $marker, true);
|
||||
@@ -310,12 +349,23 @@ class Level {
|
||||
public function on_login($user_login, $user): void {
|
||||
$user_id = $user instanceof \WP_User ? (int) $user->ID : 0;
|
||||
$today = current_time('Ymd');
|
||||
if ($user_id <= 0 || get_user_meta($user_id, self::META_LOGIN_DAY, true) === $today) {
|
||||
if ($user_id <= 0) {
|
||||
return;
|
||||
}
|
||||
$lock = self::acquire_lock('login:' . $user_id . ':' . $today);
|
||||
if ($lock === '') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (get_user_meta($user_id, self::META_LOGIN_DAY, true) === $today) {
|
||||
return;
|
||||
}
|
||||
if (self::add($user_id, 'sign_in')) {
|
||||
update_user_meta($user_id, self::META_LOGIN_DAY, $today);
|
||||
}
|
||||
} finally {
|
||||
self::release_lock($lock);
|
||||
}
|
||||
}
|
||||
|
||||
public function on_checkin(int $user_id): void {
|
||||
@@ -367,15 +417,26 @@ class Level {
|
||||
public function on_followed($follower_id, $followed_id): void {
|
||||
$follower_id = (int) $follower_id;
|
||||
$followed_id = (int) $followed_id;
|
||||
if ($follower_id <= 0 || $followed_id <= 0) {
|
||||
return;
|
||||
}
|
||||
$lock = self::acquire_lock('follow:' . $followed_id);
|
||||
if ($lock === '') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$awarded = get_user_meta($followed_id, self::META_FOLLOWED, true);
|
||||
$awarded = is_array($awarded) ? array_map('intval', $awarded) : [];
|
||||
if ($follower_id <= 0 || $followed_id <= 0 || in_array($follower_id, $awarded, true)) {
|
||||
if (in_array($follower_id, $awarded, true)) {
|
||||
return;
|
||||
}
|
||||
if (self::add($followed_id, 'followed')) {
|
||||
$awarded[] = $follower_id;
|
||||
update_user_meta($followed_id, self::META_FOLLOWED, array_values(array_unique($awarded)));
|
||||
}
|
||||
} finally {
|
||||
self::release_lock($lock);
|
||||
}
|
||||
}
|
||||
|
||||
public function on_post_like($post_id, $user_id, $active = true): void {
|
||||
|
||||
Reference in New Issue
Block a user