HEX
Server: LiteSpeed
System: Linux prometheus.hongkongserver.net 4.18.0-553.134.1.el8_10.x86_64 #1 SMP Tue Jun 16 16:05:57 EDT 2026 x86_64
User: ayxmplky (1112)
PHP: 8.1.34
Disabled: NONE
Upload Files
File: /home/ayxmplky/public_html/wp-content/themes/tactic/inc/meta-boxes.php
<?php
/**
 * Meta-boxes: Testimonials + Homepage sections
 *
 * @package tactic
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/* ══════════════════════════════════════════════
   Метабокс: Детали отзыва
══════════════════════════════════════════════ */
function tactic_register_meta_boxes(): void {
	add_meta_box(
		'tactic_product_details',
		__( 'Карточка продукции', 'tactic' ),
		'tactic_product_box_cb',
		'tactic_product',
		'normal',
		'high'
	);

	add_meta_box(
		'tactic_product_lang',
		__( 'Язык карточки продукции', 'tactic' ),
		'tactic_product_lang_box_cb',
		'tactic_product',
		'side',
		'high'
	);

	add_meta_box(
		'tactic_testimonial_details',
		__( 'Данные отзыва', 'tactic' ),
		'tactic_testimonial_box_cb',
		'tactic_testimonial',
		'normal',
		'high'
	);

	add_meta_box(
		'tactic_explore_video_details',
		__( 'Explore Tools — Видео карточки', 'tactic' ),
		'tactic_explore_video_box_cb',
		'tactic_explore_video',
		'normal',
		'high'
	);

	add_meta_box(
		'tactic_news_lang',
		__( 'Язык новости', 'tactic' ),
		'tactic_news_lang_box_cb',
		'tactic_news',
		'side',
		'high'
	);

	add_meta_box(
		'tactic_message_details',
		__( 'Данные сообщения', 'tactic' ),
		'tactic_message_box_cb',
		'tactic_message',
		'normal',
		'high'
	);

	add_meta_box(
		'tactic_home_hero',
		__( 'Главная — Hero-блок (верхний баннер)', 'tactic' ),
		'tactic_home_hero_cb',
		'page',
		'normal',
		'high'
	);

	add_meta_box(
		'tactic_home_images',
		__( 'Главная — Изображения (карта мира и пейзаж)', 'tactic' ),
		'tactic_home_images_cb',
		'page',
		'normal',
		'default'
	);

	add_meta_box(
		'tactic_about_images',
		__( 'О нас — Изображения страницы', 'tactic' ),
		'tactic_about_images_cb',
		'page',
		'normal',
		'default'
	);
}
add_action( 'add_meta_boxes', 'tactic_register_meta_boxes' );

