Jake Vanderwerf
2026-01-20 7a9054bb3f033c98067b3196378311dae54c5fbf
inc/meta/MetaManager.php
@@ -19,41 +19,45 @@
   public MetaForm $form;
   protected int|null $object_id;
   public object|null $data;
   protected array $fields =[];
   protected string $field;
   protected mixed $value;
   protected string|null $object_type;
   protected int $max_file_size = 5242880;
   protected ?string $content = null;
   protected ?string $baseKey = null;
   protected \wpdb $wpdb;
   protected array $postFields = [
      'post_title',
      'post_excerpt',
      'post_content',
      'post_date',
      'post_status',
      'post_modified',
      'post_thumbnail'
   protected array $wpDefaults = [
      'post'   => [
         'post_title',
         'post_excerpt',
         'post_content',
         'post_date',
         'post_status',
         'post_modified',
         'post_thumbnail',
         'menu_order'
      ],
      'user'   => [
         'first_name',
         'last_name',
         'display_name',
         'description',
         'user_email',
      ],
      'term'   => [
         'term_name',
         'description'
      ]
   ];
   protected array $userFields = [
      'first_name',
      'last_name',
      'description',
      'display_name',
      'user_email',
   ];
   protected array $termFields = [
      'term_name',
      'description'
   ];
   public function __construct(?int $ID = null, ?string $type = null, ?string $content = null)
   public function __construct(int|string|null $ID = null, ?string $type = null, ?string $content = null)
   {
      global $wpdb;
      $this->wpdb = $wpdb;
      $this->object_id = $ID;
      $this->object_id = is_int($ID) ? $ID : null;
      $this->object_type = $type;
      if ($ID) {
         switch ($type) {
@@ -67,6 +71,10 @@
            case 'integrations':
               $this->data = get_user($ID);
               break;
            case 'options':
               $this->baseKey = $ID;
               $this->data = null;
               break;
            default:
               $this->data = null;
               break;
@@ -109,32 +117,22 @@
   public function getValue(string $name): mixed
   {
      //Get standard post fields first
      switch ($name) {
         case 'post_title':
            return $this->data->post_title ?? '';
         case 'post_excerpt':
            return $this->data->post_excerpt ?? '';
         case 'post_content':
            return $this->data->post_content ?? '';
         case 'featured_image':
         case 'post_thumbnail':
            return get_post_thumbnail_id($this->object_id);
         case 'display_name':
            if (is_null($this->data) || !$this->data->display_name) {
               $user = get_userdata((int)get_post_meta($this->object_id, BASE . 'link', true));
               return $user->display_name;
      if (array_key_exists($this->object_type, $this->wpDefaults)) {
         $defaults = $this->wpDefaults[$this->object_type];
         if (in_array($name, $defaults)) {
            if (in_array($name, ['featured_image', 'post_thumbnail'])) {
               return get_post_thumbnail_id($this->object_id);
            }
            return $this->data->display_name ?? '';
         case 'user_email':
            if (is_null($this->data) || !$this->data->display_name) {
               $user = get_userdata(get_post_meta($this->object_id, BASE . 'link', true));
               return $user->user_email;
            }
            return $this->data->user_email ?? '';
         case 'term_name':
            return htmlspecialchars_decode($this->data->name);
            return match ($this->object_type) {
               'term' => $this->getTermField($name),
               'post' => $this->getPostField($name),
               'user' => $this->getUserField($name),
               default => ''
            };
         }
      }
      $meta_key = BASE . $name;
      switch ($this->object_type) {
         case 'post':
@@ -145,12 +143,46 @@
         case 'integrations':
            return get_user_meta($this->object_id, $meta_key, true);
         case 'options':
            return get_option($meta_key);
            $key = $this->baseKey
               ? BASE . $this->baseKey . '_' . $name
               : BASE . $name;
            return get_option($key);
         default:
            return '';
      }
   }
   protected function getTermField(string $name): mixed
   {
      // WordPress handles entity decoding and filters
      return match ($name) {
         'term_name' => get_term_field('name', $this->object_id),
         'description' => get_term_field('description', $this->object_id),
         default => ''
      };
   }
   protected function getPostField(string $name): mixed
   {
      return match ($name) {
         'post_title' => get_the_title($this->object_id),
         'post_excerpt' => get_the_excerpt($this->object_id),
         'post_content' => get_post_field('post_content', $this->object_id),
         default => $this->data->$name ?? ''
      };
   }
   protected function getUserField(string $name): mixed
   {
      return match ($name) {
         'display_name' => get_the_author_meta('display_name', $this->object_id),
         'user_email' => get_the_author_meta('user_email', $this->object_id),
         'first_name' => get_the_author_meta('first_name', $this->object_id),
         'last_name' => get_the_author_meta('last_name', $this->object_id),
         default => $this->data->$name ?? ''
      };
   }
   /**
    * @param string $name
    *
@@ -246,97 +278,62 @@
            return true;
         }
         switch ($name) {
            case 'post_title':
         if (array_key_exists($this->object_type, $this->wpDefaults)) {
            $check = $this->wpDefaults[$this->object_type];
            if (in_array($name, $check)) {
               $ID = true;
               if ($this->data->post_title !== $sanitized) {
                  $ID = wp_update_post([
                     'ID' => $this->object_id,
                     'post_title' => $sanitized
                  ]);
               if (in_array($name, ['featured_image', 'post_thumbnail'])) {
                  $old = get_post_thumbnail_id($this->object_id);
                  if ($old !== $sanitized) {
                     $ID = set_post_thumbnail($this->object_id, $sanitized);
                  }
                  return $ID !== false;
               }
               return ($ID !== 0);
            case 'post_excerpt':
               $ID = true;
               if ($this->data->post_excerpt !== $sanitized) {
                  $ID = wp_update_post([
                     'ID' => $this->object_id,
                     'post_excerpt' => $sanitized
                  ]);
               }
               return ($ID !== 0);
            case 'post_content':
               $ID = true;
               if ($this->data->post_content !== $sanitized) {
                  $ID = wp_update_post([
                     'ID' => $this->object_id,
                     'post_content' => $sanitized
                  ]);
               }
               return ($ID !== 0);
            case 'featured_image':
            case 'post_thumbnail':
               $ID = true;
               $old = get_post_thumbnail_id($this->object_id);
               $old = $this->data->$name;
               if ($old !== $sanitized) {
                  $ID = set_post_thumbnail($this->object_id, $sanitized);
               }
               return ($ID !== false);
            case 'display_name':
               $ID = true;
               $object_id = $this->object_id;
               $displayName = $this->data->display_name;
               if (!$this->data->display_name) {
                  $user = get_userdata(get_post_meta($this->object_id, BASE . 'link', true));
                  $object_id = $user->ID;
                  $displayName = $user->display_name;
               }
                  switch ($this->object_type) {
                     case 'post':
                        $ID = wp_update_post([
                           'ID' => $this->object_id,
                           $name => $sanitized
                        ]);
                        break;
                     case 'term':
                        $data = [$name => $sanitized];
                        if ($name === 'term_name') {
                           $data['slug'] = sanitize_title($sanitized);
                        }
                        $ID = wp_update_term(
                           $this->data->term_id,
                           $this->data->taxonomy,
                           $data
                        );
                        break;
                     case 'user':
                        $ID = wp_update_user([
                           'ID'  => $this->object_id,
                           $name => $sanitized
                        ]);
                        if ($name === 'display_name') {
                           $link = get_user_meta($this->object_id, BASE.'link', true);
                           if ($link !== '') {
                              wp_update_post([
                                 'ID'  => $link,
                                 'post_title'   => $sanitized
                              ]);
                           }
                        }
               if ($displayName !== $sanitized) {
                  $ID = wp_update_user([
                     'ID' => $object_id,
                     'display_name' => $sanitized
                  ]);
                  $link = get_user_meta($object_id, BASE . 'link', true);
                  wp_update_post([
                     'ID' => $link,
                     'post_title' => $sanitized,
                  ]);
                        break;
                  }
               }
               return (!is_wp_error($ID));
            case 'user_email':
               $ID = true;
               $object_id = $this->object_id;
               $email = $this->data->user_email;
               if (!$this->data->display_name) {
                  $user = get_userdata(get_post_meta($this->object_id, BASE . 'link', true));
                  $object_id = $user->ID;
                  $email = $user->user_email;
               }
               if ($email !== $sanitized) {
                  $ID = wp_update_user([
                     'ID' => $object_id,
                     'user_email' => $sanitized
                  ]);
               }
               return (!is_wp_error($ID));
            case 'term_name':
               $ID = true;
               $name = $this->data->name;
               if ($name !== $sanitized) {
                  $ID = wp_update_term($this->data->term_id, $this->data->taxonomy, [
                     'name' => $sanitized,
                     'slug' => sanitize_title($sanitized)
                  ]);
               }
               return $ID !== false;
            }
         }
         if ($field_config['type'] == 'taxonomy' && (!array_key_exists('taxonomy_type', $field_config))) {
            error_log('Attempting to set taxonomies: ' . print_r($this->object_id, true));
            error_log('Sanitized data: ' . print_r($sanitized, true));
            error_log('Taxonomy: ' . print_r($field_config['taxonomy'], true));
            $set = wp_set_post_terms($this->object_id, $sanitized, jvbCheckBase($field_config['taxonomy']), false);
            error_log('Set post terms: ' . print_r($set, true));
         }
         if ($field_config['type'] === 'location' && empty($sanitized)) {
            $this->addMeta('has_map', false);
@@ -357,7 +354,10 @@
               $result = update_user_meta($this->object_id, $meta_key, $sanitized);
               break;
            case 'options':
               $result = update_option($meta_key, $sanitized);
               $key = $this->baseKey
                  ? BASE . $this->baseKey . '_' . $name
                  : BASE . $name;
               return update_option($key, $sanitized);
         }
         if ($result === false) {
@@ -502,6 +502,10 @@
   protected function getFields(): array
   {
      if (!empty($this->fields)) {
         return $this->fields;
      }
      $type = false;
      switch ($this->object_type) {
         case 'post':
            $type = get_post_type((int)$this->object_id);
@@ -515,6 +519,9 @@
         case 'options':
            return jvbGetFields('options');
      }
      if (!$type) {
         return [];
      }
      return jvbGetFields($type, $this->object_type);
   }
@@ -542,6 +549,7 @@
   protected function getSections():array
   {
      $type = false;
      switch ($this->object_type) {
         case 'post':
            $type = get_post_type((int)$this->object_id);
@@ -601,6 +609,11 @@
        }
    }
   public function setFieldConfig(array $fields):void
   {
      $this->fields = $fields;
   }
    protected function getFieldConfig(string $name):array|false
    {
        $fields = $this->getFields();
@@ -749,7 +762,7 @@
      }
      echo (jvbCheck('submit', $options)) ? '<button type="submit">'.jvbIcon('save').'Save</button>' : '';
      echo (jvbCheck('submit', $options)) ? '<button type="submit">'.jvbIcon('floppy-disk').'Save</button>' : '';
      echo '</form>';
        $out = ob_get_clean();
@@ -793,7 +806,7 @@
            $out = '<p class="'.$name.'">'.jvbIcon('calendar').'<span></span></p>';
            break;
         case 'time':
            $out = '<p class="'.$name.'">'.jvbIcon('time').'<time></time></p>';
            $out = '<p class="'.$name.'">'.jvbIcon('clock').'<time></time></p>';
            break;
         case 'true_false':
            $out = '<p class="'.$name.'"></p>';
@@ -802,9 +815,7 @@
            return '';
      }
      $out = apply_filters('jvbMetaTypeTemplate', $out, $type);
      return $out;
      return apply_filters('jvbMetaTypeTemplate', $out, $type);
   }
   public function getDefaultValue(string $type):mixed {
@@ -828,19 +839,7 @@
         return [];
      }
      switch ($this->object_type) {
         case 'user':
            $check = $this->userFields;
            break;
         case 'term':
            $check = $this->termFields;
            break;
         case 'post':
            $check = $this->postFields;
            break;
         default:
            $check = [];
      }
      $check = array_key_exists($this->object_type, $this->wpDefaults) ? $this->wpDefaults[$this->object_type] : [];
      $setFields = array_intersect($check, $fields);
      foreach ($setFields as $f) {
@@ -942,22 +941,20 @@
      }
      // Determine table based on object type
      $check = array_key_exists($this->object_type, $this->wpDefaults) ? $this->wpDefaults[$this->object_type] : [];
      switch ($this->object_type) {
         case 'post':
            $table = $this->wpdb->postmeta;
            $id_column = 'post_id';
            $check = $this->postFields;
            break;
         case 'term':
            $table = $this->wpdb->termmeta;
            $id_column = 'term_id';
            $check = $this->termFields;
            break;
         case 'user':
         case 'integrations':
            $table = $this->wpdb->usermeta;
            $id_column = 'user_id';
            $check = $this->userFields;
            break;
         case 'options':
            try {
@@ -1006,7 +1003,8 @@
               }
               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);
                  $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'] === 'location' && empty($sanitized)) {