The history is in one table, resource_versions (with the installation's table prefix, such as omeka_resource_versions). It has no foreign keys into Omeka's tables, so the history outlives the record, its owner and everything its snapshot refers to.
Columns
| Column | Type | Meaning |
|---|---|---|
id |
INT UNSIGNED | The version's id, used in the admin's addresses |
record_type |
VARCHAR(20) | item, collection or file |
record_id |
INT UNSIGNED | The record's number |
version_num |
INT UNSIGNED | Counted per record, from 1 |
operation |
VARCHAR(20) | create, update, delete, restore or baseline |
snapshot |
MEDIUMTEXT | The JSON snapshot (see Snapshot Format) |
snapshot_hash |
CHAR(64) | The SHA-256 used to skip saves that change nothing |
record_title |
VARCHAR(255) | The record's title then: its first Dublin Core title, or a file's original filename |
user_id, user_name |
INT, VARCHAR(255) | Who made the change, or NULL (no one signed in, and baselines) |
is_batch |
TINYINT(1) | 1 for a save made by batch edit or a background job |
batch_key |
VARCHAR(32) | A key shared by every save of one request or background job |
restored_from |
INT UNSIGNED | For a restore, the version it came from |
created_at |
DATETIME | When, in UTC |
Indexes cover (record_type, record_id, version_num), (user_id, created_at), created_at, (batch_key, is_batch) and restored_from. A snapshot can be up to 16 MB; snapshots are not compressed.
A second table, resource_version_runs, records the batch rollbacks and prunes run in the background: their criteria, status (queued, running, done, error), result, the batch key of the versions they wrote, who started them, and when.
Operations
| Operation | Written when |
|---|---|
create |
A record is saved for the first time |
update |
A record is saved and its snapshot differs from its newest version |
delete |
A record is deleted; always written |
restore |
The plugin restores a version, recreates a deleted record, or a rollback does |
baseline |
Just before the first recorded save of a record that has no history yet, with its state before that save |
Capture
The plugin listens to Omeka's record hooks for items, collections and files: before_save_* and after_save_*, before_delete_* and after_delete_*. These run for every save, whatever made it: the admin forms, batch edit, the REST API, importers, background jobs, scripts.
after_save_*builds one snapshot from the database (four queries for an item, two for a collection or file), compares its hash with the newest version's, read inbefore_save_*, and inserts one row when it differs.before_save_*, for a record with no history, first keeps its state as a baseline.before_delete_*reads the record's last state while it exists;after_delete_*writes it.- Saves of a record made while it is being created (such as the derivative job Omeka runs on a new file) are left to the creation, which records the final state once.
- Saves made in Omeka's batch edit request (
items/batch-edit-save) or in a background job or command-line script are marked as bulk, under the key of that request or process.
An exception in any of this is written to the PHP error log, and to Omeka's log, with the prefix [ResourceVersioning], and dropped: a failure to record never makes a save fail. A batch edit of 50 items takes about 3 ms more per item.
Changes made straight in the database, without saving the record through Omeka, are not recorded. Among Omeka's own:
- Adding files to an existing item from code (
insert_files_for_item()) saves the files, not the item: the files get theircreateversions at once, and the item's file list is updated at its next save. Adding files from the item form saves the item. - Deleting a collection takes its items out of it with a direct update: the items' histories show the change at their next save.
- Renaming or deleting a tag on the Tags page changes items without saving them.
Admin addresses
All are under /admin/resource-versioning, handled by ResourceVersioning_IndexController.
| Address | Method | Page |
|---|---|---|
/admin/resource-versioning |
GET | Every version; filters record_type, user_id, operation, date_from, date_to (YYYY-MM-DD), page |
/admin/resource-versioning/operations |
GET | Bulk operations and rollbacks |
/admin/resource-versioning/rollback |
GET, POST | The batch rollback wizard; POST step=preview or step=execute |
/admin/resource-versioning/retention |
GET | Retention and prunes |
/admin/resource-versioning/prune |
POST | Start a prune |
/admin/resource-versioning/record/<type>/<id> |
GET | A record's history (item, collection or file) |
/admin/resource-versioning/version/<id> |
GET | A version and its snapshot |
/admin/resource-versioning/compare/<a>[/<b>] |
GET | Two versions; b defaults to the one before a, current is the record now |
/admin/resource-versioning/restore/<id> |
GET, POST | What a restore changes, then the restore (or recreation) |
/admin/resource-versioning/batch/<key> |
GET | The versions of one batch |
POST requests need the CSRF token the pages include.