Appearance
Media Replace
Replace a media library file in place: the ID and the address stay, links in content are updated — as Enable Media Replace does.
kitloom/media-replace · admins: kitloom/media-replace-filament, kitloom/media-replace-nova
A new version of a file that is already in the media library — a corrected PDF, a retouched photo, a logo in a new colour — without uploading it as a new file and changing every page that shows the old one. The file is replaced in place: the attachment keeps its ID, and with it its place in every post, gallery, widget and custom field. What the Enable Media Replace plugin does in WordPress, with the same two ways and the same rules.
Where it is
On Media → Library in either admin, every file has Replace file: on its row in the list, and in the header of its page. It is offered to users who may upload files and edit that file — the plugin's own rule: an author sees it on their own uploads, an editor on everyone's. There is no permission of its own to give.
The window asks for the new file, how to replace it, and whether to change the date.
The two ways
Just replace the file. The new file takes the old one's place on the disk, under the same name. Its address does not change, so every link to it keeps working without anyone touching the content. The new file must be of the same type as the current one (a .jpg for a .jpg; .jpeg counts as the same); choose the other way to change the type.
Replace the file, use the new file name and update all links. The new file is stored under its own name in the attachment's folder (2024/05/banner.png beside where photo.jpg was), of any type the library takes. The old file is deleted, and the old address is replaced by the new one wherever content keeps it: post content and excerpts, custom fields and other post meta, widgets and other options. A link that still carries the WordPress host the content came from (https://old-site.com/wp-content/uploads/2024/05/photo.jpg) follows too: the path from the uploads folder is rewritten as well as the full address. Revisions are left as they were — they are what the record was.
In both ways an image's sizes (thumbnail, medium, large and the rest) are cut again from the new file, the files of the old sizes are deleted, and where an old size's address is no longer cut — a smaller image has no large size — the address leads to the new file itself. A new name that is the old name keeps the old place: uploading photo.jpg again does not make photo-1.jpg.
Should a file be replaced with a different file name? Choose the second way, say the new name in the file you upload: the name is the file's own, slugged as the library stores every upload.
The date
By default the attachment keeps its date: it stays where it was in the library's order and in date-based galleries. Set the date to now moves it to today — for a file that is truly new. Either way the modified time is updated, so the site's page cache lets the new file through.
What is checked
The new file goes through the library's checks as any upload does: only a type the library takes (kitloom-media.extensions, the WordPress list by default), up to the upload size limit (kitloom-media.max_size), and a type that is safe only once cleaned — an SVG, with kitloom/safe-svg — is cleaned on the way in, for the users that module lets upload it. A file that is refused changes nothing: the old file and its sizes stay as they were.
A file on a CDN or in a cache keeps its old contents until that cache expires: the address did not change, so nothing told the cache. Purge it, or use the second way for a new address.
With kitloom/search-replace
When the Search & Replace module is installed, the links are rewritten by it, the way its runs are: a revision of each post is kept before the change, serialized values are kept whole, and every record it touched is announced to the modules that index content. Without it, the module rewrites the same three tables itself; a value that holds an array is rewritten inside and written back as JSON.
For AI agents
With kitloom/ai installed, an agent whose user may upload files has media_replace: an attachment id and the new file — from a public web address, or as base64 with its name — with the mode (file_only, new_name) and date_now. The same rules as the button: the agent's user must be allowed to edit that attachment. kitloom-media-replace.ai.register set to false leaves the tool out.
Configuration
config/kitloom-media-replace.php (php artisan vendor:publish --tag=kitloom-media-replace-config):
| Key | What |
|---|---|
ai.register | false: no media_replace tool for agents |
filament.register, nova.register | false: no «Replace file» and no «Media Replace» section in that admin; the service stays for the application's own code |
For the application
Kitloom\MediaReplace\Replacer::replace($attachment, $file, $mode, $actor, dateNow: false) — the attachment (any model of a wp_posts row of type attachment), an UploadedFile or a path on the local filesystem (with name: when the path does not say the file's name — a download), a ReplaceMode, the acting user or null for the system. It answers a Kitloom\MediaReplace\Events\FileReplaced, also dispatched as an event: the mode, the old and the new path, the old and the new addresses by size, how many links were updated. It throws AuthorizationException for a user who may not, UploadNotAllowed (and its UploadTooLarge) for a file the library refuses, InvalidArgumentException for a record that is no attachment, has no file, or changes type in the first mode.
The admins reach the button through the tags both admins read for every record of a type (IndexRecordActions::TAG in Filament, IndexAction::TAG in Nova), for type attachment; the media library's screens ask for them.