From 8c6502de2f8ec2bd8382cd6945c327d7be400e14 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Wed, 28 Jan 2026 05:34:41 +0000
Subject: [PATCH] =Queue cleanup - seems to be working enough to get legacy before and after going!

---
 inc/rest/routes/FeedRoutes.php |  293 +++++++++++++++++++++++++++++++---------------------------
 1 files changed, 156 insertions(+), 137 deletions(-)

diff --git a/inc/rest/routes/FeedRoutes.php b/inc/rest/routes/FeedRoutes.php
index 92375c2..8c50485 100644
--- a/inc/rest/routes/FeedRoutes.php
+++ b/inc/rest/routes/FeedRoutes.php
@@ -1,7 +1,7 @@
 <?php
 namespace JVBase\rest\routes;
 
-use JVBase\managers\CacheManager;
+use JVBase\managers\Cache;
 use JVBase\rest\RestRouteManager;
 use JVBase\integrations\Umami;
 use JVBase\meta\MetaManager;
@@ -32,39 +32,24 @@
 		$this->cache_name = 'feed';
 		$this->cache_ttl = 86400;
 		parent::__construct();
-		$this->cache->clear();
+		$this->cache
+			->connect('post', true)
+			->connect('taxonomy', true)
+			->connect('user', true);
+
+		if (JVB_TESTING) {
+			$this->cache->flush();
+		}
+
 	}
 
 	public function init():void
 	{
-		$this->cache->clear();
 		$this->checker = Checker::getInstance();
 
-		if (jvbSiteUsesUmami()) {
+		if (Features::hasIntegration('umami')) {
 			$this->tracker = JVB()->connect('umami');
 		}
-		$this->setupCacheConnections();
-	}
-
-	/**
-	 * Set up cache connections for automatic invalidation
-	 */
-	protected function setupCacheConnections(): void
-	{
-		// Connect to all content types with show_feed
-		$contentTypes = Features::getTypesWithFeature('show_feed', 'content');
-		foreach ($contentTypes as $type) {
-			CacheManager::for('feed_item_'.$type)->connectTo('post');
-			$this->cache->connectTo('post', $type);
-		}
-
-		// Connect to all taxonomies with show_feed
-		$taxonomies = Features::getTypesWithFeature('show_feed', 'taxonomy');
-		foreach ($taxonomies as $tax) {
-			CacheManager::for('feed_item_'.$tax)->connectTo('taxonomy');
-			$this->cache->connectTo('taxonomy', $tax);
-		}
-
 	}
 
 	/**
@@ -99,21 +84,20 @@
 				$post = get_post($postID);
 				$type = jvbNoBase($post->post_type);
 				$metaType = 'post';
-				$cache = CacheManager::for('feed_item_'.$type);
 				break;
 			default:
 				$post = get_term($postID, jvbCheckBase($type));
 				$type = jvbNoBase($type);
 				$metaType = 'term';
-				$cache = CacheManager::for('feed_item_'.$type);
 				break;
 		}
 		if (!$post || is_wp_error($post)) {
 			return [];
 		}
-//
-//		return $cache->remember($postID,
-//			function() use ($postID, $type, $metaType, $post, $skip) {
+
+		return $this->cache->remember(
+			$postID,
+			function() use ($postID, $type, $metaType, $post, $skip) {
 				$config = null;
 				switch ($metaType) {
 					case 'post':
@@ -146,33 +130,7 @@
 				];
 
 				//Format Taxonomies
-				$temp = array_filter($fields, function($field) {
-					return $field['type'] === 'taxonomy';
-				});
-				foreach ($temp as $key => $config) {
-					if (array_key_exists($key, $out['fields']) && $out['fields'][$key] !== '') {
-						$IDs = array_map('absint', explode(',', $out['fields'][$key]));
-						$data = [];
-						$icon = JVB_TAXONOMY[$config['taxonomy']]['icon']??jvbDefaultIcon();
-						foreach ($IDs as $ID) {
-							$term = get_term($ID, jvbCheckBase($config['taxonomy']));
-							if ($term && !is_wp_error($term)) {
-								$data[$ID] = [
-									'id' 	=> $ID,
-									'icon'	=> $icon,
-									'name'	=> $term->name,
-									'url'	=> get_term_link($ID, jvbCheckBase($config['taxonomy'])),
-								];
-								if ($this->tracker) {
-									$data[$ID]['umami_click'] = $this->tracker->trackClick($ID, $config['taxonomy'], ['from' => $type.'_'.$postID]);
-								}
-							}
-						}
-						if (!empty($data)) {
-							$out['fields'][$key] = $data;
-						}
-					}
-				}
+				$out['taxonomies'] = $this->extractTaxonomies($values, $postID, $type);
 
 				//Add images
 				$imgIDs = [];
@@ -208,17 +166,19 @@
 							$out['user_id'] = $owner;
 						}
 						$out['url'] = get_term_link($postID, $type);
+						$out['title'] = html_entity_decode($post->name);
 						break;
 					case 'post':
 						$out['date'] = $post->post_date;
+						$out['modified'] = $post->post_modified;
 						$out['user_id'] = (int)$post->post_author;
 						$out['url'] = get_the_permalink($postID);
+						$out['title']= get_the_title($postID);
 						break;
 				}
-//				return $out;
-//			}
-//		);
-		return $out;
+				return $out;
+			}
+		);
 	}
 
 
@@ -263,6 +223,8 @@
 		$children = get_children(['post_parent' => $post->ID, 'orderby' => 'date', 'order' => 'ASC', 'post_status' => ['publish'], 'fields'=> 'ids']);
 		array_unshift($children, $post->ID);
 
+		$item['taxonomies'] = $this->extractTaxonomies($item['fields'], $postID, jvbNoBase($post->post_type));
+
 		$subFields = [];
 		$images = [];
 		foreach ($children as $child) {
@@ -270,41 +232,91 @@
 			$f = $meta->getAll($this->timelineUniqueFields);
 			$f =  ['id' => $child] + $f;
 			$subFields[] = $f;
-
+			$item['taxonomies'] = array_merge($item['taxonomies'], $this->extractTaxonomies($f, $postID, jvbNoBase($post->post_type)));
 			$images[$f['post_thumbnail']] = jvbImageData((int) $f['post_thumbnail']);
 		}
-		$item['fields']['order'] = $subFields;
+		$item['number'] = (int)get_post_meta($post->ID,BASE.'number', true);
+		$item['fields']['before'] = get_post_thumbnail_id($children[0]);
+		$item['fields']['after'] = get_post_thumbnail_id($children[array_key_last($children)]);
+
+		$item['fields']['timeline'] = $subFields;
 		$item['images'] = $item['images'] + $images;
 
+
 		return $item;
 	}
+	protected function extractTaxonomies(array $fields, int $postID, string $content):array {
+		$taxonomies = [];
+		foreach ($fields as $key => $value) {
+			if (empty($value)) {
+				continue;
+			}
+			if (!array_key_exists($key, JVB_TAXONOMY)) {
+				continue;
+			}
 
-	protected function formatTaxonomy(WP_Term $term, int $postID, string $type)
+			$taxConfig = JVB_TAXONOMY[$key];
+			if (isset($taxConfig['public']) && $taxConfig['public'] === false) {
+				continue;
+			}
+			$terms = array_map('absint', explode(',', $value));
+			$terms = array_filter($terms); // Remove 0 values
+
+			if (empty($terms)) {
+				continue;
+			}
+			foreach($terms as $termID) {
+				$term = get_term($termID, jvbCheckBase($key));
+				if ($term && !is_wp_error($term)) {
+					$taxonomies[$key][$termID] = $this->formatTaxonomy($term, $postID, $content);
+				}
+			}
+		}
+		return $taxonomies;
+	}
+
+	protected function formatTaxonomy(WP_Term|int $term, int $postID, string $type)
 	{
-		return [
-			'ID' => $term->term_id,
-			'title' => htmlspecialchars_decode($term->name),
-			'url' => get_term_link($term->term_id, $term->taxonomy),
-			'umami_click' => $this->tracker->trackTaxonomyClick($term->term_id, $term->taxonomy, [
-				'from' => $type . '_' . $postID
-			])
-		];
+		return $this->cache->remember(
+			$term->term_id,
+			function () use ($term, $postID, $type) {
+				$base = [
+					'ID' => $term->term_id,
+					'title' => html_entity_decode($term->name),
+					'url' => get_term_link($term->term_id, $term->taxonomy),
+				];
+				if ($this->tracker) {
+					$base['umami_click'] =$this->tracker->trackTaxonomyClick($term->term_id, $term->taxonomy, [
+						'from' => $type . '_' . $postID
+					]);
+				}
+				return $base;
+			}
+		);
 	}
 
 	protected function getAuthorData(WP_Post $post)
 	{
-		$author = $this->cache->get($post->post_author, 'author_data');
-		if (!$author) {
-			$author = [
-				'id' => $post->post_author,
-				'label' => 'Artist',
-				'value' => get_the_author_meta('display_name', $post->post_author),
-				'icon' => 'artist',
-				'url' => get_the_permalink(get_user_meta($post->post_author, BASE . 'link', true)),
-			];
-			$this->cache->set($post->post_author, $author, 'author_data');
-		}
-		return $author;
+		$author = $post->post_author;
+		$userLink = get_user_meta($author, BASE.'link', true);
+		return $this->cache->remember(
+			$userLink,
+			function () use ($userLink, $author) {
+				$label = jvbUserRole($author);
+				if (array_key_exists($label, JVB_USER)) {
+					$label = JVB_USER[$label]['label'];
+				} else {
+					$label = 'Artist';
+				}
+				return [
+					'id'	=> $userLink,
+					'label'	=> $label,
+					'value'	=> get_the_title($userLink),
+					'icon'	=> 'user',
+					'url'	=> get_the_permalink($userLink),
+				];
+			}
+		);
 	}
 
 	protected function getTaxonomies(int $postID, string $content): array
@@ -320,16 +332,23 @@
 					'icon' => $config,
 					'title' => JVB_TAXONOMY[$config]['plural'],
 					'terms' => array_map(function ($term) use ($tax, $postID, $content) {
-						return [
-							'ID' => $term->term_id,
-							'title' => htmlspecialchars_decode($term->name),
-							'url' => get_term_link($term->term_id, $tax),
-							'umami_click' => $this->tracker->trackTaxonomyClick($term->term_id, $tax, [
-								'from' => $content . '_' . $postID
-							])
-						];
+						$item = $this->cache->remember(
+							$term->term_id,
+							function() use ($term, $tax, $content, $postID) {
+								return [
+									'ID'	=> $term->term_id,
+									'title'	=> html_entity_decode($term->name),
+									'url'	=> get_term_link($term->term_id, $tax),
+								];
+							}
+						);
+						$item['umami_click'] = $this->tracker->trackTaxonomyClick($term->term_id, $tax, [
+							'from'	=> $content.'_'.$postID
+						]);
+						return $item;
 					}, $terms),
 				];
+
 			}
 		}
 		return $out;
@@ -363,47 +382,46 @@
 		$args = $this->applyOrderFilters($args, $data);
 		$args = $this->applyDateFilters($args, $data);
 
-		$args = $this->applyFavouritesFilter($args, $data);
-		return $args;
+		return $this->applyFavouritesFilter($args, $data);
 	}
 
-	protected function applyTaxonomyFilters(array $args, array $data): array
-	{
-		if (!isset($data['taxonomy']) || empty($data['taxonomy'])) {
-			return $args;
-		}
-
-		$taxonomyFilters = $data['taxonomy'];
-
-		// Validate taxonomies exist and sanitize
-		$validFilters = [];
-		foreach ($taxonomyFilters as $taxonomy => $terms) {
-			if (!taxonomy_exists(jvbCheckBase($taxonomy))) {
-				continue;
-			}
-
-			$validFilters[] = [
-				'taxonomy' => jvbCheckBase($taxonomy),
-				'field' => 'term_id',
-				'terms' => array_map('absint', (array)$terms),
-				'operator' => 'IN'
-			];
-		}
-
-		if (empty($validFilters)) {
-			return $args;
-		}
-
-		// Determine relation based on match filter
-		$relation = ($data['match'] ?? 'all') === 'all' ? 'AND' : 'OR';
-
-		$args['tax_query'] = array_merge(
-			['relation' => $relation],
-			$validFilters
-		);
-
-		return $args;
-	}
+//	protected function applyTaxonomyFilters(array $args, array $data): array
+//	{
+//		if (!array_key_exists('taxonomy', $data) || empty($data['taxonomy'])) {
+//			return $args;
+//		}
+//
+//		$taxonomyFilters = $data['taxonomy'];
+//
+//		// Validate taxonomies exist and sanitize
+//		$validFilters = [];
+//		foreach ($taxonomyFilters as $taxonomy => $terms) {
+//			if (!taxonomy_exists(jvbCheckBase($taxonomy))) {
+//				continue;
+//			}
+//
+//			$validFilters[] = [
+//				'taxonomy' => jvbCheckBase($taxonomy),
+//				'field' => 'term_id',
+//				'terms' => array_map('absint', (array)$terms),
+//				'operator' => 'IN'
+//			];
+//		}
+//
+//		if (empty($validFilters)) {
+//			return $args;
+//		}
+//
+//		// Determine relation based on match filter
+//		$relation = ($data['match'] ?? 'all') === 'all' ? 'AND' : 'OR';
+//
+//		$args['tax_query'] = array_merge(
+//			['relation' => $relation],
+//			$validFilters
+//		);
+//
+//		return $args;
+//	}
 
 	/**
 	 * @param WP_REST_Request $request
@@ -413,19 +431,17 @@
 	public function handleFeedRequest(WP_REST_Request $request): WP_REST_Response
 	{
 		$args = $this->buildRequestArgs($request);
-		$cacheContext = $this->buildCacheContext($args, $request);
+		$key = $this->cache->generateKey($args);
 
 		// Check HTTP cache headers first
 		$cache_check = $this->checkHeaders(
 			$request,
-			$cacheContext['content_types'],
-			$cacheContext['additional_params']
+			$key
 		);
 		if ($cache_check) {
 			return $cache_check; // Returns 304 Not Modified
 		}
 
-		$key = $this->cache->generateKey($args);
 		$cached = $this->cache->get($key);
 		if ($cached) {
 			if ($request->get_param('highlight')) {
@@ -439,7 +455,7 @@
 		// Fetch and format items
 		$items = $this->fetchFeedItems($args);
 
-		$ttl = (str_contains($args['orderby'], 'RAND')) ? 1800 : $this->cache_ttl;
+		$ttl = (str_contains($args['orderby'], 'RAND')) ? 300 : $this->cache_ttl;
 		$this->cache->set($key, $items, $ttl);
 
 		if ($request->get_param('highlight')) {
@@ -1243,6 +1259,7 @@
 				// Get content types with show_feed
 				$contentTypes = Features::getTypesWithFeature('show_feed', 'content');
 				foreach ($contentTypes as $slug) {
+					$this->cache->tag('content:'.$slug);
 					$contentConfig = JVB_CONTENT[$slug] ?? null;
 					if (!$contentConfig) continue;
 
@@ -1263,6 +1280,8 @@
 						continue;
 					}
 
+					$this->cache->tag('taxonomy:'.$slug);
+
 					$config[$slug] = [
 						'type' => 'taxonomy',
 						'singular' => $taxConfig['singular'] ?? ucfirst($slug),

--
Gitblit v1.10.0