/* ── Callback: Продукция ── */
function tactic_product_box_cb( WP_Post $post ): void {
	wp_nonce_field( 'tactic_product_save', 'tactic_product_nonce' );

	$title_zh = (string) get_post_meta( $post->ID, '_tactic_product_title', true );
	$title_en = (string) get_post_meta( $post->ID, '_tactic_product_title_en', true );
	$desc_zh  = (string) get_post_meta( $post->ID, '_tactic_product_desc', true );
	$desc_en  = (string) get_post_meta( $post->ID, '_tactic_product_desc_en', true );
	$image_id = (int) get_post_meta( $post->ID, '_tactic_product_image_id', true );

	echo '<table class="form-table"><tbody>';
	echo '<tr><th><label for="_tactic_product_title">' . esc_html__( 'Название (основное)', 'tactic' ) . '</label></th><td><input type="text" id="_tactic_product_title" name="_tactic_product_title" value="' . esc_attr( $title_zh ) . '" class="widefat"><p class="description">' . esc_html__( 'Если пусто — используется стандартный заголовок записи.', 'tactic' ) . '</p></td></tr>';

	echo '<tr><th><label for="_tactic_product_title_en">' . esc_html__( 'Название (EN)', 'tactic' ) . '</label></th><td><input type="text" id="_tactic_product_title_en" name="_tactic_product_title_en" value="' . esc_attr( $title_en ) . '" class="widefat"><p class="description">' . esc_html__( 'Необязательно. Если пусто — используется основное название.', 'tactic' ) . '</p></td></tr>';
	echo '<tr><th><label for="_tactic_product_desc">' . esc_html__( 'Описание (основное)', 'tactic' ) . '</label></th><td><textarea id="_tactic_product_desc" name="_tactic_product_desc" class="widefat" rows="4">' . esc_textarea( $desc_zh ) . '</textarea></td></tr>';
	echo '<tr><th><label for="_tactic_product_desc_en">' . esc_html__( 'Описание (EN)', 'tactic' ) . '</label></th><td><textarea id="_tactic_product_desc_en" name="_tactic_product_desc_en" class="widefat" rows="4">' . esc_textarea( $desc_en ) . '</textarea><p class="description">' . esc_html__( 'Необязательно. Если пусто — используется основное описание.', 'tactic' ) . '</p></td></tr>';

	echo '<tr><th><label for="_tactic_product_image_id">' . esc_html__( 'Изображение карточки', 'tactic' ) . '</label></th><td>';
	echo '<input type="hidden" id="_tactic_product_image_id" name="_tactic_product_image_id" value="' . esc_attr( (string) $image_id ) . '">';
	echo '<button type="button" class="button tactic-upload-btn" data-target="_tactic_product_image_id" data-preview="_tactic_product_image_id_preview">' . esc_html__( 'Выбрать изображение', 'tactic' ) . '</button>';
	echo '<div id="_tactic_product_image_id_preview" style="margin-top:8px">';
	if ( $image_id ) {
		echo wp_get_attachment_image( $image_id, 'thumbnail' );
	}
	echo '</div>';
	echo '</td></tr>';
	echo '</tbody></table>';

	echo '<div style="margin-top:10px;padding:10px 12px;background:#f6f7f7;border:1px solid #dcdcde;border-radius:4px;">';
	echo '<strong>' . esc_html__( 'Рекомендация по изображению карточки:', 'tactic' ) . '</strong> ';
	echo esc_html__( 'PNG/WebP, 1200x900 px (соотношение 4:3), прозрачный фон, объект по центру.', 'tactic' );
	echo '</div>';
}

/* ── Сохранение: Продукция ── */
function tactic_save_product_meta( int $post_id ): void {
	if ( ! isset( $_POST['tactic_product_nonce'] ) ) {
		return;
	}
	if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_product_nonce'] ) ), 'tactic_product_save' ) ) {
		return;
	}
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	if ( isset( $_POST['_tactic_product_title_en'] ) ) {
		update_post_meta( $post_id, '_tactic_product_title_en', sanitize_text_field( wp_unslash( $_POST['_tactic_product_title_en'] ) ) );
	}
	if ( isset( $_POST['_tactic_product_title'] ) ) {
		update_post_meta( $post_id, '_tactic_product_title', sanitize_text_field( wp_unslash( $_POST['_tactic_product_title'] ) ) );
	}
	if ( isset( $_POST['_tactic_product_desc'] ) ) {
		update_post_meta( $post_id, '_tactic_product_desc', sanitize_textarea_field( wp_unslash( $_POST['_tactic_product_desc'] ) ) );
	}
	if ( isset( $_POST['_tactic_product_desc_en'] ) ) {
		update_post_meta( $post_id, '_tactic_product_desc_en', sanitize_textarea_field( wp_unslash( $_POST['_tactic_product_desc_en'] ) ) );
	}
	if ( isset( $_POST['_tactic_product_image_id'] ) ) {
		update_post_meta( $post_id, '_tactic_product_image_id', absint( $_POST['_tactic_product_image_id'] ) );
	}
}
add_action( 'save_post_tactic_product', 'tactic_save_product_meta' );

