From 3baf3d2545ba6ece6b74a64c0def59bd0774cf54 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Wed, 10 Jun 2026 16:34:12 +0000
Subject: [PATCH] =Laid the groundwork for an improved DashboardManager.php setup. Have to put it aside so I can get the dang Northeh done though.
---
inc/rest/routes/VoteRoutes.php | 366 +++++++++------------------------------------------
1 files changed, 68 insertions(+), 298 deletions(-)
diff --git a/inc/rest/routes/VoteRoutes.php b/inc/rest/routes/VoteRoutes.php
index e314f46..c0298ec 100644
--- a/inc/rest/routes/VoteRoutes.php
+++ b/inc/rest/routes/VoteRoutes.php
@@ -1,7 +1,12 @@
<?php
namespace JVBase\rest\routes;
-use JVBase\JVB;
-use JVBase\rest\RestRouteManager;
+
+use JVBase\managers\CustomTable;
+use JVBase\managers\KarmaManager;
+use JVBase\registrar\Registrar;
+use JVBase\rest\Response;
+use JVBase\rest\Rest;
+use JVBase\rest\Route;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
@@ -10,12 +15,12 @@
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
-class VoteRoutes extends RestRouteManager
+class VoteRoutes extends Rest
{
public function __construct()
{
- $this->cache_name = 'karma';
- $this->cache_ttl = 86400;
+ $this->cacheName = 'karma';
+ $this->cacheTtl = DAY_IN_SECONDS;
parent::__construct();
add_filter(BASE.'handle_bulk_operation', [$this, 'processOperation'], 10, 3);
}
@@ -26,18 +31,24 @@
*/
public function registerRoutes():void
{
- register_rest_route($this->namespace, 'vote', [
- [
- 'methods' => 'POST',
- 'callback' => [$this, 'handleVote'],
- 'permission_callback' => [$this, 'checkPermission']
- ],
- [
- 'methods' => 'GET',
- 'callback' => [$this, 'getVotes'],
- 'permission_callback' => [$this, 'checkPermission']
- ]
- ]);
+ Route::for('vote')
+ ->post([$this, 'handleVote'])
+ ->args([
+ 'user' => 'integer|required',
+ 'id' => 'string|required',
+ 'item_id' => 'integer|required',
+ 'content' => 'string|required',
+ 'vote' => 'string|required|enum:up,down',
+ ])
+ ->auth('user')
+ ->rateLimit(10)
+ ->get([$this, 'getVotes'])
+ ->args([
+ 'user' => 'integer',
+ ])
+ ->auth('user')
+ ->rateLimit(30)
+ ->register();
}
/**
@@ -47,303 +58,62 @@
*/
public function handleVote(WP_REST_Request $request):WP_REST_Response
{
- global $karma;
- if (!array_key_exists($request->get_param('content'), $karma)) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => __('Invalid content', 'jvb'),
- ]);
- }
- $vote = $request->get_param('vote');
- if (!$request->get_param('item_id') || !in_array($vote, ['up', 'down'])) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => __('Invalid item or vote attempt', 'jvb'),
- ]);
+ $content = sanitize_text_field($request->get_param('content')??'');
+ $registrar = Registrar::getInstance($content);
+ if (!$registrar || !$registrar->hasFeature('karma')) {
+ return Response::validationError(['message' => __('Invalid content', 'jvb')]);
+ }
+
+ $vote = sanitize_text_field($request->get_param('vote')??'');
+ $itemID = absint($request->get_param('item_id')??0);
+ if ($itemID === 0 || !in_array($vote, [true, false, null])) {
+ return Response::validationError(['message' => __('Invalid item or vote attempt', 'jvb')]);
}
- //cursory sanitization
- $user = (int) $request->get_param('user');
- if (!$this->userCheck($user)) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => __('User doesn\'t match. Bot?', 'jvb'),
- ]);
- }
- $operation = sanitize_text_field($request->get_param('id'));
+ $user = absint($request->get_param('user'));
+ if (!$this->userCheck($user)) {
+ return Response::validationError(['message' => __('User doesn\'t match. Bot?', 'jvb')]);
+ }
- $data = [
- 'user' => $user,
- 'item_id' => (int) $request->get_param('item_id'),
- 'content' => sanitize_text_field($request->get_param('content')),
- 'vote' => sanitize_text_field($vote),
- ];
+ $type = $registrar->getType()??false;
+ if (!$type) {
+ return Response::validationError(['message' => __('Invalid content type', 'jvb')]);
+ }
- error_log('Final Vote Data: '.print_r($data, true));
- error_log('Operation: '.print_r($operation, true));
- $queue = JVB()->queue();
- $queue->queueOperation(
- 'karmic',
- $user,
- $data,
- [
- 'priority' => 'high',
- 'operation_id' => $operation,
- ]
- );
- return new WP_REST_Response([
- 'success' => true,
- 'message' => __('Operation queued', 'jvb'),
- 'operation_id' => $operation
- ]);
+ $man = KarmaManager::getInstance($type);
+ if (!$man) {
+ return Response::validationError(['message' => __('Karma not set up', 'jvb')]);
+ }
+
+ [$success, $message] = $man->vote($user, $itemID, $content, $vote);
+
+ return match ($success) {
+ true, 'partial' => Response::success(['message' => $message]),
+ default => Response::error($message),
+ };
}
- /**
- * @param WP_Error|array $result
- * @param object $operation
- * @param array $data
- *
- * @return WP_Error|array
- */
- public function processOperation(WP_Error|array $result, object $operation, array $data):WP_Error|array
- {
- if ($operation->type !== 'karmic') {
- return $result;
- }
- // Get parameters from request
- global $karma;
- //Check if item exists
- $item = ($karma[$data['content']] === 'term') ?
- get_term($data['item_id'], BASE.$data['content']) :
- get_post($data['item_id']);
- if (!$item || is_wp_error($item)) {
- return [
- 'success' => false,
- 'result' => __('Invalid item', 'jvb')
- ];
- }
-
- global $wpdb;
- $table_name = $wpdb->prefix . BASE . 'karma_' . $data['content'];
- $key = $data['user'];
- error_log('Processing: '.print_r($data, true));
- // Check if user has already voted on this post
- $existing_vote = $wpdb->get_var(
- $wpdb->prepare(
- "SELECT vote FROM {$table_name} WHERE item_id = %d AND user_id = %d",
- $data['item_id'],
- $data['user']
- )
- );
-
- // Begin transaction for data integrity
- $wpdb->query('START TRANSACTION');
-
- try {
- // Initialize response data
- $response_data = [
- 'item_id' => $data['item_id'],
- 'previous_vote' => $existing_vote,
- 'new_vote' => $data['vote'],
- 'updated' => false
- ];
-
- error_log('Existing: '.print_r($existing_vote, true));
- error_log('New: '.print_r($data['vote'], true));
-
- // If user hasn't voted before
- if ($existing_vote === null) {
- // Insert new vote
- $inserted = $wpdb->insert(
- $table_name,
- [
- 'item_id' => $data['item_id'],
- 'user_id' => $data['user'],
- 'vote' => $data['vote'],
- 'date' => current_time('mysql')
- ],
- ['%d', '%d', '%s', '%s']
- );
-
- if (!$inserted) {
- throw new Exception('Failed to record vote');
- }
-
- // Increment the appropriate vote counter
- $this->updateVoteCount($data['content'], $data['item_id'], $data['vote'], 1);
-
- $response_data['updated'] = true;
- $this->cache->invalidate($key);
- } elseif ($existing_vote !== $data['vote']) {
- // If user is changing their vote
- // Update existing vote
- $updated = $wpdb->update(
- $table_name,
- [
- 'vote' => $data['vote'],
- ],
- [
-
- 'item_id' => $data['item_id'],
- 'user_id' => $data['user'],
- ],
- ['%s'],
- ['%d', '%d']
- );
-
- if (!$updated) {
- throw new Exception('Failed to update vote');
- }
-
- $this->updateVoteCount($data['content'], $data['item_id'], $existing_vote, -1);
-
- // Increment new vote type
- $this->updateVoteCount($data['content'], $data['item_id'], $data['vote'], 1);
-
- $response_data['updated'] = true;
- $this->cache->invalidate($key);
- } else {
- // If user is clicking the same vote again (toggle off)
- // Remove the vote
- $deleted = $wpdb->delete(
- $table_name,
- [
- 'item_id' => $data['item_id'],
- 'user_id' => $data['user']
- ],
- ['%d', '%d']
- );
-
- if (!$deleted) {
- throw new Exception('Failed to remove vote');
- }
-
- // Decrement the vote counter
- $this->updateVoteCount($data['content'], $data['item_id'], $data['vote'], -1);
-
- $response_data['new_vote'] = null;
- $response_data['updated'] = true;
- $this->cache->invalidate($key);
- }
-
- $wpdb->query('COMMIT');
-
- return [
- 'success' => true,
- 'result' => __('Vote handled', 'jvb'),
- ];
- } catch (Exception $e) {
- $wpdb->query('ROLLBACK');
- return [
- 'success' => false,
- 'result' => $e->getMessage()
- ];
- }
- }
-
- /**
- * @param string $content
- * @param int $ID
- * @param string $vote
- * @param int $value
- *
- * @return void
- */
- protected function updateVoteCount(string $content, int $ID, string $vote, int $value):void
- {
- global $karma;
-
- $key = ($vote==='down') ? BASE.'downvotes' : BASE.'upvotes';
-
- switch ($karma[$content]) {
- case 'post':
- $old = (int) get_post_meta($ID, $key, true);
- $new = max(0, $old + $value);
- update_post_meta($ID, $key, $new);
- $up = (int) get_post_meta($ID, BASE.'upvotes', true);
- $down = (int) get_post_meta($ID, BASE.'downvotes', true);
- update_post_meta($ID, BASE.'karma', $up - $down);
- break;
- case 'term':
- $old = (int) get_term_meta($ID, $key, true);
- $new = max(0, $old + $value);
- update_term_meta($ID, $key, $new);
- $up = (int) get_term_meta($ID, BASE.'upvotes', true);
- $down = (int) get_term_meta($ID, BASE.'downvotes', true);
- update_term_meta($ID, BASE.'karma', $up - $down);
- break;
- case 'user':
- $old = (int) get_user_meta($ID, $key, true);
- $new = max(0, $old + $value);
- update_user_meta($ID, $key, $new);
- $up = (int) get_user_meta($ID, BASE.'upvotes', true);
- $down = (int) get_user_meta($ID, BASE.'downvotes', true);
- update_user_meta($ID, BASE.'karma', $up - $down);
- break;
- case 'response':
- // Direct table update for responses
- global $wpdb;
- $table = $wpdb->prefix . BASE . 'responses';
-
- // Update vote count
- $field = str_replace(BASE, '', $key);
- $wpdb->query($wpdb->prepare(
- "UPDATE $table SET $field = GREATEST(0, $field + %d), karma = (upvotes - downvotes) WHERE id = %d",
- $value,
- $ID
- ));
- break;
- }
- }
/**
* @param WP_REST_Request $request
*
* @return WP_REST_Response
*/
- public function getVotes(WP_REST_Request $request):WP_REST_Response
- {
- $user = $request->get_param('user')??get_current_user_id();
- $cache = $this->cache->get($user);
- if ($cache) {
- return new WP_REST_Response($cache);
- }
+ public function getVotes(WP_REST_Request $request): WP_REST_Response
+ {
+ $user = absint($request->get_param('user') ?? get_current_user_id());
+ $cache = $this->cache->get($user);
+ if ($cache) {
+ return Response::success($cache);
+ }
- global $wpdb;
- $votes = [];
+ $votes = KarmaManager::getUserVotes($user);
- foreach (jvbGlobalKarma() as $type => $content_types) {
- foreach ($content_types as $content_type) {
- $table_name = $wpdb->prefix . BASE . 'karma_'. $content_type;
+ $this->cache->set($user, $votes);
- // Skip if table doesn't exist
- if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
- continue;
- }
-
- $results = $wpdb->get_results(
- $wpdb->prepare(
- "SELECT item_id, vote, date
- FROM {$table_name}
- WHERE user_id = %d",
- $user
- )
- );
-
- if ($results && !is_wp_error($results)) {
- foreach ($results as $vote) {
- $votes[$content_type][$vote->item_id] = $vote->vote;
- }
- }
- }
- }
-
- // Store in cache
- $this->cache->set($user, $votes);
-
- return new WP_REST_Response($votes);
- }
+ return Response::success($votes);
+ }
}
--
Gitblit v1.10.0