From b38f03c0e7218762d90fa5092696b127f24f36db Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 25 Jan 2026 07:07:26 +0000
Subject: [PATCH] =Some logical flaws in Queue.php, Queue.js, ContentExecutor.php, UploadExecutor.php - particularly with timeline ordering, frontend queue updates, etc

---
 inc/rest/routes/FavouritesRoutes.php |  266 +++++++++++++++++++++++++++++++---------------------
 1 files changed, 159 insertions(+), 107 deletions(-)

diff --git a/inc/rest/routes/FavouritesRoutes.php b/inc/rest/routes/FavouritesRoutes.php
index 5ab3310..19121b2 100644
--- a/inc/rest/routes/FavouritesRoutes.php
+++ b/inc/rest/routes/FavouritesRoutes.php
@@ -2,8 +2,8 @@
 namespace JVBase\rest\routes;
 
 use JVBase\JVB;
+use JVBase\managers\Cache;
 use JVBase\rest\RestRouteManager;
-use JVBase\managers\CacheManager;
 use WP_REST_Request;
 use WP_REST_Response;
 use WP_Error;
@@ -16,16 +16,21 @@
 class FavouritesRoutes extends RestRouteManager
 {
     protected array $valid_types;
-    protected int $user_id;
+	protected Cache $listsCache;
+	protected Cache $sharedListsCache;
+	protected Cache $favouritesCache;
 
     public function __construct()
     {
         $this->cache_name = 'favourites';
         parent::__construct();
+		$this->cache->connect('post')->connect('user')->connect('taxonomy');
+		$this->listsCache = Cache::for('lists')->connect('favourites', true);
+		$this->sharedListsCache = Cache::for('sharedLists')->connect('favourites', true);
+		$this->favouritesCache = Cache::for('allFavourites')->connect('favourites', true);
 
         $this->valid_types = array_keys(array_merge(JVB_CONTENT, JVB_TAXONOMY));
 
-        $this->user_id = get_current_user_id();
         $this->action = 'favourites-';
 
 
@@ -33,6 +38,7 @@
         add_action('before_delete_post', [$this, 'cleanupPostFavourites']);
         add_action('delete_term', [$this, 'cleanupTermFavourites'], 10, 3);
 
+		add_action('jvbUserRegistered', [$this, 'maybeAcceptListInvite'], 10, 3);
 
         // Register cleanup scheduler
         add_action('jvb_cleanupOrphanedFavourites', [$this, 'cleanupOrphanedFavourites']);
@@ -117,21 +123,30 @@
     {
 		$args = $this->buildParams($request);
 		if (!$args['user'] || $args['user'] === ''){
-			$result = [
+			return $this->addCacheHeaders(new WP_REST_Response([
 				'success'	=> false,
 				'message'	=> 'No user set'
-			];
-		}elseif (count($args) === 1 || (array_key_exists('all', $args) && $args['all'] === true)) {
+			]));
+		}
+		$key = $this->cache->generateKey($args);
+		// Check HTTP cache headers for user-specific data
+		$cache_check = $this->checkHeaders($request, $key);
+		if ($cache_check) {
+			return $cache_check;
+		}
+
+		if (count($args) === 1 || (array_key_exists('all', $args) && $args['all'] === true)) {
             $result = $this->getAllFavourites($args['user']);
 		} else {
 			$result = $this->cache->remember(
-				$args,
+				$this->cache->generateKey($args),
 				function() use ($args) {
 					return $this->getFilteredFavourites($args);
 				}
 			);
 		}
-		return new WP_REST_Response($result);
+		$response = new WP_REST_Response($result);
+		return $this->addCacheHeaders($response);
     }
 
 	protected function getFilteredFavourites(array $args):array
@@ -227,7 +242,7 @@
         }
 
 		$result = $this->cache->remember(
-			'user_'.$user_id.'_all_favourites',
+			$user_id,
 			function() use ($user_id) {
 				return $this->fetchAllFavourites($user_id);
 			}
@@ -263,14 +278,12 @@
 				$by_type[$type][] = (int)$fav->target_id;
 			}
 
-			$response_data = [
+			return [
 				'success' => true,
 				'items'		=> $by_type,
 				'has_more'	=> false,
 			];
 
-			return $response_data;
-
 		} catch (Exception $e) {
 			$this->logError(
 				$e->getMessage(),
@@ -382,6 +395,27 @@
     public function getLists(WP_REST_Request $request):WP_REST_Response
     {
         $user_id = get_current_user_id();
+
+		if (!$user_id || !$this->userCheck($user_id)) {
+			return new WP_REST_Response([
+				'success' => false,
+				'message' => 'Invalid user'
+			]);
+		}
+
+		$params = [
+			'user'	=> $user_id,
+		];
+		if ($request->get_param('id')) {
+			$params['list'] = sanitize_text_field($request->get_param('id'));
+		}
+		$key = $this->listsCache->generateKey($params);
+		// Check HTTP cache headers
+		$cache_check = $this->checkHeaders($request, $key);
+		if ($cache_check) {
+			return $cache_check;
+		}
+
         $list_id = $request->get_param('id');
 
         if ($list_id) {
@@ -390,7 +424,8 @@
             $response = $this->getAvailableLists($user_id);
         }
 
-        return new WP_REST_Response($response);
+        $response = new WP_REST_Response($response);
+		return $this->addCacheHeaders($response);
     }
     /**
      * Get lists available to a user (owned and shared)
@@ -404,28 +439,21 @@
         if (!$this->checkUser($user_id)) {
             return [];
         }
-        $key = sprintf(
-            'user_%d_lists',
-            $user_id
-        );
-        if ($include_shared) {
-            $key = $key.'_shared';
-        }
-        $cache = $this->cache->get($key, 'favourites_lists');
-        if ($cache) {
-            return $cache;
-        }
 
-        global $wpdb;
-        error_log('Attempting to get available lists..');
-        $lists_table = $wpdb->prefix . BASE . 'favourites_lists';
-        $items_table = $wpdb->prefix . BASE . 'favourites_list_items';
-        $shares_table = $wpdb->prefix . BASE . 'favourites_list_shares';
+		$cache = ($include_shared) ? $this->sharedListsCache : $this->listsCache;
+		return $cache->remember(
+			$user_id,
+			function() use ($user_id, $include_shared) {
+				global $wpdb;
+				error_log('Attempting to get available lists..');
+				$lists_table = $wpdb->prefix . BASE . 'favourites_lists';
+				$items_table = $wpdb->prefix . BASE . 'favourites_list_items';
+				$shares_table = $wpdb->prefix . BASE . 'favourites_list_shares';
 
-        try {
-            // Get owned lists
-            $owned_query = $wpdb->prepare(
-                "SELECT l.*,
+				try {
+					// Get owned lists
+					$owned_query = $wpdb->prepare(
+						"SELECT l.*,
                 COUNT(DISTINCT i.id) as item_count,
                 TRUE as is_owner,
                 FALSE as is_shared
@@ -434,16 +462,16 @@
             WHERE l.user_id = %d
             GROUP BY l.id
             ORDER BY l.created_at DESC",
-                $user_id
-            );
+						$user_id
+					);
 
-            $lists = $wpdb->get_results($owned_query);
-            error_log('Lists result: '.print_r($lists, true));
+					$lists = $wpdb->get_results($owned_query);
+					error_log('Lists result: '.print_r($lists, true));
 
-            // Add shared lists if requested
-            if ($include_shared) {
-                $shared_query = $wpdb->prepare(
-                    "SELECT l.*,
+					// Add shared lists if requested
+					if ($include_shared) {
+						$shared_query = $wpdb->prepare(
+							"SELECT l.*,
                     u.display_name as owner_name,
                     COUNT(DISTINCT i.id) as item_count,
                     s.permission_type,
@@ -456,35 +484,33 @@
                 WHERE s.user_id = %d
                 GROUP BY l.id
                 ORDER BY l.created_at DESC",
-                    $user_id
-                );
+							$user_id
+						);
 
-                $shared_lists = $wpdb->get_results($shared_query);
-                error_log('Shared lists: '.print_r($shared_lists, true));
-                $lists = [
-                    'owned' => $lists,
-                    'shared'=> $shared_lists,
-                ];
-            }
+						$shared_lists = $wpdb->get_results($shared_query);
+						error_log('Shared lists: '.print_r($shared_lists, true));
+						$lists = [
+							'owned' => $lists,
+							'shared'=> $shared_lists,
+						];
+					}
+					error_log('Lists: '.print_r($lists, true));
+					return [
+						'success' => true,
+						'lists' => $lists
+					];
+				} catch (Exception $e) {
+					JVB()->error()->log(
+						'favourites',
+						'Error getting available lists: ' . $e->getMessage(),
+						['user_id' => $user_id],
+						'error'
+					);
 
-            // Cache result
-            $this->cache->set($key, ['success' => true, 'lists'=>$lists], 'favourites_lists');
-
-            error_log('Lists: '.print_r($lists, true));
-            return [
-                'success' => true,
-                'lists' => $lists
-            ];
-        } catch (Exception $e) {
-            JVB()->error()->log(
-                'favourites',
-                'Error getting available lists: ' . $e->getMessage(),
-                ['user_id' => $user_id],
-                'error'
-            );
-
-            return [];
-        }
+					return [];
+				}
+			}
+		);
     }
 
     /**
@@ -501,7 +527,7 @@
             $user_id,
             $list_id
         );
-        $cache = $this->cache->get($key, 'favourites_lists');
+        $cache = $this->listsCache->get($key);
         if ($cache) {
             return new WP_REST_Response($cache);
         }
@@ -626,7 +652,7 @@
             ]
         ];
 
-        $this->cache->set($key, $response_data, 'favourites_lists');
+        $this->listsCache->set($key, $response_data);
         return new WP_REST_Response($response_data);
     }
 
@@ -798,23 +824,39 @@
      */
     public function getShares(WP_REST_Request $request):WP_REST_Response
     {
-        $list_id = $request->get_param('list_id');
-        $user_id = get_current_user_id();
+		$user_id = $request->get_param('user');
 
-        if (!$list_id) {
-            return $this->createErrorResponse(
-                self::ERROR_MISSING_PARAMS,
-                'List ID is required',
-                400
-            );
-        }
+		if (!$user_id || !$this->userCheck($user_id)) {
+			return new WP_REST_Response([
+				'success' => false,
+				'message' => 'Invalid user'
+			]);
+		}
 
-        $key = sprintf(
-            'user_%d_shares_for_list_%d',
-            $user_id,
-            $list_id
-        );
-        $cache = $this->cache->get($key, 'favourites_list_shares');
+		$list_id = $request->get_param('list_id');
+
+		if (!$list_id) {
+			return $this->createErrorResponse(
+				self::ERROR_MISSING_PARAMS,
+				'List ID is required',
+				400
+			);
+		}
+
+		$args = [
+			'user'	=> $user_id,
+			'list'	=> sanitize_text_field($list_id),
+		];
+		$key = $this->sharedListsCache->generateKey($args);
+		// Check HTTP cache headers
+		$cache_check = $this->checkHeaders($request, $key);
+		if ($cache_check) {
+			return $cache_check;
+		}
+
+
+
+        $cache = $this->sharedListsCache->get($key);
         if ($cache) {
             return new WP_REST_Response($cache);
         }
@@ -889,9 +931,10 @@
             ];
 
             // Cache the results
-            $this->cache->set($key, $response_data, 'favourites_list_shares');
+            $this->sharedListsCache->set($key, $response_data);
 
-            return new WP_REST_Response($response_data);
+			$response = new WP_REST_Response($response_data);
+			return $this->addCacheHeaders($response);
 
         } catch (Exception $e) {
             return $this->createErrorResponse(
@@ -1228,7 +1271,7 @@
                 'target_id' => $term_id,
                 'date_added' => $item->date_added ?? current_time('mysql'),
                 'notes' => $item->notes ?? '',
-                'title' => $term->name,
+                'title' => html_entity_decode($term->name),
                 'url' => get_term_link($term)
             ];
 
@@ -1405,8 +1448,8 @@
             }
             error_log('Results: '.print_r($results, true));
 
-            $this->cache->invalidate('favourite_counts_by_type_' . $user_id.'_all');
-            $this->cache->invalidate('favourite_counts_by_type_' . $user_id.'_not_all');
+            $this->cache->forget('favourite_counts_by_type_' . $user_id.'_all');
+            $this->cache->forget('favourite_counts_by_type_' . $user_id.'_not_all');
             return [
                 'success' => true,
                 'result' => $results
@@ -1600,8 +1643,10 @@
             $this->removeRelatedNotifications($user_id, $type, $target_id);
 
             // Invalidate cache
-            CacheManager::invalidateGroup($this->cache_name);
-            CacheManager::invalidateGroup('favourites_lists');
+			$this->cache->flush();
+			$this->listsCache->flush();
+			$this->sharedListsCache->flush();
+			$this->favouritesCache->flush();
 
             return [
                 'success' => true,
@@ -1685,9 +1730,9 @@
                 }
 
                 // Invalidate notification cache for this user
-                if (method_exists(JVB()->notification(), 'clearNotificationCache')) {
-                    JVB()->notification()->clearNotificationCache($owner_id);
-                }
+//                if (method_exists(JVB()->notification(), 'clearNotificationCache')) {
+//                    JVB()->notification()->clearNotificationCache($owner_id);
+//                }
             }
         } catch (Exception $e) {
             // Log but continue
@@ -1974,7 +2019,7 @@
             $wpdb->query('COMMIT');
 
             // Invalidate relevant caches
-            CacheManager::invalidateGroup('favourites_lists');
+			$this->listsCache->flush();
 
             return [
                 'success' => true,
@@ -2825,10 +2870,10 @@
             $list_name,
             $inviteButton,
             $inviteUrl,
-            jvbSignature()
+            JVB()->email()->signature()
         );
 
-        return jvbMail($email, $subject, $message);
+        return JVB()->email()->sendEmail($email, $subject, $message);
     }
 
     /**
@@ -3072,6 +3117,13 @@
         }
     }
 
+	public function maybeAcceptListInvite(int $user_id, string $email, array $data):void
+	{
+		if (array_key_exists('list_token', $data) && !empty($data['list_token'])) {
+			$this->acceptListInvitation($data['list_token'], $email);
+		}
+	}
+
     /**
      * Get the owner ID for a content item
      *
@@ -3258,47 +3310,47 @@
             switch ($operation->type) {
                 case 'favourites_batch':
                     $response = $this->processBatches($user_id, $data);
-                    CacheManager::invalidateGroup($this->cache_name);
+					$this->cache->flush();
                     return $response;
 
                 case 'favourite_notes':
                     $response =  $this->processNote($user_id, $data);
-                    CacheManager::invalidateGroup($this->cache_name);
+					$this->cache->flush();
                     return $response;
 
                 case 'favourite_list_create':
                     $response = $this->processListCreate($user_id, $data);
-                    CacheManager::invalidateGroup('favourites_lists');
+					$this->listsCache->flush();
                     return $response;
 
                 case 'favourite_list_update':
                     $response = $this->processUpdateList($user_id, $data);
-                    CacheManager::invalidateGroup('favourites_lists');
+					$this->listsCache->flush();
                     return $response;
 
                 case 'favourite_list_delete':
                     $response = $this->processListDeletion($user_id, $data);
-                    CacheManager::invalidateGroup('favourites_lists');
+                    $this->listsCache->flush();
                     return $response;
 
                 case 'favourite_list_add':
                     $response = $this->processAddToList($user_id, $data);
-                    CacheManager::invalidateGroup('favourites_lists');
+                    $this->listsCache->flush();
                     return $response;
 
                 case 'favourite_list_remove':
                     $response = $this->removeFromList($user_id, $data);
-                    CacheManager::invalidateGroup('favourites_lists');
+                    $this->listsCache->flush();
                     return $response;
 
                 case 'favourite_list_share':
                     $response = $this->shareList($user_id, $data);
-                    CacheManager::invalidateGroup('favourites_lists_shares');
+					$this->sharedListsCache->flush();
                     return $response;
 
                 case 'favourite_list_unshare':
                     $response = $this->unshareList($user_id, $data);
-                    CacheManager::invalidateGroup('favourites_lists_shares');
+					$this->sharedListsCache->flush();
                     return $response;
 
                 default:

--
Gitblit v1.10.0