From c16a4d78d07e81ecdd2ff9b1b9090560ab2fe488 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 04 Sep 2026 22:25:09 +0000
Subject: [PATCH] =Got the panel loading up the fields, organized by section! Now to ensure it saves properly. Still need to add: upload fields, selector fields, repeater/taglist/group fields

---
 inc/managers/Cache.php |  666 +++++++++++++++++++++----------------------------------
 1 files changed, 255 insertions(+), 411 deletions(-)

diff --git a/inc/managers/Cache.php b/inc/managers/Cache.php
index e7ebc94..d110f4a 100644
--- a/inc/managers/Cache.php
+++ b/inc/managers/Cache.php
@@ -9,21 +9,78 @@
 {
 	private string $group;
 	private int $ttl;
-	private static array $timestamps = [];
-	private const TS_GROUP = 'jvb_http_ts';
-
-	private const CONNECTIONS_OPTION = 'jvb_cache_connections';
-	private static ?array $connections = null;
-	protected array $tags = [];
 
 	private static array $instances = [];
 	private bool $hasRedis;
+	private bool $varyByAuth = false;
+	private bool $varyByUser = false;
 
-	private function __construct(string $group, int $ttl)
+	private array $index=[];
+	private ?string $target = null;
+
+	private function __construct(string $group, ?string $target = null, int $ttl = WEEK_IN_SECONDS)
 	{
+		if (!is_null($target) && empty($this->index)) {
+			$this->target = null;
+			$this->index = get_option(BASE."cache_{$target}_index",[]);
+		}
 		$this->group = $group;
 		$this->ttl   = $ttl;
-		$this->hasRedis = (bool) wp_using_ext_object_cache();
+		$this->logGroup();
+		$this->hasRedis = (bool)wp_using_ext_object_cache();
+	}
+
+	protected function logGroup():void
+	{
+		$changed = false;
+		$groups = get_option(BASE."cache_groups", []);
+		if (!array_key_exists($this->group, $groups)) {
+			$groups[$this->group] = [
+				'auth'	=> $this->varyByAuth,
+				'user'	=> $this->varyByUser,
+				'target'=> $this->target,
+				'ttl'	=> $this->ttl,
+			];
+			$changed = true;
+		}
+
+		if ($groups[$this->group]['auth'] && !$this->varyByAuth) {
+			error_log('[Cache]Group '.$this->group.' previously defined as varying by auth, but is not set. Setting it now.');
+			$this->auth();
+		}
+		if ($groups[$this->group]['user'] && !$this->varyByUser) {
+			error_log('[Cache]Group '.$this->group.' previously defined as varying by user, but is not set. Setting it now.');
+			$this->user();
+		}
+		if (is_null($this->target) && !is_null($groups[$this->group]['target'])) {
+			error_log('[Cache]Group '.$this->group. ' previously defined with target '.$groups[$this->group]['target'].'... Setting it now.');
+			$this->target = $groups[$this->group]['target'];
+		} elseif ($this->target !== $groups[$this->group]['target']) {
+			error_log('[Cache]WARNING Group previously defined with target '.$groups[$this->group]['target'].' - but is currently defined with '.$this->target. '. You may want to look into this.');
+		}
+
+		if ($this->ttl !== $groups[$this->group]['ttl']) {
+			error_log('[Cache]Group '. $this->group. ' previously defined with ttl '.$groups[$this->group]['ttl']. ' - but is currently defined with '. $this->ttl);
+			$groups[$this->group]['ttl'] = $this->ttl;
+			$changed = true;
+		}
+
+		if ($this->varyByAuth && !$groups[$this->group]['auth']) {
+			$groups[$this->group]['auth'] = true;
+			$changed = true;
+		}
+		if ($this->varyByUser && !$groups[$this->group]['user']) {
+			$groups[$this->group]['user'] = true;
+			$changed = true;
+		}
+		if ($this->target !== $groups[$this->group]['target']) {
+			$groups[$this->group]['target'] = $this->target;
+			$changed = true;
+		}
+
+		if ($changed) {
+			update_option(BASE."cache_groups", $groups, false);
+		}
 	}
 
 	public static function registerHooks(): void
@@ -32,10 +89,10 @@
 		add_action('save_post', [self::class, 'onPostChange'], 10, 2);
 		add_action('delete_post', [self::class, 'onPostDelete']);
 
-		// Post meta updates
-		add_action('updated_post_meta', [self::class, 'onPostMetaChange'], 10, 2);
-		add_action('added_post_meta', [self::class, 'onPostMetaChange'], 10, 2);
-		add_action('deleted_post_meta', [self::class, 'onPostMetaDelete'], 10, 2);
+		// Post meta updates, now handled via Meta.php?
+//		add_action('updated_post_meta', [self::class, 'onPostMetaChange'], 10, 2);
+//		add_action('added_post_meta', [self::class, 'onPostMetaChange'], 10, 2);
+//		add_action('deleted_post_meta', [self::class, 'onPostMetaDelete'], 10, 2);
 
 		// Term updates (all taxonomies)
 		add_action('edited_term', [self::class, 'onTermChange'], 10, 3);
@@ -43,9 +100,9 @@
 		add_action('delete_term', [self::class, 'onTermDelete'], 10, 3);
 
 		// Term meta updates
-		add_action('updated_term_meta', [self::class, 'onTermMetaChange'], 10, 2);
-		add_action('added_term_meta', [self::class, 'onTermMetaChange'], 10, 2);
-		add_action('deleted_term_meta', [self::class, 'onTermMetaDelete'], 10, 2);
+//		add_action('updated_term_meta', [self::class, 'onTermMetaChange'], 10, 2);
+//		add_action('added_term_meta', [self::class, 'onTermMetaChange'], 10, 2);
+//		add_action('deleted_term_meta', [self::class, 'onTermMetaDelete'], 10, 2);
 
 		// User updates
 		add_action('profile_update', [self::class, 'onUserChange'], 10, 2);
@@ -53,43 +110,76 @@
 		add_action('deleted_user', [self::class, 'onUserDelete']);
 
 		// User meta updates
-		add_action('updated_user_meta', [self::class, 'onUserMetaChange'], 10, 2);
-		add_action('added_user_meta', [self::class, 'onUserMetaChange'], 10, 2);
-		add_action('deleted_user_meta', [self::class, 'onUserMetaDelete'], 10, 2);
+//		add_action('updated_user_meta', [self::class, 'onUserMetaChange'], 10, 2);
+//		add_action('added_user_meta', [self::class, 'onUserMetaChange'], 10, 2);
+//		add_action('deleted_user_meta', [self::class, 'onUserMetaDelete'], 10, 2);
 	}
 
