From bdf344f19158a980a99dcca7c82c6e34e84533c0 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Tue, 15 Sep 2026 03:05:03 +0000
Subject: [PATCH] =Found little glitch with auto-adding rewrite rules to taxonomy Registrar instances where we have the post type as the base in the url rewrite

---
 inc/managers/IconsManager.php |  248 +++++++++++++++++++++++++++----------------------
 1 files changed, 138 insertions(+), 110 deletions(-)

diff --git a/inc/managers/IconsManager.php b/inc/managers/IconsManager.php
index 4415bc7..a3bc9ff 100644
--- a/inc/managers/IconsManager.php
+++ b/inc/managers/IconsManager.php
@@ -1,7 +1,9 @@
 <?php
 namespace JVBase\managers;
 
-use JVBase\utility\Features;
+use Exception;
+use JVBase\registrar\Registrar;
+use JVBase\base\Site;
 
 if (!defined('ABSPATH')) {
 	exit;
@@ -18,13 +20,22 @@
 	// Instance-specific properties
 	protected string $source;
 	protected array $icons = []; // Icons for THIS source [style => [names]]
-	protected CacheManager $cache;
+	protected Cache $cache;
 	protected string $style = 'regular';
 	protected array $styles = ['regular', 'bold', 'duotone', 'fill', 'light', 'thin'];
 	protected array $customIcons = []; // Custom icons for THIS source
 	protected array $map = [];
 	protected const MAX_VERSIONS = 5;
 
+	protected string $timestampKey;
+	protected string $iconKey;
+	protected string $iconHistoryKey;
+	protected static string $allIcons = 'icons_all_used';
+	protected static string $updateIcons = 'icons_needs_update';
+	protected static string $iconMap = 'icons_map';
+
+
+
 	/**
 	 * Factory method - get or create instance for a source
 	 */
@@ -33,6 +44,9 @@
 		if (!isset(self::$instances[$source])) {
 			self::$instances[$source] = new self($source);
 		}
+		self::$instances[$source]->setTimestampKey(BASE.'icons_'.$source.'_timestamp');
+		self::$instances[$source]->setIconKey(BASE.'icons_'.$source);
+		self::$instances[$source]->setIconHistoryKey(BASE.'icons_history_'.$source);
 		return self::$instances[$source];
 	}
 
@@ -42,10 +56,8 @@
 	private function __construct(string $source)
 	{
 		$this->source = $source;
-		$this->cache = CacheManager::for('icons_' . $source, WEEK_IN_SECONDS);
-		$this->style = (array_key_exists('icons', JVB_SITE) && in_array(JVB_SITE['icons'], $this->styles))
-			? JVB_SITE['icons']
-			: 'regular';
+		$this->cache = Cache::for('icons_' . $source);
+		$this->style = Site::icon();
 
 		$this->addMap();
 
@@ -73,6 +85,19 @@
 		$this->registerInstanceHooks();
 	}
 
+	protected function setIconKey(string $key):void
+	{
+		$this->iconKey = $key;
+	}
+	protected function setTimestampKey(string $key):void
+	{
+		$this->timestampKey = $key;
+	}
+	protected function setIconHistoryKey(string $key):void
+	{
+		$this->iconHistoryKey = $key;
+	}
+
 
 
 	/**
@@ -125,7 +150,7 @@
 	 */
 	protected function loadStoredIcons(): void
 	{
-		$allIcons = get_option(BASE.'usedIcons', []);
+		$allIcons = get_option(BASE.self::$allIcons, []);
 		$storedIcons = $allIcons[$this->source] ?? [];
 
 		// Merge stored icons with any existing icons (like custom icons)
@@ -145,6 +170,7 @@
 				'apple-logo',
 				'check-circle',
 				'close-circle',
+				'faders-horizontal',
 				'cloud-slash',
 				'exclamation-mark',
 				'cloud-arrow-down',
@@ -195,15 +221,11 @@
 //			]
 		];
 
+
 		// Add icons from content/taxonomy/user configs (like old behavior)
 		$configIcons = $this->getIconsFromConfigs();
 		if (!empty($configIcons)) {
-			foreach ($configIcons as $source => $icons) {
-				if (!isset($defaults[$source])) {
-					$defaults[$source] = [];
-				}
-				$defaults[$source] = array_merge($defaults[$source], $icons);
-			}
+			$defaults['icons'] = array_merge($defaults['icons'], $configIcons);
 		}
 
 		// Allow filtering per source (extensibility)
@@ -214,35 +236,27 @@
 		if (isset($allIcons[$this->source])) {
 			$icons = array_merge($icons, $allIcons[$this->source]);
 		}
