CMS home page: searchable path selector (any CMS/theme/module page) + serve any theme's page at / - #313
Merged
Conversation
…eme/module), + serve any theme's page at / The home page is ANY valid path — a CMS page, a theme page, a module page, a login screen, a dynamic product page the control never sees. So the selector becomes a combobox that ALWAYS accepts a free-typed value, with a discovery service supplying the convenience list it searches. A — the control + discovery - Cms_Service_Paths (/api, admin+): grouped, searchable path discovery. BASIC = the built-in landing, published CMS pages, each installed theme's HOME, and module home prefixes; ADVANCED (a checkbox — the "litterbox") adds every installed theme's individual content page. labelFor() renders a stored value's friendly label (shared with the controller's initial render). - tiger.combobox.js — a reusable, zero-dep "pick OR type" primitive over an /api search service: visible search input + hidden value field, grouped results, keyboard nav, and free-text passthrough (a typed path commits verbatim — "right or wrong", validated on save). House infrastructure, reusable anywhere a field is "one of a set, but may be typed". - Cms_Form_Settings: home_page is now a single validated free value (drops the CUSTOM sentinel + home_page_custom dance); the combobox writes it. Settings service/controller/view updated; the view's inline <script> moved to cms.settings.js (house rule). B — serve any theme's page at / (just a forward) - IndexController resolves a "@theme:<key>[:<slug>]" home value and forwards to the theme-content action. - PageController::themeContentAction honors a theme_content_theme param: it sets that theme active FOR THE REQUEST (Tiger_ThemeDir + themeAssets), so the whole existing render pipeline (dir, assets, layout, skins) resolves to it — no pipeline refactor. Tiger_Theme gains dirForKey/assetBaseForKey/pagesForKey. Proven live on dev: with Puma the default theme, home_page=@theme:grey-mist renders Grey Mist's home at / with its own /_greymist assets, while /login and the rest stay on Puma. Discovery is admin-gated; advanced is a strict superset of basic; the value's shape is validated. Integration test rewritten to the new contract (form shape, discovery ACL/basic/advanced/filter, labelFor). i18n added to en/es/pt/hi/de/fr (tlh is the joke marketing-only locale, intentionally skipped). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ
The home page is any valid path (the combobox fills home_page; the discoverable page list moved to Cms_Service_Paths, covered by HomePageSelectorTest). Assert the value's SHAPE + the required site name instead of the removed getMultiOptions() select. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ
WebTigers
added a commit
that referenced
this pull request
Sep 26, 2026
…pathbox/discovery (#314) * Address PR #313 review (TIGER-232..236): restore TigerCombo, harden the pathbox + discovery Astra (Codex) static review of PR #313. Five P2 findings, all remediated. TIGER-233 (regression I introduced): PR #313 overwrote the shared tiger.combobox.js (TigerCombo — the closed <select> enhancer the admin layout loads globally for the timezone fields on profile + access), reverting them to plain native selects. Restored TigerCombo verbatim; moved the new remote "pick or type" control to its own asset tiger.pathbox.js (TigerPathbox / data-tg-pathbox). Closed-set fields keep their filter-as-you-type; the CMS home field keeps pick-or-type. TIGER-232: the pathbox committed free text only in a delayed blur, so clicking Save fast captured the old value. It now exposes el._tgPathbox.flush() + TigerPathbox.flushAll(scope); cms.settings.js calls flushAll synchronously before building FormData. home_page validation errors now decorate the VISIBLE search input, not the hidden backing field. TIGER-234: every fetch response rendered unconditionally and reopened the panel. Added a per-request generation stamp + open-intent guard: a superseded or post-dismissal/post-selection response is dropped (can't overwrite newer results or reopen a closed control). TIGER-235: Cms_Service_Paths built a Zend_Db_Select and fetched full published-page rows (bodies + meta) per keystroke, then filtered/capped after — against the "query building belongs in a model" rule. Added Tiger_Model_Page::publishedSummaries($q, $limit) (small columns, published+scheduled gate, search + cap in the model); the service calls it, no query builder. Theme HOMES are now emitted for ALL themes before any advanced sub-pages so the per-group cap can't crowd a later theme's home out. One memoised Tiger_Theme::inventory() replaces re-globbing/re-reading manifests per dirForKey/pagesForKey call. TIGER-236: theme discovery (dirForKey et al.) scanned only 2 of the 4 locations Bootstrap::_initTheme resolves from, so a theme in app/themes/<name> or core/modules/theme-<name> was activatable but invisible to the selector and unresolvable by @theme:<key>. inventory() now scans all four in the SAME precedence (app over core), keyed by manifest key. Tests: HomePageSelectorTest unchanged (service contract stable); new PageTest coverage for publishedSummaries (published-only + small columns; query filter + limit). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ * PageTest: softDelete takes a WHERE clause, not a bare id Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The CMS home-page selector was a
<select>of published CMS pages plus a reveal-on-"custom" text box — it couldn't offer a theme page, and it framed the home page as a short menu rather than what it really is: any valid path. This reworks it into a searchable combobox over a path-discovery service, and teaches/to serve any installed theme's page (default theme or not).A — the control + discovery
Cms_Service_Paths(/api, admin+): grouped, searchable path discovery.labelFor()renders a stored value's friendly label (shared with the controller's initial render).tiger.combobox.js— a reusable, zero-dep "pick OR type" primitive over an/apisearch service: visible search input + hidden value field, grouped results, keyboard nav, and free-text passthrough (a typed path commits verbatim — validated on save). House infrastructure, reusable anywhere a field is "one of a set, but may be typed".Cms_Form_Settings:home_pageis now a single validated free value (drops theCUSTOMsentinel +home_page_custom); the combobox writes it. The Settings view's inline<script>moved tocms.settings.js(house rule).B — serve any theme's page at
/(just aforward())IndexControllerresolves a@theme:<key>[:<slug>]home value and forwards to the theme-content action.PageController::themeContentActionhonors atheme_content_themeparam: it sets that theme active for the request (Tiger_ThemeDir+themeAssets), so the whole existing render pipeline (dir, assets, layout, skins) resolves to it — no pipeline refactor.Tiger_ThemegainsdirForKey/assetBaseForKey/pagesForKey.Proven on dev
With Puma the default theme,
home_page = @theme:grey-mistrenders Grey Mist's home at/with its own/_greymistassets (title "Grey Mist", 11 asset refs), while/loginand everything else stay on Puma. Discovery is admin-gated; a guest/user is denied. Advanced is a strict superset of basic. The stored value's shape is validated (rejects unrooted paths, absolute URLs, query strings).Tests
HomePageSelectorTestrewritten to the new contract: thehome_pagevalue shape (accepts''/path/@theme:…/UUID, rejects junk), discovery ACL (guest/user denied, admin clears), module pages from the routing registry with non-page endpoints filtered, the search-term filter, advanced ⊇ basic, andlabelForfor each value shape. i18n added to en/es/pt/hi/de/fr (tlhis the joke marketing-only locale, intentionally skipped).🤖 Generated with Claude Code
https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