SlotFlow API Documentation

SlotSpace
in package

FinalYes

Defines the slot space, its dimensions, the slots that exist within it, and the edges and flows that operate on it.

Tags
psalm-type

TDurationResolverClosure = (\Closure(MovementEdge, TimedDurationContext): array-key)

TDimensionName = non-empty-string the name and value of a dimension must be non-empty strings

TDimensionValue = non-empty-string dimension values must be non-empty strings, and each dimension must have at least one value

TSlotKey = non-empty-string the serialized representation of a slot, used as a unique identifier, can be used as a slot pattern that matches exactly one slot

TSlotTuple = list<TDimensionValue> a tuple of dimension values in the order of dimension names, used as an alternative way to specify a slot

TSlotPartial array<TDimensionName, TDimensionValue> a partial associative specification of concrete dimension values; dimensions may be omitted, but provided values are concrete; used as a slot pattern that can match multiple slots

TSlotValues array<TDimensionName, TDimensionValue> a full associative specification of concrete dimension values; all dimensions must be present and all values must be concrete; used as a slot pattern that matches exactly one slot

TDimensionValuePattern ?non-empty-string a null or string pattern to match dimension values. Used in slot patterns. String may contain wildcards as allowed by codec. Null is equivaldent to the match-all wildcard.

TSlotTuplePattern list<TDimensionValuePattern> a tuple of dimension value patterns in the order of dimension names, used as an alternative way to specify a slot pattern.

TSlotArrayPattern array<TDimensionName, TDimensionValuePattern> a pattern specified as an associative array of dimension name to dimension value pattern, where missing or null values are treated as wildcards that match any value for the dimension. Used as a slot pattern that can match multiple slots.

TSlotPattern TSlotTuplePattern|TSlotArrayPattern|TSlotKey|null a slot pattern can be:

  • a string slot pattern (e.g. "sup.*.foo|bar") that is deserialized using the codec
  • an tuple: array value pattern in the exact order and number of dimensions defined in the slot space, where each value can be a specific value or a wildcard (null or wildcard string as defined by codec)
  • an array of dimension name to value patterns where missing or null values are treated as wildcards
  • null, to match the nil slot (for source/sink slots in edges)

TEdgePattern array{from: TSlotPattern, to: TSlotPattern}|array{TSlotPattern, TSlotPattern} a pattern to define an edge between slots, consisting of a from pattern and a to pattern. Can be used in flow step definitions.

Table of Contents

Properties

$codec  : SlotCodec
$flows  : array<non-empty-string, Flow>
$timeAxis  : TimeAxis|null
$dimensionNames  : array<int, TDimensionName>
$dimensions  : array<non-empty-string, array<int, non-empty-string>>
$edgeRuleBase  : EdgeRuleBase
Whether a movement step is limited to the declared edges.
$edgeRulesByOriginSlot  : array<non-empty-string, array<int, EdgeRule>>
Per slot key => the list of rules needed to generate the valid edges from that slot to other slots.
$nilSlot  : Slot
$outgoingEdgeByOriginSlot  : array<non-empty-string, array<non-empty-string, MovementEdge>>
$slotsByKey  : array<non-empty-string, Slot>
$slotsByPattern  : array<non-empty-string, array<int, Slot>>
$subjectKeyResolver  : Closure
$temporal  : TemporalContext
The temporal configuration this space is expanded along.

Methods

