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