Jake Vanderwerf
3 days ago ba1e1ccf869b818f7a7a897264dfea05563a7796
inc/managers/SEO/render/SchemaOutput.php
@@ -1,10 +1,9 @@
<?php
namespace JVBase\managers\SEO\render;
use JVBase\inc\managers\SEO\render\Thing\Intangible\ItemList\OfferCatalog;
use JVBase\managers\Cache;
use JVBase\managers\SEO\BreadcrumbManager;
use JVBase\managers\SEO\render\Thing\CreativeWork\WebSite;
use JVBase\managers\SEO\render\Thing\Intangible\OfferCatalog;
use JVBase\managers\SEO\render\Thing\Intangible\Service;
use JVBase\managers\SEO\render\Thing\Organization\LocalBusiness\LocalBusiness;
use JVBase\registrar\config\seo\Resolver;
@@ -23,13 +22,23 @@
   public function buildSchema():array
   {
      $schema = [];
      if (!is_front_page()) {
         $schema[] = $this->buildBasicWebsiteSchema();
      $registrar = false;
      if (is_front_page()) {
         $schema[] = $this->buildWebsiteSchema(true);
         $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']??[])) {
         $function = BASE.'build_singular_'.jvbNoBase($type).'_schema';
         if (function_exists($function)) {
            $schema = $function(get_the_ID());
         } else if ($registrar) {
            $seo = $registrar->getSEO();
            $schema[] = $seo->schema()->outputSingularSchema();
         }
@@ -39,7 +48,7 @@
         $type = $type->name;
         $registrar = Registrar::getInstance($type);
         if ($registrar && !empty($registrar->getConfig('seo')['schema']??[])) {
         if ($registrar) {
            $seo = $registrar->getSEO();
            $schema[] =$seo->schema()->outputArchiveSchema();
         }
@@ -47,11 +56,33 @@
         $type = get_queried_object();
         $type = jvbNoBase($type->taxonomy);
         $registrar = Registrar::getInstance($type);
         if ($registrar && !empty($registrar->getConfig('seo')['schema']??[])) {
         if ($registrar ) {
            $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::withFeature('is_content', 'term'))));
      if (!empty($isContent) && is_page($isContent)){
         $type = get_post_meta(get_the_id(), BASE.'for_type', true);
//       error_log('Type: '.print_r($type, true));
         if (!empty($type)) {
            $registrar = Registrar::getInstance($type);
            if ($registrar) {
               $schema[] = $registrar->getSEO()->schema()->outputContentTaxArchiveSchema();
            }
         }
      }
      if ($registrar && !empty($registrar->getSEO()->schema()->extra())) {
         $schema = array_merge($schema, $registrar->getSEO()->schema()->extra());
      }
      $breadcrumbs = $this->buildBreadcrumbs();
      if ($breadcrumbs) {
@@ -59,39 +90,47 @@
      }
      if (!empty($schema)) {
         $website = get_option(BASE.'WebsiteSchema');
         if (!empty($website)) {
            Cache::for('websiteSchema')->flush();
            $website = Cache::for('websiteSchema')->remember(
               'schema',
               function () {
                  return $this->websiteSchema();
         if (!is_front_page()) {
            $website = JVB()->schemaHelper()::schema('website');
            if (!empty($website)) {
               if (JVB_TESTING) {
                  Cache::for('websiteSchema')->flush();
               }
            );
            array_unshift($schema, $website);
               $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 = get_option(BASE.'WebsiteSchema', apply_filters(BASE.'WebsiteSchema', []));
      $stored = JVB()->schemaHelper()::schema('website');
      $website = JVB()->schemaHelper()::classFromConfig($stored);
      $seo = new WebSite();
      foreach ($stored as $property => $value) {
         $method = 'set'.ucfirst($property);
         $seo->$method($value);
      if (!$website->getUrl() || empty($website->getUrl())){
         $website->setUrl(get_home_url());
      }
      $seo->setUrl(get_home_url());
      $seo->setName(get_bloginfo('name'));
      $seo->setCreator($this->getCreator());
      return $seo->outputSchema();
      if (!$website->getName() || empty($website->getName())){
         $website->setName(get_bloginfo('name'));
      }
      if(!$website->getCreator() || empty($website->getCreator(true))) {
         $website->setCreator($this->getCreator(true));
      }
      return $website->outputSchema();
   }
   public function outputSchema():void
@@ -100,10 +139,19 @@
      if (empty($schema)) {
         return;
      }
//    $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);
      if ($encoded === false) {
         error_log('wp_json_encode failed: ' . json_last_error_msg());
         return;
      }
      echo "\n<!-- SEO Schema by JakeVan -->\n";
      echo '<script type="application/ld+json">' . "\n";
      echo wp_json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
      echo $encoded;
      echo "\n" . '</script>' . "\n";
      echo "\n" . '<!-- / SEO Schema by JakeVan -->'."\n";
   }
   public function buildBreadcrumbs():array
@@ -111,20 +159,75 @@
      return BreadcrumbManager::getInstance()->toSchema();
   }
   public function buildBasicWebsiteSchema():array
   {  Cache::for('websiteSchema')->flush();
   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(
         'reference',
         function () {
            $website = new WebSite();
            $website->setName(get_bloginfo('name'));
            $website->setUrl(get_home_url());
            $website->setId(get_home_url().'/#website');
            $website->setDescription(get_bloginfo('description'));
            $website->setInLanguage('en-CA');
            $publisher = $this->getOptionSchemaReference('organization');
            if ($publisher){
               $website->setPublisher($publisher);
         'full',
         function () use ($storedWebsite) {
            $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));
@@ -135,68 +238,78 @@
   }
   public function getCreator(bool $reference = false):LocalBusiness
   public function getCreator(bool $reference = false, bool $jakeVan = false):LocalBusiness
   {
      Cache::for('JakeVanCreator')->flush();
      if ($reference) {
      if (JVB_TESTING){
         Cache::for('JakeVanCreator')->flush();
      }
      if ($reference && $jakeVan) {
         return Cache::for('JakeVanCreator')->remember(
            'reference',
            function () {
               $creator = new LocalBusiness();
               $creator->setId('jakevan');
               $creator->setName('JakeVan');
               $creator->setAlternateName('Jake Vanderwerf');
               $creator->setUrl('https://jakevan.ca/');
               $creator->setDescription('Let\'s bring your idea to life.');
               return $creator;
            }
         );
      }
      if ($jakeVan) {
         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');
      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.');
            $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
            ]);
               $offers->setItemListElement([
                  $graphicDesign,
                  $websiteDesign,
                  $strategy,
                  $art
               ]);
            $creator->setHasOfferCatalog($offers);
            return $creator;
         }
      );
               $creator->setHasOfferCatalog($offers);
               return $creator;
            }
         );
      }
      if ($reference) {
         return $this->getOptionSchemaReference('organization');
      }
      $config = JVB()->schemaHelper()::schema('organization');
      return JVB()->schemaHelper()::classFromConfig($config);
   }
   public function getOptionSchemaReference(string $option):mixed
@@ -209,9 +322,9 @@
         error_log('Attempted to get schema reference for: '.$option.', but it does not exist');
         return null;
      }
      $action = BASE.ucfirst($option).'Schema';
      $stored = get_option($action, apply_filters($action, []));
//    $stored = get_option($action, apply_filters($action, jvbDefaultSchema($option)));
      $stored = JVB()->schemaHelper()::reference($option);
      if (empty($stored)){
         error_log('Attempted to get schema reference for: '.$option.', but defaults not set.');
         return null;
@@ -223,16 +336,28 @@
      }
      $class = new $type();
      unset($stored['type']);
      $minimal = apply_filters($action.'Reference', ['name', 'url', 'sameAs', 'logo']);
      $minimal = apply_filters(BASE.'OrganizationReference', ['name', 'url', 'sameAs', 'logo']);
      foreach ($minimal as $property) {
         $method = 'set'.ucfirst($property);
         $value = array_key_exists($property, $stored) ? $stored[$property] : null;
         if (!$value) {continue;}
         $class->$method(Resolver::resolve($property, $value));
         if (str_contains($value, '{{')) {
            $meta = null;
            $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() : [];
   }
}