<?php
/**
* wp rapid字段框架使用范本
* 用户字段我们要开一个自定义头像和社交媒体,
*/
/** 可以挂在init钩子上,也可以直接在这里创建对象 */
// 文章基本结构分为两个
//
//
// $config = [
// 'id' => 'my_custom_fields', // 唯一标识符
// 'title' => '我的自定义字段', // 显示标题
// 'context' => 'post', // 应用场景:post/term/user/option
// 'post_types' => ['post', 'page'], // 仅post上下文需要
// 'taxonomy' => 'category', // 仅term上下文需要
// ];
// $tabs = [
// 'tab1' => [
// 'label' => '基础设置',
// 'fields' => [
// // 字段定义将放在这里
// ]
// ],
// // 可以添加更多标签页
// ];
// new WP_Rapid_Fields_Pro($config, $tabs);
// add_action('init','wrf_custom_fields');
function wrf_custom_fields() {
// 文章元数据配置
$config = [
'id' => 'post_meta_fields',
'title' => '文章扩展信息',
'context' => 'post',
'post_types' => ['post', 'page'],
];
$tabs = [
'basic' => [
'label' => '基础信息',
'fields' => [
[
'type' => 'heading',
'label' => '文章设置'
],
[
'id' => 'subtitle',
'type' => 'text',
'label' => '文章副标题',
'placeholder' => '请输入副标题'
],
[
'id' => 'featured_video',
'type' => 'url',
'label' => '特色视频',
'desc' => '输入视频URL地址'
],
[
'id' => 'display_order',
'type' => 'number',
'label' => '显示顺序',
'desc' => '数字越小排序越靠前'
]
]
],
'advanced' => [
'label' => '高级设置',
'fields' => [
[
'id' => 'custom_css',
'type' => 'raw_html',
'label' => '自定义CSS',
'desc' => '仅管理员可编辑'
],
[
'id' => 'page_layout',
'type' => 'select',
'label' => '页面布局',
'options' => [
'default' => '默认布局',
'fullwidth' => '全宽布局',
'sidebar' => '侧边栏布局'
]
]
]
]
];
new WP_Rapid_Fields_Pro($config, $tabs);
// 分类法元数据配置
$config = [
'id' => 'category_meta',
'title' => '分类扩展字段',
'context' => 'term',
'taxonomy' => 'category',
];
$tabs = [
'settings' => [
'label' => '分类设置',
'fields' => [
[
'id' => 'category_icon',
'type' => 'image',
'label' => '分类图标'
],
[
'id' => 'category_color',
'type' => 'color',
'label' => '主题颜色'
],
[
'id' => 'is_featured',
'type' => 'checkbox',
'label' => '推荐分类',
'desc' => '在首页显示此分类'
]
]
]
];
new WP_Rapid_Fields_Pro($config, $tabs);
// 主题选项配置
$config = [
'id' => 'theme_options',
'title' => '主题设置',
'context' => 'option',
];
$tabs = [
'general' => [
'label' => '常规设置',
'fields' => [
[
'id' => 'site_logo',
'type' => 'image',
'label' => '网站Logo'
],
[
'id' => 'favicon',
'type' => 'image',
'label' => '网站图标'
],
[
'id' => 'contact_email',
'type' => 'email',
'label' => '联系邮箱'
]
]
],
'social' => [
'label' => '社交链接',
'fields' => [
[
'id' => 'social_links',
'type' => 'group',
'label' => '社交平台',
'button' => '添加平台',
'sub_fields' => [
[
'id' => 'platform',
'type' => 'text',
'label' => '平台名称'
],
[
'id' => 'url',
'type' => 'url',
'label' => '链接地址'
],
[
'id' => 'icon',
'type' => 'image',
'label' => '平台图标'
]
]
]
]
]
];
new WP_Rapid_Fields_Pro($config, $tabs);
// 用户元数据配置
$config = [
'id' => 'user_profile_fields',
'title' => '扩展资料',
'context' => 'user',
];
$tabs = [
'social' => [
'label' => '社交资料',
'fields' => [
[
'id' => 'user_avatar',
'type' => 'image',
'label' => '自定义头像'
],
[
'id' => 'twitter',
'type' => 'url',
'label' => 'Twitter',
'placeholder' => 'https://twitter.com/用户名'
],
[
'id' => 'github',
'type' => 'url',
'label' => 'GitHub',
'placeholder' => 'https://github.com/用户名'
]
]
]
];
new WP_Rapid_Fields_Pro($config, $tabs);
}
//图片库字段保存为图片ID的逗号分隔字符串:
$gallery_ids = get_post_meta($post_id, 'gallery_field', true);
$image_ids = explode(',', $gallery_ids);
foreach ($image_ids as $image_id) {
$image_url = wp_get_attachment_image_url($image_id, 'full');
echo '<img src="' . esc_url($image_url) . '">';
}
// 应用头部尾部代码 尾部的钩子是 wp_footer
// Assuming you initialized the class with ID 'my_theme_options'
// new WP_Rapid_Fields_Pro( ['id' => 'my_theme_options', ...], ... );
add_action( 'wp_head', function() {
// 1. Get the whole options array
// Pattern: {your_config_id}_opts
$options = get_option( 'my_theme_opts_opts' );
// 2. Check if your specific field exists and isn't empty
if ( ! empty( $options['custom_css_code'] ) ) {
// 3. Output the code.
// We use echo directly because this is intended to be raw HTML/JS.
echo $options['custom_css_code'];
// Optional: Add a newline for source code cleanliness
echo "\n";
}
}, 1 ); // Priority 1 ensures it runs early in the head
// 禁止头像并创建本地头像如果没有本地头像就创建svg
/**
* Local custom avatar system with SVG initials generator
* * Logic:
* 1. Hook into pre_get_avatar.
* 2. If we return an <img> tag string, WordPress stops there (disabling Gravatar naturally).
* 3. We detect if it's a registered user with a custom upload.
* 4. If not, we generate an SVG Data URI.
* 5. We bypass esc_url for Data URIs to prevent the src="" bug.
*/
add_filter('pre_get_avatar', 'custom_svg_initials_avatar', 10, 3);
function custom_svg_initials_avatar($avatar, $id_or_email, $args) {
$user = false;
$user_id = 0;
// 1. Normalize User Detection
if (is_numeric($id_or_email)) {
$user_id = (int) $id_or_email;
} elseif (is_string($id_or_email) && ($user = get_user_by('email', $id_or_email))) {
$user_id = $user->ID;
} elseif (is_object($id_or_email) && !empty($id_or_email->user_id)) {
$user_id = (int) $id_or_email->user_id;
}
// 2. Check for Custom Uploaded Image (Meta field: 'custom_avatar')
if ($user_id > 0) {
$custom_url = get_user_meta($user_id, 'custom_avatar', true);
if (!empty($custom_url)) {
return build_avatar_img($custom_url, $args);
}
}
// 3. Fallback: Generate SVG Initials
// Determine the name to display
$name = '';
if ($user_id > 0) {
$user_data = get_userdata($user_id);
$name = $user_data->display_name;
} elseif (is_object($id_or_email) && !empty($id_or_email->comment_author)) {
$name = $id_or_email->comment_author;
} else {
// Fallback for purely email inputs on comments
$name = is_string($id_or_email) ? $id_or_email : 'Visitor';
}
// Generate Initials & Color
$initials = strtoupper(get_initials_from_name($name));
$size = isset($args['size']) ? (int) $args['size'] : 96;
// Create a unique color based on the name string so it's consistent for the user
$hash = md5($name);
$color = '#' . substr($hash, 0, 6);
// Generate SVG HTML
$svg = create_svg_avatar($initials, $color, $size);
// Encode as Data URI
$data_uri = 'data:image/svg+xml;base64,' . base64_encode($svg);
return build_avatar_img($data_uri, $args);
}
/**
* Helper: Build the <img> tag safely
*/
function build_avatar_img($src, $args) {
$size = isset($args['size']) ? (int) $args['size'] : 96;
$alt = isset($args['alt']) ? $args['alt'] : '';
$class = isset($args['class']) ? $args['class'] : 'avatar';
// Sanitize classes
$class_safe = esc_attr($class . ' avatar-' . $size . ' photo');
// CRITICAL FIX:
// If it's a Data URI, esc_url() will strip it. We must use esc_attr() instead.
if (strpos($src, 'data:image') === 0) {
$src_safe = esc_attr($src);
} else {
$src_safe = esc_url($src);
}
return sprintf(
'<img alt="%s" src="%s" class="%s" height="%d" width="%d" loading="lazy" />',
esc_attr($alt),
$src_safe,
$class_safe,
$size,
$size
);
}
/**
* Helper: Extract Initials
*/
function get_initials_from_name($name) {
if (empty($name)) return '?';
// Strip special chars/numbers for cleaner initials
$clean_name = trim(preg_replace('/[0-9@\.]/', '', $name));
if (empty($clean_name)) $clean_name = $name; // Fallback if name was only numbers/emails
$parts = preg_split('/\s+/', $clean_name);
if (count($parts) >= 2) {
return mb_substr($parts[0], 0, 1) . mb_substr($parts[1], 0, 1);
}
return mb_substr($name, 0, 1);
}
/**
* Helper: Generate SVG Code
*/
function create_svg_avatar($initials, $bg_color, $size) {
// Dynamic font size relative to container
$font_size = round($size * 0.45);
return '
<svg xmlns="http://www.w3.org/2000/svg" width="'.$size.'" height="'.$size.'" viewBox="0 0 '.$size.' '.$size.'">
<rect width="100%" height="100%" fill="'.$bg_color.'" />
<text x="50%" y="50%" dy=".35em"
font-size="'.$font_size.'"
fill="#ffffff"
text-anchor="middle"
font-family="sans-serif, Arial"
font-weight="bold">
'.$initials.'
</text>
</svg>';
}
/**
* CLEANUP:
* We do NOT need to hook into 'pre_option_show_avatars' or 'get_avatar_data'.
* By returning a value in 'pre_get_avatar' above, we effectively short-circuit
* WordPress standard Gravatar logic.
*/