{"id":5016,"date":"2025-09-18T16:25:50","date_gmt":"2025-09-18T14:25:50","guid":{"rendered":"https:\/\/wpmastertoolkit.com\/module\/media-replacement\/"},"modified":"2025-09-18T16:37:24","modified_gmt":"2025-09-18T14:37:24","slug":"media-replacement","status":"publish","type":"module","link":"https:\/\/wpmastertoolkit.com\/en\/module\/5016-autosave-v1\/","title":{"rendered":"Media Replacement"},"content":{"rendered":"<h1 class=\"wp-block-heading\">Media Replacement - Replace WordPress media without breaking your links<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>We've all been there: a badly retouched image, an obsolete PDF, a video compressed too hard... but already inserted all over the site. Deleting then re-importing breaks URLs, leaves pages with dead links, and changes the media ID.<br>The module <strong>Media Replacement<\/strong> of WPMasterToolKit solves this problem: it <strong>replaces the source file<\/strong> media <strong>without changing its ID, file name or publication date<\/strong>. Result : <strong>all URLs and integrations remain valid<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Which plugins can this module replace?<\/h2>\n\n\n\n<p>Relevant if you use a dedicated plugin such as \"Enable Media Replace\". This module <strong>offers the same logic<\/strong> (in-place replacement) but integrated natively into WPMasterToolKit, with no additional plug-ins required.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Exactly what the module does<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>In-place replacement<\/strong> copy your new file <strong>over the existing file<\/strong> on the disc.<\/li>\n\n\n\n<li><strong>Identity preserved<\/strong> : <strong>ID, slug\/filename and date<\/strong> remain the same - so <strong>no URL changes<\/strong>.<\/li>\n\n\n\n<li><strong>Regenerated miniatures<\/strong> After replacement, the module restarts <code data-no-auto-translation=\"\">wp_generate_attachment_metadata()<\/code> for <strong>recreate all undersizes<\/strong> (thumbnails).<\/li>\n\n\n\n<li><strong>Strict type checking<\/strong> the new file <strong>must have the same MIME type<\/strong> (e.g. JPG \u2192 JPG, PDF \u2192 PDF). This avoids inconsistencies and integration problems.<\/li>\n\n\n\n<li><strong>Visual overview<\/strong> an admin-side interface for viewing information <strong>\"Current<\/strong> vs. <strong>\"New<\/strong> (type, size, width\/height for images) before validation.<\/li>\n\n\n\n<li><strong>Reliable cleaning of old files<\/strong> deletion of existing files and sub-sizes, including images <strong><code data-no-auto-translation=\"\">-scaled<\/code><\/strong>. If a plugin (e.g. multilingual) blocks deletion, a <strong>\"hard delete<\/strong> makes sure to wipe off any leftovers.<\/li>\n\n\n\n<li><strong>Natural integration into the admin<\/strong> :\n<ul class=\"wp-block-list\">\n<li>Button <strong>\"Replace media<\/strong> in the line actions of the <strong>Media library<\/strong> (list).<\/li>\n\n\n\n<li>Button in the <strong>editing mode<\/strong> media.<\/li>\n\n\n\n<li>Button in the <strong>Publish box<\/strong> (attachment editing screen).<\/li>\n\n\n\n<li>An internal page (under <strong>Media<\/strong>) handles upload and confirmation - it is <strong>hidden from the menu<\/strong> to remain accessible only via action buttons.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">UX details on the administration side<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Clear interface with two columns: <strong>Current<\/strong> vs. <strong>New<\/strong>.<\/li>\n\n\n\n<li>Drag &amp; drop or click to select file.<\/li>\n\n\n\n<li><strong>Immediate validation on the JS side<\/strong> (max site weight, same type), with localized messages.<\/li>\n\n\n\n<li><strong>Replace\" button<\/strong> disabled until validations are completed.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Scenarios and limits to be aware of<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Same type required<\/strong> : you <strong>can't<\/strong> replace a PNG with a JPG. Keeping the same format guarantees 0 case.<\/li>\n\n\n\n<li><strong>File name retained<\/strong> : it's designed to keep <strong>exactly the same URL<\/strong>.<\/li>\n\n\n\n<li><strong>CDN \/ cache<\/strong> After replacement, remember to <strong>purge cache<\/strong> if you use a CDN or aggressive caching.<\/li>\n\n\n\n<li><strong>Dimensions<\/strong> if you import a larger\/smaller image, the thumbnails will be regenerated accordingly (depending on your WordPress image sizes\/theme).<\/li>\n\n\n\n<li><strong>Permissions<\/strong> accessible to roles with <code data-no-auto-translation=\"\">upload_files<\/code>.<\/li>\n\n\n\n<li><strong>Security<\/strong> everything is protected by <strong>nonce<\/strong> and controls on the uploaded file (<code data-no-auto-translation=\"\">is_uploaded_file<\/code>authorized types, max WordPress size).<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">How to use this module<\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Go to <strong>Media<\/strong> \u2192 <strong>Library<\/strong>.<\/li>\n\n\n\n<li>On the media line to be replaced, click <strong>Replace media<\/strong> (or open the media file and click the same button).<figure class=\"wp-block-image size-large\"><img alt=\"\" fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"417\" src=\"https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-1024x417.png\" class=\"wp-image-5017\" srcset=\"https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-1024x417.png 1024w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-300x122.png 300w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-768x313.png 768w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-1536x626.png 1536w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-18x7.png 18w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image.png 1899w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/li>\n\n\n\n<li>Drag and drop the <strong>new file<\/strong> (same type as the original).<figure class=\"wp-block-image size-large\"><img alt=\"\" decoding=\"async\" width=\"1024\" height=\"632\" src=\"https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-1-1024x632.png\" class=\"wp-image-5019\" srcset=\"https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-1-1024x632.png 1024w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-1-300x185.png 300w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-1-768x474.png 768w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-1-18x12.png 18w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-1.png 1296w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/li>\n\n\n\n<li>Check info in preview <strong>\"New\"<\/strong>.<\/li>\n\n\n\n<li>Click <strong>Replace<\/strong>.<br>That's all there is to it: <strong>URL does not change<\/strong>the site continues to point to the same ID, but with the <strong>updated file<\/strong>.<figure class=\"wp-block-image size-large\"><img alt=\"\" decoding=\"async\" width=\"1024\" height=\"639\" src=\"https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-2-1024x639.png\" class=\"wp-image-5022\" srcset=\"https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-2-1024x639.png 1024w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-2-300x187.png 300w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-2-768x479.png 768w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-2-18x12.png 18w, https:\/\/wpmastertoolkit.com\/wp-content\/uploads\/2025\/09\/image-2.png 1293w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Our technical choices (and why)<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Keep ID\/path<\/strong> copy the new file <strong>on the original path<\/strong> (<code data-no-auto-translation=\"\">copy()<\/code> \u2192 same name, same location). This is the only way to ensure that <strong>all links remain valid<\/strong>.<\/li>\n\n\n\n<li><strong>Strict MIME validation<\/strong> comparison between the original MIME and that of the new file via <code data-no-auto-translation=\"\">wp_check_filetype_and_ext()<\/code> and <code data-no-auto-translation=\"\">get_post_mime_type()<\/code> to avoid surprises (embed, players, HTML tags, etc.).<\/li>\n\n\n\n<li><strong>Robust cleaning<\/strong> we use <code data-no-auto-translation=\"\">wp_delete_attachment_files()<\/code> with metadata and backup sizes, then a <strong>fallback<\/strong> physical deletion if necessary (in the case of images <code data-no-auto-translation=\"\">-scaled<\/code> or multilingual plugins).<\/li>\n\n\n\n<li><strong>Metadata regeneration<\/strong> : <code data-no-auto-translation=\"\">wp_generate_attachment_metadata()<\/code> + <code data-no-auto-translation=\"\">wp_update_attachment_metadata()<\/code> to recreate all sub-sizes immediately after replacement - no need for third-party tools.<\/li>\n\n\n\n<li><strong>Experience admin<\/strong> buttons added via :\n<ul class=\"wp-block-list\">\n<li><code data-no-auto-translation=\"\">media_row_actions<\/code><\/li>\n\n\n\n<li><code data-no-auto-translation=\"\">attachment_fields_to_edit<\/code> (for the modal)<\/li>\n\n\n\n<li><code data-no-auto-translation=\"\">attachment_submitbox_misc_actions<\/code> (edit screen)<br>A <strong>sub-menu page hidden<\/strong> is loaded on demand to display the replacement UI, with dedicated assets (CSS\/JS) and localized strings.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Safety &amp; capacity<\/strong> :\n<ul class=\"wp-block-list\">\n<li>Restricted access via <code data-no-auto-translation=\"\">upload_files<\/code>.<\/li>\n\n\n\n<li><strong>Nonce<\/strong> for all URLs and forms.<\/li>\n\n\n\n<li>Controls <code data-no-auto-translation=\"\">is_uploaded_file<\/code>management of upload errors, and respect for <code data-no-auto-translation=\"\">wp_max_upload_size()<\/code> (via localized JS).<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li><strong>Performance<\/strong> conditional asset loading <strong>only<\/strong> on the replacement page. If the module is not activated, <strong>nothing is loaded<\/strong>.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>The module <strong>Media Replacement<\/strong> of WPMasterToolKit makes media replacement a simple <strong>safe, fast and without side effects<\/strong> : <strong>same ID, same URL, same date<\/strong>but <strong>updated file<\/strong> and <strong>regenerated miniatures<\/strong>. No more broken links or the hassle of re-importing. It's the ideal tool for keeping media libraries clean and up-to-date, with complete confidence.<\/p>\n\n\n\n<p><\/p>","protected":false},"excerpt":{"rendered":"<p>The WPMasterToolKit plugin for WordPress offers a practical solution with its \"Media Replacement\" module, allowing you to replace media files without breaking existing links. More integrated and effective than similar plugins such as \"Enable Media Replace\", this function aims to reduce the number of active plugins to improve site performance. It integrates seamlessly into the WordPress administration interface, enabling transparent and secure file replacement while maintaining link integrity. It's the ideal solution for simplified, optimized media management.<\/p>","protected":false},"featured_media":0,"parent":0,"template":"","meta":{"_acf_changed":true,"_seopress_robots_primary_cat":"","_seopress_titles_title":"","_seopress_titles_desc":"","_seopress_robots_index":"","_surecart_dashboard_logo_width":"180px","_surecart_dashboard_show_logo":true,"_surecart_dashboard_navigation_orders":true,"_surecart_dashboard_navigation_invoices":true,"_surecart_dashboard_navigation_subscriptions":true,"_surecart_dashboard_navigation_downloads":true,"_surecart_dashboard_navigation_billing":true,"_surecart_dashboard_navigation_account":true},"class_list":["post-5016","module","type-module","status-publish","hentry"],"acf":[],"_links":{"self":[{"href":"https:\/\/wpmastertoolkit.com\/en\/wp-json\/wp\/v2\/module\/5016","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wpmastertoolkit.com\/en\/wp-json\/wp\/v2\/module"}],"about":[{"href":"https:\/\/wpmastertoolkit.com\/en\/wp-json\/wp\/v2\/types\/module"}],"wp:attachment":[{"href":"https:\/\/wpmastertoolkit.com\/en\/wp-json\/wp\/v2\/media?parent=5016"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}