Repository navigation
Store media assets with versioned metadata, folders and tags #2542
Copy link
Copy link
Closed
Labels
Milestone
Description
Part of #2427 (F-MED). Next slice after the storage (#2540): media assets with versioned metadata, including folders, tags, alt text and caption, and their use through the reference index (MED-01, MED-02, CNT-05). The bytes go to the configured storage, and every upload and metadata change makes a new version, as entries do (CNT-02).
Scope
- Core (
FluentCMS.Core.Media):MediaAsset: id, site, latest version, published version and the latest version's metadata.MediaAssetVersion: file name, content type, length, SHA-256, storage name and key, folder, tags, alt text, caption, and when it was written.AssetMetadata, checked all at once by field (UX-03):- a file name without path separators;
- a folder path of lowercase slug segments, such as
products/drills, or none; - up to 32 distinct tags of lowercase words;
- alt text and a caption, each blank-free when given.
- Core:
IMediaLibrary, returningResult:- upload a stream with its content type and metadata;
- update the metadata from the version the caller read;
- read an asset or any of its versions;
- list assets by folder (with or without subfolders) and by tag;
- list the folders in use;
- open an asset's bytes.
- Uploads: the bytes go to the storage
Media__Storagenames, and the version records that storage. An empty file, or one larger thanMedia__MaxBytes(50 MB by default), is refused and its bytes are deleted again. A new version made by a metadata change keeps the same bytes. - Infrastructure:
MediaAssetsandMediaAssetVersions, scoped to the site. A trigger refuses any update of a version row on both providers, as for entry versions. Concurrent updates from one version get a conflict.media.uploadedandmedia.updatedare appended in the same unit of work. - Usage (CNT-05): an entry that references a media asset that does not exist now fails with
reference_not_found, as a missing entry does. Where used for an asset (Index entry references and answer where used #2492) lists the entries that show it. - Migrations for SQLite and PostgreSQL, each with a working
Down.
Out of scope
- Media operations in change sets and publishing them, the upload and attach tools, and media in agent scopes: the next slice.
- The "alt text required" check: the slice after.
- Soft delete and restore: the last slice.
- The library screen: after the desk's layout exists (F-DSK F-DSK: Review desk as the home screen #2422).
- Image processing and variants (M1 out of scope).
Acceptance
- An upload stores the bytes in the configured storage and version 1 with its metadata, and the bytes read back.
media.uploadednames the asset. - A metadata update stores the next version with the same bytes. A stale base version gets
version_conflict, and invalid metadata comes back field by field, each storing nothing. - An empty or oversized upload is refused and leaves no bytes behind.
- Assets list by folder, with or without subfolders, and by tag, and the folders in use list once each.
- An entry that references a missing asset is refused. An entry that references an asset appears in where used for it.
- An update of a version row fails on both providers.
- Everything above passes on SQLite and PostgreSQL, the new migration's
Downworks on both, andProjectReferenceRulesTestspass with no new package.
Its tests define content types with media fields, so it merges after SCH-05 (#2520).
Activity
Store media assets with versioned metadata, folders and tags (#2543)
Put media in change sets and add the media tools (#2546)