__construct()  : mixed
Create one slot space from dimensions and optional time configuration.
confine()  : self
Restrict where one dimension value may occur: `$dimension = $value` is valid only on slots whose `$axis` is one of `$allowed`.
define()  : self
Define one untimed slot space from dimensions.
defineTimed()  : self
Define one timed slot space from dimensions and a time axis.
dimensionNames()  : array<int, non-empty-string>
dimensions()  : array<non-empty-string, array<int, non-empty-string>>
dimensionValues()  : array<int, non-empty-string>
Get the list of all possible valid values for a specific dimension.
edgeRules()  : self
This is used to generate the valid edges between slots, after the valid slots have been determined by the slot rules.
edgesBetween()  : array<string|int, MovementEdge>
Generate edges using pattern expansion Both wildcard and missing values are supported, with the same semantics.
edgesByLabels()  : array<int, MovementEdge>
Return all currently valid edges generated from rules matching any of the given labels.
expandSlotPattern()  : array<int, array<non-empty-string, non-empty-string>|null>
Expand a string or array of Slot pattern into a list of partials.
flow()  : self
Register a named flow definition.
getDispatchCalendar()  : DispatchCalendarInterface|null
Return the configured dispatch calendar, if any.
getDurationResolver()  : TimedDurationResolverInterface|null
Return the configured duration resolver, if any.
getEdgesFrom()  : array<non-empty-string, MovementEdge>
Apply edge rules in sequence to generate a list of edges Cache edge list by slot key at $this->outgoingEdgeByOriginSlot.
getFlow()  : Flow
matchPartial()  : array<int, Slot>
Finds all slots matching the given partial pattern, where the pattern can contain specific values, and '*' can be used as a wildcard expression to match any value for a dimension.
matchPattern()  : array<int, Slot>
Resolve a slot pattern directly to matching slots.
nilSlot()  : Slot
setDispatchCalendar()  : self
Set the dispatch calendar that may delay when timed edges may depart.
setDurationResolver()  : self
Set the resolver used to convert base edges into timed durations.
slot()  : Slot
Finds the slot corresponding to the given key or values. The input can be either a serialized key string or an array of dimension values, which will be serialized using the defined serializer.
slotRules()  : self
This function is to be used after the SlotSpace is constructed and applies provided inclusion/exclusion rules in sequential order, to shape the slot space into a shape meaningful for the application domain.
subjectKey()  : non-empty-string
Resolve one internal subject key using the space's configured resolver.
subjectKeyResolver()  : self
Configure how arbitrary subject values are converted to stable internal keys.
temporal()  : TemporalContext
Return the temporal configuration this space is expanded along.
trySlot()  : Slot|null
Finds the slot corresponding to the given key or values. The input can be either a serialized key string or an array of dimension values, which will be serialized using the defined serializer.
validateKnownDimensionNames()  : void
cartesian()  : array<int, array<non-empty-string, non-empty-string>>
Generate the cartesian product of the given dimensions, where the input is an array of dimension name to list of values, and the output is a list of all combinations of dimension values, where each combination is represented as an array of dimension name to value.
defaultSubjectKey()  : string

Properties

$dimensionNames

private array<int, TDimensionName> $dimensionNames = []

$dimensions

private array<non-empty-string, array<int, non-empty-string>> $dimensions = []
Tags
psalm-var

array<TDimensionName, list<TDimensionValue>>

$edgeRuleBase

Whether a movement step is limited to the declared edges.

private EdgeRuleBase $edgeRuleBase = \Nandan108\SlotFlow\Rules\EdgeRuleBase::All

Tightening is one-way: once a caller has stated EdgeRuleBase::None, a later edgeRules() call that does not repeat it cannot reopen the topology. A rule list assembled from several independent contributors is exactly the case this enum exists for, and a contributor appending rules under the default must not silently un-enforce what another one declared.

$edgeRulesByOriginSlot

Per slot key => the list of rules needed to generate the valid edges from that slot to other slots.

private array<non-empty-string, array<int, EdgeRule>> $edgeRulesByOriginSlot = []
Tags
psalm-var

array<TSlotKey, list<EdgeRule>>

$outgoingEdgeByOriginSlot

private array<non-empty-string, array<non-empty-string, MovementEdge>> $outgoingEdgeByOriginSlot = []
Tags
psalm-var

array<TSlotKey, array<TSlotKey, MovementEdge>>

$slotsByKey

private array<non-empty-string, Slot> $slotsByKey = []
Tags
psalm-var

array<TSlotKey, Slot>

$slotsByPattern

private array<non-empty-string, array<int, Slot>> $slotsByPattern = []

$subjectKeyResolver

private Closure $subjectKeyResolver

$temporal

The temporal configuration this space is expanded along.

private TemporalContext $temporal

An untimed space still carries one, with every member null, so consumers never branch on a null context before asking it a question. It is the space's single temporal dependency: everything the timed layer needs from a space is reachable through it, and the normalization of raw callables lives there rather than once per consumer.

Methods

__construct()

Create one slot space from dimensions and optional time configuration.

public __construct(array<non-empty-string, array<int, non-empty-string>> $dimensions[, TimeAxis|null $timeAxis = null ][, TimedDurationResolverInterface|Closure|null $durationResolver = null ][, SlotCodec>|null $codecClass = null ]) : mixed
Parameters
$dimensions : array<non-empty-string, array<int, non-empty-string>>
$timeAxis : TimeAxis|null = null
$durationResolver : TimedDurationResolverInterface|Closure|null = null
$codecClass : SlotCodec>|null = null
Tags
psalm-param

