Repository navigation
Media Library: find attachments not used anywhere on the site - #84300
Open
Vrishabhsk wants to merge 4 commits into
Open
Vrishabhsk wants to merge 4 commits into
Vrishabhsk wants to merge 4 commits into
Conversation
🤖 PR meta 🤖🎉 PropsIf you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. Updated as activity occurs, without notifying anyone named here. Add the 🏷️ LabelsThis pull request needs exactly one label indicating its type, and has 0.
Read more about Type labels in Gutenberg. If you cannot add labels yourself, a reviewer can do it for you. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
Adds a "Unused" view to the Media Library so people can find media that is not referenced by any post, page, template, or pattern — the files that are candidates for cleanup.
Concretely:
usedsignal on attachments, exposed through the REST API:GET /wp/v2/media?used=false→ only unused attachments.GET /wp/v2/media?used=true→ only used attachments.GET /wp/v2/media?include_used=true→ includes the computedusedboolean on each item.usedfield to "Unused".Used/Unused) that can be added through the view options or the "Add filter" menu.Why?
WordPress's existing "Attached to" relation only records where a file was uploaded from. An image inserted into another post, a featured image, a logo, or a file placed via the library all read as "unattached" even though they are in use. That misleads people cleaning up storage into deleting files the site still shows.
This computes a stronger, conservative "is this file referenced anywhere?" signal:
core/image,core/cover,core/audio,core/video,core/file,core/playlist-track,core/media-text,core/gallery);wp-image-<id>/wp-attachment-<id>,[gallery ids="…"], and the attachment URL;Detection is deliberately conservative: any reference found counts, and ambiguity resolves to "used". A false "unused" is what leads to deleting a file that is still shown — the dangerous direction — so a file is only reported unused when no reference was found.
How?
lib/media/class-gutenberg-media-usage.php— computes the used set by parsing post content withparse_blocks()(not regex over serialized markup) and reading a block→attribute map, mirroringmedia-id attributesinpackages/editor/src/store/utils/attach-media-in-post/media-ids-in-blocks.js. The result is memoized per request and invalidated on content/meta/option writes. Extensible throughgutenberg_media_usage_scanned_post_types,gutenberg_media_usage_media_id_attributes,gutenberg_used_attachment_ids, andgutenberg_attachment_is_used.usedfilter maps topost__in/post__not_in;include_usedgates the computed field. Both are opt-in, because detection reads every post's content, so ordinary Media Library browsing and the editor's media modal are unaffected.packages/media-fields— newusedField, registered inORDERED_MEDIA_FIELDSso both the attachment list and the media editor consume it throughusePostFields, instead of special-casingattachmentin the post-list route.routes/post-list— translates theusedfilter (and a visibleusedcolumn) to the REST query inviewToQuery().Testing Instructions
Automated
Manual
npm run wp-env-test start wp-env run cli -- wp plugin activate gutenberg wp-env run cli -- wp option update gutenberg-experiments --format=json \ '{"gutenberg-extensible-site-editor":true,"gutenberg-media-editor":true}'admin.php?page=site-editor-v2&p=/types/attachment/list/allUsed/Unusedfor each file.Screenshots / screencast
Notes / open questions
upload.phpscreen. There is currently no admin-menu entry for that list; it is reached via URL or the media editor's breadcrumb until the new library ships more broadly.Use of AI Tools
This change was developed with opencode using the
deepseek-v4.1-flash:cloudmodel served through Ollama Cloud. The model was used to research the codebase, implement the PHP detection and REST layer, theusedfield and its registration, the post-list query translation, and the unit tests, and to run the feature end to end against a localwp-envsite.