From 772462eeca3002a1d52508aeba485aab2b4742ad Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Tue, 03 Mar 2026 19:06:19 +0000
Subject: [PATCH] =MAJOR OVERHAUL. Likely should have made a new branch ages ago. Key changes: Registrar.php is the base for custom post types, taxonomies, and user roles. Replaces JVB_CONTENT, JVB_TAXONOMY, and JVB_USER constants, eliminates most of Features.php (except for JVB_SITE, JVB_MEMBERSHIP), and has built in sanitizing and validation via sub-classes. Also started a major overhaul of the Schema output. Created a shit ton of property traits and classes to help sanitize and ensure proper data for different schema types. Still a bunch to do, but better to be starting committing changes here on this other branch.

---
 inc/managers/SEO/SchemaOutputManager.php |   66 +++++++++++++++++---------------
 1 files changed, 35 insertions(+), 31 deletions(-)

diff --git a/inc/managers/SEO/SchemaOutputManager.php b/inc/managers/SEO/SchemaOutputManager.php
index d53da29..e7a44f4 100644
--- a/inc/managers/SEO/SchemaOutputManager.php
+++ b/inc/managers/SEO/SchemaOutputManager.php
@@ -2,8 +2,10 @@
 namespace JVBase\managers\SEO;
 
 use JVBase\managers\Cache;
+use JVBase\managers\SEO\schemas\SchemaResolverRegistry;
 use JVBase\meta\Meta;
 use JVBase\managers\SEO\schemas\SchemaDefinition;
+use JVBase\registrar\Registrar;
 use WP_Term;
 use WP_User;
 
@@ -60,21 +62,16 @@
 	 */
 	public function excludeHiddenSingles(array $ids): array
 	{
-		$hiddenTypes = [];
-		$timelineTypes = [];
+		$hiddenTypes = array_map(function($type) {
+				return jvbCheckBase($type);
+			},
+			Registrar::getFeatured('hide_single', 'post')
+		);
 
-		// Find post types with hide_single or is_timeline flags
-		foreach (JVB_CONTENT as $slug => $config) {
-			$postType = BASE . $slug;
+		$timelineTypes = array_map(function($type) {
+			return jvbCheckBase($type);
+		}, Registrar::getFeatured('is_timeline', 'post'));
 
-			if (!empty($config['hide_single'])) {
-				$hiddenTypes[] = $postType;
-			}
-
-			if (!empty($config['is_timeline'])) {
-				$timelineTypes[] = $postType;
-			}
-		}
 
 		$hiddenIds = [];
 
@@ -120,7 +117,6 @@
 	public function filterTitle(string $title, ?array $args): string
 	{
 		if ($args !== null) {
-			// Not in the loop (admin, etc.)
 			return $title;
 		}
 
@@ -131,14 +127,22 @@
 
 		$metaConfig = $this->config->meta();
 
-		if (empty($metaConfig['title'])) {
+		if (empty($metaConfig['metaTitle'])) {
 			return $title;
 		}
 
 		$resolver = $this->getResolver();
-		$customTitle = $resolver->resolve($metaConfig['title']);
+		$customTitle = $resolver->resolve($metaConfig['metaTitle']);
 
-		return $customTitle ?: $title;
+		if (!$customTitle) {
+			return $title;
+		}
+
+		// Strip trailing site name — TSF adds its own branding
+		$siteName = get_bloginfo('name');
+		$customTitle = preg_replace('/\s*[|\-–—]\s*' . preg_quote($siteName, '/') . '\s*$/i', '', $customTitle);
+
+		return $customTitle;
 	}
 
 	/**
@@ -157,12 +161,12 @@
 
 		$metaConfig = $this->config->meta();
 
-		if (empty($metaConfig['description'])) {
+		if (empty($metaConfig['metaDescription'])) {
 			return $description;
 		}
 
 		$resolver = $this->getResolver();
-		$customDescription = $resolver->resolve($metaConfig['description']);
+		$customDescription = $resolver->resolve($metaConfig['metaDescription']);
 
 		// Truncate to reasonable length
 		if (strlen($customDescription) > 160) {
@@ -189,16 +193,16 @@
 		$metaConfig = $this->config->meta();
 
 		// Check for custom image
-		if (!empty($metaConfig['image'])) {
+		if (!empty($metaConfig['socialPreviewImage'])) {
 			$resolver = $this->getResolver();
-			$imageUrl = $resolver->resolve($metaConfig['image']);
+			$imageUrl = $resolver->resolve($metaConfig['socialPreviewImage']);
 
 			if ($imageUrl) {
 				$params['og:image'] = $imageUrl;
 
 				// Use twitter-specific image if set, otherwise use main image
-				if (!empty($metaConfig['twitter_image'])) {
-					$twitterImage = $resolver->resolve($metaConfig['twitter_image']);
+				if (!empty($metaConfig['twitterImage'])) {
+					$twitterImage = $resolver->resolve($metaConfig['twitterImage']);
 					$params['twitter:image'] = $twitterImage ?: $imageUrl;
 				} else {
 					$params['twitter:image'] = $imageUrl;
@@ -532,12 +536,12 @@
 			$resolver = $this->getResolver();
 			$metaConfig = $this->config->meta();
 
-			if (!empty($metaConfig['title'])) {
-				$webpage['name'] = $resolver->resolve($metaConfig['title']);
+			if (!empty($metaConfig['metaTitle'])) {
+				$webpage['name'] = $resolver->resolve($metaConfig['metaTitle']);
 			}
 
-			if (!empty($metaConfig['description'])) {
-				$webpage['description'] = $resolver->resolve($metaConfig['description']);
+			if (!empty($metaConfig['metaDescription'])) {
+				$webpage['description'] = $resolver->resolve($metaConfig['metaDescription']);
 			}
 		}
 
@@ -562,7 +566,7 @@
 			$post = get_post();
 			if ($post) {
 				$postType = jvbNoBase($post->post_type);
-				if (defined('JVB_CONTENT') && isset(JVB_CONTENT[$postType])) {
+				if (Registrar::getInstance($postType)) {
 					$this->config = ConfigManager::for($postType);
 					return [
 						'objectType' => 'post',
@@ -575,7 +579,7 @@
 			$term = get_queried_object();
 			if ($term instanceof WP_Term) {
 				$taxonomy = jvbNoBase($term->taxonomy);
-				if (defined('JVB_TAXONOMY') && isset(JVB_TAXONOMY[$taxonomy])) {
+				if (Registrar::getInstance($taxonomy)) {
 					$this->config = ConfigManager::for($taxonomy);
 					return [
 						'objectType' => 'term',
@@ -588,7 +592,7 @@
 			$user = get_queried_object();
 			if ($user instanceof WP_User) {
 				$role = jvbUserRole($user->ID);
-				if (defined('JVB_USER') && isset(JVB_USER[$role])) {
+				if (Registrar::getInstance($role)) {
 					$this->config = ConfigManager::for($role);
 					return [
 						'objectType' => 'user',
@@ -604,7 +608,7 @@
 			}
 			$postType = jvbNoBase($postType);
 
-			if (defined('JVB_CONTENT') && isset(JVB_CONTENT[$postType])) {
+			if (Registrar::getInstance($postType)) {
 				$this->config = ConfigManager::for($postType);
 				return [
 					'objectType' => 'archive',

--
Gitblit v1.10.0