-	/* ---------------------------------------------------------------------
-	 * Factory
-	 * ------------------------------------------------------------------- */
+	public function auth(): static
+	{
+		$this->varyByAuth = true;
+		return $this;
+	}
 
-	public static function for(string $group, int $ttl = HOUR_IN_SECONDS): self
+	public function user(): static
+	{
+		$this->varyByUser = true;
+		return $this;
+	}
+
+	private function resolveKey(int|string $key): string
+	{
+		if ($this->varyByUser) {
+			return $key . ':u' . get_current_user_id();
+		}
+		if ($this->varyByAuth) {
+			return $key . ':' . (is_user_logged_in() ? 'auth' : 'guest');
+		}
+		return (string) $key;
+	}
+
+	public static function for(string $group, ?string $target = null, int $ttl = HOUR_IN_SECONDS): self
 	{
 		$group = sanitize_key($group);
 
 		if (!isset(self::$instances[$group])) {
-			self::$instances[$group] = new self($group, $ttl);
+			self::$instances[$group] = new self($group, $target, $ttl);
 		}
 
 		return self::$instances[$group];
 	}
 
+	/**
+	 * To help facilitate cache flushing on object updates, we track the keys that are used for a particular id
+	 * Generally, $this->target will either be 'post', 'user', 'term', or 'custom'
+	 * @param int $ID
+	 * @param string $key
+	 * @return void
+	 */
+	protected function trackID(int $ID, string $key):void
+	{
+		if (is_null($this->target)) {
+			return;
+		}
+		if (!array_key_exists($ID, $this->index[$this->target])) {
+			$this->index[$ID] = [];
+		}
+		if (!array_key_exists($this->group, $this->index[$ID])) {
+			$this->index[$ID][$this->group] = [];
+		}
+		if (!in_array($key, $this->index[$ID][$this->group])) {
+			$this->index[$this->target][$ID][$this->group][] = $key;
+			update_option(BASE."cache_{$this->target}_index", $this->index, false);
+		}
+	}
+
 	/* ---------------------------------------------------------------------
 	 * Core operations
 	 * ------------------------------------------------------------------- */
 
 	public function remember(int|string|array $key, callable $callback, ?int $ttl = null): mixed
 	{
-		if (is_array($key)) {
-			$key = $this->generateKey($key);
-		}
-		if (!empty($this->tags)) {
-			return $this->rememberTagged(
-				$key,
-				$this->tags,
-				$callback,
-				$ttl
-			);
-		}
+		$key = $this->generateKey($key);
 
 		$value = $this->get($key);
 
@@ -100,49 +190,60 @@
 		$value = $callback();
 
 		if ($value !== null && $value !== false) {
-			$this->set($key, $value);
+			$this->set($key, $value, $ttl);
 		}
 
 		return $value;
 	}
