The files the dev seeds put in a site's media library, and where any other seed gets a picture.
A media row used to be written with an invented path — /uploads/images/3.jpg, which nothing had
ever written a file to — so every thumbnail in the library fell back to its type glyph, the
builder's media sheet handed pages an <img src> that answered 404, and a blog cover was either
nothing or one of the marketing site's own photographs. The set under priv/dev_seed_media is
drawn from primitives rather than photographed: nobody's copyright, nothing downloaded, and small
enough (well under 40 KB each) to live in the repository.
A FILE'S NAME SAYS WHAT IT IS FOR. cover-* is a wide banner, card-* a listing picture,
avatar-* a portrait and doc-* a document; that prefix is the whole registration, so adding one
is dropping it in the directory. An entry whose prefix is none of those — or that is not a file at
all — is left alone rather than guessed at: files/0 is what the seed writes, and it only names
what it can describe.
Storing goes through the resource's own upload path — Media.validate_and_process_file/1 then
Media.save_file_to_storage/3 — so a seeded row lands exactly where an uploaded one does, under
/uploads/<site>/media/<category>/<uuid>.<ext>, and replacing, archiving or deleting it from the
admin works on it like any other file. The copy is staged through a temporary file first: storing
removes the source it is given, and the source here is a file the repository ships.
There are no videos in the set. A real .mp4 needs an encoder nothing in this toolchain has, and a
row pointing at one we could not write is the 404 this module exists to remove. That costs the dev
database the one :videos row the old seed invented, so a seeded library no longer has anything
for the media screen's type filter, its by_type read or the film glyph the thumbnail column draws
in place of a picture — ground the resource's own tests and the stress seed still cover, and that a
real .webm should take back the day something here can write one.
Summary
Functions
The pixel size of path in the shape the dimensions attribute stores, or %{} for a file whose
header this cannot read.
Where the shipped files live.
Every shipped file as %{filename: ..., path: ..., shape: ..., title: ...}, ordered by name.
The paths of the images site_id already has, grouped by shape — %{cover: [...], card: [...], avatar: [...]}.
Writes whatever of the set site_id does not have yet into its library, one category per shape
the set has, and returns the media rows it wrote.
Functions
The pixel size of path in the shape the dimensions attribute stores, or %{} for a file whose
header this cannot read.
Read from the file rather than declared beside it, so a replaced picture cannot leave a row
describing the one before it. Every picture in the set is a lossy WebP, which keeps its canvas
size in the first chunk (VP8) 26 bytes in, as two 14-bit values; that is the one header this
reads. Anything else — a document, or a lossless (VP8L) or extended (VP8X) WebP somebody adds
later — answers %{} rather than a guess, and the suite says which file it was, so the clause for
that chunk gets written the day a file needs it.
@spec directory() :: String.t()
Where the shipped files live.
Configurable, the way MishkaCmsCore.Runtime.PageUpload.directory/1 is, and for a reason the
shipped path cannot cover: a file's presence in this directory IS its registration, and under
:test the path below resolves through Mix's priv symlink to the repository's own source. A
suite proving that a file dropped in between two runs is picked up would be dropping it into the
set the package ships — one killed VM away from a stray picture nothing ignores and git add -A
commits. Pointed somewhere else, it writes where it can afford to.
Every shipped file as %{filename: ..., path: ..., shape: ..., title: ...}, ordered by name.
Answers [] when the directory is not there — a package that did not ship it seeds a library with
nothing in it rather than failing the whole run.
The paths of the images site_id already has, grouped by shape — %{cover: [...], card: [...], avatar: [...]}.
This is how a seed that needs a picture asks for one: the blog's covers and avatars are rows in
the library rather than strings pointing at whatever happens to be under priv/static. A site
that has not been media-seeded answers %{}, and every caller has to read that as "no picture",
because that is also what a fresh install looks like.
@spec install(String.t()) :: [MishkaCmsCore.Runtime.Media.t()]
Writes whatever of the set site_id does not have yet into its library, one category per shape
the set has, and returns the media rows it wrote.
A file that cannot be stored is reported and skipped: a library short one picture is worth more to whoever is seeding than a run that stops on it.
RUN AGAIN, THIS ADDS ONLY WHAT IS NEW. Reseeding is how a developer gets the pictures a later
version of this set ships without dropping their database, so a category that is there is reused
and a file that is there is passed over — which is also what makes dropping one more file into
priv/dev_seed_media and reseeding the way to add it. It never updates: the row an admin renamed,
re-described or moved to another category is theirs.