/* ── Callback: Язык карточки продукции ── */
function tactic_product_lang_box_cb( WP_Post $post ): void {
	wp_nonce_field( 'tactic_product_lang_save', 'tactic_product_lang_nonce' );

	$current_lang = (string) get_post_meta( $post->ID, '_tactic_product_lang', true );
	if ( ! in_array( $current_lang, [ 'zh', 'en' ], true ) ) {
		$current_lang = tactic_product_lang();
	}

	echo '<p style="margin-top:0">' . esc_html__( 'Обязательный параметр. Карточка показывается только на выбранном языке сайта.', 'tactic' ) . '</p>';
	echo '<label for="_tactic_product_lang" class="screen-reader-text">' . esc_html__( 'Язык карточки продукции', 'tactic' ) . '</label>';
	echo '<select id="_tactic_product_lang" name="_tactic_product_lang" class="widefat" required>';
	echo '<option value="zh"' . selected( $current_lang, 'zh', false ) . '>' . esc_html__( 'Китайский (zh)', 'tactic' ) . '</option>';
	echo '<option value="en"' . selected( $current_lang, 'en', false ) . '>' . esc_html__( 'Английский (en)', 'tactic' ) . '</option>';
	echo '</select>';
}

/* ── Сохранение: Язык карточки продукции ── */
function tactic_save_product_lang_meta( int $post_id ): void {
	if ( ! isset( $_POST['tactic_product_lang_nonce'] ) ) {
		return;
	}

	if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_product_lang_nonce'] ) ), 'tactic_product_lang_save' ) ) {
		return;
	}

	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}

	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	$lang = isset( $_POST['_tactic_product_lang'] ) ? sanitize_key( (string) wp_unslash( $_POST['_tactic_product_lang'] ) ) : '';
	if ( ! in_array( $lang, [ 'zh', 'en' ], true ) ) {
		$lang = tactic_product_lang();
	}

	update_post_meta( $post_id, '_tactic_product_lang', $lang );
}
add_action( 'save_post_tactic_product', 'tactic_save_product_lang_meta' );

/* ── Подсказка в блоке миниатюры для продукции ── */
function tactic_product_thumbnail_hint( string $content, int $post_id, $thumbnail_id ): string {
	if ( get_post_type( $post_id ) !== 'tactic_product' ) {
		return $content;
	}

	$hint = '<p class="description" style="margin-top:8px;">'
		. esc_html__( 'Рекомендуемое изображение: PNG/WebP, 1200x900 px (4:3), прозрачный фон.', 'tactic' )
		. '</p>';

	return $content . $hint;
}
add_filter( 'admin_post_thumbnail_html', 'tactic_product_thumbnail_hint', 10, 3 );

