From 2127b1bdd73ecd2423e443992da4b442f5a3c1a3 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Wed, 04 Feb 2026 21:19:25 +0000
Subject: [PATCH] =Major overhaul of MetaManager.php -> Meta.php and RestRouteManager.php -> Rest.php. Seems to work for JakeVan
---
inc/meta/MetaManager.php | 397 ++++++++++++++++++++++++++++++++------------------------
1 files changed, 229 insertions(+), 168 deletions(-)
diff --git a/inc/meta/MetaManager.php b/inc/meta/MetaManager.php
index a1d7dbc..4fe121f 100644
--- a/inc/meta/MetaManager.php
+++ b/inc/meta/MetaManager.php
@@ -1,7 +1,10 @@
<?php
namespace JVBase\meta;
+use DateTime;
use Exception;
+use JVBase\utility\Features;
+use WP_Post;
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
@@ -10,13 +13,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,61 +31,71 @@
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;
- 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) {
case 'post':
$this->data = get_post((string)$ID);
+ $this->content = jvbNoBase($this->data->post_type);
+ $this->isTimeline = Features::forContent($this->content)->has('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;
+ $this->data = null;
break;
default:
$this->data = null;
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();
}
/**
@@ -110,32 +126,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':
@@ -146,12 +152,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
*
@@ -223,7 +263,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
@@ -237,7 +277,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}");
}
@@ -247,93 +286,69 @@
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':
- 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,
- ]);
- }
- return (!is_wp_error($ID));
- case 'user_email':
- $ID = true;
+ $ID = jvb_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 !== '') {
+ jvb_update_post([
+ 'ID' => $link,
+ 'post_title' => $sanitized
+ ]);
+ }
+ }
- $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;
+ break;
+ }
}
- 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))) {
- $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);
@@ -354,13 +369,22 @@
$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) {
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) {
@@ -520,7 +544,8 @@
return [];
}
- return jvbGetFields($type, $this->object_type);
+ $this->fields = jvbGetFields($type, $this->object_type);
+ return $this->fields;
}
protected function getObjectType(): string|false
@@ -667,11 +692,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);
}
@@ -812,9 +837,7 @@
return '';
}
- $out = apply_filters('jvbMetaTypeTemplate', $out, $type);
-
- return $out;
+ return apply_filters('jvbMetaTypeTemplate', $out, $type);
}
public function getDefaultValue(string $type):mixed {
@@ -838,19 +861,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) {
@@ -941,7 +952,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;
@@ -951,23 +962,22 @@
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) {
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 {
@@ -996,7 +1006,7 @@
$temp = [];
foreach ($setFields as $f) {
$temp[$f] = $fields[$f];
- unset($fields[array_search($f, $fields)]);
+ unset($fields[$f]);
}
$setFields = $temp;
@@ -1012,12 +1022,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)) {
@@ -1075,6 +1091,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)) {
@@ -1083,7 +1118,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':
@@ -1094,6 +1129,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) {
@@ -1387,4 +1425,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;
+ }
}
--
Gitblit v1.10.0