Files
ITStudioMainSite/plugins/itstudio-recruitment/includes/recruitment-articles.php
T
2026-07-21 09:55:39 +08:00

296 lines
9.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 招新文章标记:ACF “招新文章标记” 字段组、is_recruitment_article 判定、
* 编辑页 meta box、以及“加入我们”页顶部招新新闻 feed。
* 抽离自主题 functions.php(lift-and-shift,逻辑未改)。
*/
if (!defined('ABSPATH')) {
exit;
}
function itstudio_register_acf_fields() {
if (!function_exists('acf_add_local_field_group')) {
return;
}
acf_add_local_field_group(array(
'key' => 'group_itstudio_recruitment_article',
'title' => '招新文章标记',
'fields' => array(
array(
'key' => 'field_itstudio_is_recruitment_article',
'label' => '是否为招新文章',
'name' => 'itstudio_is_recruitment_article',
'type' => 'true_false',
'instructions' => '勾选后,该文章会在“加入我们”页面顶部新闻条中显示(按发布时间排序)。',
'required' => 0,
'default_value' => 0,
'ui' => 1,
'ui_on_text' => '是',
'ui_off_text' => '否',
),
),
'location' => array(
array(
array(
'param' => 'post_type',
'operator' => '==',
'value' => 'announcement',
),
),
array(
array(
'param' => 'post_type',
'operator' => '==',
'value' => 'news',
),
),
array(
array(
'param' => 'post_type',
'operator' => '==',
'value' => 'post',
),
),
),
'position' => 'side',
'style' => 'default',
'active' => true,
'show_in_rest' => 1,
));
}
add_action('acf/init', 'itstudio_register_acf_fields');
function itstudio_get_recruitment_article_meta_key() {
return 'itstudio_is_recruitment_article';
}
function itstudio_normalize_recruitment_flag($value) {
if (is_bool($value)) {
return $value;
}
if (is_numeric($value)) {
return ((int) $value) > 0;
}
$value = strtolower(trim((string) $value));
return in_array($value, array('1', 'true', 'yes', 'on', 'y'), true);
}
function itstudio_is_recruitment_article($post_id) {
$post_id = (int) $post_id;
if ($post_id <= 0) {
return false;
}
$meta_key = itstudio_get_recruitment_article_meta_key();
$meta_keys = array(
$meta_key,
'_itstudio_is_recruitment_article',
'itstudio_join_article',
'join_recruitment_article',
'is_recruitment_article',
);
foreach ($meta_keys as $key) {
$raw = get_post_meta($post_id, $key, true);
if ($raw !== '' && $raw !== null && itstudio_normalize_recruitment_flag($raw)) {
return true;
}
}
if (function_exists('get_field')) {
$acf_keys = array(
'itstudio_is_recruitment_article',
'is_recruitment_article',
'itstudio_join_article',
);
foreach ($acf_keys as $acf_key) {
$raw = get_field($acf_key, $post_id, false);
if ($raw !== '' && $raw !== null && itstudio_normalize_recruitment_flag($raw)) {
return true;
}
}
}
return false;
}
function itstudio_add_recruitment_meta_boxes() {
$screens = array('announcement', 'news', 'post');
foreach ($screens as $screen) {
add_meta_box(
'itstudio_recruitment_flag',
__('招新文章', 'itstudio'),
'itstudio_render_recruitment_meta_box',
$screen,
'side',
'high'
);
}
}
add_action('add_meta_boxes', 'itstudio_add_recruitment_meta_boxes');
function itstudio_render_recruitment_meta_box($post) {
$meta_key = itstudio_get_recruitment_article_meta_key();
$checked = itstudio_is_recruitment_article((int) $post->ID);
wp_nonce_field('itstudio_save_recruitment_meta', 'itstudio_recruitment_meta_nonce');
?>
<p>
<label for="itstudio_is_recruitment_article">
<input
type="checkbox"
id="itstudio_is_recruitment_article"
name="itstudio_is_recruitment_article"
value="1"
<?php checked($checked); ?>
>
<?php esc_html_e('在加入我们页面显示为招新新闻', 'itstudio'); ?>
</label>
</p>
<p style="color:#666;line-height:1.5;margin:0;">
<?php esc_html_e('仅显示当年且已发布的招新文章,最多展示 5 篇。', 'itstudio'); ?>
</p>
<input type="hidden" name="itstudio_recruitment_meta_key" value="<?php echo esc_attr($meta_key); ?>">
<?php
}
function itstudio_save_recruitment_meta_box($post_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
return;
}
if (!isset($_POST['itstudio_recruitment_meta_nonce'])) {
return;
}
$nonce = sanitize_text_field(wp_unslash($_POST['itstudio_recruitment_meta_nonce']));
if (!wp_verify_nonce($nonce, 'itstudio_save_recruitment_meta')) {
return;
}
$post_type = get_post_type($post_id);
if (!in_array($post_type, array('announcement', 'news', 'post'), true)) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
$meta_key = itstudio_get_recruitment_article_meta_key();
$checked = isset($_POST['itstudio_is_recruitment_article'])
? sanitize_text_field(wp_unslash($_POST['itstudio_is_recruitment_article']))
: '';
if (itstudio_normalize_recruitment_flag($checked)) {
update_post_meta($post_id, $meta_key, '1');
} else {
delete_post_meta($post_id, $meta_key);
}
}
add_action('save_post', 'itstudio_save_recruitment_meta_box');
function itstudio_join_get_recruitment_feed_items($join_runtime = array(), $limit = 5) {
$limit = max(1, min(10, (int) $limit));
$join_runtime = is_array($join_runtime) ? $join_runtime : array();
$now = new DateTimeImmutable('now', wp_timezone());
$now_year = (int) $now->format('Y');
$display_year = isset($join_runtime['recruitment_year']) && is_numeric($join_runtime['recruitment_year'])
? (int) $join_runtime['recruitment_year']
: $now_year;
$season_start_ts = null;
$season_end_ts = null;
$stages = isset($join_runtime['stages']) && is_array($join_runtime['stages']) ? $join_runtime['stages'] : array();
foreach ($stages as $stage) {
if (!is_array($stage)) {
continue;
}
$start_ts = isset($stage['start_ts']) && is_numeric($stage['start_ts']) ? (int) $stage['start_ts'] : null;
$end_ts = isset($stage['end_ts']) && is_numeric($stage['end_ts']) ? (int) $stage['end_ts'] : null;
if ($start_ts !== null && ($season_start_ts === null || $start_ts < $season_start_ts)) {
$season_start_ts = $start_ts;
}
if ($end_ts !== null && ($season_end_ts === null || $end_ts > $season_end_ts)) {
$season_end_ts = $end_ts;
}
}
$now_ts = (int) (isset($join_runtime['now_ts']) && is_numeric($join_runtime['now_ts']) ? $join_runtime['now_ts'] : ((int) $now->format('U') * 1000));
if ($season_start_ts !== null && $now_ts < $season_start_ts && $display_year > $now_year) {
// 下年招新未开始:继续展示本年招新资讯
$display_year = $now_year;
}
$query = new WP_Query(array(
'post_type' => array('announcement', 'news', 'post'),
'post_status' => 'publish',
'posts_per_page' => 80,
'orderby' => 'date',
'order' => 'DESC',
'no_found_rows' => true,
'ignore_sticky_posts' => true,
'date_query' => array(
array(
'year' => $display_year,
),
),
));
$items = array();
if ($query->have_posts()) {
foreach ($query->posts as $post) {
if (count($items) >= $limit) {
break;
}
$post_id = (int) $post->ID;
if (!itstudio_is_recruitment_article($post_id)) {
continue;
}
$title = trim((string) get_the_title($post_id));
$url = (string) get_permalink($post_id);
if ($title === '' || $url === '') {
continue;
}
$excerpt = function_exists('itstudio_get_post_excerpt_chars')
? itstudio_get_post_excerpt_chars($post_id, 72)
: wp_html_excerpt(trim(wp_strip_all_tags((string) get_post_field('post_excerpt', $post_id))), 72, '...');
if ($excerpt === '') {
$excerpt = '...';
}
$author_id = (int) get_post_field('post_author', $post_id);
$author = trim((string) get_the_author_meta('display_name', $author_id));
if ($author === '') {
$author = 'Unknown';
}
$items[] = array(
'id' => $post_id,
'title' => $title,
'excerpt' => $excerpt,
'url' => $url,
'date' => get_the_date('Y-m-d H:i', $post_id),
'date_iso' => get_the_date('c', $post_id),
'author' => $author,
'type' => get_post_type($post_id),
);
}
}
wp_reset_postdata();
return array(
'display_year' => $display_year,
'items' => $items,
);
}