/* ── Callback: Сотрудник ── */
function tactic_testimonial_box_cb( WP_Post $post ): void {
	wp_nonce_field( 'tactic_testimonial_save', 'tactic_testimonial_nonce' );

	$full_name    = (string) get_post_meta( $post->ID, '_tactic_full_name', true );
	$full_name_en = (string) get_post_meta( $post->ID, '_tactic_full_name_en', true );
	$position     = (string) get_post_meta( $post->ID, '_tactic_position', true );
	$position_en  = (string) get_post_meta( $post->ID, '_tactic_position_en', true );
	$company      = (string) get_post_meta( $post->ID, '_tactic_company', true );
	$company_en   = (string) get_post_meta( $post->ID, '_tactic_company_en', true );
	$video_url    = (string) get_post_meta( $post->ID, '_tactic_video_url', true );
	$preview_id   = (int) get_post_meta( $post->ID, '_tactic_preview_id', true );

	echo '<table class="form-table"><tbody>';
	echo '<tr><th><label for="_tactic_full_name">' . esc_html__( 'ФИО (китайский)', 'tactic' ) . '</label></th><td><input type="text" id="_tactic_full_name" name="_tactic_full_name" value="' . esc_attr( $full_name ) . '" class="widefat"></td></tr>';
	echo '<tr><th><label for="_tactic_full_name_en">' . esc_html__( 'ФИО (EN)', 'tactic' ) . '</label></th><td><input type="text" id="_tactic_full_name_en" name="_tactic_full_name_en" value="' . esc_attr( $full_name_en ) . '" class="widefat"></td></tr>';
	echo '<tr><th><label for="_tactic_position">' . esc_html__( 'Должность (китайский)', 'tactic' ) . '</label></th><td><input type="text" id="_tactic_position" name="_tactic_position" value="' . esc_attr( $position ) . '" class="widefat"></td></tr>';
	echo '<tr><th><label for="_tactic_position_en">' . esc_html__( 'Должность (EN)', 'tactic' ) . '</label></th><td><input type="text" id="_tactic_position_en" name="_tactic_position_en" value="' . esc_attr( $position_en ) . '" class="widefat"></td></tr>';
	echo '<tr><th><label for="_tactic_company">' . esc_html__( 'Компания (китайский)', 'tactic' ) . '</label></th><td><input type="text" id="_tactic_company" name="_tactic_company" value="' . esc_attr( $company ) . '" class="widefat"></td></tr>';
	echo '<tr><th><label for="_tactic_company_en">' . esc_html__( 'Компания (EN)', 'tactic' ) . '</label></th><td><input type="text" id="_tactic_company_en" name="_tactic_company_en" value="' . esc_attr( $company_en ) . '" class="widefat"></td></tr>';

	echo '<tr><th><label for="_tactic_preview_id">' . esc_html__( 'Превью отзыва', 'tactic' ) . '</label></th><td>';
	echo '<input type="hidden" id="_tactic_preview_id" name="_tactic_preview_id" value="' . esc_attr( (string) $preview_id ) . '">';
	echo '<button type="button" class="button tactic-upload-btn" data-target="_tactic_preview_id" data-preview="_tactic_preview_id_preview">' . esc_html__( 'Выбрать изображение', 'tactic' ) . '</button>';
	echo '<p style="margin-top:6px;color:#646970;">' . esc_html__( 'Используется как превью видео-отзыва. Если пусто, берётся миниатюра записи.', 'tactic' ) . '</p>';
	echo '<div id="_tactic_preview_id_preview" style="margin-top:8px">';
	if ( $preview_id ) {
		echo wp_get_attachment_image( $preview_id, 'thumbnail' );
	}
	echo '</div>';
	echo '</td></tr>';

	echo '<tr><th><label for="_tactic_video_url">' . esc_html__( 'Видео отзыва', 'tactic' ) . '</label></th><td>';
	echo '<input type="url" id="_tactic_video_url" name="_tactic_video_url" value="' . esc_url( $video_url ) . '" class="widefat" placeholder="https://.../video.mp4">';
	echo '<p style="margin-top:8px;display:flex;gap:8px;align-items:center;flex-wrap:wrap;">';
	echo '<button type="button" class="button tactic-upload-video-btn" data-target="_tactic_video_url">' . esc_html__( 'Выбрать видео из медиатеки', 'tactic' ) . '</button>';
	echo '<span style="color:#646970;">' . esc_html__( 'Загрузите и выберите mp4/webm.', 'tactic' ) . '</span>';
	echo '</p>';
	echo '</td></tr>';
	echo '</tbody></table>';
}

/* ── Сохранение: Сотрудник ── */
function tactic_save_testimonial_meta( int $post_id ): void {
	if ( ! isset( $_POST['tactic_testimonial_nonce'] ) ) {
		return;
	}
	if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_testimonial_nonce'] ) ), 'tactic_testimonial_save' ) ) {
		return;
	}
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	$text_keys = [ '_tactic_full_name', '_tactic_full_name_en', '_tactic_position', '_tactic_position_en', '_tactic_company', '_tactic_company_en' ];
	foreach ( $text_keys as $key ) {
		if ( isset( $_POST[ $key ] ) ) {
			update_post_meta( $post_id, $key, sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) );
		}
	}

	if ( isset( $_POST['_tactic_preview_id'] ) ) {
		update_post_meta( $post_id, '_tactic_preview_id', absint( $_POST['_tactic_preview_id'] ) );
	}
	if ( isset( $_POST['_tactic_video_url'] ) ) {
		update_post_meta( $post_id, '_tactic_video_url', esc_url_raw( wp_unslash( $_POST['_tactic_video_url'] ) ) );
	}
}
add_action( 'save_post_tactic_testimonial', 'tactic_save_testimonial_meta' );

