460 lines
18 KiB
PHP
460 lines
18 KiB
PHP
<?php
|
|
/**
|
|
* 空笺未寄 — functions.php
|
|
*/
|
|
|
|
// ── 主题设置 ──────────────────────────────────
|
|
add_action('after_setup_theme', 'kjweji_setup');
|
|
function kjweji_setup() {
|
|
add_theme_support('title-tag');
|
|
add_theme_support('post-thumbnails');
|
|
add_image_size('kjweji-featured', 960, 400, true);
|
|
add_image_size('kjweji-card', 600, 375, true);
|
|
add_theme_support('custom-logo', array(
|
|
'height' => 40,
|
|
'width' => 160,
|
|
'flex-height' => true,
|
|
));
|
|
add_theme_support('html5', array(
|
|
'comment-form', 'comment-list', 'gallery', 'caption', 'style', 'script',
|
|
));
|
|
register_nav_menus(array(
|
|
'primary' => '主导航',
|
|
));
|
|
}
|
|
|
|
// ── 资源加载 ──────────────────────────────────
|
|
add_action('wp_enqueue_scripts', 'kjweji_enqueue_assets');
|
|
function kjweji_enqueue_assets() {
|
|
wp_enqueue_style('kjweji-style', get_stylesheet_uri(), array(), '1.0.0');
|
|
// 字体改用系统自带(Google Fonts 在中国大陆不可用)
|
|
wp_enqueue_script('kjweji-lightbox',
|
|
get_template_directory_uri() . '/assets/js/lightbox.js',
|
|
array(), '1.0.0', true);
|
|
}
|
|
|
|
// ── 注册自定义文章类型: tucao(微言) ──────────
|
|
add_action('init', 'kjweji_register_tucao');
|
|
function kjweji_register_tucao() {
|
|
register_post_type('tucao', array(
|
|
'labels' => array(
|
|
'name' => '微言',
|
|
'singular_name' => '微言',
|
|
'add_new' => '写微言',
|
|
'add_new_item' => '写一条微言',
|
|
'edit_item' => '编辑微言',
|
|
'new_item' => '新微言',
|
|
'view_item' => '查看微言',
|
|
'search_items' => '搜索微言',
|
|
'not_found' => '暂无微言',
|
|
'not_found_in_trash' => '回收站中暂无微言',
|
|
),
|
|
'public' => true,
|
|
'has_archive' => true,
|
|
'rewrite' => array('slug' => 'tucao'),
|
|
'show_in_rest' => true,
|
|
'supports' => array('title', 'editor', 'author', 'thumbnail', 'comments'),
|
|
'menu_position' => 25,
|
|
'menu_icon' => 'dashicons-format-chat',
|
|
'supports' => array('title', 'editor', 'author', 'thumbnail', 'comments'),
|
|
));
|
|
}
|
|
|
|
// 主题激活时,把已存在的 tucao 文章全部开放评论
|
|
add_action('after_switch_theme', 'kjweji_open_tucao_comments');
|
|
function kjweji_open_tucao_comments() {
|
|
$posts = get_posts(array('post_type' => 'tucao', 'posts_per_page' => -1, 'post_status' => 'any'));
|
|
foreach ($posts as $post) {
|
|
wp_update_post(array('ID' => $post->ID, 'comment_status' => 'open'));
|
|
}
|
|
}
|
|
|
|
// ── 摘要取前 2-3 句 ───────────────────────────
|
|
// 摘要:取文章内容的前 N 个字符(在句号处截断)
|
|
function kjweji_excerpt($max_sentences = 5, $max_chars = 300) {
|
|
$content = get_the_content();
|
|
$content = wp_strip_all_tags($content);
|
|
if (empty($content)) return '';
|
|
// 先按字符截断
|
|
if (mb_strlen($content) > $max_chars) {
|
|
$content = mb_substr($content, 0, $max_chars);
|
|
// 回退到最后一个句号
|
|
$last_period = mb_strrpos($content, '。');
|
|
if ($last_period !== false && $last_period > $max_chars / 2) {
|
|
$content = mb_substr($content, 0, $last_period + 1);
|
|
}
|
|
}
|
|
return esc_html(trim($content));
|
|
}
|
|
|
|
// ── OG 标签 ───────────────────────────────────
|
|
add_action('wp_head', 'kjweji_og_tags');
|
|
function kjweji_og_tags() {
|
|
if (is_singular()) {
|
|
$title = get_the_title();
|
|
$desc = kjweji_excerpt(2);
|
|
$url = get_permalink();
|
|
} else {
|
|
$title = get_bloginfo('name');
|
|
$desc = get_bloginfo('description');
|
|
$url = home_url();
|
|
}
|
|
echo '<meta property="og:type" content="' . (is_singular() ? 'article' : 'website') . '" />' . "\n";
|
|
echo '<meta property="og:title" content="' . esc_attr($title) . '" />' . "\n";
|
|
echo '<meta property="og:description" content="' . esc_attr($desc) . '" />' . "\n";
|
|
echo '<meta property="og:url" content="' . esc_url($url) . '" />' . "\n";
|
|
if (is_singular() && has_post_thumbnail()) {
|
|
$img = get_the_post_thumbnail_url(null, 'kjweji-featured');
|
|
echo '<meta property="og:image" content="' . esc_url($img) . '" />' . "\n";
|
|
}
|
|
echo '<meta name="twitter:card" content="summary_large_image" />' . "\n";
|
|
}
|
|
|
|
// ── 首页只显示普通文章(非 tucao) ─────────────
|
|
add_action('pre_get_posts', 'kjweji_home_only_posts');
|
|
function kjweji_home_only_posts($query) {
|
|
if (!is_admin() && $query->is_main_query() && $query->is_home()) {
|
|
$query->set('post_type', 'post');
|
|
}
|
|
}
|
|
|
|
// 浏览量
|
|
function kjweji_get_views() {
|
|
$count = get_post_meta(get_the_ID(), 'post_views', true);
|
|
return $count ? (int) $count : 0;
|
|
}
|
|
|
|
// 禁用 WP emoji 转图片
|
|
remove_action('wp_head', 'print_emoji_detection_script', 7);
|
|
remove_action('wp_print_styles', 'print_emoji_styles');
|
|
remove_action('admin_print_scripts', 'print_emoji_detection_script');
|
|
remove_action('admin_print_styles', 'print_emoji_styles');
|
|
|
|
add_filter('emoji_svg_url', '__return_false');
|
|
|
|
// 隐藏顶部 admin bar
|
|
add_filter('show_admin_bar', '__return_false');
|
|
|
|
// 评论表单中文化
|
|
add_filter('comment_form_default_fields', function($fields) {
|
|
$fields['author'] = '<p class="comment-form-author"><label for="author">显示名称</label><input id="author" name="author" type="text" size="30" /></p>';
|
|
$fields['email'] = '<p class="comment-form-email"><label for="email">邮箱</label><input id="email" name="email" type="email" size="30" /></p>';
|
|
$fields['url'] = '<p class="comment-form-url"><label for="url">网站</label><input id="url" name="url" type="url" size="30" /></p>';
|
|
$fields['cookies'] = '<p class="comment-form-cookies-consent"><input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes" /><label for="wp-comment-cookies-consent">在此浏览器中保存我的信息</label></p>';
|
|
return $fields;
|
|
});
|
|
|
|
// 评论无需审核直接发布
|
|
add_filter('pre_comment_approved', function() { return 1; });
|
|
|
|
add_action('template_include', function($template) {
|
|
if (get_query_var('post_type') === 'post' && !is_home() && !is_singular()) {
|
|
$t = locate_template('archive.php');
|
|
if ($t) return $t;
|
|
}
|
|
return $template;
|
|
});
|
|
|
|
|
|
|
|
// ── 本地头像:用户资料页上传 ─────────────────────
|
|
add_action('show_user_profile', 'kjweji_avatar_field');
|
|
add_action('edit_user_profile', 'kjweji_avatar_field');
|
|
function kjweji_avatar_field($user) {
|
|
wp_enqueue_media();
|
|
$att_id = get_user_meta($user->ID, 'custom_avatar', true);
|
|
$preview = $att_id ? wp_get_attachment_image_url($att_id, 'medium') : '';
|
|
wp_nonce_field('kjweji_avatar_nonce', 'kjweji_avatar_nonce_field');
|
|
echo '<h3>自定义头像</h3>';
|
|
echo '<table class="form-table"><tr><th><label>上传本地头像</label></th><td>';
|
|
echo '<input type="hidden" id="custom_avatar" name="custom_avatar" value="' . esc_attr($att_id) . '" />';
|
|
echo '<div id="avatar_preview" style="margin-bottom:10px">';
|
|
if ($preview) echo '<img src="' . esc_url($preview) . '" style="max-width:120px;border-radius:8px;" />';
|
|
echo '</div>';
|
|
echo '<button type="button" class="button" id="upload_avatar_btn">选择图片</button>';
|
|
echo '<button type="button" class="button" id="remove_avatar_btn" style="margin-left:5px;' . ($att_id ? '' : 'display:none;') . '">移除</button>';
|
|
echo '</td></tr></table>';
|
|
echo '<script>
|
|
jQuery(function($) {
|
|
var frame;
|
|
$("#upload_avatar_btn").click(function(e) {
|
|
e.preventDefault();
|
|
if (frame) { frame.open(); return; }
|
|
frame = wp.media({ title: "选择头像", button: { text: "设为头像" }, multiple: false });
|
|
frame.on("select", function() {
|
|
var att = frame.state().get("selection").first().toJSON();
|
|
$("#custom_avatar").val(att.id);
|
|
$("#avatar_preview").html("<img src=\'" + att.url + "\' style=\'max-width:120px;border-radius:8px;\' />");
|
|
$("#remove_avatar_btn").show();
|
|
});
|
|
frame.open();
|
|
});
|
|
$("#remove_avatar_btn").click(function() {
|
|
$("#custom_avatar").val("");
|
|
$("#avatar_preview").html("");
|
|
$(this).hide();
|
|
});
|
|
});
|
|
</script>';
|
|
}
|
|
add_action('personal_options_update', 'kjweji_save_avatar');
|
|
add_action('edit_user_profile_update', 'kjweji_save_avatar');
|
|
function kjweji_save_avatar($user_id) {
|
|
if (!current_user_can('edit_user', $user_id)) return;
|
|
if (!isset($_POST['kjweji_avatar_nonce_field']) || !wp_verify_nonce($_POST['kjweji_avatar_nonce_field'], 'kjweji_avatar_nonce')) return;
|
|
if (isset($_POST['custom_avatar'])) {
|
|
$att_id = intval($_POST['custom_avatar']);
|
|
if ($att_id) {
|
|
update_user_meta($user_id, 'custom_avatar', $att_id);
|
|
} else {
|
|
delete_user_meta($user_id, 'custom_avatar');
|
|
}
|
|
}
|
|
}
|
|
|
|
// 本地头像(团队证件照)
|
|
add_filter('get_avatar', function($avatar, $id_or_email, $size, $default, $alt) {
|
|
$uid = 0;
|
|
if (is_numeric($id_or_email)) $uid = (int) $id_or_email;
|
|
elseif (is_object($id_or_email) && isset($id_or_email->user_id)) $uid = (int) $id_or_email->user_id;
|
|
elseif (is_object($id_or_email) && $id_or_email instanceof WP_Comment) {
|
|
$uid = (int) $id_or_email->user_id;
|
|
}
|
|
// 如果传的是 email 但找不到用户,尝试用 email 找
|
|
if (!$uid && is_string($id_or_email) && strpos($id_or_email, '@') !== false) {
|
|
$u = get_user_by('email', $id_or_email);
|
|
if ($u) $uid = $u->ID;
|
|
}
|
|
$att_id = get_user_meta($uid, 'custom_avatar', true);
|
|
if ($att_id) {
|
|
$url = wp_get_attachment_image_url($att_id, 'medium');
|
|
if ($url) {
|
|
return '<img src="' . esc_url($url) . '" class="avatar avatar-' . $size . ' photo" width="' . $size . '" height="' . $size . '" alt="" />';
|
|
}
|
|
}
|
|
return $avatar; // fallback
|
|
}, 10, 5);
|
|
|
|
// 激活主题时自动初始化
|
|
add_action('after_switch_theme', 'kjweji_setup_pages');
|
|
function kjweji_setup_pages() {
|
|
// 创建笺文页
|
|
if (!get_page_by_path('articles')) {
|
|
wp_insert_post([
|
|
'post_title' => '笺文', 'post_name' => 'articles',
|
|
'post_type' => 'page', 'post_status' => 'publish',
|
|
'meta_input' => ['_wp_page_template' => 'page-articles.php'],
|
|
]);
|
|
}
|
|
// 创建拾影页
|
|
if (!get_page_by_path('photos')) {
|
|
wp_insert_post([
|
|
'post_title' => '拾影', 'post_name' => 'photos',
|
|
'post_type' => 'page', 'post_status' => 'publish',
|
|
'meta_input' => ['_wp_page_template' => 'page-photos.php'],
|
|
]);
|
|
}
|
|
// 创建导航菜单
|
|
if (!wp_get_nav_menu_object('主导航')) {
|
|
$menu_id = wp_create_nav_menu('主导航');
|
|
foreach ([
|
|
['首页', '/'],
|
|
['笺文', '/articles/'],
|
|
['微言', '/tucao/'],
|
|
['拾影', '/photos/'],
|
|
] as $item) {
|
|
wp_update_nav_menu_item($menu_id, 0, [
|
|
'menu-item-title' => $item[0],
|
|
'menu-item-url' => $item[1],
|
|
'menu-item-status' => 'publish',
|
|
]);
|
|
}
|
|
$locations = get_theme_mod('nav_menu_locations') ?: [];
|
|
$locations['primary'] = $menu_id;
|
|
set_theme_mod('nav_menu_locations', $locations);
|
|
}
|
|
flush_rewrite_rules();
|
|
}
|
|
|
|
// ── 检查固定链接格式 ──────────────────────────
|
|
// 如果启用了 /index.php/ 前缀,自定义文章类型的路由会失效
|
|
add_action('admin_notices', 'kjweji_permalink_notice');
|
|
function kjweji_permalink_notice() {
|
|
$permalink = get_option('permalink_structure');
|
|
if ($permalink && strpos($permalink, 'index.php') !== false) {
|
|
echo '<div class="notice notice-warning is-dismissible"><p><strong>空笺未寄主题提示:</strong>检测到固定链接包含 <code>/index.php/</code>,会导致「微言」和「拾影」页面无法访问。建议在「设置 → 固定链接」中改用不含 <code>index.php</code> 的格式(如 <code>/%postname%/</code>)。</p></div>';
|
|
}
|
|
}
|
|
|
|
// 自定义文章类型:拾影
|
|
add_action('init', 'kjweji_register_photo');
|
|
function kjweji_register_photo() {
|
|
register_post_type('photo', array(
|
|
'labels' => array(
|
|
'name' => '拾影',
|
|
'singular_name' => '拾影',
|
|
'add_new' => '发拾影',
|
|
'add_new_item' => '发新拾影',
|
|
'edit_item' => '编辑拾影',
|
|
),
|
|
'public' => true,
|
|
'has_archive' => false,
|
|
'rewrite' => array('slug' => 'photo/%post_id%'),
|
|
'show_in_rest' => true,
|
|
'supports' => array('title', 'editor', 'author', 'thumbnail'),
|
|
'menu_position' => 26,
|
|
'menu_icon' => 'dashicons-format-gallery',
|
|
));
|
|
}
|
|
|
|
|
|
|
|
add_filter('post_type_link', function($link, $post) {
|
|
if ($post->post_type === 'photo' && $post->post_status === 'publish') {
|
|
return home_url(user_trailingslashit('/photo/' . $post->ID . '/' . $post->post_name));
|
|
}
|
|
return $link;
|
|
}, 10, 2);
|
|
|
|
// 匹配 /photo/123/slug/ 格式
|
|
add_action('init', function() {
|
|
add_rewrite_rule('^photo/([0-9]+)/([^/]+)/?$', 'index.php?post_type=photo&p=$matches[1]', 'top');
|
|
add_rewrite_rule('^photo/([0-9]+)/?$', 'index.php?post_type=photo&p=$matches[1]', 'top');
|
|
});
|
|
|
|
// 允许通过 REST API 创建评论
|
|
add_filter('rest_allow_anonymous_comments', '__return_false');
|
|
|
|
// 评论后重定向回当前页
|
|
|
|
|
|
// tucao 不要详情页,直接回 archive
|
|
add_action('template_redirect', function() {
|
|
if (is_singular('tucao')) {
|
|
wp_redirect(get_post_type_archive_link('tucao'), 301);
|
|
exit;
|
|
}
|
|
});
|
|
|
|
// 评论后送回微言列表并锚点定位
|
|
add_filter('comment_post_redirect', function($loc, $comment) {
|
|
$post = get_post($comment->comment_post_ID);
|
|
if ($post && $post->post_type === 'tucao') {
|
|
return get_post_type_archive_link('tucao') . '#tucao-' . $comment->comment_post_ID;
|
|
}
|
|
return $loc;
|
|
}, 99, 2);
|
|
|
|
// 中国时区
|
|
date_default_timezone_set('Asia/Shanghai');
|
|
|
|
// 评论回复标题中文化
|
|
add_filter('comment_form_defaults', function($defaults) {
|
|
$defaults['title_reply_to'] = '回复 %s';
|
|
$defaults['cancel_reply_link'] = '取消回复';
|
|
$defaults['title_reply_before'] = '<h3 class="comment-reply-title">';
|
|
$defaults['title_reply_after'] = '</h3>';
|
|
return $defaults;
|
|
});
|
|
|
|
// ── Customizer(外观 → 自定义 → 空笺未寄设置) ────
|
|
add_action('customize_register', 'kjweji_customize_register');
|
|
function kjweji_customize_register($wp_customize) {
|
|
// 注册 section
|
|
$wp_customize->add_section('kjweji_settings', array(
|
|
'title' => '空笺未寄设置',
|
|
'priority' => 30,
|
|
));
|
|
|
|
// ── 首页 ──
|
|
$wp_customize->add_setting('kjweji_hero_intro', array(
|
|
'default' => "这里是自白者的栖息地。\n吐槽,落笔,沉思,接住那一缕若有的情绪。\n片语只言,皆是存在。",
|
|
'sanitize_callback' => 'sanitize_textarea_field',
|
|
));
|
|
$wp_customize->add_control('kjweji_hero_intro', array(
|
|
'label' => '首页介绍文字',
|
|
'section' => 'kjweji_settings',
|
|
'type' => 'textarea',
|
|
));
|
|
|
|
$wp_customize->add_setting('kjweji_hero_couplet', array(
|
|
'default' => '空笺待写千般意,未寄先存一寸心',
|
|
'sanitize_callback' => 'sanitize_text_field',
|
|
));
|
|
$wp_customize->add_control('kjweji_hero_couplet', array(
|
|
'label' => '首页对联',
|
|
'section' => 'kjweji_settings',
|
|
'type' => 'text',
|
|
));
|
|
|
|
$wp_customize->add_setting('kjweji_hero_couplet_hl1', array(
|
|
'default' => '千般意',
|
|
'sanitize_callback' => 'sanitize_text_field',
|
|
));
|
|
$wp_customize->add_control('kjweji_hero_couplet_hl1', array(
|
|
'label' => '对联高亮词1',
|
|
'section' => 'kjweji_settings',
|
|
'type' => 'text',
|
|
));
|
|
|
|
$wp_customize->add_setting('kjweji_hero_couplet_hl2', array(
|
|
'default' => '一寸心',
|
|
'sanitize_callback' => 'sanitize_text_field',
|
|
));
|
|
$wp_customize->add_control('kjweji_hero_couplet_hl2', array(
|
|
'label' => '对联高亮词2',
|
|
'section' => 'kjweji_settings',
|
|
'type' => 'text',
|
|
));
|
|
|
|
// ── 页脚 ──
|
|
$wp_customize->add_setting('kjweji_footer_motto', array(
|
|
'default' => '空笺待写千般意,未寄先存一寸心',
|
|
'sanitize_callback' => 'sanitize_text_field',
|
|
));
|
|
$wp_customize->add_control('kjweji_footer_motto', array(
|
|
'label' => '页脚格言',
|
|
'section' => 'kjweji_settings',
|
|
'type' => 'text',
|
|
));
|
|
|
|
$wp_customize->add_setting('kjweji_footer_text', array(
|
|
'default' => '每一段文字,都在时光里等待回音',
|
|
'sanitize_callback' => 'sanitize_text_field',
|
|
));
|
|
$wp_customize->add_control('kjweji_footer_text', array(
|
|
'label' => '页脚版权文案',
|
|
'section' => 'kjweji_settings',
|
|
'type' => 'text',
|
|
));
|
|
|
|
// ── 页面副标题 ──
|
|
$wp_customize->add_setting('kjweji_articles_subtitle', array(
|
|
'default' => '字里行间,尽是岁月',
|
|
'sanitize_callback' => 'sanitize_text_field',
|
|
));
|
|
$wp_customize->add_control('kjweji_articles_subtitle', array(
|
|
'label' => '笺文页副标题',
|
|
'section' => 'kjweji_settings',
|
|
'type' => 'text',
|
|
));
|
|
|
|
$wp_customize->add_setting('kjweji_photos_subtitle', array(
|
|
'default' => '在时光里截图',
|
|
'sanitize_callback' => 'sanitize_text_field',
|
|
));
|
|
$wp_customize->add_control('kjweji_photos_subtitle', array(
|
|
'label' => '拾影页副标题',
|
|
'section' => 'kjweji_settings',
|
|
'type' => 'text',
|
|
));
|
|
}
|
|
|
|
// tucao 自动生成标题
|
|
add_filter('wp_insert_post_data', function($data) {
|
|
if ($data['post_type'] === 'tucao' && empty($data['post_title'])) {
|
|
$data['post_title'] = '微言-' . time();
|
|
}
|
|
return $data;
|
|
});
|