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

---
 base/seo.php |  320 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 282 insertions(+), 38 deletions(-)

diff --git a/base/seo.php b/base/seo.php
index bd248f9..79c66d8 100644
--- a/base/seo.php
+++ b/base/seo.php
@@ -1,4 +1,286 @@
 <?php
+namespace JVBase\base;
+use JVBase\meta\Meta;
+use JVBase\registrar\config\seo\Resolver;
+use JVBase\registrar\Registrar;
+
+class SchemaHelper
+{
+	protected static array $allowedTypes;
+	protected static array $allowedFormats = ['schema', 'archive', 'meta', 'reference'];
+	protected static array $schemas = [];
+	protected static array $metas = [];
+	protected static array $archives = [];
+	protected static array $references = [];
+	public function __construct()
+	{
+		self::$allowedTypes = array_merge(['website', 'organization'], Registrar::getRegistered());
+	}
+	public static function checkType(string $type, string $reference = '[SchemaHelper] Invalid type'):string|false
+	{
+		$type = strtolower($type);
+		if (!in_array($type, self::$allowedTypes)) {
+			error_log($reference.': '.$type);
+			return false;
+		}
+		return $type;
+	}
+	public static function checkFormat(string $format, string $reference = '[SchemaHelper] Invalid format'):string|false
+	{
+		$format = strtolower($format);
+		if (!in_array($format, self::$allowedFormats)) {
+			error_log($reference.': '.$format);
+			return false;
+		}
+		return $format;
+	}
+	public static function getConfig(string $type, string $format):array
+	{
+		$reference = '[SchemaHelper]::getConfig';
+		$type = self::checkType($type, $reference);
+		$format = self::checkFormat($format, $reference);
+		if (!$type || !$format) {
+			return [];
+		}
+		return match($format) {
+			'schema' => self::schema($type),
+			'archive' => self::archive($type),
+			'meta' => self::meta($type),
+			'reference' => self::reference($type),
+		};
+	}
+	public static function schema(string $type): array
+	{
+		$type = self::checkType($type, '[SchemaHelper]::schema');
+		if (!$type) {
+			return [];
+		}
+
+		if (!array_key_exists($type, self::$schemas)) {
+			self::$schemas[$type] = get_option(BASE.ucfirst($type).'Schema', self::getDefault($type, 'schema'));
+		}
+		return self::$schemas[$type];
+	}
+	public static function meta(string $type): array
+	{
+		$type = self::checkType($type, '[SchemaHelper]::meta');
+		if (!$type) {
+			return [];
+		}
+		if (!array_key_exists($type, self::$metas)) {
+			self::$metas[$type] = get_option(BASE.ucfirst($type).'Meta', self::getDefault($type, 'meta'));
+		}
+		return self::$metas[$type];
+	}
+	public static function archive(string $type): array
+	{
+		$type = self::checkType($type, '[SchemaHelper]::archive');
+		error_log('[SchemaHelper]::archive type: '.print_r($type, true));
+		if (!$type) {
+			return [];
+		}
+
+		if (!array_key_exists($type, self::$archives)) {
+			self::$archives[$type] = get_option(BASE.ucfirst($type).'Archive', self::getDefault($type, 'archive'));
+		}
+		return self::$archives[$type];
+	}
+	public static function reference(string $type): array
+	{
+		$type = self::checkType($type, '[SchemaHelper]::reference');
+		if (!$type) {
+			return [];
+		}
+		if (!array_key_exists($type, self::$references)) {
+			self::$references[$type] = get_option(BASE.ucfirst($type).'Reference', self::getDefault($type, 'reference'));
+		}
+		return self::$references[$type];
+	}
+
+	public static function getDefault(string $type, string $format):array
+	{
+		$reference = '[SchemaHelper]::getDefault';
+		$type = self::checkType($type, $reference);
+		$format = self::checkFormat($format, $reference);
+		if (!$type || !$format) {
+			return [];
+		}
+
+		$defaults = match ($format) {
+			'schema' => match ($type) {
+				'website' => [
+					'type'	=> 'JVBase\managers\SEO\render\Thing\CreativeWork\WebSite',
+					'name' => get_bloginfo('name'),
+					'url' => get_home_url(),
+					'id' => get_home_url() . '#website',
+					'description' => get_bloginfo('description'),
+					'inLanguage' => 'en-CA'
+				],
+				default => []
+			},
+			'archive' => [
+				'type'	=> 'JVBase\managers\SEO\render\Thing\CreativeWork\WebPage\CollectionPage',
+			],
+			default => [],
+		};
+		return apply_filters(BASE.ucfirst($type).ucfirst($format).'Default', $defaults);
+	}
+
+	public static function updateHistory(string $type, string $format, array $newest):bool
+	{
+		$reference = '[SchemaHelper]::updateHistory';
+		$type = self::checkType($type, $reference);
+		$format = self::checkFormat($format, $reference);
+		if (!$type || !$format) {
+			return false;
+		}
+
+		$historyOption = BASE.ucfirst($type).ucfirst($format).'History';
+		$history = get_option($historyOption, []);
+		array_unshift($history, $newest);
+		if (count($history) > 5) {
+			array_pop($history);
+		}
+		return update_option($historyOption, $history);
+	}
+
+	public static function update(string $type, string $format, array $config, ?Meta $meta = null):bool
+	{
+		$reference = '[SchemaHelper]::update';
+		$type = self::checkType($type, $reference);
+		$format = self::checkFormat($format, $reference);
+		if (!$type || !$format) {
+			return false;
+		}
+		$method = 'update'.ucfirst($type);
+		return self::$method($config, $meta);
+	}
+	public static function updateSchema(string $type, array $config):bool
+	{
+		$reference = '[SchemaHelper]::updateSchema';
+		$type = self::checkType($type, $reference);
+		if (!$type) {
+			return false;
+		}
+		if (!class_exists($config['type'])){
+			error_log('[SchemaHelper]::updateSchema Config must be a valid schema type: '.$config['type']);
+			return false;
+		}
+		if (!in_array($type, self::$allowedTypes)) {
+			error_log('[SchemaHelper]::updateSchema Config must have a schema type');
+		}
+
+		return self::updateClassConfig($type, 'schema', $config);
+	}
+
+	public static function updateClassConfig(string $type, string $format, array $config):bool
+	{
+		$reference = '[SchemaHelper]::updateClassConfig';
+		$type = self::checkType($type, $reference);
+		if (!$type) {
+			return false;
+		}
+		if (!class_exists($config['type'])){
+			error_log($reference.' Config must be a valid schema type: '.$config['type']);
+			return false;
+		}
+		if (!in_array($type, self::$allowedTypes)) {
+			error_log($reference.' Config must have a schema type');
+		}
+		//Merge stored config with updates
+		$stored = self::schema($type);
+		$update = array_merge_recursive($stored, $config);
+
+		//Validate Properties
+		$className = $update['type'];
+		unset($update['type']);
+		foreach ($update as $property => $value) {
+			if (!property_exists($className, $property)) {
+				error_log($reference.' invalid property attempted: '.$property.', with value: '.print_r($value, true).' for class: '.$className);
+				unset($update[$property]);
+			}
+		}
+		$update['type'] = $className;
+
+		//Add changes to history (keeps last 5 changes)
+		self::updateHistory($type, $format, $update);
+		self::$schemas[$type] = $update;
+		return update_option(BASE.ucfirst($type).ucfirst($format), $update);
+	}
+
+	public static function updateMeta(string $type, array $config):bool
+	{
+		$type = self::checkType($type, '[SchemaHelper]::updateMeta');
+		$allowed = array_filter($config, function($key) {
+			$allowed = in_array($key, ['name', 'description']);
+			if (!$allowed) {
+				error_log('[SchemaHelper]::updateMeta invalid property attempted: '.$key);
+			}
+			return $allowed;
+		});
+		if (empty($allowed)) {
+			error_log('[SchemaHelper]::updateMeta Name or Description must be set');
+			return false;
+		}
+		$config = array_map('sanitize_text_field', $config);
+		self::updateHistory($type, 'meta', $config);
+		self::$metas[$type] = $config;
+		return update_option(BASE.ucfirst($type).'Meta', $config);
+	}
+
+	public static function updateArchive(string $type, array $config):bool
+	{
+		$reference = '[SchemaHelper]::updateArchive';
+		$type = self::checkType($type, $reference);
+		if (!$type) {
+			return false;
+		}
+		if (!class_exists($config['type'])){
+			error_log('[SchemaHelper]::updateSchema Config must be a valid schema type: '.$config['type']);
+			return false;
+		}
+		if (!in_array($type, self::$allowedTypes)) {
+			error_log('[SchemaHelper]::updateSchema Config must have a schema type');
+		}
+
+		return self::updateClassConfig($type, 'schema', $config);
+	}
+
+	public static function classFromConfig(array $config, ?Meta $meta = null):mixed
+	{
+		if (!array_key_exists('type', $config)) {
+			error_log('[SchemaHelper]::classFromConfig No class defined in config: '.print_r($config, true));
+			return false;
+		}
+		$className = $config['type'];
+		unset($config['type']);
+		$class = new $className();
+
+		foreach ($config as $property => $value) {
+			if (is_array($value)) {
+				$value = self::classFromConfig($value, $meta);
+			}
+			$method = 'set'.ucfirst($property);
+			if (!method_exists($class, $method)) {
+				error_log('[SchemaHelper]::classFromConfig - method: '.$method.' does not exist in class: '.$className);
+				continue;
+			}
+			if (is_string($value) && str_contains($value, '{{')) {
+				$value = Resolver::resolveForSchema($property, $value, $config, $meta);
+			}
+			if (!empty($value)) {
+				$class->$method($value);
+			}
+		}
+		return $class;
+	}
+}
+
+
+
+
+
+
 /**
  * JVB_SCHEMA: Site-wide schema configuration
  *
@@ -9,44 +291,6 @@
  *   - attribution: Developer/maintainer info
  */
 
