From 275c0d74cd68677622a5431505c5c870c473063d Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 29 Mar 2026 21:40:15 +0000
Subject: [PATCH] =Seems to be working, huzzah! Added some changes for on-this-page nav

---
 inc/rest/Rest.php |  192 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 192 insertions(+), 0 deletions(-)

diff --git a/inc/rest/Rest.php b/inc/rest/Rest.php
index 406a3ab..3357ca4 100644
--- a/inc/rest/Rest.php
+++ b/inc/rest/Rest.php
@@ -2,6 +2,7 @@
 namespace JVBase\rest;
 
 use JVBase\managers\Cache;
+use JVBase\meta\Meta;
 use JVBase\registrar\Registrar;
 use JVBase\utility\Features;
 use WP_REST_Request;
@@ -89,6 +90,21 @@
 	// CACHE MANAGEMENT
 	// =========================================================================
 
+	protected function checkCache(string $key, $request):WP_REST_Response|false
+	{
+		// Check HTTP cache headers with the specific content type
+		$cache_check = $this->checkHeaders($request, $key);
+		if ($cache_check) {
+			return $cache_check;
+		}
+
+		$cache = $this->cache->get($key);
+		if ($cache) {
+			$response = Response::success($cache);
+			return $this->addCacheHeaders($response);
+		}
+		return false;
+	}
 	/**
 	 * Check request headers for conditional caching (ETag, If-Modified-Since)
 	 */
@@ -517,6 +533,9 @@
 	***************************************************************************/
 	protected function isTimeline($args, $data):bool
 	{
+		if (!array_key_exists('post_type', $args)) {
+			return false;
+		}
 		$post_types = is_array($args['post_type']) ? $args['post_type'] : [$args['post_type']];
 		$hasTimeline = array_map(function($item) { return jvbCheckBase($item); },Registrar::getFeatured('is_timeline', 'post'));
 		return !empty(array_intersect($post_types, $hasTimeline));
@@ -712,4 +731,177 @@
 		delete_user_meta($user_id, BASE . 'session_fingerprint');
 		delete_user_meta($user_id, BASE . 'session_timestamp');
 	}
