To do after:

Problem/Motivation

Child 5 of #3624396: Plan: Harden InstanceInterface, IslandInterface and DisplayBuildableInterface as public API before RC1. Islands are what contrib extends most, so their API has to be right before RC1.

  • An island calls the instance a builder: build(InstanceInterface $builder), buildContent(), getHtmlId(string $builder_id), and the protected $builder and $builderId of IslandPluginBase. The 11 on*() methods of the same island say $instance, as does the rest of the API. The builder is the editing UI, as in getBuilderUrl(). The instance is the entity.
  • keyboardShortcuts() is a static method, called on the class, so an island cannot answer from its configuration. Its docblock promises a map of keys to descriptions.
  • type is optional on #[Island], while an island without a type does not work.
  • afterBuild() is declared twice, on IslandInterface and on IslandWithFormInterface. reloadWithNodeData() has no caller.
  • ThirdPartySettingsInterface has the short name of core's config entity interface, for a single getSummary() method.
  • Docblocks: the on*() methods call $instance an ID, and IslandInterface does not say how to extend it.

Proposed resolution

  • $builder becomes $instance and $builderId becomes $instanceId: the protected properties of IslandPluginBase, and the arguments of build(), buildContent() and getHtmlId(), in every island. Renamed outright before RC1, with a change record, as every API change up to beta9. No contrib island is known, and display_builder_ai and the dev tools change in lockstep, requiring the release that renames.
  • The other protected members contrib uses stay as they are: $nodeId, $data, the promoted services, buildButton() and reloadWithLocalData(). Child 9 lists them as supported.
  • getKeyboardShortcuts(): array on the interface replaces the static keyboardShortcuts(), which is removed. The base default returns no shortcut, the islands that declare one override it, and ProfileViewBuilder calls it. Its docblock gives the shape it really returns.
  • type required on #[Island]. Every island passes named arguments, so moving it after label breaks none of them. Fallback: keep the default, and throw from the plugin manager for an island without a type.
  • afterBuild() leaves IslandWithFormInterface, and stays on IslandInterface. reloadWithNodeData(), which has no caller, is removed.
  • ThirdPartySettingsInterface renamed outright.
  • Docblocks of IslandInterface and the on*() methods. docs/island-plugins.md drops the promise that build() may return NULL.

Remaining tasks

  • Name the replacement of ThirdPartySettingsInterface.
  • Update display_builder_ai and the dev tools, and raise their constraint on drupal/display_builder.
  • Write the change record.

User interface changes

None.

API changes

  • IslandPluginBase::$builder and $builderId renamed to $instance and $instanceId. Arguments renamed in build(), buildContent() and getHtmlId().
  • New IslandInterface::getKeyboardShortcuts(). keyboardShortcuts() removed.
  • type required on #[Island].
  • reloadWithNodeData() removed. ThirdPartySettingsInterface renamed.

Data model changes

None.

Comments

mogtofu33 created an issue. See original summary.

mogtofu33’s picture

Issue summary: View changes
mogtofu33’s picture

Issue summary: View changes
mogtofu33’s picture

Status: Active » Needs work
pdureau’s picture

beta9 has been released. Changing the tag.

pdureau’s picture

$builder becomes $instance and $builderId becomes $instanceId: the protected properties of IslandPluginBase, and the arguments of build(), buildContent() and getHtmlId(), in every island. Renamed outright before RC1, with a change record, as every API change up to beta9. No contrib island is known, and display_builder_ai and the dev tools change in lockstep, requiring the release that renames.

It is the good time to do such a change, which is a leftover of the big instance/node/builder confusion of summer 2025. I don't see how it breaks compatibility thoughts:

  • Those parameters are positioned, and not used as named arguments
  • The positions stay the same, only the name change
  • Then, their use is internal to each method

👌 It worth to check.

The other protected members contrib uses stay as they are: $nodeId, $data, the promoted services, buildButton() and reloadWithLocalData(). Child 9 lists them as supported.

👌 OK, let's not change too much so close to 1.0.0

getKeyboardShortcuts(): array on the interface replaces the static keyboardShortcuts(), which is removed. The base default returns no shortcut, the islands that declare one override it, and ProfileViewBuilder calls it. Its docblock gives the shape it really returns.

👌OK, let's do this.

type required on #[Island]. Every island passes named arguments, so moving it after label breaks none of them. Fallback: keep the default, and throw from the plugin manager for an island without a type.

👌OK, let's do this.

afterBuild() leaves IslandWithFormInterface, and stays on IslandInterface. reloadWithNodeData(), which has no caller, is removed.

👌OK, let's do this.

ThirdPartySettingsInterface renamed outright.

⚠️ Why? It was named like the Core interface for familiarity reason. It has only one method but it is expected to host more. Third party settings will be the most movable part of the API, we have only scratched the surface with our curent panels.

Docblocks of IslandInterface and the on*() methods. docs/island-plugins.md drops the promise that build() may return NULL.

⚠️ We need a way of making the distinction between:

  • an island not reacting to an event ("I pass"): it was the purpose of NULL
  • one emptying its renderable as a reaction to an event: it was the purpose of an empty array

Maybe it is not properly documented, or not properly implemented, and I would advise to address such topic in a dedicated ticket.

pdureau’s picture

I would like to give a try, but I see it is "Needs work". Do you already have something local ?