<?php
|
namespace JVBase\meta;
|
|
use InvalidArgumentException;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
|
class Registry
|
{
|
protected string $object; // post type or taxonomy slug
|
protected string $object_type; // post, term, user
|
protected array $fields;
|
protected string $prefix = BASE;
|
|
public function __construct(array $fields, string $object, string $object_type)
|
{
|
if (!in_array($object_type, ['post', 'term', 'user'])) {
|
return;
|
}
|
|
$this->fields = $fields;
|
$this->object = jvbCheckBase($object);
|
$this->object_type = $object_type;
|
}
|
|
public function registerMetaFields(): void
|
{
|
$fields = $this->fields;
|
|
foreach ($fields as $name => $options) {
|
if (in_array($name, [
|
'post_title',
|
'post_content',
|
'post_excerpt',
|
'featured_image',
|
'display_name',
|
'user_email',
|
])) {
|
unset($fields[$name]);
|
}
|
}
|
|
foreach ($fields as $field_name => $field) {
|
$this->validateFieldType($field_name, $field);
|
$field = array_merge(MetaTypeManager::getType($field['type']), $field);
|
$args = $this->getFieldArgs($field_name, $field);
|
|
$args = apply_filters(
|
BASE . 'meta_field_args',
|
$args,
|
$field_name,
|
$field,
|
$this->object_type
|
);
|
|
$temp = register_meta($this->object_type, $this->prefix . $field_name, $args);
|
|
if (!$temp) {
|
$args['auth_callback'] = gettype($args['auth_callback']);
|
error_log('Error with registering meta:' . print_r([
|
'object_type' => $this->object_type,
|
'prefix' => $this->prefix,
|
'field_name' => $field_name,
|
'args' => $args,
|
], true));
|
}
|
|
do_action(BASE . 'meta_field_registered', $field_name, $field, $this);
|
}
|
}
|
|
protected function validateFieldType(string $field_name, array $field): void
|
{
|
$required = ['name', 'type', 'label'];
|
$field['name'] = $field_name;
|
foreach ($required as $type) {
|
if (!isset($field[$type])) {
|
throw new InvalidArgumentException(sprintf('Field %s is required', $type));
|
}
|
}
|
}
|
|
protected function getFieldArgs(string $field_name, array $field): array
|
{
|
$args = [
|
'object_subtype' => $this->object,
|
'type' => MetaTypeManager::getMetaType($field['type']),
|
'label' => __($field['label'], 'jvb') ?? '',
|
'description' => __($field['description'] ?? '', 'jvb'),
|
'single' => true,
|
'show_in_rest' => $field['show_in_rest'] ?? true,
|
'sanitize_callback' => $this->getSanitizeCallback($field),
|
'auth_callback' => [$this, 'validate_permissions'],
|
'default' => $field['default'] ?? '',
|
];
|
|
if ($this->object_type === 'post') {
|
$args['revisions_enabled'] = true;
|
}
|
|
if (in_array($field['type'], ['repeater', 'group', 'location']) || $args['type'] === 'array') {
|
$args['show_in_rest'] = [
|
'schema' => $this->getFieldSchema($field)
|
];
|
}
|
|
return $args;
|
}
|
|
/**
|
* Build sanitize callback for register_meta
|
*/
|
protected function getSanitizeCallback(array $field): callable
|
{
|
return fn($value) => Sanitizer::sanitize($value, $field);
|
}
|
|
protected function getFieldSchema(array $field): array
|
{
|
if ($field['type'] === 'repeater') {
|
$properties = [];
|
foreach ($field['fields'] as $key => $subfield) {
|
$properties[$key] = [
|
'type' => MetaTypeManager::getMetaType($subfield['type'])
|
];
|
}
|
|
return [
|
'type' => 'object',
|
'items' => [
|
'type' => 'object',
|
'properties' => $properties
|
]
|
];
|
} elseif ($field['type'] === 'group') {
|
$properties = [];
|
foreach ($field['fields'] as $key => $subfield) {
|
$properties[$key] = [
|
'type' => MetaTypeManager::getMetaType($subfield['type'])
|
];
|
|
if (isset($subfield['description'])) {
|
$properties[$key]['description'] = $subfield['description'];
|
}
|
|
if (in_array($subfield['type'], ['select', 'radio']) && isset($subfield['options'])) {
|
$properties[$key]['enum'] = array_keys($subfield['options']);
|
}
|
}
|
|
return [
|
'type' => 'object',
|
'properties' => $properties,
|
'additionalProperties' => false
|
];
|
} elseif ($field['type'] === 'location') {
|
return [
|
'type' => 'object',
|
'properties' => [
|
'address' => ['type' => 'string'],
|
'lat' => ['type' => 'number'],
|
'lng' => ['type' => 'number']
|
]
|
];
|
}
|
|
return [
|
'items' => ['type' => 'string']
|
];
|
}
|
|
protected function logError(string $message, array $context = []): void
|
{
|
error_log(sprintf(
|
'[Meta.Registry] %s | Context: %s',
|
$message,
|
json_encode($context)
|
));
|
}
|
}
|