1107 lines
39 KiB
PHP
1107 lines
39 KiB
PHP
<?php
|
||
|
||
function itstudio_theme_setup() {
|
||
add_theme_support('title-tag');
|
||
add_theme_support('post-thumbnails');
|
||
add_theme_support('automatic-feed-links');
|
||
add_theme_support('html5', array(
|
||
'search-form',
|
||
'gallery',
|
||
'caption',
|
||
));
|
||
|
||
register_nav_menus(array(
|
||
'primary' => __('Primary Menu', 'itstudio'),
|
||
));
|
||
|
||
load_theme_textdomain('itstudio', get_template_directory() . '/languages');
|
||
}
|
||
add_action('after_setup_theme', 'itstudio_theme_setup');
|
||
|
||
add_filter('comments_open', '__return_false', 20, 2);
|
||
add_filter('pings_open', '__return_false', 20, 2);
|
||
add_filter('comments_array', '__return_empty_array', 10, 2);
|
||
|
||
function itstudio_disable_comments_post_types() {
|
||
$post_types = array('post', 'page', 'announcement', 'news', 'service');
|
||
foreach ($post_types as $post_type) {
|
||
if (post_type_supports($post_type, 'comments')) {
|
||
remove_post_type_support($post_type, 'comments');
|
||
}
|
||
if (post_type_supports($post_type, 'trackbacks')) {
|
||
remove_post_type_support($post_type, 'trackbacks');
|
||
}
|
||
}
|
||
}
|
||
add_action('init', 'itstudio_disable_comments_post_types', 100);
|
||
|
||
function itstudio_hide_comments_menu() {
|
||
remove_menu_page('edit-comments.php');
|
||
}
|
||
add_action('admin_menu', 'itstudio_hide_comments_menu', 999);
|
||
|
||
function itstudio_hide_admin_bar_comments() {
|
||
remove_action('admin_bar_menu', 'wp_admin_bar_comments_menu', 60);
|
||
}
|
||
add_action('init', 'itstudio_hide_admin_bar_comments');
|
||
|
||
function itstudio_redirect_comments_admin_pages() {
|
||
global $pagenow;
|
||
if ($pagenow === 'edit-comments.php' || $pagenow === 'comment.php') {
|
||
wp_safe_redirect(admin_url());
|
||
exit;
|
||
}
|
||
}
|
||
add_action('admin_init', 'itstudio_redirect_comments_admin_pages');
|
||
|
||
function itstudio_remove_comments_dashboard_widget() {
|
||
remove_meta_box('dashboard_recent_comments', 'dashboard', 'normal');
|
||
}
|
||
add_action('wp_dashboard_setup', 'itstudio_remove_comments_dashboard_widget');
|
||
|
||
function itstudio_apply_site_identity() {
|
||
$site_name = '爱特工作室';
|
||
$site_tagline = '爱特工作室官方网站';
|
||
|
||
if (get_option('blogname') !== $site_name) {
|
||
update_option('blogname', $site_name);
|
||
}
|
||
|
||
if (get_option('blogdescription') !== $site_tagline) {
|
||
update_option('blogdescription', $site_tagline);
|
||
}
|
||
}
|
||
add_action('init', 'itstudio_apply_site_identity', 20);
|
||
|
||
function itstudio_output_favicon() {
|
||
$favicon_url = get_template_directory_uri() . '/resources/it_logo_2024.svg';
|
||
echo '<link rel="icon" href="' . esc_url($favicon_url) . '" type="image/svg+xml">' . "\n";
|
||
echo '<link rel="shortcut icon" href="' . esc_url($favicon_url) . '" type="image/svg+xml">' . "\n";
|
||
}
|
||
|
||
function itstudio_output_theme_bootstrap_script() {
|
||
echo '<meta name="color-scheme" content="dark light">' . "\n";
|
||
echo '<script>(function(){var d=document.documentElement;var t="light";try{var s=localStorage.getItem("theme");if(s==="dark"||s==="light"){t=s;}else if(window.matchMedia){t=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";}}catch(e){if(window.matchMedia){t=window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";}}d.setAttribute("data-theme",t);d.style.colorScheme=t;})();</script>' . "\n";
|
||
}
|
||
|
||
function itstudio_output_lang_bootstrap_script() {
|
||
echo '<style id="itstudio-lang-boot-style">html.itstudio-lang-pending body{visibility:hidden;}</style>' . "\n";
|
||
echo '<script>(function(){var d=document.documentElement;var lang="zh";d.classList.add("itstudio-lang-pending");try{var s=localStorage.getItem("language");if(s==="zh"||s==="en"){lang=s;}}catch(e){}d.setAttribute("lang",lang);window.__ITSTUDIO_LANG__=lang;var apply=function(root){var scope=root||document;var txt=scope.querySelectorAll("[data-cn][data-en]");for(var i=0;i<txt.length;i++){var el=txt[i];var next=lang==="en"?el.getAttribute("data-en"):el.getAttribute("data-cn");if(!next){continue;}if(el.tagName==="INPUT"||el.tagName==="TEXTAREA"){var tp=(el.getAttribute("type")||"").toLowerCase();if(tp==="submit"||tp==="button"||tp==="reset"){el.value=next;continue;}}el.textContent=next;}var ph=scope.querySelectorAll("[data-cn-placeholder][data-en-placeholder]");for(var j=0;j<ph.length;j++){var ep=ph[j];var pk=lang==="en"?"data-en-placeholder":"data-cn-placeholder";var pv=ep.getAttribute(pk);if(pv){ep.setAttribute("placeholder",pv);}}var ar=scope.querySelectorAll("[data-cn-aria-label][data-en-aria-label]");for(var k=0;k<ar.length;k++){var ea=ar[k];var ak=lang==="en"?"data-en-aria-label":"data-cn-aria-label";var av=ea.getAttribute(ak);if(av){ea.setAttribute("aria-label",av);}}};var finish=function(){if(document.body){document.body.setAttribute("lang",lang);}d.classList.remove("itstudio-lang-pending");var st=document.getElementById("itstudio-lang-boot-style");if(st&&st.parentNode){st.parentNode.removeChild(st);}};var run=function(){apply(document);finish();};if(document.readyState==="loading"){document.addEventListener("DOMContentLoaded",run,{once:true});}else{run();}})();</script>' . "\n";
|
||
}
|
||
function itstudio_disable_default_site_icon() {
|
||
remove_action('wp_head', 'wp_site_icon', 99);
|
||
remove_action('admin_head', 'wp_site_icon', 99);
|
||
remove_action('login_head', 'wp_site_icon', 99);
|
||
}
|
||
add_action('init', 'itstudio_disable_default_site_icon');
|
||
add_action('wp_head', 'itstudio_output_theme_bootstrap_script', 0);
|
||
add_action('wp_head', 'itstudio_output_lang_bootstrap_script', 1);
|
||
add_action('wp_head', 'itstudio_output_favicon', 1);
|
||
add_action('admin_head', 'itstudio_output_favicon', 1);
|
||
add_action('login_head', 'itstudio_output_favicon', 1);
|
||
|
||
function itstudio_enqueue_scripts() {
|
||
// 基础样式 (Style.css)
|
||
wp_enqueue_style('itstudio-style', get_stylesheet_uri(), array(), '2.1.2');
|
||
|
||
wp_enqueue_style('itstudio-header', get_template_directory_uri() . '/assets/css/header.css', array('itstudio-style'), '2.1.2');
|
||
wp_enqueue_style('itstudio-footer', get_template_directory_uri() . '/assets/css/footer.css', array('itstudio-style'), '2.1.2');
|
||
wp_enqueue_style('itstudio-content', get_template_directory_uri() . '/assets/css/content.css', array('itstudio-style'), '2.1.2');
|
||
|
||
// 仅在首页加载首页样式
|
||
if (is_front_page() || is_home()) {
|
||
wp_enqueue_style('itstudio-front-page', get_template_directory_uri() . '/assets/css/front-page.css', array('itstudio-style'), '2.1.2');
|
||
wp_enqueue_script('itstudio-landing-hero-canvas', get_template_directory_uri() . '/assets/js/landing-hero-canvas.js', array(), '1.0.0', true);
|
||
}
|
||
|
||
// 仅在工作室介绍页加载(包含 /about fallback)
|
||
$is_about = is_page('about') || is_page_template('page-about.php');
|
||
if (!$is_about && is_404()) {
|
||
global $wp;
|
||
$request = isset($wp->request) ? trim($wp->request, '/') : '';
|
||
$is_about = ($request === 'about');
|
||
}
|
||
|
||
if ($is_about) {
|
||
wp_enqueue_style('itstudio-about-hero', get_template_directory_uri() . '/assets/css/about-hero.css', array('itstudio-content'), '2.1.2');
|
||
wp_enqueue_script('itstudio-animejs', get_template_directory_uri() . '/assets/js/vendor/anime.min.js', array(), '3.2.2', true);
|
||
wp_enqueue_script('itstudio-about-hero-waves', get_template_directory_uri() . '/assets/js/hero-waves.js', array('itstudio-animejs'), '1.0.0', true);
|
||
wp_enqueue_script('itstudio-about-hero', get_template_directory_uri() . '/assets/js/home-hero.js', array('itstudio-animejs'), '1.0.0', true);
|
||
}
|
||
|
||
// 仅在便民服务页加载(包含 /services fallback)
|
||
$is_services = is_page('services') || is_page_template('page-services.php');
|
||
if (!$is_services && is_404()) {
|
||
global $wp;
|
||
$request = isset($wp->request) ? trim($wp->request, '/') : '';
|
||
$is_services = ($request === 'services');
|
||
}
|
||
|
||
if ($is_services) {
|
||
wp_enqueue_style('itstudio-services-page', get_template_directory_uri() . '/assets/css/services-page.css', array('itstudio-content'), '1.0.0');
|
||
}
|
||
|
||
// Scripts
|
||
wp_enqueue_script('itstudio-theme-toggle', get_template_directory_uri() . '/assets/js/theme-toggle.js', array(), '1.0.0', true);
|
||
wp_enqueue_script('itstudio-lang-toggle', get_template_directory_uri() . '/assets/js/lang-toggle.js', array(), '1.0.0', true);
|
||
wp_enqueue_script('itstudio-main', get_template_directory_uri() . '/assets/js/main.js', array(), '1.0.0', true);
|
||
|
||
if (is_singular(array('post', 'announcement', 'news'))) {
|
||
wp_enqueue_script('itstudio-single-title-fit', get_template_directory_uri() . '/assets/js/single-title-fit.js', array(), '1.0.0', true);
|
||
}
|
||
}
|
||
add_action('wp_enqueue_scripts', 'itstudio_enqueue_scripts');
|
||
|
||
function itstudio_register_sidebars() {
|
||
register_sidebar(array(
|
||
'name' => __('Footer - Column 1', 'itstudio'),
|
||
'id' => 'footer-1',
|
||
'description' => __('Footer widget area 1', 'itstudio'),
|
||
'before_widget' => '<div class="footer-widget">',
|
||
'after_widget' => '</div>',
|
||
'before_title' => '<h3 class="widget-title">',
|
||
'after_title' => '</h3>',
|
||
));
|
||
|
||
register_sidebar(array(
|
||
'name' => __('Footer - Column 2', 'itstudio'),
|
||
'id' => 'footer-2',
|
||
'description' => __('Footer widget area 2', 'itstudio'),
|
||
'before_widget' => '<div class="footer-widget">',
|
||
'after_widget' => '</div>',
|
||
'before_title' => '<h3 class="widget-title">',
|
||
'after_title' => '</h3>',
|
||
));
|
||
}
|
||
add_action('widgets_init', 'itstudio_register_sidebars');
|
||
|
||
function itstudio_intro_body_class($classes) {
|
||
$is_about = is_page('about') || is_page_template('page-about.php');
|
||
if (!$is_about && is_404()) {
|
||
global $wp;
|
||
$request = isset($wp->request) ? trim($wp->request, '/') : '';
|
||
$is_about = ($request === 'about');
|
||
}
|
||
|
||
if ($is_about) {
|
||
$classes[] = 'intro-about';
|
||
}
|
||
|
||
return $classes;
|
||
}
|
||
add_filter('body_class', 'itstudio_intro_body_class');
|
||
|
||
function itstudio_custom_post_types() {
|
||
register_post_type('announcement', array(
|
||
'labels' => array(
|
||
'name' => __('Announcements', 'itstudio'),
|
||
'singular_name' => __('Announcement', 'itstudio'),
|
||
),
|
||
'public' => true,
|
||
'has_archive' => true,
|
||
'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'custom-fields'),
|
||
'taxonomies' => array('post_tag'),
|
||
'menu_icon' => 'dashicons-megaphone',
|
||
'show_in_rest' => true,
|
||
));
|
||
|
||
register_post_type('news', array(
|
||
'labels' => array(
|
||
'name' => __('News', 'itstudio'),
|
||
'singular_name' => __('News', 'itstudio'),
|
||
),
|
||
'public' => true,
|
||
'has_archive' => 'news',
|
||
'rewrite' => array(
|
||
'slug' => 'news',
|
||
'with_front' => false,
|
||
),
|
||
'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'custom-fields'),
|
||
'taxonomies' => array('post_tag'),
|
||
'menu_icon' => 'dashicons-media-document',
|
||
'show_in_rest' => true,
|
||
));
|
||
|
||
register_taxonomy('service_category', array('service'), array(
|
||
'labels' => array(
|
||
'name' => __('服务分类', 'itstudio'),
|
||
'singular_name' => __('服务分类', 'itstudio'),
|
||
),
|
||
'hierarchical' => true,
|
||
'public' => true,
|
||
'show_ui' => true,
|
||
'show_admin_column' => false,
|
||
'show_in_rest' => true,
|
||
'rewrite' => array(
|
||
'slug' => 'service-category',
|
||
'with_front' => false,
|
||
),
|
||
));
|
||
|
||
register_post_type('service', array(
|
||
'labels' => array(
|
||
'name' => __('便民服务', 'itstudio'),
|
||
'singular_name' => __('便民服务', 'itstudio'),
|
||
'menu_name' => __('便民服务', 'itstudio'),
|
||
'add_new_item' => __('新增便民服务', 'itstudio'),
|
||
'edit_item' => __('编辑便民服务', 'itstudio'),
|
||
),
|
||
'public' => true,
|
||
'show_ui' => true,
|
||
'show_in_menu' => true,
|
||
'show_in_nav_menus' => false,
|
||
'exclude_from_search' => true,
|
||
'publicly_queryable' => true,
|
||
'has_archive' => false,
|
||
'rewrite' => array(
|
||
'slug' => 'service',
|
||
'with_front' => false,
|
||
),
|
||
'supports' => array('title', 'excerpt', 'thumbnail', 'page-attributes'),
|
||
'taxonomies' => array('service_category'),
|
||
'menu_icon' => 'dashicons-admin-tools',
|
||
'show_in_rest' => true,
|
||
));
|
||
|
||
register_taxonomy_for_object_type('post_tag', 'announcement');
|
||
register_taxonomy_for_object_type('post_tag', 'news');
|
||
}
|
||
add_action('init', 'itstudio_custom_post_types');
|
||
|
||
function itstudio_register_acf_fields() {
|
||
if (!function_exists('acf_add_local_field_group')) {
|
||
return;
|
||
}
|
||
|
||
acf_add_local_field_group(array(
|
||
'key' => 'group_itstudio_content_priority',
|
||
'title' => '内容权重',
|
||
'fields' => array(
|
||
array(
|
||
'key' => 'field_itstudio_weight',
|
||
'label' => '权重',
|
||
'name' => 'itstudio_weight',
|
||
'type' => 'number',
|
||
'instructions' => '数值越大,文章在侧栏排序越靠前。',
|
||
'required' => 0,
|
||
'default_value' => 0,
|
||
'min' => 0,
|
||
'step' => 1,
|
||
),
|
||
),
|
||
'location' => array(
|
||
array(
|
||
array(
|
||
'param' => 'post_type',
|
||
'operator' => '==',
|
||
'value' => 'post',
|
||
),
|
||
),
|
||
array(
|
||
array(
|
||
'param' => 'post_type',
|
||
'operator' => '==',
|
||
'value' => 'announcement',
|
||
),
|
||
),
|
||
array(
|
||
array(
|
||
'param' => 'post_type',
|
||
'operator' => '==',
|
||
'value' => 'news',
|
||
),
|
||
),
|
||
),
|
||
'position' => 'side',
|
||
'style' => 'default',
|
||
'active' => true,
|
||
'show_in_rest' => 1,
|
||
));
|
||
}
|
||
add_action('acf/init', 'itstudio_register_acf_fields');
|
||
|
||
function itstudio_get_service_url_meta_key() {
|
||
return '_itstudio_service_url';
|
||
}
|
||
|
||
function itstudio_get_service_title_cn_meta_key() {
|
||
return '_itstudio_service_title_cn';
|
||
}
|
||
|
||
function itstudio_get_service_title_en_meta_key() {
|
||
return '_itstudio_service_title_en';
|
||
}
|
||
|
||
function itstudio_get_service_excerpt_cn_meta_key() {
|
||
return '_itstudio_service_excerpt_cn';
|
||
}
|
||
|
||
function itstudio_get_service_excerpt_en_meta_key() {
|
||
return '_itstudio_service_excerpt_en';
|
||
}
|
||
|
||
function itstudio_get_service_category_name_cn_meta_key() {
|
||
return 'itstudio_service_category_name_cn';
|
||
}
|
||
|
||
function itstudio_get_service_category_name_en_meta_key() {
|
||
return 'itstudio_service_category_name_en';
|
||
}
|
||
|
||
function itstudio_get_service_category_i18n_labels($term) {
|
||
if (!$term || is_wp_error($term)) {
|
||
return array(
|
||
'cn' => '未分类',
|
||
'en' => 'Uncategorized',
|
||
);
|
||
}
|
||
|
||
$term_id = (int) $term->term_id;
|
||
$name_cn = trim((string) get_term_meta($term_id, itstudio_get_service_category_name_cn_meta_key(), true));
|
||
$name_en = trim((string) get_term_meta($term_id, itstudio_get_service_category_name_en_meta_key(), true));
|
||
|
||
if ($name_cn === '') {
|
||
$name_cn = (string) $term->name;
|
||
}
|
||
if ($name_en === '') {
|
||
$name_en = $name_cn;
|
||
}
|
||
|
||
return array(
|
||
'cn' => $name_cn,
|
||
'en' => $name_en,
|
||
);
|
||
}
|
||
|
||
function itstudio_get_service_i18n_content($service_id, $excerpt_limit = 90) {
|
||
$service_id = (int) $service_id;
|
||
if ($service_id <= 0) {
|
||
return array(
|
||
'title_cn' => '',
|
||
'title_en' => '',
|
||
'excerpt_cn' => '',
|
||
'excerpt_en' => '',
|
||
);
|
||
}
|
||
|
||
$title_cn = trim((string) get_post_meta($service_id, itstudio_get_service_title_cn_meta_key(), true));
|
||
$title_en = trim((string) get_post_meta($service_id, itstudio_get_service_title_en_meta_key(), true));
|
||
$excerpt_cn = trim((string) get_post_meta($service_id, itstudio_get_service_excerpt_cn_meta_key(), true));
|
||
$excerpt_en = trim((string) get_post_meta($service_id, itstudio_get_service_excerpt_en_meta_key(), true));
|
||
|
||
$fallback_title = trim((string) get_the_title($service_id));
|
||
if ($fallback_title === '') {
|
||
$fallback_title = '未命名服务';
|
||
}
|
||
|
||
$fallback_excerpt = function_exists('itstudio_get_post_excerpt_chars')
|
||
? itstudio_get_post_excerpt_chars($service_id, $excerpt_limit)
|
||
: wp_html_excerpt(wp_strip_all_tags((string) get_post_field('post_excerpt', $service_id)), $excerpt_limit, '...');
|
||
$fallback_excerpt = trim((string) $fallback_excerpt);
|
||
if ($fallback_excerpt === '') {
|
||
$fallback_excerpt = '暂无简介';
|
||
}
|
||
|
||
if ($title_cn === '') {
|
||
$title_cn = $fallback_title;
|
||
}
|
||
if ($title_en === '') {
|
||
$title_en = $title_cn;
|
||
}
|
||
if ($excerpt_cn === '') {
|
||
$excerpt_cn = $fallback_excerpt;
|
||
}
|
||
if ($excerpt_en === '') {
|
||
$excerpt_en = $excerpt_cn;
|
||
}
|
||
|
||
return array(
|
||
'title_cn' => $title_cn,
|
||
'title_en' => $title_en,
|
||
'excerpt_cn' => $excerpt_cn,
|
||
'excerpt_en' => $excerpt_en,
|
||
);
|
||
}
|
||
|
||
function itstudio_add_service_meta_boxes() {
|
||
add_meta_box(
|
||
'itstudio_service_link',
|
||
__('服务双语与链接', 'itstudio'),
|
||
'itstudio_render_service_link_meta_box',
|
||
'service',
|
||
'normal',
|
||
'high'
|
||
);
|
||
}
|
||
add_action('add_meta_boxes', 'itstudio_add_service_meta_boxes');
|
||
|
||
function itstudio_render_service_link_meta_box($post) {
|
||
$service_url = (string) get_post_meta($post->ID, itstudio_get_service_url_meta_key(), true);
|
||
$title_cn = (string) get_post_meta($post->ID, itstudio_get_service_title_cn_meta_key(), true);
|
||
$title_en = (string) get_post_meta($post->ID, itstudio_get_service_title_en_meta_key(), true);
|
||
$excerpt_cn = (string) get_post_meta($post->ID, itstudio_get_service_excerpt_cn_meta_key(), true);
|
||
$excerpt_en = (string) get_post_meta($post->ID, itstudio_get_service_excerpt_en_meta_key(), true);
|
||
wp_nonce_field('itstudio_save_service_meta', 'itstudio_service_meta_nonce');
|
||
?>
|
||
<p>
|
||
<label for="itstudio_service_title_cn"><strong><?php esc_html_e('中文名称', 'itstudio'); ?></strong></label>
|
||
</p>
|
||
<p>
|
||
<input
|
||
type="text"
|
||
id="itstudio_service_title_cn"
|
||
name="itstudio_service_title_cn"
|
||
class="widefat"
|
||
placeholder="<?php echo esc_attr((string) get_the_title($post)); ?>"
|
||
value="<?php echo esc_attr($title_cn); ?>"
|
||
>
|
||
</p>
|
||
<p>
|
||
<label for="itstudio_service_title_en"><strong><?php esc_html_e('英文名称', 'itstudio'); ?></strong></label>
|
||
</p>
|
||
<p>
|
||
<input
|
||
type="text"
|
||
id="itstudio_service_title_en"
|
||
name="itstudio_service_title_en"
|
||
class="widefat"
|
||
placeholder="Service Name"
|
||
value="<?php echo esc_attr($title_en); ?>"
|
||
>
|
||
</p>
|
||
<p>
|
||
<label for="itstudio_service_excerpt_cn"><strong><?php esc_html_e('中文简介', 'itstudio'); ?></strong></label>
|
||
</p>
|
||
<p>
|
||
<textarea
|
||
id="itstudio_service_excerpt_cn"
|
||
name="itstudio_service_excerpt_cn"
|
||
class="widefat"
|
||
rows="3"
|
||
placeholder="<?php echo esc_attr((string) get_the_excerpt($post)); ?>"
|
||
><?php echo esc_textarea($excerpt_cn); ?></textarea>
|
||
</p>
|
||
<p>
|
||
<label for="itstudio_service_excerpt_en"><strong><?php esc_html_e('英文简介', 'itstudio'); ?></strong></label>
|
||
</p>
|
||
<p>
|
||
<textarea
|
||
id="itstudio_service_excerpt_en"
|
||
name="itstudio_service_excerpt_en"
|
||
class="widefat"
|
||
rows="3"
|
||
placeholder="Short English description"
|
||
><?php echo esc_textarea($excerpt_en); ?></textarea>
|
||
</p>
|
||
<p>
|
||
<label for="itstudio_service_url"><strong><?php esc_html_e('目标链接', 'itstudio'); ?></strong></label>
|
||
</p>
|
||
<p>
|
||
<input
|
||
type="url"
|
||
id="itstudio_service_url"
|
||
name="itstudio_service_url"
|
||
class="widefat"
|
||
placeholder="https://example.com"
|
||
value="<?php echo esc_attr($service_url); ?>"
|
||
>
|
||
</p>
|
||
<p class="description">
|
||
<?php esc_html_e('支持分别填写中英文名称与简介;未填写时会回退到标题/摘要。', 'itstudio'); ?>
|
||
</p>
|
||
<?php
|
||
}
|
||
|
||
function itstudio_save_service_meta($post_id) {
|
||
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
|
||
return;
|
||
}
|
||
|
||
if (!isset($_POST['itstudio_service_meta_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['itstudio_service_meta_nonce'])), 'itstudio_save_service_meta')) {
|
||
return;
|
||
}
|
||
|
||
if (!current_user_can('edit_post', $post_id)) {
|
||
return;
|
||
}
|
||
|
||
if (get_post_type($post_id) !== 'service') {
|
||
return;
|
||
}
|
||
|
||
$title_cn = isset($_POST['itstudio_service_title_cn']) ? sanitize_text_field(wp_unslash($_POST['itstudio_service_title_cn'])) : '';
|
||
$title_en = isset($_POST['itstudio_service_title_en']) ? sanitize_text_field(wp_unslash($_POST['itstudio_service_title_en'])) : '';
|
||
$excerpt_cn = isset($_POST['itstudio_service_excerpt_cn']) ? sanitize_textarea_field(wp_unslash($_POST['itstudio_service_excerpt_cn'])) : '';
|
||
$excerpt_en = isset($_POST['itstudio_service_excerpt_en']) ? sanitize_textarea_field(wp_unslash($_POST['itstudio_service_excerpt_en'])) : '';
|
||
|
||
$meta_updates = array(
|
||
itstudio_get_service_title_cn_meta_key() => trim($title_cn),
|
||
itstudio_get_service_title_en_meta_key() => trim($title_en),
|
||
itstudio_get_service_excerpt_cn_meta_key() => trim($excerpt_cn),
|
||
itstudio_get_service_excerpt_en_meta_key() => trim($excerpt_en),
|
||
);
|
||
|
||
foreach ($meta_updates as $meta_key => $value) {
|
||
if ($value === '') {
|
||
delete_post_meta($post_id, $meta_key);
|
||
} else {
|
||
update_post_meta($post_id, $meta_key, $value);
|
||
}
|
||
}
|
||
|
||
$url_meta_key = itstudio_get_service_url_meta_key();
|
||
$raw_url = isset($_POST['itstudio_service_url']) ? trim((string) wp_unslash($_POST['itstudio_service_url'])) : '';
|
||
|
||
if ($raw_url === '') {
|
||
delete_post_meta($post_id, $url_meta_key);
|
||
return;
|
||
}
|
||
|
||
if (strpos($raw_url, '/') === 0) {
|
||
$raw_url = home_url($raw_url);
|
||
}
|
||
|
||
$service_url = esc_url_raw($raw_url);
|
||
if ($service_url === '') {
|
||
delete_post_meta($post_id, $url_meta_key);
|
||
return;
|
||
}
|
||
|
||
update_post_meta($post_id, $url_meta_key, $service_url);
|
||
}
|
||
add_action('save_post_service', 'itstudio_save_service_meta');
|
||
|
||
function itstudio_service_category_add_fields($taxonomy) {
|
||
wp_nonce_field('itstudio_save_service_category_meta', 'itstudio_service_category_meta_nonce');
|
||
?>
|
||
<div class="form-field term-itstudio-service-name-cn-wrap">
|
||
<label for="itstudio_service_cat_name_cn"><?php esc_html_e('中文名称', 'itstudio'); ?></label>
|
||
<input type="text" name="itstudio_service_cat_name_cn" id="itstudio_service_cat_name_cn" value="">
|
||
</div>
|
||
<div class="form-field term-itstudio-service-name-en-wrap">
|
||
<label for="itstudio_service_cat_name_en"><?php esc_html_e('英文名称', 'itstudio'); ?></label>
|
||
<input type="text" name="itstudio_service_cat_name_en" id="itstudio_service_cat_name_en" value="" placeholder="Category Name">
|
||
</div>
|
||
<?php
|
||
}
|
||
add_action('service_category_add_form_fields', 'itstudio_service_category_add_fields');
|
||
|
||
function itstudio_service_category_edit_fields($term) {
|
||
$term_id = (int) $term->term_id;
|
||
$name_cn = (string) get_term_meta($term_id, itstudio_get_service_category_name_cn_meta_key(), true);
|
||
$name_en = (string) get_term_meta($term_id, itstudio_get_service_category_name_en_meta_key(), true);
|
||
wp_nonce_field('itstudio_save_service_category_meta', 'itstudio_service_category_meta_nonce');
|
||
?>
|
||
<tr class="form-field term-itstudio-service-name-cn-wrap">
|
||
<th scope="row"><label for="itstudio_service_cat_name_cn"><?php esc_html_e('中文名称', 'itstudio'); ?></label></th>
|
||
<td><input type="text" name="itstudio_service_cat_name_cn" id="itstudio_service_cat_name_cn" value="<?php echo esc_attr($name_cn); ?>"></td>
|
||
</tr>
|
||
<tr class="form-field term-itstudio-service-name-en-wrap">
|
||
<th scope="row"><label for="itstudio_service_cat_name_en"><?php esc_html_e('英文名称', 'itstudio'); ?></label></th>
|
||
<td><input type="text" name="itstudio_service_cat_name_en" id="itstudio_service_cat_name_en" value="<?php echo esc_attr($name_en); ?>" placeholder="Category Name"></td>
|
||
</tr>
|
||
<?php
|
||
}
|
||
add_action('service_category_edit_form_fields', 'itstudio_service_category_edit_fields');
|
||
|
||
function itstudio_save_service_category_meta($term_id) {
|
||
if (!current_user_can('manage_categories')) {
|
||
return;
|
||
}
|
||
|
||
if (!isset($_POST['itstudio_service_category_meta_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['itstudio_service_category_meta_nonce'])), 'itstudio_save_service_category_meta')) {
|
||
return;
|
||
}
|
||
|
||
$name_cn = isset($_POST['itstudio_service_cat_name_cn']) ? sanitize_text_field(wp_unslash($_POST['itstudio_service_cat_name_cn'])) : '';
|
||
$name_en = isset($_POST['itstudio_service_cat_name_en']) ? sanitize_text_field(wp_unslash($_POST['itstudio_service_cat_name_en'])) : '';
|
||
|
||
$term_meta = array(
|
||
itstudio_get_service_category_name_cn_meta_key() => trim($name_cn),
|
||
itstudio_get_service_category_name_en_meta_key() => trim($name_en),
|
||
);
|
||
|
||
foreach ($term_meta as $meta_key => $value) {
|
||
if ($value === '') {
|
||
delete_term_meta($term_id, $meta_key);
|
||
} else {
|
||
update_term_meta($term_id, $meta_key, $value);
|
||
}
|
||
}
|
||
}
|
||
add_action('created_service_category', 'itstudio_save_service_category_meta');
|
||
add_action('edited_service_category', 'itstudio_save_service_category_meta');
|
||
|
||
function itstudio_get_service_target_url($service_id) {
|
||
$service_id = (int) $service_id;
|
||
if ($service_id <= 0) {
|
||
return '';
|
||
}
|
||
|
||
$meta_key = itstudio_get_service_url_meta_key();
|
||
$url = (string) get_post_meta($service_id, $meta_key, true);
|
||
if ($url !== '') {
|
||
return $url;
|
||
}
|
||
|
||
return (string) get_permalink($service_id);
|
||
}
|
||
|
||
function itstudio_service_admin_columns($columns) {
|
||
$columns['service_category'] = __('分类', 'itstudio');
|
||
$columns['service_url'] = __('跳转链接', 'itstudio');
|
||
return $columns;
|
||
}
|
||
add_filter('manage_service_posts_columns', 'itstudio_service_admin_columns');
|
||
|
||
function itstudio_service_admin_custom_column($column, $post_id) {
|
||
if ($column === 'service_category') {
|
||
$terms = get_the_terms($post_id, 'service_category');
|
||
if (empty($terms) || is_wp_error($terms)) {
|
||
echo '<span style="color:#888;">' . esc_html__('未分类', 'itstudio') . '</span>';
|
||
return;
|
||
}
|
||
|
||
$labels = array();
|
||
foreach ($terms as $term) {
|
||
$i18n = itstudio_get_service_category_i18n_labels($term);
|
||
$label = $i18n['cn'];
|
||
if ($i18n['en'] !== $i18n['cn']) {
|
||
$label .= ' / ' . $i18n['en'];
|
||
}
|
||
$labels[] = $label;
|
||
}
|
||
|
||
echo esc_html(implode(' | ', $labels));
|
||
return;
|
||
}
|
||
|
||
if ($column === 'service_url') {
|
||
$url = itstudio_get_service_target_url($post_id);
|
||
if ($url === '') {
|
||
echo '<span style="color:#888;">-</span>';
|
||
return;
|
||
}
|
||
|
||
echo '<a href="' . esc_url($url) . '" target="_blank" rel="noopener noreferrer">' . esc_html($url) . '</a>';
|
||
}
|
||
}
|
||
add_action('manage_service_posts_custom_column', 'itstudio_service_admin_custom_column', 10, 2);
|
||
|
||
function itstudio_archive_document_title($parts) {
|
||
if (is_post_type_archive('announcement')) {
|
||
$parts['title'] = '公告通知';
|
||
} elseif (is_post_type_archive('news')) {
|
||
$parts['title'] = '社团新闻';
|
||
}
|
||
|
||
return $parts;
|
||
}
|
||
add_filter('document_title_parts', 'itstudio_archive_document_title', 20);
|
||
|
||
// Fallback: render /about even if the page isn't created in WP admin.
|
||
function itstudio_about_fallback() {
|
||
if (!is_404()) {
|
||
return;
|
||
}
|
||
|
||
global $wp;
|
||
$request = isset($wp->request) ? trim($wp->request, '/') : '';
|
||
if ($request !== 'about') {
|
||
return;
|
||
}
|
||
|
||
$template = locate_template('page-about.php');
|
||
if ($template) {
|
||
global $wp_query;
|
||
if ($wp_query) {
|
||
$wp_query->is_404 = false;
|
||
$wp_query->is_page = true;
|
||
$wp_query->is_singular = true;
|
||
$virtual_post = new WP_Post((object) array(
|
||
'ID' => 0,
|
||
'post_type' => 'page',
|
||
'post_parent' => 0,
|
||
'post_title' => __('工作室介绍', 'itstudio'),
|
||
'post_status' => 'publish',
|
||
'post_name' => 'about',
|
||
'post_content' => '',
|
||
));
|
||
$wp_query->post = $virtual_post;
|
||
$wp_query->posts = array($virtual_post);
|
||
$wp_query->queried_object = $virtual_post;
|
||
$wp_query->queried_object_id = 0;
|
||
$wp_query->post_count = 1;
|
||
$wp_query->found_posts = 1;
|
||
$wp_query->max_num_pages = 1;
|
||
global $post;
|
||
$post = $virtual_post;
|
||
setup_postdata($post);
|
||
}
|
||
add_filter('document_title_parts', function ($parts) {
|
||
$parts['title'] = __('工作室介绍', 'itstudio');
|
||
return $parts;
|
||
});
|
||
status_header(200);
|
||
nocache_headers();
|
||
include $template;
|
||
exit;
|
||
}
|
||
}
|
||
add_action('template_redirect', 'itstudio_about_fallback');
|
||
|
||
// Fallback: render /news via archive.php even if the page isn't created in WP admin.
|
||
function itstudio_news_fallback() {
|
||
if (!is_404()) {
|
||
return;
|
||
}
|
||
|
||
global $wp;
|
||
$request = isset($wp->request) ? trim($wp->request, '/') : '';
|
||
if ($request !== 'news') {
|
||
return;
|
||
}
|
||
|
||
$template = locate_template('archive.php');
|
||
if ($template) {
|
||
global $wp_query;
|
||
if ($wp_query) {
|
||
$wp_query->is_404 = false;
|
||
$wp_query->is_page = true;
|
||
$wp_query->is_singular = true;
|
||
$virtual_post = new WP_Post((object) array(
|
||
'ID' => 0,
|
||
'post_type' => 'page',
|
||
'post_parent' => 0,
|
||
'post_title' => __('社团新闻', 'itstudio'),
|
||
'post_status' => 'publish',
|
||
'post_name' => 'news',
|
||
'post_content' => '',
|
||
));
|
||
$wp_query->post = $virtual_post;
|
||
$wp_query->posts = array($virtual_post);
|
||
$wp_query->queried_object = $virtual_post;
|
||
$wp_query->queried_object_id = 0;
|
||
$wp_query->post_count = 1;
|
||
$wp_query->found_posts = 1;
|
||
$wp_query->max_num_pages = 1;
|
||
global $post;
|
||
$post = $virtual_post;
|
||
setup_postdata($post);
|
||
}
|
||
add_filter('document_title_parts', function ($parts) {
|
||
$parts['title'] = __('社团新闻', 'itstudio');
|
||
return $parts;
|
||
});
|
||
$GLOBALS['itstudio_archive_mode'] = 'news';
|
||
status_header(200);
|
||
nocache_headers();
|
||
include $template;
|
||
unset($GLOBALS['itstudio_archive_mode']);
|
||
exit;
|
||
}
|
||
}
|
||
add_action('template_redirect', 'itstudio_news_fallback');
|
||
|
||
// Fallback: render /services even if the page isn't created in WP admin.
|
||
function itstudio_services_fallback() {
|
||
if (!is_404()) {
|
||
return;
|
||
}
|
||
|
||
global $wp;
|
||
$request = isset($wp->request) ? trim($wp->request, '/') : '';
|
||
if ($request !== 'services') {
|
||
return;
|
||
}
|
||
|
||
$template = locate_template('page-services.php');
|
||
if ($template) {
|
||
global $wp_query;
|
||
if ($wp_query) {
|
||
$wp_query->is_404 = false;
|
||
$wp_query->is_page = true;
|
||
$wp_query->is_singular = true;
|
||
$virtual_post = new WP_Post((object) array(
|
||
'ID' => 0,
|
||
'post_type' => 'page',
|
||
'post_parent' => 0,
|
||
'post_title' => __('便民服务', 'itstudio'),
|
||
'post_status' => 'publish',
|
||
'post_name' => 'services',
|
||
'post_content' => '',
|
||
));
|
||
$wp_query->post = $virtual_post;
|
||
$wp_query->posts = array($virtual_post);
|
||
$wp_query->queried_object = $virtual_post;
|
||
$wp_query->queried_object_id = 0;
|
||
$wp_query->post_count = 1;
|
||
$wp_query->found_posts = 1;
|
||
$wp_query->max_num_pages = 1;
|
||
global $post;
|
||
$post = $virtual_post;
|
||
setup_postdata($post);
|
||
}
|
||
add_filter('document_title_parts', function ($parts) {
|
||
$parts['title'] = __('便民服务', 'itstudio');
|
||
return $parts;
|
||
});
|
||
status_header(200);
|
||
nocache_headers();
|
||
include $template;
|
||
exit;
|
||
}
|
||
}
|
||
add_action('template_redirect', 'itstudio_services_fallback');
|
||
|
||
function itstudio_get_post_views($post_id) {
|
||
$post_id = (int) $post_id;
|
||
if ($post_id <= 0) {
|
||
return 0;
|
||
}
|
||
|
||
$meta_keys = array(
|
||
'post_views_count',
|
||
'itstudio_views',
|
||
'views',
|
||
'post_views',
|
||
'view_count',
|
||
'views_count',
|
||
);
|
||
|
||
$max_views = 0;
|
||
foreach ($meta_keys as $meta_key) {
|
||
$raw = get_post_meta($post_id, $meta_key, true);
|
||
if ($raw !== '' && is_numeric($raw)) {
|
||
$max_views = max($max_views, (int) $raw);
|
||
}
|
||
}
|
||
|
||
return max(0, $max_views);
|
||
}
|
||
|
||
function itstudio_get_post_weight($post_id, $field_name = 'itstudio_weight') {
|
||
$post_id = (int) $post_id;
|
||
if ($post_id <= 0) {
|
||
return 0;
|
||
}
|
||
|
||
if (!function_exists('get_field')) {
|
||
return 0;
|
||
}
|
||
|
||
$raw = get_field($field_name, $post_id, false);
|
||
if ($raw === '' || $raw === null || !is_numeric($raw)) {
|
||
return 0;
|
||
}
|
||
|
||
return (int) $raw;
|
||
}
|
||
|
||
function itstudio_get_post_char_count($post_id) {
|
||
$post_id = (int) $post_id;
|
||
if ($post_id <= 0) {
|
||
return 0;
|
||
}
|
||
|
||
$content = (string) get_post_field('post_content', $post_id);
|
||
$plain_text = trim(wp_strip_all_tags($content));
|
||
if ($plain_text === '') {
|
||
return 0;
|
||
}
|
||
|
||
if (function_exists('mb_strlen')) {
|
||
return (int) mb_strlen($plain_text, 'UTF-8');
|
||
}
|
||
|
||
return (int) strlen($plain_text);
|
||
}
|
||
|
||
function itstudio_get_post_excerpt_chars($post_id, $limit = 200) {
|
||
$post_id = (int) $post_id;
|
||
$limit = max(1, (int) $limit);
|
||
if ($post_id <= 0) {
|
||
return '';
|
||
}
|
||
|
||
$excerpt = (string) get_post_field('post_excerpt', $post_id);
|
||
if (trim($excerpt) === '') {
|
||
$excerpt = (string) get_post_field('post_content', $post_id);
|
||
}
|
||
|
||
$excerpt = trim(wp_strip_all_tags($excerpt));
|
||
if ($excerpt === '') {
|
||
return '';
|
||
}
|
||
|
||
return wp_html_excerpt($excerpt, $limit, '...');
|
||
}
|
||
|
||
function itstudio_is_probably_bot_request() {
|
||
$user_agent = strtolower(trim((string) ($_SERVER['HTTP_USER_AGENT'] ?? '')));
|
||
if ($user_agent === '') {
|
||
return true;
|
||
}
|
||
|
||
$bot_signatures = array(
|
||
'bot',
|
||
'spider',
|
||
'crawl',
|
||
'slurp',
|
||
'headless',
|
||
'preview',
|
||
'facebookexternalhit',
|
||
'discordbot',
|
||
'telegrambot',
|
||
'linkedinbot',
|
||
'applebot',
|
||
'googlebot',
|
||
'bingbot',
|
||
'wget',
|
||
'curl',
|
||
'python-requests',
|
||
'postmanruntime',
|
||
);
|
||
|
||
foreach ($bot_signatures as $signature) {
|
||
if (strpos($user_agent, $signature) !== false) {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
$purpose = strtolower((string) ($_SERVER['HTTP_PURPOSE'] ?? ''));
|
||
$sec_purpose = strtolower((string) ($_SERVER['HTTP_SEC_PURPOSE'] ?? ''));
|
||
$x_moz = strtolower((string) ($_SERVER['HTTP_X_MOZ'] ?? ''));
|
||
if (strpos($purpose, 'prefetch') !== false || strpos($sec_purpose, 'prefetch') !== false || $x_moz === 'prefetch') {
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
function itstudio_get_view_cookie_name() {
|
||
return 'itstudio_viewed_posts';
|
||
}
|
||
|
||
function itstudio_read_view_cookie_map() {
|
||
$cookie_name = itstudio_get_view_cookie_name();
|
||
$raw_cookie = isset($_COOKIE[$cookie_name]) ? wp_unslash((string) $_COOKIE[$cookie_name]) : '';
|
||
if ($raw_cookie === '') {
|
||
return array();
|
||
}
|
||
|
||
$decoded = json_decode($raw_cookie, true);
|
||
if (!is_array($decoded)) {
|
||
return array();
|
||
}
|
||
|
||
$clean = array();
|
||
foreach ($decoded as $post_id => $timestamp) {
|
||
$post_id = (int) $post_id;
|
||
$timestamp = (int) $timestamp;
|
||
if ($post_id > 0 && $timestamp > 0) {
|
||
$clean[(string) $post_id] = $timestamp;
|
||
}
|
||
}
|
||
|
||
return $clean;
|
||
}
|
||
|
||
function itstudio_write_view_cookie_map($map, $window_seconds) {
|
||
if (!headers_sent()) {
|
||
$cookie_name = itstudio_get_view_cookie_name();
|
||
$expire_at = time() + max(DAY_IN_SECONDS, (int) $window_seconds * 2);
|
||
$path = defined('COOKIEPATH') && COOKIEPATH ? COOKIEPATH : '/';
|
||
$domain = defined('COOKIE_DOMAIN') ? COOKIE_DOMAIN : '';
|
||
$secure = is_ssl();
|
||
$http_only = true;
|
||
$encoded = wp_json_encode($map);
|
||
if (!is_string($encoded)) {
|
||
return;
|
||
}
|
||
|
||
if (PHP_VERSION_ID >= 70300) {
|
||
setcookie($cookie_name, $encoded, array(
|
||
'expires' => $expire_at,
|
||
'path' => $path,
|
||
'domain' => $domain,
|
||
'secure' => $secure,
|
||
'httponly' => $http_only,
|
||
'samesite' => 'Lax',
|
||
));
|
||
} else {
|
||
setcookie($cookie_name, $encoded, $expire_at, $path, $domain, $secure, $http_only);
|
||
}
|
||
|
||
$_COOKIE[$cookie_name] = $encoded;
|
||
}
|
||
}
|
||
|
||
function itstudio_should_count_post_view($post_id) {
|
||
$post_id = (int) $post_id;
|
||
if ($post_id <= 0) {
|
||
return false;
|
||
}
|
||
|
||
if (itstudio_is_probably_bot_request()) {
|
||
return false;
|
||
}
|
||
|
||
$window_seconds = (int) apply_filters('itstudio_post_view_window_seconds', 12 * HOUR_IN_SECONDS);
|
||
$window_seconds = max(60, $window_seconds);
|
||
$max_entries = (int) apply_filters('itstudio_post_view_cookie_max_entries', 120);
|
||
$max_entries = max(10, $max_entries);
|
||
|
||
$now = time();
|
||
$key = (string) $post_id;
|
||
$map = itstudio_read_view_cookie_map();
|
||
|
||
foreach ($map as $id => $timestamp) {
|
||
if (($now - (int) $timestamp) > $window_seconds) {
|
||
unset($map[$id]);
|
||
}
|
||
}
|
||
|
||
if (isset($map[$key]) && ($now - (int) $map[$key]) < $window_seconds) {
|
||
return false;
|
||
}
|
||
|
||
$map[$key] = $now;
|
||
if (count($map) > $max_entries) {
|
||
asort($map, SORT_NUMERIC);
|
||
$map = array_slice($map, -$max_entries, null, true);
|
||
}
|
||
|
||
itstudio_write_view_cookie_map($map, $window_seconds);
|
||
|
||
return true;
|
||
}
|
||
|
||
function itstudio_track_post_views() {
|
||
if (is_admin() || wp_doing_ajax() || wp_doing_cron()) {
|
||
return;
|
||
}
|
||
|
||
if (!is_singular(array('post', 'announcement', 'news')) || is_preview() || is_feed() || is_trackback() || is_embed()) {
|
||
return;
|
||
}
|
||
|
||
if (!isset($_SERVER['REQUEST_METHOD']) || strtoupper((string) $_SERVER['REQUEST_METHOD']) !== 'GET') {
|
||
return;
|
||
}
|
||
|
||
$post_id = (int) get_queried_object_id();
|
||
if ($post_id <= 0) {
|
||
return;
|
||
}
|
||
|
||
if (!itstudio_should_count_post_view($post_id)) {
|
||
return;
|
||
}
|
||
|
||
$views = itstudio_get_post_views($post_id) + 1;
|
||
update_post_meta($post_id, 'post_views_count', $views);
|
||
update_post_meta($post_id, 'itstudio_views', $views);
|
||
}
|
||
add_action('template_redirect', 'itstudio_track_post_views', 20);
|