*/ // Abort if this file is accessed directly. if (!defined('ABSPATH')) { exit; } class Metasync_Post_Meta_Settings { private $common; public function __construct() { $this->common = new Metasync_Common(); add_action('admin_init', [$this, 'add_post_meta_data'], 2); add_action('save_post', [$this, 'common_robots_meta_box_save']); add_action('save_post', [$this, 'advance_robots_meta_box_save']); add_action('save_post', [$this, 'redirection_meta_box_save']); add_action('save_post', [$this, 'canonical_meta_box_save']); add_action('save_post', [$this, 'video_sitemap_meta_box_save']); } public function add_post_meta_data() { // Don't show meta boxes if user's role doesn't have plugin access if (!Metasync::current_user_has_plugin_access()) { return; } $plugin_name = Metasync::get_effective_plugin_name(); $general_settings = Metasync::get_option('general', []); $post_types = array_values(get_post_types(['public' => true], 'names')); $post_types = array_diff($post_types, ['attachment']); // Only add meta boxes if not disabled in settings if (empty($general_settings['disable_common_robots_metabox'])) { add_meta_box('common-robots-meta', "Common Robots Meta by $plugin_name", [$this, 'common_robots_meta_box_display'], $post_types, 'normal', 'default'); } if (empty($general_settings['disable_advance_robots_metabox'])) { add_meta_box('advance-robots-meta', "Advance Robots Meta by $plugin_name", [$this, 'advance_robots_meta_box_display'], $post_types, 'normal', 'default'); } if (empty($general_settings['disable_redirection_metabox'])) { add_meta_box('post-redirection-meta', "Redirection by $plugin_name", [$this, 'post_redirection_display'], $post_types, 'normal', 'default'); } if (empty($general_settings['disable_canonical_metabox'])) { add_meta_box('post-canonical-meta', "Canonical by $plugin_name", [$this, 'post_canonical_display'], $post_types, 'normal', 'default'); } // Video Sitemap meta box — only if video sitemap is enabled $video_settings = get_option('metasync_video_sitemap_settings', []); if (!empty($video_settings['enabled'])) { $video_post_types = !empty($video_settings['post_types']) ? (array) $video_settings['post_types'] : ['post', 'page']; add_meta_box( 'metasync-video-sitemap-meta', "Video Sitemap by $plugin_name", [$this, 'video_sitemap_meta_box_display'], $video_post_types, 'normal', 'default' ); } } public function common_robots_meta_box_display() { global $post; $post_meta_robots = get_post_meta($post->ID, 'metasync_common_robots', true); // Check new spelling first, fall back to old for backward compatibility $common_meta_robots = Metasync::get_option('common_robots_meta') ?? Metasync::get_option('common_robots_mata') ?? ''; $common_robots = $post_meta_robots ? $post_meta_robots : $common_meta_robots; wp_nonce_field('metasync_common_robots_nonce', 'metasync_common_robots_nonce'); ?> ID, 'metasync_advance_robots', true); // Check new spelling first, fall back to old for backward compatibility $common_meta_robots = Metasync::get_option('advance_robots_meta') ?? Metasync::get_option('advance_robots_mata') ?? ''; $advance_robots = $post_meta_robots ? $post_meta_robots : $common_meta_robots; $snippet_advance_robots_enable = $advance_robots['max-snippet']['enable'] ?? ''; $snippet_advance_robots_length = $advance_robots['max-snippet']['length'] ?? ''; $video_advance_robots_enable = $advance_robots['max-video-preview']['enable'] ?? ''; $video_advance_robots_length = $advance_robots['max-video-preview']['length'] ?? ''; $image_advance_robots_enable = $advance_robots['max-image-preview']['enable'] ?? ''; $image_advance_robots_length = $advance_robots['max-image-preview']['length'] ?? ''; wp_nonce_field('metasync_advance_robots_nonce', 'metasync_advance_robots_nonce'); ?> ID, 'metasync_post_redirection_meta', true) ?? ''; $enable = $post_redirection['enable'] ?? ''; $type = $post_redirection['type'] ?? ''; $url = $post_redirection['url'] ?? ''; wp_nonce_field('metasync_post_redirection_nonce', 'metasync_post_redirection_nonce'); ?> ID, 'meta_canonical', true) ?? ''; // Fix legacy array values stored by sanitize_array() if (is_array($post_canonical)) { $post_canonical = reset($post_canonical) ?: ''; // Repair the stored value so it won't recur if (!empty($post_canonical)) { update_post_meta($post->ID, 'meta_canonical', (string) $post_canonical); } } wp_nonce_field('metasync_post_canonical_nonce', 'metasync_post_canonical_nonce'); ?> common->sanitize_array($post_data[$field_name]); } if (!empty($common_robots)) update_post_meta($post_id, 'metasync_common_robots', $common_robots); elseif (empty($common_robots) && $old_common_robots) delete_post_meta($post_id, 'metasync_common_robots', $old_common_robots); } public function advance_robots_meta_box_save($post_id) { if (!current_user_can('edit_post', $post_id)) return; // WP-197: When saving from Gutenberg (REST API context) and the sidebar // JSON exists, skip — the sidebar auto-save is the source of truth. if (defined('REST_REQUEST') && REST_REQUEST && !empty(get_post_meta($post_id, '_metasync_robots_advanced', true))) { return; } $post_data = metasync_sanitize_input_array($_POST); // Check for new field name first, then old for backward compatibility $field_name = isset($post_data['advanced_robots_meta']) ? 'advanced_robots_meta' : 'advanced_robots_mata'; if (!isset($post_data['metasync_advance_robots_nonce'], $post_data[$field_name]) || !wp_verify_nonce($post_data['metasync_advance_robots_nonce'], 'metasync_advance_robots_nonce')) return; $old_advance_robots = get_post_meta($post_id, 'metasync_advance_robots', true); $advance_robots = $this->common->sanitize_array($post_data[$field_name]); if (!empty($advance_robots)) update_post_meta($post_id, 'metasync_advance_robots', $advance_robots); elseif (empty($advance_robots) && $old_advance_robots) delete_post_meta($post_id, 'metasync_advance_robots', $old_advance_robots); } public function redirection_meta_box_save($post_id) { if (!current_user_can('edit_post', $post_id)) return; $post_data = metasync_sanitize_input_array($_POST); // Check for new field name first, then old for backward compatibility $field_name = isset($post_data['post_redirect_meta']) ? 'post_redirect_meta' : 'post_redirect_mata'; if (!isset($post_data['metasync_post_redirection_nonce'], $post_data[$field_name]) || !wp_verify_nonce($post_data['metasync_post_redirection_nonce'], 'metasync_post_redirection_nonce')) return; $old_post_redirection_meta = get_post_meta($post_id, 'metasync_post_redirection_meta', true); $post_redirection_meta = $this->common->sanitize_array($post_data[$field_name]); if (isset($post_redirection_meta['enable'])) update_post_meta($post_id, 'metasync_post_redirection_meta', $post_redirection_meta); else delete_post_meta($post_id, 'metasync_post_redirection_meta', $old_post_redirection_meta); } public function canonical_meta_box_save($post_id) { if (!current_user_can('edit_post', $post_id)) return; $post_data = metasync_sanitize_input_array($_POST); // Check for new field name first, then old for backward compatibility $field_name = isset($post_data['post_canonical_url_meta']) ? 'post_canonical_url_meta' : 'post_canonical_url_mata'; if (!isset($post_data['metasync_post_canonical_nonce'], $post_data[$field_name]) || !wp_verify_nonce($post_data['metasync_post_canonical_nonce'], 'metasync_post_canonical_nonce')) return; $old_post_canonical_meta = get_post_meta($post_id, 'meta_canonical', true); // Canonical is a URL string — sanitize as URL, not array $raw_value = $post_data[$field_name]; if (is_array($raw_value)) { $raw_value = reset($raw_value); // extract first element if array } $post_canonical_meta = esc_url_raw(trim((string) $raw_value)); if (!empty($post_canonical_meta)) update_post_meta($post_id, 'meta_canonical', $post_canonical_meta); else delete_post_meta($post_id, 'meta_canonical', $old_post_canonical_meta); } public function show_top_admin_bar() { if ( Metasync::current_user_has_plugin_access() ) { show_admin_bar( true ); } } /** * Display the Video Sitemap meta box in post editor. */ public function video_sitemap_meta_box_display() { global $post; $video_url = get_post_meta($post->ID, '_metasync_video_url', true); $video_thumbnail = get_post_meta($post->ID, '_metasync_video_thumbnail', true); $video_title = get_post_meta($post->ID, '_metasync_video_title', true); $video_desc = get_post_meta($post->ID, '_metasync_video_description', true); $video_duration = get_post_meta($post->ID, '_metasync_video_duration', true); wp_nonce_field('metasync_video_sitemap_meta_nonce', 'metasync_video_sitemap_meta_nonce'); ?>

'_metasync_video_url', 'metasync_video_thumbnail' => '_metasync_video_thumbnail', 'metasync_video_title' => '_metasync_video_title', 'metasync_video_description' => '_metasync_video_description', 'metasync_video_duration' => '_metasync_video_duration', ]; foreach ($fields as $form_key => $meta_key) { if (!isset($_POST[$form_key])) { continue; } $value = $_POST[$form_key]; // Sanitize per field type if (in_array($meta_key, ['_metasync_video_url', '_metasync_video_thumbnail'], true)) { $value = esc_url_raw($value); } elseif ($meta_key === '_metasync_video_duration') { $value = absint($value); $value = $value > 0 ? $value : ''; } elseif ($meta_key === '_metasync_video_description') { $value = sanitize_textarea_field($value); } else { $value = sanitize_text_field($value); } if (!empty($value)) { update_post_meta($post_id, $meta_key, $value); } else { delete_post_meta($post_id, $meta_key); } } } }