/* ── Callback: Explore Tools видео ── */
function tactic_explore_video_box_cb( WP_Post $post ): void {
	wp_nonce_field( 'tactic_explore_video_save', 'tactic_explore_video_nonce' );

	$video_url  = (string) get_post_meta( $post->ID, '_tactic_video_url', true );
	$preview_id = (int) get_post_meta( $post->ID, '_tactic_preview_id', true );

	echo '<table class="form-table"><tbody>';
	echo '<tr><th><label for="_tactic_preview_id">' . esc_html__( 'Превью видео', 'tactic' ) . '</label></th><td>';
	echo '<input type="hidden" id="_tactic_preview_id" name="_tactic_preview_id" value="' . esc_attr( (string) $preview_id ) . '">';
	echo '<button type="button" class="button tactic-upload-btn" data-target="_tactic_preview_id" data-preview="_tactic_preview_id_preview">' . esc_html__( 'Выбрать изображение', 'tactic' ) . '</button>';
	echo '<p style="margin-top:6px;color:#646970;">' . esc_html__( 'Картинка карточки в блоке Explore на странице About.', 'tactic' ) . '</p>';
	echo '<div id="_tactic_preview_id_preview" style="margin-top:8px">';
	if ( $preview_id ) {
		echo wp_get_attachment_image( $preview_id, 'thumbnail' );
	}
	echo '</div>';
	echo '</td></tr>';

	echo '<tr><th><label for="_tactic_video_url">' . esc_html__( 'Ссылка на видео', 'tactic' ) . '</label></th><td>';
	echo '<input type="url" id="_tactic_video_url" name="_tactic_video_url" value="' . esc_url( $video_url ) . '" class="widefat" placeholder="https://.../video.mp4">';
	echo '<p style="margin-top:8px;display:flex;gap:8px;align-items:center;flex-wrap:wrap;">';
	echo '<button type="button" class="button tactic-upload-video-btn" data-target="_tactic_video_url">' . esc_html__( 'Выбрать видео из медиатеки', 'tactic' ) . '</button>';
	echo '<span style="color:#646970;">' . esc_html__( 'Поддерживается mp4/webm.', 'tactic' ) . '</span>';
	echo '</p>';
	echo '</td></tr>';
	echo '</tbody></table>';
}

/* ── Сохранение: Explore Tools видео ── */
function tactic_save_explore_video_meta( int $post_id ): void {
	if ( ! isset( $_POST['tactic_explore_video_nonce'] ) ) {
		return;
	}

	if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_explore_video_nonce'] ) ), 'tactic_explore_video_save' ) ) {
		return;
	}

	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}

	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	if ( isset( $_POST['_tactic_preview_id'] ) ) {
		update_post_meta( $post_id, '_tactic_preview_id', absint( $_POST['_tactic_preview_id'] ) );
	}

	if ( isset( $_POST['_tactic_video_url'] ) ) {
		update_post_meta( $post_id, '_tactic_video_url', esc_url_raw( wp_unslash( $_POST['_tactic_video_url'] ) ) );
	}
}
add_action( 'save_post_tactic_explore_video', 'tactic_save_explore_video_meta' );

/* ── Callback: Язык новости ── */
function tactic_news_lang_box_cb( WP_Post $post ): void {
	wp_nonce_field( 'tactic_news_lang_save', 'tactic_news_lang_nonce' );

	$current_lang = (string) get_post_meta( $post->ID, '_tactic_news_lang', true );
	if ( ! in_array( $current_lang, [ 'zh', 'en' ], true ) ) {
		$current_lang = tactic_news_lang();
	}

	echo '<p style="margin-top:0">' . esc_html__( 'Обязательный параметр. Новость показывается только на выбранном языке сайта.', 'tactic' ) . '</p>';
	echo '<label for="_tactic_news_lang" class="screen-reader-text">' . esc_html__( 'Язык новости', 'tactic' ) . '</label>';
	echo '<select id="_tactic_news_lang" name="_tactic_news_lang" class="widefat" required>';
	echo '<option value="zh"' . selected( $current_lang, 'zh', false ) . '>' . esc_html__( 'Китайский (zh)', 'tactic' ) . '</option>';
	echo '<option value="en"' . selected( $current_lang, 'en', false ) . '>' . esc_html__( 'Английский (en)', 'tactic' ) . '</option>';
	echo '</select>';
}

