init(); } protected function init(): void { $this->types = array_map(function ($type) { return jvbCheckBase($type); }, Registrar::getRegistered()); } public function buildSchema():array { $schema = []; $schema[] = $this->buildWebsiteSchema(false); if (is_front_page()) { $test = $this->buildOrganizationSchema(); if (!empty($test)) { $schema[] = $test; } } if (is_singular($this->types)) { $type = get_post_type(); $registrar = Registrar::getInstance($type); if ($registrar && !empty($registrar->getConfig('seo')['schema']??[])) { $seo = $registrar->getSEO(); $schema[] = $seo->schema()->outputSingularSchema(); } }elseif (is_post_type_archive($this->types)) { $type = get_queried_object(); $type = $type->name; $registrar = Registrar::getInstance($type); if ($registrar && !empty($registrar->getConfig('seo')['schema']??[])) { $seo = $registrar->getSEO(); $schema[] =$seo->schema()->outputArchiveSchema(); } } elseif (is_tax($this->types)) { $type = get_queried_object(); $type = jvbNoBase($type->taxonomy); $registrar = Registrar::getInstance($type); if ($registrar && !empty($registrar->getConfig('seo')['schema']??[])) { $seo = $registrar->getSEO(); error_log('SEO: '.print_r($seo->schema(), true)); $schema[] = $seo->schema()->outputArchiveSchema(); } } $isContent = array_values(array_filter(array_map(function($item) { return intval(get_option(BASE.$item.'_archive', false)); },Registrar::getFeatured('is_content', 'term')))); if (is_page($isContent)){ $type = get_post_meta(get_the_id(), BASE.'for_type', true); error_log('Type: '.print_r($type, true)); $registrar = Registrar::getInstance($type); if ($registrar) { $schema[] = $registrar->getSEO()->schema()->outputContentTaxArchiveSchema(); } } $breadcrumbs = $this->buildBreadcrumbs(); if ($breadcrumbs) { $schema[] = $breadcrumbs; } if (!empty($schema)) { $website = JVB()->schemaHelper()::schema('website'); if (!empty($website)) { if (JVB_TESTING) { Cache::for('websiteSchema')->flush(); } $website = Cache::for('websiteSchema')->remember( 'schema', function () { return $this->websiteSchema(); } ); array_unshift($schema, $website); } $schema = [ '@context' => 'https://schema.org', '@graph' => $schema ]; } return $schema; } protected function websiteSchema():array { $stored = JVB()->schemaHelper()::schema('website'); $website = JVB()->schemaHelper()::classFromConfig($stored); if (!$website->getUrl() || empty($website->getUrl())){ $website->setUrl(get_home_url()); } if (!$website->getName() || empty($website->getName())){ $website->setName(get_bloginfo('name')); } if(!$website->getCreator() || empty($website->getCreator())) { $website->setCreator($this->getCreator()); } return $website->outputSchema(); } public function outputSchema():void { $schema = $this->buildSchema(); if (empty($schema)) { return; } echo "\n\n"; echo '' . "\n"; echo "\n" . ''."\n"; } public function buildBreadcrumbs():array { return BreadcrumbManager::getInstance()->toSchema(); } public function buildWebsiteSchema(bool $full = true):array { if (JVB_TESTING){ Cache::for('websiteSchema')->flush(); } $storedWebsite = JVB()->schemaHelper()::schema('website'); if (!$full) { return Cache::for('websiteSchema')->remember( 'reference', function () use ($storedWebsite) { $allowed = ['type','name', 'url', 'description', 'inLanguage']; $storedWebsite = array_filter($storedWebsite, function ($key) use ($allowed) { return in_array($key, $allowed); }, ARRAY_FILTER_USE_KEY); $website = JVB()->schemaHelper()::classFromConfig($storedWebsite); if (!$website->getName() || empty($website->getName())) { $website->setName(get_bloginfo('name')); } if (!$website->getUrl() || empty($website->getUrl())) { $website->setUrl(get_home_url()); } if (!$website->getId() || empty($website->getId())) { $website->setId(get_home_url().'/#website'); } if (!$website->getDescription() || empty($website->getDescription())) { $website->setDescription(get_bloginfo('description')); } if (!$website->getInLanguage() || empty($website->getInLanguage())) { $website->setInLanguage('en-CA'); } if (!$website->getPublisher() || empty($website->getPublisher())) { $publisher = $this->getOptionSchemaReference('organization'); if ($publisher){ $website->setPublisher($publisher); } } $website->setCreator($this->getCreator(true)); return $website->outputSchema(); } ); } return Cache::for('websiteSchema')->remember( 'full', function () use ($storedWebsite) { error_log('StoredWebsite: '.print_r($storedWebsite, true)); $website = JVB()->schemaHelper()::classFromConfig($storedWebsite); if (!$website->getName() || empty($website->getName())) { $website->setName(get_bloginfo('name')); } if (!$website->getUrl() || empty($website->getUrl())) { $website->setUrl(get_home_url()); } if (!$website->getId() || empty($website->getId())) { $website->setId(get_home_url().'/#website'); } if (!$website->getDescription() || empty($website->getDescription())) { $website->setDescription(get_bloginfo('description')); } if (!$website->getInLanguage() || empty($website->getInLanguage())) { $website->setInLanguage('en-CA'); } if (!$website->getPublisher() || empty($website->getPublisher())) { $publisher = $this->getOptionSchemaReference('organization'); if ($publisher){ $website->setPublisher($publisher); } } $website->setCreator($this->getCreator(true)); return $website->outputSchema(); } ); } public function getCreator(bool $reference = false):LocalBusiness { if (JVB_TESTING){ Cache::for('JakeVanCreator')->flush(); } if ($reference) { return Cache::for('JakeVanCreator')->remember( 'reference', function () { $creator = new LocalBusiness(); $creator->setName('JakeVan'); $creator->setAlternateName('Jake Vanderwerf'); $creator->setUrl('https://jakevan.ca/'); $creator->setDescription('Let\'s bring your idea to life.'); return $creator; } ); } return Cache::for('JakeVanCreator')->remember( 'full', function () { $creator = new LocalBusiness(); $creator->setName('JakeVan'); $creator->setId('https://jakevan.ca/#localbusiness'); $creator->setAlternateName(['Jake Vanderwerf', 'Rooted Romantic', 'Jacob Vanderwerf']); $creator->setUrl('https://jakevan.ca'); $creator->setSameAs([ 'https://bsky.app/profile/jakevan.ca', ]); $creator->setAreaServed(['Edmonton, Alberta', 'Alberta', 'Canada']); $offers = new OfferCatalog(); $offers->setName('Services'); $offers->setUrl('https://jakevan.ca/services'); $graphicDesign = new Service(); $graphicDesign->setName('Graphic Design'); $graphicDesign->setUrl('https://jakevan.ca/services/design/'); $graphicDesign->setDescription('From print to digital design.'); $websiteDesign = new Service(); $websiteDesign->setName('Development'); $websiteDesign->setUrl('https://jakevan.ca/services/development/'); $websiteDesign->setDescription('From basic websites to custom functionality.'); $strategy = new Service(); $strategy->setName('Strategy'); $strategy->setUrl('https://jakevan.ca/services/strategy/'); $strategy->setDescription('From developing your business plan to SEO.'); $art = new Service(); $art->setName('Art'); $art->setUrl('https://jakevan.ca/services/art/'); $art->setDescription('From unique, custom, handmade pieces to small-scale wholesale.'); $offers->setItemListElement([ $graphicDesign, $websiteDesign, $strategy, $art ]); $creator->setHasOfferCatalog($offers); return $creator; } ); } public function getOptionSchemaReference(string $option):mixed { if (!in_array(strtolower($option), array_merge( ['organization', 'website'], Registrar::getRegistered() ))) { error_log('Attempted to get schema reference for: '.$option.', but it does not exist'); return null; } $action = BASE.ucfirst($option).'Schema'; $stored = JVB()->schemaHelper()::reference($action); if (empty($stored)){ error_log('Attempted to get schema reference for: '.$option.', but defaults not set.'); return null; } $type = $stored['type']; if (!class_exists($type)){ error_log('Attempted to get schema reference, but class does not exist: '.$type); return null; } $class = new $type(); unset($stored['type']); $minimal = apply_filters($action.'Reference', ['name', 'url', 'sameAs', 'logo']); foreach ($minimal as $property) { $method = 'set'.ucfirst($property); $value = array_key_exists($property, $stored) ? $stored[$property] : null; if (!$value) {continue;} if (str_contains($value, '{{')) { $value = Resolver::resolve($property, $value); } $class->$method($value); } return $class; } public function buildOrganizationSchema():array { $config = JVB()->schemaHelper()::schema('organization'); $class = JVB()->schemaHelper()::classFromConfig($config); return ($class)? $class->outputSchema() : []; } }