Skip to content
docsv0.25.1

CompositeComponentRegistry

One {@see ComponentRegistryInterface} over ordered, LABELLED layers — the host's own components, then each plugin's — so ONE live endpoint serves every plugin's components and a cross-component effect resolves across them (greenhouse decisions/0211). Resolution is first-layer-wins, but shadowing is never silent: at construction every name that appears in two layers is checked, and a name bound to DIFFERENT definitions (a different class, or a different instance of a class that carries state) throws {@see ComponentNameConflictException} naming the component and both layers. The same instance registered in two layers is fine, and so are two instances of a STATELESS class (no instance property at all) — with nothing to differ in, they are one definition. The check is identity or statelessness, never a structural compare: two instances of a stateful class are a conflict even when their state would compare equal (a deep `==` over a component that holds a collaborator pointing back at it is a fatal, not a verdict). The shipped components hold a dispatcher, so two `new TextareaComponent()` under one name in two layers ARE a conflict: a plugin reuses the host's instance or names its own component. Conflict detection and {@see names()} cover the layers that implement {@see ListsComponents}; an opaque layer still resolves but cannot be enumerated, so it takes no part in either. Writes go to the one layer named writable (a plugin registering late, a host adopting a section); with no writable layer the composite is read-only and {@see register()} throws.

CompositeComponentRegistry::__construct()

public function __construct(array $layers, ?string $writable = null):

Parameters

Parameters of __construct()
NameTypeDescription
$layersarray<string, ComponentRegistryInterface>label => registry, in resolution order (first wins)
$writable(string | null)the label of the layer {@see register()} writes to, or null for a read-only composite

Throws

\InvalidArgumentException if there are no layers, or `$writable` names no layer

ComponentNameConflictException if two layers bind one name to different definitions

CompositeComponentRegistry::has()

public function has(string $name): bool

True when any layer has a component under `$name`.

Parameters

Parameters of has()
NameTypeDescription
$namestring

CompositeComponentRegistry::get()

public function get(string $name): Milpa\Live\Contracts\Component\ComponentDefinitionInterface

The component under `$name` from the first layer that has it.

Parameters

Parameters of get()
NameTypeDescription
$namestring

Throws

\RuntimeException If no layer has a component under `$name`.

CompositeComponentRegistry::register()

public function register(string $name, Milpa\Live\Contracts\Component\ComponentDefinitionInterface $component): void

Registers `$component` in the writable layer.

Parameters

Parameters of register()
NameTypeDescription
$namestring
$componentMilpa\Live\Contracts\Component\ComponentDefinitionInterface

Throws

\LogicException if the composite has no writable layer

ComponentNameConflictException if another layer already binds `$name` to a different definition

CompositeComponentRegistry::names()

public function names(): array

The union of every listing layer's names, in layer order then registration order, each name once.

CompositeComponentRegistry::labels()

public function labels(): array

The layer labels, in resolution order.