/* ── Сохранение: Язык новости ── */
function tactic_save_news_lang_meta( int $post_id ): void {
	if ( ! isset( $_POST['tactic_news_lang_nonce'] ) ) {
		return;
	}

	if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_news_lang_nonce'] ) ), 'tactic_news_lang_save' ) ) {
		return;
	}

	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}

	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	$lang = isset( $_POST['_tactic_news_lang'] ) ? sanitize_key( (string) wp_unslash( $_POST['_tactic_news_lang'] ) ) : '';
	if ( ! in_array( $lang, [ 'zh', 'en' ], true ) ) {
		$lang = tactic_news_lang();
	}

	update_post_meta( $post_id, '_tactic_news_lang', $lang );
}
add_action( 'save_post_tactic_news', 'tactic_save_news_lang_meta' );

/* ── Callback: Hero ── */
function tactic_home_hero_cb( WP_Post $post ): void {
	if ( (int) get_option( 'page_on_front' ) !== $post->ID ) {
		echo '<p>' . esc_html__( 'Эти настройки отображаются только на странице "Главная".', 'tactic' ) . '</p>';
		return;
	}
	wp_nonce_field( 'tactic_home_save', 'tactic_home_nonce' );

	$fields = [
		'_hero_bg_id'    => [ __( 'Hero — фоновое изображение', 'tactic' ), 'image' ],
		'_hero_slide_ids'=> [ __( 'Hero — слайды (несколько изображений)', 'tactic' ), 'images' ],
		'_hero_title'    => [ __( 'Hero — заголовок',                   'tactic' ), 'text'  ],
		'_hero_subtitle' => [ __( 'Hero — подзаголовок',                'tactic' ), 'text'  ],
		'_hero_btn1_text'=> [ __( 'Кнопка 1 — текст',                     'tactic' ), 'text'  ],
		'_hero_btn1_url' => [ __( 'Кнопка 1 — ссылка',                    'tactic' ), 'url'   ],
		'_hero_btn2_text'=> [ __( 'Кнопка 2 — текст',                     'tactic' ), 'text'  ],
		'_hero_btn2_url' => [ __( 'Кнопка 2 — ссылка',                    'tactic' ), 'url'   ],
	];

	tactic_render_meta_fields( $post->ID, $fields );
}

/* ── Callback: Images ── */
function tactic_home_images_cb( WP_Post $post ): void {
	if ( (int) get_option( 'page_on_front' ) !== $post->ID ) {
		echo '<p>' . esc_html__( 'Эти настройки отображаются только на странице "Главная".', 'tactic' ) . '</p>';
		return;
	}

	$fields = [
		'_map_bg_id'       => [ __( 'Карта мира — изображение', 'tactic' ), 'image' ],
		'_landscape_bg_id' => [ __( 'Пейзажный баннер — изображение', 'tactic' ), 'image' ],
	];

	tactic_render_meta_fields( $post->ID, $fields );
}

/* ── Callback: About page images ── */
function tactic_about_images_cb( WP_Post $post ): void {
	$about_page = get_page_by_path( 'about' ) ?? get_page_by_path( 'o-kompanii' );
	if ( ! $about_page || $about_page->ID !== $post->ID ) {
		echo '<p>' . esc_html__( 'Эти настройки отображаются только на странице «О нас».', 'tactic' ) . '</p>';
		return;
	}
	wp_nonce_field( 'tactic_about_save', 'tactic_about_nonce' );

	$fields = [
		'_about_hero_bg_id'   => [ __( 'О нас — фон заголовка (светлый)', 'tactic' ), 'image' ],
		'_about_building_id'  => [ __( 'О нас — фото здания / производства', 'tactic' ), 'image' ],
	];

	tactic_render_meta_fields( $post->ID, $fields );
}

