From d7e7d248cbe41cd7a9ef9c2fb022b6c4831f99a3 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 31 May 2026 15:22:56 +0000
Subject: [PATCH] =jakevan complete

---
 inc/managers/AdminPages.php |  493 +++++++++---------------------------------------------
 1 files changed, 83 insertions(+), 410 deletions(-)

diff --git a/inc/managers/AdminPages.php b/inc/managers/AdminPages.php
index cf42870..5878e17 100644
--- a/inc/managers/AdminPages.php
+++ b/inc/managers/AdminPages.php
@@ -1,7 +1,8 @@
 <?php
 namespace JVBase\managers;
 
-use JVBase\utility\Features;
+use JVBase\registrar\Registrar;
+use JVBase\base\Site;
 use WP_REST_Response;
 
 if (!defined('ABSPATH')) {
@@ -31,7 +32,7 @@
             'menu_title' => 'JakeVan',
             'capability' => 'manage_options',
             'menu_slug' => BASE . 'settings',
-            'icon' => jvbCSSIcon('settings'),
+            'icon' => jvbCSSIcon('gear-six'),
             'position' => 0
         ];
 		$this->subpages = get_option(BASE.'adminSubpage', []);
@@ -47,182 +48,11 @@
 
 		add_filter(BASE.'admin_action_filter', [$this, 'handleCacheActions'], 10, 3);
 
-		add_action('rest_api_init', [$this, 'registerRestRoutes']);
 		// Handle form submissions
 		add_action('admin_init', [$this, 'handleAdminPageSubmission']);
 		add_action('admin_notices', [$this, 'displayAdminNotices']);
     }
 
-	/**
-	 * Register REST API routes for admin actions
-	 */
-	public function registerRestRoutes(): void
-	{
-		register_rest_route('jvb/v1', '/admin-cache', [
-			'methods' => 'POST',
-			'callback' => [$this, 'handleCacheAction'],
-			'permission_callback' => [$this, 'checkAdminPermission']
-		]);
-
-		register_rest_route('jvb/v1', '/admin-icons', [
-			'methods' => 'POST',
-			'callback' => [$this, 'handleIconAction'],
-			'permission_callback' => [$this, 'checkAdminPermission']
-		]);
-	}
-
-	/**
-	 * Check if user has admin permissions
-	 */
-	public function checkAdminPermission(\WP_REST_Request $request): bool
-	{
-		if (!current_user_can('manage_options')) {
-			return false;
-		}
-
-		// Verify nonce
-		$nonce = $request->get_header('X-WP-Nonce');
-		if (!wp_verify_nonce($nonce, 'wp_rest')) {
-			return false;
-		}
-
-		return true;
-	}
-
-	/**
-	 * Handle cache-related actions
-	 */
-	public function handleCacheAction(\WP_REST_Request $request): \WP_REST_Response
-	{
-		$action = sanitize_text_field($request->get_param('action'));
-
-		switch ($action) {
-			case 'flush-all':
-				$total = Cache::flushAll();
-				return new \WP_REST_Response([
-					'success' => true,
-					'message' => $total.' caches flushed successfully'
-				]);
-
-			case 'flush-cache':
-				$group = sanitize_text_field($request->get_param('group'));
-				if (empty($group)) {
-					return new \WP_REST_Response([
-						'success' => false,
-						'message' => 'No cache group specified'
-					], 400);
-				}
-
-				Cache::for($group)?->flush();
-
-				return new \WP_REST_Response([
-					'success' => true,
-					'message' => "Cache group '{$group}' flushed successfully"
-				]);
-
-			default:
-				return new \WP_REST_Response([
-					'success' => false,
-					'message' => 'Invalid action'
-				], 400);
-		}
-	}
-
-	/**
-	 * Handle icon-related actions
-	 */
-	public function handleIconAction(\WP_REST_Request $request): \WP_REST_Response
-	{
-		$action = sanitize_text_field($request->get_param('action'));
-		$source = sanitize_text_field($request->get_param('source') ?? 'icons');
-		$icons = IconsManager::for($source);
-
-		switch ($action) {
-			case 'refresh-icons':
-				// Force regenerate CSS immediately
-				$icons->forceRefresh();
-				IconsManager::regenerateAllCSS([$source => true]);
-
-				return new \WP_REST_Response([
-					'success' => true,
-					'message' => "Icon CSS regenerated successfully for '{$source}'"
-				]);
-
-			case 'refresh-all-icons':
-				// Regenerate all icon sources
-				foreach (['icons', 'forms', 'dash'] as $src) {
-					IconsManager::for($src)->forceRefresh();
-				}
-				IconsManager::regenerateAllCSS();
-
-				return new \WP_REST_Response([
-					'success' => true,
-					'message' => 'All icon CSS files regenerated successfully'
-				]);
-
-			case 'restore-icon-version':
-				$timestamp = (int)$request->get_param('timestamp');
-				if (empty($timestamp)) {
-					return new \WP_REST_Response([
-						'success' => false,
-						'message' => 'No timestamp provided'
-					], 400);
-				}
-
-				if ($icons->restoreVersion($timestamp)) {
-					return new \WP_REST_Response([
-						'success' => true,
-						'message' => 'Icon version restored successfully'
-					]);
-				}
-
-				return new \WP_REST_Response([
-					'success' => false,
-					'message' => 'Failed to restore icon version'
-				], 500);
-
-			case 'merge-icon-versions':
-				$timestamps = $request->get_param('timestamps');
-
-				if (empty($timestamps) || !is_array($timestamps)) {
-					return new \WP_REST_Response([
-						'success' => false,
-						'message' => 'No versions selected for merging'
-					], 400);
-				}
-
-				$timestamps = array_map('intval', $timestamps);
-
-				if (count($timestamps) < 2) {
-					return new \WP_REST_Response([
-						'success' => false,
-						'message' => 'Please select at least 2 versions to merge'
-					], 400);
-				}
-
-				if ($icons->mergeVersions($timestamps)) {
-					// Regenerate CSS after merge
-					IconsManager::regenerateAllCSS([$source => true]);
-
-					return new \WP_REST_Response([
-						'success' => true,
-						'message' => 'Icon versions merged successfully'
-					]);
-				}
-
-				return new \WP_REST_Response([
-					'success' => false,
-					'message' => 'Failed to merge icon versions'
-				], 500);
-
-			default:
-				return new \WP_REST_Response([
-					'success' => false,
-					'message' => 'Invalid action'
-				], 400);
-		}
-	}
-
     /**
      * Register a subpage to appear under the main settings page
      *
@@ -388,6 +218,11 @@
         }
     }
 
+	public function getMainConfig():array
+	{
+		return $this->main_page;
+	}
+
     /**
      * Render the main settings page
      */