array<TDimensionName, list<TDimensionValue>> $dimensions

confine()

Restrict where one dimension value may occur: `$dimension = $value` is valid only on slots whose `$axis` is one of `$allowed`.

public confine(non-empty-string $dimension, non-empty-string $value, non-empty-string $axis, array<int, non-empty-string> $allowed) : self

A constraint, not a sequence step, and that is the entire difference from slotRules(). It cannot depend on ordering, because it never widens: it removes the slots carrying $value whose $axis falls outside $allowed, and touches nothing else. Two confinements over different values cannot interact; two over the same value intersect, which is the only honest reading of "both of these must hold".

That makes it the right primitive wherever the space is assembled from independent sources. A rule sequence there needs every author to agree on a base and an order; a confinement needs neither, and structurally cannot empty the space — the worst a wrong one does is remove the slots for its own value.

// "pending" means in the inbound leg, so it cannot exist on premise
$space->confine('stt', 'pnd', 'loc', ['sup', 'trs/inb']);

Both dimensions must exist and $value must be one this space declares — a confinement over a value nothing can hold is a typo whose only symptom would be its silence.

Parameters
$dimension : non-empty-string

the dimension owning the constrained value

$value : non-empty-string

the value whose placement is constrained

$axis : non-empty-string

the dimension the constraint reads

$allowed : array<int, non-empty-string>

the only $axis values $value may co-occur with; empty means the value can occur nowhere at all, which is refused rather than silently emptying it

Tags
throws
SlotFlowInvalidArgumentException

if a dimension or value is unknown, or $allowed is empty

Return values
self

define()

Define one untimed slot space from dimensions.

public static define(array<non-empty-string, array<int, non-empty-string>> $dimensions[, SlotCodec>|null $codecClass = null ]) : self
Parameters
$dimensions : array<non-empty-string, array<int, non-empty-string>>
$codecClass : SlotCodec>|null = null
Tags
psalm-param

array<TDimensionName, list<TDimensionValue>> $dimensions

Return values
self

defineTimed()

Define one timed slot space from dimensions and a time axis.

public static defineTimed(array<non-empty-string, array<int, non-empty-string>> $dimensions, TimeAxis $timeAxis[, TimedDurationResolverInterface|Closure|null $durationResolver = null ][, SlotCodec>|null $codecClass = null ]) : self
Parameters
$dimensions : array<non-empty-string, array<int, non-empty-string>>
$timeAxis : TimeAxis
$durationResolver : TimedDurationResolverInterface|Closure|null = null
$codecClass : SlotCodec>|null = null
Tags
psalm-param

array<TDimensionName, list<TDimensionValue>> $dimensions

Return values
self

dimensionNames()

public dimensionNames() : array<int, non-empty-string>
Tags
psalm-return

list<TDimensionName>

Return values
array<int, non-empty-string>

dimensions()

public dimensions() : array<non-empty-string, array<int, non-empty-string>>
APIYes
Tags
psalm-return

array<TDimensionName, list<TDimensionValue>>

Return values
array<non-empty-string, array<int, non-empty-string>>

dimensionValues()

Get the list of all possible valid values for a specific dimension.

public dimensionValues(non-empty-string $dimension) : array<int, non-empty-string>
Parameters
$dimension : non-empty-string
Tags
psalm-param

TDimensionName $dimension

psalm-return

list<TDimensionValue>

Return values
array<int, non-empty-string>

edgeRules()

This is used to generate the valid edges between slots, after the valid slots have been determined by the slot rules.

public edgeRules(RuleSet<string|int, EdgeRule>|array<int, EdgeRule|RuleSet<string|int, EdgeRule>> $rules[, EdgeRuleBase $base = EdgeRuleBase::All ]) : self

The starting point is always an empty set of edges, and the rules are applied sequentially to add edges between slots matching the from and to patterns.

Edge rules are stored at origin slot level, to be lazily evaluated into actual edges when needed.

Whether the declared graph constrains movement is stated by $base, not inferred from the presence of rules — see EdgeRuleBase. Under the default the rules label, annotate and deny without limiting what a move() may traverse, which is what a space declaring no topology has always meant; under EdgeRuleBase::None the declared graph is authoritative and a step over an undeclared pair finds no edge.

