| | |
| | | namespace JVBase\managers; |
| | | |
| | | use Exception; |
| | | use JVBase\managers\queue\Queue; |
| | | use JVBase\rest\Rest; |
| | | use JVBase\rest\routes\VoteRoutes; |
| | | use WP_Error; |
| | | use WP_Post; |
| | | use WP_Term; |
| | | use WP_User; |
| | | use WP_Query; |
| | | |
| | | if (!defined('ABSPATH')) { |
| | | exit; // Exit if accessed directly |
| | |
| | | protected string $references; |
| | | protected CustomTable $table; |
| | | protected static Cache $cache; |
| | | protected Rest $route; |
| | | |
| | | private function __construct(string $key, ?string $references = null) |
| | | { |
| | | $this->route = VoteRoutes::getInstance(); |
| | | $this->key = $key; |
| | | if (is_null($references)) { |
| | | $references = match($key){ |
| | | 'post' => 'post', |
| | | 'term' => 'term', |
| | | 'user' => 'user', |
| | | 'post', 'posts' => 'post', |
| | | 'term','terms', 'taxonomy' => 'term', |
| | | 'user', 'users' => 'user', |
| | | 'response', 'responses' => 'response', |
| | | default => false |
| | | }; |
| | | if (!$references) { |
| | |
| | | // break; |
| | | // } |
| | | if (!isset(self::$cache)) { |
| | | self::$cache = Cache::for('user_karma')->connect('user'); |
| | | self::$cache = Cache::for('user_karma')->user(); |
| | | } |
| | | |
| | | $this->registerHooks(); |
| | | |
| | | } |
| | | |
| | | protected function registerHooks():void |
| | | { |
| | | if ($this->references === 'post') { |
| | | add_filter('posts_join', [$this, 'maybeJoinKarmaOrderby'], 10, 2); |
| | | add_filter('posts_orderby', [$this, 'maybeApplyKarmaOrderby'], 10, 2); |
| | | } elseif ($this->references === 'term') { |
| | | add_filter('terms_clauses', [$this, 'maybeApplyKarmaTermOrderby'], 10, 3); |
| | | } |
| | | |
| | | add_filter(BASE.'handle_bulk_operation', [$this, 'processOperation'], 10, 3); |
| | | } |
| | | |
| | | /** |
| | | * Supported orderby keys: 'karma_upvotes', 'karma_downvotes', 'karma_score' |
| | | */ |
| | | protected function karmaOrderExpr(string $orderby, string $alias = 'jvb_karma'): ?string |
| | | { |
| | | return match ($orderby) { |
| | | 'upvotes' => "COALESCE({$alias}.upvotes, 0)", |
| | | 'downvotes' => "COALESCE({$alias}.downvotes, 0)", |
| | | 'karmic_score' => "COALESCE({$alias}.upvotes, 0) - COALESCE({$alias}.downvotes, 0)", |
| | | default => null, |
| | | }; |
| | | } |
| | | |
| | | public function maybeJoinKarmaOrderby(string $join, WP_Query $query): string |
| | | { |
| | | if (!in_array($query->get('orderby'), ['upvotes', 'downvotes', 'karmic_score'])) { |
| | | return $join; |
| | | } |
| | | |
| | | global $wpdb; |
| | | $table = $this->table->getFullTableName(); |
| | | $content = $query->get('post_type') ?: 'post'; |
| | | |
| | | $join .= $wpdb->prepare( |
| | | " LEFT JOIN (SELECT item_id, |
| | | SUM(vote = 'up') as upvotes, |
| | | SUM(vote = 'down') as downvotes |
| | | FROM {$table} WHERE content = %s GROUP BY item_id) jvb_karma |
| | | ON jvb_karma.item_id = {$wpdb->posts}.ID", |
| | | $content |
| | | ); |
| | | return $join; |
| | | } |
| | | |
| | | public function maybeApplyKarmaOrderby(string $orderby, WP_Query $query): string |
| | | { |
| | | $expr = $this->karmaOrderExpr($query->get('orderby')); |
| | | if (!$expr) { |
| | | return $orderby; |
| | | } |
| | | $order = strtoupper($query->get('order')) === 'ASC' ? 'ASC' : 'DESC'; |
| | | return "{$expr} {$order}"; |
| | | } |
| | | |
| | | public function maybeApplyKarmaTermOrderby(array $clauses, array $taxonomies, array $args): array |
| | | { |
| | | $expr = $this->karmaOrderExpr($args['orderby'] ?? ''); |
| | | if (!$expr) { |
| | | return $clauses; |
| | | } |
| | | global $wpdb; |
| | | $table = $this->table->getFullTableName(); |
| | | $content = jvbNoBase($taxonomies[0] ?? ''); |
| | | |
| | | $clauses['join'] .= $wpdb->prepare( |
| | | " LEFT JOIN (SELECT item_id, |
| | | SUM(vote = 'up') as upvotes, |
| | | SUM(vote = 'down') as downvotes |
| | | FROM {$table} WHERE content = %s GROUP BY item_id) jvb_karma |
| | | ON jvb_karma.item_id = t.term_id", |
| | | $content |
| | | ); |
| | | $clauses['orderby'] = "ORDER BY {$expr}"; |
| | | $clauses['order'] = strtoupper($args['order'] ?? 'DESC') === 'ASC' ? 'ASC' : 'DESC'; |
| | | |
| | | return $clauses; |
| | | } |
| | | |
| | | public function karmaTable():CustomTable |
| | | { |
| | | return $this->table; |
| | | } |
| | | |
| | | public static function getInstance(string $key):KarmaManager|false |
| | | { |
| | | if (!isset(self::$instances[$key])) { |
| | |
| | | { |
| | | $key = sanitize_key($key); |
| | | if (!isset(self::$instances[$key])) { |
| | | self::$instances[$key] = new KarmaManager($key, $references); |
| | | self::$instances[$key] = new self($key, $references); |
| | | } |
| | | |
| | | return self::$instances[$key]; |
| | |
| | | 'post' => get_post($itemID), |
| | | 'term' => get_term($itemID, $based), |
| | | 'user' => get_userdata($itemID), |
| | | 'response' => JVB()->responses()->response->get(['id' => $itemID])??false, |
| | | 'response' => Responses::getInstance()->responseExists($itemID), |
| | | default => false //TODO if we do have custom tables, we'll have to set that up here |
| | | }; |
| | | } |
| | |
| | | } |
| | | self::$cache->forget($userID); |
| | | |
| | | JVB()->queue()->queueOperation( |
| | | Queue::getInstance()->queueOperation( |
| | | 'karmic', |
| | | 0, |
| | | [ |
| | |
| | | update_user_meta($item['itemID'], BASE.'karma', $karma); |
| | | break; |
| | | case 'response': |
| | | JVB()->responses()->response->update( |
| | | [ |
| | | 'upvotes' => $upvotes, |
| | | 'downvotes' => $downvotes, |
| | | 'karma' => $karma |
| | | ], |
| | | [ |
| | | 'id' => $item['itemID'] |
| | | ] |
| | | ); |
| | | Responses::getInstance()->updateKarma($item['itemID'], $upvotes, $downvotes, $karma); |
| | | break; |
| | | } |
| | | $results[$item['itemID']] = true; |