From 8c6502de2f8ec2bd8382cd6945c327d7be400e14 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Wed, 28 Jan 2026 05:34:41 +0000
Subject: [PATCH] =Queue cleanup - seems to be working enough to get legacy before and after going!

---
 inc/managers/AdminPages.php |  315 +++++++++++++++++++++++++++++++--------------------
 1 files changed, 190 insertions(+), 125 deletions(-)

diff --git a/inc/managers/AdminPages.php b/inc/managers/AdminPages.php
index 5145e51..cf42870 100644
--- a/inc/managers/AdminPages.php
+++ b/inc/managers/AdminPages.php
@@ -34,7 +34,7 @@
             'icon' => jvbCSSIcon('settings'),
             'position' => 0
         ];
-		$this->subpages = apply_filters('jvbAdminSubpages', []);
+		$this->subpages = get_option(BASE.'adminSubpage', []);
 //        delete_option(BASE.'admin_actions');
 //        delete_option(BASE.'admin_subpages');
 //        $this->getSubpages();
@@ -48,6 +48,9 @@
 		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']);
     }
 
 	/**
@@ -95,10 +98,10 @@
 
 		switch ($action) {
 			case 'flush-all':
-				wp_cache_flush();
+				$total = Cache::flushAll();
 				return new \WP_REST_Response([
 					'success' => true,
-					'message' => 'All caches flushed successfully'
+					'message' => $total.' caches flushed successfully'
 				]);
 
 			case 'flush-cache':
@@ -110,7 +113,7 @@
 					], 400);
 				}
 
-				\JVBase\managers\CacheManager::invalidateAll($group);
+				Cache::for($group)?->flush();
 
 				return new \WP_REST_Response([
 					'success' => true,
@@ -131,14 +134,30 @@
 	public function handleIconAction(\WP_REST_Request $request): \WP_REST_Response
 	{
 		$action = sanitize_text_field($request->get_param('action'));
-		$icons = \JVBase\managers\IconsManager::getInstance();
+		$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'
+					'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':
@@ -182,6 +201,9 @@
 				}
 
 				if ($icons->mergeVersions($timestamps)) {
+					// Regenerate CSS after merge
+					IconsManager::regenerateAllCSS([$source => true]);
+
 					return new \WP_REST_Response([
 						'success' => true,
 						'message' => 'Icon versions merged successfully'
@@ -434,7 +456,7 @@
     protected function renderStatusItems():void
     {
         // Get queue stats
-        $queue_status = JVB()->queue()->getQueueStatus();
+        $queue_status = JVB()->queue()->getStatus();
 		error_log('Queue Status: '.print_r($queue_status, true));
 
         // Other system checks
@@ -579,9 +601,9 @@
             if (current_user_can($action['capability'])) {
                 ?>
                 <a data-action="<?=$action['slug']?>" class="jvb-action">
-                    <?= jvbIcon($action['icon']); ?>
+                    <?= jvbDashIcon($action['icon']); ?>
                     <span class="jvb-link-title"><?= esc_html($action['label'])?></span>
-                    <span class="loader"><?=jvbIcon('arrows-clockwise')?><?=jvbIcon('check')?></span>
+                    <span class="loader"><?=jvbDashIcon('arrows-clockwise')?><?=jvbDashIcon('check')?></span>
                 </a>
                 <?php
             }
@@ -636,7 +658,7 @@
      */
     protected function getIcon(string $icon = 'logo', bool $css = false): string
     {
-        $svg = jvbIcon($icon, ['wrap' => false]);
+        $svg = jvbDashIcon($icon, ['wrap' => false]);
         if ($css) {
             // For CSS, replace currentColor with brand color
             $svg = str_replace('currentColor', '#FF0080', $svg);
@@ -655,20 +677,22 @@
 
 	public function renderCachePage():void
 	{
-		$connections = CacheManager::getAllConnections();
+		$groups = Cache::getAllGroups();
 
 		// Separate generic vs. specific caches
 		$generic_groups = [];
 		$content_specific = [];
 		$nonce = wp_create_nonce('wp_rest');
 
-		foreach ($connections as $group => $configs) {
-			$is_generic = !$this->isBoundToContentOrTaxonomy($group);
+		// Separate by type
+		$generic = [];
+		$specific = [];
 
-			if ($is_generic) {
-				$generic_groups[$group] = $configs;
+		foreach ($groups as $group => $data) {
+			if ($this->isBoundToContentOrTaxonomy($group)) {
+				$specific[$group] = $data;
 			} else {
-				$content_specific[$group] = $configs;
+				$generic[$group] = $data;
 			}
 		}
 
@@ -678,7 +702,7 @@
 
 			<div class="jvb-cache-actions">
 				<button type="button" class="button button-primary" data-action="flush-all">
-					<?= jvbIcon('arrows-clockwise'); ?>
+					<?= jvbDashIcon('arrows-clockwise'); ?>
 					Flush All Caches
 				</button>
 			</div>
@@ -703,7 +727,7 @@
 								<td><?= $this->formatConnections($configs); ?></td>
 								<td>
 									<button type="button" class="button" data-action="flush-cache" data-group="<?= esc_attr($group); ?>">
-										<?= jvbIcon('trash'); ?> Flush
+										<?= jvbDashIcon('trash'); ?> Flush
 									</button>
 								</td>
 							</tr>
@@ -724,13 +748,26 @@
 					</tr>
 					</thead>
 					<tbody>
-					<?php foreach ($content_specific as $group => $configs): ?>
+					<?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); ?>">
-									<?= jvbIcon('trash'); ?> Flush
+									<?= jvbDashIcon('trash'); ?> Flush
+								</button>
+							</td>
+						</tr>
+					<?php endforeach; ?>
+					<?php foreach ($generic 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"
+										data-group="<?= esc_attr($group); ?>">
+									<?= jvbDashIcon('trash'); ?> Flush
 								</button>
 							</td>
 						</tr>
@@ -816,15 +853,24 @@
 		return false;
 	}
 
-	protected function formatConnections(array $configs): string
+	protected function formatConnections(array $data): string
 	{
-		$connections = [];
-		foreach ($configs as $config) {
-			$parent = $config['parent'] ?? 'unknown';
-			$scope = $config['scope'] ?? 'id';
-			$connections[] = "{$parent} ({$scope})";
+		$parts = [];
+
+		if (!empty($data['connects_to'])) {
+			$targets = array_map(function($conn) {
+				$flush_text = $conn['flush'] ? ' (flush all)' : '';
+				return $conn['group'] . $flush_text;
+			}, $data['connects_to']);
+			$parts[] = '<strong>Invalidates:</strong> ' . implode(', ', $targets);
 		}
-		return esc_html(implode(', ', $connections));
+
+		if (!empty($data['connected_from'])) {
+			$sources = array_map(fn($conn) => $conn['group'], $data['connected_from']);
+			$parts[] = '<strong>Invalidated by:</strong> ' . implode(', ', $sources);
+		}
+
+		return $parts ? implode('<br>', $parts) : 'No connections';
 	}
 
 	public function handleCacheActions($response, $request, $action):WP_REST_Response
@@ -850,7 +896,8 @@
 				], 400);
 			}
 
-			\JVBase\managers\CacheManager::invalidateAll($group);
+			$group = sanitize_text_field($request->get_param('group'));
+			Cache::invalidateGroup($group);
 
 			return new WP_REST_Response([
 				'success' => true,
@@ -858,74 +905,19 @@
 			]);
 		}
 
-		if ($action === '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);
-			}
-
-			// Convert to integers
-			$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);
-			}
-
-			$icons = \JVBase\managers\IconsManager::getInstance();
-
-			if ($icons->mergeVersions($timestamps)) {
-				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);
-		}
-
-		if ($action === 'refresh-icons') {
-			$icons = \JVBase\managers\IconsManager::getInstance();
-			$icons->forceRefresh();
-
-			return new WP_REST_Response([
-				'success' => true,
-				'message' => 'Icon CSS refresh triggered'
-			]);
-		}
-
-		if ($action === 'restore-icon-version') {
-			$timestamp = (int)$request->get_param('timestamp');
-			$icons = \JVBase\managers\IconsManager::getInstance();
-
-			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);
-		}
-
 		return $response;
 	}
 
 	public function renderIconsPage():void
 	{
-		$icons = \JVBase\managers\IconsManager::getInstance();
+		// Get current source from query param or default to 'icons'
+		$current_source = $_GET['icon_source'] ?? 'icons';
+		$current_source = sanitize_text_field($current_source);
+
+		// Get all registered icon sources
+		$all_sources = ['icons', 'forms', 'dash']; // You could get this dynamically if needed
+
+		$icons = IconsManager::for($current_source);
 		$versions = $icons->getVersionHistory();
 		$nonce = wp_create_nonce('wp_rest');
 
@@ -933,18 +925,30 @@
 		<div class="wrap jvb-admin-wrap">
 			<h1>Icon Management</h1>
 
+			<!-- 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">
+					<?php foreach ($all_sources as $source): ?>
+						<option value="<?= esc_attr($source); ?>" <?= selected($current_source, $source, false); ?>>
+							<?= esc_html(ucfirst($source)); ?>
+						</option>
+					<?php endforeach; ?>
+				</select>
+			</div>
+
 			<div class="jvb-icon-actions">
-				<button type="button" class="button button-primary" data-action="refresh-icons">
-					<?= jvbIcon('arrows-clockwise'); ?>
+				<button type="button" class="button button-primary" data-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" id="merge-versions-btn" disabled>
-					<?= jvbIcon('git-merge'); ?>
+				<button type="button" class="button" data-action="merge-icon-versions" data-source="<?= esc_attr($current_source); ?>" id="merge-versions-btn" disabled>
+					<?= jvbDashIcon('git-merge'); ?>
 					Merge Selected Versions
 				</button>
 			</div>
 
-			<h2>Version History</h2>
+			<h2>Version History for <?= esc_html(ucfirst($current_source)); ?></h2>
 			<table class="wp-list-table widefat fixed striped">
 				<thead>
 				<tr>
@@ -974,18 +978,18 @@
 							<td>
 								<?= esc_html($version['icon_count']); ?> icons
 								<button type="button"
-										class="button-link"
-										data-action="view-icon-list"
+										class="button-link view-icon-list-btn"
 										data-timestamp="<?= esc_attr($version['timestamp']); ?>">
 									(view)
 								</button>
 							</td>
 							<td><?= esc_html($version['size_formatted']); ?></td>
 							<td>
-								<button type="button" class="button"
+								<button type="button" class="button restore-version-btn"
 										data-action="restore-icon-version"
+										data-source="<?= esc_attr($current_source); ?>"
 										data-timestamp="<?= esc_attr($version['timestamp']); ?>">
-									<?= jvbIcon('arrow-counter-clockwise'); ?> Restore
+									<?= jvbDashIcon('arrow-counter-clockwise'); ?> Restore
 								</button>
 							</td>
 						</tr>
@@ -1009,10 +1013,11 @@
 			(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, ...data };
+					const body = { action, source: currentSource, ...data };
 
 					return fetch(apiUrl, {
 						method: 'POST',
@@ -1069,34 +1074,28 @@
 				});
 
 				// Force refresh button
-				const refreshBtn = document.getElementById('refresh-icons-btn');
-				if (refreshBtn) {
-					refreshBtn.addEventListener('click', function() {
-						if (confirm('Force regenerate icon CSS? This will reload the page.')) {
-							this.disabled = true;
-							callIconAction('refresh-icons');
-						}
-					});
-				}
+				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
-				const mergeBtn = document.getElementById('merge-versions-btn');
-				if (mergeBtn) {
-					mergeBtn.addEventListener('click', function() {
-						const checkboxes = document.querySelectorAll('.version-checkbox:checked');
-						const timestamps = Array.from(checkboxes).map(cb => parseInt(cb.value));
+				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 (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 });
-						}
-					});
-				}
+					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 => {
@@ -1113,4 +1112,70 @@
 		</script>
 		<?php
 	}
