From c19264ac916707096fe294d996a1b7fb85206b34 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 08 Mar 2026 19:55:31 +0000
Subject: [PATCH] =Furthering along the complete refactor. Added some basic setup for is_content taxonomies, including a page for an archive of the terms.
---
inc/registrar/config/seo/Schema.php | 207 ++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 171 insertions(+), 36 deletions(-)
diff --git a/inc/registrar/config/seo/Schema.php b/inc/registrar/config/seo/Schema.php
index 91f03cb..b48b8de 100644
--- a/inc/registrar/config/seo/Schema.php
+++ b/inc/registrar/config/seo/Schema.php
@@ -34,7 +34,10 @@
'description' => '{{post_excerpt}}',
];
- protected array $defaultArchive = [];
+ protected array $defaultArchive = [
+ 'type' => 'JVBase\managers\SEO\render\Thing\CreativeWork\WebPage\CollectionPage',
+ 'title' => '{{registrar.plural}}'
+ ];
public function __construct(string $slug, string $type)
{
@@ -52,6 +55,16 @@
$this->cache->connect($registrar->getType());
$this->referenceCache->connect($registrar->getType());
$this->archiveCache->connect($registrar->getType());
+
+ switch ($registrar->getType()) {
+ case 'term':
+ $this->defaultSchema['type'] = 'JVBase\managers\SEO\render\Thing\CreativeWork\WebPage\CollectionPage';
+ break;
+ case 'user':
+ $this->defaultSchema['type'] = 'JVBase\managers\SEO\render\Thing\CreativeWork\WebPage\ProfilePage';
+ break;
+ }
+ $this->defaultArchive['description'] = '{{registrar.'.$slug.'.description}}';
}
$this->initFilters();
$this->registerHooks();
@@ -75,6 +88,8 @@
{
add_action('wp_head', [$this, 'outputSchema'], 1);
add_filter('the_seo_framework_schema_graph_data', [$this, 'filterTSFSchema'], 10, 2);
+ add_filter('the_seo_framework_title_from_custom_field', [$this, 'filterTSFOGTitle'], 10, 2);
+
$this->maybeExcludeSingles();
}
protected function maybeExcludeSingles(): void
@@ -119,67 +134,120 @@
}
public function filterTSFSchema(array $graph, ?array $args):array
{
- if (jvbTSFDoIt($this->slug, $args)){
+ $based = jvbCheckBase($this->slug);
+ if (is_front_page() || is_singular($based) || is_post_type_archive($based) || is_tax($based)) {
return [];
}
+
+// if (jvbTSFDoIt($this->slug, $args)){
+// return [];
+// }
return $graph;
}
public function outputSchema():void
{
+ $registrar = Registrar::getInstance($this->slug);
if (is_singular()) {
$this->outputSingularSchema();
} elseif (is_post_type_archive(jvbCheckBase($this->slug) || is_tax(jvbCheckBase($this->slug)))) {
$this->outputArchiveSchema();
+ } if ($registrar && $registrar->hasFeature('is_content') && is_single(get_option(BASE.$this->slug.'_archive'))) {
+ $this->outputContentTaxArchiveSchema();
}
}
public function outputSingularSchema():array
{
$ID = get_the_ID();
- $this->cache->flush();
+ if (JVB_TESTING){
+ $this->cache->flush();
+ }
+
return $this->cache->remember(
$ID,
function () use ($ID) {
$meta = Meta::forPost($ID);
$config = $this->getConfig();
- $class = new $config['type']();
- unset($config['type']);
- foreach ($config as $property => $value){
- $value = Resolver::resolveForSchema($property, $value, $config, $meta);
- $method = 'set'.ucfirst($property);
- $class->$method($value);
- }
+ $class = $this->classFromConfig($config, $meta);
$class->setAuthor(JVB()->seo()->getCreator(true));
- $schema = $class->outputSchema();
- error_log('Generated archive schema: '.print_r($schema, true));
- return $schema;
+ return $class->outputSchema();
}
);
}
+ public function outputContentTaxArchiveSchema():array
+ {
+ $ID = get_the_ID();
+ if (JVB_TESTING) {
+ $this->cache->flush();
+ }
+ return $this->cache->remember(
+ $ID,
+ function() use ($ID) {
+ $action = BASE.ucfirst($this->slug).'Schema';
+ $config = get_option($action, apply_filters($action, $this->defaultSchema));
+ if (!array_key_exists('type', $config)) {
+ $config['type'] = 'JVBase\managers\SEO\render\Thing\CreativeWork\WebPage\CollectionPage';
+ }
+ if (!class_exists($config['type'])) {
+ error_log('No class found for archive schema output: '.$config['type']);
+ return [];
+ }
+ $class = $this->classFromConfig($config);
+
+ $class->setIsPartOf(get_home_url().'/#website');
+ $itemList = new render\Thing\Intangible\ItemList\ItemList();
+ $items = get_terms([
+ 'taxonomy' => jvbCheckBase($this->slug),
+// 'hide_empty' => true,
+ 'fields' => 'ids',
+ ]);
+
+ $pos = 1;
+ $itemListItems = [];
+ foreach ($items as $ID) {
+ $item = $this->outputReferenceSchema($ID, 'term',false);
+ $listItem = new render\Thing\Intangible\ListItem();
+ $listItem->setPosition($pos);
+ $listItem->setItem($item);
+ $itemListItems[] = $listItem;
+ $pos++;
+ }
+ wp_reset_postdata();
+ $itemList->setItemListElement($itemListItems);
+ $class->setMainEntity($itemList);
+
+ return $class->outputSchema();
+ }
+ );
+ }
+
public function outputArchiveSchema():array
{
- $this->archiveCache->flush();
+ if (JVB_TESTING){
+ $this->archiveCache->flush();
+ }
+
return $this->archiveCache->remember(
$this->slug,
function() {
$action = BASE.ucfirst($this->slug).'Archive';
$config = get_option($action, apply_filters($action, $this->defaultArchive));
-
+ if (!array_key_exists('type', $config)) {
+ $config['type'] = 'JVBase\managers\SEO\render\Thing\CreativeWork\WebPage\CollectionPage';
+ }
if (!class_exists($config['type'])) {
error_log('No class found for archive schema output: '.$config['type']);
return [];
}
+ $obj = get_queried_object();
+ $meta = (property_exists($obj, 'taxonomy')) ? Meta::forTerm($obj->term_id) : null;
- $class = new $config['type'];
- unset($config['type']);
- foreach ($config as $property=>$value) {
- $method = 'set'.ucfirst($property);
- $class->$method($value);
- }
+ $class = $this->classFromConfig($config, $meta);
+
$class->setIsPartOf(get_home_url().'/#website');
$itemList = new render\Thing\Intangible\ItemList\ItemList();
$items = new WP_Query([
@@ -191,7 +259,7 @@
$pos = 1;
$itemListItems = [];
foreach ($items->posts as $ID) {
- $item = $this->outputReferenceSchema($ID, false);
+ $item = $this->outputReferenceSchema($ID, 'post',false);
$listItem = new render\Thing\Intangible\ListItem();
$listItem->setPosition($pos);
$listItem->setItem($item);
@@ -209,24 +277,43 @@
);
}
- public function outputReferenceSchema(int $ID, bool $outputSchema = true):mixed
+ public function outputReferenceSchema(int $ID, string $type, bool $outputSchema = true):mixed
{
- $this->referenceCache->flush();
+ if (JVB_TESTING){
+ $this->referenceCache->flush();
+ }
+
$cached = $this->referenceCache->remember(
$ID,
- function () use ($ID) {
- $meta = Meta::forPost($ID);
- $config = $this->getConfig();
- $class = new $config['type']();
- $class->setId(get_the_permalink($ID).'/#'.$class->getTypeName());
- foreach ($this->referenceProperties as $property => $value){
- $value = Resolver::resolveForSchema($property, $value, $this->schema, $meta);
- $method = 'set'.ucfirst($property);
- $class->$method($value);
+ function () use ($ID, $type) {
+ switch ($type) {
+ case 'post':
+ $meta = Meta::forPost($ID);
+ break;
+ case 'term':
+ $meta = Meta::forTerm($ID);
+ break;
+ case 'user':
+ $meta = Meta::forUser($ID);
+ break;
+ default:
+ error_log('Invalid type used for reference: '.print_r($type, true));
+ $meta = null;
+ }
+ $config = $this->getConfig('archive');
+ $class = $this->classFromConfig($config, $meta);
+ $class->delete('about');
+
+ switch ($type) {
+ case 'post':
+ $class->setId(get_the_permalink($ID).'#'.$class->getTypeName());
+ break;
+ case 'term':
+ $class->setId(get_term_link($ID).'#'.$class->getTypeName());
+ break;
}
- $schema = $class->outputSchema();
- error_log('Generated archive schema: '.print_r($schema, true));
+
return $class;
}
);
@@ -264,7 +351,12 @@
}
public function defineReference(string $property, string $value):void
{
- $class = $this->getConfig('schema')['type'];
+ $config = $this->getConfig();
+ if (!array_key_exists('type', $config)) {
+ $config['type'] = $this->defaultSchema['type'];
+ update_option(BASE.ucfirst($this->slug).'Schema', $config);
+ }
+ $class = $this->getConfig()['type'];
if (!class_exists($class)) {
error_log('[SEO]Schema::defineReference Class not found: '.$class);
return;
@@ -294,4 +386,47 @@
$this->defineReference($property, $value);
}
}
+
+ public function filterTSFOGTitle(string $title, ?array $args):string{
+ $based = jvbCheckBase($this->slug);
+
+ if (is_singular($based)){
+ $config = $this->getConfig('meta');
+ $meta = Meta::forPost(get_the_ID());
+ $title = Resolver::resolve($config['name'], $meta);
+ } elseif (is_post_type_archive($based) || is_tax($based)) {
+ $config = $this->getConfig('archive');
+ $title = $config['name'];
+ }
+ return $title;
+ }
+
+ protected function classFromConfig(array $config, ?Meta $meta = null):mixed
+ {
+ if (!array_key_exists('type', $config)) {
+ error_log('[Schema]::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 = $this->classFromConfig($value, $meta);
+ }
+ $method = 'set'.ucfirst($property);
+ if (!method_exists($class, $method)) {
+ error_log('[Schema]::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;
+ }
}
--
Gitblit v1.10.0