fix: #3620603 Seed the backing page with the node's default full-content layout
Fixes a defect I introduced in the previous MR on this issue. The page-backed fallback 500s on any content type whose ContentTemplate binds to the entity — which is every real template — and it did not carry the default layout over.
Issue: #3620603
The bug
The backing canvas_page was seeded from the node's default ContentTemplate verbatim. A template's props are bound to the entity it renders, and a canvas_page has no node to bind them to, so the save throws:
EntityStorageException: `entity:node:blog[title][value]` is an expression for entity type
`node`, but the provided entity is of type `canvas_page`.On Varbase 11's blog template, 6 props are entity-bound.
Why the previous MR missed it: it was verified on a Drupal CMS site whose page bundle had no ContentTemplate at all, so the seeding branch never ran against a real template, and the sync was proven with a tree hand-copied from another canvas_page — which by definition holds no node-bound expressions. The plumbing was proven; the realistic case was not.
The fix
Overriding must start from the content type's default full-content layout — that is what makes it an override rather than a blank slate. So the layout is carried over in full, with each entity-bound prop evaluated against the node and stored as its value:
$item['inputs'][$prop] = PropSource::parse($value)->evaluate($node, FALSE)->value;A prop that cannot be evaluated is dropped so the component falls back to its own default — losing one prop beats losing the layout, and leaving the expression in place would make the save throw.
Because the layout is now per-node, those values are a snapshot taken at override time rather than live bindings. On the patched path the loader still seeds the node's own field, where the bindings stay live. That difference is documented on the class.
Two alternatives were rejected: seeding nothing (an empty editor defeats the feature), and filtering the bound components out (on this template that leaves 6 of 11, so the editor would open on a layout silently different from the template).
Verified on a fresh Varbase 11.0.x site (Drupal 11.4.6, canvas 1.10.1) through the browser
Unpatched (final class, guard active, fallback path):
| Check | Before this MR | After |
|---|---|---|
| Fallback editor | 500 EntityStorageException |
opens on the default layout: breadcrumb, node title as heading, date, Share block, header and footer |
| Seeded page tree | not reached | 11 items — matches the template's 11 |
entity:node expressions on the page |
not reached | none |
| Page save to node field | not reached | 11 items synced |
| Node renders the layout | not reached | 7,532 bytes |
drush cr |
works | works |
Patched (varbase-patches applied, loader swap active) — unchanged by this MR:
| Check | Result |
|---|---|
| Content type toggle | enabled, no warning |
| First save of the setting | works: field storage and instance both created |
Editor /canvas/editor/node/15 |
loads, template layout renders |
| Reset flow (HTMX + CSRF) | 204 + HX-Redirect |
phpcs: 0 errors.
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