<?php
|
|
namespace JVBase\inc\registrar\helpers;
|
use JVBase\meta\MetaTypeManager;
|
use JVBase\meta\Sanitizer;
|
use JVBase\registrar\Registrar;
|
|
if (!defined('ABSPATH')) {
|
exit;
|
}
|
class AddCustomFields {
|
protected Registrar $registrar;
|
|
public function __construct(Registrar $registrar) {
|
$this->registrar = $registrar;
|
|
if ($registrar->getType() === 'post') {
|
add_action('enqueue_block_editor_assets', [$this, 'enqueue']);
|
}
|
|
add_action('init', [$this, 'registerMeta']);
|
}
|
|
public function enqueue():void
|
{
|
if ($this->registrar->getType() !== 'post') {
|
return;
|
}
|
$screen = get_current_screen();
|
if (!$screen || $screen->post_type !== $this->registrar->getBased()) {
|
return;
|
}
|
|
$asset = include JVB_DIR.'/build/_meta/fields.asset.php';
|
|
wp_enqueue_script(
|
'jvb-editor-fields',
|
JVB_URL.'build/_meta/fields.js',
|
$asset['dependencies'],
|
$asset['version'],
|
true
|
);
|
|
wp_add_inline_script(
|
'jvb-editor-fields',
|
'window.jvbFieldConfig = '.wp_json_encode([
|
'fields' => array_map(function($f) {
|
$f['name'] = jvbCheckBase($f['name']);
|
$f['id'] = jvbCheckBase($f['name']);
|
if ($f['type'] === 'selector') {
|
$f['taxonomy'] = jvbCheckBase($f['taxonomy']);
|
}
|
if (array_key_exists('condition', $f)) {
|
$f['condition']['field'] = jvbCheckBase($f['condition']['field']);
|
}
|
return $f;
|
},array_values($this->registrar->getFields(false))),
|
'sections' => array_map(function ($s) {
|
$s['id'] = jvbCheckBase($s['slug']);
|
$s['fields'] = array_map(function ($f) {
|
return jvbCheckBase($f);
|
}, $s['fields']);
|
return $s;
|
},$this->registrar->getSections()),
|
]).';',
|
'before'
|
);
|
|
}
|
|
public function registerMeta():void
|
{
|
foreach ($this->registrar->getFields(false) as $name => $config) {
|
$metaType = $this->getSchemaType($config);
|
|
$rawSchema = in_array($metaType, ['array', 'object'], true)
|
? $this->determineSchema($config)
|
: true;
|
|
$schema = is_array($rawSchema) ? $this->schema($rawSchema) : $rawSchema;
|
//Allow for null
|
if ($metaType === 'object') {
|
$metaType = ['object', 'null'];
|
}
|
register_post_meta($this->registrar->getBased(), jvbCheckBase($name), [
|
'single' => true,
|
'type' => $metaType,
|
'default' => $config['default'] ?? MetaTypeManager::getType($config['type'])['default'] ?? '',
|
'sanitize_callback' => fn($value) => (Sanitizer::sanitize($value, $config)),
|
'auth_callback' => fn($allowed, $key, $postID) => current_user_can('edit_post', $postID),
|
'show_in_rest' => $schema,
|
'revisions_enabled' => true,
|
]);
|
}
|
}
|
protected function getSchemaType(array $config):string
|
{
|
$type = MetaTypeManager::getMetaType($config['type']);
|
if ($config['type'] === 'text' && array_key_exists('subtype', $config) && $config['subtype'] === 'number'){
|
$type = 'number';
|
}
|
return $type;
|
}
|
protected function determineSchema(array $config):array|bool
|
{
|
return match ($config['type']) {
|
'url' => $this->schemaText('uri'),
|
'email' => $this->schemaText('email'),
|
'text' => $this->checkText($config),
|
'select','set','radio','checkbox' => $this->schemaOptions($config),
|
'repeater' => $this->schemaRepeater($config),
|
'taglist' => $this->schemaTagList($config),
|
'group' => $this->schemaGroup($config),
|
'location' => $this->schemaLocation($config),
|
default => true
|
};
|
}
|
protected function schema(array $additional = []):array
|
{
|
return [
|
'schema' => $additional
|
];
|
}
|
|
protected function checkText(array $config):array|true
|
{
|
if (!array_key_exists('subtype', $config)) {
|
return true;
|
}
|
return match ($config['subtype']) {
|
'url' => $this->schemaText('url'),
|
'email' => $this->schemaText('email'),
|
default => true
|
};
|
}
|
|
protected function schemaText(string $type):array|true
|
{
|
if (!in_array($type, ['uri', 'email', 'date-time', 'hex-color', 'uuid', 'ip'])) {
|
error_log('Attempted to set unknown schema type for Meta: '.$type);
|
return true;
|
}
|
return $this->schema(['type' => 'string', 'format' => $type]);
|
}
|
|
protected function schemaOptions(array $config):array|true
|
{
|
if (!array_key_exists('options', $config) || empty($config['options'])) {
|
return true;
|
}
|
return $this->schema([
|
'type' => 'string',
|
'enum' => $config['options']
|
]);
|
}
|
|
protected function schemaRepeater(array $config):array|true
|
{
|
$schema = [
|
'type' => 'object',
|
];
|
$properties = [];
|
$required = [];
|
foreach ($config['fields']??[] as $name => $c) {
|
$args = [
|
'type' => $this->getSchemaType($c)
|
];
|
|
if (array_key_exists('required', $c) && $c['required']) {
|
$required[] = $name;
|
}
|
|
$tmp = $this->determineSchema($c);
|
if (is_array($tmp)) {
|
if (array_key_exists('default', $tmp)) {
|
$args['default'] = $tmp['default'];
|
}
|
if (array_key_exists('enum', $tmp)) {
|
$args['enum'] = $tmp['enum'];
|
}
|
if (array_key_exists('format', $tmp)) {
|
$args['format'] = $tmp['format'];
|
}
|
}
|
if (array_key_exists('default', $c)) {
|
//TODO: We should check for any stored default for the SEO things
|
$args['default'] = $c['default'];
|
}
|
$properties[$name] = $args;
|
}
|
|
$schema['properties'] = $properties;
|
if (!empty($required)) {
|
$schema['required'] = $required;
|
}
|
return $schema;
|
}
|
protected function schemaTagList(array $config):array|true
|
{
|
//Likely just the same as repeater
|
return $this->schemaRepeater($config);
|
}
|
protected function schemaGroup(array $config):array|true
|
{
|
//Likely just the same as repeater
|
return $this->schemaRepeater($config);
|
}
|
protected function schemaLocation(array $config):array|true
|
{
|
return [
|
'type' => ['object', 'null'],
|
'properties' => [
|
'address' => [
|
'type' => 'string'
|
],
|
'lat' => [
|
'type' => 'number',
|
],
|
'lng' => [
|
'type' => 'number',
|
],
|
'street' => [
|
'type' => 'string'
|
],
|
'city' => [
|
'type' => 'string'
|
],
|
'province' => [
|
'type' => 'string'
|
],
|
'postal_code' => [
|
'type' => 'string'
|
],
|
'country' => [
|
'type' => 'string'
|
],
|
]
|
];
|
}
|
}
|