Jake Vanderwerf
2026-04-15 c4aa5cdb5e90ad4b420e22772797d16980232a2b
inc/meta/MetaManager.php
@@ -2,6 +2,7 @@
namespace JVBase\meta;
use Exception;
use JVBase\registrar\Registrar;
if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
@@ -10,13 +11,16 @@
/**
 * Core meta management class
 */
/**
 * @deprecated Use Meta() now
 */
class MetaManager
{
   public MetaTypeManager $type_manager;
   public MetaValidator $validator;
   public MetaSanitizer $sanitizer;
   public MetaRenderer $renderer;
   public MetaForm $form;
   public Validator $validator;
   public Sanitizer $sanitizer;
   public Render $renderer;
   protected int|null $object_id;
   public object|null $data;
   protected array $fields =[];
@@ -25,6 +29,7 @@
   protected string|null $object_type;
   protected int $max_file_size = 5242880;
   protected ?string $content = null;
   protected bool $isTimeline = false;
   protected ?string $baseKey = null;
   protected \wpdb $wpdb;
@@ -63,13 +68,18 @@
         switch ($type) {
            case 'post':
               $this->data = get_post((string)$ID);
               $this->content = jvbNoBase($this->data->post_type);
               $registrar = Registrar::getInstance($this->content);
               $this->isTimeline = $registrar && $registrar->hasFeature('is_timeline');
               break;
            case 'term':
               $this->data = get_term($ID);
               $this->content = jvbNoBase($this->data->taxonomy);
               break;
            case 'user':
            case 'integrations':
               $this->data = get_user($ID);
               $this->content = jvbUserRole($ID);
               break;
            case 'options':
               $this->baseKey = $ID;
@@ -80,13 +90,11 @@
               break;
         }
      }
      $this->content = $content;
      $this->type_manager = new MetaTypeManager();
      $this->validator = new MetaValidator();
      $this->sanitizer = new MetaSanitizer();
      $this->renderer = new MetaRenderer();
      $this->form = new MetaForm();
      $this->validator = new Validator();
      $this->sanitizer = new Sanitizer();
      $this->renderer = new Render();
   }
   /**
@@ -254,7 +262,7 @@
    *
    * @return bool
    */
   public function updateValue(string $name, mixed $value): bool
   public function updateValue(string $name, mixed $value, bool $updatePost = true): bool
   {
      try {
         // Get field definition
@@ -268,7 +276,6 @@
         $field_config['name'] = $name;
         // Validate value
         if (!$this->validator->validate($value, $field_config)) {
            error_log('Validation unsuccessful');
            throw new Exception("Validation failed for {$name}");
         }
@@ -293,7 +300,8 @@
               if ($old !== $sanitized) {
                  switch ($this->object_type) {
                     case 'post':
                        $ID = wp_update_post([
                        $ID = jvb_update_post([
                           'ID' => $this->object_id,
                           $name => $sanitized
                        ]);
@@ -317,7 +325,7 @@
                        if ($name === 'display_name') {
                           $link = get_user_meta($this->object_id, BASE.'link', true);
                           if ($link !== '') {
                              wp_update_post([
                              jvb_update_post([
                                 'ID'  => $link,
                                 'post_title'   => $sanitized
                              ]);
@@ -333,7 +341,13 @@
         if ($field_config['type'] == 'taxonomy' && (!array_key_exists('taxonomy_type', $field_config))) {
            $set = wp_set_post_terms($this->object_id, $sanitized, jvbCheckBase($field_config['taxonomy']), false);
            if (empty(trim($sanitized))) {
               // Clear all terms when value is empty
               wp_set_object_terms($this->object_id, [], jvbCheckBase($field_config['taxonomy']), false);
            } else {
               $term_ids = array_map('intval', array_filter(explode(',', $sanitized)));
               wp_set_object_terms($this->object_id, $term_ids, jvbCheckBase($field_config['taxonomy']), false);
            }
         }
         if ($field_config['type'] === 'location' && empty($sanitized)) {
            $this->addMeta('has_map', false);
@@ -364,6 +378,12 @@
            throw new Exception("Failed to update meta value for {$name}");
         }
         if ($updatePost && $this->object_type === 'post') {
            //Flush the cache for this post.
            jvb_update_post([
               'ID'  => $this->object_id,
            ]);
         }
         return true;
      } catch (Exception $e) {
@@ -517,13 +537,14 @@
            $type = jvbUserRole((int)$this->object_id);
            break;
         case 'options':
            return jvbGetFields('options');
            return Registrar::getFieldsFor('options');
      }
      if (!$type) {
         return [];
      }
      return jvbGetFields($type, $this->object_type);
      $this->fields = Registrar::getFieldsFor($type);
      return $this->fields;
   }
   protected function getObjectType(): string|false
@@ -567,22 +588,9 @@
      if (!$type) {
         return [];
      }
      return jvbGetSections($type, $this->object_type);
      return Registrar::getInstance($type)->getSections()??[];
   }
    protected function getRegistry():mixed
    {
        switch ($this->object_type) {
            case 'post':
                return JVB_CONTENT[jvbNoBase(get_post_type((int)$this->object_id))]??null;
            case 'term':
                $term = get_term((int)$this->object_id);
                return JVB_TAXONOMY[jvbNoBase($term->taxonomy)]??null;
            case 'user':
                return JVB_USER;
        }
        return null;
    }
    /**
     * @param string $message
@@ -670,11 +678,11 @@
      $out = '';
        switch ($type) {
            case 'form':
                $out =  $this->form->render($name, $value, $config, $showHidden, true);
                $out =  Form::render($name, $value, $config);
            $out = apply_filters('jvbRenderFormMeta', $out, $name, $config, $value, $this->getObjectType());
            break;
            case 'render':
                $out = $this->renderer->render($name, $value, $config, true);
                $out = $this->renderer->render($name, $value, $config);
            if (empty($out) && !$hideEmpty) {
               $out = $this->getEmptyTemplate($config['type'], $name);
            }
@@ -707,26 +715,18 @@
      }
      if (empty($fields)) {
         $fields = ($this->content) ? jvbGetFields($this->content, $this->object_type) : $this->getFields();
         $fields = ($this->content) ? Registrar::getFieldsFor($this->content) : $this->getFields();
      }
      if ($sections !== false && empty($sections)) {
         $sections = ($this->content) ? jvbGetSections($this->content, $this->object_type) : $this->getSections();
         $sections = ($this->content) ? Registrar::getInstance($this->content)->getSections() : $this->getSections();
      }
      if (!empty($sections)){
         $tabs = [];
         foreach ($sections as $slug => $title) {
            $tabs[$slug] = [
               'title'  => $title,
               'content' => '',
               'description' => jvbSectionDescription($slug)??'',
            ];
            $icon = jvbSectionIcon($slug);
            if ($icon !== '') {
               $tabs[$slug]['icon'] = $icon;
            }
         foreach ($sections as $config) {
            $tabs[$config['slug']] = $config;
         }
      } else {
         $tabs = false;
@@ -930,7 +930,7 @@
      return false;
   }
   public function setAll(array $fields):bool
   public function setAll(array $fields, bool $updatePost = true):bool
   {
      if (empty($fields) || !$this->object_type) {
         return false;
@@ -940,6 +940,7 @@
         return false;
      }
      // Determine table based on object type
      $check = array_key_exists($this->object_type, $this->wpDefaults) ? $this->wpDefaults[$this->object_type] : [];
      switch ($this->object_type) {
@@ -983,7 +984,7 @@
      $temp = [];
      foreach ($setFields as $f) {
         $temp[$f] = $fields[$f];
         unset($fields[array_search($f, $fields)]);
         unset($fields[$f]);
      }
      $setFields = $temp;
@@ -999,12 +1000,18 @@
               // Sanitize value
               $sanitized = $this->sanitizer->sanitize($value, $field_config);
               if ($this->checkOverrides($field, $sanitized, $field_config)) {
                  return true;
                  continue;
               }
               if ($field_config['type'] === 'taxonomy' && !array_key_exists('taxonomy_type', $field_config)){
                  $term_ids = array_map('intval', explode(',', trim($sanitized)));
                  $set = wp_set_post_terms($this->object_id, $term_ids, jvbCheckBase($field_config['taxonomy']), false);
               if ($field_config['type'] == 'taxonomy' && (!array_key_exists('taxonomy_type', $field_config))) {
                  if (empty(trim($sanitized))) {
                     // Clear all terms when value is empty
                     wp_set_object_terms($this->object_id, [], jvbCheckBase($field_config['taxonomy']), false);
                  } else {
                     $term_ids = array_map('intval', array_filter(explode(',', $sanitized)));
                     wp_set_object_terms($this->object_id, $term_ids, jvbCheckBase($field_config['taxonomy']), false);
                  }
               }
               if ($field_config['type'] === 'location' && empty($sanitized)) {
@@ -1062,6 +1069,25 @@
         }
         if (!empty($setFields)) {
            foreach ($setFields as $field => $value) {
               $field_config = $this->getFieldConfig($field);
               if ($field_config) {
                  $setFields[$field] = $this->sanitizer->sanitize($value, $field_config);
               }
               if ($field === 'post_date') {
                  $datetime = strtotime($setFields[$field]);
                  if ($datetime !== false) {
                     $setFields[$field] = date('Y-m-d H:i:s', $datetime);
                  } else {
                     $setFields[$field] = date('Y-m-d H:i:s', time());
                  }
                  $setFields['post_date_gmt'] = get_gmt_from_date($setFields[$field]);
                  $setFields['edit_date'] = true;
               }
            }
            switch ($this->object_type) {
               case 'post':
                  if (array_key_exists('post_thumbnail', $setFields)) {
@@ -1070,7 +1096,7 @@
                  }
                  if (!empty($setFields)) {
                     $result = wp_update_post(array_merge(['ID' => $this->object_id], $setFields), true);
                     $result = jvb_update_post(array_merge(['ID' => $this->object_id], $setFields));
                  }
                  break;
               case 'user':
@@ -1081,6 +1107,9 @@
                  wp_update_term($this->object_id, $this->data->taxonomy, $setFields);
                  break;
            }
         } elseif ($updatePost && $this->object_type === 'post' && !empty($this->object_id)) {
            //Update the 'post modified' date with meta updates, for filtering
            jvb_update_post(['ID' => $this->object_id]);
         }
      } catch (Exception $e) {
@@ -1374,4 +1403,27 @@
         }
      }
   }
   private function getOrCreateTerm(string $termName, string $taxonomy):?int
   {
      $taxonomy = jvbCheckBase($taxonomy);
      $term = get_term_by('name', $termName, $taxonomy);
      if (!$term) {
         $result = wp_insert_term($termName, $taxonomy);
         if (is_wp_error($result)) {
            return null;
         }
         $termID = $result['term_id'];
      } else {
         $termID = $term->term_id;
      }
      if ($termID) {
         return $termID;
      }
      return null;
   }
}