'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(''; 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); } }