'number', 'prefix' => '$']);
* echo Render::render('gallery', $images, ['type' => 'gallery']);
*/
class Render
{
/**
* Render a field value based on type
*/
public static function render(string $name, mixed $value, array $config = []): string
{
if (!apply_filters('jvbShouldRenderMeta', true, $name, $config['type'] ?? 'text', null)) {
return '';
}
$type = $config['type'] ?? 'text';
$method = 'render' . str_replace('_', '', ucwords($type, '_'));
$output = method_exists(static::class, $method)
? static::$method($name, $value, $config)
: static::renderDefault($name, $value, $config);
return apply_filters('jvbRenderFrontendMeta', $output, $name, $config, $value, null);
}
/**
* Render with Meta instance (convenience method)
*/
public static function renderFrom(Meta $meta, string $name, bool $hideEmpty = true): string
{
$value = $meta->get($name);
$config = $meta->config($name) ?? ['type' => 'text'];
$output = static::render($name, $value, $config);
if (empty($output) && !$hideEmpty) {
return static::getEmptyTemplate($config['type'] ?? 'text', $name);
}
return $output;
}
// ─────────────────────────────────────────────────────────────
// Type Renderers
// ─────────────────────────────────────────────────────────────
protected static function renderDefault(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
return sprintf('%s', esc_attr($name), esc_html($value));
}
protected static function renderText(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
return sprintf('%s', esc_attr($name), esc_html($value));
}
protected static function renderTextarea(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
return sprintf('
%s
', esc_attr($name), wp_kses_post(wpautop($value)));
}
protected static function renderNumber(string $name, mixed $value, array $config): string
{
if ($value === '' || $value === null) {
return '';
}
$prefix = $config['prefix'] ?? '';
$suffix = $config['suffix'] ?? '';
$decimals = $config['decimals'] ?? 0;
return sprintf(
'%s%s%s',
esc_attr($name),
esc_html($prefix),
esc_html(number_format((float)$value, $decimals)),
esc_html($suffix)
);
}
protected static function renderEmail(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
return sprintf(
'%s%s',
esc_attr($name),
esc_attr($value),
jvbIcon('envelope'),
esc_html($value)
);
}
protected static function renderUrl(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
$label = $config['label'] ?? parse_url($value, PHP_URL_HOST) ?? $value;
return sprintf(
'%s%s',
esc_attr($name),
esc_url($value),
jvbIcon('link'),
esc_html($label)
);
}
protected static function renderDate(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
$format = $config['format'] ?? get_option('date_format');
$timestamp = strtotime($value);
if (!$timestamp) {
return '';
}
return sprintf(
'',
esc_attr($name),
esc_attr(date('Y-m-d', $timestamp)),
jvbIcon('calendar'),
esc_html(date_i18n($format, $timestamp))
);
}
protected static function renderTime(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
$format = $config['format'] ?? get_option('time_format');
$timestamp = strtotime($value);
if (!$timestamp) {
return '';
}
return sprintf(
'',
esc_attr($name),
esc_attr(date('H:i', $timestamp)),
jvbIcon('clock'),
esc_html(date_i18n($format, $timestamp))
);
}
protected static function renderDatetime(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
$format = $config['format'] ?? get_option('date_format') . ' ' . get_option('time_format');
$timestamp = strtotime($value);
if (!$timestamp) {
return '';
}
return sprintf(
'',
esc_attr($name),
esc_attr(date('Y-m-d\TH:i:s', $timestamp)),
jvbIcon('calendar'),
esc_html(date_i18n($format, $timestamp))
);
}
protected static function renderTrueFalse(string $name, mixed $value, array $config): string
{
$isTrue = filter_var($value, FILTER_VALIDATE_BOOLEAN);
$labels = $config['labels'] ?? ['Yes', 'No'];
return sprintf(
'%s',
esc_attr($name),
$isTrue ? 'true' : 'false',
esc_html($isTrue ? $labels[0] : $labels[1])
);
}
protected static function renderImage(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
$size = $config['size'] ?? 'medium';
$image = wp_get_attachment_image($value, $size, false, [
'class' => "{$name} attachment-{$size}"
]);
return $image ?: '';
}
protected static function renderGallery(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
$ids = is_array($value) ? $value : explode(',', $value);
$ids = array_filter(array_map('intval', $ids));
if (empty($ids)) {
return '';
}
$size = $config['size'] ?? 'thumbnail';
$output = sprintf('', esc_attr($name));
foreach ($ids as $id) {
$image = wp_get_attachment_image($id, $size);
if ($image) {
$output .= $image;
}
}
$output .= '
';
return $output;
}
protected static function renderTaxonomy(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
$ids = is_array($value) ? $value : explode(',', $value);
$ids = array_filter(array_map('intval', $ids));
if (empty($ids)) {
return '';
}
$terms = [];
foreach ($ids as $id) {
$term = get_term($id);
if ($term && !is_wp_error($term)) {
$link = get_term_link($term);
$terms[] = sprintf(
'%s',
esc_url($link),
esc_html($term->name)
);
}
}
return sprintf(
'%s',
esc_attr($name),
implode(', ', $terms)
);
}
protected static function renderUser(string $name, mixed $value, array $config): string
{
if (empty($value)) {
return '';
}
$ids = is_array($value) ? $value : explode(',', $value);
$ids = array_filter(array_map('intval', $ids));
if (empty($ids)) {
return '';
}
$users = [];
foreach ($ids as $id) {
$user = get_userdata($id);
if ($user) {
$users[] = esc_html($user->display_name);
}
}
return sprintf(
'%s',
esc_attr($name),
implode(', ', $users)
);
}
protected static function renderSelect(string $name, mixed $value, array $config): string
{
if (empty($value) || empty($config['options'])) {
return '';
}
$label = $config['options'][$value] ?? $value;
return sprintf(
'%s',
esc_attr($name),
esc_html($label)
);
}
protected static function renderSet(string $name, mixed $value, array $config): string
{
if (empty($value) || empty($config['options'])) {
return '';
}
$values = is_array($value) ? $value : explode(',', $value);
$labels = [];
foreach ($values as $v) {
$v = trim($v);
if (isset($config['options'][$v])) {
$labels[] = $config['options'][$v];
}
}
if (empty($labels)) {
return '';
}
return sprintf(
'%s',
esc_attr($name),
esc_html(implode(', ', $labels))
);
}
protected static function renderLocation(string $name, mixed $value, array $config): string
{
if (empty($value) || empty($value['address'])) {
return '';
}
return sprintf(
'%s%s',
esc_attr($name),
jvbIcon('map-pin'),
esc_html($value['address'])
);
}
protected static function renderRepeater(string $name, mixed $value, array $config): string
{
if (empty($value) || !is_array($value)) {
return '';
}
$fields = $config['fields'] ?? [];
$output = sprintf('', esc_attr($name));
foreach ($value as $index => $row) {
$output .= '
';
foreach ($row as $fieldName => $fieldValue) {
$fieldConfig = $fields[$fieldName] ?? ['type' => 'text'];
$output .= static::render($fieldName, $fieldValue, $fieldConfig);
}
$output .= '
';
}
$output .= '
';
return $output;
}
protected static function renderGroup(string $name, mixed $value, array $config): string
{
if (empty($value) || !is_array($value)) {
return '';
}
$fields = $config['fields'] ?? [];
$output = sprintf('', esc_attr($name));
foreach ($value as $fieldName => $fieldValue) {
$fieldConfig = $fields[$fieldName] ?? ['type' => 'text'];
$output .= static::render($fieldName, $fieldValue, $fieldConfig);
}
$output .= '
';
return $output;
}
// ─────────────────────────────────────────────────────────────
// Empty Templates
// ─────────────────────────────────────────────────────────────
public static function getEmptyTemplate(string $type, string $name): string
{
$template = match ($type) {
'text', 'textarea', 'number' => '',
'url', 'email' => '' . jvbIcon('link') . '',
'set', 'checkbox', 'radio', 'taxonomy', 'user' => '',
'image', 'gallery' => '',
'date' => '' . jvbIcon('calendar') . '
',
'time' => '' . jvbIcon('clock') . '
',
'true_false' => '',
default => ''
};
return apply_filters('jvbMetaTypeTemplate', $template, $type);
}
}