'_republish_replace_author', 'replace_publish_date' => '_republish_replace_publish_date', 'replace_modified_date' => '_republish_replace_modified_date', ]; private const PRO_OVERRIDES = [ 'replace_tax' => '_republish_replace_tax', 'replace_post-metas' => '_republish_replace_post-metas', 'delete_comments' => '_republish_delete_comments', ]; /** * Constructor. * * @param array $options Module options. * @param Content_Refresher_Refresher $refresher Shared refresher service. */ public function __construct( array $options, Content_Refresher_Refresher $refresher ) { $this->options = $options; $this->refresher = $refresher; add_action( 'add_meta_boxes', [ $this, 'register' ] ); add_action( 'save_post', [ $this, 'save' ] ); add_action( 'wp_ajax_adminoptim_republish_conversion', [ $this, 'convert_draft' ] ); add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] ); } /** * Register the appropriate metabox for the current post. * * @return void */ public function register(): void { global $post; if ( ! $post instanceof \WP_Post || ! $this->post_type_enabled( $post->post_type ) || ! $this->refresher->can_refresh( wp_get_current_user(), $post ) ) { return; } if ( $this->refresher->is_refresh_copy( $post->ID ) ) { add_meta_box( 'adminoptim_refresh_settings', __( 'Content Refresh', 'admin-optimizer' ), [ $this, 'render_overrides' ], $post->post_type, 'side' ); } elseif ( 'publish' !== $post->post_status ) { add_meta_box( 'adminoptim_convert_to_refresh', __( 'Convert to Refresh Copy', 'admin-optimizer' ), [ $this, 'render_conversion' ], $post->post_type, 'normal' ); } } /** * Render the replacement-override fields for a refresh copy. * * @param \WP_Post $post Refresh-copy post being edited. * * @return void */ public function render_overrides( $post ): void { wp_nonce_field( 'adminoptim_refresh_settings', 'adminoptim_refresh_settings_nonce' ); $labels = [ 'replace_author' => __( 'Author', 'admin-optimizer' ), 'replace_publish_date' => __( 'Publish date', 'admin-optimizer' ), 'replace_modified_date' => __( 'Modified date', 'admin-optimizer' ), 'replace_tax' => __( 'Taxonomies', 'admin-optimizer' ), 'replace_post-metas' => __( 'Custom fields', 'admin-optimizer' ), 'delete_comments' => __( 'Comments', 'admin-optimizer' ), ]; $overrides = Module_Registry::is_pro_active() ? array_merge( self::OVERRIDES, self::PRO_OVERRIDES ) : self::OVERRIDES; foreach ( $overrides as $field => $meta_key ) { $value = get_post_meta( $post->ID, $meta_key, true ); ?>


refresher->is_refresh_copy( $post_id ) || ! $this->refresher->can_refresh( wp_get_current_user(), $post ) ) { return; } $submitted = isset( $_POST['content_refresh'] ) && is_array( $_POST['content_refresh'] ) ? wp_unslash( $_POST['content_refresh'] ) : []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- each value is sanitize_key()'d and whitelisted below before use. $overrides = Module_Registry::is_pro_active() ? array_merge( self::OVERRIDES, self::PRO_OVERRIDES ) : self::OVERRIDES; foreach ( $overrides as $field => $meta_key ) { $value = isset( $submitted[ $field ] ) ? sanitize_key( $submitted[ $field ] ) : 'default'; if ( in_array( $value, [ 'yes', 'no' ], true ) ) { update_post_meta( $post_id, $meta_key, $value ); } else { delete_post_meta( $post_id, $meta_key ); } } } /** * Ajax handler that converts an existing draft into a refresh copy. * * @return void */ public function convert_draft(): void { check_ajax_referer( 'adminoptim_republish_conversion' ); $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0; $parent_id = isset( $_POST['parent_id'] ) ? absint( $_POST['parent_id'] ) : 0; $post = get_post( $post_id ); $parent = get_post( $parent_id ); if ( ! $post instanceof \WP_Post || ! $parent instanceof \WP_Post || 'publish' === $post->post_status || $post->post_type !== $parent->post_type || ! $this->post_type_enabled( $post->post_type ) || ! $this->refresher->can_refresh( wp_get_current_user(), $post ) || ! current_user_can( 'edit_post', $parent_id ) ) { wp_send_json_error( [ 'message' => __( 'The draft or original post is invalid.', 'admin-optimizer' ) ], 403 ); } update_post_meta( $post_id, '_republish_post', 1 ); update_post_meta( $post_id, '_republish_post_parent', $parent_id ); wp_send_json_success( [ 'message' => __( 'Converted. Reload the editor to continue.', 'admin-optimizer' ) ] ); } /** * Enqueue the metabox script on the post-edit screen for an eligible draft. * * @param string $hook_suffix Current admin page hook suffix. * * @return void */ public function enqueue_assets( $hook_suffix ): void { global $post; if ( 'post.php' !== $hook_suffix || ! $post instanceof \WP_Post || 'publish' === $post->post_status || ! $this->post_type_enabled( $post->post_type ) ) { return; } wp_enqueue_script( 'adminoptim-content-refresher-metabox', Content_Refresher::MODULE_URI . 'assets/js/metabox.min.js', [ 'jquery' ], ADMINOPTIMIZER_VERSION, true ); wp_localize_script( 'adminoptim-content-refresher-metabox', 'AdminOptimRefreshConversion', [ 'postId' => $post->ID ] ); } /** * Check whether the content-refresh feature is enabled for a post type. * * @param string $post_type Post type to check. * * @return bool */ private function post_type_enabled( string $post_type ): bool { return ! empty( $this->options['refresh_post_types'] ) && in_array( $post_type, (array) $this->options['refresh_post_types'], true ); } }