AdvertFormTrait uses trait:short, trait:short, trait:short, trait:short, trait:short
Advert add/edit form (`/admin/bazaar/advert`) as a standard admin presenter form (`createForm()`), not a component.
Dynamic parameters are rendered by the shared ParameterFieldBuilder, so the category, user and region pickers work normally through the presenter PickerHostTrait and the template uses admin classes.
Composed of:
- AdvertLoadingTrait: loads parameters by categories, context and pre-fill,
- AdvertFormFieldsTrait: admin-only fields (moderation, counters, dates),
- AdvertCategoryFieldsTrait: categories (multiplier, picker, paid),
- AdvertUploaderTrait: images (dropzone).
meta['suppressNotifications'] makes the Api AdvertManager::completedSave skip all e-mails
and notifications; the price is still recomputed from the parameters (sorting). A new advert still
feeds the watchdogs (meta['notifyWatchdogs']), the same as one inserted on the front end.
IMPORTANT: the consuming AdvertPresenter must use AdvertFormTrait, PickerHostTrait and
DependentSelectBoxAware, have ?Advert $editedAdvert and implement pickers() (delegating to
AdvertCategoryFieldsTrait::pickers()); otherwise the form does not work.
Table of Contents
Constants
- ADV_DT_FORMAT : mixed = 'Y-m-d\TH:i'
- Value format of `<input type=datetime-local>`.
- REGION_PARAMETER_TYPES : array<string|int, mixed> = [\App\Core\Base\Shared\Shared\Models\Entities\P...
- Parameter types that carry the advert region (tree picker and municipality or postcode suggest).
Properties
- $advertLanguageManager : LanguageManager
- $advertLocalizationManager : LocalizationManager
- $advertManager : AdvertManager
- $categoryManager : CategoryManager
- $categoryParameterRelManager : CategoryParameterRelManager
- $currencyManager : CurrencyManager
- $parameterGroupManager : ParameterGroupManager
- $parameterManager : ParameterManager
- $pickerFactory : PickerFactory
- $uploaderDropzoneFactory : UploaderDropzoneFactory
- $fieldBuilder : ParameterFieldBuilder|null
- $hasSelectedCategory : bool
- Whether at least one category is selected; the template hides the admin-only fields (`d-none`) until then.
- $parameterFormItems : array<string|int, ParameterFormItem>
- $parameterFormPrepared : bool
Methods
- getUploaderControlMap() : array<string, string>
- Returns the map of form control name to uploader child name: the first `IMAGE_UPLOADER` maps to `imgUploader`, the first `FILE_UPLOADER` to `fileUploader`. The template looks controls up here and renders a dropzone for a match, a classic input otherwise.
- createComponentEditForm() : Form
- createComponentFileUploader() : UploaderDropzone
- createComponentImgUploader() : UploaderDropzone
- pickers() : array<string, PickerConfig>
- Returns the presenter picker configuration (the {@see \App\UI\Admin\System\Presenters\Traits\Pickers\PickerHostTrait} contract).
- addAdminFields() : void
- addCategoryFields() : void
- addOwnerFields() : void
- Adds the hidden field for the advert author (user), filled by the picker (suggest or modal) with `insert_user_id`. {@see AdvertBuildTrait::buildAdvert()} sets it as a managed association.
- addUploaderFields() : void
- Adds the hidden fields with the dropzone temp-directory tokens.
- advIntOrNull() : int|null
- advLabel() : string
- Translates a relative key through the presenter translator and domain, for labels rendered raw (group legends) where Nette `{label}` does not help.
- advStr() : string
- advStrOrNull() : string|null
- aggregateCategoryParameterRels() : array<int, array{order: int, required: bool, groupId: ?int}>
- Aggregates the `CategoryParameterRel` rows across categories into one entry per parameter id: minimum order, required if any category requires it, first non-null group id.
- applyCategoryRels() : void
- Builds the object-graph collection `categoryRels` from the submitted multiplier rows.
- applyParameterRels() : void
- Builds the object-graph collection `parameterRels` from the submitted rows.
- buildAdvert() : Advert
- buildAssetsMeta() : array<int, array{type: string, imageId?: int, name?: string, path?: string, order: int}>|null
- Builds `meta['assets']` for the Api `afterSave`: the ordered images, existing ids plus new files as a `path` into the temp directory.
- buildCategoryRowDefaults() : array<int, array{categoryId: int, category: string, paid: bool}>
- Builds the category row defaults from the edited advert (`categoryId`, label and `paid` from the database).
- buildCurrencyItems() : array<int, string>
- buildFilesMeta() : array<int, array{type: string, fileId?: int, name?: string, path?: string, order: int}>|null
- Builds `meta['files']` for the Api `afterSave` (`processFiles` to `fileRels`): the ordered files, existing ids plus new files as a `path` into the temp directory. Same shape as the assets, with `fileId` instead of `imageId`.
- buildParameterContext() : ParameterFormContext
- Fills {@see ParameterFormContext} (`languageId` and the items for the currency/region selects).
- buildParametersMeta() : array<int, array{id: int, value: string, value2?: string}>
- Builds flat rows `id`, `value` and optional `value2` from the submitted dynamic parameter values through {@see ParameterFieldBuilder::extractValues()} (persistable types only). The input for {@see applyParameterRels()} (object-graph collection), not a meta key.
- buildRegionItems() : array<int, string>
- Builds the items of a `SELECT_REGION` parameter: a plain `<select>`, not a Picker.
- buildRegionPreviewFieldMap() : array<string, string>
- Builds the preview after selecting a municipality: item data key to the form key of the parameter `city`, `zip` or `country` (only parameters the current form categories have).
- categoryMultiPicker() : PickerConfig
- categoryName() : string
- cleanupUploaders() : void
- configureFileUploader() : void
- configureImageUploader() : void
- Configures the image uploader.
- extractCategoryRows() : array<int, array{categoryId: int, paid: bool}>
- Builds flat rows `{categoryId, paid}` from the submitted multiplier rows; the input for {@see AdvertFormTrait::applyCategoryRels()} (object-graph collection), not a meta key. Deduplicated, positive `categoryId`.
- extractSubmittedCategoryIds() : array<int, int>
- Returns category ids from the submitted multiplier rows (`categories[*][categoryId]`), the same shape that save reads in {@see AdvertCategoryFieldsTrait::extractCategoryRows()}.
- findFirstParameterOfType() : Parameter|null
- gateAdvertColumns() : void
- Column gates of the parameters written into advert columns, the same as the front form (`AdvertFormComponent\Traits\FormFieldsTrait::gateAdvertColumns()`): the contact e-mail goes to `email` and the price is copied to the sort column `price` (`AdvertPriceColumnTrait` on the Api). The builder knows only the parameter type, so a negative price was stored (`-5`) and a longer e-mail or a price out of the column range failed the save in the database (admin walkthrough B5).
- getEditedAdvert() : Advert|null
- getEntityValues() : array<int, mixed>
- Returns the pre-filled values of the dynamic parameters from the edited advert (`parameterRels`).
- getFieldBuilder() : ParameterFieldBuilder
- getRegionLabel() : string
- guardAdvertReferences() : void
- Guards the ids written into foreign keys of the advert: the author (picker) and the insert language and localization (typed numbers). A deleted or mistyped id failed the save on the foreign key with a generic message (admin walkthrough B3/B6 family); the admin-only columns are measured by the column gate.
- guardCategoriesSelected() : void
- Enforces at least one selected category; called from `onValidate`.
- itemsHaveType() : bool
- loadParameterGroups() : array<string|int, ParameterGroupInterface>
- loadParameters() : array<string|int, ParameterFormItem>
- parseFileTypes() : array<string|int, string>
- prepareExistingAssets() : array<int, array{imageId: int, thumbPath: string, isMain: bool, order: int}>
- prepareExistingFiles() : array<int, array{imageId: int, thumbPath: string, fileName: string, isMain: bool, order: int}>
- Returns the existing files for the dropzone (the key `imageId` is the generic dropzone identifier).
- prepareParameterForm() : void
- Loads parameters by the advert categories, context and pre-fill, and initializes the builder.
- resolveActiveCategories() : array<string|int, Category>
- Returns the categories that decide which dynamic parameters are shown.
- resolveAnyRegionParameterField() : array{key: string, type: int}|null
- Returns the region parameter from the code list, independent of the selected category; used only to register the picker so suggest works on the add form too. Returns the first active root parameter of type `SELECT_REGION` (or legacy 37) or `REGION_PICKER`; null means the module has no region parameter.
- resolveCategoryLabel() : string|null
- resolveEditedAdvertCategories() : array<string|int, Category>
- Returns the categories of the edited advert (from `categoryRels`); empty for a new advert.
- resolveRegionParameterField() : array{key: string, type: int}|null
- Returns the form field of the region parameter: `key` is `parameter_<id>` (the picker `targetField`) and `type` decides the picker (`SELECT_REGION` or legacy 37: tree picker, `REGION_PICKER`: municipality or postcode suggest). Null means the system has no region parameter, so no picker is registered.
- resolveUploaderToken() : string|null
- saveAdvertForm() : bool
- Saves the advert with notifications suppressed (`meta['suppressNotifications']`).
- suggestCategories() : array<int, array{id: int, label: string}>
- syncUploaderTokenFields() : void
- Aligns the hidden token fields with the real uploader temp directories.
Constants
ADV_DT_FORMAT
Value format of `<input type=datetime-local>`.
private
mixed
ADV_DT_FORMAT
= 'Y-m-d\TH:i'
REGION_PARAMETER_TYPES
Parameter types that carry the advert region (tree picker and municipality or postcode suggest).
private
array<string|int, mixed>
REGION_PARAMETER_TYPES
= [\App\Core\Base\Shared\Shared\Models\Entities\ParameterType::SELECT_REGION, \App\Core\Form\Parameters\SelectRegionHandler::LEGACY_REGION_WITH_POSTCODE, \App\Core\Base\Shared\Shared\Models\Entities\ParameterType::REGION_PICKER]
Properties
$advertLanguageManager
public
LanguageManager
$advertLanguageManager
Attributes
- #[Inject]
$advertLocalizationManager
public
LocalizationManager
$advertLocalizationManager
Attributes
- #[Inject]
$advertManager
public
AdvertManager
$advertManager
Attributes
- #[Inject]
$categoryManager
public
CategoryManager
$categoryManager
Attributes
- #[Inject]
$categoryParameterRelManager
public
CategoryParameterRelManager
$categoryParameterRelManager
Attributes
- #[Inject]
$currencyManager
public
CurrencyManager
$currencyManager
Attributes
- #[Inject]
$parameterGroupManager
public
ParameterGroupManager
$parameterGroupManager
Attributes
- #[Inject]
$parameterManager
public
ParameterManager
$parameterManager
Attributes
- #[Inject]
$pickerFactory
public
PickerFactory
$pickerFactory
Attributes
- #[Inject]
$uploaderDropzoneFactory
public
UploaderDropzoneFactory
$uploaderDropzoneFactory
Attributes
- #[Inject]
$fieldBuilder
private
ParameterFieldBuilder|null
$fieldBuilder
= null
$hasSelectedCategory
Whether at least one category is selected; the template hides the admin-only fields (`d-none`) until then.
private
bool
$hasSelectedCategory
= false
$parameterFormItems
private
array<string|int, ParameterFormItem>
$parameterFormItems
= []
$parameterFormPrepared
private
bool
$parameterFormPrepared
= false
Methods
getUploaderControlMap()
Returns the map of form control name to uploader child name: the first `IMAGE_UPLOADER` maps to `imgUploader`, the first `FILE_UPLOADER` to `fileUploader`. The template looks controls up here and renders a dropzone for a match, a classic input otherwise.
public
getUploaderControlMap() : array<string, string>
Return values
array<string, string>createComponentEditForm()
protected
createComponentEditForm() : Form
Return values
FormcreateComponentFileUploader()
protected
createComponentFileUploader() : UploaderDropzone
Return values
UploaderDropzonecreateComponentImgUploader()
protected
createComponentImgUploader() : UploaderDropzone
Return values
UploaderDropzonepickers()
Returns the presenter picker configuration (the {@see \App\UI\Admin\System\Presenters\Traits\Pickers\PickerHostTrait} contract).
protected
pickers() : array<string, PickerConfig>
Return values
array<string, PickerConfig>addAdminFields()
private
addAdminFields(Form $form) : void
Parameters
- $form : Form
addCategoryFields()
private
addCategoryFields(Form $form) : void
Parameters
- $form : Form
addOwnerFields()
Adds the hidden field for the advert author (user), filled by the picker (suggest or modal) with `insert_user_id`. {@see AdvertBuildTrait::buildAdvert()} sets it as a managed association.
private
addOwnerFields(Form $form) : void
The region is not an admin field but the parameter SELECT_REGION rendered as a picker; see
AdvertCategoryFieldsTrait::pickers() and the denormalization in buildAdvert().
Parameters
- $form : Form
addUploaderFields()
Adds the hidden fields with the dropzone temp-directory tokens.
private
addUploaderFields(Form $form) : void
On an AJAX re-render (validation error) the token is taken from the POST. Called from AdvertFormTrait::createComponentEditForm().
Parameters
- $form : Form
advIntOrNull()
private
advIntOrNull(mixed $value) : int|null
Parameters
- $value : mixed
Return values
int|nulladvLabel()
Translates a relative key through the presenter translator and domain, for labels rendered raw (group legends) where Nette `{label}` does not help.
private
advLabel(string $key) : string
Parameters
- $key : string
Return values
stringadvStr()
private
advStr(mixed $value) : string
Parameters
- $value : mixed
Return values
stringadvStrOrNull()
private
advStrOrNull(mixed $value) : string|null
Parameters
- $value : mixed
Return values
string|nullaggregateCategoryParameterRels()
Aggregates the `CategoryParameterRel` rows across categories into one entry per parameter id: minimum order, required if any category requires it, first non-null group id.
private
aggregateCategoryParameterRels(array<string|int, Category> $categories) : array<int, array{order: int, required: bool, groupId: ?int}>
Parameters
- $categories : array<string|int, Category>
Return values
array<int, array{order: int, required: bool, groupId: ?int}>applyCategoryRels()
Builds the object-graph collection `categoryRels` from the submitted multiplier rows.
private
applyCategoryRels(Advert $advert, array<int, array{categoryId: int, paid: bool}> $rows) : void
category is a light reference (new Category()->setId($id), like applyParameterRels());
EntityHydrator::extract() serializes it as {"id":{"id":X}} and the Api hydrateForPersist
looks it up as a managed entity. paid comes from the form explicitly (the admin gets it
prefilled from the database and may change it; the external path is guarded by
CategoryRelsPaidSanitizationTrait).
IMPORTANT: always call it, even with $rows === []. Unlike applyParameterRels(), an
empty collection is a legitimate admin remove-all: the Api orphanRemoval deletes all
categories of the advert (the opposite empty semantics, see saveAdvertForm()).
Parameters
- $advert : Advert
- $rows : array<int, array{categoryId: int, paid: bool}>
applyParameterRels()
Builds the object-graph collection `parameterRels` from the submitted rows.
private
applyParameterRels(Advert $advert, array<int, array{id: int, value: string, value2?: string}> $rows) : void
parameter is a light reference (new Parameter()->setId($id), like Region and User in
AdvertBuildTrait::buildAdvert()); EntityHydrator::extract() serializes it as
{"id":{"id":X}} and the Api hydrateForPersist looks it up as a managed entity.
IMPORTANT: call only when $rows !== [] (see saveAdvertForm()). Replacing the
collection with an empty array would make orphanRemoval delete all existing parameters of the
advert on the Api side. An empty submit leaves the collection untouched (the clone from
AdvertBuildTrait::buildAdvert() carries the old state).
Parameters
- $advert : Advert
- $rows : array<int, array{id: int, value: string, value2?: string}>
buildAdvert()
private
buildAdvert(ArrayHash $values) : Advert
Parameters
- $values : ArrayHash
Return values
AdvertbuildAssetsMeta()
Builds `meta['assets']` for the Api `afterSave`: the ordered images, existing ids plus new files as a `path` into the temp directory.
private
buildAssetsMeta(ArrayHash $values) : array<int, array{type: string, imageId?: int, name?: string, path?: string, order: int}>|null
IMPORTANT: an empty list is a valid instruction to remove all images (the user deleted the last
one) and the caller must send it. "Unknown" (no uploader in the form) is returned as null and
the caller must not set the assets key in meta; otherwise a missing component would delete
the relations. Same tri-state pattern as
ComplaintFileUploaderTrait::buildComplaintFilesMeta().
Parameters
- $values : ArrayHash
Return values
array<int, array{type: string, imageId?: int, name?: string, path?: string, order: int}>|nullbuildCategoryRowDefaults()
Builds the category row defaults from the edited advert (`categoryId`, label and `paid` from the database).
private
buildCategoryRowDefaults() : array<int, array{categoryId: int, category: string, paid: bool}>
Return values
array<int, array{categoryId: int, category: string, paid: bool}>buildCurrencyItems()
private
buildCurrencyItems() : array<int, string>
Return values
array<int, string>buildFilesMeta()
Builds `meta['files']` for the Api `afterSave` (`processFiles` to `fileRels`): the ordered files, existing ids plus new files as a `path` into the temp directory. Same shape as the assets, with `fileId` instead of `imageId`.
private
buildFilesMeta(ArrayHash $values) : array<int, array{type: string, fileId?: int, name?: string, path?: string, order: int}>|null
Same tri-state semantics as buildAssetsMeta(): an empty list removes all files, null
means there is no uploader in the form and the files key must not be set in meta.
Parameters
- $values : ArrayHash
Return values
array<int, array{type: string, fileId?: int, name?: string, path?: string, order: int}>|nullbuildParameterContext()
Fills {@see ParameterFormContext} (`languageId` and the items for the currency/region selects).
private
buildParameterContext(array<string|int, ParameterFormItem> $items) : ParameterFormContext
Parameters
- $items : array<string|int, ParameterFormItem>
Return values
ParameterFormContextbuildParametersMeta()
Builds flat rows `id`, `value` and optional `value2` from the submitted dynamic parameter values through {@see ParameterFieldBuilder::extractValues()} (persistable types only). The input for {@see applyParameterRels()} (object-graph collection), not a meta key.
private
buildParametersMeta(ArrayHash $values) : array<int, array{id: int, value: string, value2?: string}>
Parameters
- $values : ArrayHash
Return values
array<int, array{id: int, value: string, value2?: string}>buildRegionItems()
Builds the items of a `SELECT_REGION` parameter: a plain `<select>`, not a Picker.
private
buildRegionItems(int|null $langId) : array<int, string>
IMPORTANT: only country and region (level <= 2). After the municipalities are imported into
cms_system_regions (thousands of nodes), an unfiltered findAll() would flood the select.
Municipality and district are chosen in the suggester, not here.
Parameters
- $langId : int|null
Return values
array<int, string>buildRegionPreviewFieldMap()
Builds the preview after selecting a municipality: item data key to the form key of the parameter `city`, `zip` or `country` (only parameters the current form categories have).
private
buildRegionPreviewFieldMap() : array<string, string>
Return values
array<string, string>categoryMultiPicker()
private
categoryMultiPicker([string $container = 'categories' ][, string $targetField = 'categoryId' ][, string $displayField = 'category' ]) : PickerConfig
Parameters
- $container : string = 'categories'
- $targetField : string = 'categoryId'
- $displayField : string = 'category'
Return values
PickerConfigcategoryName()
private
categoryName(Category $category) : string
Parameters
- $category : Category
Return values
stringcleanupUploaders()
private
cleanupUploaders() : void
configureFileUploader()
private
configureFileUploader(UploaderDropzone $uploader) : void
Parameters
- $uploader : UploaderDropzone
configureImageUploader()
Configures the image uploader.
private
configureImageUploader(UploaderDropzone $uploader) : void
IMPORTANT: this runs in the component factory (createComponent*()), not in prepareParameterForm().
The dropzone upload signal is a separate request in which the edit form is never built, so the
uploader would be created unconfigured (default subDir and mime types) and the upload would fail.
It takes the instance instead of $this[...] to avoid recursion inside the factory.
Parameters
- $uploader : UploaderDropzone
extractCategoryRows()
Builds flat rows `{categoryId, paid}` from the submitted multiplier rows; the input for {@see AdvertFormTrait::applyCategoryRels()} (object-graph collection), not a meta key. Deduplicated, positive `categoryId`.
private
extractCategoryRows(ArrayHash $values) : array<int, array{categoryId: int, paid: bool}>
Parameters
- $values : ArrayHash
Return values
array<int, array{categoryId: int, paid: bool}>extractSubmittedCategoryIds()
Returns category ids from the submitted multiplier rows (`categories[*][categoryId]`), the same shape that save reads in {@see AdvertCategoryFieldsTrait::extractCategoryRows()}.
private
extractSubmittedCategoryIds() : array<int, int>
Deduplicated and positive; non-row multiplier keys (creator, remover) are skipped.
Return values
array<int, int>findFirstParameterOfType()
private
findFirstParameterOfType(int $type) : Parameter|null
Parameters
- $type : int
Return values
Parameter|nullgateAdvertColumns()
Column gates of the parameters written into advert columns, the same as the front form (`AdvertFormComponent\Traits\FormFieldsTrait::gateAdvertColumns()`): the contact e-mail goes to `email` and the price is copied to the sort column `price` (`AdvertPriceColumnTrait` on the Api). The builder knows only the parameter type, so a negative price was stored (`-5`) and a longer e-mail or a price out of the column range failed the save in the database (admin walkthrough B5).
private
gateAdvertColumns(Form $form) : void
Parameters
- $form : Form
getEditedAdvert()
private
getEditedAdvert() : Advert|null
Return values
Advert|nullgetEntityValues()
Returns the pre-filled values of the dynamic parameters from the edited advert (`parameterRels`).
private
getEntityValues() : array<int, mixed>
Return values
array<int, mixed>getFieldBuilder()
private
getFieldBuilder() : ParameterFieldBuilder
Return values
ParameterFieldBuildergetRegionLabel()
private
getRegionLabel(Region $region, int|null $langId) : string
Parameters
- $region : Region
- $langId : int|null
Return values
stringguardAdvertReferences()
Guards the ids written into foreign keys of the advert: the author (picker) and the insert language and localization (typed numbers). A deleted or mistyped id failed the save on the foreign key with a generic message (admin walkthrough B3/B6 family); the admin-only columns are measured by the column gate.
private
guardAdvertReferences(Form $form) : void
Parameters
- $form : Form
guardCategoriesSelected()
Enforces at least one selected category; called from `onValidate`.
private
guardCategoriesSelected(Form $form, ArrayHash $values) : void
Checked only on a real save (update or save). Add, remove and parametersRefresh are UI
submitters with setValidationScope([]) whose only job is the AJAX redraw, but Nette runs
onValidate for them too (Container::validate() calls the handlers
regardless of scope); without this gate "Add category" would report an error.
IMPORTANT: the error must go to a concrete component, not the form. The admin templates do
not render form-level errors (only the flash), and HiddenField::addError() is hard-wired
to form level. The carrier is therefore the "Add category" button (multiplier_creator), the
only component always rendered in the categories section, even with zero rows; the template
prints the error below it (Advert/Tabs/_form.latte). Form level is only a fallback
when the multiplier has no such button (maxCopies).
Parameters
- $form : Form
- $values : ArrayHash
itemsHaveType()
private
itemsHaveType(array<string|int, ParameterFormItem> $items, int $type) : bool
Parameters
- $items : array<string|int, ParameterFormItem>
- $type : int
Return values
boolloadParameterGroups()
private
loadParameterGroups(array<string|int, ParameterFormItem> $items) : array<string|int, ParameterGroupInterface>
Parameters
- $items : array<string|int, ParameterFormItem>
Return values
array<string|int, ParameterGroupInterface>loadParameters()
private
loadParameters(array<string|int, Category> $categories) : array<string|int, ParameterFormItem>
Parameters
- $categories : array<string|int, Category>
Return values
array<string|int, ParameterFormItem>parseFileTypes()
private
parseFileTypes(string|null $fileType, array<string|int, string> $fallback) : array<string|int, string>
Parameters
- $fileType : string|null
- $fallback : array<string|int, string>
Return values
array<string|int, string>prepareExistingAssets()
private
prepareExistingAssets() : array<int, array{imageId: int, thumbPath: string, isMain: bool, order: int}>
Return values
array<int, array{imageId: int, thumbPath: string, isMain: bool, order: int}>prepareExistingFiles()
Returns the existing files for the dropzone (the key `imageId` is the generic dropzone identifier).
private
prepareExistingFiles() : array<int, array{imageId: int, thumbPath: string, fileName: string, isMain: bool, order: int}>
Return values
array<int, array{imageId: int, thumbPath: string, fileName: string, isMain: bool, order: int}>prepareParameterForm()
Loads parameters by the advert categories, context and pre-fill, and initializes the builder.
private
prepareParameterForm() : void
Idempotent: called from createComponentEditForm() and from the render action (for the uploader map).
resolveActiveCategories()
Returns the categories that decide which dynamic parameters are shown.
private
resolveActiveCategories() : array<string|int, Category>
On POST (AJAX category refresh and a real save) the live selected categories come from the submitted multiplier rows, so the parameters follow the current selection. On a clean GET the stored advert categories are used (a new advert has none, so no dynamic parameters are shown until a category is chosen, see AdvertLoadingTrait::loadParameters()).
IMPORTANT: reads the raw POST, not the form object: prepareParameterForm() runs in
createComponentEditForm() before addCategoryFields(), so the categories multiplier is not attached yet.
Return values
array<string|int, Category>resolveAnyRegionParameterField()
Returns the region parameter from the code list, independent of the selected category; used only to register the picker so suggest works on the add form too. Returns the first active root parameter of type `SELECT_REGION` (or legacy 37) or `REGION_PICKER`; null means the module has no region parameter.
private
resolveAnyRegionParameterField() : array{key: string, type: int}|null
Return values
array{key: string, type: int}|nullresolveCategoryLabel()
private
resolveCategoryLabel(int $id) : string|null
Parameters
- $id : int
Return values
string|nullresolveEditedAdvertCategories()
Returns the categories of the edited advert (from `categoryRels`); empty for a new advert.
private
resolveEditedAdvertCategories() : array<string|int, Category>
Return values
array<string|int, Category>resolveRegionParameterField()
Returns the form field of the region parameter: `key` is `parameter_<id>` (the picker `targetField`) and `type` decides the picker (`SELECT_REGION` or legacy 37: tree picker, `REGION_PICKER`: municipality or postcode suggest). Null means the system has no region parameter, so no picker is registered.
private
resolveRegionParameterField() : array{key: string, type: int}|null
IMPORTANT: on the add form no category is selected yet and parameterFormItems is empty.
Without the fallback to the parameter code list the picker would not be registered, the
standalone GET signal picker-…-suggest would end with 404 and the region could be chosen
only through the modal.
Return values
array{key: string, type: int}|nullresolveUploaderToken()
private
resolveUploaderToken(string $componentName, string $postField) : string|null
Parameters
- $componentName : string
- $postField : string
Return values
string|nullsaveAdvertForm()
Saves the advert with notifications suppressed (`meta['suppressNotifications']`).
private
saveAdvertForm(ArrayHash $values) : bool
The dynamic parameters (form values) are built directly as the object-graph collection
$advert->parameterRels; the Api beforeSave recomputes advert.price (sorting) and geocodes
the coordinates, and the rels are written by a real Doctrine cascade and orphanRemoval persist.
parametersTouched is only an internal gate flag that keeps geocoding from running on a save
without submitted parameters (the collection itself is always truthy, even when unchanged).
Categories (categoryRels) are built as an object-graph collection too
(applyCategoryRels()) and always applied, even when empty (remove-all is legitimate
and orphanRemoval deletes them). meta['assets'] makes the Api sync images.
Parameters
- $values : ArrayHash
Return values
boolsuggestCategories()
private
suggestCategories(string $query) : array<int, array{id: int, label: string}>
Parameters
- $query : string
Return values
array<int, array{id: int, label: string}>syncUploaderTokenFields()
Aligns the hidden token fields with the real uploader temp directories.
private
syncUploaderTokenFields(Form $form) : void
Called from AJAX redraw handlers. addHidden() sets only a default and on a submitted form the
POSTed value wins; on the add form it is empty because the uploaders did not exist at submit time.
Without this the hidden field renders empty and buildAssetsMeta() cannot tell which temp
directory holds the uploaded files on save.
Parameters
- $form : Form