Parameters
$rules : RuleSet<string|int, EdgeRule>|array<int, EdgeRule|RuleSet<string|int, EdgeRule>>
$base : EdgeRuleBase = EdgeRuleBase::All

whether movement is limited to the declared edges; tightening is one-way

Return values
self

edgesBetween()

Generate edges using pattern expansion Both wildcard and missing values are supported, with the same semantics.

public edgesBetween(non-empty-string|array<non-empty-string, string|null>|null $fromPattern, non-empty-string|array<non-empty-string, string|null>|null $toPattern) : array<string|int, MovementEdge>
Parameters
$fromPattern : non-empty-string|array<non-empty-string, string|null>|null

Specified values match with equality, wildcard/missing match with anything

$toPattern : non-empty-string|array<non-empty-string, string|null>|null

Specified values are kept, wildcard/missing are filled in from the $fromPattern match

Tags
psalm-param

TSlotPattern $fromPattern Specified values match with equality, wildcard/missing match with anything

TSlotPattern $toPattern Specified values are kept, wildcard/missing are filled in from the $fromPattern match

Under EdgeRuleBase::None the pairs the patterns express are intersected with the declared graph, and the declared edge is returned rather than a freshly built one — so a movement step sees the label and metadata its edge rule carries, exactly as a labeled step does. Boundary movements into or out of the nil slot are never constrained.

Return values
array<string|int, MovementEdge>

edgesByLabels()

Return all currently valid edges generated from rules matching any of the given labels.

public edgesByLabels(array<int, non-empty-string> $labels) : array<int, MovementEdge>
Parameters
$labels : array<int, non-empty-string>
Return values
array<int, MovementEdge>

expandSlotPattern()

Expand a string or array of Slot pattern into a list of partials.

public expandSlotPattern(string|array<non-empty-string, string|null>|null $pattern) : array<int, array<non-empty-string, non-empty-string>|null>
Parameters
$pattern : string|array<non-empty-string, string|null>|null
Tags
psalm-param

TSlotPattern $pattern

psalm-return

list<TSlotPartial>|array{null}

throws
SlotFlowInvalidArgumentException

if the pattern is invalid or contains unknown dimensions or values

Return values
array<int, array<non-empty-string, non-empty-string>|null>

flow()

Register a named flow definition.

public flow(non-empty-string $name, callable(Flow): mixed|array<int, array{0?: array|string|null, 1?: array|string|null, from?: array|string|null, to?: array|string|null}> $builder) : self
Parameters
$name : non-empty-string
$builder : callable(Flow): mixed|array<int, array{0?: array|string|null, 1?: array|string|null, from?: array|string|null, to?: array|string|null}>
Tags
psalm-param

\Closure(Flow):mixed|list<TEdgePattern> $builder

Return values
self

getEdgesFrom()

Apply edge rules in sequence to generate a list of edges Cache edge list by slot key at $this->outgoingEdgeByOriginSlot.

public getEdgesFrom(Slot $from) : array<non-empty-string, MovementEdge>
Parameters
$from : Slot
Tags
psalm-return

array<TSlotKey, MovementEdge>

Return values
array<non-empty-string, MovementEdge>

getFlow()

public getFlow(string $name) : Flow
Parameters
$name : string
Return values
Flow

matchPartial()

Finds all slots matching the given partial pattern, where the pattern can contain specific values, and '*' can be used as a wildcard expression to match any value for a dimension.

public matchPartial(array<non-empty-string, string|null> $partial) : array<int, Slot>

The pattern can be either a serialized key string or an array of dimension values, where missing or null values are treated as '*' wildcards.

Parameters
$partial : array<non-empty-string, string|null>
Tags
psalm-param

array<TDimensionName, TDimensionValuePattern> $partial

Return values
array<int, Slot>

matchPattern()

Resolve a slot pattern directly to matching slots.

public matchPattern(array<string|int, mixed>|string|null $pattern) : array<int, Slot>

Exact string keys are short-circuited through the slot registry. General string patterns are cached after expansion so repeated lookups can reuse the resolved slot list without re-running pattern deserialization and matching.

Parameters
$pattern : array<string|int, mixed>|string|null
Tags
psalm-param

TSlotPattern $pattern

Return values
array<int, Slot>

setDurationResolver()

Set the resolver used to convert base edges into timed durations.

public setDurationResolver(mixed $durationResolver) : self
Parameters
$durationResolver : mixed
Tags
psalm-param

