task: #3567225 Make the component tree loader extensible

Refs #3567225

Summary

Removes final from ComponentTreeLoader and widens its two promoted constructor properties to protected, so a contrib module can subclass it and swap the service.

That is the whole change: one file, one hunk.

Why this merge request shrank

It previously carried the full per-node Content Template override feature across 11 files. That has been reverted here, leaving only the extension point, for two reasons.

The extension point is the part with a caller waiting on it. Canvas Override subclasses ComponentTreeLoader in its service provider. Against stock Drupal Canvas 1.10.0 that is a hard PHP fatal:

Fatal error: Class Drupal\canvas_override\Storage\CanvasOverrideComponentTreeLoader
cannot extend final class Drupal\canvas\Storage\ComponentTreeLoader

The editor never boots: /canvas/api/v0/layout/node/{nid} returns the fatal instead of JSON. Verified on Drupal 11.4.5 with Drupal Canvas 1.10.0. With this one hunk applied, the same request returns HTTP 200 JSON and the editor renders with no console errors.

The five TypeScript files could not work as shipped. canvas.libraries.yml loads the prebuilt ui/dist/assets/index.js, and Drupal Canvas ships that bundle prebuilt, so changing ui/src has no runtime effect until the bundle is rebuilt. Confirmed by inspection: the shipped bundle contains no occurrence of hidePageDataPanel; after a local npm run build it does. Any site consuming this as a Composer patch gets the shipped bundle back on every composer install.

Keeping those files here also meant re-rolling an 11-file patch on every Drupal Canvas release, for changes that were inert.

What was removed

ApiLayoutController, JsonSchemaPropsComponentSourceBase, TypedDataHelper, CanvasConfigUpdater, DrupalSettings.ts, ContextualPanel.tsx, Topbar.tsx, ComponentInstanceForm.tsx, UndoRedo.tsx, layoutModelSlice.ts.

The per-node Content Template override feature still needs its own issue and merge request. Two of the reverted changes are unrelated fixes that deserve separate issues rather than riding along with a feature: the null guard in ComponentInstanceForm.tsx, and layoutModelSlice.ts using the active editor frame context instead of a hardcoded 'template'.

Testing

  • composer run lint and npm run lint pass.
  • Install a module that subclasses ComponentTreeLoader and swaps the service; confirm no fatal.
  • Confirm ComponentTreeLoader behaviour is unchanged for Drupal Canvas itself: the class is still concrete, only the final marker and two property visibilities changed.

AI usage disclosure

Per the Drupal AI contribution policy: AI (Claude Code) assisted with identifying the minimal required change, reverting the unrelated files, and verifying the result on a live site. All changes were reviewed and verified by the human contributor (Rajab Natshah), who is responsible for the logic, security, and licensing.

Edited by Rajab Natshah

Merge request reports

Loading