ID ) !== 'attachment' ) { return $actions; } $edit_url = admin_url( 'post.php?post=' . $post->ID . '&action=edit' ); $actions['replace_rename'] = sprintf( '%s', esc_url( $edit_url ), esc_attr__( 'Replace or Rename', 'optimole-wp' ), esc_html__( 'Replace or Rename', 'optimole-wp' ) ); return $actions; } /** * Enqueue scripts. * * @param string $hook The hook. */ public function enqueue_scripts( $hook ) { if ( $hook !== 'post.php' && $hook !== 'upload.php' ) { return; } if ( $hook === 'post.php' ) { $id = (int) sanitize_text_field( $_GET['post'] ); if ( ! $id ) { return; } if ( ! current_user_can( 'edit_post', $id ) ) { return; } if ( get_post_type( $id ) !== 'attachment' ) { return; } $mime_type = get_post_mime_type( $id ); $max_file_size = wp_max_upload_size(); // translators: %s is the max file size in MB. $max_file_size_error = sprintf( __( 'File size is too large. Max file size is %sMB', 'optimole-wp' ), $max_file_size / 1024 / 1024 ); wp_enqueue_style( 'optml-attachment-edit', OPTML_URL . 'assets/css/single-attachment.css', [], OPTML_VERSION ); wp_register_script( 'optml-attachment-edit', OPTML_URL . 'assets/js/single-attachment.js', [ 'jquery' ], OPTML_VERSION, true ); wp_localize_script( 'optml-attachment-edit', 'OMAttachmentEdit', [ 'ajaxURL' => admin_url( 'admin-ajax.php' ), 'maxFileSize' => $max_file_size, 'attachmentId' => $id, 'mimeType' => $mime_type, 'nonce' => wp_create_nonce( 'optml_replace_media_nonce' ), 'i18n' => [ 'maxFileSizeError' => $max_file_size_error, 'replaceFileError' => __( 'Error replacing file', 'optimole-wp' ), ], ] ); wp_enqueue_script( 'optml-attachment-edit' ); } elseif ( $hook === 'upload.php' ) { wp_enqueue_script( 'optml-modal-attachment', OPTML_URL . 'assets/js/modal-attachment.js', [ 'jquery', 'media-views', 'media-models' ], OPTML_VERSION, true ); wp_localize_script( 'optml-modal-attachment', 'OptimoleModalAttachment', [ 'editPostURL' => admin_url( 'post.php' ), 'i18n' => [ 'replaceOrRename' => __( 'Replace or Rename', 'optimole-wp' ), ], ] ); } } /** * Add fields to attachment edit form. * * @param array $form_fields Array of form fields. * @param WP_Post $post The post object. * * @return array Modified form fields. */ public function add_attachment_fields( $form_fields, $post ) { if ( ! function_exists( 'get_current_screen' ) ) { return $form_fields; } $screen = get_current_screen(); $attachment = new Optml_Attachment_Model( $post->ID ); if ( ! $attachment->can_be_renamed_or_replaced() ) { return $form_fields; } if ( ! isset( $screen ) ) { return $form_fields; } if ( $screen->parent_base !== 'upload' ) { return $form_fields; } $form_fields['optml_rename_file'] = [ 'label' => __( 'Rename attached file', 'optimole-wp' ), 'input' => 'html', 'html' => $this->get_rename_field( $attachment ), ]; $form_fields['optml_replace_file'] = [ 'label' => __( 'Replace file', 'optimole-wp' ), 'input' => 'html', 'html' => $this->get_replace_field( $attachment ), ]; $form_fields['optml_footer_row'] = [ 'label' => '', 'input' => 'html', 'html' => $this->get_footer_html(), ]; $form_fields['optml_spacer_row'] = [ 'label' => '', 'input' => 'html', 'html' => '
', ]; return $form_fields; } /** * Get the rename field HTML. * * @param \Optml_Attachment_Model $attachment The attachment model. * * @return string The HTML. */ private function get_rename_field( \Optml_Attachment_Model $attachment ) { $file_name_no_ext = $attachment->get_filename_no_ext(); $file_ext = $attachment->get_extension(); $html = ''; $html .= '
'; $html .= '
'; $html .= ''; $html .= '.' . esc_html( $file_ext ) . ''; $html .= '
'; $html .= ''; $html .= '
'; $html .= ''; wp_nonce_field( 'optml_rename_media_nonce', 'optml_rename_nonce' ); return $html; } /** * Get the replace field HTML. * * @param \Optml_Attachment_Model $attachment The attachment model. * * @return string The HTML. */ private function get_replace_field( \Optml_Attachment_Model $attachment ) { $file_ext = $attachment->get_extension(); $file_ext = in_array( $file_ext, [ 'jpg', 'jpeg' ], true ) ? [ '.jpg', '.jpeg' ] : [ '.' . $file_ext ]; $html = '
'; $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; $html .= ''; $html .= ''; $html .= $this->get_svg_loader(); $html .= '

' . __( 'This will replace the current file with the new one. This action cannot be undone.', 'optimole-wp' ) . '

'; $html .= '
'; $html .= ''; $html .= '
'; return $html; } /** * Get the footer HTML. * * @return string The HTML. */ private function get_footer_html() { $html = ''; $html .= '
'; $html .= '' . __( 'Optimole logo', 'optimole-wp' ) . ''; // translators: %s is the 'Optimole'. $html .= '' . sprintf( __( 'Powered by %s', 'optimole-wp' ), 'Optimole' ) . ''; $html .= '
'; return $html; } /** * Prepare the new filename before saving. * * @param array $post_data Array of post data. * @param array $attachment Array of attachment data. * * @return array Modified post data. */ public function prepare_attachment_filename( array $post_data, array $attachment ) { if ( ! current_user_can( 'edit_post', $post_data['ID'] ) ) { return $post_data; } if ( ! isset( $post_data['post_type'] ) || $post_data['post_type'] !== 'attachment' ) { return $post_data; } if ( ! isset( $post_data['optml_rename_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( $post_data['optml_rename_nonce'] ), 'optml_rename_media_nonce' ) ) { return $post_data; } $new_name = sanitize_text_field( $post_data['optml_rename_file'] ); $new_name = trim( $new_name ); if ( empty( $new_name ) ) { return $post_data; } if ( strlen( $new_name ) > 100 ) { return $post_data; } /** * Store filename for later, it will be used to rename the attachment. * * We do it this way because we don't want to rename the attachment immediately, during the attachment fields update as it will break things. * * @see Optml_Attachment_Edit::save_attachment_filename() */ update_post_meta( $post_data['ID'], '_optml_pending_rename', $new_name ); return $post_data; } /** * Save the new filename when attachment is updated * * @param int $post_id The post ID. */ public function save_attachment_filename( $post_id ) { $new_filename = get_post_meta( $post_id, '_optml_pending_rename', true ); if ( empty( $new_filename ) ) { return; } // Delete the meta so we don't rename again delete_post_meta( $post_id, '_optml_pending_rename' ); $renamer = new Optml_Attachment_Rename( $post_id, $new_filename ); $status = $renamer->rename(); if ( is_wp_error( $status ) ) { wp_die( $status->get_error_message() ); } } /** * Replace the file */ public function replace_file() { if ( ! check_ajax_referer( 'optml_replace_media_nonce', 'optml_replace_nonce', false ) ) { wp_send_json_error( __( 'Security check failed', 'optimole-wp' ) ); } $id = absint( $_POST['attachment_id'] ?? 0 ); if ( ! $id ) { wp_send_json_error( __( 'Invalid attachment ID', 'optimole-wp' ) ); } if ( get_post_type( $id ) !== 'attachment' ) { wp_send_json_error( __( 'Invalid attachment ID', 'optimole-wp' ) ); } if ( ! current_user_can( 'edit_post', $id ) ) { wp_send_json_error( __( 'You are not allowed to replace this file', 'optimole-wp' ) ); } if ( ! isset( $_FILES['file'] ) ) { wp_send_json_error( __( 'No file uploaded', 'optimole-wp' ) ); } $file_info = wp_check_filetype_and_ext( $_FILES['file']['tmp_name'], $_FILES['file']['name'] ); if ( empty( $file_info['type'] ) ) { wp_send_json_error( __( 'Could not determine uploaded file type', 'optimole-wp' ) ); } $original_mime = get_post_mime_type( $id ); if ( $file_info['type'] !== $original_mime ) { wp_send_json_error( __( 'The uploaded file type does not match the original file type.', 'optimole-wp' ) ); } $replacer = new Optml_Attachment_Replace( $id, $_FILES['file'] ); $replaced = $replacer->replace(); $is_error = is_wp_error( $replaced ); $response = [ 'success' => ! $is_error, 'message' => $is_error ? $replaced->get_error_message() : __( 'File replaced successfully', 'optimole-wp' ), ]; wp_send_json( $response ); } /** * Bust cached assets when an attachment is renamed. * * @param int $attachment_id The attachment ID. * @param string $old_url The old attachment URL. * @param string $new_url The new attachment URL. */ public function bust_cache_on_rename( $attachment_id, $old_url, $new_url ) { $this->clear_cache(); } /** * Bust cached assets when an attachment is replaced. * * @param int $attachment_id The attachment ID. * * @return void */ public function bust_cache_on_replace( $attachment_id ) { $this->clear_cache(); } /** * Clear the cache for third-party plugins. * * @return void */ private function clear_cache() { if ( class_exists( '\ThemeIsle\GutenbergBlocks\Server\Dashboard_Server' ) && is_callable( [ '\ThemeIsle\GutenbergBlocks\Server\Dashboard_Server', 'regenerate_styles' ] ) ) { \ThemeIsle\GutenbergBlocks\Server\Dashboard_Server::regenerate_styles(); } if ( did_action( 'elementor/loaded' ) ) { if ( class_exists( '\Elementor\Plugin' ) ) { \Elementor\Plugin::instance()->files_manager->clear_cache(); } } } /** * Get the SVG loader. * * @return string The SVG loader. */ private function get_svg_loader() { return ''; } }