+
+	public static function addSubpage(string $key, array $value):void
+	{
+		$option = get_option(BASE.'adminSubpage', []);
+		if (empty($option) || !array_key_exists($key, $option)) {
+			$option[$key] = $value;
+			update_option(BASE.'adminSubpage', $option);
+		}
+	}
+
+	/**
+	 * Handle admin page form submissions
+	 * Fires after WordPress admin_init
+	 */
+	public function handleAdminPageSubmission(): void
+	{
+		// Only process on our admin pages
+		if (!isset($_GET['page']) || strpos($_GET['page'], BASE) !== 0) {
+			return;
+		}
+
+		// Check for form submission
+		if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['submit'])) {
+			return;
+		}
+
+		// Verify nonce
+		$nonce_field = BASE . 'admin_page_nonce';
+		if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], $nonce_field)) {
+			add_action('admin_notices', function() {
+				echo '<div class="notice notice-error"><p>Security check failed. Please try again.</p></div>';
+			});
+			return;
+		}
+
+		$page_slug = sanitize_text_field($_GET['page']);
+
+		// Allow other classes to handle their page submissions
+		$result = apply_filters('jvb_admin_page_submission', null, $page_slug, $_POST);
+
+		// Store result in transient for after redirect
+		if (is_array($result)) {
+			set_transient(BASE . 'admin_notice_' . get_current_user_id(), $result, 30);
+		}
+
+		// Redirect to prevent form resubmission (POST-Redirect-GET pattern)
+		wp_safe_redirect(add_query_arg(['page' => $page_slug], admin_url('admin.php')));
+		exit;
+	}
+
+	/**
+	 * Display admin notices from form submissions
+	 */
+	public function displayAdminNotices(): void
+	{
+		$notice = get_transient(BASE . 'admin_notice_' . get_current_user_id());
+
+		if ($notice && is_array($notice)) {
+			delete_transient(BASE . 'admin_notice_' . get_current_user_id());
+
+			$type = $notice['success'] ? 'success' : 'error';
+			$message = $notice['message'] ?? 'Settings saved.';
+
+			echo '<div class="notice notice-' . esc_attr($type) . ' is-dismissible"><p>' . esc_html($message) . '</p></div>';
+		}
+	}
 }

--
Gitblit v1.10.0