-
-	public function get(int|string|array $id): mixed
+	protected function transientKey(string $key):string
 	{
-		if (is_array($id)) {
-			$id = $this->generateKey($id);
-		}
-		if ($this->hasRedis) {
-			$value = wp_cache_get($id, $this->group);
-		} else {
-			$value = get_transient("jvb_{$this->group}_{$id}");
-		}
-
-		return $value;
+		return BASE."{$this->group}_{$key}";
 	}
 
-	public function set(int|string|array $id, mixed $value, ?int $ttl = null): void
+	public function get(int|string|array $key): mixed
 	{
-		if (is_array($id)) {
-			$id = $this->generateKey($id);
-		}
-		$ttl = $ttl ?? $this->ttl;
+		$key = $this->generateKey($key, false);
+
+		$value = $this->hasRedis ?
+			wp_cache_get($key, $this->group) :
+			get_transient($this->transientKey($key));
+
+		return $value['value']??false;
+	}
+	public function getTimestamp(int|string|array $key): mixed
+	{
+		$key = $this->generateKey($key, false);
+
+		$value = $this->hasRedis ?
+			wp_cache_get($key, $this->group) :
+			get_transient($this->transientKey($key));
+		return $value['modified']??false;
+	}
+
+	public function set(int|string|array $key, mixed $value, ?int $ttl = null): void
+	{
+		$key = $this->generateKey($key);
+		$ttl = $ttl??$this->ttl;
+		$store = [
+			'value'	=> $value,
+			'modified'	=> time()
+		];
 		if ($this->hasRedis) {
-			wp_cache_set($id, $value, $this->group, $ttl);
+			wp_cache_set($key, $store, $this->group, $ttl);
 		} else {
-			set_transient("jvb_{$this->group}_{$id}", $value, $ttl);
+			set_transient($this->transientKey($key), $store, $ttl);
 		}
 	}
 
-	public function forget(int|string|array $id): void
+	public function forget(int|string|array $key): void
 	{
-		if (is_array($id)) {
-			$id = $this->generateKey($id);
-		}
+		$key = $this->generateKey($key);
 		if ($this->hasRedis) {
-			wp_cache_delete($id, $this->group);
+			wp_cache_delete($key, $this->group);
 		} else {
-			delete_transient("jvb_{$this->group}_{$id}");
+			delete_transient($this->transientKey($key));
 		}
+
 	}
 
 	public function flush(): void
@@ -158,265 +259,53 @@
 		}
 	}
 
