From 46d681c6b825d21b3f698d793c4e630c687d90ad Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Thu, 21 May 2026 21:41:53 +0000
Subject: [PATCH] =Major CustomBlocks.php overhaul, expanding block support and customization from the editor. theme.json should now be updated on new themes to set brand colours, etc. Also note: major change to .col vs .row alignment: simplifying it to .top .bottom vs the confusion of the differences for .col/.row .start and .a-start

---
 inc/blocks/FeedBlock.php |  159 +++++++++++++++++++++++++++++-----------------------
 1 files changed, 88 insertions(+), 71 deletions(-)

diff --git a/inc/blocks/FeedBlock.php b/inc/blocks/FeedBlock.php
index 8c630dd..c6b1f0b 100644
--- a/inc/blocks/FeedBlock.php
+++ b/inc/blocks/FeedBlock.php
@@ -1,9 +1,9 @@
 <?php
 namespace JVBase\blocks;
 
-use JVBase\managers\CacheManager;
-use JVBase\utility\Features;
-use JVBase\utility\Checker;
+use JVBase\managers\Cache;
+use JVBase\registrar\Registrar;
+use JVBase\base\Site;
 use JVBase\forms\TaxonomySelector;
 use WP_Block;
 
@@ -13,39 +13,21 @@
 
 class FeedBlock
 {
-	protected CacheManager $cache;
+	protected Cache $cache;
 	protected array $config;
 	protected string $path = JVB_DIR.'/build/feed';
 
 	public function __construct()
 	{
 		// Initialize cache with connections
-		$this->cache = CacheManager::for('feed_block', WEEK_IN_SECONDS);
-		$this->cache->clear();
-		// Set up cache connections for all feed content types
-		$this->setupCacheConnections();
+		$this->cache = Cache::for('feed_block', WEEK_IN_SECONDS);
+//		if (JVB_TESTING) {
+//			$this->cache->flush();
+//		}
 
 		add_action('init', [$this, 'registerBlock']);
 	}
 
-	/**
-	 * Set up cache connections for feed content
-	 */
-	protected function setupCacheConnections(): void
-	{
-		// Connect to all content types that show in feed
-		$contentTypes = Features::getTypesWithFeature('show_feed', 'content');
-		foreach ($contentTypes as $type) {
-			CacheManager::for('feed_content')->connectTo('post', $type);
-		}
-
-		// Connect to all taxonomies that show in feed
-		$taxonomies = Features::getTypesWithFeature('show_feed', 'taxonomy');
-		foreach ($taxonomies as $tax) {
-			CacheManager::for('feed_taxonomy')->connectTo('taxonomy', $tax);
-		}
-	}
-
 	public function registerBlock()
 	{
 		register_block_type($this->path, [
@@ -71,12 +53,13 @@
 
 		if (is_post_type_archive() || is_singular()) {
 			$content = is_singular() ? jvbNoBase($type->post_type) : jvbNoBase($type->name);
-			$mainConfig = JVB_CONTENT[$content]??false;
-			if ($mainConfig && array_key_exists('feed', $mainConfig) && array_key_exists('config', $mainConfig['feed'])){
-				$config = array_merge($config, $mainConfig['feed']['config']);
+
+			$registrar = Registrar::getInstance($content)??false;
+			if ($registrar) {
+				$config = array_merge($config, $registrar->getConfig('feed'));
 			} else {
 				$config['content'] = $content;
-				$config['icon'] = JVB_CONTENT[$content]['icon']??[jvbLogoIcon()];
+				$config['icon'] = jvbDefaultIcon();
 			}
 			if (is_singular()) {
 				$config['source'] = $type->ID;
@@ -85,13 +68,13 @@
 			$config['taxonomies'] = $this->getTaxonomies([$content]);
 		} elseif (is_tax()) {
 			$content = jvbNoBase($type->taxonomy);
-			$mainConfig = JVB_TAXONOMY[$content]??false;
-			if ($mainConfig) {
-				$config['content'] = $mainConfig['for_content'];
-				$config['context'] = $content;  // ← ADD THIS
-				$config['taxonomies'] = $this->getTaxonomies($mainConfig['for_content']);
-				if (array_key_exists('feed', $mainConfig) && array_key_exists('config', $mainConfig['feed'])){
-					$config = array_merge($config, $mainConfig['feed']['config']);
+			$registrar = Registrar::getInstance($content)??false;
+			if ($registrar) {
+				$config['content'] = $registrar->registrar->for;
+				$config['context'] = $content;
+				$config['taxonomies'] = $this->getTaxonomies($registrar->registrar->for);
+				if (!empty($registrar->getConfig('feed'))){
+					$config = array_merge($config, $registrar->getConfig('feed'));
 				}
 			}
 			$config['source'] = $type->term_id;
@@ -106,17 +89,21 @@
 
 	/**
 	 * Get taxonomies for given content types
-	 * Uses Checker instead of globals
+
 	 */
 	protected function getTaxonomies(array $content): array
 	{
-		$checker = Checker::getInstance();
+
 		$taxonomies = [];
 
 		foreach ($content as $contentType) {
-			$contentTaxonomies = $checker->getTaxonomiesForContent($contentType);
+			$registrar = Registrar::getInstance($contentType);
+			if (!$registrar) {
+				continue;
+			}
+			$contentTaxonomies = $registrar->registrar->taxonomies;
 			$contentTaxonomies = array_filter($contentTaxonomies, function($taxonomy) {
-				return array_key_exists('show_feed', JVB_TAXONOMY[$taxonomy]) && JVB_TAXONOMY[$taxonomy]['show_feed'];
+				return Registrar::getInstance($taxonomy)?->hasFeature('show_feed');
 			});
 			$taxonomies = array_merge($taxonomies, $contentTaxonomies);
 		}
@@ -129,7 +116,7 @@
 
 		$this->config = $this->buildParams($attributes);
 		return $this->cache->remember(
-			$this->config,
+			$this->cache->generateKey($this->config),
 			function() {
 				return $this->renderBlock();
 			}
@@ -188,6 +175,7 @@
 			echo TaxonomySelector::outputSelectorModal();
 			?>
 		</section>
+		<footer><button data-action="refresh" data-ignore><?=jvbIcon('arrows-clockwise')?><span>Hard Refresh</span></span></button></footer>
 		<?php
 		return ob_get_clean();
 	}
@@ -205,8 +193,8 @@
 			<?php if ($hasMany) {
 				//If we have multiple content, only show the content first
 				?>
-				<details class="col a-start">
-				<summary class="row btw">
+				<details class="col left">
+				<summary class="row x-btw">
 					<span class="label">SHOWING: </span>
 					<?php
 					$labels = [];
@@ -247,7 +235,7 @@
 			<?php } ?>
 
 
-					<?php if (Features::forSite()->has('favourites') && is_user_logged_in()) : ?>
+					<?php if (Site::has('favourites') && is_user_logged_in()) : ?>
 						<input type="checkbox" id="favourites" class="btn" name="favourites" value="on"
 							   data-filter="favourites">
 						<label for="favourites" title="Show Favourites" class="row">
@@ -261,23 +249,22 @@
 				if (!empty ($this->config['taxonomies'])) {
 				?>
 					<div class="filters">
-						<div class="filter-group row start">
+						<div class="filter-group row left">
 							<span class="label">FILTER BY:</span>
 
 							<?php
-							$checker = Checker::getInstance();
 							foreach ($this->config['taxonomies'] as $tax) :
-								$taxConfig = JVB_TAXONOMY[$tax] ?? null;
-								if (!$taxConfig) continue;
+								$registrar = Registrar::getInstance($tax)??false;
+								if (!$registrar) continue;
 
-								$contentForTax = $checker->getContentForTaxonomy($tax);
+								$contentForTax = $registrar->registrar->for;
 								$hidden = empty($contentForTax) ? ' hidden' : '';
 
 								$taxSelector = new TaxonomySelector(
 									'feed-'.$tax,
 									$tax,
 									[
-										'icon'			=> $taxConfig['icon']??jvbLogoIcon(),
+										'icon'			=> $registrar->getIcon()??jvbLogoIcon(),
 										'update' 		=> '.selected-items-section .selected-items',
 										'types' 		=> $contentForTax,
 										'autocomplete'	=> false,
@@ -292,8 +279,8 @@
 						<div class="selected-items-section">
 							<div class="selected-items row"></div>
 							<div class="filter-actions row">
-								<?= jvbRenderToggleTextField('match', 'Match', 'Filters', 'ALL', 'ANY', false, ['filter' => 'match']) ?>
-								<button type="button" class="clear-filters row">
+								<?= str_replace('class="toggle-text"', 'class="toggle-text" hidden', jvbRenderToggleTextField('match', 'Match', 'Filters', 'ALL', 'ANY', false, ['filter' => 'match'])) ?>
+								<button type="button" class="clear-filters row" hidden>
 									<?= jvbIcon('x') ?>
 									Clear All Filters
 								</button>
@@ -301,8 +288,8 @@
 						</div>
 					</div>
 				<?php } ?>
-					<div class="row btw nowrap">
-						<div class="order-by filter-group row start w-full">
+					<div class="row x-btw nowrap">
+						<div class="order-by filter-group row left w-full">
 							<span class="label">ORDER BY:</span>
 							<?php
 							//TODO: Get content types that can be sorted alphabetically
@@ -314,19 +301,46 @@
 							</label>
 
 							<input type="radio" id="order-date" class="btn" name="orderby" value="date" data-filter="orderby" checked>
-							<label for="order-date" title="Order by Date" class="row">
+							<label for="order-date" title="Order by Date Created" class="row">
 								<?= jvbIcon('calendar', ['title' => 'Date']) ?>
-								<span class="label">Date</span>
+								<span class="label">Date Created</span>
 							</label>
 
+							<input type="radio" id="order-modified" class="btn" name="orderby" value="modified" data-filter="orderby">
+							<label for="order-modified" title="Order by Date Modified" class="row">
+								<?= jvbIcon('clock-clockwise') ?>
+								<span class="label">Date Modified</span>
+							</label>
+
+							<?php
+								$custom = [];
+								foreach ($this->getContent() as $content) {
+									$registrar = Registrar::getInstance($content)??false;
+
+									if ($registrar && !empty($registrar->config('feed')->getCustomOrder())) {
+										$custom = array_merge_recursive($custom, $registrar->config('feed')->getCustomOrder());
+									}
+								}
+								foreach ($custom as $slug => $conf) {
+									?>
+									<input type="radio" id="order-<?=$slug?>" class="btn" name="orderby" value="<?=$slug?>" data-for="<?=$conf['for']?>" data-filter="orderby">
+									<label for="order-<?=$slug?>" title="<?= $conf['label']?>" class="row">
+										<?= jvbIcon($conf['icon']) ?>
+										<span class="label"><?=$conf['label']?></span>
+									</label>
+									<?php
+								}
+								$custom = implode(',', array_keys($custom));
+							?>
 							<input type="radio" id="order-random" class="btn" name="orderby" value="random" data-filter="orderby">
 							<label for="order-random" title="Random Order" class="row">
 								<?= jvbIcon('shuffle') ?>
 								<span class="label">Random</span>
 							</label>
+
 						</div>
 
-						<div class="order-direction filter-group row start w-full" data-for-order="date,title">
+						<div class="order-direction filter-group row left w-full" data-for-order="date,modified,title<?= $custom === '' ? '' : ','.$custom?>">
 							<span class="label">ORDER:</span>
 							<input type="radio" id="order-desc" class="btn" name="order" value="desc" data-filter="order" checked>
 							<label for="order-desc" title="Sort Descending (A-Z, 1-10)" class="row">
@@ -356,8 +370,8 @@
 			$total = count($this->getContent()) - 1;
 			for ($i = 1; $i <= 36; $i++) {
 				$rand = rand(0, $total);
-				$config = Features::getConfig($this->getContent()[$rand]);
-				$icon = jvbIcon($config['icon']??jvbLogoIcon());
+				$config = Registrar::getInstance($this->getContent()[$rand]);
+				$icon = jvbIcon($config->getIcon??jvbLogoIcon());
 				?>
 				<div class="placeholder"><?=apply_filters('jvbFeedPlaceholder', $icon) ?></div>
 				<?php
@@ -391,7 +405,7 @@
 			}
 		}
 
-
+		echo '<template class="feedTerm"><button class="remove-term">'.jvbIcon(jvbDefaultIcon()).'<span></span>'.jvbIcon('x').'</button></template>';
 		echo '<template class="emptyState">'.apply_filters('jvbFeedEmptyState', '<div class="empty-state">
                 <h3>'.jvbIcon($this->getIcon()).'NOTHING HERE'.jvbIcon($this->getIcon()).'</h3>
                 <p>Try tweaking those filters a bit.</p>
@@ -401,7 +415,8 @@
 
 	protected function getFavouritesButton(string $content):string
 	{
-		if (!Features::forSite()->has('favourites') && !Features::forContent($content)->has('favouritable')) {
+		$registrar = Registrar::getInstance($content);
+		if (!$registrar || !Site::has('favourites') || !$registrar->hasFeature('favouritable')) {
 			return '';
 		}
 		return '<button class="favourite" type="button" title="Add to favourites" data-action="favourite">
@@ -411,7 +426,8 @@
 	}
 	protected function getUpvotesButton(string $content):string
 	{
-		if (!Features::forSite()->has('karma') && !Features::forContent($content)->has('karma')){
+		$registrar = Registrar::getInstance($content);
+		if (!Site::has('karma') || !$registrar || !$registrar->hasFeature('karma')){
 			return '';
 		}
 		return '<div class="karma row">
@@ -428,14 +444,16 @@
 	}
 	protected function getDefaultTemplate(string $content): string
 	{
-		$config = JVB_CONTENT[$content]??[];
-		$hasConfig = array_key_exists('feed', $config);
-		$images = ($hasConfig && array_key_exists('images', $config['feed']) ? $config['feed']['images']:['post_thumbnail']);
-		$images = (is_array($images)) ? $images : [$images];
-		$fields = ($hasConfig && array_key_exists('fields', $config['feed']) ? $config['feed']['fields']:['post_title', 'post_date']);
+		$config = Registrar::getInstance($content)->getConfig('feed');
+		$allFields = Registrar::getFieldsFor($content);
+		$images = $config['images']??['post_thumbnail'];
+		$fields = $config['fields']??['post_title','post_date','post_excerpt'];
 		$fields = array_filter($fields, function($field) use($images) {
 			return !in_array($field, $images);
 		});
+		$fields = array_filter($allFields, function($field) use($fields) {
+			return in_array($field, $fields);
+		}, ARRAY_FILTER_USE_KEY);
 		$template = '<div class="feed item col '.$content.'">'.$this->getFavouritesButton($content).$this->getUpvotesButton($content);
 
 		//Add all defined images, but allow for filtering
@@ -452,9 +470,8 @@
 
 		$fieldsTemplate = '';
 
-		foreach ($fields as $fieldName) {
-			$fieldType = JVB_CONTENT[$content][$fieldName]['type']??'text';
-			$fieldsTemplate .= apply_filters('jvbFeedItemField', $this->defaultFieldTemplate($fieldType, $fieldName), $content, $fieldName, $fieldType);
+		foreach ($fields as $fieldName => $config) {
+			$fieldsTemplate .= apply_filters('jvbFeedItemField', $this->defaultFieldTemplate($config['type'], $fieldName), $content, $fieldName, $config['type']);
 		}
 		$template .= '<div class="item-info">'.apply_filters('jvbFeedItemFields', $fieldsTemplate, $content, $fields).'</div>';
 		$template .= '</details></div>';

--
Gitblit v1.10.0