Phase 14c-2: editor pages module on iManager 2.0#24
Merged
Conversation
The /editor/pages admin module is back online — list, create, edit,
save, delete, drag-renumber and Markdown preview, all on the iManager
2.0 stack with Csrf + Sanitizer + Request + Frontend\PageRepository.
Frontend\PageRepository write surface added (still final readonly):
- save(Item) persist via ItemRepository, wrap as Page
- delete(int) idempotent forward
- renumber(list<int>) bulk position rewrite by id-order
- slugTaken(slug, parent) uniqueness preflight, scoped to parent
- nextPosition() helper for new-page position default
New Editor\Pages\PagesModule covers the legacy 612-line
editor/modules/pages/pages.php:
- renderList: sortable table with edit/delete actions, CSRF token
for inline form (renumber + delete links).
- renderEdit: name/menu_title/slug/content/parent/template/published
fields. Image section is read-only for 14c-2 (existing entries
listed; upload widget reattaches in 14d with FilePond +
UploadHandler).
- saveAction: validates name+slug+content, derives slug from name
when omitted, rejects reserved slugs, rejects duplicate slug under
the same parent, preserves existing image data on update; flashes
success and redirects to /pages/edit/?page=N.
- deleteAction: refuses page id=1, refuses pages with children,
flashes success/error and redirects to /pages/.
- renumberAction: AJAX endpoint returning {status:0|1}; CSRF-checked.
- markdownPreviewAction: AJAX endpoint returning {status:1, text:HTML}
rendered via Sanitizer::markdown().
EditorRouter routes /editor/pages* to PagesModule and removes the
"coming soon" placeholder for that slug; auth gating still kicks
anonymous GET/POST to /editor/auth/ before reaching the module.
CSRF: all write paths check tokens via Imanager\Http\Csrf — login
form, edit/save form, delete link, renumber AJAX, markdown preview.
Tokens are scoped per-form-name ("pages" for the module's form).
Manual smoke (PHP built-in server):
GET /editor/pages 200, sortable table, 8 migrated rows
GET /editor/pages/edit/?page=3 200, edit form pre-filled (Get started)
GET /editor/pages/edit/ 200, empty new-page form
POST save (new) 302 → /pages/edit/?page=10 (DB row +1)
POST render-markdown 200 JSON {status:1, text:...}
GET /pages/delete/?page=10&... 302 → /pages/ (DB row gone)
Anonymous GET /editor/pages 302 → /editor/auth/
Anonymous POST /editor/pages 302 → /editor/auth/
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.
Summary
The
/editor/pagesadmin module is back online — list, create, edit,save, delete, drag-renumber and Markdown preview, all on the iManager
2.0 stack with
Csrf+Sanitizer+Request+Frontend\PageRepository.Frontend\PageRepositorywrite surface added (stillfinal readonly):save(Item)— persist via ItemRepository, wrap as Pagedelete(int)— idempotent forwardrenumber(list<int>)— bulk position rewrite by id-orderslugTaken(slug, parent)— uniqueness preflight, scoped to parentnextPosition()— helper for new-page position defaultNew
Editor\Pages\PagesModulecovers the legacy 612-lineeditor/modules/pages/pages.php:for inline form (renumber + delete links).
fields. Image section is read-only for 14c-2 (existing entries
listed; upload widget reattaches in 14d with FilePond + UploadHandler).
when omitted, rejects reserved slugs, rejects duplicate slug under the
same parent, preserves existing image data on update; flashes success
and redirects to
/pages/edit/?page=N.flashes success/error and redirects to
/pages/.{status:0|1}; CSRF-checked.{status:1, text:HTML}rendered via
Sanitizer::markdown().EditorRouterroutes/editor/pages*toPagesModuleand removes the"coming soon" placeholder for that slug; auth gating still kicks anonymous
GET/POST to
/editor/auth/before reaching the module.CSRF: all write paths check tokens via
Imanager\Http\Csrf— loginform, edit/save form, delete link, renumber AJAX, markdown preview.
Tokens are scoped per-form-name (
"pages"for the module's form).Test plan
GET /editor/pages200, sortable table, 8 migrated rowsGET /editor/pages/edit/?page=3200, edit form pre-filledGET /editor/pages/edit/200, empty new-page form{status:1, text:...}GET /pages/delete/?page=10&…302 → /pages/ (DB row gone)GET /editor/pages302 → /editor/auth/POST /editor/pages302 → /editor/auth/