From d7dbe7fee362d587dfc334135d9581b6216a4295 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 23 Nov 2025 04:13:56 +0000
Subject: [PATCH] =Timeline block, and feed block updated. DataStore.js refactored to not block rendering

---
 inc/rest/routes/TermRoutes.php |  237 ++++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 163 insertions(+), 74 deletions(-)

diff --git a/inc/rest/routes/TermRoutes.php b/inc/rest/routes/TermRoutes.php
index 269dc2a..1f8c726 100644
--- a/inc/rest/routes/TermRoutes.php
+++ b/inc/rest/routes/TermRoutes.php
@@ -5,6 +5,7 @@
 use JVBase\rest\RestRouteManager;
 use JVBase\managers\TaxonomyRelationships;
 use JVBase\managers\UserTermsManager;
+use JVBase\utility\Features;
 use WP_REST_Request;
 use WP_REST_Response;
 use Exception;
@@ -149,6 +150,14 @@
     public function getTermDetails(WP_REST_Request $request):WP_REST_Response
     {
         $data = $request->get_params();
+		// Collect all taxonomies being queried
+		$taxonomies = array_keys($data);
+
+		// Check HTTP cache headers
+		$cache_check = $this->checkHeaders($request, $taxonomies);
+		if ($cache_check) {
+			return $cache_check;
+		}
         $terms = [];
         foreach ($data as $tax => $IDs) {
             $args = [
@@ -158,9 +167,10 @@
 
             $terms[$tax] = $this->formatTerms($args, BASE.$tax);
         }
-        return new WP_REST_Response([
+        $response = new WP_REST_Response([
             'items' => $terms,
         ]);
+		return $this->addCacheHeaders($response);
     }
 
     /**
@@ -171,7 +181,19 @@
     public function handleTermSelectionRequest(WP_REST_Request $request):WP_REST_Response
     {
 		$data = $request->get_params();
-		$taxonomy = jvbCheckBase($data['taxonomy']);
+		$taxonomy = jvbCheckBase($data['taxonomy'])??'';
+
+		// Check HTTP cache headers
+		$cache_check = $this->checkHeaders($request, $taxonomy);
+		if ($cache_check) {
+			error_log('Header Check failed');
+			return $cache_check;
+		}
+
+		// Handle batch request (multiple taxonomies)
+		if (str_contains($taxonomy, ',')) {
+			return $this->handleBatchTermRequest($taxonomy, $data, $request);
+		}
 
 		if (array_key_exists('termIDs', $data)) {
 			$args = [
@@ -182,7 +204,8 @@
 			$key = $this->cache->generateKey($args);
 			$cached = $this->cache->get($key);
 			if ($cached) {
-				return new WP_REST_Response($cached);
+				$response = new WP_REST_Response($cached);
+				return $this->addCacheHeaders($response);
 			}
 
 			$formatted = $this->formatTerms($args, $taxonomy);
@@ -190,22 +213,25 @@
 				'items'	=> $formatted
 			];
 			$this->cache->set($key, $response);
-			return new WP_REST_Response($response);
+			$response = new WP_REST_Response($response);
+			return $this->addCacheHeaders($response);
 		}
 		if (array_key_exists('content', $data)) {
 			// If content_type is provided, use the specialized endpoint
 			$content_type = $request->get_param('content');
 			global $feed_types;
 			if (taxIsJVBContentTax($content_type)) {
-				return $this->getTermsForContentType($request);
+				$response = $this->getTermsForContentType($request);
+				return $this->addCacheHeaders($response);
 			}
 		}
 
         $taxonomy = BASE.$request->get_param('taxonomy');
         $search = $request->get_param('search');
-        $parent = (int)$request->get_param('parent');
-        $page = max(1, (int)$request->get_param('page'));
-        $per_page = max(20, (int)$request->get_param('per_page'));
+
+		$parent = (int)$data['parent']??0;
+		$page = max(1, (int)($data['page']??1));
+		$per_page = 25;
 
         if (!taxonomy_exists($taxonomy)) {
             return new WP_REST_Response([
@@ -225,7 +251,9 @@
 
         // If searching, handle differently
         if (!empty($search)) {
-            return $this->handleTermSearch($request);
+			error_log('Handling search...');
+            $response = $this->handleTermSearch($request);
+			return $this->addCacheHeaders($response);
         }
 
         // Get terms for current level with child count
@@ -248,7 +276,7 @@
             $related = $manager->getUserTermIDs($userID, $taxonomy);
 
             if (empty($related)) {
-                return new WP_REST_Response([
+                $response = new WP_REST_Response([
                     'items' => [],
                     'pagination' => [
                         'page' => 1,
@@ -258,6 +286,7 @@
                         'has_more' => false
                     ]
                 ]);
+				return $this->addCacheHeaders($response);
             }
 
             $args['include'] = $related;
@@ -270,7 +299,7 @@
             $related = $manager->getRelatedTerms($ID, BASE.$request->get_param('taxonomy'));
 
             if (empty($related)) {
-                return new WP_REST_Response([
+                $response = new WP_REST_Response([
                     'items' => [],
                     'pagination' => [
                         'page' => 1,
@@ -280,6 +309,7 @@
                         'has_more' => false
                     ]
                 ]);
+				return $this->addCacheHeaders($response);
             }
             $args['tax_query'] = [
                 'taxonomy'  => $taxonomy,
@@ -328,7 +358,7 @@
                 $args['include'] = $related_term_ids;
             } else {
                 // No related terms found, return empty result
-                return new WP_REST_Response([
+                $response =  new WP_REST_Response([
                     'items' => [],
                     'pagination' => [
                         'page' => 1,
@@ -338,6 +368,8 @@
                         'has_more' => false
                     ]
                 ]);
+
+				return $this->addCacheHeaders($response);
             }
         }
 
@@ -345,9 +377,10 @@
 
         $key = $this->cache->generateKey($args);
         $cache = $this->cache->get($key);
-		$cache = false;
+
         if ($cache) {
-            return $cache;
+            $response = new WP_REST_Response($cache);
+			return $this->addCacheHeaders($response);
         }
 
         $formatted_terms = $this->formatTerms($args, $taxonomy);
@@ -375,48 +408,114 @@
         ];
 
         $this->cache->set($key, $response);
-        return new WP_REST_Response($response);
+        $response = new WP_REST_Response($response);
+		return $this->addCacheHeaders($response);
     }
 
+	protected function handleBatchTermRequest(string $taxonomy, array $data, WP_REST_Request $request):WP_REST_Response
+	{
+		$taxonomies = array_map('trim', explode(',', $taxonomy));
+		$all_terms = [];
+		$parent = (int)$data['parent']??0;
+		$page = max(1, (int)($data['page']??1));
+		$per_page = 25;
+		$mainArgs = [
+			'hide_empty'=> false,
+			'parent'	=> $parent,
+			'number'	=> $per_page,
+			'orderby'	=> 'name',
+			'offset'	=> ($page -1) * $per_page,
+		];
+
+		foreach ($taxonomies as $taxonomy) {
+			if (!taxonomy_exists(BASE.$taxonomy)) {
+				continue;
+			}
+			$args = $mainArgs;
+			$args['taxonomy'] = BASE.$taxonomy;
+
+			$all_terms = array_merge($all_terms, $this->formatTerms($args, $taxonomy));
+		}
+
+		$response = [
+			'items'	=> $all_terms,
+			'pagination'=> [
+				'page' => $page,
+				'per_page'=> $per_page,
+				'has_more' => true,
+			]
+		];
+
+		$response = new WP_REST_Response($response);
+		return $this->addCacheHeaders($response);
+	}
+
+
     /**
      * @param array $args
      * @param string $taxonomy
      *
      * @return array
      */
-    protected function formatTerms(array $args, string $taxonomy):array
-    {
-        $terms = get_terms($args);
+	protected function formatTerms(array $args, string $taxonomy): array
+	{
+		return $this->cache->remember(
+			$this->cache->generateKey($args),
+			function() use ($args, $taxonomy) {
+				$terms = get_terms($args);
 
-        if (is_wp_error($terms)) {
-            return [];
-        }
+				if (is_wp_error($terms)) {
+					return [];
+				}
+
+				$formatted_terms = [];
+				foreach ($terms as $term) {
+					$formatted_terms[] = $this->formatSingleTerm($term, $taxonomy, true);
+				}
+
+				return $formatted_terms;
+			}
+		);
 
 
+	}
 
-        $formatted_terms = [];
-        foreach ($terms as $term) {
-            // Check for children explicitly
-            $children_args = [
-                'taxonomy' => $taxonomy,
-                'parent' => $term->term_id,
-                'fields' => 'count',
-                'hide_empty' => false
-            ];
-            $count = wp_count_terms($children_args);
-            $has_children = !is_wp_error($count) && $count > 0;
+	/**
+	 * Format a single term with caching
+	 *
+	 * @param object $term WP_Term object
+	 * @param string $taxonomy Full taxonomy name
+	 *
+	 * @return array Formatted term data
+	 */
+	protected function formatSingleTerm(object $term, string $taxonomy): array
+	{
+		$cache_key = "{$term->term_id}_{$taxonomy}";
 
-            $formatted_terms[] = [
-                'id' => $term->term_id,
-                'name' => $term->name,
-                'parent' => $term->parent,
-                'path' => $this->getTermPath($term->term_id, $term->name, $taxonomy),
-                'hasChildren' => $has_children,
-            ];
-        }
+		return $this->cache->remember($cache_key, function() use ($term, $taxonomy) {
+			$data = [
+				'id' => $term->term_id,
+				'name' => $term->name,
+				'slug' => $term->slug,
+				'parent' => $term->parent,
+				'path' => $this->getTermPath($term->term_id, $term->name, $taxonomy),
+				'taxonomy' => jvbNoBase($term->taxonomy),
+				'count' => $term->count,
+			];
 
-        return $formatted_terms;
-    }
+			$children_args = [
+				'taxonomy' => $taxonomy,
+				'parent' => $term->term_id,
+				'fields' => 'count',
+				'hide_empty' => false
+			];
+			$count = wp_count_terms($children_args);
+			$data['hasChildren'] = !is_wp_error($count) && $count > 0;
+
+
+			return $data;
+		});
+	}
 
     /**
      * @param WP_REST_Request $request
@@ -467,16 +566,10 @@
         $total_terms = wp_count_terms($count_args);
 
         $formatted_terms = [];
-        foreach ($terms as $term) {
-            $formatted_terms[$term->term_id] = [
-                'id'            => $term->term_id,
-                'name'          => $term->name,
-                'parent'        => $term->parent,
-                'path'          => $this->getTermPath($term->term_id, $term->name, $taxonomy),
-                'hasChildren'   => (bool)$term->has_children,
-                'count'         => (int)$term->count
-            ];
-        }
+		foreach ($terms as $term) {
+			// Search results show path, so includeChildren = false for performance
+			$formatted_terms[] = $this->formatSingleTerm($term, $taxonomy, false);
+		}
 
         // Calculate pagination info
         $total_pages = ceil($total_terms / $per_page);
@@ -667,15 +760,12 @@
             $formatted_terms = [];
             $is_hierarchical = is_taxonomy_hierarchical($taxonomy);
 
-            foreach ($terms as $term) {
-                $formatted_terms[$term->term_id] = [
-                    'id' => $term->term_id,
-                    'name' => $term->name,
-                    'count' => $term->count,
-                    'path' => $this->getTermPath($term->term_id, $term->name, $taxonomy),
-                    'relationship_strength' => $term->relationship_count ?? 0
-                ];
-            }
+			foreach ($terms as $term) {
+				$formatted = $this->formatSingleTerm($term, $taxonomy, false);
+				// Add relationship strength which is unique to this method
+				$formatted['relationship_strength'] = $term->relationship_count ?? 0;
+				$formatted_terms[] = $formatted;
+			}
 
             // Build response
             $total_pages = ceil($total / $per_page);
@@ -759,16 +849,10 @@
             $is_hierarchical = is_taxonomy_hierarchical($taxonomy);
 
             // Format terms
-            $formatted_terms = [];
-            foreach ($terms as $term) {
-                $formatted_terms[$term->term_id] = [
-                    'id' => $term->term_id,
-                    'name' => $term->name,
-                    'count' => $term->count,
-                    'parent' => $term->parent,
-                    'path' => $this->getTermPath($term->term_id, $term->name, $taxonomy)
-                ];
-            }
+			$formatted_terms = [];
+			foreach ($terms as $term) {
+				$formatted_terms[] = $this->formatSingleTerm($term, $taxonomy, false);
+			}
 
             // Get total for pagination
             $total_args = array_merge($args, ['fields' => 'count', 'number' => '']);
@@ -811,13 +895,15 @@
         $name = sanitize_text_field($request->get_param('name'));
         $parent = (int)$request->get_param('parent') ?: 0;
 
+
         try {
             // Check if term already exists
             $existing = term_exists($name, jvbCheckBase($taxonomy), $parent);
 
             if ($existing) {
-                $term = get_term($existing['term_id'], jvbCheckBase($taxonomy));
 
+                $term = get_term($existing['term_id'], jvbCheckBase($taxonomy));
+				error_log('Existing Term: '.print_r($term, true));
                 return new WP_REST_Response([
                     'success' => false,
                     'message' => 'Term already exists',
@@ -830,7 +916,8 @@
             }
 
 
-			if (jvbSiteHasTermApproval()) {
+			if (Features::forMembership()->has('term_approval')) {
+				error_log('Term Approval required');
 				// Get approval routes instance
 				$approval_routes = JVB()->routes('approvals');
 				// Create approval request
@@ -854,13 +941,15 @@
 					]
 				];
 			} else {
+				error_log('Creating new Term: ');
 				$termID = wp_insert_term(
 					$name,
 					jvbCheckBase($taxonomy),
 					[
-						'parent'	=> absint($parent??0)
+						'parent'	=> absint($parent)
 					]
 				);
+				error_log('Result: '.print_r($termID, true));
 
 				if (is_wp_error($termID)) {
 					throw new Exception('Failed to create new term');

--
Gitblit v1.10.0