/* ── Сохранение: About page ── */
function tactic_save_about_meta( int $post_id ): void {
	if ( ! isset( $_POST['tactic_about_nonce'] ) ) {
		return;
	}
	if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_about_nonce'] ) ), 'tactic_about_save' ) ) {
		return;
	}
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	foreach ( [ '_about_hero_bg_id', '_about_building_id' ] as $key ) {
		if ( isset( $_POST[ $key ] ) ) {
			update_post_meta( $post_id, $key, absint( $_POST[ $key ] ) );
		}
	}
}
add_action( 'save_post_page', 'tactic_save_about_meta' );

/* ── Универсальный рендер полей ── */
function tactic_render_meta_fields( int $post_id, array $fields ): void {
	echo '<table class="form-table"><tbody>';
	foreach ( $fields as $key => [$label, $type] ) {
		$value = get_post_meta( $post_id, $key, true );
		echo '<tr><th><label>' . esc_html( $label ) . '</label></th><td>';

		if ( $type === 'image' ) {
			$id = absint( $value );
			printf(
				'<input type="hidden" name="%1$s" id="%1$s" value="%2$s">',
				esc_attr( $key ),
				$id
			);
			printf(
				'<button type="button" class="button tactic-upload-btn" data-target="%1$s" data-preview="%1$s_preview">%2$s</button>',
				esc_attr( $key ),
				esc_html__( '选择图片', 'tactic' )
			);
			echo '<div id="' . esc_attr( $key ) . '_preview" style="margin-top:8px">';
			if ( $id ) {
				echo wp_get_attachment_image( $id, 'thumbnail' );
			}
			echo '</div>';
		} elseif ( $type === 'images' ) {
			$ids = array_filter( array_map( 'absint', explode( ',', (string) $value ) ) );
			printf(
				'<input type="hidden" name="%1$s" id="%1$s" value="%2$s">',
				esc_attr( $key ),
				esc_attr( implode( ',', $ids ) )
			);
			printf(
				'<button type="button" class="button tactic-upload-multi-btn" data-target="%1$s" data-preview="%1$s_preview">%2$s</button>',
				esc_attr( $key ),
				esc_html__( 'Выбрать слайды', 'tactic' )
			);
			echo '<p class="description" style="margin-top:6px">' . esc_html__( 'Можно выбрать несколько изображений. Первая картинка станет первым слайдом.', 'tactic' ) . '</p>';
			echo '<div id="' . esc_attr( $key ) . '_preview" style="margin-top:8px;display:flex;gap:8px;flex-wrap:wrap">';
			foreach ( $ids as $img_id ) {
				echo wp_get_attachment_image( $img_id, 'thumbnail', false, [ 'style' => 'width:120px;height:80px;object-fit:cover;border:1px solid #ddd' ] );
			}
			echo '</div>';
		} elseif ( $type === 'url' ) {
			printf(
				'<input type="url" name="%1$s" id="%1$s" value="%2$s" class="widefat">',
				esc_attr( $key ),
				esc_url( $value )
			);
		} else {
			printf(
				'<input type="text" name="%1$s" id="%1$s" value="%2$s" class="widefat">',
				esc_attr( $key ),
				esc_attr( $value )
			);
		}
		echo '</td></tr>';
	}
	echo '</tbody></table>';
}

