'; foreach ($fields as $field) { self::field($widget, $field, $instance[(string) ($field['id'] ?? '')] ?? ($field['default'] ?? ''), ''); } echo ''; } private static function field(SchemaWidget $widget, array $field, $value, string $parent): void { $type = (string) ($field['type'] ?? 'text'); $id = (string) ($field['id'] ?? ''); if (in_array($type, ['content', 'subheading', 'submessage'], true)) { self::display_field($field, $type); return; } if ($id === '') { return; } $key = $parent === '' ? $id : $parent . '[' . $id . ']'; $field_id = $widget->get_field_id(str_replace(['[', ']'], ['-', ''], $key)); $field_name = $widget->get_field_name($key); $dependency = !empty($field['dependency']) ? wp_json_encode($field['dependency']) : ''; echo '
'; if (!empty($field['label'])) { echo ''; } if (!empty($field['subtitle'])) { echo '

' . esc_html((string) $field['subtitle']) . '

'; } if (!empty($field['description'])) { echo '

' . wp_kses_post((string) $field['description']) . '

'; } switch ($type) { case 'switcher': self::switcher($field_id, $field_name, (bool) $value); break; case 'radio': case 'button_set': case 'palette': case 'image_select': self::radios($field_id, $field_name, (array) ($field['options'] ?? []), (string) $value, $type); break; case 'select': self::select($field_id, $field_name, $field, $value); break; case 'checkbox': self::checkboxes($field_id, $field_name, $field, $value); break; case 'terms': self::terms($field_id, $field_name, $field, $value); break; case 'number': case 'spinner': case 'slider': self::number($field_id, $field_name, $field, $value, $type); break; case 'textarea': $rows = max(1, (int) ($field['attributes']['rows'] ?? 4)); echo ''; break; case 'upload': self::upload($field_id, $field_name, (string) $value, (string) ($field['library'] ?? '')); break; case 'color': echo ''; break; case 'icon': echo jio_icon_picker_field($field_name, $field_id, (string) $value); break; case 'link': self::link($widget, $key, is_array($value) ? $value : []); break; case 'spacing': self::spacing($widget, $key, is_array($value) ? $value : [], (array) ($field['edges'] ?? [])); break; case 'background': self::background($widget, $key, is_array($value) ? $value : []); break; case 'group': self::group($widget, $field, is_array($value) ? $value : [], $key); break; case 'fieldset': case 'accordion': self::nested($widget, $field, is_array($value) ? $value : [], $key); break; case 'text': default: echo ''; } echo '
'; } private static function display_field(array $field, string $type): void { $content = (string) ($field['content'] ?? $field['label'] ?? ''); $class = self::field_class($field, $type); if ($type === 'submessage') { $style = in_array($field['style'] ?? '', ['success', 'info', 'warning', 'danger'], true) ? $field['style'] : 'normal'; $class .= ' jio-widget-field--submessage-' . $style; } echo '
' . wp_kses_post($content) . '
'; } /** Reference CSF row classes: type modifier plus schema `class` (e.g. compact) and `inline`. */ private static function field_class(array $field, string $type): string { $classes = ['jio-widget-field', 'jio-widget-field--' . $type]; foreach (preg_split('/\s+/', trim((string) ($field['class'] ?? ''))) ?: [] as $extra) { if ($extra !== '') { $classes[] = 'is-' . sanitize_html_class($extra); } } if (!empty($field['inline'])) { $classes[] = 'is-inline'; } return implode(' ', $classes); } private static function switcher(string $id, string $name, bool $value): void { echo ''; echo ''; } private static function radios(string $id, string $name, array $options, string $value, string $type): void { echo '
'; foreach ($options as $key => $label) { $option_id = $id . '-' . sanitize_html_class((string) $key); $image = is_array($label) ? (string) ($label['image'] ?? $label['url'] ?? '') : (string) $label; $text = is_array($label) ? (string) ($label['label'] ?? $label['title'] ?? $key) : (string) $label; if ($type === 'image_select' && $text === $image) $text = (string) $key; if ($type === 'image_select' && filter_var($image, FILTER_VALIDATE_URL)) { $body = '' . esc_attr($text) . '' . esc_html($text) . ''; } elseif ($type === 'palette') { $body = '' . esc_html($text) . ''; } else { $body = esc_html($text); } echo ''; } echo '
'; } private static function palette_color(string $key): string { $colors = [ '' => '#fff', 'c-red' => 'rgba(255,84,115,.4)', 'c-red-2' => 'rgba(194,41,46,.4)', 'c-yellow' => 'rgba(255,111,6,.4)', 'c-yellow-2' => 'rgba(179,103,8,.4)', 'c-cyan' => 'rgba(8,196,193,.4)', 'c-blue' => 'rgba(41,151,247,.4)', 'c-blue-2' => 'rgba(77,130,249,.4)', 'c-green' => 'rgba(18,185,40,.4)', 'c-green-2' => 'rgba(72,135,24,.4)', 'c-purple' => 'rgba(213,72,245,.4)', 'c-purple-2' => 'rgba(154,72,245,.4)', 'b-red' => '#f74b3d', 'b-yellow' => '#f3920a', 'b-cyan' => '#08c4c1', 'b-blue' => '#0a8cf3', 'b-green' => '#1fd05a', 'b-purple' => '#c133f5', 'b-black' => '#121517', 'jb-red' => 'linear-gradient(135deg,#ffbeb4 10%,#f61a1a 100%)', 'jb-pink' => 'linear-gradient(135deg,#ff5e7f 30%,#ff967e 100%)', 'jb-yellow' => 'linear-gradient(135deg,#ffd6b2 10%,#ff651c 100%)', 'jb-cyan' => 'linear-gradient(140deg,#039ab3 10%,#58dbcf 90%)', 'jb-blue' => 'linear-gradient(135deg,#b6e6ff 10%,#198aff 100%)', 'jb-green' => 'linear-gradient(135deg,#ccffcd 10%,#52bb51 100%)', 'jb-purple' => 'linear-gradient(135deg,#fec2ff 10%,#d000de 100%)', 'jb-vip1' => 'linear-gradient(25deg,#eab869 10%,#fbecd4 60%,#ffe0ae 100%)', 'jb-vip2' => 'linear-gradient(317deg,#4d4c4c 30%,#878787 70%,#5f5c5c 100%)', 'focus-color' => 'linear-gradient(135deg,#74d5f6,#9866ff)', 'key-color' => '#333', 'muted-color' => '#777', 'muted-2-color' => '#999', 'muted-3-color' => '#b1b1b1', ]; return $colors[$key] ?? '#dcdcde'; } private static function select(string $id, string $name, array $field, $value): void { $multiple = !empty($field['multiple']); echo ''; } private static function checkboxes(string $id, string $name, array $field, $value): void { $options = (array) ($field['options'] ?? []); if (!$options) { self::switcher($id, $name, (bool) $value); return; } $values = array_map('strval', (array) $value); foreach ($options as $key => $label) { echo ' '; } } private static function number(string $id, string $name, array $field, $value, string $type): void { $min = isset($field['min']) ? ' min="' . esc_attr((string) $field['min']) . '"' : ''; $max = isset($field['max']) ? ' max="' . esc_attr((string) $field['max']) . '"' : ''; $step = ' step="' . esc_attr((string) ($field['step'] ?? 1)) . '"'; $input_type = $type === 'slider' ? 'range' : 'number'; $unit = trim((string) ($field['unit'] ?? '')); echo '
' . esc_html((string) $value) . '' . ($unit !== '' ? '' . esc_html($unit) . '' : '') . '
'; } private static function terms(string $id, string $name, array $field, $value): void { $taxonomy = (string) ($field['taxonomy'] ?? 'category'); $terms = get_terms(['taxonomy' => $taxonomy, 'hide_empty' => false, 'number' => 500, 'orderby' => 'name']); if (is_wp_error($terms)) { $terms = []; } $selected = array_values(array_filter(array_map('absint', (array) $value))); $by_id = []; foreach ($terms as $term) { $by_id[(int) $term->term_id] = $term; } echo '
'; echo ''; echo '
'; foreach ($selected as $term_id) { if (!isset($by_id[$term_id])) { continue; } echo '' . esc_html((string) $by_id[$term_id]->name) . ''; } echo '
'; echo ''; echo '
'; foreach ($terms as $term) { $term_id = (int) $term->term_id; echo ''; } echo '
'; } private static function upload(string $id, string $name, string $value, string $library = ''): void { $library = in_array($library, ['image', 'video'], true) ? $library : ''; echo '
'; // 参考主题:视频上传字段不展示预览图(视频 URL 作为 img src 会得到破图)。 if ($value !== '' && $library !== 'video') { echo ''; } echo ''; echo '
'; } private static function link(SchemaWidget $widget, string $key, array $value): void { echo ''; } private static function spacing(SchemaWidget $widget, string $key, array $value, array $edges = []): void { $all = ['top' => 'dashicons-arrow-up-alt', 'right' => 'dashicons-arrow-right-alt', 'bottom' => 'dashicons-arrow-down-alt', 'left' => 'dashicons-arrow-left-alt']; $visible = $edges ? array_intersect_key($all, array_flip($edges)) : $all; echo '
'; foreach ($visible as $edge => $icon) { echo ''; } echo '
'; } private static function background(SchemaWidget $widget, string $key, array $value): void { echo '
'; self::plain_input($widget, $key . '[color]', (string) ($value['color'] ?? ''), 'text', '背景颜色', 'widefat jio-widget-color'); self::plain_input($widget, $key . '[image]', (string) ($value['image'] ?? ''), 'url', '背景图片 URL'); foreach ([ 'position' => ['center center' => '居中', 'top center' => '顶部', 'bottom center' => '底部', 'center left' => '左侧', 'center right' => '右侧'], 'repeat' => ['no-repeat' => '不重复', 'repeat' => '平铺', 'repeat-x' => '水平平铺', 'repeat-y' => '垂直平铺'], 'attachment' => ['scroll' => '滚动', 'fixed' => '固定'], 'size' => ['cover' => '覆盖', 'contain' => '包含', 'auto' => '原始尺寸'], ] as $part => $options) { $name = $widget->get_field_name($key . '[' . $part . ']'); echo ''; } echo '
'; } private static function group(SchemaWidget $widget, array $field, array $rows, string $key): void { $token = '__index_' . substr(md5($key), 0, 8) . '__'; $button_title = (string) ($field['button_title'] ?? __('添加项目', 'jio')); echo '
'; foreach ($rows as $index => $row) { self::group_row($widget, $field, is_array($row) ? $row : [], $key, (string) $index); } echo '
'; } private static function group_row(SchemaWidget $widget, array $field, array $row, string $key, string $index): void { $prefix = (string) ($field['item_label'] ?? $field['label'] ?? __('项目', 'jio')); $number = ctype_digit($index) ? ((int) $index + 1) : 0; $title = $prefix . $number; if (!empty($row['title'])) $title .= ':' . strip_tags((string) $row['title']); echo '
' . esc_html($title) . '
'; foreach ((array) ($field['fields'] ?? []) as $child) { $child_id = (string) ($child['id'] ?? ''); self::field($widget, $child, $row[$child_id] ?? ($child['default'] ?? ''), $key . '[' . $index . ']'); } echo '
'; } private static function nested(SchemaWidget $widget, array $field, array $value, string $key): void { echo '
' . esc_html((string) ($field['label'] ?? '更多设置')) . '
'; foreach ((array) ($field['fields'] ?? []) as $child) { $child_id = (string) ($child['id'] ?? ''); self::field($widget, $child, $value[$child_id] ?? ($child['default'] ?? ''), $key); } echo '
'; } private static function plain_input(SchemaWidget $widget, string $key, string $value, string $type, string $placeholder, string $class = 'widefat'): void { $name = $widget->get_field_name($key); $id = $widget->get_field_id(str_replace(['[', ']'], ['-', ''], $key)); echo ''; } }