From 3d25ad7de4fdbb3eba2cde2a62422e6be5d79a0a Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Tue, 25 Aug 2026 22:57:22 +0000
Subject: [PATCH] =It's been a minute. I went through the Routes and associated Managers and ensured they played together well. Reworked the Cache.php, and I think I caught all the references. Moving away from JVBase() root class, to individuall classes that are Instanced. Double checked for the ABSPATH check in every file, and added index.php to every directory that didn't already have it. Also still working on the MenuBlock to work with WooCommerce for now for Northeh
---
inc/rest/routes/TermRoutes.php | 827 ++++++++++++++++------------------------------------------
1 files changed, 233 insertions(+), 594 deletions(-)
diff --git a/inc/rest/routes/TermRoutes.php b/inc/rest/routes/TermRoutes.php
index ec029c8..8178cad 100644
--- a/inc/rest/routes/TermRoutes.php
+++ b/inc/rest/routes/TermRoutes.php
@@ -1,11 +1,14 @@
<?php
namespace JVBase\rest\routes;
-use JVBase\JVB;
-use JVBase\rest\RestRouteManager;
+use JVBase\Instance;
+use JVBase\managers\Cache;
use JVBase\managers\TaxonomyRelationships;
+use JVBase\registrar\Registrar;
+use JVBase\rest\Rest;
use JVBase\managers\UserTermsManager;
-use JVBase\utility\Features;
+use JVBase\rest\Route;
+use JVBase\base\Site;
use WP_REST_Request;
use WP_REST_Response;
use Exception;
@@ -13,20 +16,24 @@
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
-class TermRoutes extends RestRouteManager
+class TermRoutes extends Rest
{
+ use Instance;
protected object $term_index_manager;
protected int $per_page;
public function __construct()
{
- $this->cache_name = 'terms';
+ $this->cacheName = 'terms';
parent::__construct();
-// $this->cache->invalidateGroup('terms');
+ $this->cache = Cache::for('terms', 'term');
+ if (JVB_TESTING) {
+ $this->cache->flush();
+ }
+
$this->per_page = 20;
add_action('edited_term', [$this, 'deleteTermPath']);
- add_action('wp_login', [$this, 'clearUserTaxonomyCache'], 10, 2);
}
/**
@@ -35,60 +42,31 @@
*/
public function registerRoutes():void
{
- register_rest_route($this->namespace, '/terms', [
- [
- 'methods' => 'GET',
- 'callback' => [$this, 'handleTermSelectionRequest'],
- 'permission_callback' => [$this, 'checkPermission'],
- 'args' => [
- 'page' => [
- 'required' => true,
- 'type' => 'integer',
- 'default' => 1,
- ],
- 'taxonomy' => [
- 'required' => true,
- 'type' => 'string'
- ],
- 'search' => [
- 'required' => false,
- 'type' => 'string'
- ],
- 'parent' => [
- 'required' => false,
- 'type' => 'integer',
- 'default' => 0
- ]
- ]
- ],
- [
- 'methods' => 'POST',
- 'callback' => [$this, 'createTermRequest'],
- 'permission_callback' => [$this, 'checkPermission'],
- 'args' => [
- 'taxonomy' => [
- 'required' => true,
- 'type' => 'string'
- ],
- 'name' => [
- 'required' => true,
- 'type' => 'string'
- ],
- 'parent' => [
- 'required' => false,
- 'type' => 'integer',
- 'default' => 0
- ]
- ]
- ]
- ]);
+ Route::for('terms')
+ ->get([$this, 'handleTermSelectionRequest'])
+ ->auth('public')
+ ->rateLimit()
+ ->args([
+ 'page' => 'int|required',
+ 'taxonomy' => 'string|required',
+ 'search' => 'string',
+ 'parent' => 'int'
+ ])
+ ->post([$this, 'createTermRequest'])
+ ->auth('isVerified')
+ ->rateLimit(30)
+ ->args([
+ 'taxonomy' => 'string|required',
+ 'name' => 'string|required',
+ 'parent' => 'int|default:0',
+ ])
+ ->register();
- //TODO: Just wrap this up to the normal GET request
- register_rest_route($this->namespace, '/terms/check', [
- 'methods' => 'GET',
- 'callback' => [$this, 'getTermDetails'],
- 'permission_callback' => [$this, 'checkPermission'],
- ]);
+ Route::for('terms/check')
+ ->get([$this,'getTermDetails'])
+ ->auth('public')
+ ->rateLimit()
+ ->register();
}
/**
@@ -102,22 +80,19 @@
$term = get_term($term_id);
if (is_wp_error($term)) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => $term
- ]);
+ return $this->error('No term found');
}
$data = [
'id' => $term->term_id,
- 'name' => $term->name,
+ 'name' => html_entity_decode($term->name),
'slug' => $term->slug,
'taxonomy' => $term->taxonomy,
];
// Add relationship data if requested
if ($request->get_param('include_relationships')) {
- $relationship_manager = new TaxonomyRelationships();
+ $relationship_manager = TaxonomyRelationships::getInstance();
$related_taxonomies = $request->get_param('related_taxonomies') ?: ['jvb_style', 'jvb_theme', 'jvb_city'];
$data['relationships'] = [];
@@ -132,7 +107,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);
@@ -140,7 +115,7 @@
}
}
- return new WP_REST_Response($data);
+ return $this->success($data);
}
/**
@@ -148,31 +123,27 @@
*
* @return WP_REST_Response
*/
- public function getTermDetails(WP_REST_Request $request):WP_REST_Response
- {
- $data = $request->get_params();
- // Collect all taxonomies being queried
- $taxonomies = array_keys($data);
+ public function getTermDetails(WP_REST_Request $request): WP_REST_Response
+ {
+ $data = $request->get_params();
- // Check HTTP cache headers
- $cache_check = $this->checkHeaders($request, $taxonomies);
- if ($cache_check) {
- return $cache_check;
- }
- $terms = [];
- foreach ($data as $tax => $IDs) {
- $args = [
- 'taxonomy' => BASE.$tax,
- 'include' => $IDs
- ];
+ $terms = $this->cache->remember(
+ ['termDetails' => $data],
+ function() use ($data) {
+ $result = [];
+ foreach ($data as $tax => $IDs) {
+ $args = [
+ 'taxonomy' => BASE . $tax,
+ 'include' => $IDs
+ ];
+ $result[$tax] = $this->formatTerms($args, BASE . $tax);
+ }
+ return $result;
+ }
+ );
- $terms[$tax] = $this->formatTerms($args, BASE.$tax);
- }
- $response = new WP_REST_Response([
- 'items' => $terms,
- ]);
- return $this->addCacheHeaders($response);
- }
+ return $this->success(['items' => $terms]);
+ }
/**
* @param WP_REST_Request $request
@@ -183,11 +154,8 @@
{
$data = $request->get_params();
$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;
+ if (empty($taxonomy)) {
+ return $this->success(['message' => 'No taxonomy selected']);
}
// Handle batch request (multiple taxonomies)
@@ -200,52 +168,42 @@
$args = [
'taxonomy' => $taxonomy,
'include' => $data['termIDs'],
- 'hide_empty' => false,
+ 'hide_empty' => true,
];
- $key = $this->cache->generateKey($args);
- $cached = $this->cache->get($key);
- if ($cached) {
- $response = new WP_REST_Response($cached);
- return $this->addCacheHeaders($response);
- }
+ $data = $this->cache->remember(
+ $args,
+ function() use ($args, $taxonomy) {
+ return $this->formatTerms($args, $taxonomy);
+ }
+ );
- $formatted = $this->formatTerms($args, $taxonomy);
$response = [
- 'items' => $formatted
+ 'items' => $data
];
- $this->cache->set($key, $response);
- $response = new WP_REST_Response($response);
- return $this->addCacheHeaders($response);
+
+ return $this->success($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)) {
- $response = $this->getTermsForContentType($request);
- return $this->addCacheHeaders($response);
+ $registrar = Registrar::getInstance($content_type);
+ if ($registrar->hasFeature('is_content')) {
+ //TODO: Not sure what we're trying for here. Doesn't seem to be used.
+ //TODO: Likely for taxonomy content types, like tattoo shops
+ return $this->emptyResult();
}
}
- $taxonomy = BASE.$request->get_param('taxonomy');
+ $taxonomy = jvbCheckBase($request->get_param('taxonomy'));
+ if (!taxonomy_exists($taxonomy)) {
+ return $this->emptyResult();
+ }
$search = $request->get_param('search');
$parent = (int)$data['parent']??0;
$page = max(1, (int)($data['page']??1));
$per_page = 25;
- if (!taxonomy_exists($taxonomy)) {
- return new WP_REST_Response([
- 'items' => [],
- 'pagination' => [
- 'page' => 1,
- 'per_page' => $per_page,
- 'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => false
- ]
- ]);
- }
$tax_obj = get_taxonomy($taxonomy);
$is_hierarchical = $tax_obj->hierarchical;
@@ -253,14 +211,14 @@
// If searching, handle differently
if (!empty($search)) {
error_log('Handling search...');
- $response = $this->handleTermSearch($request);
- return $this->addCacheHeaders($response);
+
+ return $this->handleTermSearch($request);
}
// Get terms for current level with child count
$args = [
'taxonomy' => $taxonomy,
- 'hide_empty' => false,
+ 'hide_empty' => true,
'parent' => $parent,
'number' => $per_page,
'orderby'=> 'name',
@@ -272,22 +230,12 @@
if ($request->get_param('main_context') && in_array(jvbCheckBase(json_decode($request->get_param('main_context'), true)['context']), jvbUserTypes())) {
$main_context = json_decode($request->get_param('main_context'), true);
- $userID = get_post_meta($main_context['id'], BASE.'link', true);
- $manager = new UserTermsManager();
- $related = $manager->getUserTermIDs($userID, $taxonomy);
+ $userID = get_post_meta($main_context['id'], BASE.'profile_link', true);
+ $manager = UserTermsManager::getInstance();
+ $related = $manager->fetchUserTerms($userID, $taxonomy);
if (empty($related)) {
- $response = new WP_REST_Response([
- 'items' => [],
- 'pagination' => [
- 'page' => 1,
- 'per_page' => $per_page,
- 'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => false
- ]
- ]);
- return $this->addCacheHeaders($response);
+ return $this->emptyResult();
}
$args['include'] = $related;
@@ -296,21 +244,11 @@
$main_context = json_decode($request->get_param('main_context'), true);
$thisTaxonomy = str_replace('taxonomy:', '', $main_context['context']);
$ID = (int)$main_context['id'];
- $manager = new TaxonomyRelationships();
+ $manager = TaxonomyRelationships::getInstance();
$related = $manager->getRelatedTerms($ID, BASE.$request->get_param('taxonomy'));
if (empty($related)) {
- $response = new WP_REST_Response([
- 'items' => [],
- 'pagination' => [
- 'page' => 1,
- 'per_page' => $per_page,
- 'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => false
- ]
- ]);
- return $this->addCacheHeaders($response);
+ return $this->emptyResult();
}
$args['tax_query'] = [
'taxonomy' => $taxonomy,
@@ -323,7 +261,7 @@
$match = $request->get_param('match') ?? 'any';
$context = json_decode($request['context'], true);
- $relationshipManager = new TaxonomyRelationships();
+ $relationshipManager = TaxonomyRelationships::getInstance();
// Prepare array to collect term IDs that match the context
$related_term_ids = [];
@@ -359,58 +297,40 @@
$args['include'] = $related_term_ids;
} else {
// No related terms found, return empty result
- $response = new WP_REST_Response([
- 'items' => [],
- 'pagination' => [
- 'page' => 1,
- 'per_page' => $per_page,
- 'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => false
- ]
- ]);
-
- return $this->addCacheHeaders($response);
+ return $this->emptyResult();
}
}
+ $response = $this->cache->remember(
+ $args,
+ function() use ($args, $taxonomy, $parent, $per_page, $page, $is_hierarchical) {
+ $formatted_terms = $this->formatTerms($args, $taxonomy);
+ // Get total count for pagination
+ $total_terms = wp_count_terms([
+ 'taxonomy' => $taxonomy,
+ 'hide_empty' => false,
+ 'parent' => $parent
+ ]);
+ // Calculate pagination
+ $total_pages = ceil($total_terms / $per_page);
+ $has_more = $page < $total_pages;
- $key = $this->cache->generateKey($args);
- $cache = $this->cache->get($key);
+ return [
+ 'items' => $formatted_terms,
+ 'is_hierarchical' => $is_hierarchical,
+ 'pagination' => [
+ 'page' => $page,
+ 'per_page' => $per_page,
+ 'total_pages' => $total_pages,
+ 'total_terms' => (int)$total_terms
+ ],
+ 'has_more' => $has_more
+ ];
+ }
+ );
- if ($cache) {
- $response = new WP_REST_Response($cache);
- return $this->addCacheHeaders($response);
- }
-
- $formatted_terms = $this->formatTerms($args, $taxonomy);
- // Get total count for pagination
- $total_terms = wp_count_terms([
- 'taxonomy' => $taxonomy,
- 'hide_empty' => false,
- 'parent' => $parent
- ]);
-
- // Calculate pagination
- $total_pages = ceil($total_terms / $per_page);
- $has_more = $page < $total_pages;
-
- $response = [
- 'items' => $formatted_terms,
- 'is_hierarchical' => $is_hierarchical,
- 'pagination' => [
- 'page' => $page,
- 'per_page' => $per_page,
- 'total_pages' => $total_pages,
- 'total_terms' => (int)$total_terms,
- 'has_more' => $has_more
- ]
- ];
-
- $this->cache->set($key, $response);
- $response = new WP_REST_Response($response);
- return $this->addCacheHeaders($response);
+ return $this->success($response);
}
protected function handleBatchTermRequest(string $taxonomy, array $data, WP_REST_Request $request):WP_REST_Response
@@ -442,13 +362,12 @@
'items' => $all_terms,
'pagination'=> [
'page' => $page,
- 'per_page'=> $per_page,
- 'has_more' => true,
- ]
+ 'per_page'=> $per_page
+ ],
+ 'has_more' => true,
];
- $response = new WP_REST_Response($response);
- return $this->addCacheHeaders($response);
+ return $this->success($response);
}
@@ -461,7 +380,7 @@
protected function formatTerms(array $args, string $taxonomy): array
{
return $this->cache->remember(
- $this->cache->generateKey($args),
+ $args,
function() use ($args, $taxonomy) {
$terms = get_terms($args);
@@ -471,7 +390,7 @@
$formatted_terms = [];
foreach ($terms as $term) {
- $formatted_terms[] = $this->formatSingleTerm($term, $taxonomy, true);
+ $formatted_terms[] = $this->formatSingleTerm($term, $taxonomy);
}
return $formatted_terms;
@@ -496,7 +415,7 @@
return $this->cache->remember($cache_key, function() use ($term, $taxonomy) {
$data = [
'id' => $term->term_id,
- 'name' => $term->name,
+ 'name' => html_entity_decode($term->name),
'slug' => $term->slug,
'parent' => $term->parent,
'path' => $this->getTermPath($term->term_id, $term->name, $taxonomy),
@@ -523,74 +442,56 @@
*
* @return WP_REST_Response
*/
- public function handleTermSearch(WP_REST_Request $request):WP_REST_Response
- {
- $taxonomy = BASE.$request->get_param('taxonomy');
- $search = $request->get_param('search');
- $page = $request->get_param('page') ?? 1;
- $per_page = $request->get_param('per_page') ?? 20;
+ public function handleTermSearch(WP_REST_Request $request): WP_REST_Response
+ {
+ $taxonomy = BASE . $request->get_param('taxonomy');
+ $search = $request->get_param('search');
+ $page = $request->get_param('page') ?? 1;
+ $per_page = $request->get_param('per_page') ?? 20;
- // When searching, we want to search across all terms regardless of hierarchy
- $args = [
- 'taxonomy' => $taxonomy,
- 'hide_empty' => false,
- 'search' => $search,
- 'search_columns' => ['name', 'slug'],
- 'fields' => 'all',
- 'number' => $per_page,
- 'offset' => ($page - 1) * $per_page,
- ];
+ $args = [
+ 'taxonomy' => $taxonomy,
+ 'hide_empty' => true,
+ 'search' => $search,
+ 'search_columns' => ['name', 'slug'],
+ 'fields' => 'all',
+ 'number' => $per_page,
+ 'offset' => ($page - 1) * $per_page,
+ ];
- $key = $this->cache->generateKey($args);
- $cache = $this->cache->get($key);
- if ($cache) {
- return new WP_REST_Response($cache);
- }
+ $data = $this->cache->remember(
+ $args,
+ function() use ($args, $taxonomy, $page, $per_page) {
+ $terms = get_terms($args);
- $terms = get_terms($args);
+ if (is_wp_error($terms)) {
+ return $this->emptyResult($page, $per_page);
+ }
- if (is_wp_error($terms)) {
- return new WP_REST_Response([
- 'items' => [],
- 'pagination' => [
- 'page' => 0,
- 'per_page' => 20,
- 'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => false
- ]
- ]);
- }
+ $formatted_terms = array_map(
+ fn($term) => $this->formatSingleTerm($term, $taxonomy),
+ $terms
+ );
- // Get total count for pagination
- $count_args = array_merge($args, ['fields' => 'count']);
- $total_terms = wp_count_terms($count_args);
+ $count_args = array_merge($args, ['fields' => 'count']);
+ $total_terms = wp_count_terms($count_args);
+ $total_pages = ceil($total_terms / $per_page);
- $formatted_terms = [];
- foreach ($terms as $term) {
- // Search results show path, so includeChildren = false for performance
- $formatted_terms[] = $this->formatSingleTerm($term, $taxonomy, false);
- }
+ return [
+ 'items' => $formatted_terms,
+ 'pagination' => [
+ 'page' => (int)$page,
+ 'per_page' => (int)$per_page,
+ 'total_pages' => $total_pages,
+ 'total_terms' => (int)$total_terms
+ ],
+ 'has_more' => $page < $total_pages
+ ];
+ }
+ );
- // Calculate pagination info
- $total_pages = ceil($total_terms / $per_page);
- $has_more = $page < $total_pages;
-
- $response = [
- 'items' => $formatted_terms,
- 'pagination' => [
- 'page' => (int)$page,
- 'per_page' => (int)$per_page,
- 'total_pages' => $total_pages,
- 'total_terms' => (int)$total_terms,
- 'has_more' => $has_more
- ]
- ];
-
- $this->cache->set($key, $response);
-
- return new WP_REST_Response($response);
- }
+ return $this->success($data);
+ }
/**
* @param int $termID
@@ -631,308 +532,46 @@
delete_term_meta($termID, BASE.'term_path');
}
- /**
- * @param string $username
- * @param object $user
- *
- * @return void
- */
- public function clearUserTaxonomyCache(string $username, object $user):void
- {
- global $wpdb;
-
- // Get all transients for this user
- $like_pattern = $wpdb->esc_like(BASE.'user_' . $user->ID) . '_%';
-
- $transients = $wpdb->get_col($wpdb->prepare("
- SELECT option_name
- FROM {$wpdb->options}
- WHERE option_name LIKE %s
- AND option_name LIKE %s
- ", '_transient_' . $like_pattern, '%'));
-
- // Delete all found transients
- foreach ($transients as $transient) {
- delete_transient(str_replace('_transient_', '', $transient));
- }
- }
/**
* @param WP_REST_Request $request
*
* @return WP_REST_Response
*/
- public function getTermsForContentType(WP_REST_Request $request):WP_REST_Response
- {
- $manager = new TaxonomyRelationships();
- $content_type = BASE . $request->get_param('content');
- $taxonomy = BASE . $request->get_param('taxonomy');
- $search = $request->get_param('search');
- $page = max(1, intval($request->get_param('page')));
- $per_page = $request->get_param('per_page') ?: 20;
+ public function createTermRequest(WP_REST_Request $request): WP_REST_Response
+ {
+ $user_id = get_current_user_id();
+ $taxonomy = $request->get_param('taxonomy');
+ $name = sanitize_text_field($request->get_param('name'));
+ $parent = (int)$request->get_param('parent') ?: 0;
- // Create cache key
- $cache_key = "terms_for_{$content_type}_{$taxonomy}_" . md5("{$search}_{$page}_{$per_page}");
+ try {
+ $existing = term_exists($name, jvbCheckBase($taxonomy), $parent);
- $cache_key = $this->cache->generateKey([
- 'terms_for' => $content_type,
- 'taxonomy' => $taxonomy,
- 'search' => $search,
- 'page' => $page,
- 'per_page' => $per_page
- ]);
- $cache = $this->cache->get($cache_key);
- // Try cache first
- if ($cache !== false) {
- return new WP_REST_Response($cache);
- }
-
- try {
- global $wpdb;
-
- // Starting the query building
- $query_args = [];
- $terms_query = "
- SELECT DISTINCT t.term_id, t.name, t.slug, tt.count, tt.taxonomy,
- (SELECT COUNT(DISTINCT tm.meta_key) FROM {$wpdb->termmeta} tm WHERE tm.term_id = t.term_id) AS meta_count
- FROM {$wpdb->terms} t
- JOIN {$wpdb->term_taxonomy} tt ON t.term_id = tt.term_id
- JOIN {$manager->getTableName()} tr ON (
- (tr.primary_taxonomy = %s AND tr.primary_term_id = t.term_id)
- OR (tr.related_taxonomy = %s AND tr.related_term_id = t.term_id)
- )
- ";
-
- $query_args[] = $taxonomy;
- $query_args[] = $taxonomy;
-
- // Add content type filter through posts
- $query_where = " WHERE tt.taxonomy = %s";
- $query_args[] = $taxonomy;
-
- // Add search condition if provided
- if ($search) {
- $query_where .= " AND (t.name LIKE %s OR t.slug LIKE %s)";
- $search_like = '%' . $wpdb->esc_like($search) . '%';
- $query_args[] = $search_like;
- $query_args[] = $search_like;
- }
-
- // Add relationship strength ordering
- $query_order = " GROUP BY t.term_id";
- $query_order .= " ORDER BY COUNT(tr.id) DESC, tt.count DESC";
-
- // Add pagination
- $query_limit = " LIMIT %d OFFSET %d";
- $query_args[] = $per_page;
- $query_args[] = ($page - 1) * $per_page;
-
- // Combine the query
- $final_query = $query_where . $query_order . $query_limit;
-
- // Get terms
- $terms = $wpdb->get_results(
- $wpdb->prepare(
- $terms_query . $final_query,
- $query_args
- )
- );
- // Get total count for pagination
- $count_query = str_replace($query_limit, '', $query_where);
- $count_query = "SELECT COUNT(DISTINCT t.term_id) FROM {$wpdb->terms} t
- JOIN {$wpdb->term_taxonomy} tt ON t.term_id = tt.term_id
- JOIN {$manager->getTableName()} tr ON (
- (tr.primary_taxonomy = %s AND tr.primary_term_id = t.term_id)
- OR (tr.related_taxonomy = %s AND tr.related_term_id = t.term_id)
- ) " . $count_query;
-
- // Remove pagination args
- array_pop($query_args);
- array_pop($query_args);
-
- $total = $wpdb->get_var(
- $wpdb->prepare(
- $count_query,
- $query_args
- )
- );
-
- // Format terms
- $formatted_terms = [];
- $is_hierarchical = is_taxonomy_hierarchical($taxonomy);
-
- 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;
+ if ($existing) {
+ $term = get_term($existing['term_id'], jvbCheckBase($taxonomy));
+ return $this->success(['message' => 'Term already exists', 'term' => [
+ 'id' => $term->term_id,
+ 'name' => html_entity_decode($term->name),
+ 'path' => $this->getTermPath($term->term_id, $term->name, $taxonomy)
+ ]]);
}
- // Build response
- $total_pages = ceil($total / $per_page);
- $results = [
- 'items' => $formatted_terms,
- 'pagination' => [
- 'page' => (int)$page,
- 'per_page' => (int)$per_page,
- 'total_terms'=> $total,
- 'total_pages'=> $total_pages,
- 'has_more' => $page < $total_pages
- ]
- ];
-
- // Cache results
- $this->cache->set($cache_key, $results);
-
- return new WP_REST_Response($results);
-
- } catch (Exception $e) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => $e->getMessage()
- ]);
- }
- }
-
- /**
- * @param WP_REST_Request $request
- *
- * @return WP_REST_Response
- */
- public function handleTermsRequest(WP_REST_Request $request):WP_REST_Response
- {
- $taxonomy = BASE.$request->get_param('taxonomy');
- $search = $request->get_param('search');
- $page = max(1, intval($request->get_param('page')));
- $per_page = $request->get_param('per_page') ?: $this->per_page;
-
- // Create cache key
- $cache_key = "terms_{$taxonomy}_" . md5("{$search}_{$page}_{$per_page}");
- $cache = $this->cache->get($cache_key);
- if ($cache) {
- return new WP_REST_Response($cache);
- }
-
- try {
- // Build query args
- $args = [
- 'taxonomy' => $taxonomy,
- 'hide_empty' => false,
- 'orderby' => $search ? 'name' : 'count',
- 'order' => $search ? 'ASC' : 'DESC',
- 'number' => $per_page,
- 'offset' => ($page - 1) * $per_page,
- 'fields' => 'all'
- ];
-
- // Add search if provided
- if ($search) {
- $args['search'] = $search;
- }
-
- // Get terms
- $terms = get_terms($args);
-
- if (is_wp_error($terms)) {
- return new WP_REST_Response([
- 'items' => [],
- 'pagination' => [
- 'page' => 0,
- 'per_page' => 20,
- 'total_pages' => 0,
- 'total_terms' => 0,
- 'has_more' => 0
- ]
- ]);
- }
-
- // Check if taxonomy is hierarchical
- $is_hierarchical = is_taxonomy_hierarchical($taxonomy);
-
- // Format terms
- $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' => '']);
- $total = wp_count_terms($taxonomy, $total_args);
- $total_pages = ceil($total / $per_page);
-
- $results = [
- 'items' => $formatted_terms,
- 'pagination' => [
- 'page' => (int)$page,
- 'per_page' => (int)$per_page,
- 'total_pages' => $total_pages,
- 'total_terms' => (int)$total,
- 'has_more' => $page < $total_pages
- ]
- ];
-
- // Cache results
- $this->cache->set($cache_key, $results);
-
- return new WP_REST_Response($results);
-
- } catch (Exception $e) {
- return new WP_REST_Response([
- 'success' => false,
- 'message' => $e->getMessage()
- ]);
- }
- }
-
- /**
- * @param WP_REST_Request $request
- *
- * @return WP_REST_Response
- */
- public function createTermRequest(WP_REST_Request $request):WP_REST_Response
- {
- $user_id = get_current_user_id();
- $taxonomy = $request->get_param('taxonomy');
- $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));
- 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,
- 'path' => $this->getTermPath($term->term_id, $term->name, $taxonomy)
- ]
- ]);
- }
-
-
- if (Features::forMembership()->has('term_approval')) {
- error_log('Term Approval required');
- // Get approval routes instance
+ $membership = Site::membership();
+ if ($membership && $membership->has('term_approval')) {
$approval_routes = JVB()->routes('approvals');
- // Create approval request
$request_id = $approval_routes->createTermApprovalRequest(
$user_id,
$taxonomy,
sanitize_title($name),
absint($parent)
);
+
if (!$request_id) {
throw new Exception('Failed to create approval request');
}
- $return = [
- 'success' => true,
+
+ return $this->success([
'message' => 'Term suggestion submitted for approval',
'term' => [
'id' => 'pending_' . $request_id,
@@ -940,50 +579,50 @@
'pending' => true,
'request_id' => $request_id
]
- ];
- } else {
- error_log('Creating new Term: ');
- $termID = wp_insert_term(
- $name,
- jvbCheckBase($taxonomy),
- [
- 'parent' => absint($parent)
- ]
- );
- error_log('Result: '.print_r($termID, true));
-
- if (is_wp_error($termID)) {
- throw new Exception('Failed to create new term');
- }
-
- $return = [
- 'success' => true,
- 'message' => $name.' created successfully',
- 'term' => [
- 'id' => $termID['term_id'],
- 'name' => $name,
- 'path' => $this->getTermPath($termID['term_id'], $name, $taxonomy)
- ]
- ];
+ ], 202); // 202 Accepted for pending approval
}
- return new WP_REST_Response($return);
+ $termID = wp_insert_term(
+ $name,
+ jvbCheckBase($taxonomy),
+ ['parent' => absint($parent)]
+ );
- } catch (Exception $e) {
- JVB()->error()->log(
- 'terms',
- 'Term creation failed: ' . $e->getMessage(),
- [
- 'user_id' => $user_id,
- 'taxonomy' => $taxonomy,
- 'name' => $name
- ]
- );
+ if (is_wp_error($termID)) {
+ throw new Exception($termID->get_error_message());
+ }
- return new WP_REST_Response([
- 'success' => false,
- 'message' => $e->getMessage()
- ], 500);
- }
- }
+ return $this->success([
+ 'message' => $name . ' created successfully',
+ 'term' => [
+ 'id' => $termID['term_id'],
+ 'name' => $name,
+ 'path' => $this->getTermPath($termID['term_id'], $name, $taxonomy)
+ ]
+ ], 201); // 201 Created
+
+ } catch (Exception $e) {
+ JVB()->error()->log(
+ 'terms',
+ 'Term creation failed: ' . $e->getMessage(),
+ ['user_id' => $user_id, 'taxonomy' => $taxonomy, 'name' => $name]
+ );
+
+ return $this->error($e->getMessage(), 'term_creation_failed', 500);
+ }
+ }
+
+ protected function emptyResult(int $page = 1, int $per_page = 20):WP_REST_Response
+ {
+ return $this->success([
+ 'items' => [],
+ 'pagination' => [
+ 'page' => $page,
+ 'per_page' => $per_page,
+ 'total_pages' => 0,
+ 'total_terms' => 0
+ ],
+ 'has_more' => false
+ ]);
+ }
}
--
Gitblit v1.10.0