Jake Vanderwerf
2026-08-30 87237f15618e2320967b9380c360b89f7323d2e9
inc/managers/SEO/BreadcrumbManager.php
@@ -2,8 +2,9 @@
namespace JVBase\managers\SEO;
use JVBase\managers\Cache;
use JVBase\managers\DirectoryManager;
use JVBase\registrar\Registrar;
use JVBase\utility\Features;
use JVBase\base\Site;
use WP_Post;
use WP_Term;
@@ -20,15 +21,21 @@
class BreadcrumbManager
{
   private Cache $cache;
   private Cache $termCache;
   private Cache $postCache;
   private Cache $userCache;
   private static ?self $instance = null;
   private static bool $hasDirectory;
   private static array $directories;
   private function __construct()
   {
      $this->cache = Cache::for('breadcrumbs', MONTH_IN_SECONDS)->connect('post')->connect('taxonomy')->connect('user');
      $this->cache->flush();
      if (JVB_TESTING) {
         $this->cache->flush();
      }
      $this->cache = Cache::for('breadcrumbs');
      $this->termCache = Cache::for('breadcrumbs_tax', 'term');
      $this->postCache = Cache::for('breadcrumbs_post', 'post');
      $this->userCache = Cache::for('breadcrumbs_user', 'user');
      self::$hasDirectory = Site::has('is_directory');
      self::$directories = self::$hasDirectory ? DirectoryManager::getInstance()->directories() : [];
   }
   public static function getInstance(): self
@@ -50,24 +57,21 @@
         return [];
      }
      switch (true) {
         case is_singular():
            $key = get_queried_object_id();
            break;
         case is_post_type_archive():
            $obj = get_queried_object();
            $key = $obj->name;
            break;
         case is_tax():
            $obj = get_queried_object();
            $key = $obj->taxonomy;
            break;
         default:
            $key = 'home';
            break;
      }
      return $this->cache->remember(
      $key = match(true) {
         is_singular() => get_queried_object_id(),
         is_tax() => get_queried_object()->term_id,
         is_post_type_archive() => get_queried_object()->name,
         default => 'home'
      };
      $cache = match(true) {
         is_singular()  => $this->postCache,
         is_tax()    => $this->termCache,
         is_author()    => $this->userCache,
         default        => $this->cache
      };
      return $cache->remember(
         $key,
         function() {
            $crumbs = $this->buildCrumbs();
@@ -91,9 +95,12 @@
      ];
      $obj = get_queried_object();
      if (is_null($obj)) {
         return $crumbs;
      }
      if (is_tax()) {
         $crumbs = $this->addTaxonomyCrumbs($crumbs, $obj);
      } elseif (is_singular()) {
      } elseif (is_singular() || is_home()) {
         $crumbs = $this->addArchiveCrumbs($crumbs, $obj);
         $hierarchy = $this->addSingularCrumbs($crumbs, $obj);
         $crumbs = $crumbs + $hierarchy;
@@ -117,10 +124,19 @@
            $content = is_array($registrar->registrar->for) ? $registrar->registrar->for[0] : $registrar->registrar->for;
            $contentRegistrar = Registrar::getInstance($content);
            $crumbs[] = [
               'name' => $contentRegistrar->getConfig('breadcrumbs')['title']??$contentRegistrar->getPlural(),
               'url'  => get_post_type_archive_link(jvbCheckBase($content)),
            ];
            if(self::$hasDirectory && $contentRegistrar && $contentRegistrar->hasFeature('show_directory')) {
               if (!empty(self::$directories[$content]??[])){
                  $crumbs[] = [
                     'name'   => self::$directories[$content]['title'],
                     'url' => self::$directories[$content]['url']
                  ];
               }
            } else {
               $crumbs[] = [
                  'name' => $contentRegistrar->getConfig('breadcrumbs')['title']??$contentRegistrar->getPlural(),
                  'url'  => get_post_type_archive_link(jvbCheckBase($content)),
               ];
            }
//          $crumbs[] = [
//             'name' => 'By ' . $registrar->getSingular(),
//             'url'  => false,
@@ -130,12 +146,14 @@
      // Add directory if exists
      if ($registrar && $registrar->hasFeature('directory')) {
         $directory = JVB()->directories()?->directories($tax);
         $crumbs[] = [
            'name' => $directory['title'],
            'url'  => $directory['url']
         ];
      if (self::$hasDirectory && $registrar && $registrar->hasFeature('show_directory')) {
         if (!empty(self::$directories[$tax]??[])) {
            $crumbs[] = [
               'name'   => self::$directories[$tax]['title'],
               'url' => self::$directories[$tax]['url']
            ];
         }
      }
      // Add term hierarchy
@@ -155,25 +173,15 @@
         $crumbConfig = $registrar->getConfig('breadcrumbs');
      }
      if($registrar && $registrar->hasFeature('show_directory')) {
         $directory = JVB()->directories()?->directories($content)??[];
         if (!empty($directory)) {
            $crumbs[] = [
               'name'   => $directory['title'],
               'url' =>$directory['url']
            ];
         }
      }
      // Handle directory posts specially
      if (JVB()->directories() && JVB()->directories()->isDirectory()) {
      if (self::$hasDirectory && DirectoryManager::getInstance()->isDirectory()) {
         $pos = jvbGetDirectoryInfo();
         if (!empty($pos)) {
            // Special case for map
            if ($pos['title'] == 'Map') {
               $crumbs[] = [
                  'name' => 'Tattoo Shops',
                  'url'  => JVB()->directories()?->directories(BASE.'shop')['url']
                  'url'  => DirectoryManager::getInstance()->directories(BASE.'shop')['url']??''
               ];
            }
@@ -199,21 +207,50 @@
    */
   private function addArchiveCrumbs(array $crumbs, object $obj): array
   {
      if (is_singular('page') || is_home()) {
         return $crumbs;
      }
      $type = is_singular() ? $obj->post_type : $obj->name;
      $name = jvbNoBase($type);
      $registrar = Registrar::getInstance($name);
      if (Features::forSite()->has('is_directory') && $name === 'directory') {
         $crumbs[] = [
            'name'   => JVB()->directories()->referAs(true),
            'url' => get_post_type_archive_link($type)
         ];
      } elseif (is_post_type_archive() && $registrar && $registrar->hasFeature('show_directory')) {
      if(self::$hasDirectory && $registrar && $registrar->hasFeature('show_directory')) {
         if (!empty(self::$directories[$name]??[])){
            $crumbs[] = [
               'name'   => self::$directories[$name]['title'],
               'url' => self::$directories[$name]['url']
            ];
         }
      } elseif (Site::has('is_directory') && $name === 'directory') {
         $crumbs[] = [
            'name' => $registrar->getConfig('breadcrumbs')['title'] ?? $registrar->getPlural(),
            'url'  => get_post_type_archive_link($type)
            'name'   => DirectoryManager::getInstance()->referAs(true),
            'url' => get_post_type_archive_link($type)
         ];
      } elseif ($registrar) {
         $crumbs[] = [
            'name'   => $registrar->getConfig('breadcrumbs')['title'] ?? $registrar->getPlural(),
            'url' => get_post_type_archive_link($type)
         ];
      } else {
         if (function_exists('is_shop') && is_shop()) {
            $ID = get_option( 'woocommerce_shop_page_id' );
            $crumbs[] = [
               'name'   => get_the_title($ID),
               'url' => get_the_permalink($ID)
            ];
         } else {
            $postTypeObject = get_post_type_object($type);
            $crumbs[] = [
               'name'   => $postTypeObject->label,
               'url' => get_post_type_archive_link($type)
            ];
         }
      }
      return $crumbs;
@@ -356,17 +393,6 @@
      ];
   }
   /**
    * Invalidate breadcrumb cache for specific object
    */
   public function invalidateCache(?int $objectId = null): void
   {
      if ($objectId) {
         $this->cache->forget($objectId);
      } else {
         $this->cache->flush();
      }
   }
   public function addTaxToCrumbs(array $crumbs, string|array $taxonomy):array
   {