Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
bd7f350
#160 - Full control over the launch form fields (type, options, const…
clever-age-gtonon Oct 15, 2026
629709f
#160 - execution_user changes must have it's own issue
clever-age-gtonon Oct 16, 2026
92f63be
Revert "#160 - execution_user changes must have it's own issue"
clever-age-gtonon Oct 16, 2026
a5e397a
#160 - Revert: execution_user is no longer forced to the connected us…
clever-age-gtonon Oct 16, 2026
eba7505
#160 - Revert: no format rule on the keys of the free context pairs a…
clever-age-gtonon Oct 16, 2026
f299867
#160 - Revert: ProcessConfigurationsManager resolves the ui, notifica…
clever-age-gtonon Oct 16, 2026
399d67b
#160 - Form types are given by their FQCN only, drop symfony/doctrine…
clever-age-gtonon Oct 16, 2026
1a2e51d
#160 - Test a field constraint given by its FQCN
clever-age-gtonon Oct 16, 2026
ef621a2
#160 - Resolve the launch form in an internal resolver, only on the l…
clever-age-gtonon Oct 16, 2026
b66b4b4
#160 - Mark ContextValueNormalizer @internal
clever-age-gtonon Oct 16, 2026
6918572
#160 - Refuse a scalar default on an enum field, document !php/enum
clever-age-gtonon Oct 16, 2026
505f7e5
#160 - Check the form UI option at compile time
clever-age-gtonon Oct 16, 2026
e63af6a
#160 - Report a non-convertible launch form value as a form error ins…
clever-age-gtonon Oct 16, 2026
eef9ada
#160 - Check the launch forms with the form factory each time the con…
clever-age-gtonon Oct 16, 2026
cdc331b
#160 - Declared context fields are not required by default
clever-age-gtonon Oct 16, 2026
728d066
#160 - Split the CHANGELOG entry into bullets
clever-age-gtonon Oct 16, 2026
8883fe1
#160 - Remove CheckLaunchFormsPass: the launch forms are checked by L…
clever-age-gtonon Oct 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ Latest
* [#172](https://github.com/cleverage/ui-process-bundle/issues/172) Prefix the route names of the bundle with `cleverage_ui_process_`, as required by the Symfony best practices for bundles: `cleverage_ui_process_login`, `cleverage_ui_process_logout`, `cleverage_ui_process_list`, `cleverage_ui_process_launch`, `cleverage_ui_process_http_execute`, and the dashboard `cleverage_ui_process`, so that the routes generated by EasyAdmin for the CRUD pages are `cleverage_ui_process_<crud>_<action>`. The former names (`process`, `process_<crud>_<action>`, `process_login`, `process_logout`, `process_list`, `process_launch`, `http_process_execute`) are deprecated route aliases (new `config/routes/deprecated_aliases.yaml`, loaded by the documented import, and internal `DeprecatedEasyAdminRouteAliasLoader` for the routes generated by EasyAdmin), removed in 4.0; `?routeName=<former name>` URLs keep working. Document that `easyadmin.routes` generates the routes of every dashboard. Update documentation and UPGRADE.md, add tests.
* [#166](https://github.com/cleverage/ui-process-bundle/issues/166) Doctrine ORM 2: the entities have readonly properties (since v3.2), which the legacy proxies of ORM 2 cannot handle (`Cannot unset readonly property ... from scope Proxies\__CG__\...` when an entity proxy is loaded). The container compilation now fails with an explicit message when ORM 2 is used without `doctrine.orm.enable_lazy_ghost_objects: true` (new internal `CheckDoctrineLazyGhostObjectsPass`); nothing changes with ORM 3. Update documentation, add tests.
* [#164](https://github.com/cleverage/ui-process-bundle/issues/164) Require `symfony/polyfill-php83`, `symfony/polyfill-php84` and `symfony/polyfill-php85`: the functions of PHP 8.3 to 8.5 (`json_validate()`, `array_find()`, `array_first()`...) can be used while supporting PHP 8.2 (see `CONTRIBUTING.md`). Rector is configured for PHP 8.2 (was 8.5, which allowed it to introduce PHP 8.3+ functions without polyfill) with the `PHP_POLYFILLS` set (`withPhpSets()` without argument), it does not change the code. `array_last()` replaces `end()` in a test. Tests: lazy ghost proxies with Doctrine ORM 2 (now installed by the lowest dependencies job), as configured by the Symfony recipe: the legacy proxies cannot unset the readonly properties of the entities.
* [#160](https://github.com/cleverage/ui-process-bundle/issues/160) Launch form: full control over the fields of the launch form through the new `form` UI option.
* `form.input` and `form.context.<key>`: `type` (the FQCN of a form type), `options` (the form type options, with `constraints`) and `default` (the initial value; an enum case given with `!php/enum` for an `EnumType`). The declared context fields are not required by default.
* `form.allow_extra_context` (default `true`): free key/value context pairs for the undeclared keys. A free pair whose key is a declared field is reported as a validation error (new `reserved_keys` option of `ProcessContextType`).
* `form.constraints`: the constraints of the whole form.
* The typed values of the form are converted into process values after the validation (enums, dates, date intervals, `Stringable` objects); a value that cannot be converted is reported as an error of its field.
* The launch forms are checked each time the container is built (internal `LaunchFormsCacheWarmer`): they are resolved, then built with the form factory of the application (form type options, default values, constraint validators).
* The `form` option is only resolved by the launch page (internal `ProcessConfigurationsManager::getLaunchFormOptions()` and `LaunchFormOptionsResolver`): `getUiOptions()` does not resolve it, the process list and the executions list do not depend on the launch form.
* The free context pairs of the launch form are named `launch[context][extra][<index>][key|value]` (was `launch[context][<index>][key|value]`): the `context` child of `LaunchType` is a compound `FormType` (form theme blocks `_launch_context_extra_entry_*`). The duplicated keys of `default.context` are merged (the last one wins).
* Deprecate the `entrypoint_type` (use `form.input.type`), `default` (use `form.input.default` and `form.context.<key>.default`) and `constraints` (use `form.constraints`) UI options, folded into `form` until 4.0; their deprecation is triggered each time the launch form of such a process is displayed.
* Add documentation, an upgrade guide and tests.
* [#158](https://github.com/cleverage/ui-process-bundle/issues/158) CI: test the lowest versions allowed by `composer.json` (`--prefer-lowest`, PHP 8.2). Require `symfony/scheduler` ^6.4.44 || ^7.4.17 || ^8.1.5: the `every` expressions validation (`EveryExpressionValidator`) relies on the `PeriodicalTrigger` rejecting the intervals that do not move the run date forward or resolve to zero seconds (older versions loop forever on e.g. "yesterday", and fail with a `TypeError` on an invalid expression). `ProcessExecutionDurationFilter`: the number of seconds is cast to an integer and inlined in the DQL instead of being bound as a parameter (#111): with DBAL 3, the SQLite platform puts the `SECOND` intervals inside a string literal, so the parameter was never bound ("column index out of range" error on SQLite with DBAL 3).
* [#156](https://github.com/cleverage/ui-process-bundle/issues/156) `LogRecord::contextIsEmpty()` (deprecated since v3.1, use `hasContextInfo()`) triggers a deprecation at runtime with `trigger_deprecation()` (`symfony/deprecation-contracts`, now required). Add tests.
* [#154](https://github.com/cleverage/ui-process-bundle/issues/154) Add a `.gitattributes`: the development files (`.docker/`, `.github/`, `tests/`, quality tools and PHPUnit configurations, `Makefile`) are no longer part of the archive installed by Composer (`dist`), remove the unused `package.json` (Webpack Encore leftover of the Symfony skeleton: no `webpack.config.js`, no `assets/`).
Expand Down
68 changes: 68 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,74 @@ The routes of the bundle are prefixed with `cleverage_ui_process_`. The former n
The routes of the CRUD pages are generated by EasyAdmin from the dashboard route name, e.g.
`process_process_execution_index` is now `cleverage_ui_process_process_execution_index`.

### Deprecated UI options of the launch form

The `entrypoint_type`, `default` and `constraints` UI options are deprecated in favor of the new `form` option (see
[process UI options](docs/reference/02-process_ui_options.md#form-fields)), and will be removed in 4.0:

| Deprecated option | Replacement |
|---------------------|-----------------------------------------------------------------------------------|
| `entrypoint_type` | `form.input.type` |
| `default.input` | `form.input.default` |
| `default.context` | `form.context.<key>.default` (or a free pair with `form.allow_extra_context`) |
| `constraints` | `form.constraints` |

```yaml
# Before (3.2)
options:
ui:
ui_launch_mode: form
entrypoint_type: file
default:
context:
- key: delimiter
value: ','
constraints:
- Collection:
fields:
input:
- File: { extensions: [csv] }
context:
- Collection:
fields:
delimiter:
- Choice: { choices: [',', ';'] }

# After (3.3)
options:
ui:
ui_launch_mode: form
form:
input:
type: Symfony\Component\Form\Extension\Core\Type\FileType
options:
constraints:
- File:
# A CSV file is often detected as "text/plain" (semicolon delimiter, few lines): allow it explicitly
extensions:
csv: ['text/csv', 'text/plain', 'application/csv', 'text/x-csv', 'text/x-comma-separated-values']
context:
delimiter:
type: Symfony\Component\Form\Extension\Core\Type\ChoiceType
default: ','
options:
choices: { 'Comma (,)': ',', 'Semicolon (;)': ';' }
required: true
```

- Mixing a deprecated option and its replacement (e.g. `entrypoint_type` and `form.input`, or `constraints` and
`form.constraints`) raises an `InvalidOptionsException`.
- The HTML names of the free context pairs of the launch form change from `launch[context][<index>][key|value]` to
`launch[context][extra][<index>][key|value]`: update the functional tests of your application that submit this
form.
- The `context` child of `LaunchType` is now a compound `FormType` (the declared fields, then the `extra`
`CollectionType` of the free pairs) instead of a `CollectionType`: update the form theme blocks of your application
(`_launch_context_entry_*` becomes `_launch_context_extra_entry_*`), the form type extensions and the code using
`$form->get('context')`.
- The duplicated keys of `default.context` are merged, the last pair wins (two pairs were displayed).
- A process using a deprecated option triggers its deprecations each time its launch form is displayed: expect them
in the deprecation logs until the process is migrated.

## v3.0

### Import routes
Expand Down
5 changes: 5 additions & 0 deletions config/services/cache_warmer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
CleverAge\UiProcessBundle\CacheWarmer\:
resource: '../../src/CacheWarmer/'
autowire: true
autoconfigure: true
59 changes: 29 additions & 30 deletions docs/cookbooks/form_file_upload.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,25 @@ clever_age_process:
source: CSV upload
target: Logs
ui_launch_mode: form
entrypoint_type: file
default:
form:
input:
type: Symfony\Component\Form\Extension\Core\Type\FileType
options:
label: CSV file
constraints:
- NotNull: ~
- File:
# A CSV file is often detected as "text/plain" (semicolon delimiter, few lines): allow it explicitly
extensions:
csv: ['text/csv', 'text/plain', 'application/csv', 'text/x-csv', 'text/x-comma-separated-values']
context:
- key: delimiter
value: ','
constraints:
- Collection:
fields:
input:
- NotNull: ~
- File:
extensions: [csv]
context:
- Collection:
fields:
delimiter:
- Choice:
choices: [',', ';']
message: 'delimiter context must be , or ;. {{ value }} given.'
delimiter:
type: Symfony\Component\Form\Extension\Core\Type\ChoiceType
default: ','
options:
label: Delimiter
choices: { 'Comma (,)': ',', 'Semicolon (;)': ';' }
required: true # a select that is not required has an empty choice
tasks:
log_file:
service: '@CleverAge\ProcessBundle\Task\Reporting\LoggerTask'
Expand All @@ -62,17 +62,16 @@ clever_age_process:
How it works:
- `ui_launch_mode: form` makes the "Launch" action of the process list open a form instead of a confirmation modal
(see [launch modes](../reference/02-process_ui_options.md#launch-modes)).
- `entrypoint_type: file` turns the `input` field into a file upload. As the process has an `entry_point`, the field
is required. The uploaded file is saved in the `upload_directory` directory and its path is sent to the
`log_file` task (see [launch form](../reference/02-process_ui_options.md#launch-form)).
- `default.context` pre-fills a `delimiter` line in the context collection
(see [default values](../reference/02-process_ui_options.md#default-values)). It is injected into the
`InputCsvReaderTask` through the `{{ delimiter }}` contextualized option, exactly like `-c delimiter:";"` on the
console.
- `constraints` validate the whole form data (`input` and `context`): the process is not queued while the file is not
a CSV or the delimiter is not `,` or `;` (see [constraints](../reference/02-process_ui_options.md#constraints)).
As the `Collection` constraint rejects extra fields, users cannot add other context values: add
`allowExtraFields: true` to allow them.
- `form.input` with a `FileType` type turns the `input` field into a file upload. As the process has an `entry_point`, the
field is required (HTML attribute); its `NotNull` and `File` constraints are checked by the server: the process is
not queued while no file is uploaded or the file is not a CSV, and the error is displayed under the field. The
uploaded file is saved in the `upload_directory` directory and its path is sent to the `log_file` task (see
[launch form](../reference/02-process_ui_options.md#launch-form)).
- `form.context.delimiter` (a `ChoiceType`) adds a `delimiter` select, pre-selected on `,`
(see [form fields](../reference/02-process_ui_options.md#form-fields)). A value outside of the choices is refused by
the field itself. The selected value is injected into the `InputCsvReaderTask` through the `{{ delimiter }}`
contextualized option, exactly like `-c delimiter:";"` on the console.
- Users can still add free key/value pairs to the context: set `form.allow_extra_context: false` to forbid them.
- On submit, a message is sent to the `execute_process` transport, so a `messenger:consume execute_process` worker
must be running (see [messenger](../reference/08-messenger.md)). The connected user email is added to the context
as `execution_user`.
Expand All @@ -92,4 +91,4 @@ curl --location 'https://your-domain.com/http/process/execute' \
--form 'context[delimiter]=";"'
```

Note that the launch form `constraints` are not applied to HTTP API calls.
Note that the launch form fields and constraints are not applied to HTTP API calls.
Loading
Loading