-use JVBase\managers\SEO\SchemaBuilder;
-
-$schema = apply_filters('jvb_schema', []);
-$registry = SchemaBuilder::getInstance();
-$checked = [];
-foreach ($schema as $key => $config) {
-
-	if (array_key_exists('type', $config)) {
-		$type = $config['type'];
-	} elseif ($key === 'website') {
-		$type = 'WebSite';
-	}
-	$exists = !is_null($registry->getTypeDefinition($type));
-	if (!$exists) {
-//		error_log('[JVB_SCHEMA] No definitions for: '.print_r($type, true));
-		continue;
-	}
-	$allowed = $registry->getFieldsForType($type);
-	$filtered = array_filter($config, function ($item) use ($allowed) {
-		return in_array($item, $allowed);
-	}, ARRAY_FILTER_USE_KEY);
-
-	if (empty($filtered)) {
-//		error_log('[JVB_SCHEMA] No valid filters for '.$type.'.');
-		continue;
-	}
-	$removed = array_filter($config, function ($item) use ($allowed) {
-		return !in_array($item, $allowed);
-	}, ARRAY_FILTER_USE_KEY);
-
-	if (!empty($removed)) {
-//		error_log('[JVB_SCHEMA] Invalid fields detected for '.$type.': '.print_r($removed, true));
-	}
-	$checked[$key] = $filtered;
-}
-
-define('JVB_SCHEMA', $checked);
-
 
 /**
 JVB_CONTENT['artwork'] = [

--
Gitblit v1.10.0