+
+	/*******************************
+	 * META HELPERS
+	*******************************/
+	public function getFieldsOfType(array $fields, string|array $type, Meta $meta, array $subType = []):array
+	{
+		$gotFields = [];
+		if (is_string($type)) {
+			$type = [$type];
+		}
+		foreach ($fields as $field => $value) {
+			//Skip empty values
+			if (empty($value)) {
+				continue;
+			}
+			$config = $meta->config($field);
+			if (in_array($config['type'], ['group', 'repeater', 'tagList'])) {
+				foreach ($config['fields'] as $subfield => $subConfig) {
+					if (is_numeric($subfield) && array_key_exists('name', $subConfig)) {
+						$subfield = $subConfig['name'];
+					}
+					if (is_numeric($subfield)) continue;
+					if (array_key_exists('type', $subConfig) && in_array($subConfig['type'], $type)) {
+						$gotFields[] = $field.':'.$subfield;
+					}
+				}
+			} elseif (in_array($config['type'], $type)) {
+				$gotFields[] = $field;
+			} else if ((!empty($subType) && in_array($config['type'], array_keys($subType)) && in_array($config['subtype'], array_values($subType)))) {
+				$gotFields[] = $field;
+			}
+		}
+		return $gotFields;
+	}
+
+
+	protected function extractImages(array $fields, Meta $meta):array
+	{
+		$images = [];
+		$get = $this->getFieldsOfType($fields, ['upload', 'gallery','image'], $meta);
+		if (!empty($get)) {
+			$baseFields = array_map(function($fieldName) {
+				return (str_contains($fieldName, ':')) ? strtok($fieldName, ':') : $fieldName;
+			}, $get);
+
+			$temp = array_map(
+				function($item) {
+					return explode(':', $item);
+				},
+				array_filter($get, function($fieldName) {
+					return str_contains($fieldName, ':');
+				})
+			);
+			$complex = [];
+			foreach ($temp as $tmp) {
+				$complex[$tmp[0]] = $tmp[1];
+			}
+
+			$fields = array_filter($fields, function ($field) use ($baseFields) {
+				return in_array($field, $baseFields);
+			}, ARRAY_FILTER_USE_KEY);
+
+			foreach ($fields as $fieldName => $value) {
+				//Check if it's a complex field
+				if (array_key_exists($fieldName, $complex)) {
+					$check = $complex[$fieldName];
+					foreach ($value as $row) {
+						foreach ($row as $fName => $fValue) {
+							if ($fName === $check && !empty($fValue)) {
+								$images = $this->addImages($fValue, $images);
+							}
+						}
+					}
+				} else {
+					$images = $this->addImages($value, $images);
+				}
+			}
+		}
+		return $images;
+	}
+	public function addImages(string $imgs, array $images):array
+	{
+		$temp = explode(',', $imgs);
+		foreach ($temp as $img) {
+			if (is_numeric($img) && !array_key_exists($img, $images) && $img > 0) {
+				$images[$img] = jvbImageData((int)$img);
+			}
+		}
+		return $images;
+	}
+
+	protected function extractTerms(array $fields, Meta $meta):array
+	{
+		$terms = [];
+		$get = $this->getFieldsOfType($fields, ['taxonomy'], $meta, ['selector' => 'taxonomy']);
+		if (!empty($get)) {
+			$baseFields = array_map(function($fieldName) {
+				return (str_contains($fieldName, ':')) ? strtok($fieldName, ':') : $fieldName;
+			}, $get);
+
+			$complex = array_map(
+				function($item) {
+					return explode(':', $item);
+				},
+				array_filter($get, function($fieldName) {
+					return str_contains($fieldName, ':');
+				})
+			);
+
+			$fields = array_filter($fields, function ($field) use ($baseFields) {
+				return in_array($field, $baseFields);
+			}, ARRAY_FILTER_USE_KEY);
+
+			foreach ($fields as $fieldName => $value) {
+				$config = $meta->config($fieldName);
+				//Check if it's a complex field
+				if (array_key_exists($fieldName, $complex)) {
+					foreach ($value as $row) {
+						foreach ($row as $fName => $fValue) {
+							if (in_array($fName, $complex[$fieldName])) {
+								$terms = $this->addTerms($fValue, $terms, $config);
+							}
+						}
+					}
+				} else {
+
+					$terms = $this->addTerms($value, $terms, $config);
+				}
+			}
+		}
+		return $terms;
+
+	}
+
+	protected function addTerms(string $value, array $terms, array $config):array
+	{
+		$taxonomy = jvbNoBase($config['taxonomy']);
+		if (empty($value)) {
+			return $terms;
+		}
+		$ids = array_map('absint', explode(',',$value));
+		$cache = Cache::for('term_data')->connect('taxonomy');
+		$cache->flush();
+		if (!array_key_exists($taxonomy, $terms)) {
+			$terms[$taxonomy] = [];
+			$registrar = Registrar::getInstance($taxonomy);
+			$terms[$taxonomy]['icon'] = $registrar ? $registrar->getIcon() : jvbDefaultIcon();;
+		}
+		foreach ($ids as $id) {
+			$data = $cache->remember(
+				$id,
+				function () use ($id, $taxonomy) {
+					$term = get_term($id, $taxonomy);
+					if ($term && !is_wp_error($term)) {
+						return [
+							'id'	=> $term->term_id,
+							'name'	=> $term->name,
+							'slug'	=> $term->slug,
+							'parent'	=> $term->parent,
+							'path'	=> JVB()->routes('term')->getTermPath($term->term_id, $term->name, $taxonomy),
+							'taxonomy'	=> jvbNoBase($term->taxonomy),
+							'count'	=> $term->count,
+						];
+					}
+					return [];
+				}
+			);
+			if (!empty($data)) {
+				$terms[$taxonomy][$id] = $data;
+			}
+		}
+		return $terms;
+	}
 }

--
Gitblit v1.10.0