Keeps a revision history only for media tagged with one of the configured
taxonomy terms. The term is read from a configurable reference field on the
media entity. On an Islandora site that field is Media Use
(field_media_use) and the default term is Preservation Master File. Every
other media item (Service File, Thumbnail Image, Extracted Text, FITS File,
Original File, ...) is updated in place on save, and its older revisions can
be removed.
Derivative media are regenerated often. Each regeneration used to add a row to
media_revision and media_field_revision and a new file_usage entry, which
kept superseded derivative files on disk. Only a few media uses have a history
worth keeping.
hook_media_presave()callssetNewRevision(FALSE)on any media whose Media Use is not a configured term. Drupal only decides whether to write a revision row after presave hooks run, so this covers the media form, JSON:API and REST, Islandora Workbench, derivative generation and migrations.- For media that keep revisions, the same hook sets the new revision's creation time to the request time when the caller left it unchanged. Core REST, Islandora Workbench and derivative saves do not set it, so the revision would otherwise carry the time of the revision it was loaded from. A time set explicitly (for example by a migration) is kept.
- Reverting a media item to an older revision is not suppressed, because the revert form saves a copy of that revision and suppressing it would overwrite the old row in place. The copy becomes the current revision as usual.
hook_media_update()queues a media item for pruning when its Media Use changes from a configured term to something else, or when a save created a new revision for a media item that keeps none (a revert, or a save forced by content moderation).- The
selective_revisions_prunequeue worker (run by cron) and theRevisionPrunerservice delete every revision except the current one. The latest revision is also kept in case a moderation workflow has a draft. Deleting a revision decrements file usage, so orphaned files become temporary and are removed by cron.
The configured terms are resolved by their field_external_uri (for example
http://pcdm.org/use#PreservationMasterFile). Every term carrying a
configured URI counts, so a media item keeps revisions when any of its Media
Use values is any matching term. This also makes duplicate terms (the same
URI on two term IDs, as a re-run migration can create) safe. Term inserts,
updates and deletes in the configured vocabulary reset the resolved set
within the same request.
The module fails open. If the Media Use field does not exist on media, if
field_external_uri does not exist on taxonomy terms, or if none of the
configured URIs matches a term, an error is logged, every media keeps its
revisions, the prune queue is suspended, and the Drush command refuses to
run. A typo in the settings can therefore never delete preservation history.
Media types without the Media Use field (for example able_player_caption)
never keep revisions.
The module is not on Packagist. Add the GitHub repository to your site's
composer.json, then require the module:
composer config repositories.selective_revisions vcs https://github.com/digitalutsc/selective_revisions
composer require digitalutsc/selective_revisions:dev-main
drush en selective_revisions
Drush 12 or later is needed for the selective-revisions:prune command; the
module itself works without Drush.
/admin/config/media/selective-revisions lets you change the field name,
vocabulary, and the list of term external URIs (one per line). The page lists
every resolved term and warns when one URI matches more than one term. Until
at least one matching term exists, every media keeps its revisions and nothing
is pruned.
Make sure every media type has Create new revision enabled so that configured uses of all types get a history; the module suppresses the revision for everything else.
drush selective-revisions:prune --dry-run # report only
drush selective-revisions:prune # queue for cron
drush selective-revisions:prune --now # delete immediately
drush selective-revisions:prune --now --bundle=image
Alias: drush sr:prune.
ddev exec "SIMPLETEST_DB=mysql://db:db@db/db vendor/bin/phpunit -c web/core web/modules/custom/selective_revisions"