Loading
feat: #3620603 Edit per-content layouts on a backing canvas_page when Canvas is unpatched
Makes per-content Canvas layouts work on a stock, unpatched Canvas, so vardot/varbase-patches is no longer required for this module's feature to function.
Issue: #3620603
Why this works
Measuring first showed the patch was only ever needed for one thing. On an unpatched Canvas 1.10.1:
| Flow | Unpatched |
|---|---|
| Node full-view rendering of the per-entity tree | works - the canvas_naive_render_sdc_tree formatter reads field items and never calls the loader |
ComponentTreeLoader::getCanvasFieldName($node) |
throws LogicException |
ComponentTreeLoader::load($canvas_page) |
works |
Canvas editor on a canvas_page |
loads |
So storage and rendering were already fine. Only the editor needed a patched Canvas.
What it does
Each override-enabled node gets its own canvas_page as the editing surface. Canvas supports that natively, so getCanvasFieldName() is never reached and nothing is subclassed - final stops mattering.
CanvasOverridePageResolvercreates the backing page lazily, seeding it from the node's existing tree or the default ContentTemplate, and maps node to page in a key-value collection (no field, no schema or config change).CanvasRedirectControllersends the Canvas Override tab to the page's editor when the loader is not extendable, and keeps today's direct per-node editor when it is.hook_canvas_page_insert/updatecopies the page's tree onto the node's own field. One direction only, so there is nothing to reconcile, and the render path is untouched.hook_node_deleteremoves the backing page and its mapping.- The content type form gains the stale-container warning that had no reader after the previous MR removed
hook_requirements, soSWAPPED_PARAMETERis live again rather than dead code.
Gated on isComponentTreeLoaderExtendable(), so a patched site keeps its current behaviour and does not regress.
Verified on an unpatched Canvas 1.10.1
| Check | Result |
|---|---|
/node/15/canvas |
redirects to /canvas/editor/canvas_page/7, editor loads |
| Backing page + mapping | page created lazily, mapping {"15": 7} |
| Page save to node field | 27-item tree copied onto field_canvas_layout |
| Node renders the layout | 29,696 bytes with component markup (1,084 when empty) |
cannot extend final in logs |
0 |
Still to look at before merge
- The editor's preview area renders grey on an unpublished backing page. The tree is present and the node renders it, so this looks like preview-of-unpublished rather than missing data, but it is unconfirmed.
- The editor's Page data panel exposes
canvas_pagefields (URL alias, SEO, Open Graph) that do not apply to a node-backed layout; a backing page is not independently routable, so these are worth hiding. - No automated coverage yet for the page-backed path.
AI-Generated: Yes
Checkpoints:
- File an issue
- Addition/Change/Update/Fix
- Testing to ensure no regression
- Automated unit testing coverage
- Automated functional testing coverage
- UX/UI designer responsibilities
- Readability
- Accessibility
- Performance
- Security
- Developer Documentation
- User Guide Documentation
- Reviewed by human
- Code review by maintainers
- Full testing and approval
- Credit contributors
- Review with the product owner
- Release notes snippet
- Release
Edited by Rajab Natshah