Plugin Directory

Changeset 3478375


Ignore:
Timestamp:
03/09/2026 05:02:00 PM (4 weeks ago)
Author:
a1tools
Message:

v2.0.2: Remove Replace File and Delete buttons from Media Management

Location:
a1-tools/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • a1-tools/trunk/a1-tools.php

    r3478262 r3478375  
    44 * Plugin URI:        https://tools.a-1chimney.com
    55 * Description:       Connects your WordPress site to the A1 Tools platform for centralized management of contact information, social media links, and business details.
    6  * Version:           2.0.1
     6 * Version:           2.0.2
    77 * Requires at least: 5.0
    88 * Requires PHP:      7.4
     
    2121
    2222// Plugin constants.
    23 define( 'A1TOOLS_VERSION', '2.0.1' );
     23define( 'A1TOOLS_VERSION', '2.0.2' );
    2424define( 'A1TOOLS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
    2525define( 'A1TOOLS_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
  • a1-tools/trunk/includes/class-a1-tools-media-management.php

    r3478262 r3478375  
    4242        add_action( 'wp_ajax_a1tools_find_duplicates',  array( $this, 'ajax_find_duplicates' ) );
    4343        add_action( 'wp_ajax_a1tools_scan_unused',      array( $this, 'ajax_scan_unused' ) );
    44         add_action( 'wp_ajax_a1tools_delete_media',     array( $this, 'ajax_delete_media' ) );
    45         add_action( 'wp_ajax_a1tools_replace_media',    array( $this, 'ajax_replace_media' ) );
    4644        add_action( 'admin_enqueue_scripts',            array( $this, 'enqueue_admin_assets' ) );
    4745    }
     
    7270            'nonceDuplicates' => wp_create_nonce( 'a1tools_find_duplicates' ),
    7371            'nonceUnused'     => wp_create_nonce( 'a1tools_scan_unused' ),
    74             'nonceDelete'     => wp_create_nonce( 'a1tools_delete_media' ),
    75             'nonceReplace'    => wp_create_nonce( 'a1tools_replace_media' ),
    7672        ) );
    7773
     
    593589
    594590    // =========================================================================
    595     // AJAX: Delete Media
    596     // =========================================================================
    597 
    598     public function ajax_delete_media() {
    599         check_ajax_referer( 'a1tools_delete_media', 'nonce' );
    600         if ( ! current_user_can( 'delete_posts' ) ) {
    601             wp_send_json_error( array( 'message' => 'Permission denied.' ) );
    602         }
    603 
    604         $id = absint( $_POST['attachment_id'] ?? 0 );
    605         if ( ! $id ) {
    606             wp_send_json_error( array( 'message' => 'Invalid attachment ID.' ) );
    607         }
    608 
    609         $post = get_post( $id );
    610         if ( ! $post || 'attachment' !== $post->post_type ) {
    611             wp_send_json_error( array( 'message' => 'Attachment not found.' ) );
    612         }
    613 
    614         $deleted = wp_delete_attachment( $id, true );
    615         if ( ! $deleted ) {
    616             wp_send_json_error( array( 'message' => 'Could not delete the file.' ) );
    617         }
    618 
    619         wp_send_json_success( array( 'message' => 'File deleted.', 'id' => $id ) );
    620     }
    621 
    622     // =========================================================================
    623     // AJAX: Replace Media File
    624     // =========================================================================
    625 
    626     public function ajax_replace_media() {
    627         check_ajax_referer( 'a1tools_replace_media', 'nonce' );
    628         if ( ! current_user_can( 'upload_files' ) ) {
    629             wp_send_json_error( array( 'message' => 'Permission denied.' ) );
    630         }
    631 
    632         $id = absint( $_POST['attachment_id'] ?? 0 );
    633         if ( ! $id ) {
    634             wp_send_json_error( array( 'message' => 'Invalid attachment ID.' ) );
    635         }
    636 
    637         $post = get_post( $id );
    638         if ( ! $post || 'attachment' !== $post->post_type ) {
    639             wp_send_json_error( array( 'message' => 'Attachment not found.' ) );
    640         }
    641 
    642         if ( empty( $_FILES['file'] ) ) {
    643             wp_send_json_error( array( 'message' => 'No file uploaded.' ) );
    644         }
    645 
    646         require_once ABSPATH . 'wp-admin/includes/file.php';
    647         require_once ABSPATH . 'wp-admin/includes/image.php';
    648         require_once ABSPATH . 'wp-admin/includes/media.php';
    649 
    650         // Upload file to a temporary location.
    651         $upload = wp_handle_upload( $_FILES['file'], array( 'test_form' => false ) );
    652         if ( isset( $upload['error'] ) ) {
    653             wp_send_json_error( array( 'message' => $upload['error'] ) );
    654         }
    655 
    656         global $wpdb;
    657 
    658         $old_file   = get_attached_file( $id );
    659         $old_meta   = wp_get_attachment_metadata( $id );
    660         $upload_dir = wp_upload_dir();
    661         $old_dir    = dirname( $old_file );
    662 
    663         // Delete old thumbnails.
    664         if ( ! empty( $old_meta['sizes'] ) ) {
    665             foreach ( $old_meta['sizes'] as $size_data ) {
    666                 $thumb_path = trailingslashit( $old_dir ) . $size_data['file'];
    667                 if ( file_exists( $thumb_path ) ) {
    668                     @unlink( $thumb_path );
    669                 }
    670             }
    671         }
    672         // Delete old original-image backup if exists.
    673         if ( ! empty( $old_meta['original_image'] ) ) {
    674             $orig_path = trailingslashit( $old_dir ) . $old_meta['original_image'];
    675             if ( file_exists( $orig_path ) ) {
    676                 @unlink( $orig_path );
    677             }
    678         }
    679         // Delete old main file.
    680         if ( file_exists( $old_file ) ) {
    681             @unlink( $old_file );
    682         }
    683 
    684         // Keep same base name, allow extension to change.
    685         $old_name     = pathinfo( $old_file, PATHINFO_FILENAME );
    686         $old_ext      = pathinfo( $old_file, PATHINFO_EXTENSION );
    687         $new_ext      = pathinfo( $upload['file'], PATHINFO_EXTENSION );
    688         $new_basename = $old_name . '.' . $new_ext;
    689         $new_file     = trailingslashit( $old_dir ) . $new_basename;
    690 
    691         // Ensure target directory exists.
    692         wp_mkdir_p( $old_dir );
    693 
    694         // Move uploaded file to old location.
    695         if ( ! @rename( $upload['file'], $new_file ) ) {
    696             wp_send_json_error( array( 'message' => 'Could not move uploaded file.' ) );
    697         }
    698 
    699         // Update _wp_attached_file.
    700         $relative = ltrim( str_replace( wp_normalize_path( $upload_dir['basedir'] ), '', wp_normalize_path( $new_file ) ), '/\\' );
    701         update_post_meta( $id, '_wp_attached_file', $relative );
    702 
    703         // Regenerate all thumbnails.
    704         $new_meta = wp_generate_attachment_metadata( $id, $new_file );
    705         wp_update_attachment_metadata( $id, $new_meta );
    706 
    707         // Update MIME type and GUID.
    708         $new_mime = $upload['type'];
    709         $new_url  = $upload_dir['baseurl'] . '/' . $relative;
    710 
    711         $wpdb->update(
    712             $wpdb->posts,
    713             array(
    714                 'post_mime_type' => $new_mime,
    715                 'guid'          => $new_url,
    716             ),
    717             array( 'ID' => $id )
    718         );
    719 
    720         // If extension changed and update_refs is on, update references.
    721         $update_refs = ! empty( $_POST['update_refs'] );
    722         if ( $update_refs && strtolower( $old_ext ) !== strtolower( $new_ext ) ) {
    723             $old_relative = ltrim( str_replace( wp_normalize_path( $upload_dir['basedir'] ), '', wp_normalize_path( $old_file ) ), '/\\' );
    724             $old_url      = $upload_dir['baseurl'] . '/' . $old_relative;
    725 
    726             $posts_with_ref = $wpdb->get_col( $wpdb->prepare(
    727                 "SELECT ID FROM {$wpdb->posts} WHERE post_content LIKE %s AND post_type NOT IN ('revision','attachment')",
    728                 '%' . $wpdb->esc_like( $old_url ) . '%'
    729             ) );
    730             foreach ( $posts_with_ref as $pid ) {
    731                 $content = get_post_field( 'post_content', $pid );
    732                 $content = str_replace( $old_url, $new_url, $content );
    733                 wp_update_post( array( 'ID' => $pid, 'post_content' => $content ) );
    734             }
    735         }
    736 
    737         // Thumbnail for card update.
    738         $thumb_src = wp_get_attachment_image_src( $id, 'thumbnail' );
    739 
    740         wp_send_json_success( array(
    741             'message'       => 'File replaced successfully.',
    742             'filename'      => $new_basename,
    743             'url'           => $new_url,
    744             'thumbnail_url' => $thumb_src ? $thumb_src[0] : '',
    745             'mime_type'     => $new_mime,
    746             'file_size'     => filesize( $new_file ),
    747             'file_size_fmt' => size_format( filesize( $new_file ) ),
    748             'width'         => $new_meta['width'] ?? 0,
    749             'height'        => $new_meta['height'] ?? 0,
    750         ) );
    751     }
    752 
    753     // =========================================================================
    754591    // Rename Logic (preserved from v1)
    755592    // =========================================================================
     
    1085922        .a1mm-undo-link { font-size:12px; color:#2271b1; cursor:pointer; margin-left:4px; text-decoration:underline; }
    1086923        .a1mm-undo-link:hover { color:#135e96; }
    1087         .a1mm-delete-btn { color:#b32d2e !important; border-color:#b32d2e !important; }
    1088         .a1mm-delete-btn:hover { background:#b32d2e !important; color:#fff !important; }
    1089924        .a1mm-meta-msg { font-size:12px; margin-left:4px; }
    1090925        .a1mm-meta-msg.success { color:#00a32a; }
     
    12371072        +     '<label class="a1mm-refs-label"><input type="checkbox" class="a1mm-refs-cb" checked /> Update refs</label>'
    12381073        +     '<button type="button" class="button button-primary a1mm-save-meta-btn">Save</button>'
    1239         +     '<input type="file" class="a1mm-replace-file" accept="image/*,video/*,audio/*,application/pdf" style="display:none" />'
    1240         +     '<button type="button" class="button a1mm-replace-btn">Replace</button>'
    1241         +     '<button type="button" class="button a1mm-delete-btn">Delete</button>'
    12421074        +     '<span class="a1mm-item-msg"></span>'
    12431075        +   '</div>'
     
    13821214});
    13831215
    1384 // ---- Delete ----
    1385 $(document).on('click', '.a1mm-delete-btn', function() {
    1386     var $it = $(this).closest('.a1mm-item');
    1387     var id = $it.data('id');
    1388     var fn = $it.find('.a1mm-current code').text();
    1389     if (!confirm('Permanently delete "' + fn + '"? This cannot be undone.')) return;
    1390     var $b = $(this);
    1391     $b.prop('disabled',true).text('Deleting...');
    1392 
    1393     $.post(a1mm.ajax, {
    1394         action:'a1tools_delete_media', nonce:a1mm.nonceDelete,
    1395         attachment_id: id
    1396     }, function(r) {
    1397         if (r.success) {
    1398             $it.slideUp(300, function() { $(this).remove(); });
    1399         } else {
    1400             $b.prop('disabled',false).text('Delete');
    1401             alert(r.data.message||'Delete failed.');
    1402         }
    1403     }).fail(function() {
    1404         $b.prop('disabled',false).text('Delete');
    1405         alert('Network error.');
    1406     });
    1407 });
    1408 
    1409 // ---- Replace File ----
    1410 $(document).on('click', '.a1mm-replace-btn', function() {
    1411     $(this).closest('.a1mm-item').find('.a1mm-replace-file').click();
    1412 });
    1413 $(document).on('change', '.a1mm-replace-file', function() {
    1414     var file = this.files[0];
    1415     if (!file) return;
    1416     var $it = $(this).closest('.a1mm-item');
    1417     var id = $it.data('id');
    1418     var fn = $it.find('.a1mm-current code').text();
    1419     var $btn = $it.find('.a1mm-replace-btn');
    1420     var $msg = $it.find('.a1mm-item-msg');
    1421     var ur = $it.find('.a1mm-refs-cb').is(':checked') ? 1 : 0;
    1422 
    1423     if (!confirm('Replace "' + fn + '" with "' + file.name + '"?\nThe old file will be permanently replaced.')) {
    1424         this.value = ''; return;
    1425     }
    1426 
    1427     $btn.prop('disabled',true).text('Uploading...');
    1428     $msg.text('').attr('class','a1mm-item-msg');
    1429 
    1430     var fd = new FormData();
    1431     fd.append('action', 'a1tools_replace_media');
    1432     fd.append('nonce', a1mm.nonceReplace);
    1433     fd.append('attachment_id', id);
    1434     fd.append('file', file);
    1435     fd.append('update_refs', ur);
    1436 
    1437     $.ajax({
    1438         url: a1mm.ajax, type: 'POST', data: fd,
    1439         processData: false, contentType: false,
    1440         success: function(r) {
    1441             if (r.success) {
    1442                 var d = r.data;
    1443                 if (d.thumbnail_url) $it.find('.a1mm-thumb img').attr('src', d.thumbnail_url + '?t=' + Date.now());
    1444                 $it.find('.a1mm-current code').text(d.filename);
    1445                 $it.find('.a1mm-new-name').val(d.filename.replace(/\.[^.]+$/,''));
    1446                 $it.find('.a1mm-ext').text('.' + d.filename.split('.').pop());
    1447                 $it.data('url', d.url);
    1448                 // Update meta line
    1449                 var mp = [esc(d.mime_type), esc(d.file_size_fmt)];
    1450                 if (d.width && d.height) mp.push(d.width+'&times;'+d.height);
    1451                 $it.find('.a1mm-meta').html(mp.join(' &nbsp;|&nbsp; '));
    1452                 // Update size badges
    1453                 $it.find('.a1mm-badge-large').remove();
    1454                 if (d.file_size > 512000) {
    1455                     $it.find('.a1mm-badges').append('<span class="a1mm-badge a1mm-badge-large">'+esc(d.file_size_fmt)+'</span>');
    1456                 }
    1457                 $msg.text('File replaced!').attr('class','a1mm-item-msg success');
    1458             } else {
    1459                 $msg.text(r.data.message||'Replace failed.').attr('class','a1mm-item-msg error');
    1460             }
    1461             $btn.prop('disabled',false).text('Replace');
    1462         },
    1463         error: function() {
    1464             $btn.prop('disabled',false).text('Replace');
    1465             $msg.text('Upload error.').attr('class','a1mm-item-msg error');
    1466         }
    1467     });
    1468     this.value = '';
    1469 });
    1470 
    14711216// ---- Bulk Rename ----
    14721217$('#a1mm-bulk-rename-btn').on('click', function() {
  • a1-tools/trunk/readme.txt

    r3478262 r3478375  
    44Requires at least: 5.0
    55Tested up to: 6.9
    6 Stable tag: 2.0.1
     6Stable tag: 2.0.2
    77Requires PHP: 7.4
    88License: GPLv2 or later
     
    151151
    152152== Changelog ==
     153
     154= 2.0.2 =
     155* Removed: Replace File and Delete buttons from Media Management for safety — use WordPress Media Library for file deletion and replacement
    153156
    154157= 2.0.1 =
Note: See TracChangeset for help on using the changeset viewer.