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/managers/NotificationManager.php |  248 +++++++++++++++++++++++--------------------------
 1 files changed, 115 insertions(+), 133 deletions(-)

diff --git a/inc/managers/NotificationManager.php b/inc/managers/NotificationManager.php
index 5656303..5a02499 100644
--- a/inc/managers/NotificationManager.php
+++ b/inc/managers/NotificationManager.php
@@ -20,7 +20,11 @@
  */
 class NotificationManager
 {
-    protected object $cache;
+    protected Cache $userCache; //the individual notifications
+    protected Cache $contentCache;	//the 'shared' notifications on new content that has been created
+	protected Cache $artistsCache;
+	protected Cache $favouritesCache;
+	protected Cache $followerCache;
     protected string $campaign;
 	protected string $table = BASE.'notifications';
 	protected string $contentTable = BASE.'notifications_content';
@@ -139,7 +143,11 @@
      */
     public function __construct()
     {
-        $this->cache = CacheManager::for('notifications', WEEK_IN_SECONDS);
+        $this->userCache = Cache::for('userNotifications', WEEK_IN_SECONDS);
+        $this->contentCache = Cache::for('contentNotifications', WEEK_IN_SECONDS)->connect('post', true)->connect('taxonomy', true);
+        $this->artistsCache = Cache::for('artist', WEEK_IN_SECONDS)->connect('post');
+        $this->favouritesCache = Cache::for('favouritedUsers', WEEK_IN_SECONDS)->connect('favourites');
+        $this->followerCache = Cache::for('totalFollowers', WEEK_IN_SECONDS)->connect('favourites');
 
         // Add filter for bulk operation handling
         add_filter(BASE . 'handle_bulk_operation', [ $this, 'processOperation' ], 10, 3);
@@ -364,7 +372,7 @@
      */
     public function notifyVerifiedArtists(string $type, int|null $action_user_id = null, string $message = '', int|null $target_id = null, string|null $target_type = null, array|null $context = null):bool|WP_Error
     {
-        $artists = $this->getVerifiedArtists();
+        $artists = $this->getVerified('artist');
         return $this->addNotification($artists, $type, $action_user_id, $message, $target_id, $target_type, $context);
     }
     /**
@@ -381,7 +389,7 @@
      */
     public function notifyVerifiedPartners(string $type, int|null $action_user_id = null, string $message = '', int|null $target_id = null, string|null $target_type = null, array|null $context = null):bool|WP_Error
     {
-        $artists = $this->getVerifiedPartners();
+        $artists = $this->getVerified('partner');
         return $this->addNotification($artists, $type, $action_user_id, $message, $target_id, $target_type, $context);
     }
     /**
@@ -398,7 +406,7 @@
      */
     public function notifyEnthusiasts(string $type, int|null $action_user_id = null, string $message = '', int|null $target_id = null, string|null $target_type = null, array|null $context = null):bool|WP_Error
     {
-        $artists = $this->getEnthusiasts();
+        $artists = $this->getUserIDs('enthusiast');
         return $this->addNotification($artists, $type, $action_user_id, $message, $target_id, $target_type, $context);
     }
     /**
@@ -415,7 +423,7 @@
      */
     public function notifyEveryone(string $type, int|null $action_user_id = null, string $message = '', int|null $target_id = null, string|null $target_type = null, array|null $context = null):bool|WP_Error
     {
-        $artists = $this->getEveryone();
+        $artists = $this->getUserIDs(array_keys(JVB_USER));
         return $this->addNotification($artists, $type, $action_user_id, $message, $target_id, $target_type, $context);
     }
 
@@ -1100,7 +1108,7 @@
         }
 
         $content = '';
-        $cache   = CacheManager::for('digest_content', HOUR_IN_SECONDS * 6); // Cache for 6 hours
+        $cache   = Cache::for('digest_content', HOUR_IN_SECONDS * 6); // Cache for 6 hours
 
         // Group updates by artist
         $updates_by_artist = [];
@@ -1519,19 +1527,16 @@
     protected function getArtistData(int $user_id):array|false
     {
         // Try to get from cache
-        $cache_key = "artist_data_{$user_id}";
-        $cached = $this->cache->get($cache_key);
+		$artist_id = get_user_meta($user_id, BASE . 'link', true);
+		if (!$artist_id || $artist_id === '') {
+			return false;
+		}
+        $cached = $this->artistsCache->get($artist_id);
 
         if ($cached !== false) {
             return $cached;
         }
 
-        // Get artist post ID from user meta
-        $artist_id = get_user_meta($user_id, BASE . 'link', true);
-        if (!$artist_id) {
-            return false;
-        }
-
         // Get basic artist data
         $artist_post = get_post($artist_id);
         if (!$artist_post) {
@@ -1548,7 +1553,7 @@
         ];
 
         // Cache the result
-        $this->cache->set($cache_key, $data, null,'artists');
+        $this->artistsCache->set($artist_id, $data);
 
         return $data;
     }
@@ -1560,19 +1565,25 @@
      */
     protected function getFollowedArtists(int $user_id):array
     {
-        global $wpdb;
-        $favourites_table = $wpdb->prefix . BASE . 'favourites';
+		return $this->favouritesCache->remember(
+			$user_id,
+			function() use ($user_id) {
+				global $wpdb;
+				$favourites_table = $wpdb->prefix . BASE . 'favourites';
 
-        // Get artists this user has favourited
-        return $wpdb->get_col($wpdb->prepare(
-            "SELECT f.target_id
-         FROM {$favourites_table} f
-         JOIN {$wpdb->posts} p ON f.target_id = p.ID
-         WHERE f.user_id = %d
-         AND f.type = 'artist'
-         AND p.post_status = 'publish'",
-            $user_id
-        ));
+				// Get artists this user has favourited
+				return $wpdb->get_col($wpdb->prepare(
+				"SELECT f.target_id
+					 FROM {$favourites_table} f
+					 JOIN {$wpdb->posts} p ON f.target_id = p.ID
+					 WHERE f.user_id = %d
+					 AND f.type = 'artist'
+					 AND p.post_status = 'publish'",
+					$user_id
+				));
+			}
+		);
+
     }
 
     /**
@@ -1582,15 +1593,21 @@
      */
     protected function getFollowerCount(int $artist_id):int
     {
-        global $wpdb;
-        $favourites_table = $wpdb->prefix . BASE . 'favourites';
+		return $this->followerCache->remember(
+			$artist_id,
+			function() use ($artist_id) {
+				global $wpdb;
+				$favourites_table = $wpdb->prefix . BASE . 'favourites';
 
-        return $wpdb->get_var($wpdb->prepare(
-            "SELECT COUNT(DISTINCT user_id)
-         FROM {$favourites_table}
-         WHERE target_id = %d AND type = 'artist'",
-            $artist_id
-        ));
+				return $wpdb->get_var($wpdb->prepare(
+					"SELECT COUNT(DISTINCT user_id)
+					 FROM {$favourites_table}
+					 WHERE target_id = %d AND type = 'artist'",
+					$artist_id
+				));
+			}
+		);
+
     }
 
     /**
@@ -1598,27 +1615,16 @@
      *
      * @return string
      */
-    protected function pluralize(string $word):string
+    protected function pluralize(string $content):string
     {
-        $irregular = [
-            'tattoo' => 'tattoos',
-            'piercing' => 'piercings',
-            'artwork' => 'artwork',
-            'news' => 'news',
-            'offer' => 'offers',
-            'event' => 'events'
-        ];
-
-        if (isset($irregular[$word])) {
-            return $irregular[$word];
-        }
-
-        // Simple pluralization rules
-        if (str_ends_with($word, 'y')) {
-            return substr($word, 0, -1) . 'ies';
-        }
-
-        return $word . 's';
+        if (array_key_exists($content, JVB_CONTENT)) {
+			return JVB_CONTENT[$content]['plural'];
+		} elseif (array_key_exists($content, JVB_TAXONOMY)) {
+			return JVB_TAXONOMY[$content]['plural'];
+		} elseif (array_key_exists($content, JVB_USER)) {
+			return JVB_USER[$content]['plural'];
+		}
+		return $content;
     }
 
     /**
@@ -1628,9 +1634,8 @@
      */
     protected function clearNotificationCache(int $user_id):void
     {
-
-        $this->cache->delete("user_{$user_id}_notifications_", 'notifications_' . $user_id);
-        $this->cache->delete("user_{$user_id}_content_notifications_", 'notifications_' . $user_id);
+		$this->userCache->forget($user_id);
+		$this->contentCache->forget($user_id);
     }
 
     /**
@@ -1697,78 +1702,56 @@
     /**
      * @return array
      */
-    protected function getVerifiedArtists():array
+    protected function getVerified(string|array $userRoles):array
     {
-        $artists = $this->cache->get('verified_artists');
-        if ($artists) {
-            return $artists;
-        }
+		$userRoles = $this->checkRoles($userRoles);
 
-        $artists = get_users([
-            'role'          => BASE.'artist',
-            'capability'    => 'skip_moderation',
-            'fields'        => 'ID'
-        ]);
-
-        $this->cache->set('verified_artists', $artists);
-        return $artists;
+		if (empty($userRoles)) {
+			return [];
+		}
+		$cache = Cache::for('verifiedUsers', DAY_IN_SECONDS)->connect('user',true);
+		return $cache->remember(
+			'verified',
+			function() use ($userRoles) {
+				return get_users([
+					'role'          => $userRoles,
+					'capability'    => 'skip_moderation',
+					'fields'        => 'ID'
+				]);
+			}
+		);
     }
 
-    /**
-     * @return array
-     */
-    protected function getVerifiedPartners():array
-    {
-        $partners = $this->cache->get('verified_partners');
-        if ($partners) {
-            return $partners;
-        }
+	protected function getUserIDs(array|string $roles):array
+	{
+		$roles = $this->checkRoles($roles);
+		if (empty($roles)) {
+			return [];
+		}
+		$cache = Cache::for('everyone', DAY_IN_SECONDS)->connect('user', true);
+		return $cache->remember(
+			$cache->generateKey($roles),
+			function() use ($roles) {
+				return get_users([
+					'role'	=> $roles,
+					'fields'	=> 'ID'
+				]);
+			}
+		);
+	}
 
-        $partners = get_users([
-            'role'          => BASE.'partner',
-            'capability'    => 'skip_moderation',
-            'fields'        => 'ID'
-        ]);
+	protected function checkRoles(string|array $roles):array
+	{
+		if (!is_array($roles)) {
+			$roles = explode(',',$roles);
+		}
 
-        $this->cache->set('verified_partners', $partners);
-        return $partners;
-    }
-
-    /**
-     * @return array
-     */
-    protected function getEnthusiasts():array
-    {
-        $enthusiasts = $this->cache->get('enthusiasts');
-        if ($enthusiasts) {
-            return $enthusiasts;
-        }
-
-        $enthusiasts = get_users([
-            'role'          => BASE.'enthusiast',
-            'fields'        => 'ID'
-        ]);
-
-        $this->cache->set('enthusiasts', $enthusiasts);
-        return $enthusiasts;
-    }
-
-    /**
-     * @return array
-     */
-    protected function getEveryone():array
-    {
-        $users = $this->cache->get('users');
-        if ($users) {
-            return $users;
-        }
-        $users = get_users([
-            'role__in' => [BASE.'artist', BASE.'enthusiast', BASE.'partner'],
-            'fields'    => 'ID'
-        ]);
-        $this->cache->set('users', $users);
-        return $users;
-    }
+		return array_map(function ($r) {
+			return jvbCheckBase(trim($r));
+		}, array_filter($roles, function ($r) {
+			return array_key_exists(trim($r), JVB_USER);
+		}));
+	}
 
     /**
      * @param int $userID
@@ -1777,13 +1760,12 @@
      */
     protected function checkUser(int $userID):bool
     {
-        $checked = $this->cache->get($userID, 'checked_users');
-        if ($checked) {
-            return $checked;
-        }
-        $test = (bool)get_userdata($userID);
-
-        $this->cache->set($userID, $test, null, 'checked_users');
-        return $test;
+		$cache = Cache::for('checked_users', DAY_IN_SECONDS)->connect('user', true);
+		return $cache->remember(
+			$userID,
+			function() use ($userID) {
+				return (bool)get_userdata($userID)?:null;
+			}
+		);
     }
 }

--
Gitblit v1.10.0