Changeset 3478375
- Timestamp:
- 03/09/2026 05:02:00 PM (4 weeks ago)
- Location:
- a1-tools/trunk
- Files:
-
- 3 edited
-
a1-tools.php (modified) (2 diffs)
-
includes/class-a1-tools-media-management.php (modified) (6 diffs)
-
readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
a1-tools/trunk/a1-tools.php
r3478262 r3478375 4 4 * Plugin URI: https://tools.a-1chimney.com 5 5 * 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. 16 * Version: 2.0.2 7 7 * Requires at least: 5.0 8 8 * Requires PHP: 7.4 … … 21 21 22 22 // Plugin constants. 23 define( 'A1TOOLS_VERSION', '2.0. 1' );23 define( 'A1TOOLS_VERSION', '2.0.2' ); 24 24 define( 'A1TOOLS_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 25 25 define( 'A1TOOLS_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); -
a1-tools/trunk/includes/class-a1-tools-media-management.php
r3478262 r3478375 42 42 add_action( 'wp_ajax_a1tools_find_duplicates', array( $this, 'ajax_find_duplicates' ) ); 43 43 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' ) );46 44 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) ); 47 45 } … … 72 70 'nonceDuplicates' => wp_create_nonce( 'a1tools_find_duplicates' ), 73 71 'nonceUnused' => wp_create_nonce( 'a1tools_scan_unused' ), 74 'nonceDelete' => wp_create_nonce( 'a1tools_delete_media' ),75 'nonceReplace' => wp_create_nonce( 'a1tools_replace_media' ),76 72 ) ); 77 73 … … 593 589 594 590 // ========================================================================= 595 // AJAX: Delete Media596 // =========================================================================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 File624 // =========================================================================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 // =========================================================================754 591 // Rename Logic (preserved from v1) 755 592 // ========================================================================= … … 1085 922 .a1mm-undo-link { font-size:12px; color:#2271b1; cursor:pointer; margin-left:4px; text-decoration:underline; } 1086 923 .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; }1089 924 .a1mm-meta-msg { font-size:12px; margin-left:4px; } 1090 925 .a1mm-meta-msg.success { color:#00a32a; } … … 1237 1072 + '<label class="a1mm-refs-label"><input type="checkbox" class="a1mm-refs-cb" checked /> Update refs</label>' 1238 1073 + '<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>'1242 1074 + '<span class="a1mm-item-msg"></span>' 1243 1075 + '</div>' … … 1382 1214 }); 1383 1215 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: id1396 }, 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 line1449 var mp = [esc(d.mime_type), esc(d.file_size_fmt)];1450 if (d.width && d.height) mp.push(d.width+'×'+d.height);1451 $it.find('.a1mm-meta').html(mp.join(' | '));1452 // Update size badges1453 $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 1471 1216 // ---- Bulk Rename ---- 1472 1217 $('#a1mm-bulk-rename-btn').on('click', function() { -
a1-tools/trunk/readme.txt
r3478262 r3478375 4 4 Requires at least: 5.0 5 5 Tested up to: 6.9 6 Stable tag: 2.0. 16 Stable tag: 2.0.2 7 7 Requires PHP: 7.4 8 8 License: GPLv2 or later … … 151 151 152 152 == 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 153 156 154 157 = 2.0.1 =
Note: See TracChangeset
for help on using the changeset viewer.