From 47e77f9fac1155c536b2b87fec552c7fcce66fa6 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Mon, 01 Jun 2026 18:06:34 +0000
Subject: [PATCH] =Timeline block fixes. Next up: adding article schema classes

---
 inc/managers/SEO/render/Traits/_Properties/hasOfferCatalogTrait.php |  133 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 130 insertions(+), 3 deletions(-)

diff --git a/inc/managers/SEO/render/Traits/_Properties/hasOfferCatalogTrait.php b/inc/managers/SEO/render/Traits/_Properties/hasOfferCatalogTrait.php
index 90f336a..e7d32a7 100644
--- a/inc/managers/SEO/render/Traits/_Properties/hasOfferCatalogTrait.php
+++ b/inc/managers/SEO/render/Traits/_Properties/hasOfferCatalogTrait.php
@@ -1,7 +1,14 @@
 <?php
 namespace JVBase\managers\SEO\render\Traits\_Properties;
 
-use JVBase\managers\SEO\render\Thing\Intangible\OfferCatalog;
+use JVBase\base\SchemaHelper;
+use JVBase\inc\managers\SEO\render\Thing\Intangible\ItemList\OfferCatalog;
+use JVBase\managers\SEO\render\Thing\Intangible\Offer;
+use JVBase\managers\SEO\render\Thing\Intangible\Service;
+use JVBase\managers\SEO\render\Thing\Intangible\StructuredValue\PriceSpecification;
+use JVBase\managers\SEO\render\Thing\Product\Product;
+use JVBase\meta\Meta;
+use JVBase\registrar\Fields;
 use JVBase\registrar\Registrar;
 
 if (!defined('ABSPATH')) {
@@ -17,8 +24,26 @@
 	{
 		return $this->hasOfferCatalog??null;
 	}
-	public function setHasOfferCatalog(OfferCatalog $hasOfferCatalog):void
+	public function setHasOfferCatalog(OfferCatalog|array $hasOfferCatalog):void
 	{
+		if (is_array($hasOfferCatalog)){
+			if (array_key_exists('generate', $hasOfferCatalog) && $hasOfferCatalog['generate']) {
+				$this->generateOfferCatalog($hasOfferCatalog);
+			} else {
+				if (!array_key_exists('type', $hasOfferCatalog)) {
+					$hasOfferCatalog['type'] = 'JVBase\inc\managers\SEO\render\Thing\Intangible\ItemList\OfferCatalog';
+				}
+				$items = [];
+				if (array_key_exists('items', $hasOfferCatalog)) {
+					$items = $hasOfferCatalog['items'];
+					unset($hasOfferCatalog['items']);
+				}
+				$hasOfferCatalog = SchemaHelper::classFromConfig($hasOfferCatalog);
+				if (!empty($items)) {
+					$hasOfferCatalog->setItemListElement($items);
+				}
+			}
+		}
 		$this->hasOfferCatalog = $hasOfferCatalog;
 	}
 
@@ -31,7 +56,8 @@
 			'fields'	=> [
 				'generate'	=> [
 					'type'	=> 'true_false',
-					'label'	=> 'Generate from Content type?'
+					'label'	=> 'Generate from Content type?',
+					'default'	=> false,
 				],
 				'content_type'	=> [
 					'type'	=> 'checkbox',
@@ -67,10 +93,111 @@
 						'description'	=> [
 							'type'	=> 'textarea',
 							'label'	=> 'Description'
+						],
+						'price'	=> [
+							'type'	=> 'number',
+							'label'	=> 'Price'
 						]
 					]
 				]
 			]
 		];
 	}
+
+	public function setHasOfferCatalogField(Fields $fields):void
+	{
+		$fields->addField(
+			'hasOfferCatalog',
+			[
+				'type'	=> 'repeater',
+				'label'	=> 'Main Products & Services',
+				'fields'	=> [
+					'type'	=> [
+						'type'	=> 'radio',
+						'label'	=> __('Select Type', 'jvb'),
+						'options'	=> [
+							'product'	=> 'Product',
+							'service'	=> 'Service'
+						],
+						'required' => true,
+					],
+					'name'	=> [
+						'type'	=> 'text',
+						'label'	=> __('Name of Product or Service', 'jvb'),
+						'required'	=> true,
+					],
+					'description'	=> [
+						'type'	=> 'textarea',
+						'label'	=> __('Description (optional)', 'jvb'),
+					],
+					'price'	=> [
+						'type'	=> 'text',
+						'subtype'	=> 'number',
+						'label'		=> __('Price', 'jvb'),
+					],
+					'unitText' 	=> [
+						'type'	=> 'radio',
+						'label'	=> 'Price per unit',
+						'options'	=> [
+							'hour'	=> 'Hour',
+							'unit'	=> 'Unit',
+						],
+						'default'	=> 'unit',
+					]
+				],
+			]
+		);
+	}
+
+	public function formatHasOfferCatalogField(Meta $meta):void
+	{
+		$catalog = $meta->get('hasOfferCatalog');
+		if (!empty($catalog)) {
+			$offerCatalog = [];
+			$name = '';
+			$services = array_filter($catalog, function ($item) {
+				return $item['type'] === 'service';
+			});
+			$products =array_filter($catalog, function ($item) {
+				return $item['type'] === 'product';
+			});
+			if (count($products) > 0) {
+				$name = 'Products';
+				if (count($services) > 0) {
+					$name .= ' & ';
+				}
+			}
+			if (count($services) > 0) {
+				$name .= 'Services';
+			}
+			foreach ($catalog as $row) {
+				$offer = new Offer();
+
+				$item = match($row['type']) {
+					'product'	=> new Product(),
+					'service' 	=> new Service(),
+				};
+
+				$item->setName($row['name']);
+				if (!empty($row['description'])) {
+					$item->setDescription($row['description']);
+				}
+				if (!empty($row['price'])) {
+					$price = new PriceSpecification();
+					$price->setPrice($row['price']);
+					$price->setPriceCurrency('CAD');
+					$price->setUnitText($row['unitText']);
+					$offer->setPriceSpecification($price);
+				}
+				$offer->setItemOffered($item);
+				$offerCatalog[] =  $offer;
+			}
+			if (!empty(!$offerCatalog)) {
+				$final = new OfferCatalog();
+				$final->setName($name);
+				$final->setItemListElement($offerCatalog);
+				$this->sethasOfferCatalog($final);
+			}
+		}
+	}
 }

--
Gitblit v1.10.0