Jake Vanderwerf
2026-03-29 275c0d74cd68677622a5431505c5c870c473063d
inc/rest/Rest.php
@@ -2,6 +2,7 @@
namespace JVBase\rest;
use JVBase\managers\Cache;
use JVBase\meta\Meta;
use JVBase\registrar\Registrar;
use JVBase\utility\Features;
use WP_REST_Request;
@@ -89,6 +90,21 @@
   // CACHE MANAGEMENT
   // =========================================================================
   protected function checkCache(string $key, $request):WP_REST_Response|false
   {
      // Check HTTP cache headers with the specific content type
      $cache_check = $this->checkHeaders($request, $key);
      if ($cache_check) {
         return $cache_check;
      }
      $cache = $this->cache->get($key);
      if ($cache) {
         $response = Response::success($cache);
         return $this->addCacheHeaders($response);
      }
      return false;
   }
   /**
    * Check request headers for conditional caching (ETag, If-Modified-Since)
    */
@@ -517,6 +533,9 @@
   ***************************************************************************/
   protected function isTimeline($args, $data):bool
   {
      if (!array_key_exists('post_type', $args)) {
         return false;
      }
      $post_types = is_array($args['post_type']) ? $args['post_type'] : [$args['post_type']];
      $hasTimeline = array_map(function($item) { return jvbCheckBase($item); },Registrar::getFeatured('is_timeline', 'post'));
      return !empty(array_intersect($post_types, $hasTimeline));
@@ -712,4 +731,177 @@
      delete_user_meta($user_id, BASE . 'session_fingerprint');
      delete_user_meta($user_id, BASE . 'session_timestamp');
   }
   /*******************************
    * META HELPERS
   *******************************/
   public function getFieldsOfType(array $fields, string|array $type, Meta $meta, array $subType = []):array
   {
      $gotFields = [];
      if (is_string($type)) {
         $type = [$type];
      }
      foreach ($fields as $field => $value) {
         //Skip empty values
         if (empty($value)) {
            continue;
         }
         $config = $meta->config($field);
         if (in_array($config['type'], ['group', 'repeater', 'tagList'])) {
            foreach ($config['fields'] as $subfield => $subConfig) {
               if (is_numeric($subfield) && array_key_exists('name', $subConfig)) {
                  $subfield = $subConfig['name'];
               }
               if (is_numeric($subfield)) continue;
               if (array_key_exists('type', $subConfig) && in_array($subConfig['type'], $type)) {
                  $gotFields[] = $field.':'.$subfield;
               }
            }
         } elseif (in_array($config['type'], $type)) {
            $gotFields[] = $field;
         } else if ((!empty($subType) && in_array($config['type'], array_keys($subType)) && in_array($config['subtype'], array_values($subType)))) {
            $gotFields[] = $field;
         }
      }
      return $gotFields;
   }
   protected function extractImages(array $fields, Meta $meta):array
   {
      $images = [];
      $get = $this->getFieldsOfType($fields, ['upload', 'gallery','image'], $meta);
      if (!empty($get)) {
         $baseFields = array_map(function($fieldName) {
            return (str_contains($fieldName, ':')) ? strtok($fieldName, ':') : $fieldName;
         }, $get);
         $temp = array_map(
            function($item) {
               return explode(':', $item);
            },
            array_filter($get, function($fieldName) {
               return str_contains($fieldName, ':');
            })
         );
         $complex = [];
         foreach ($temp as $tmp) {
            $complex[$tmp[0]] = $tmp[1];
         }
         $fields = array_filter($fields, function ($field) use ($baseFields) {
            return in_array($field, $baseFields);
         }, ARRAY_FILTER_USE_KEY);
         foreach ($fields as $fieldName => $value) {
            //Check if it's a complex field
            if (array_key_exists($fieldName, $complex)) {
               $check = $complex[$fieldName];
               foreach ($value as $row) {
                  foreach ($row as $fName => $fValue) {
                     if ($fName === $check && !empty($fValue)) {
                        $images = $this->addImages($fValue, $images);
                     }
                  }
               }
            } else {
               $images = $this->addImages($value, $images);
            }
         }
      }
      return $images;
   }
   public function addImages(string $imgs, array $images):array
   {
      $temp = explode(',', $imgs);
      foreach ($temp as $img) {
         if (is_numeric($img) && !array_key_exists($img, $images) && $img > 0) {
            $images[$img] = jvbImageData((int)$img);
         }
      }
      return $images;
   }
   protected function extractTerms(array $fields, Meta $meta):array
   {
      $terms = [];
      $get = $this->getFieldsOfType($fields, ['taxonomy'], $meta, ['selector' => 'taxonomy']);
      if (!empty($get)) {
         $baseFields = array_map(function($fieldName) {
            return (str_contains($fieldName, ':')) ? strtok($fieldName, ':') : $fieldName;
         }, $get);
         $complex = array_map(
            function($item) {
               return explode(':', $item);
            },
            array_filter($get, function($fieldName) {
               return str_contains($fieldName, ':');
            })
         );
         $fields = array_filter($fields, function ($field) use ($baseFields) {
            return in_array($field, $baseFields);
         }, ARRAY_FILTER_USE_KEY);
         foreach ($fields as $fieldName => $value) {
            $config = $meta->config($fieldName);
            //Check if it's a complex field
            if (array_key_exists($fieldName, $complex)) {
               foreach ($value as $row) {
                  foreach ($row as $fName => $fValue) {
                     if (in_array($fName, $complex[$fieldName])) {
                        $terms = $this->addTerms($fValue, $terms, $config);
                     }
                  }
               }
            } else {
               $terms = $this->addTerms($value, $terms, $config);
            }
         }
      }
      return $terms;
   }
   protected function addTerms(string $value, array $terms, array $config):array
   {
      $taxonomy = jvbNoBase($config['taxonomy']);
      if (empty($value)) {
         return $terms;
      }
      $ids = array_map('absint', explode(',',$value));
      $cache = Cache::for('term_data')->connect('taxonomy');
      $cache->flush();
      if (!array_key_exists($taxonomy, $terms)) {
         $terms[$taxonomy] = [];
         $registrar = Registrar::getInstance($taxonomy);
         $terms[$taxonomy]['icon'] = $registrar ? $registrar->getIcon() : jvbDefaultIcon();;
      }
      foreach ($ids as $id) {
         $data = $cache->remember(
            $id,
            function () use ($id, $taxonomy) {
               $term = get_term($id, $taxonomy);
               if ($term && !is_wp_error($term)) {
                  return [
                     'id'  => $term->term_id,
                     'name'   => $term->name,
                     'slug'   => $term->slug,
                     'parent' => $term->parent,
                     'path'   => JVB()->routes('term')->getTermPath($term->term_id, $term->name, $taxonomy),
                     'taxonomy'  => jvbNoBase($term->taxonomy),
                     'count'  => $term->count,
                  ];
               }
               return [];
            }
         );
         if (!empty($data)) {
            $terms[$taxonomy][$id] = $data;
         }
      }
      return $terms;
   }
}