v0.0.39

30 June 2026

SSE toolkit, outbound HTTP client, FTS5 full-text search in the registry, page navigation helpers, image dimension metadata, and Api\Client.

Added

  • Sse toolkit class : start() sets SSE headers and disables output buffering; send(event, data, id) emits one event; comment() sends a keep-alive ping; aborted() checks for client disconnect; watch(markerPath, event, intervalMs, keepaliveSecs) polls a marker file for mtime changes and emits an event each time it changes, exiting cleanly when the client disconnects. A page.update:after hook now writes site/storage/events/{uuid}.touch so pages can wire a live route to Sse::watch() without any extra infrastructure.
  • Http toolkit class and HttpResponse : curl-backed outbound HTTP: Http::get/post/put/patch/delete(url, ...). Array bodies are auto-encoded as JSON with Content-Type: application/json. HttpResponse wraps status, headers, and body with ok(), text(), json(), and header(name) accessors.
  • Api\Client : configurable HTTP client backed by Http. Constructed via $app->api(string $name): accepts either a named connector from config.api.connectors (with base_url and optional headers) or an absolute URL for ad-hoc use. Supports get/post/put/patch/delete with fluent header()/headers()/timeout() overrides.
  • Registry schema 6: search_index FTS5 virtual table (uuid UNINDEXED, content). search=words query DSL token : each whitespace-separated word becomes a quoted FTS5 phrase (AND-joined), results sorted by BM25 relevance when no explicit sort= is given.
  • Page::slug() : returns basename($this->url()).
  • Page::next(bool $includeHidden) / Page::prev() : next and previous siblings in parent's child order.
  • Page::contains(Page $other) : true if $other is this page or a descendant.
  • Page::hasChildren(bool $includeHidden) : true if the page has any children.
  • Page::isActive() : true if this page is the current request page.
  • Page::isOpen() : true if this page or any descendant is the current request page (for open nav states).
  • File::$type (PHP 8.4 property hook) : virtual property returning a semantic MIME category string: image, video, audio, document, archive, code, or file.
  • PageImage::width(), height(), ratio(), isLandscape(), isPortrait(), isSquare() : image dimension metadata, lazily resolved via getimagesize().
  • Url::join(string ...$parts) : joins URL path segments, normalising slashes between them, preserving a leading /.
  • F::clearStat(string $path) : wraps clearstatcache(true, $path).
  • phlat/config.json : email and api keys with defaults (smtp://mailpit:1025 and a 30s timeout with an empty connectors map).
  • functions.php : isLoggedIn(), make(string $name), and fieldtypeEditTemplate(string $type) global helpers.

Changed

  • Page::url() now accepts optional $path and $query arguments : $page->url('edit') and $page->url('', ['page' => 2]) produce sub-paths and query strings without manual concatenation. The root page now returns / instead of an empty string.