From 32ce5c542c90be348895328078e392dde2052957 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Fri, 04 Sep 2026 19:15:16 +0000
Subject: [PATCH] =Working at adding defined fields to a dedicated panel in the gutenberg editor. Registrar now has AddCustomFields.php, which currently only supports post fields. Added a @wordpress/plugins base _meta/fields in /build and /src that successfully creates a panel. Next steps: determine sections and fields, group fields by section (each section to a panel), and save output

---
 inc/managers/SEO/render/SchemaOutput.php |  121 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 120 insertions(+), 1 deletions(-)

diff --git a/inc/managers/SEO/render/SchemaOutput.php b/inc/managers/SEO/render/SchemaOutput.php
index 30a9c02..87c2e7c 100644
--- a/inc/managers/SEO/render/SchemaOutput.php
+++ b/inc/managers/SEO/render/SchemaOutput.php
@@ -6,10 +6,18 @@
 use JVBase\Instance;
 use JVBase\managers\Cache;
 use JVBase\managers\SEO\BreadcrumbManager;
+use JVBase\managers\SEO\render\Thing\CreativeWork\Menu;
+use JVBase\managers\SEO\render\Thing\CreativeWork\MenuSection;
+use JVBase\managers\SEO\render\Thing\Intangible\MenuItem;
+use JVBase\managers\SEO\render\Thing\Intangible\Offer;
 use JVBase\managers\SEO\render\Thing\Intangible\Service;
 use JVBase\managers\SEO\render\Thing\Organization\LocalBusiness\LocalBusiness;
+use JVBase\managers\SEO\render\Thing\Thing;
+use JVBase\meta\Meta;
 use JVBase\registrar\config\seo\Resolver;
 use JVBase\registrar\Registrar;
+use WP_Query;
+
 if (!defined('ABSPATH')) {
 	exit;
 }
@@ -36,6 +44,7 @@
 				$schema[] = $test;
 			}
 		}
+
 		if (is_singular($this->types)) {
 			$type = get_post_type();
 			$registrar = Registrar::getInstance($type);
@@ -66,6 +75,8 @@
 //				error_log('SEO: '.print_r($seo->schema(), true));
 				$schema[] = $seo->schema()->outputArchiveSchema();
 			}
+		} elseif (is_post_type_archive('product')) {
+			$schema[] = $this->buildProductSchema();
 		}
 		$isContent = array_values(array_filter(array_map(function($item) {
 			return intval(get_option(BASE.$item.'_archive', false));
@@ -144,7 +155,7 @@
 		}
 //		$encoded =  wp_json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
 //		$encoded =  wp_json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT, 1024);
-		$encoded = wp_json_encode($schema, JSON_UNESCAPED_SLASHES, 1024);
+		$encoded = wp_json_encode($schema, JSON_UNESCAPED_SLASHES, 2048);
 		if ($encoded === false) {
 			error_log('wp_json_encode failed: ' . json_last_error_msg());
 			return;
@@ -362,5 +373,113 @@
 		$class = SchemaHelper::getInstance()::classFromConfig($config);
 		return ($class)? $class->outputSchema() : [];
 	}
+
+	public function buildProductSchema():array
+	{
+		$sections = aneb_menu_sections();
+		if (empty($sections)) {
+			$sections = [];
+		}
+
+		$menuSections = [];
+
+		foreach ($sections as $s) {
+			if (empty($s['id'])) {
+				continue;
+			}
+			$items = new WP_Query([
+				'post_type'         => 'product',
+				'order'             => 'ASC',
+				'posts_per_page'    => -1,
+				'post_status'       => 'publish',
+				'tax_query'         => [
+					[
+						'taxonomy'  => 'product_cat',
+						'terms'     => (int)$s['id']
+					]
+				],
+				'fields'            => 'ids',
+			]);
+			if (!$items->have_posts())  {
+				continue;
+			}
+
+			$section = new MenuSection();
+
+			$section->setName($s['name']);
+			$section->setId(get_post_type_archive_link('product').'#'.sanitize_title($s['name']));
+			if (!empty($s['description'])) {
+				$section->setDescription($s['description']);
+			}
+
+			$menuItems = [];
+			foreach ($items->posts as $ID) {
+				$meta = Meta::forPost($ID);
+				$fields = $meta->getAll();
+				if (empty($fields['variations'])) {
+					$item = $this->buildMenuItem($ID, $fields);
+					if ($item) {
+						$menuItems[] = $item;
+					}
+				} else {
+					foreach ($fields['variations'] as $variation) {
+						$item = $this->buildMenuItem($ID, $variation);
+						if ($item) {
+							$menuItems[] = $item;
+						}
+					}
+				}
+			}
+
+			if (!empty($menuItems)) {
+				$section->setHasMenuItem($menuItems);
+				$menuSections[] = $section;
+			}
+
+
+		}
+
+		if (!empty($menuSections)) {
+			$schema = new Menu();
+			$schema->setName(get_bloginfo('name') . ' | Alberta\'s Best Food Truck Menu');
+			$schema->setId(get_post_type_archive_link('product').'#menu');
+			$schema->setDescription('Southern style barbeque with Northern flair from Meeting Creek, Alberta');
+			$schema->setUrl(get_post_type_archive_link('product'));
+
+			$schema->setHasMenuSection($menuSections);
+
+			return $schema->outputSchema();
+		}
+
+		return [];
+	}
+
+		protected function buildMenuItem(int $ID, array $fields):MenuItem|false
+		{
+			$item = new MenuItem();
+			$item->setUrl(get_the_permalink($ID));
+			$base = get_post_type_archive_link('product').'#'.$ID.'-'.sanitize_title($fields['post_title']);
+			$item->setId($base);
+			$doit = false;
+			if (!empty($fields['post_thumbnail']??'')) {
+				$doit = true;
+				$item->setImage(Thing::createImageFromID($fields['post_thumbnail']));
+			}
+
+			if (!empty($fields['post_excerpt']??'')) {
+				$doit = true;
+				$item->setDescription(wp_strip_all_tags($fields['post_excerpt']));
+			}
+
+			if (!empty($fields['price']??'')) {
+				$doit = true;
+				$offer = new Offer();
+				$offer->setId($base.'-price');
+				$offer->setPrice($fields['price']);
+				$offer->setPriceCurrency('CAD');
+				$item->setOffers($offer);
+			}
+			return $doit ? $item : false;
+		}
 }
 

--
Gitblit v1.10.0