ParameterFieldsTrait
Builds the "Parameters" section of the product set edit form (tab "Set").
Each parameterRows multiplier row holds a parameter picker (suggest over root parameters); its typed
parameter_X field from ParameterFieldBuilder is rendered inline and appears via AJAX after
the pick (parametersRefresh submit, snippet redraw).
The active set (parameters whose fields are built) comes from the submitted
parameterRows[*][parameterId] on POST and from editedSet.parameterRels on GET. The template finds
each field by the row's parameterId.
Saving replaces the ProductSet::$parameterRels collection fully (orphan removal), even when empty:
the submitted rows are the whole truth. The surrogate PK keeps multi-value types from colliding.
IMPORTANT: the host must receive parameterManager and parameterGroupManager through its constructor;
#[Inject] is not filled on components, so the properties would stay uninitialized (see
ProductSetEdit). The host must also
register 'parameterId' => $this->parameterRowPicker() in pickers().
Table of Contents
Properties
- $fieldBuilder : ParameterFieldBuilder|null
- $parameterFormItems : array<string|int, ParameterFormItem>
- $parameterFormPrepared : bool
Methods
- parameterRowPicker() : PickerConfig
- Returns the picker config for a multiplier row: suggest over root parameters (excluding the already picked) plus a modal on `:Admin:Eshop:Parameter`.
- addParameterRowFields() : void
- Adds the `parameterRows` multiplier: hidden `parameterId` (filled by the picker) and text `parameterName` (label that survives AJAX).
- applyProductSetParameterRels() : void
- Replaces `parameterRels` fully; `parameter` is a thin id reference that the Api hydrator resolves as a managed entity.
- buildEshopCurrencyItems() : array<int, string>
- buildEshopParameterContext() : ParameterFormContext
- buildParameterRowDefaults() : array<int, array{parameterId: int, parameterName: string}>
- Returns the prefilled rows: one row per distinct parameter with a value in the edited set (a multi-value parameter is one row).
- buildProductSetParameterRows() : array<int, array{id: int, value: string, value2?: string}>
- Converts the submitted values to flat id/value/value2 rows via {@see ParameterFieldBuilder::extractValues()}.
- extractSubmittedParameterIds() : array<int, int>
- Returns the deduplicated positive IDs from the submitted `parameterRows[*][parameterId]`; non-row multiplier keys are skipped.
- getFieldBuilder() : ParameterFieldBuilder
- getProductSetParameterValues() : array<int, mixed>
- Returns the prefill values (`parameterRels`) shaped by parameter type.
- loadEshopParameterGroups() : array<string|int, ParameterGroupInterface>
- loadEshopParameters() : array<string|int, ParameterFormItem>
- Loads the active root parameters for the given IDs, without rule graphs.
- parameterDisplayName() : string
- prepareParameterForm() : void
- Loads the active parameters (by multiplier rows or the edited set), their groups and the context, and initializes the builder.
- resolveActiveParameterIds() : array<int, int>
- Returns the IDs of parameters whose typed field is built.
- resolveDuplicateParameters() : array<int, Parameter>
- Returns parameters for prefilling a new variant opened in a duplicate context (`$duplicateFromSetId`).
- resolveEditedSetParameters() : array<int, Parameter>
- Returns the distinct parameters of a set (by `parameterRels`) sorted by `lft`, so the row order is stable.
- resolveParameterLabel() : string|null
- resolveProductCategoryParameters() : array<int, Parameter>
- Returns parameters for prefilling a new variant: the Api bridge `parameters-for-product` aggregates over all product categories (distinct, ordered by minimum `order`).
- suggestParameters() : array<int, array{id: int, label: string}>
- Suggests root parameters by name, skipping the already picked ones on POST: the typed `parameter_X` field exists once per parameter.
Properties
$fieldBuilder
private
ParameterFieldBuilder|null
$fieldBuilder
= null
$parameterFormItems
private
array<string|int, ParameterFormItem>
$parameterFormItems
= []
$parameterFormPrepared
private
bool
$parameterFormPrepared
= false
Methods
parameterRowPicker()
Returns the picker config for a multiplier row: suggest over root parameters (excluding the already picked) plus a modal on `:Admin:Eshop:Parameter`.
protected
parameterRowPicker() : PickerConfig
Picking a parameter clicks parametersRefresh to render its typed field.
Return values
PickerConfigaddParameterRowFields()
Adds the `parameterRows` multiplier: hidden `parameterId` (filled by the picker) and text `parameterName` (label that survives AJAX).
private
addParameterRowFields(Form $form) : void
The typed value field is not part of the row; the template renders the builder's parameter_X inline.
Parameters
- $form : Form
applyProductSetParameterRels()
Replaces `parameterRels` fully; `parameter` is a thin id reference that the Api hydrator resolves as a managed entity.
private
applyProductSetParameterRels(ProductSet $set, array<int, array{id: int, value: string, value2?: string}> $rows) : void
Always called, even with empty $rows (remove all): the submitted rows are the whole
truth, unlike Bazaar where parameters outside the chosen category are absent from the form.
The identity of rows is carried over: a new rel takes the id of a stored rel of the same
parameter, preferring one with the same value, so a changed value is an update, not delete
plus insert. The hydrator pairs owned children by id
(OrmEntityHydrator), so an unchanged save leaves
product_set_parameter_rel untouched; unused old rels are removed by orphan removal.
Parameters
- $set : ProductSet
- $rows : array<int, array{id: int, value: string, value2?: string}>
buildEshopCurrencyItems()
private
buildEshopCurrencyItems() : array<int, string>
Return values
array<int, string>buildEshopParameterContext()
private
buildEshopParameterContext(array<string|int, ParameterFormItem> $items) : ParameterFormContext
Parameters
- $items : array<string|int, ParameterFormItem>
Return values
ParameterFormContextbuildParameterRowDefaults()
Returns the prefilled rows: one row per distinct parameter with a value in the edited set (a multi-value parameter is one row).
private
buildParameterRowDefaults() : array<int, array{parameterId: int, parameterName: string}>
Without an edited set, the rows come from resolveDuplicateParameters().
Return values
array<int, array{parameterId: int, parameterName: string}>buildProductSetParameterRows()
Converts the submitted values to flat id/value/value2 rows via {@see ParameterFieldBuilder::extractValues()}.
private
buildProductSetParameterRows(ArrayHash<string|int, mixed> $values) : array<int, array{id: int, value: string, value2?: string}>
Parameters
- $values : ArrayHash<string|int, mixed>
Return values
array<int, array{id: int, value: string, value2?: string}>extractSubmittedParameterIds()
Returns the deduplicated positive IDs from the submitted `parameterRows[*][parameterId]`; non-row multiplier keys are skipped.
private
extractSubmittedParameterIds() : array<int, int>
Return values
array<int, int>getFieldBuilder()
private
getFieldBuilder() : ParameterFieldBuilder
Return values
ParameterFieldBuildergetProductSetParameterValues()
Returns the prefill values (`parameterRels`) shaped by parameter type.
private
getProductSetParameterValues() : array<int, mixed>
Uses the edited set, otherwise the duplicate source set (same priority as resolveDuplicateParameters()); category-seeded parameters carry no values.
Return values
array<int, mixed>loadEshopParameterGroups()
private
loadEshopParameterGroups(array<string|int, ParameterFormItem> $items) : array<string|int, ParameterGroupInterface>
Parameters
- $items : array<string|int, ParameterFormItem>
Return values
array<string|int, ParameterGroupInterface>loadEshopParameters()
Loads the active root parameters for the given IDs, without rule graphs.
private
loadEshopParameters(array<int, int> $ids) : array<string|int, ParameterFormItem>
IMPORTANT: rules (dependent selects) are never applied in the eshop: the admin controls the
set's parameter list fully and the front end always shows all choices. optionsCollection
stays because it holds select choices, not rules. The required flag of a parameter applies to the
parameters the admin put on the set.
Parameters
- $ids : array<int, int>
Return values
array<string|int, ParameterFormItem>parameterDisplayName()
private
parameterDisplayName(Parameter $parameter) : string
Parameters
- $parameter : Parameter
Return values
stringprepareParameterForm()
Loads the active parameters (by multiplier rows or the edited set), their groups and the context, and initializes the builder.
private
prepareParameterForm() : void
Idempotent.
resolveActiveParameterIds()
Returns the IDs of parameters whose typed field is built.
private
resolveActiveParameterIds() : array<int, int>
On GET: the edited set's parameters with a value, otherwise resolveDuplicateParameters(). On POST: the submitted multiplier rows, which always win over the seed. Bundle mode and standalone add prefill nothing.
Return values
array<int, int>resolveDuplicateParameters()
Returns parameters for prefilling a new variant opened in a duplicate context (`$duplicateFromSetId`).
private
resolveDuplicateParameters() : array<int, Parameter>
The distinct parameters of the source set win over the category prefill from resolveProductCategoryParameters(); without a source set it falls back to the category prefill.
Return values
array<int, Parameter>resolveEditedSetParameters()
Returns the distinct parameters of a set (by `parameterRels`) sorted by `lft`, so the row order is stable.
private
resolveEditedSetParameters([ProductSet|null $set = null ]) : array<int, Parameter>
Parameters come from the rels and carry translations (includes parameterRels.parameter).
$set defaults to $this->editedSet; resolveDuplicateParameters() passes the
duplicate source set.
Parameters
- $set : ProductSet|null = null
Return values
array<int, Parameter>resolveParameterLabel()
private
resolveParameterLabel(int $id) : string|null
Parameters
- $id : int
Return values
string|nullresolveProductCategoryParameters()
Returns parameters for prefilling a new variant: the Api bridge `parameters-for-product` aggregates over all product categories (distinct, ordered by minimum `order`).
private
resolveProductCategoryParameters() : array<int, Parameter>
Resolved as entities so buildParameterRowDefaults() gets the row label.
Bundle mode and standalone add prefill nothing ($this->productId is null there).
Return values
array<int, Parameter>suggestParameters()
Suggests root parameters by name, skipping the already picked ones on POST: the typed `parameter_X` field exists once per parameter.
private
suggestParameters(string $query) : array<int, array{id: int, label: string}>
Parameters
- $query : string