'Content Taxonomy Tables', // page_title
'menu_title' => 'Taxonomy Tables', // menu_title
'capability' => 'manage_options', // capability
'menu_slug' => 'jvb-taxonomy-table', // menu_slug (will become BASE.'integrations')
'callback' => [$this, 'renderAdminPage'], // callback
];
return $subpages;
}
/**
* Handle admin actions
*/
public function handleActions(): void
{
if (!current_user_can('manage_options')) {
return;
}
// Handle individual taxonomy rebuild
if (isset($_POST['rebuild_taxonomy']) && wp_verify_nonce($_POST['_wpnonce'], 'rebuild_taxonomy')) {
$taxonomy = sanitize_text_field($_POST['taxonomy']);
$registrar = Registrar::getInstance($taxonomy);
if ($registrar && $registrar->hasFeature('is_content')) {
$results = $this->rebuildCustomTable($taxonomy);
// Store results in transient to display after redirect
set_transient('jvb_rebuild_results_' . $taxonomy, $results, 300); // 5 minutes
wp_redirect(add_query_arg('rebuilt', $taxonomy, wp_get_referer()));
exit;
}
// Display results if available
$results = get_transient('jvb_rebuild_results_' . $this->slug);
if ($results) {
delete_transient('jvb_rebuild_results_' . $this->slug);
add_action('admin_notices', function() use ($results) {
$class = $results['errors'] > 0 ? 'notice-warning' : 'notice-success';
echo '
';
echo '
Taxonomy Rebuild Results:
';
echo '
';
foreach ($results['messages'] as $message) {
echo '- ' . esc_html($message) . '
';
}
echo '
';
echo '
';
});
}
}
// Handle rebuild all
if (isset($_POST['rebuild_all']) && wp_verify_nonce($_POST['_wpnonce'], 'rebuild_all')) {
$results = $this->rebuildAllContentTaxonomies();
$this->storeResults('rebuild_all', $results);
wp_redirect(add_query_arg('rebuilt', 'all', wp_get_referer()));
exit;
}
}
/**
* Store results in transient for display
*/
protected function storeResults(string $key, array $results): void
{
set_transient("jvb_admin_results_{$key}", $results, 300);
}
/**
* Render admin page
*/
public function renderAdminPage(): void
{
// Display any stored results
$this->displayResults();
?>
Content Tables Management
Content Taxonomies
These taxonomies have custom content tables that can be rebuilt from existing term data.
| Taxonomy |
Table Status |
Term Count |
Table Count |
Actions |
getTableInfo($slug);
$term_count = wp_count_terms($taxonomy, ['hide_empty' => false]);
?>
= esc_html($registrar->getPlural()) ?>
= esc_html($taxonomy) ?>
|
Table exists
Table missing
|
= esc_html($term_count) ?> terms |
= esc_html($table_info['count']) ?> records
N/A
|
Create table first via plugin activation
|
Table Information
Content tables store frequently accessed data from taxonomies for improved performance.
When to Rebuild:
- After importing terms via CSV or other bulk methods
- If you notice discrepancies between term counts and table counts
- After modifying custom table field definitions
- If custom table data appears to be corrupted or missing
WP-CLI Commands:
wp jvb rebuild-content-tables - Rebuild all content tables
wp jvb rebuild-content-tables <taxonomy> - Rebuild specific taxonomy table
prefix . BASE . 'content_' . $slug;
$exists = $wpdb->get_var("SHOW TABLES LIKE '{$table}'") === $table;
$count = 0;
if ($exists) {
$count = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$table}");
}
return [
'exists' => $exists,
'count' => $count,
'table' => $table
];
}
/**
* Display results from previous actions
*/
protected function displayResults(): void
{
// Check for rebuild completion
if (isset($_GET['rebuilt'])) {
$rebuilt = sanitize_text_field($_GET['rebuilt']);
if ($rebuilt === 'all') {
$results = get_transient('jvb_admin_results_rebuild_all');
if ($results) {
delete_transient('jvb_admin_results_rebuild_all');
$this->displayAllRebuildResults($results);
}
} else {
$results = get_transient("jvb_admin_results_rebuild_{$rebuilt}");
if ($results) {
delete_transient("jvb_admin_results_rebuild_{$rebuilt}");
$this->displaySingleRebuildResults($rebuilt, $results);
}
}
}
}
/**
* Display results for single taxonomy rebuild
*/
protected function displaySingleRebuildResults(string $taxonomy, array $results): void
{
$class = $results['errors'] > 0 ? 'notice-warning' : 'notice-success';
?>
Rebuild Results: = esc_html(ucfirst($taxonomy)) ?>
0 ? 'notice-warning' : 'notice-success';
?>
Rebuild All Results
Summary:
= $results['total_taxonomies'] ?> taxonomies processed,
= $results['successful_rebuilds'] ?> successful,
= $results['failed_rebuilds'] ?> failed
$detail): ?>
= esc_html(ucfirst($taxonomy)) ?>
✓ Success
⚠ = $detail['errors'] ?> errors
0,
'errors' => 0,
'total' => 0,
'messages' => []
];
// Check if this is a content taxonomy
$registrar = Registrar::getInstance($taxonomy);
if (!$registrar->hasFeature('is_content')) {
$results['messages'][] = "Taxonomy {$taxonomy} is not a content taxonomy";
return $results;
}
global $wpdb;
$table = $wpdb->prefix . BASE . 'content_' . $taxonomy;
// Check if table exists
if ($wpdb->get_var("SHOW TABLES LIKE '{$table}'") !== $table) {
$results['messages'][] = "Custom table {$table} does not exist";
return $results;
}
// Clear existing data
$wpdb->query("TRUNCATE TABLE {$table}");
$results['messages'][] = "Cleared existing data from {$table}";
// Get all terms for this taxonomy
$terms = get_terms([
'taxonomy' => jvbCheckBase($taxonomy),
'hide_empty'=> false,
'number' => 0, // Get all terms
'fields' => 'ids'
]);
if (is_wp_error($terms)) {
$results['messages'][] = "Error fetching terms: " . $terms->get_error_message();
return $results;
}
$results['total'] = count($terms);
$results['messages'][] = "Found {$results['total']} terms to process";
JVB()->queue()->queueOperation(
'sync_content_taxonomy_tables',
0,
[
'terms' => $terms,
'taxonomy' => $taxonomy
],
[
'chunk_key' => 'terms',
'chunk_size' => 10,
]
);
$results['messages'][] = 'Added to queue!';
return $results;
}
public function processOperation(WP_Error $result, object $operation, array $data):WP_Error|array
{
switch ($operation->type) {
case 'sync_content_taxonomy_tables':
return $this->processContentTaxonomyTableSync($operation, $data);
default:
return $result;
}
}
public function processContentTaxonomyTableSync(object $operation, array $data):array
{
$taxonomy = $data['taxonomy'];
$registrar = new TaxonomyRegistrar($taxonomy, JVB_TAXONOMY[$taxonomy]);
$results = ['errors' => 0, 'success' => 0];
foreach ($data['terms'] as $term) {
try {
$registrar->syncTermToCustomTable($term);
$results['success']++;
} catch (Exception $e) {
$results['errors']++;
$results['messages'][] = "Error processing term {$term->term_id} ({$term->name}): " . $e->getMessage();
}
}
$results['messages'][] = "Rebuild complete: {$results['success']} successful, {$results['errors']} errors";
return [
'success' => true,
'result' => $results
];
}
}
new ContentTaxonomy();