/* ══════════════════════════════════════════════
   Метабокс: Входящее сообщение (read-only)
══════════════════════════════════════════════ */
function tactic_message_box_cb( WP_Post $post ): void {
	$fields = [
		'_msg_email'    => __( 'Email', 'tactic' ),
		'_msg_company'  => __( 'Компания', 'tactic' ),
		'_msg_country'  => __( 'Страна', 'tactic' ),
		'_msg_gender'   => __( 'Пол', 'tactic' ),
		'_msg_mobile'   => __( 'Мобильный', 'tactic' ),
		'_msg_phone'    => __( 'Телефон', 'tactic' ),
		'_msg_address'  => __( 'Адрес', 'tactic' ),
		'_msg_industry' => __( 'Сфера / Роль', 'tactic' ),
		'_msg_terms'    => __( 'Согласие с условиями', 'tactic' ),
	];

	echo '<style>
		.msg-view-table { width:100%; border-collapse:collapse; }
		.msg-view-table th { width:160px; padding:10px 14px; text-align:left; font-weight:600; color:#50575e; vertical-align:top; border-bottom:1px solid #f0f0f0; }
		.msg-view-table td { padding:10px 14px; vertical-align:top; border-bottom:1px solid #f0f0f0; color:#1d2327; }
		.msg-view-table .msg-body td { white-space:pre-wrap; font-size:14px; line-height:1.6; }
		.msg-view-table a { color:#0073aa; }
	</style>';

	echo '<table class="msg-view-table"><tbody>';

	// Имя (из заголовка записи)
	echo '<tr><th>' . esc_html__( 'Имя', 'tactic' ) . '</th><td>' . esc_html( $post->post_title ) . '</td></tr>';

	foreach ( $fields as $key => $label ) {
		$val = get_post_meta( $post->ID, $key, true );
		if ( ! $val ) continue;
		if ( $key === '_msg_terms' ) {
			$val = $val === '1' ? __( 'Да', 'tactic' ) : __( 'Нет', 'tactic' );
		}
		if ( $key === '_msg_email' ) {
			$val = '<a href="mailto:' . esc_attr( $val ) . '">' . esc_html( $val ) . '</a>';
			echo '<tr><th>' . esc_html( $label ) . '</th><td>' . $val . '</td></tr>'; // phpcs:ignore
		} else {
			echo '<tr><th>' . esc_html( $label ) . '</th><td>' . esc_html( $val ) . '</td></tr>';
		}
	}

	// Сообщение
	$msg = get_post_meta( $post->ID, '_msg_text', true );
	if ( $msg ) {
		echo '<tr class="msg-body"><th>' . esc_html__( 'Сообщение', 'tactic' ) . '</th><td>' . esc_html( $msg ) . '</td></tr>';
	}

	echo '</tbody></table>';
}

/* ── Сохранение: Homepage ── */
function tactic_save_home_meta( int $post_id ): void {
	if ( ! isset( $_POST['tactic_home_nonce'] ) ) {
		return;
	}
	if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['tactic_home_nonce'] ) ), 'tactic_home_save' ) ) {
		return;
	}
	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
		return;
	}
	if ( ! current_user_can( 'edit_post', $post_id ) ) {
		return;
	}

	$int_keys = [ '_hero_bg_id', '_map_bg_id', '_landscape_bg_id' ];
	foreach ( $int_keys as $key ) {
		if ( isset( $_POST[ $key ] ) ) {
			update_post_meta( $post_id, $key, absint( $_POST[ $key ] ) );
		}
	}

	if ( isset( $_POST['_hero_slide_ids'] ) ) {
		$raw_ids = explode( ',', (string) wp_unslash( $_POST['_hero_slide_ids'] ) );
		$ids     = array_filter( array_map( 'absint', $raw_ids ) );
		update_post_meta( $post_id, '_hero_slide_ids', implode( ',', $ids ) );
	}

	$text_keys = [ '_hero_title', '_hero_subtitle', '_hero_btn1_text', '_hero_btn2_text' ];
	foreach ( $text_keys as $key ) {
		if ( isset( $_POST[ $key ] ) ) {
			update_post_meta( $post_id, $key, sanitize_text_field( wp_unslash( $_POST[ $key ] ) ) );
		}
	}

	$url_keys = [ '_hero_btn1_url', '_hero_btn2_url' ];
	foreach ( $url_keys as $key ) {
		if ( isset( $_POST[ $key ] ) ) {
			update_post_meta( $post_id, $key, esc_url_raw( wp_unslash( $_POST[ $key ] ) ) );
		}
	}
}
add_action( 'save_post_page', 'tactic_save_home_meta' );