@@ -483,11 +318,11 @@
         </li>
         <li>
             <span class="status-label">Content Types:</span>
-            <span class="status-value"><?= count(JVB_CONTENT); ?> registered</span>
+            <span class="status-value"><?= count(Registrar::getRegistered('post')); ?> registered</span>
         </li>
         <li>
             <span class="status-label">Taxonomies:</span>
-            <span class="status-value"><?= count(JVB_TAXONOMY); ?> registered</span>
+            <span class="status-value"><?= count(Registrar::getRegistered('term')); ?> registered</span>
         </li>
         <?php
     }
@@ -519,10 +354,8 @@
         global $wpdb;
 
         $week_ago = date('Y-m-d H:i:s', strtotime('-7 days'));
-		$content_types = [];
-		foreach (JVB_CONTENT as $content => $config) {
-			$content_types[jvbCheckBase($content)] = $config['plural'];
-		}
+		$content_types = array_map(function ($type) { return jvbCheckBase($type); },
+			Registrar::getRegistered('post'));
 
         ?>
         <table class="jvb-content-table">
@@ -615,40 +448,41 @@
      *
      * @param string $hook Current admin page
      */
-    public function enqueueAdminAssets(string $hook):void
-    {
-        // Check if we're on an Edmonton Ink admin page
-        if (strpos($hook, BASE) === false) {
-            return;
-        }
+	public function enqueueAdminAssets(string $hook):void
+	{
+		// More robust check for JVB admin pages
+		if (strpos($hook, BASE) === false) {
+			return;
+		}
 
-        // Enqueue admin styles
-        wp_enqueue_style(
-            'jvb-admin-styles',
-            JVB_URL . 'assets/css/admin.css',
-            [],
-            '1.0.0'
-        );
+		// Enqueue admin styles
+		wp_enqueue_style(
+			'jvb-admin-styles',
+			JVB_URL . 'assets/css/admin.css',
+			[],
+			'1.1'
+		);
 
-        // Enqueue admin scripts
-        wp_enqueue_script(
-            'jvb-admin-scripts',
-            JVB_URL . 'assets/js/admin.js',
-            [],
-            '1.0.0',
-            true
-        );
+		// Enqueue admin scripts - make sure jvb-auth is loaded first
+		wp_enqueue_script(
+			'jvb-admin-scripts',
+			JVB_URL . 'assets/js/admin.js',
+			['jvb-auth'],
+			'1.1',
+			['strategy' => 'defer', 'in_footer' => true]
+		);
 
-        wp_localize_script(
-            'jvb-admin-scripts',
-            'jvbSettings',
-            [
-                'api'    => rest_url('jvb/v1/admin-action'),
-                'nonce'     => wp_create_nonce('wp_rest'),
-                'action' => wp_create_nonce('itsme'),
-            ]
-        );
-    }
+		// Localize to jvb-admin-scripts as well for redundancy
+		wp_localize_script(
+			'jvb-auth',
+			'jvbSettings',
+			[
+				'api'    => rest_url('jvb/v1/'),
+				'nonce'  => wp_create_nonce('wp_rest'),
+				'action' => wp_create_nonce('itsme'),
+			]
+		);
+	}
 
     /**
      * Create a custom SVG icon for the admin menu
@@ -679,11 +513,6 @@
 	{
 		$groups = Cache::getAllGroups();
 
-		// Separate generic vs. specific caches
-		$generic_groups = [];
-		$content_specific = [];
-		$nonce = wp_create_nonce('wp_rest');
-
 		// Separate by type
 		$generic = [];
 		$specific = [];
@@ -701,7 +530,9 @@
 			<h1>Cache Management</h1>
 
 			<div class="jvb-cache-actions">
-				<button type="button" class="button button-primary" data-action="flush-all">
+				<button type="button"
+						class="button button-primary"
+						data-cache-action="flush-all">
 					<?= jvbDashIcon('arrows-clockwise'); ?>
 					Flush All Caches
 				</button>
@@ -718,15 +549,18 @@
 					</tr>
 					</thead>
 					<tbody>
-					<?php if (empty($generic_groups)): ?>
+					<?php if (empty($generic)): ?>
 						<tr><td colspan="3">No generic caches registered</td></tr>
 					<?php else: ?>
-						<?php foreach ($generic_groups as $group => $configs): ?>
+						<?php foreach ($generic as $group => $data): ?>
 							<tr>
 								<td><strong><?= esc_html($group); ?></strong></td>
-								<td><?= $this->formatConnections($configs); ?></td>
+								<td><?= $this->formatConnections($data); ?></td>
 								<td>
-									<button type="button" class="button" data-action="flush-cache" data-group="<?= esc_attr($group); ?>">
+									<button type="button"
+											class="button"
+											data-cache-action="flush-cache"
+											data-group="<?= esc_attr($group); ?>">
 										<?= jvbDashIcon('trash'); ?> Flush
 									</button>
 								</td>
@@ -748,24 +582,14 @@
 					</tr>
 					</thead>
 					<tbody>
-					<?php foreach ($specific as $group => $configs): ?>
-						<tr>
-							<td><strong><?= esc_html($group); ?></strong></td>
-							<td><?= $this->formatConnections($configs); ?></td>
-							<td>
-								<button type="button" class="button" data-action="flush-cache" data-group="<?= esc_attr($group); ?>">
-									<?= jvbDashIcon('trash'); ?> Flush
-								</button>
-							</td>
-						</tr>
-					<?php endforeach; ?>
-					<?php foreach ($generic as $group => $data): ?>
+					<?php foreach ($specific as $group => $data): ?>
 						<tr>
 							<td><strong><?= esc_html($group); ?></strong></td>
 							<td><?= $this->formatConnections($data); ?></td>
 							<td>
-								<button type="button" class="button"
-										data-action="flush-cache"
+								<button type="button"
+										class="button"
+										data-cache-action="flush-cache"
 										data-group="<?= esc_attr($group); ?>">
 									<?= jvbDashIcon('trash'); ?> Flush
 								</button>
@@ -776,57 +600,6 @@
 				</table>
 			</details>
 		</div>
-		<script>
-			(function() {
-				const apiUrl = '<?= esc_js(rest_url('jvb/v1/admin-cache')); ?>';
-				const nonce = '<?= esc_js($nonce); ?>';
-
-				function callCacheAction(action, data = {}) {
-					const body = { action, ...data };
-
-					return fetch(apiUrl, {
-						method: 'POST',
-						headers: {
-							'Content-Type': 'application/json',
-							'X-WP-Nonce': nonce
-						},
-						body: JSON.stringify(body)
-					})
-						.then(response => response.json())
-						.then(data => {
-							if (data.success) {
-								alert(data.message || 'Success!');
-								location.reload();
-							} else {
-								alert('Error: ' + (data.message || 'Unknown error'));
-							}
-						})
-						.catch(error => {
-							alert('Network error: ' + error.message);
-							console.error('Error:', error);
-						});
-				}
-
-				// Flush all caches
-				document.querySelector('[data-action="flush-all"]')?.addEventListener('click', function() {
-					if (confirm('Flush all caches? This may temporarily slow down your site.')) {
-						this.disabled = true;
-						callCacheAction('flush-all');
-					}
-				});
-
-				// Flush individual cache groups
-				document.querySelectorAll('[data-action="flush-cache"]').forEach(btn => {
-					btn.addEventListener('click', function() {
-						const group = this.getAttribute('data-group');
-						if (confirm(`Flush cache group "${group}"?`)) {
-							this.disabled = true;
-							callCacheAction('flush-cache', { group: group });
-						}
-					});
-				});
-			})();
-		</script>
 		<?php
 	}
 
@@ -834,22 +607,12 @@
 	{
 		$group = jvbNoBase($group);
 
-		if (defined('JVB_CONTENT')) {
-			foreach (JVB_CONTENT as $key => $config) {
-				if (jvbNoBase($key) === $group) {
-					return true;
-				}
+		$registered = Registrar::getRegistered();
+		foreach ($registered as $r) {
+			if ($r === $group) {
+				return true;
 			}
 		}
-
-		if (defined('JVB_TAXONOMY')) {
-			foreach (JVB_TAXONOMY as $key => $config) {
-				if (jvbNoBase($key) === $group) {
-					return true;
-				}
-			}
-		}
-
 		return false;
 	}
 
@@ -915,11 +678,10 @@
 		$current_source = sanitize_text_field($current_source);
 
 		// Get all registered icon sources
-		$all_sources = ['icons', 'forms', 'dash']; // You could get this dynamically if needed
+		$all_sources = ['icons', 'forms', 'dash'];
 
 		$icons = IconsManager::for($current_source);
 		$versions = $icons->getVersionHistory();
-		$nonce = wp_create_nonce('wp_rest');
 
 		?>
 		<div class="wrap jvb-admin-wrap">
@@ -928,9 +690,11 @@
 			<!-- Source Selector -->
 			<div class="jvb-icon-source-selector">
 				<label for="icon-source-select">Icon Source:</label>
-				<select id="icon-source-select" onchange="window.location.href='<?= admin_url('admin.php?page=' . BASE . 'icons&icon_source='); ?>' + this.value">
+				<select id="icon-source-select"
+						onchange="window.location.href='<?= admin_url('admin.php?page=' . BASE . 'icons&icon_source='); ?>' + this.value">
 					<?php foreach ($all_sources as $source): ?>
-						<option value="<?= esc_attr($source); ?>" <?= selected($current_source, $source, false); ?>>
+						<option value="<?= esc_attr($source); ?>"
+							<?= selected($current_source, $source, false); ?>>
 							<?= esc_html(ucfirst($source)); ?>
 						</option>
 					<?php endforeach; ?>
@@ -938,11 +702,19 @@
 			</div>
 
 			<div class="jvb-icon-actions">
-				<button type="button" class="button button-primary" data-action="refresh-icons" data-source="<?= esc_attr($current_source); ?>">
+				<button type="button"
+						class="button button-primary"
+						data-icon-action="refresh-icons"
+						data-source="<?= esc_attr($current_source); ?>">
 					<?= jvbDashIcon('arrows-clockwise'); ?>
 					Force Refresh CSS
 				</button>
-				<button type="button" class="button" data-action="merge-icon-versions" data-source="<?= esc_attr($current_source); ?>" id="merge-versions-btn" disabled>
+				<button type="button"
+						class="button"
+						data-icon-action="merge-icon-versions"
+						data-source="<?= esc_attr($current_source); ?>"
+						id="merge-versions-btn"
+						disabled>
 					<?= jvbDashIcon('git-merge'); ?>
 					Merge Selected Versions
 				</button>
@@ -985,15 +757,18 @@
 							</td>
 							<td><?= esc_html($version['size_formatted']); ?></td>
 							<td>
-								<button type="button" class="button restore-version-btn"
-										data-action="restore-icon-version"
+								<button type="button"
+										class="button restore-version-btn"
+										data-icon-action="restore-icon-version"
 										data-source="<?= esc_attr($current_source); ?>"
 										data-timestamp="<?= esc_attr($version['timestamp']); ?>">
 									<?= jvbDashIcon('arrow-counter-clockwise'); ?> Restore
 								</button>
 							</td>
 						</tr>
-						<tr id="icon-list-<?= esc_attr($version['timestamp']); ?>" class="icon-list-row" style="display: none;">
+						<tr id="icon-list-<?= esc_attr($version['timestamp']); ?>"
+							class="icon-list-row"
+							style="display: none;">
 							<td colspan="5">
 								<div class="icon-list-content">
 									<?php foreach ($version['iconList'] as $style => $icons): ?>
@@ -1008,108 +783,6 @@
 				</tbody>
 			</table>
 		</div>
-
-		<script>
-			(function() {
-				const apiUrl = '<?= esc_js(rest_url('jvb/v1/admin-icons')); ?>';
-				const nonce = '<?= esc_js($nonce); ?>';
-				const currentSource = '<?= esc_js($current_source); ?>';
-
-				// Helper function for API calls
-				function callIconAction(action, data = {}) {
-					const body = { action, source: currentSource, ...data };
-
-					return fetch(apiUrl, {
-						method: 'POST',
-						headers: {
-							'Content-Type': 'application/json',
-							'X-WP-Nonce': nonce
-						},
-						body: JSON.stringify(body)
-					})
-						.then(response => response.json())
-						.then(data => {
-							if (data.success) {
-								alert(data.message || 'Success!');
-								location.reload();
-							} else {
-								alert('Error: ' + (data.message || 'Unknown error'));
-							}
-							return data;
-						})
-						.catch(error => {
-							alert('Network error: ' + error.message);
-							console.error('Error:', error);
-						});
-				}
-
-				// Enable/disable merge button based on selection
-				document.querySelectorAll('.version-checkbox').forEach(checkbox => {
-					checkbox.addEventListener('change', function() {
-						const checkedCount = document.querySelectorAll('.version-checkbox:checked').length;
-						document.getElementById('merge-versions-btn').disabled = checkedCount < 2;
-					});
-				});
-
-				// Select all functionality
-				const selectAll = document.getElementById('select-all-versions');
-				if (selectAll) {
-					selectAll.addEventListener('change', function() {
-						document.querySelectorAll('.version-checkbox').forEach(checkbox => {
-							checkbox.checked = this.checked;
-							checkbox.dispatchEvent(new Event('change'));
-						});
-					});
-				}
-
-				// Toggle icon list view
-				document.querySelectorAll('.view-icon-list-btn').forEach(btn => {
-					btn.addEventListener('click', function() {
-						const timestamp = this.getAttribute('data-timestamp');
-						const row = document.getElementById('icon-list-' + timestamp);
-						if (row) {
-							row.style.display = row.style.display === 'none' ? '' : 'none';
-						}
-					});
-				});
-
-				// Force refresh button
-				document.querySelector('[data-action="refresh-icons"]')?.addEventListener('click', function() {
-					if (confirm('Force regenerate icon CSS? This will reload the page.')) {
-						this.disabled = true;
-						callIconAction('refresh-icons');
-					}
-				});
-
-				// Merge versions button
-				document.getElementById('merge-versions-btn')?.addEventListener('click', function() {
-					const checkboxes = document.querySelectorAll('.version-checkbox:checked');
-					const timestamps = Array.from(checkboxes).map(cb => parseInt(cb.value));
-
-					if (timestamps.length < 2) {
-						alert('Please select at least 2 versions to merge');
-						return;
-					}
-
-					if (confirm(`Merge ${timestamps.length} versions? This will create a new CSS file with all unique icons.`)) {
-						this.disabled = true;
-						callIconAction('merge-icon-versions', { timestamps: timestamps });
-					}
-				});
-
-				// Restore version buttons
-				document.querySelectorAll('.restore-version-btn').forEach(btn => {
-					btn.addEventListener('click', function() {
-						const timestamp = parseInt(this.getAttribute('data-timestamp'));
-
-						if (confirm('Restore this icon version? This will reload the page.')) {
-							this.disabled = true;
-							callIconAction('restore-icon-version', { timestamp: timestamp });
-						}
-					});
-				});
-			})();
-		</script>
 		<?php
 	}
 

--
Gitblit v1.10.0