From f859e64a57c624ff2daa2b21355f65a49fd4807d Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sat, 29 Aug 2026 03:09:12 +0000
Subject: [PATCH] =Some more tweaks. Mostly on the MenuBlock and adding the Meta.php to WooCommerce Products
---
inc/meta/Meta.php | 256 +++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 225 insertions(+), 31 deletions(-)
diff --git a/inc/meta/Meta.php b/inc/meta/Meta.php
index a6594a7..d929089 100644
--- a/inc/meta/Meta.php
+++ b/inc/meta/Meta.php
@@ -1,6 +1,7 @@
<?php
namespace JVBase\meta;
+use JVBase\base\Options;
use JVBase\registrar\Registrar;
use WP_Post;
use WP_Term;
@@ -17,9 +18,9 @@
*/
protected string $type;
/**
- * @var string the full slug, with BASE
+ * @var ?string the full slug, with BASE
*/
- protected string $slug;
+ protected ?string $slug;
protected string $contentType;
protected Item $item;
@@ -27,10 +28,10 @@
protected Validator $validator;
protected Sanitizer $sanitizer;
protected array $fields;
- protected WP_Post|WP_Term|WP_User|null $wpObject;
+ protected WP_Post|WP_Term|WP_User|false|null $wpObject;
protected int|string $ID;
protected MetaTypeManager $typeManager;
- protected static array $instances = ['post' => [],'term' => [], 'user'=>[],'options'=>[]];
+ protected static array $instances = ['post' => [],'term' => [], 'user'=>[],'option'=>[]];
protected array $defaults = ['post_thumbnail'];
/**
@@ -75,30 +76,30 @@
/**
* Create Meta instance for options
*/
- public static function forOptions(?string $baseKey = 'ajv'): self
+ public static function forOptions(?string $baseKey = BASE): self
{
- if (array_key_exists($baseKey, self::$instances['options'])) {
- return self::$instances['options'][$baseKey];
+ if (array_key_exists($baseKey, self::$instances['option'])) {
+ return self::$instances['option'][$baseKey];
}
- $new = new self($baseKey, 'options');
- self::$instances['options'][$baseKey] = $new;
+ $new = new self($baseKey, 'option');
+ self::$instances['option'][$baseKey] = $new;
return $new;
}
/***************************************************************
* Constructor
***************************************************************/
- public function __construct(int|string|null $id, string $type)
+ public function __construct(int|string|null $id, string $type, array $fields = [])
{
$this->validator = new Validator();
$this->sanitizer = new Sanitizer();
$this->typeManager = new MetaTypeManager();
$this->type = $type;
$this->ID = $id;
- $this->buildData($id, $type);
+ $this->buildData($id, $type, $fields);
}
- protected function buildData(int|string|null $id, string $type):void
+ protected function buildData(int|string|null $id, string $type, array $fields):void
{
$this->wpObject = match($type) {
'post' => get_post($id),
@@ -114,24 +115,173 @@
default => null
};
+ $registrar = !is_null($this->slug) ? Registrar::getInstance($this->slug) : false;
+ $fields = $registrar ? $registrar->getFields() : $fields;
-
- $registrar = Registrar::getInstance($this->slug);
- $fields = $registrar ? $registrar->getFields() : [];
+ if ($this->type == 'option') {
+ $options = Options::getInstance();
+ $fields = $options->getFields();
+ }
$meta = match($type) {
'post' => get_post_meta($id),
'term' => get_term_meta($id),
'user' => get_user_meta($id),
default => []
};
+ if (!$meta) {
+ $meta = [];
+ }
$meta = array_map(fn($value) => maybe_unserialize($value[0]), $meta);
+
+ $this->fields = [];
+
+ if (class_exists('WooCommerce') && $this->type === 'post' && $this->wpObject->post_type??'' === 'product') {
+ $fields['post_title'] = [
+ 'type' => 'text',
+ 'label' => 'Title',
+ ];
+ $fields['post_content'] = [
+ 'type' => 'text',
+ 'label' => 'Content',
+ ];
+ $fields['post_excerpt'] = [
+ 'type' => 'text',
+ 'label' => 'Short Description',
+ ];
+ $fields['ID'] = [
+ 'type' => 'text',
+ 'label' => 'ID',
+ ];
+
+
+ $fields['_stock'] = [
+ 'type' => 'number',
+ 'label' => 'Stock',
+ 'default' => null
+ ];
+ $fields['_stock_status'] = [
+ 'type' => 'select',
+ 'label' => 'Stock Status',
+ 'default' => 'instock',
+ 'options' => [
+ 'instock' => 'In Stock',
+ 'outofstock' => 'Out of Stock',
+ 'onbackorder' => 'On Backorder'
+ ]
+ ];
+ $fields['_price'] = [
+ 'type' => 'text',
+ 'subtype' => 'number',
+ 'label' => 'Price'
+ ];
+
+
+ $product = wc_get_product($id);
+
+ $fields['sku'] = [
+ 'type' => 'text',
+ 'label' => 'SKU',
+ ];
+
+ $out = [];
+ if ($product && $product->is_type('variable')) {
+ $var = $product->get_children();
+ $var = array_filter(array_map(function($v) {
+ return wc_get_product($v);
+ }, $var));
+
+ $title= $product->get_title();
+ foreach ($var as $variation) {
+ $out[] = [
+ 'id' => $variation->get_id(),
+ 'sku' => $variation->get_sku(),
+ 'title' => str_replace($title.' - ', '', $variation->get_name()),
+ 'price' => $variation->get_price(),
+ 'description'=> $variation->get_short_description(),
+ 'sale' => $variation->get_sale_price(),
+ 'img' => $variation->get_image_id(),
+ 'stock' => $variation->get_stock_quantity(),
+ 'stock_status' => $variation->get_stock_status()
+ ];
+ }
+ }
+ if (!empty($out)) {
+ $this->fields['variations'] = new Field('variations', $out, [
+ 'type' => 'repeater',
+ 'label' => 'Variations',
+ 'fields' => [
+ 'id' => [
+ 'type' => 'text',
+ 'subtype' => 'number',
+ 'label' => 'Variation ID',
+ ],
+ 'sku' => [
+ 'type' => 'text',
+ 'label' => 'Stock Keeping Unit (SKU)'
+ ],
+ 'title' => [
+ 'type' => 'text',
+ 'label' => 'Variation Title'
+ ],
+ 'price' => [
+ 'type' => 'text',
+ 'subtype' => 'number',
+ 'label' => 'Variation Price'
+ ],
+ 'sale' => [
+ 'type' => 'text',
+ 'subtype' => 'number',
+ 'label' => 'Sale Price',
+ ],
+ 'image' => [
+ 'type' => 'text',
+ 'subtype' => 'number',
+ 'label' => 'Variation Image ID'
+ ],
+ 'stock' => [
+ 'type' => 'text',
+ 'label' => 'Stock Quantity'
+ ],
+ 'stock_status' => [
+ 'type' => 'text',
+ 'label' => 'Stock Status'
+ ]
+ ]
+ ]);
+ }
+
+
+ }
foreach ($fields as $fieldName => $config) {
$fieldName = jvbNoBase($fieldName);
- if ($this->wpObject && property_exists($this->wpObject, $fieldName)) {
+ $value = '';
+ if ($this->type === 'option') {
+ $value = get_option(BASE . $fieldName, $config['default'] ?? '');
+ } else if ($this->wpObject && $this->wpObject->post_type === 'product') {
+ if (property_exists($this->wpObject, $fieldName)) {
+ $value = $this->wpObject->$fieldName;
+ } else {
+ $product = wc_get_product($this->wpObject->ID);
+ $value = match ($fieldName) {
+ 'sku' => $product->get_sku(),
+ '_price' => $product->get_price(),
+ 'description'=> $product->get_short_description(),
+ 'sale' => $product->get_sale_price(),
+ 'img' => $product->get_image_id(),
+ '_stock' => $product->get_stock_quantity(),
+ '_stock_status' => $product->get_stock_status(),
+ default => '',
+ };
+ }
+
+ } else if (
+ ($this->wpObject && property_exists($this->wpObject, $fieldName))
+ || ($type === 'user' && $this->wpObject && property_exists($this->wpObject->data, $fieldName))) {
$config['wp'] = true;
$value = $this->wpObject->$fieldName;
- } else if (in_array($fieldName, $this->defaults)) {
+
+ } else if (in_array($fieldName, $this->defaults)) {
$config['wp'] = true;
switch ($fieldName) {
case 'post_thumbnail':
@@ -192,8 +342,20 @@
if (str_contains($name, ':')) {
return $this->getByPath($name);
}
-
- return $this->fields[$name]->get();
+ // Group shortcut path
+ if (str_contains($name, '|')) {
+ [$parent, $child] = explode('|', $name, 2);
+ return $this->group($parent)->get($child);
+ }
+ if (!array_key_exists($name, $this->fields)) {
+ error_log('[Meta]::get Attempted to get unregistered field: '.$name);
+ return '';
+ }
+ if (is_null($this->fields[$name])) {
+ error_log('[Meta]::get Field does not seem to be setup yet: '.$name);
+ return '';
+ }
+ return $this->fields[$name]->get()??'';
}
/**
@@ -206,6 +368,11 @@
return $this->setByPath($name, $value);
}
+ // Group shortcut
+ if (str_contains($name, '|')) {
+ return $this->setGroup($name, $value, $autosave);
+ }
+
$field = $this->fields[$name]??false;
if (!$field) {
error_log('No config found for field: '.$name);
@@ -312,12 +479,12 @@
}
break;
case 'term':
- $result = wp_update_term($this->ID, $this->slug, $defaults);
+ $termDefaults = array_map(fn($field) => $field->value, $defaults);
+ $result = wp_update_term($this->ID, $this->slug, $termDefaults);
break;
case 'user':
- $data = array_merge([
- 'ID' => $this->ID
- ], $defaults);
+ $userDefaults = array_map(fn($field) => $field->value, $defaults);
+ $data = array_merge(['ID' => $this->ID], $userDefaults);
$result = wp_update_user($data);
break;
}
@@ -330,7 +497,7 @@
'post' => 'update_post_meta',
'term' => 'update_term_meta',
'user' => 'update_user_meta',
- 'options', 'option' => 'update_option',
+ 'option' => 'update_option',
default => false,
};
if (!$function) {
@@ -338,14 +505,20 @@
return false;
}
foreach ($custom as $field) {
- $result = $function($this->ID, BASE.$field->name, $field->value);
+ if ($this->type === 'option') {
+ $result = update_option(BASE.$field->name, $field->value);
+ } else {
+ $result = $function($this->ID, BASE.$field->name, $field->value);
+ }
+
if (!$result) {
error_log('Problem saving field: '.$field->name.' with value: '.print_r($field->value, true));
}
}
- if ($this->type === 'term' && Registrar::getInstance($this->slug)->hasFeature('is_content')) {
- update_term_meta($this->ID, BASE.'date_modified', date('Y-m-d H:i:s'));
- }
+ //Now handled directly from Registrar
+// if ($this->type === 'term' && Registrar::getInstance($this->slug)->hasFeature('is_content')) {
+// update_term_meta($this->ID, BASE.'date_modified', date('Y-m-d H:i:s'));
+// }
}
@@ -372,7 +545,7 @@
'post' => delete_post_meta($this->ID, BASE.$name),
'term' => delete_term_meta($this->ID, BASE.$name),
'user', 'integrations' => delete_user_meta($this->ID, BASE.$name),
- 'options' => delete_option(BASE.$name),
+ 'option' => delete_option(BASE.$name),
default => false
};
}
@@ -403,9 +576,9 @@
return new Repeater($this, $name);
}
+
protected function setByPath(string $path, mixed $value): self
{
- error_log('Setting by path: '.$path.', with value: '.print_r($value, true));
$parts = explode(':', $path, 3);
if (count($parts) !== 3) {
return $this;
@@ -428,6 +601,22 @@
return $this->repeater($repeaterName)->field((int) $rowIndex, $subField);
}
+
+
+ public function group(string $name): Group
+ {
+ return new Group($this, $name);
+ }
+
+ protected function setGroup(string $name, mixed $value, bool $autosave = true): self
+ {
+ $parent = strtok($name, '|');
+ $child = str_replace($parent . '|', '', $name);
+
+ $this->group($parent)->set($child, $value, $autosave);
+ return $this;
+ }
+
// ─────────────────────────────────────────────────────────────
// Utility Methods
// ─────────────────────────────────────────────────────────────
@@ -476,6 +665,11 @@
return $this->contentType;
}
+ public function item():Item
+ {
+ return $this->item;
+ }
+
// ─────────────────────────────────────────────────────────────
// Protected Helpers
@@ -512,7 +706,7 @@
/**
* Get default value for a field type
*/
- protected function getDefaultValue(string $name): mixed
+ protected function getDefaultValue(string $name): string|int|bool|array
{
$config = $this->item->getFieldConfig($name);
$type = $config['type'] ?? 'text';
--
Gitblit v1.10.0