Repository navigation
#160 - Full control over the launch form fields (type, options, constraints, default) through the new form UI option - #168
clever-age-gtonon wants to merge 17 commits into
Conversation
njoubert-cleverage
left a comment
There was a problem hiding this comment.
Thanks for this work: the feature covers the whole scope of #160, the deprecated options are cleanly folded into form, the deprecation messages name the process, and the docs, upgrade guide and tests (403 → 588) are thorough. CI is green and the CHANGELOG conflict of #161 is solved.
Requesting changes for the points below (details in the inline comments).
Blocking
- Scope. The PR bundles three changes that are not part of #160 and deserve their own issue/PR (and changelog entry):
execution_useralways set to the connected user and reserved (security-related behaviour change, previously a context value could override it);- the format rule on the keys of the free context pairs, including the schedules;
ProcessConfigurationsManagerresolving only the requested option (ui/notification/logs), which changes how invalidnotification/logsoptions are reported.
- Key format rule = BC break in a minor. Free keys such as
api.token,a/bora bused to work and are now refused at launch, and existing schedules can no longer be saved from the UI. The root cause is in process-bundle:ContextualOptionResolverbuilds its regex from the context keys withoutpreg_quote()(that is what thezz)|x|(?:zz/a/btests show). It should be fixed there; here the naming rule should only apply to the keys declared inform.context, which must be valid form field names anyway. - Form type: FQCN only.
FORM_TYPE_ALIASESintroduces a second naming scheme for the form types: a closed list of 35 entries to maintain, while any type (including a project-specific one) can already be given by its FQCN. It also requiressymfony/doctrine-bridgeonly for theentityalias. I'd remove it and accept FQCNs only, as the Symfony form builder does and as in the draft of #160:resolveFormType()then only checksclass_exists/FormTypeInterface/ not a button, andsymfony/doctrine-bridgecan be dropped fromcomposer.json(docs, changelog and tests to update). This also solves theentityissue: its data is the entity itself, converted through__toString(), i.e. its label rather than its identifier, and its default value cannot be written in YAML.
The short names of the constraints (Choice,File...) are not concerned: that is the existingConstraintLoadersyntax. A test with a constraint given by its FQCN (e.g. a project-specific constraint) is missing though: it is documented but not covered.
Important
- Default values of object types: the docs cover
date/dateinterval(input: string), but notenum(a YAML scalar where the field expects an enum case). Either refuse it at resolution or document it. - Late configuration errors: an invalid field option gives a 500 on the launch page, and a non-convertible value gives a 500 after the user filled and submitted the form. At least the latter should be reported as a form error.
- Process list:
list.html.twigresolves the UI options of every process, so one invalidformconfiguration breaks the whole page, and every rendering triggers one deprecation per process using the deprecated options.
Minor
ProcessConfigurationsManagergrows to ~700 lines, mostly the launch form resolution: it could move to a dedicated (internal) resolver.- Public API surface:
getLaunchFormDefaults()is only used by the tests;buildLaunchFormDefaults(), theui_optionsoption ofLaunchTypeandContextValueNormalizer(instantiated withnewin the controller) should be@internal. - The declared context fields are
required: trueby default (Symfony default): acheckboxmust then be checked (thedry_runexample of #160 needs an explicitrequired: false). Afalsedefault for the declared context fields would be safer. - The CHANGELOG entry is a single ~2000-character paragraph: it would be easier to read split into bullets.
- One 3k-line commit makes the review hard: splitting per point 1 would help.
🤖 Generated with Claude Code
| // The rule of FormConfigBuilder::isValidName() applied to the declared context keys of the launch form, and | ||
| // not only digits (PHP casts such an array key to an integer) | ||
| new Regex( | ||
| pattern: '/^(?![0-9]+$)[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', |
There was a problem hiding this comment.
This rejects keys that used to work (api.token, a/b, a b...) in the launch form and the schedules: BC break in a minor. The underlying problem is ContextualOptionResolver in process-bundle, which puts the context keys into a regex without preg_quote(); it should be fixed there. Here, the naming rule is only needed for the keys declared in form.context (form field names).
There was a problem hiding this comment.
Reverted in eba7505: the free context pairs (launch form and schedules) accept any non-empty key again, as on main. The naming rule only applies to the keys declared in form.context (form field names).
| * | ||
| * @var array<string, class-string> | ||
| */ | ||
| private const FORM_TYPE_ALIASES = [ |
There was a problem hiding this comment.
I'd drop this alias table and accept FQCNs only for type (as the Symfony form builder and the draft of #160): one naming scheme, nothing to maintain, a project-specific type works the same way, and symfony/doctrine-bridge is no longer needed.
There was a problem hiding this comment.
Done in 399d67b: the alias table is removed, type is the FQCN of a form type only (class_exists, FormTypeInterface, not a button), the short names are refused with an explicit message.
| 'ulid' => Type\UlidType::class, | ||
| 'collection' => Type\CollectionType::class, | ||
| 'repeated' => Type\RepeatedType::class, | ||
| 'entity' => EntityType::class, |
There was a problem hiding this comment.
The data of an EntityType is the entity: through ContextValueNormalizer it becomes its __toString() (a label, not the identifier), and its default value cannot be written in YAML. Removing the aliases (see above) removes this one too.
There was a problem hiding this comment.
Solved by 399d67b: no entity alias anymore. An EntityType can still be given by its FQCN; the docs describe the object data (must be \Stringable) and recommend a ChoiceType with scalar choices.
| "symfony/console": "^6.4 || ^7.4 || ^8", | ||
| "symfony/dependency-injection": "^6.4 || ^7.4 || ^8", | ||
| "symfony/deprecation-contracts": "^2.5 || ^3", | ||
| "symfony/doctrine-bridge": "^6.4 || ^7.4 || ^8", |
There was a problem hiding this comment.
Only required for the entity alias: can be removed with FQCN-only types.
| * | ||
| * @return LaunchFormData | ||
| */ | ||
| public function getLaunchFormDefaults(string $processCode): array |
There was a problem hiding this comment.
Only used by the tests: new public API without a caller. Could be removed (or @internal), same question for buildLaunchFormDefaults().
There was a problem hiding this comment.
Removed in ef621a2: getLaunchFormDefaults() and buildLaunchFormDefaults() are gone, the initial data is part of the launch form resolved by the new internal getLaunchFormOptions() / LaunchFormOptionsResolver; the launch_form option of LaunchType is internal.
| if (null === $recipients) { | ||
| return null; | ||
| $resolver->setDefaults(['notification' => [], 'logs' => [], 'ui' => []]); | ||
| foreach (['notification', 'logs', 'ui'] as $name) { |
There was a problem hiding this comment.
Resolving only the requested option is a sensible change, but it is not part of #160 and changes how invalid notification / logs options are reported (no longer by the process list): it deserves its own issue/PR.
| return (string) $value; | ||
| } | ||
|
|
||
| throw new \LogicException(\sprintf('The value of "%s" ("%s") cannot be used as a process context value: use a form type returning a scalar (e.g. "choice" with scalar choices), or make the class implement \Stringable.', $name, get_debug_type($value))); |
There was a problem hiding this comment.
This is raised after the user filled and submitted the form, and ends as a 500. It would be friendlier as a form error (or detected earlier). Also, this class is instantiated with new in the controller: @internal?
There was a problem hiding this comment.
Done: e63af6a reports a value that cannot be converted as an error of its field (input, declared field or free pairs), the form is displayed again and nothing is dispatched. ContextValueNormalizer is @internal (b66b4b4). Besides, the launch forms are now checked each time the container is built, by a cache warmer that resolves them and builds them with the form factory of the application: form type options, default values, constraint validators (eef9ada, 8883fe1).
…er nor reserved (out of scope) Out of the scope of #160 (review of #168): back to the behaviour of main. - LaunchAction::dispatch(): the context is merged over execution_user again (array_merge), as before. - Remove ProcessExecuteMessage::EXECUTION_USER_KEY, ProcessContextType::createExecutionUserConstraint() and the key_constraints option of ProcessContextType. - execution_user is no longer reserved in the free context pairs of the launch form, in the schedules, nor in form.context ("extra" stays reserved: it is the child of the free pairs). - Tests and documentation updated accordingly. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…nd of the schedules (out of scope) Out of the scope of #160 and a BC break in a minor (review of #168): keys such as "api.token", "a/b" or "a b" are accepted again in the free context pairs of the launch form and in the schedules, as on main. - ProcessContextType: remove the Regex constraint of the key (NotBlank and the reserved_keys option of #160 are kept). - The naming rule still applies to the keys declared in form.context, which are form field names. - ProcessScheduleCrudTest and docs/reference/05-scheduler.md back to main; tests, reference documentation, upgrade guide and changelog updated. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tion and logs options together again (out of scope) Out of the scope of #160 (review of #168): as on main, the getters resolve the ui, notification and logs options in one pass, so invalid notification or logs options are reported again by the process list. - resolveOptions() resolves the three options again (notification and logs normalizers inlined as on main, the ui one delegating to the resolution of the launch form). - Remove the tests of the independent resolutions. - docs/reference/04-process_executions_and_logs.md and 09-notifications.md back to main; upgrade guide and changelog updated. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…-bridge Review of #168: one naming scheme for the form types, as the Symfony form builder and the draft of #160. - ProcessConfigurationsManager: remove the FORM_TYPE_ALIASES table; the default type is TextType::class; resolveFormType() only checks that the class exists, implements FormTypeInterface and is not a button type. The short names ("text", "choice"...) are refused with an explicit message. - composer.json: symfony/doctrine-bridge is no longer required (it was only needed by the "entity" alias). An EntityType can still be given by its FQCN when the bridge is installed. - Tests, reference documentation, cookbook, upgrade guide and changelog use FQCNs. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: documented but not covered. A project-specific constraint (tests/App/Validator/Even) given by its FQCN in form.context.<key>.options .constraints: - ProcessConfigurationsManagerTest: built by ConstraintLoader, with and without options; - Functional/LaunchActionTest (new test.form_custom_constraint process): the violation is displayed under the field and nothing is dispatched, a valid value is dispatched. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…aunch page (process and executions lists unaffected) Review of #168: the process list resolved the UI options of every process, so one invalid "form" option broke the whole page (as the executions list, through the source/target), and each rendering triggered the deprecations of every process using the deprecated options. ProcessConfigurationsManager also grew to ~700 lines, mostly for the launch form. - New internal LaunchFormOptionsResolver: resolves the "form" UI option, checks its conflicts with the deprecated "entrypoint_type", "default" and "constraints" options, folds them into the launch form, builds the initial data of the form, and triggers the deprecations (same messages). - ProcessConfigurationsManager::getUiOptions() is back to its shape of main: "form" is accepted as is, not resolved; no deprecation is triggered. - New internal ProcessConfigurationsManager::getLaunchFormOptions(), used by LaunchAction; LaunchType receives the resolved launch form through its internal "launch_form" option (was "ui_options"). - getLaunchFormDefaults() and buildLaunchFormDefaults() are removed: the initial data is part of the resolved launch form. - Tests: the launch form tests move to LaunchFormOptionsResolverTest; the manager and Twig runtime tests are back to main (plus "form" not resolved); the process list triggers no deprecation. - Reference documentation, upgrade guide and changelog updated. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: no new public API without a caller. - ContextValueNormalizer (instantiated by LaunchAction) is @internal. - The other launch form internals are already internal since the previous commit: LaunchFormOptionsResolver, getLaunchFormOptions() and the "launch_form" option of LaunchType; getLaunchFormDefaults() and buildLaunchFormDefaults() (only used by the tests) were removed. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: the default value of an EnumType field written as a YAML scalar cannot be transformed by the field, which expects an enum case. - LaunchFormOptionsResolver: the default value of an EnumType field must be a case of the enum of options.class (a list of cases with "multiple"), otherwise an InvalidOptionsException suggests the "!php/enum" YAML tag. - The "!php/enum" tag goes through the process bundle configuration and the container: functional test with a backed enum field (pre-selected default, value of the case given to the process). - Reference documentation (default values of the fields) and changelog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: an invalid launch form configuration was only reported when the launch page was opened (500). - New internal CheckLaunchFormsPass, registered by the bundle: for each process declaring the "form" UI option, the launch form is resolved (the deprecated options folded into it) when the container is compiled; an invalid launch form fails the compilation with a message naming the process (type, forbidden options, file fields, keys, enum default, constraints, conflicts with the deprecated options). - Only the UI options are checked: the tasks and the other options of the process are not concerned. A process without "form" is not checked (no BC break), a launch form using an environment variable is left to the launch page, and the parameters are resolved. The deprecations stay triggered on the launch page only. - The options of the form types themselves are still resolved by the form factory when the form is built, and the submitted values are converted after the submission. - Tests: the pass and its registration; the tests booting the test kernel declare the classes used at compile time (strict coverage metadata). - Reference documentation and changelog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tead of a 500 Review of #168: a value that cannot be converted into a process value was raised as a LogicException (500) after the user filled and submitted the form. - LaunchAction converts the input and the context before saving the uploaded file and dispatching; a value that cannot be converted is reported as an error of its field (the input, a declared context field, or the free context pairs), the form is displayed again and nothing is dispatched. - The message of ContextValueNormalizer names a ChoiceType instead of the removed "choice" alias. - Functional tests for the input and a context field; reference documentation and changelog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: the declared context fields followed the Symfony default (required: true), so a CheckboxType had to be checked (the dry_run example of #160 needed an explicit required: false). - LaunchType: the declared context fields are not required by default, an explicit "required" option of the field takes precedence (the input is still required when the process defines an entry_point). - A select that is not required has an empty choice: the Delimiter examples (reference, cookbook, upgrade guide) set required: true. - Tests, reference documentation and changelog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: the entry was a single ~2000-character paragraph. It is split into bullets, and only describes the scope of #160. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…raints, default) through the new form UI option Add the `form` UI option declaring the `input` field and each context field of the launch form (type alias or FQCN, form type options with their constraints, default value), whether free context pairs are allowed, and the constraints of the whole form. Typed values are converted into process values by the new ContextValueNormalizer. Deprecate the `entrypoint_type`, `default` and `constraints` UI options (folded into `form` until 4.0). Reserve the `execution_user` context key, validate the format of the free context keys (launch form and schedules), resolve only the requested process option in ProcessConfigurationsManager and the UI options once per launch request. Require symfony/doctrine-bridge. Add documentation, an upgrade guide and tests. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This reverts commit 588f35e.
…er nor reserved (out of scope) Out of the scope of #160 (review of #168): back to the behaviour of main. - LaunchAction::dispatch(): the context is merged over execution_user again (array_merge), as before. - Remove ProcessExecuteMessage::EXECUTION_USER_KEY, ProcessContextType::createExecutionUserConstraint() and the key_constraints option of ProcessContextType. - execution_user is no longer reserved in the free context pairs of the launch form, in the schedules, nor in form.context ("extra" stays reserved: it is the child of the free pairs). - Tests and documentation updated accordingly. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…nd of the schedules (out of scope) Out of the scope of #160 and a BC break in a minor (review of #168): keys such as "api.token", "a/b" or "a b" are accepted again in the free context pairs of the launch form and in the schedules, as on main. - ProcessContextType: remove the Regex constraint of the key (NotBlank and the reserved_keys option of #160 are kept). - The naming rule still applies to the keys declared in form.context, which are form field names. - ProcessScheduleCrudTest and docs/reference/05-scheduler.md back to main; tests, reference documentation, upgrade guide and changelog updated. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tion and logs options together again (out of scope) Out of the scope of #160 (review of #168): as on main, the getters resolve the ui, notification and logs options in one pass, so invalid notification or logs options are reported again by the process list. - resolveOptions() resolves the three options again (notification and logs normalizers inlined as on main, the ui one delegating to the resolution of the launch form). - Remove the tests of the independent resolutions. - docs/reference/04-process_executions_and_logs.md and 09-notifications.md back to main; upgrade guide and changelog updated. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…-bridge Review of #168: one naming scheme for the form types, as the Symfony form builder and the draft of #160. - ProcessConfigurationsManager: remove the FORM_TYPE_ALIASES table; the default type is TextType::class; resolveFormType() only checks that the class exists, implements FormTypeInterface and is not a button type. The short names ("text", "choice"...) are refused with an explicit message. - composer.json: symfony/doctrine-bridge is no longer required (it was only needed by the "entity" alias). An EntityType can still be given by its FQCN when the bridge is installed. - Tests, reference documentation, cookbook, upgrade guide and changelog use FQCNs. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: documented but not covered. A project-specific constraint (tests/App/Validator/Even) given by its FQCN in form.context.<key>.options .constraints: - ProcessConfigurationsManagerTest: built by ConstraintLoader, with and without options; - Functional/LaunchActionTest (new test.form_custom_constraint process): the violation is displayed under the field and nothing is dispatched, a valid value is dispatched. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…aunch page (process and executions lists unaffected) Review of #168: the process list resolved the UI options of every process, so one invalid "form" option broke the whole page (as the executions list, through the source/target), and each rendering triggered the deprecations of every process using the deprecated options. ProcessConfigurationsManager also grew to ~700 lines, mostly for the launch form. - New internal LaunchFormOptionsResolver: resolves the "form" UI option, checks its conflicts with the deprecated "entrypoint_type", "default" and "constraints" options, folds them into the launch form, builds the initial data of the form, and triggers the deprecations (same messages). - ProcessConfigurationsManager::getUiOptions() is back to its shape of main: "form" is accepted as is, not resolved; no deprecation is triggered. - New internal ProcessConfigurationsManager::getLaunchFormOptions(), used by LaunchAction; LaunchType receives the resolved launch form through its internal "launch_form" option (was "ui_options"). - getLaunchFormDefaults() and buildLaunchFormDefaults() are removed: the initial data is part of the resolved launch form. - Tests: the launch form tests move to LaunchFormOptionsResolverTest; the manager and Twig runtime tests are back to main (plus "form" not resolved); the process list triggers no deprecation. - Reference documentation, upgrade guide and changelog updated. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: no new public API without a caller. - ContextValueNormalizer (instantiated by LaunchAction) is @internal. - The other launch form internals are already internal since the previous commit: LaunchFormOptionsResolver, getLaunchFormOptions() and the "launch_form" option of LaunchType; getLaunchFormDefaults() and buildLaunchFormDefaults() (only used by the tests) were removed. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: the default value of an EnumType field written as a YAML scalar cannot be transformed by the field, which expects an enum case. - LaunchFormOptionsResolver: the default value of an EnumType field must be a case of the enum of options.class (a list of cases with "multiple"), otherwise an InvalidOptionsException suggests the "!php/enum" YAML tag. - The "!php/enum" tag goes through the process bundle configuration and the container: functional test with a backed enum field (pre-selected default, value of the case given to the process). - Reference documentation (default values of the fields) and changelog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: an invalid launch form configuration was only reported when the launch page was opened (500). - New internal CheckLaunchFormsPass, registered by the bundle: for each process declaring the "form" UI option, the launch form is resolved (the deprecated options folded into it) when the container is compiled; an invalid launch form fails the compilation with a message naming the process (type, forbidden options, file fields, keys, enum default, constraints, conflicts with the deprecated options). - Only the UI options are checked: the tasks and the other options of the process are not concerned. A process without "form" is not checked (no BC break), a launch form using an environment variable is left to the launch page, and the parameters are resolved. The deprecations stay triggered on the launch page only. - The options of the form types themselves are still resolved by the form factory when the form is built, and the submitted values are converted after the submission. - Tests: the pass and its registration; the tests booting the test kernel declare the classes used at compile time (strict coverage metadata). - Reference documentation and changelog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tead of a 500 Review of #168: a value that cannot be converted into a process value was raised as a LogicException (500) after the user filled and submitted the form. - LaunchAction converts the input and the context before saving the uploaded file and dispatching; a value that cannot be converted is reported as an error of its field (the input, a declared context field, or the free context pairs), the form is displayed again and nothing is dispatched. - The message of ContextValueNormalizer names a ChoiceType instead of the removed "choice" alias. - Functional tests for the input and a context field; reference documentation and changelog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…tainer is built The compiler pass only checks the structure of the launch forms: the services (form types, type extensions, constraint validators) do not exist yet when the container is compiled. The options of the form types, the default values and the constraint validators were still only checked on the launch page (500). - New internal LaunchFormsCacheWarmer, not optional: Symfony runs it after each build of the container (cache:clear, cache:warmup, and the automatic rebuild in debug mode). For each process declaring the "form" UI option, it builds the launch form with the form factory of the application (form type options and type extensions, "constraints" option), sets its default values (transformed by the fields), and resolves the validator of each constraint, nested constraints included (Collection, All...). An invalid launch form fails with a message naming the process. - Registered without explicit tag nor arguments: config/services/ cache_warmer.yaml loads src/CacheWarmer/ with autowire and autoconfigure (kernel.cache_warmer tag from FrameworkBundle), #[Autowire] for the process configurations manager and the (optional) validator factory. - Tests: the warmer (valid forms, unknown or invalid form type options, default value that cannot be transformed, missing validators, without validator), its run with the container of the test application; the tests booting the test kernel declare the classes used by the warmer. - Reference documentation and changelog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: the declared context fields followed the Symfony default (required: true), so a CheckboxType had to be checked (the dry_run example of #160 needed an explicit required: false). - LaunchType: the declared context fields are not required by default, an explicit "required" option of the field takes precedence (the input is still required when the process defines an entry_point). - A select that is not required has an empty choice: the Delimiter examples (reference, cookbook, upgrade guide) set required: true. - Tests, reference documentation and changelog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
Review of #168: the entry was a single ~2000-character paragraph. It is split into bullets, and only describes the scope of #160. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…aunchFormsCacheWarmer LaunchFormsCacheWarmer runs after each build of the container and resolves each launch form (same structural checks as the compiler pass: types, keys, file fields, enum defaults, constraints, conflicts with the deprecated options) before building it with the form factory of the application: the compiler pass is redundant. - Remove CheckLaunchFormsPass, its registration and its tests, and the metadata of the tests booting the test kernel. - LaunchFormsCacheWarmer docblock, reference documentation and changelog. Co-Authored-By: Claude Opus 5.5 <[email protected]>
318365c to
8883fe1
Compare
| @@ -0,0 +1,5 @@ | |||
| services: | |||
There was a problem hiding this comment.
According to symfony best pratices for bundles, services should not use autowiring or autoconfiguration. Instead, all services should be defined explicitly.
Description
Implements #160 (rebased on
main): the process configuration has full control over the UI launch form (ui_launch_mode: form). For theinputfield and each context key, it declares the form type (FQCN), its options (with the field constraints) and its default value. Example: thedelimitercontext value becomes a "Delimiter" select instead of two free text inputs.The data of the form keeps its shape (
{input, context: {key => value}}), so the dispatched message is unchanged.Changes
formUI option:form.input/form.context.<key>:type(FQCN of a form type, not a button),options(withconstraints, same syntax as the global constraints),default;EnumTypedefault is an enum case (!php/enum);form.allow_extra_context(defaulttrue). A free pair whose key is a declared field is a validation error (reserved_keysoption ofProcessContextType).ContextValueNormalizer). A value that cannot be converted is reported as an error of its field.LaunchFormOptionsResolver(ProcessConfigurationsManager::getLaunchFormOptions()), only on the launch page;getUiOptions()keeps its 3.2 shape: the process list and the executions list do not depend on the launch form, and trigger no deprecation.LaunchFormsCacheWarmer, not optional, also run on the automatic rebuild in debug mode): each launch form is resolved, then built with the form factory of the application (form type options and type extensions, default values, constraint validators). An invalid launch form failscache:clearwith a message naming the process.entrypoint_type→form.input.type,default→form.*.default,constraints→form.constraints.form, and mixing a deprecated option with its replacement is refused.02-process_ui_options.md), cookbook (form_file_upload.md), upgrade guide, changelog.Tests
PHPUnit (also with pcov and strict coverage metadata, as in the CI), PHPStan level 10, PHP-CS-Fixer, Rector, twig-cs-fixer: OK.
Breaking changes
None for a configuration that keeps working with the deprecated options (minor, 3.3). See
UPGRADE.md:launch[context][extra][<index>], ascontextis now a compoundFormType(form theme blocks_launch_context_extra_entry_*);default.contextkeys are merged (the last one wins).🤖 Generated with Claude Code