-	/* ---------------------------------------------------------------------
-	 * Invalidation
-	 * ------------------------------------------------------------------- */
-
-	public static function invalidateItem(string $group, int|string|array $id): void
+	public static function clearPost(int $ID):void
 	{
-		if (is_array($id)) {
-			$id = self::for($group)->generateKey($id);
+		$index = get_option(BASE."cache_post_index", []);
+		if (!array_key_exists($ID, $index)) {
+			return;
 		}
-		$group = sanitize_key($group);
-
-		if (wp_using_ext_object_cache()) {
-			wp_cache_delete($id, $group);
-		} else {
-			delete_transient("jvb_{$group}_{$id}");
-		}
-		self::touch($group);
-
-		foreach (self::connections()[$group] ?? [] as $conn) {
-			$target = $conn['target'] ?? $conn; // Backwards compat if still string
-			$flush = $conn['flush'] ?? false;
-
-			if ($flush) {
-				// Flush entire target group
-				self::invalidateGroup($target);
-			} else {
-				// Just delete this item ID
-				if (wp_using_ext_object_cache()) {
-					wp_cache_delete($id, $target);
-				} else {
-					delete_transient("jvb_{$target}_{$id}");
-				}
-				self::touch($target);
+		foreach ($index[$ID] as $group => $keys) {
+			$cache = self::for($group, 'post');
+			foreach ($keys as $key) {
+				$cache->forget($key);
 			}
 		}
-		self::invalidateByTag($group, $id);
 	}
+	public static function clearUser(int $ID):void
+	{
+		$index = get_option(BASE."cache_user_index", []);
+		if (!array_key_exists($ID, $index)) {
+			return;
+		}
+		foreach ($index[$ID] as $group => $keys) {
+			$cache = self::for($group, 'user');
+			foreach ($keys as $key) {
+				$cache->forget($key);
+			}
+		}
+	}
+	public static function clearTerm(int $ID):void
+	{
+		$index = get_option(BASE."cache_term_index", []);
+		if (!array_key_exists($ID, $index)) {
+			return;
+		}
+		foreach ($index[$ID] as $group => $keys) {
+			$cache = self::for($group, 'term');
+			foreach ($keys as $key) {
+				$cache->forget($key);
+			}
+		}
+	}
+
 
 	public static function invalidateGroup(string $group): void
 	{
-		$group = sanitize_key($group);
-
-		if (wp_using_ext_object_cache()) {
-			wp_cache_flush_group($group);
-		} else {
-			$instance = self::for($group);
-			$instance->clearGroupTransients();
-		}
-
-		self::touch($group);
-
-		foreach (self::connections()[$group] ?? [] as $conn) {
-			$target = $conn['target'] ?? $conn; // Backwards compat
-
-			// When flushing entire source group, always flush connected targets
-			// (regardless of flush flag - we don't know which items to delete)
-			if (wp_using_ext_object_cache()) {
-				wp_cache_flush_group($target);
-			} else {
-				$instance = self::for($target);
-				$instance->clearGroupTransients();
-			}
-			self::touch($target);
-		}
-	}
-
-	public static function touch(string $group): int
-	{
-		$group = sanitize_key($group);
-		$time  = time();
-
-		if (wp_using_ext_object_cache()) {
-			wp_cache_set($group, $time, self::TS_GROUP, WEEK_IN_SECONDS);
-		} else {
-			set_transient('jvb_ts_' . $group, $time, WEEK_IN_SECONDS);
-		}
-
-		self::$timestamps[$group] = $time;
-		return $time;
-	}
-
-	public static function lastModified(string|array $groups): int
-	{
-		if (is_array($groups)) {
-			return max(array_map([self::class, 'lastModified'], $groups));
-		}
-
-		$group = sanitize_key($groups);
-
-		if (isset(self::$timestamps[$group])) {
-			return self::$timestamps[$group];
-		}
-
-		if (wp_using_ext_object_cache()) {
-			$ts = (int) wp_cache_get($group, self::TS_GROUP);
-		} else {
-			$ts = (int) get_transient('jvb_ts_' . $group);
-		}
-
-		if (!$ts) {
-			$ts = time();
-			if (wp_using_ext_object_cache()) {
-				wp_cache_set($group, $ts, self::TS_GROUP, WEEK_IN_SECONDS);
-			} else {
-				set_transient('jvb_ts_' . $group, $ts, WEEK_IN_SECONDS);
-			}
-		}
-
-		return self::$timestamps[$group] = $ts;
-	}
-
-	public function getLastModifiedForTags(array $tags): ?int
-	{
-		if (!$this->hasRedis) {
-			return null;
-		}
-		$redis = self::redis();
-		if (!$redis) {
-			return null;
-		}
-
-		$lastModified = 0;
-
-		foreach ($tags as $tag) {
-			$ts = $redis->get("jvb:tag:{$tag}:lastModified");
-			if ($ts) {
-				$lastModified = max($lastModified, (int) $ts);
-			}
-		}
-
-		return $lastModified ?: null;
-	}
-
-	/****************************************************
-	 * CONNECTIONS
-	 ****************************************************/
-	private static function connections(): array
-	{
-		if (self::$connections === null) {
-			self::$connections = get_option(self::CONNECTIONS_OPTION, []);
-		}
-		return self::$connections;
+		self::for($group)->flush();
 	}
 
 
-	public function connect(string $source, bool $flush = false): self
-	{
-		$source = sanitize_key($source);
-		$target = $this->group;
-
-		$all = self::connections();
-		$all[$source] ??= [];
-
-		$before = count($all[$source]);
-
-		// Add the connection
-		$all[$source][] = ['target' => $target, 'flush' => $flush];
-
-		// Remove duplicates by serializing for comparison
-		$all[$source] = array_values(array_unique($all[$source], SORT_REGULAR));
-
-		// Only update if something actually changed
-		if (count($all[$source]) !== $before) {
-			update_option(self::CONNECTIONS_OPTION, $all, false);
-			self::$connections = $all;
-		}
-
-		return $this;
-	}
-	/****************************************************
-	 * REDIS
-	 ****************************************************/
-	private static function redis(): ?\Redis
-	{
-		global $wp_object_cache;
-
-		return $wp_object_cache instanceof \WP_Object_Cache
-		&& isset($wp_object_cache->redis)
-			? $wp_object_cache->redis
-			: null;
-	}
-
-	/**
-	 * Remember with tags for complex invalidation scenarios
-	 *
-	 * Example: Cache user favorites tagged by each post ID
-	 * When any post updates, this cache entry auto-invalidates
-	 *
-	 * @param int|string|array $key Cache key
-	 * @param array $tags Array of [group, id] pairs: [['post', 123], ['user', 456]]
-	 * @param callable $callback Function to generate value if cache miss
-	 * @return mixed Cached or generated value
-	 */
-	public function rememberTagged(
-		int|string|array $key,
-		array $tags,
-		callable $callback,
-		?int $ttl = null
-	): mixed {
-		if (is_array($key)) {
-			$id = $this->generateKey($key);
-		}
-		$tags = array_unique(array_merge(
-			$this->getTags(),
-			array_map('sanitize_key', $tags)
-		));
-
-
-		$value = wp_cache_get($key, $this->group);
-		if ($value !== false) {
-			return $value;
-		}
-
-		$value = $callback();
-		if ($value === null || $value === false) {
-			return $value;
-		}
-
-		wp_cache_set($key, $value, $this->group, $this->ttl);
-
-		if ($redis = self::redis()) {
-			foreach ($tags as [$tagGroup, $tagId]) {
-				$redis->sAdd("tag:$tagGroup:$tagId", "{$this->group}:$key");
-			}
-		}
-
-		return $value;
-	}
-
-	private static function invalidateByTag(string $group, int|string|array $id): void
-	{
-		if (is_array($id)) {
-			$id = self::for($group)->generateKey($id);
-		}
-		if (!$redis = self::redis()) {
-			return;
-		}
-
-		$key = "tag:$group:$id";
-		$targets = $redis->sMembers($key);
-
-		foreach ($targets as $target) {
-			[$group, $id] = explode(':', $target, 2);
-			wp_cache_delete($id, $group);
-		}
-
-		$redis->del($key);
-	}
-
-	public function tag(string $tag): static
-	{
-		$this->tags[] = sanitize_key($tag);
-		return $this;
-	}
-
-	public function getTags(): array
-	{
-		return array_unique($this->tags);
-	}
 	/****************************************************
 	 * TRANSIENT HELPER
 	 ****************************************************/
@@ -424,8 +313,8 @@
 	{
 		global $wpdb;
 
-		$pattern = '_transient_jvb_' . $this->group . '_%';
-		$timeout_pattern = '_transient_timeout_jvb_' . $this->group . '_%';
+		$pattern = '_transient_' .BASE. $this->group . '%';
+		$timeout_pattern = '_transient_timeout_' . BASE . $this->group . '%';
 
 		// Remove LIMIT to avoid table locks, add retry for deadlocks
 		$attempts = 0;
@@ -465,52 +354,52 @@
 		}
 
 //		error_log('[Clearing cache for post change: '.$postId.']');
-		self::invalidateItem('post', $postId);
+		self::clearPost($postId);
 	}
 
 	public static function onPostDelete(int $postId): void
 	{
 //		error_log('[Clearing cache for post delete: '.$postId.']');
-		self::invalidateItem('post', $postId);
+		self::clearPost($postId);
 	}
 
-	public static function onPostMetaChange(int $metaId, int $objectId): void
-	{
-//		error_log('[Clearing cache for post meta change: '.$objectId.']');
-		self::invalidateItem('post', $objectId);
-	}
-
-	public static function onPostMetaDelete(array $metaIds, int $objectId): void
-	{
-//		error_log('[Clearing cache for post meta delete: '.$objectId.']');
-		self::invalidateItem('post', $objectId);
-	}
+//	public static function onPostMetaChange(int $metaId, int $objectId): void
+//	{
+////		error_log('[Clearing cache for post meta change: '.$objectId.']');
+//		self::invalidateItem('post', $objectId);
+//	}
+//
+//	public static function onPostMetaDelete(array $metaIds, int $objectId): void
+//	{
+////		error_log('[Clearing cache for post meta delete: '.$objectId.']');
+//		self::invalidateItem('post', $objectId);
+//	}
 
 	/****************************************************
 	 * HOOKS - Terms
 	 ****************************************************/
 	public static function onTermChange(int $termId, int $ttId, string $taxonomy): void
 	{
-//		error_log('[Clearing cache for term change: '.$termId.']');
-		self::invalidateItem('taxonomy', $termId);
+		error_log('[Clearing cache for term change: '.$termId.']');
+		self::clearTerm($termId);
 	}
 
 	public static function onTermDelete(int $termId): void
 	{
 //		error_log('[Clearing cache for term delete: '.$termId.']');
-		self::invalidateItem('taxonomy', $termId);
+		self::clearTerm($termId);
 	}
 
 	public static function onTermMetaChange(int $metaId, int $objectId): void
 	{
 //		error_log('[Clearing cache for term meta change: '.$objectId.']');
-		self::invalidateItem('taxonomy', $objectId);
+		self::clearTerm($objectId);
 	}
 
 	public static function onTermMetaDelete(array $metaIds, int $objectId): void
 	{
 //		error_log('[Clearing cache for term meta delete: '.$objectId.']');
-		self::invalidateItem('taxonomy', $objectId);
+		self::clearTerm($objectId);
 	}
 
 	/****************************************************
@@ -519,25 +408,25 @@
 	public static function onUserChange(int $userId): void
 	{
 //		error_log('[Clearing cache for user change: '.$userId.']');
-		self::invalidateItem('user', $userId);
+		self::clearUser($userId);
 	}
 
 	public static function onUserDelete(int $userId): void
 	{
 //		error_log('[Clearing cache for user delete: '.$userId.']');
-		self::invalidateItem('user', $userId);
+		self::clearUser($userId);
 	}
 
 	public static function onUserMetaChange(int $metaId, int $objectId): void
 	{
 //		error_log('[Clearing cache for user meta change: '.$objectId.']');
-		self::invalidateItem('user', $objectId);
+		self::clearUser($objectId);
 	}
 
 	public static function onUserMetaDelete(array $metaIds, int $objectId): void
 	{
 //		error_log('[Clearing cache for user meta delete: '.$objectId.']');
-		self::invalidateItem('user', $objectId);
+		self::clearUser($objectId);
 	}
 	/***************************************************
 	 * UTILITY
@@ -546,13 +435,33 @@
 	 * Generate a cache key from parameters
 	 * Useful for caching based on multiple variables
 	 *
-	 * @param array $params Key-value pairs that uniquely identify this cache entry
+	 * @param int|string|array $key Key-value pairs that uniquely identify this cache entry
 	 * @return string MD5 hash of sorted parameters
 	 */
-	public function generateKey(array $params): string
+	public function generateKey(int|string|array $key, bool $trackIt = true): string
 	{
-		ksort($params);
-		return md5(serialize($params));
+		$trackID = false;
+		$ID = false;
+
+		if (!is_null($this->target) && is_int($key)) {
+			//Likely an item id. Store it for reference
+			$trackID = true;
+			$ID = $key;
+		}
+		if (is_array($key)) {
+			ksort($key);
+			if (!is_null($this->target) && array_key_exists('id', $key)) {
+				$trackID = true;
+				$ID = $key['id'];
+			}
+			$key = md5(serialize($key));
+		}
+
+		$key = $this->resolveKey($key);
+		if ($trackIt && !is_null($this->target) && $ID && $trackID) {
+			$this->trackID($ID, $key);
+		}
+		return $key;
 	}
 
 	/**
@@ -563,90 +472,25 @@
 	 */
 	public static function flushAll(): int
 	{
-		$all = self::connections();
-		$groups = [];
-
-		// Collect all unique groups from connections
-		foreach ($all as $source => $targets) {
-			$groups[$source] = true;
-			foreach ($targets as $conn) {
-				$target = $conn['target'] ?? $conn;
-				$groups[$target] = true;
-			}
-		}
-
-		// Add any instantiated groups not in connections
-		foreach (array_keys(self::$instances) as $group) {
-			$groups[$group] = true;
-		}
-
-		// Flush each group
+		$groups = get_option(BASE."cache_groups", []);
 		$count = 0;
-		foreach (array_keys($groups) as $group) {
-			self::invalidateGroup($group);
-			$count++;
+		foreach ($groups as $group => $conf) {
+			$cache = Cache::for($group, $conf['target']??null, $conf['ttl']);
+			$cache->flush();
+			$count ++ ;
+
+			usleep(50000); // Wait 50ms before retry
 		}
-
-		// Also flush timestamp cache
-		if (wp_using_ext_object_cache()) {
-			wp_cache_flush_group(self::TS_GROUP);
-		}
-
-		// Clear in-memory caches
-		self::$timestamps = [];
-
 		return $count;
 	}
 
 	/**
-	 * Get all cache groups and their connections for admin display
+	 * Get all cache groups
 	 *
-	 * @return array Format: ['group' => ['connects_to' => [...], 'connected_from' => [...]]]
+	 * @return array
 	 */
 	public static function getAllGroups(): array
 	{
-		$connections = self::connections();
-		$groups = [];
-
-		// Build bidirectional view
-		foreach ($connections as $source => $targets) {
-			if (!isset($groups[$source])) {
-				$groups[$source] = ['connects_to' => [], 'connected_from' => []];
-			}
-
-			foreach ($targets as $conn) {
-				$target = $conn['target'] ?? $conn;
-				$flush = $conn['flush'] ?? false;
-
-				// Source connects to target
-				$groups[$source]['connects_to'][] = [
-					'group' => $target,
-					'flush' => $flush
-				];
-
-				// Target is connected from source
-				if (!isset($groups[$target])) {
-					$groups[$target] = ['connects_to' => [], 'connected_from' => []];
-				}
-				$groups[$target]['connected_from'][] = [
-					'group' => $source,
-					'flush' => $flush
-				];
-			}
-		}
-
-		// Add any instantiated groups not in connections
-		foreach (array_keys(self::$instances) as $group) {
-			if (!isset($groups[$group])) {
-				$groups[$group] = ['connects_to' => [], 'connected_from' => []];
-			}
-		}
-
-		return $groups;
-	}
-
-	public function hasRedis():bool
-	{
-		return $this->hasRedis;
+		return get_option(BASE."cache_groups", []);
 	}
 }

--
Gitblit v1.10.0