v0.0.53
7 July 2026
App-level SQLite cache, image effects and lifecycle hooks for collection items, and file-identity fixes for subdirectory-stored files.
Added
Cache: SQLite-backed key/value cache atsite/storage/cache/{name}.db.$app->cache(string $name = 'app')returns a named instance. API:get,has,set,remember,remove,flush.set()/remember()accept an optional TTL in seconds. Enabled by default; disable per name viaconfig.cache.{name}.enabled = false.item.update:afteranditem.delete:beforelifecycle hooks, alongside the existing page/user hooks. NewItem::delete()emits the delete hook before removing the item's folder.- Image transform DSL:
blur,brightness,contrast,gamma,invert,pixelate,sharpeneffects, alongside the existinggrayscale. FieldTypeCollectionitems are now indexed intosearch_index, same as pages.new()accepts an optional deterministic$uuid; addedhas()anditem()lookups.
Fixed
PageFile/PageImagederived a file's identity from its basename only, breaking URL and mime resolution for files stored in subdirectories. Both now carry the full relative filename.Toolkit\Http's cURL header callback measured the trimmed line's length instead of the raw line's, breaking on HTTP/2 status lines.PageFiles::meta()computed acreatedtimestamp fallback even for files that don't exist; now guarded withF::exists().
Changed
Str::slug()now preserves underscores mid-string (still trims both-and_from the ends); the{slug}route token widened to match.App::renderFragment()now merges the page'sappcontroller context into fragment renders, same as full-page renders.- Renamed the
cacheaddon tohttp-purge, to avoid colliding with the newCacheclass. - Item storage sharding simplified from two levels to one (
{2-char-hash}/{uuid}); item creation moved fromRegistryintoFieldTypeCollection::new().