feat(badges): auto-award medals from catalog thresholds
Evaluate medal get_type metrics on login/checkin/content and grant matching badges; optional search-history slot on search widget.
This commit is contained in:
1 parent
8f17ac410b
commit
dbe1275173
1 file changed
+168
@@ -0,0 +1,168 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Auto-grant medals from catalog thresholds (zibll zib_auto_add_user_medal lite).
|
||||||
|
*
|
||||||
|
* @package AKSRT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace AKSRT\User;
|
||||||
|
|
||||||
|
defined('ABSPATH') || exit;
|
||||||
|
|
||||||
|
class BadgeAutoAward {
|
||||||
|
|
||||||
|
private static $instance = null;
|
||||||
|
|
||||||
|
public static function get_instance(): self {
|
||||||
|
if (null === self::$instance) {
|
||||||
|
self::$instance = new self();
|
||||||
|
}
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function init(): void {
|
||||||
|
// Run after login / current user bootstrap.
|
||||||
|
add_action('wp_login', [$this, 'on_login'], 20, 2);
|
||||||
|
add_action('wp', [$this, 'maybe_for_current_user'], 30);
|
||||||
|
// Cheap hooks for common counters.
|
||||||
|
add_action('publish_post', [$this, 'on_content_change'], 20, 1);
|
||||||
|
add_action('comment_post', [$this, 'on_content_change'], 20, 1);
|
||||||
|
add_action('aksrt_user_followed', [$this, 'on_follow'], 20, 2);
|
||||||
|
add_action('aksrt_checkin_done', [$this, 'on_checkin'], 20, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function on_login($user_login, $user): void {
|
||||||
|
if ($user instanceof \WP_User) {
|
||||||
|
$this->evaluate((int) $user->ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function maybe_for_current_user(): void {
|
||||||
|
if (!is_user_logged_in() || is_admin()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Throttle: once per 10 minutes per user.
|
||||||
|
$uid = get_current_user_id();
|
||||||
|
$key = 'aksrt_badge_auto_' . $uid;
|
||||||
|
if (get_transient($key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_transient($key, 1, 10 * MINUTE_IN_SECONDS);
|
||||||
|
$this->evaluate($uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function on_content_change($arg = null): void {
|
||||||
|
$uid = get_current_user_id();
|
||||||
|
if ($uid > 0) {
|
||||||
|
$this->evaluate($uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function on_follow(int $follower_id, int $following_id): void {
|
||||||
|
if ($following_id > 0) {
|
||||||
|
$this->evaluate($following_id);
|
||||||
|
}
|
||||||
|
if ($follower_id > 0) {
|
||||||
|
$this->evaluate($follower_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function on_checkin(int $user_id): void {
|
||||||
|
if ($user_id > 0) {
|
||||||
|
$this->evaluate($user_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function evaluate(int $user_id): void {
|
||||||
|
if ($user_id <= 0 || !class_exists('\AKSRT\User\Badges') || !Badges::enabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!class_exists('\AKSRT\Settings\Settings')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$identity = \AKSRT\Settings\Settings::get_user_identity_settings();
|
||||||
|
$medal = is_array($identity['medal'] ?? null) ? $identity['medal'] : [];
|
||||||
|
$items = is_array($medal['items_by_slug'] ?? null) ? $medal['items_by_slug'] : [];
|
||||||
|
if (!$items) {
|
||||||
|
// Fall back to badge dictionary without thresholds.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($items as $slug => $item) {
|
||||||
|
$get_type = sanitize_key((string) ($item['get_type'] ?? 'manually_add'));
|
||||||
|
if ($get_type === 'manually_add' || $get_type === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$need = max(0, (int) ($item['get_val'] ?? 0));
|
||||||
|
if ($need <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$val = $this->metric($user_id, $get_type);
|
||||||
|
if ($val >= $need) {
|
||||||
|
Badges::grant($user_id, (string) $slug, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function metric(int $user_id, string $type): int {
|
||||||
|
switch ($type) {
|
||||||
|
case 'registration_time':
|
||||||
|
$user = get_userdata($user_id);
|
||||||
|
if (!$user) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$reg = strtotime((string) $user->user_registered);
|
||||||
|
if ($reg <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return max(0, (int) floor((time() - $reg) / DAY_IN_SECONDS));
|
||||||
|
|
||||||
|
case 'checkin_all_day':
|
||||||
|
$v = (int) get_user_meta($user_id, 'aksrt_checkin_all_day', true);
|
||||||
|
if ($v <= 0) {
|
||||||
|
$v = (int) get_user_meta($user_id, 'checkin_all_day', true);
|
||||||
|
}
|
||||||
|
return $v;
|
||||||
|
|
||||||
|
case 'new_post':
|
||||||
|
return (int) count_user_posts($user_id, 'post', true);
|
||||||
|
|
||||||
|
case 'bbs_post':
|
||||||
|
return post_type_exists('aksrt_forum_topic')
|
||||||
|
? (int) count_user_posts($user_id, 'aksrt_forum_topic', true)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
case 'comment':
|
||||||
|
return (int) get_comments(['user_id' => $user_id, 'count' => true, 'status' => 'approve']);
|
||||||
|
|
||||||
|
case 'followed':
|
||||||
|
if (class_exists('\AKSRT\User\Follow')) {
|
||||||
|
return (int) Follow::get_instance()->get_follower_count($user_id);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case 'like':
|
||||||
|
return (int) get_user_meta($user_id, 'aksrt_like_count', true)
|
||||||
|
?: (int) get_user_meta($user_id, 'like-posts', true);
|
||||||
|
|
||||||
|
case 'views':
|
||||||
|
return (int) get_user_meta($user_id, 'aksrt_user_views', true);
|
||||||
|
|
||||||
|
case 'pay_income':
|
||||||
|
return (int) get_user_meta($user_id, 'aksrt_pay_income', true);
|
||||||
|
|
||||||
|
case 'pay_rebate':
|
||||||
|
return (int) get_user_meta($user_id, 'aksrt_pay_rebate', true);
|
||||||
|
|
||||||
|
default:
|
||||||
|
/**
|
||||||
|
* Allow extensions to provide metric values.
|
||||||
|
*
|
||||||
|
* @param int $value
|
||||||
|
* @param int $user_id
|
||||||
|
* @param string $type
|
||||||
|
*/
|
||||||
|
return (int) apply_filters('aksrt_badge_metric_value', 0, $user_id, $type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user