TimedDurationResolverInterface|TDurationResolverClosure|null $durationResolver

Return values
self

slot()

Finds the slot corresponding to the given key or values. The input can be either a serialized key string or an array of dimension values, which will be serialized using the defined serializer.

public slot(Slot|string|array<string|int, string>|null $keyOrValues) : Slot

All dimensions must be specified in the input, and wildcards are not allowed.

Parameters
$keyOrValues : Slot|string|array<string|int, string>|null
Tags
see
SlotPattern::from

for more flexible pattern matching with support for wildcards and missing values.

psalm-param

Slot|TSlotPattern $keyOrValues

throws
SlotFlowInvalidArgumentException

if the resulting key does not correspond to any defined slot

Return values
Slot

slotRules()

This function is to be used after the SlotSpace is constructed and applies provided inclusion/exclusion rules in sequential order, to shape the slot space into a shape meaningful for the application domain.

public slotRules(RuleSet<string|int, SlotRule>|array<int, SlotRule|RuleSet<string|int, SlotRule>> $rules[, SlotRuleBase $base = SlotRuleBase::All ]) : self

A "full slot space" is defined by the cartesian product of all dimensions and their values, and contains all possible combinations of dimension values. Inclusion rules add matching slots to the valid set, while exclusion rules remove remove them.

Since the rules are applied sequentially, later rules may override earlier ones.

The starting set is stated, not inferred — see SlotRuleBase. An exclusion-led sequence keeps its historical meaning under the SlotRuleBase::All default; an inclusion-led one now has to say SlotRuleBase::None, which is the whole point: that spelling is the one where a mistake yields an empty space rather than a wrong one.

Ordering still matters between rules, but only among inclusions. With the base fixed, an exclusion narrows wherever it sits in the sequence — which is what makes a rule list safe to assemble from several independent contributors. For a constraint that must not depend on ordering at all, use confine().

Parameters
$rules : RuleSet<string|int, SlotRule>|array<int, SlotRule|RuleSet<string|int, SlotRule>>

patterns to include or exclude. An empty list leaves the space untouched, whatever the base — "no opinion", not "exclude all".

$base : SlotRuleBase = SlotRuleBase::All

the set the sequence starts from

Tags
throws
SlotFlowInvalidArgumentException

if a pattern names a dimension this space does not have

Return values
self

subjectKey()

Resolve one internal subject key using the space's configured resolver.

public subjectKey(mixed $subject) : non-empty-string
Parameters
$subject : mixed
Return values
non-empty-string

subjectKeyResolver()

Configure how arbitrary subject values are converted to stable internal keys.

public subjectKeyResolver(callable(mixed): string $resolver) : self
Parameters
$resolver : callable(mixed): string
Return values
self

trySlot()

Finds the slot corresponding to the given key or values. The input can be either a serialized key string or an array of dimension values, which will be serialized using the defined serializer.

public trySlot(Slot|string|array<string|int, string>|null $keyOrValues[, bool $throwOnInvalidDimensionValues = false ]) : Slot|null

All dimensions must be specified in the input, and wildcards are not allowed.

Parameters
$keyOrValues : Slot|string|array<string|int, string>|null
$throwOnInvalidDimensionValues : bool = false
Tags
see
SlotPattern::from

for more flexible pattern matching with support for wildcards and missing values.

psalm-param

Slot|TSlotPattern $keyOrValues

Return values
Slot|null

Returns the SlotKey if found, or null if no matching slot exists

validateKnownDimensionNames()

public validateKnownDimensionNames(array<string|int, mixed> $names) : void
Parameters
$names : array<string|int, mixed>

list of dimension names that must all exist in the slot space

Tags
psalm-param

array $names

throws
SlotFlowInvalidArgumentException

cartesian()

Generate the cartesian product of the given dimensions, where the input is an array of dimension name to list of values, and the output is a list of all combinations of dimension values, where each combination is represented as an array of dimension name to value.

private cartesian(array<non-empty-string, array<int, non-empty-string>> $dimensions) : array<int, array<non-empty-string, non-empty-string>>

Dimensions with empty value lists are ignored.

Parameters
$dimensions : array<non-empty-string, array<int, non-empty-string>>
Return values
array<int, array<non-empty-string, non-empty-string>>

defaultSubjectKey()

private defaultSubjectKey(mixed $subject) : string
Parameters
$subject : mixed
Return values
string
On this page

Search results