-
 		if (!empty($icons)) {
 			$this->include($icons);
 		}
 	}
 
 	/**
-	 * Get icons from JVB_CONTENT, JVB_TAXONOMY, JVB_USER configs
+	 * Get icons from Registrar instances
+	 *
 	 */
 	protected function getIconsFromConfigs(): array
 	{
 		$icons = [];
-		$check = [JVB_CONTENT, JVB_TAXONOMY, JVB_USER];
+		$registered = Registrar::getRegistered();
 
-		foreach ($check as $constant) {
-			foreach ($constant as $key => $value) {
-				if (isset($value['icon'])) {
-					// Determine source based on context (you could add 'icon_source' to configs)
-					$source = $value['icon_source'] ?? 'icons';
-
-					if (!isset($icons[$source])) {
-						$icons[$source] = [];
-					}
-					$icons[$source][] = $value['icon'];
-				}
-			}
+		foreach ($registered as $type) {
+			$registrar = Registrar::getInstance($type);
+			$icons[] = $registrar->getIcon();
 		}
 
-		return $icons;
+
+		return array_unique(array_filter($icons));
 	}
 
 	/**
@@ -316,20 +330,19 @@
 	 */
 	protected function saveIcons(): void
 	{
-		$allIcons = [];
-		foreach (self::$instances as $source => $instance) {
-			$allIcons[$source] = $instance->icons;
-		}
+		$allIcons = array_map(function ($instance) {
+			return $instance->icons;
+		}, self::$instances);
 
-		update_option(BASE.'usedIcons', $allIcons);
+		update_option(BASE.self::$allIcons, $allIcons);
 
 		// Track WHICH source needs updating
-		$needsUpdate = get_option(BASE.'icons_needs_update', []);
+		$needsUpdate = get_option(BASE.self::$updateIcons, []);
 		if (!is_array($needsUpdate)) {
 			$needsUpdate = [];
 		}
 		$needsUpdate[$this->source] = true;
-		update_option(BASE.'icons_needs_update', $needsUpdate);
+		update_option(BASE.self::$updateIcons, $needsUpdate);
 	}
 
 	/**
@@ -357,24 +370,24 @@
 
 	protected function addMap(): void
 	{
-		$map = get_option(BASE.'iconMap');
+		$map = get_option(BASE.self::$iconMap);
 		if (!$map) {
 			$map = [
 				'seo'	=> 'robot'
 			];
-			if (Features::forSite()->has('referrals')) {
+			if (Site::has('referrals')) {
 				$map['referrals'] = 'hand-heart';
 			}
-			if (Features::forSite()->has('dashboard')) {
+			if (Site::has('dashboard')) {
 				$map['dash'] = 'door';
 			}
-			if (Features::forSite()->has('magicLink')) {
+			if (Site::has('magic_link')) {
 				$map['magicLink'] = 'magic-wand';
 			}
-			if (Features::hasAnyIntegration()) {
+			if (Site::hasAnyIntegration()) {
 				$map['integrations'] = 'plugs-connected';
 			}
-			update_option(BASE.'iconMap', $map);
+			update_option(BASE.self::$iconMap, $map);
 		}
 
 		$this->map = apply_filters('jvbMapIcons', $map);
@@ -385,7 +398,8 @@
 	 */
 	protected function registerGlobalHooks(): void
 	{
-		add_action('init', [$this, 'checkCSS']);
+		add_action('wp_loaded', [self::class, 'checkCSS']);
+		add_action('shutdown', [self::class, 'checkCSS']);
 	}
 
 	/**
@@ -407,20 +421,26 @@
 
 	public function enqueueIconStyles():void
 	{
-		wp_enqueue_style('jvb-icons-'.$this->source);
+//		if (file_exists(JVB_CHILD_URL . "assets/css/{$this->source}.css")){
+			wp_enqueue_style('jvb-icons-'.$this->source);
+//		}
+
 	}
 
-	public function checkCSS(): void
+	public static function checkCSS(): void
 	{
-		$needsUpdate = get_option(BASE.'icons_needs_update', []);
+		$needsUpdate = get_option(BASE.self::$updateIcons, []);
+		$needsUpdate = array_filter($needsUpdate, function ($item) {
+			return $item === true;
+		});
 		if (!empty($needsUpdate)) {
 			error_log('Regenerating CSS for sources: ' . implode(', ', array_keys($needsUpdate)));
-			delete_option(BASE.'icons_needs_update');
+			delete_option(BASE.self::$updateIcons);
 			self::regenerateAllCSS($needsUpdate);
 		}
 	}
 
-	protected static function regenerateAllCSS(array $sourcesToUpdate = []): void
+	public static function regenerateAllCSS(array $sourcesToUpdate = []): void
 	{
 		error_log('[IconsManager]:regenerateCSS');
 		$css_dir = JVB_CHILD_DIR.'/assets/css/';
@@ -429,63 +449,41 @@
 			wp_mkdir_p($css_dir);
 		}
 
+		// Load all icons from database option
+		$allIcons = get_option(BASE.self::$allIcons, []);
+
 		// If no specific sources provided, regenerate all
 		if (empty($sourcesToUpdate)) {
-			$sourcesToUpdate = array_fill_keys(array_keys(self::$instances), true);
+			$sourcesToUpdate = array_fill_keys(array_keys($allIcons), true);
 		}
 
-		// Generate CSS only for sources that need it
-		foreach (self::$instances as $source => $instance) {
-			if (!isset($sourcesToUpdate[$source])) {
+		// Generate CSS for each source that needs it
+		foreach ($sourcesToUpdate as $source => $needsUpdate) {
+			if (!$needsUpdate || !isset($allIcons[$source])) {
 				continue;
 			}
 
+			// Get or create instance for this source
+			$instance = self::for($source);
+
+			// Temporarily set icons from database
+			$originalIcons = $instance->icons;
+			$instance->icons = $allIcons[$source];
+
 			$css = $instance->generateIconCSS();
 			$css_path = $css_dir . $source . '.css';
 
 			$instance->archiveCurrentVersion($css);
 
 			if (file_put_contents($css_path, $css) !== false) {
-				CacheManager::updateTimestamp('icons_' . $source);
+				Cache::for('icons_'.$source)->flush();
 				error_log("[IconsManager] Updated {$source}.css");
 			} else {
 				error_log("[IconsManager] Could not write {$source}.css");
 			}
-		}
-	}
 
-	protected function regenerateCSS(array $sourcesToUpdate = []): void
-	{
-		error_log('[IconsManager]:regenerateCSS');
-		$css_dir = JVB_CHILD_DIR.'/assets/css/';
-
-		if (!file_exists($css_dir)) {
-			wp_mkdir_p($css_dir);
-		}
-
-		// If no specific sources provided, regenerate all
-		if (empty($sourcesToUpdate)) {
-			$sourcesToUpdate = array_fill_keys(array_keys(self::$instances), true);
-		}
-
-		// Generate CSS only for sources that need it
-		foreach (self::$instances as $source => $instance) {
-			if (!isset($sourcesToUpdate[$source])) {
-				continue; // Skip this source
-			}
-
-			$css = $instance->generateIconCSS();
-			$css_path = $css_dir . $source . '.css';
-
-			// Archive current version before overwriting
-			$instance->archiveCurrentVersion($css);
-
-			if (file_put_contents($css_path, $css) !== false) {
-				CacheManager::updateTimestamp('icons_' . $source);
-				error_log("[IconsManager] Updated {$source}.css");
-			} else {
-				error_log("[IconsManager] Could not write {$source}.css");
-			}
+			// Restore original icons
+			$instance->icons = $originalIcons;
 		}
 	}
 
@@ -496,10 +494,11 @@
 
 	/**
 	 * Prevent unserialization
+	 * @throws Exception
 	 */
 	public function __wakeup()
 	{
-		throw new \Exception("Cannot unserialize singleton");
+		throw new Exception("Cannot unserialize singleton");
 	}
 
 	/**
@@ -516,6 +515,10 @@
 	 */
 	public function get(string $name, array $options = []): string
 	{
+		if (empty($name)) {
+			//No icon requested
+			return '';
+		}
 		$style = $options['style'] ?? $this->style;
 		$name = $this->map[$name] ?? $name;
 
@@ -526,7 +529,7 @@
 		}
 
 		// Track usage - only if not already tracked
-		if (!isset($this->icons[$style])) {
+		if (!array_key_exists($style, $this->icons)) {
 			$this->icons[$style] = [];
 		}
 
@@ -616,7 +619,7 @@
 	/**
 	 * Get raw SVG content for CSS mask-image
 	 */
-	protected function getRawSvg(string $name, ?string $style = null): ?string
+	public function getRawSvg(string $name, ?string $style = null): ?string
 	{
 		if (!$style) {
 			$style = $this->style;
@@ -640,7 +643,7 @@
 
 	public function registerStyle(): void
 	{
-		$timestamp = CacheManager::getTimestamp('icons_' . $this->source);
+		$timestamp = get_option($this->timestampKey);
 		$handle = 'jvb-icons-' . $this->source;
 
 		wp_register_style(
@@ -661,18 +664,36 @@
 		foreach ($this->icons as $style => $names) {
 			$styleClass = ($style !== $this->style) ? '-'.substr($style, 0, 2) : '';
 			foreach ($names as $icon) {
-				$svg = $this->getEncodedSVG($icon, $style);
-				if ($svg !== '') {
-					$css .= ".icon-{$icon}{$styleClass}{";
-					$css .= "--icon:url('data:image/svg+xml;base64,{$svg}');";
-					$css .= "}";
-				}
+				$css .= $this->generateSingleIconCss($icon, $style, $styleClass);
 			}
 		}
-
+		update_option($this->timestampKey, time());
 		return $this->minifyCss($css);
 	}
 
+	public function generateSingleIconCss(string $icon, ?string $style = null, ?string $styleClass = null):string
+	{
+		$style = $style??$this->style;
+		$styleClass = $styleClass??($style !== $this->style) ? '-'.substr($style, 0, 2) : '';
+		$css = '';
+		$svg = $this->getEncodedSVG($icon, $style);
+		if ($svg !== '') {
+			if ($icon === 'caret-down') {
+				$css .= 'details summary::after,';
+			} elseif ($icon === 'faders-horizontal') {
+				$css .= 'details.all-filters summary::after,';
+			} elseif ($icon === 'link') {
+				$css .= 'input[type=url],';
+			} elseif ($icon === apply_filters('jvbSeparatorLogo', 'logo')) {
+				$css .= 'hr.logo::before,';
+			}
+			$css .= ".icon-{$icon}{$styleClass}{";
+			$css .= "--icon:url('data:image/svg+xml;base64,{$svg}');";
+			$css .= "}";
+		}
+		return $css;
+	}
+
 	protected function minifyCSS(string $css): string
 	{
 		// Remove comments
@@ -690,6 +711,14 @@
 		if (!$style) {
 			$style = $this->style;
 		}
+
+		$icon = $this->map[$icon] ?? $icon;
+
+		// Validate icon exists
+		if (!$this->iconExists($icon, $style)) {
+			error_log('[IconsManager] Icon not found: ' . $icon);
+			return '';
+		}
 		$svg = $this->getEncodedSVG($icon, $style);
 		if ($svg !== '') {
 			return "data:image/svg+xml;base64,{$svg}";
@@ -717,14 +746,12 @@
 	 */
 	public function clearIconCache(): void
 	{
-		delete_option(BASE . 'icon_usage_list'); // Legacy
-		delete_option(BASE.'usedIcons');
-		delete_option(BASE.'iconMap');
+		delete_option(self::$allIcons);
+		delete_option(self::$iconMap);
 
 		// Clear cache for all sources
 		foreach (self::$instances as $source => $instance) {
-			$instance->cache->delete('icon_styles_css');
-			CacheManager::updateTimestamp('icons_' . $source);
+			$instance->cache->forget('icon_styles_css');
 		}
 	}
 
@@ -752,12 +779,12 @@
 			$history = array_slice($history, 0, self::MAX_VERSIONS);
 		}
 
-		update_option(BASE.'icon_css_history_' . $this->source, $history);
+		update_option($this->iconHistoryKey, $history);
 	}
 
 	public function getVersionHistory(): array
 	{
-		return get_option(BASE.'icon_css_history_' . $this->source, []);
+		return get_option($this->iconHistoryKey, []);
 	}
 
 	public function restoreVersion(int $timestamp): bool
@@ -778,7 +805,7 @@
 				if (file_put_contents($css_path, $entry['css']) !== false) {
 					$this->icons = $entry['iconList'];
 					$this->saveIcons();
-					CacheManager::updateTimestamp('icons_' . $this->source);
+					Cache::for('icons_'.$this->source)->flush();
 					return true;
 				}
 
@@ -793,13 +820,14 @@
 	public function forceRefresh(): void
 	{
 		$this->clearIconCache();
-		$needsUpdate = get_option(BASE.'icons_needs_update', []);
+		$needsUpdate = get_option(BASE.self::$updateIcons, []);
 		if (!is_array($needsUpdate)) {
 			$needsUpdate = [];
 		}
 		$needsUpdate[$this->source] = true;
-		update_option(BASE.'icons_needs_update', $needsUpdate);
-		CacheManager::updateTimestamp('icons_' . $this->source);
+		update_option(BASE.self::$updateIcons, $needsUpdate);
+
+		Cache::for('icons_'.$this->source)->flush();
 	}
 
 	public function mergeVersions(array $timestamps): bool
@@ -808,7 +836,7 @@
 			return false;
 		}
 
-		$history = get_option(BASE.'icon_css_history_' . $this->source, []);
+		$history = get_option($this->iconHistoryKey, []);
 		$merged_icons = [];
 
 		// Collect icons from selected versions

--
Gitblit v1.10.0