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/TermRoutes.php | 314 +++++++++++++++++++++++++++++++++------------------
1 files changed, 203 insertions(+), 111 deletions(-)
diff --git a/inc/rest/routes/TermRoutes.php b/inc/rest/routes/TermRoutes.php
index 269dc2a..438139e 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;
@@ -21,8 +22,11 @@
{
$this->cache_name = 'terms';
parent::__construct();
-// $this->cache->invalidateGroup('terms');
+ if (JVB_TESTING) {
+ $this->cache->flush();
+ }
$this->per_page = 20;
+
add_action('edited_term', [$this, 'deleteTermPath']);
add_action('wp_login', [$this, 'clearUserTaxonomyCache'], 10, 2);
}
@@ -108,7 +112,7 @@
$data = [
'id' => $term->term_id,
- 'name' => $term->name,
+ 'name' => html_entity_decode($term->name),
'slug' => $term->slug,
'taxonomy' => $term->taxonomy,
];
@@ -130,7 +134,7 @@
$term = get_term($rel->related_term_id, $rel->related_taxonomy);
return [
'id' => $rel->related_term_id,
- 'name' => $term ? $term->name : 'Unknown',
+ 'name' => $term ? html_entity_decode($term->name) : 'Unknown',
'count' => $rel->relationship_count
];
}, $relationships);
@@ -149,6 +153,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 +170,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,18 +184,31 @@
public function handleTermSelectionRequest(WP_REST_Request $request):WP_REST_Response
{
$data = $request->get_params();
- $taxonomy = jvbCheckBase($data['taxonomy']);
+ $taxonomy = sanitize_text_field($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);
+ }
+ $taxonomy = jvbCheckBase($taxonomy);
if (array_key_exists('termIDs', $data)) {
$args = [
'taxonomy' => $taxonomy,
'include' => $data['termIDs'],
- 'hide_empty' => false,
+ 'hide_empty' => true,
];
$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 +216,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([
@@ -214,9 +243,9 @@
'page' => 1,
'per_page' => $per_page,
'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => false
- ]
+ 'total_terms' => 0
+ ],
+ 'has_more' => false
]);
}
@@ -225,13 +254,15 @@
// 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
$args = [
'taxonomy' => $taxonomy,
- 'hide_empty' => false,
+ 'hide_empty' => true,
'parent' => $parent,
'number' => $per_page,
'orderby'=> 'name',
@@ -248,16 +279,17 @@
$related = $manager->getUserTermIDs($userID, $taxonomy);
if (empty($related)) {
- return new WP_REST_Response([
+ $response = new WP_REST_Response([
'items' => [],
'pagination' => [
'page' => 1,
'per_page' => $per_page,
'total_pages' => 0,
'total_terms' => 0,
- 'has_more' => false
- ]
+ ],
+ 'has_more' => false
]);
+ return $this->addCacheHeaders($response);
}
$args['include'] = $related;
@@ -270,16 +302,17 @@
$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,
'per_page' => $per_page,
'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => false
- ]
+ 'total_terms' => 0
+ ],
+ 'has_more' => false
]);
+ return $this->addCacheHeaders($response);
}
$args['tax_query'] = [
'taxonomy' => $taxonomy,
@@ -328,16 +361,18 @@
$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,
'per_page' => $per_page,
'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => false
- ]
+ 'total_terms' => 0
+ ],
+ 'has_more' => false
]);
+
+ return $this->addCacheHeaders($response);
}
}
@@ -345,9 +380,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);
@@ -369,54 +405,120 @@
'page' => $page,
'per_page' => $per_page,
'total_pages' => $total_pages,
- 'total_terms' => (int)$total_terms,
- 'has_more' => $has_more
- ]
+ 'total_terms' => (int)$total_terms
+ ],
+ 'has_more' => $has_more
];
$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' => html_entity_decode($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
@@ -433,7 +535,7 @@
// When searching, we want to search across all terms regardless of hierarchy
$args = [
'taxonomy' => $taxonomy,
- 'hide_empty' => false,
+ 'hide_empty' => true,
'search' => $search,
'search_columns' => ['name', 'slug'],
'fields' => 'all',
@@ -456,9 +558,9 @@
'page' => 0,
'per_page' => 20,
'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => false
- ]
+ 'total_terms' => 0
+ ],
+ 'has_more' => false
]);
}
@@ -467,16 +569,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);
@@ -488,9 +584,9 @@
'page' => (int)$page,
'per_page' => (int)$per_page,
'total_pages' => $total_pages,
- 'total_terms' => (int)$total_terms,
- 'has_more' => $has_more
- ]
+ 'total_terms' => (int)$total_terms
+ ],
+ 'has_more' => $has_more
];
$this->cache->set($key, $response);
@@ -667,15 +763,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);
@@ -685,9 +778,9 @@
'page' => (int)$page,
'per_page' => (int)$per_page,
'total_terms'=> $total,
- 'total_pages'=> $total_pages,
- 'has_more' => $page < $total_pages
- ]
+ 'total_pages'=> $total_pages
+ ],
+ 'has_more' => $page < $total_pages
];
// Cache results
@@ -726,7 +819,7 @@
// Build query args
$args = [
'taxonomy' => $taxonomy,
- 'hide_empty' => false,
+ 'hide_empty' => true,
'orderby' => $search ? 'name' : 'count',
'order' => $search ? 'ASC' : 'DESC',
'number' => $per_page,
@@ -749,9 +842,9 @@
'page' => 0,
'per_page' => 20,
'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => 0
- ]
+ 'total_terms' => 0
+ ],
+ 'has_more' => 0
]);
}
@@ -759,16 +852,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' => '']);
@@ -781,9 +868,9 @@
'page' => (int)$page,
'per_page' => (int)$per_page,
'total_pages' => $total_pages,
- 'total_terms' => (int)$total,
- 'has_more' => $page < $total_pages
- ]
+ 'total_terms' => (int)$total
+ ],
+ 'has_more' => $page < $total_pages
];
// Cache results
@@ -811,26 +898,29 @@
$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',
'term' => [
'id' => $term->term_id,
- 'name' => $term->name,
+ 'name' => html_entity_decode($term->name),
'path' => $this->getTermPath($term->term_id, $term->name, $taxonomy)
]
]);
}
- 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 +944,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