diff --git a/development/components/form/_index.md b/development/components/form/_index.md index 9a089bc936..e3f68e5389 100644 --- a/development/components/form/_index.md +++ b/development/components/form/_index.md @@ -1,8 +1,276 @@ --- -title: The Form component +title: Forms with Symfony menuTitle: Form +useMermaid: true --- -# The Form component +# Forms with Symfony -{{% children /%}} +## Introduction + +Symfony's `Forms` system separates the construction, rendering, and processing of forms. This involves multiple key concepts, including form creation, data provision, validation, data persistence from submitted forms, and form rendering. + +- [`Controllers`](#controllers) - Handles all logic for the `Form` +- [`FormBuilder`](#form-builder) - Builds the `Form`, and provide data to the `Form` + - [`FormDataProvider`](#form-data-provider) - Provides data to the `Form` +- [`Form`](#form-types) - Defines the `Form` and its content +- [`Form Theme`](#form-theme) - Allows to customise the style of the `Form` +- `Form Templates` - Allows to render the `Form` with `Twig` +- [`FormHandler`](#form-handler) - Handles the submited `Form`, provides data to the `FormDataHandler`, and handles `FormHandlerResult` + - [`FormDataHandler`](#form-handler) - Persists the data to `Database` + +
+graph + AA(Http Request)-.->A + subgraph Core + subgraph Admin Theme + K(Form Theme) + end + subgraph Render form + A(Controller)-->O(FormBuilder) + O-->|1|M(FormDataProvider) + M-->|2|O + O-->|3|P(Form) + P-->F(Rendered Form) + K-->F + A-->Q(Form Templates) + Q-->F + end + subgraph Handle form + F -- Submit -->G(Controller) + G-->H(FormHandler) + H-->|Persist|Z(FormDataHandler) + end + end + G-.->ZZ(Redirect) + style F fill:#f9f,stroke:#333,stroke-width:2px + style Core fill:#fbfbea +
+ +### Controllers + +`Controllers` in the back office receive HTTP requests. When handling requests for creating or editing an entity, they instantiate and utilize several concepts. + +### FormBuilder + +In most scenarios, the Controller initially instantiates the FormBuilder. This component constructs the necessary Form, incorporating all Form Types. It also retrieves data from the FormDataProvider, ensuring that the form is populated with the appropriate data. +The `FormBuilder` will build the required `Form` with all `Form Types`, and retrieve data from the `FormDataProvider`. + +### FormDataProvider + +The FormDataProvider is responsible for retrieving data from the Database. This data is used to populate the form when editing an existing entity. Additionally, it provides default values for the form fields, both when creating a new entity and when editing an existing one. + +### Form Types + +Developers have access to a wide range of field types ([see Symfony types](https://symfony.com/doc/4.4/reference/forms/types.html)) that come from the Symfony framework. Additionally, PrestaShop enhances this selection with its own reusable field types. + +A complete reference of PrestaShop form types can be found [here]({{< relref "/8/development/components/form/types-reference">}}). + +### FormHandler + +The `FormHandler` is responsible of: + +- extracting the form data, +- triggering the `actionBeforeCreateFormHandler`, `actionBeforeUpdateFormHandler`, `actionAfterCreateFormHandler` and `actionAfterUpdateFormHandler` hooks +- calling the `FormDataHandler` +- returning a `FormHandlerResult` + +### FormDataHandler + +The `FormDataHandler` is tasked with persisting data to the Database. It accomplishes this by dispatching a CQRS command to the command bus, ensuring efficient and effective data handling. + +{{% notice note %}} +This page focuses on migrated Forms utilizing Symfony and the CQRS pattern. + +It's important to note that data can be persisted in several ways, including: [Doctrine entities]({{}}), using [ObjectModel entities]({{}}), or using [CQRS concepts]({{}}). +{{% /notice %}} + +### Form Theme + +To render forms in a clean and user-friendly way, PrestaShop extended Symfony's [Bootstrap 4 Form Theme][sf-bootstrap4-form-theme] to create **PrestaShop UI Kit Form theme**. Learn more on [Symfony Form theme for PrestaShop]({{< relref "/8/development/components/form/form-theme/form-theme">}}) + +## Customize forms by modules + +### Concepts + +- `FormModifier`: This component is used to modify the Form, primarily for module integration. +- `FormModifier` hook_: Connects the FormModifier to the form, enabling modifications. +- `FormDataProviderData` hook: Facilitates the provision of specific data to the form. +- `FormDataProviderDefaultData` hook: Used for supplying default data to the form. +- `FormHandler hook`: Allows the module to handle the form and its data effectively. + +
+graph + AA(Http Request)-.->A + subgraph Core + subgraph Admin Theme + K(Form Theme) + end + subgraph Render Form + A(Controller)-->O(FormBuilder) + O-->|1|M(FormDataProvider) + M-->|2|O + O-->|3|P(Form) + P-->F(Rendered Form) + K-->F + A-->Q(Form Templates) + Q-->F + end + subgraph Handle Form + F -- Submit -->G(Controller) + G-->H(FormHandler) + H-->|"Persist"|Z(FormDataHandler) + end + end + subgraph Module + I(FormModifier) -->S(FormModifier hook) + S -.-> O + H -.-> J(FormHandler hooks) + T(FormDataProviderDefaultData hook) -.-> M + U(FormDataProviderData hook) -.-> M + end + G-.->ZZ(Redirect) + style F fill:#f9f,stroke:#333,stroke-width:2px + style Module fill:#dcedfc + style Core fill:#fbfbea +
+ +### FormModifier + +A `FormModifier` (also known as `FormBuilderModifier`) allows you to alter the contents of a Form. It is particularly useful within modules, allowing developers to add, modify, or remove elements from the form as required. + +It's been implemented in an example module: [DemoProductForm2](https://github.com/PrestaShop/example-modules/blob/master/demoproductform2/src/Form/Modifier/ProductFormModifier.php). + +```php +namespace PrestaShop\Module\DemoProductForm\Form\Modifier; +[...] + +final class ProductFormModifier +{ + public function __construct( + private readonly TranslatorInterface $translator, + private readonly FormBuilderModifier $formBuilderModifier + ) { + } + + public function modify( + ?ProductId $productId, + FormBuilderInterface $productFormBuilder + ): void { + [...] + } +``` + +```yml +services: + PrestaShop\Module\DemoProductForm\Form\Modifier\ProductFormModifier: + autowire: true + public: true + arguments: + $formBuilderModifier: '@form.form_builder_modifier' +``` + +#### FormModifier hook + +A `FormModifier` by itself will not affect a `Form` unless it is properly hooked. To ensure functionality, the `FormModifier` must be linked by implementing the [actionFormBuilderModifier]({{FormBuilderModifier">}}). + +In the module, register the hook and implement the method, for example, for the `Product` entity: + +```php +public function install() +{ + $this->registerHook('actionProductFormBuilderModifier'); +} + +public function hookActionProductFormBuilderModifier(array $params): void +{ + /** @var ProductFormModifier $productFormModifier */ + $productFormModifier = $this->get(ProductFormModifier::class); + $productId = isset($params['id']) ? new ProductId((int) $params['id']) : null; + + $productFormModifier->modify($productId, $params['form_builder']); +} +``` + +### FormDataProviderDefaultData Hook + +The [`ActionFormDataProviderDefaultData` hook]({{FormDataProviderDefaultData">}}) allows your module to provide or modify the default values sent to forms. + +```php +public function install() +{ + $this->registerHook('actionProductFormDataProviderDefaultData'); +} + +public function hookActionProductFormDataProviderDefaultData(array $params): void +{ + // define default values for fields in $params["data"] +} +``` + +This hook has been implemented as an example in our [example-modules repository](https://github.com/PrestaShop/example-modules/tree/master/demoformdataproviders). + +### FormDataProviderData Hook + +The [`ActionFormDataProviderData` hook]({{FormDataProviderData">}}) allows your module to provide or modify the values sent to forms. + +```php +public function install() +{ + $this->registerHook('actionProductFormDataProviderData'); +} + +public function hookActionProductFormDataProviderData(array $params): void +{ + // change value of fields in $params["data"] +} +``` + +This hook has been implemented as an example in our [example-modules repository - demoformdataproviders](https://github.com/PrestaShop/example-modules/tree/master/demoformdataproviders). + +### FormHandler hook + +The `FormHandler` hook is designed to intercept `Form` data, enabling the execution of various operations with this data. Its primary function is to facilitate the persistence of form data, ensuring that the data captured by the form can be effectively processed and stored later. + +There are 4 hooks available to work with the `Form` data: + +| Hook | Description | +| --- | --- | +| `actionBeforeCreateFormHandler` | Triggered on **creation** of an IdentifiableObject, **before** persisting it to Database | +| `actionBeforeUpdateFormHandler` | Triggered on **update** of an IdentifiableObject, **before** persisting it to Database | +| `actionAfterCreateFormHandler` | Triggered on **creation** of an IdentifiableObject, **after** persisting it to Database | +| `actionAfterUpdateFormHandler` | Triggered on **update** of an IdentifiableObject, **after** persisting it to Database | + +
+graph TD + subgraph "Update" + BA(actionBeforeUpdateFormNameFormHandler) --> BB(IdentifiableObject updated) + BB --> BC(actionAfterUpdateFormNameFormHandler) + end + subgraph "Create" + A(actionBeforeCreateFormNameFormHandler) --> B(IdentifiableObject created) + B --> C(actionAfterCreateFormNameFormHandler) + end +
+ +It as been implemented in an example module: [DemoProductForm](https://github.com/PrestaShop/example-modules/blob/master/demoproductform/demoproductform.php). + +```php +public function hookActionAfterUpdateCombinationFormFormHandler(array $params): void +{ + $combinationId = $params['form_data']['id']; + [...] +} +``` + +## Examples + +You can find some examples of how to use forms in your modules to extend PrestaShop capabilities: + +| Subject | Link | +| --- | --- | +| Extend a Symfony form in a module with an upload field for image | [Tutorial]({{}}) | +| How to extend the new product page form | [Tutorial]({{}}) | +| How to modify Customers grid | [Tutorial]({{}}) | + +[sf-bootstrap4-form-theme]: https://symfony.com/doc/4.4/form/bootstrap4.html diff --git a/development/components/form/form-theme/form-pages.md b/development/components/form/form-theme/form-pages.md index b65af7a3c3..32869aac93 100644 --- a/development/components/form/form-theme/form-pages.md +++ b/development/components/form/form-theme/form-pages.md @@ -1,9 +1,9 @@ --- -title: List of forms +title: List of migrated forms weight: 20 --- -# List of forms +# List of migrated forms This section states when a page that contains a Symfony form has been migrated to Symfony, and when the form has been simplified to rely on the PrestaShop UI Kit Form theme. @@ -11,7 +11,6 @@ You can find the detailed status of the project on the [GitHub tracking issue][f [form-theme-simplification-project]: https://github.com/PrestaShop/PrestaShop/issues/16482 - Page | Migrated in version | Form simplified in version --------------------------|:-------------------------:|:-----------------------------: **Advanced Parameters** | | @@ -25,9 +24,9 @@ Advanced Parameters > Webservice | 1.7.5 | Advanced Parameters > Webservice > Add new webservice key | 1.7.6 | 1.7.8 Advanced Parameters > Email | 1.7.5 | 1.7.8 Advanced Parameters > Database > SQL Manager | 1.7.5 | 1.7.8 -Advanced Parameters > Team > Employees | 1.7.6 | 8.0 -Advanced Parameters > Team > Employees > Add new employee | 1.7.6 | 8.0 -Advanced Parameters > Team > Employees > Profiles > Add new profile | 1.7.6 | 8.0 +Advanced Parameters > Team > Employees | 1.7.6 | 8.1 +Advanced Parameters > Team > Employees > Add new employee | 1.7.6 | 8.1 +Advanced Parameters > Team > Employees > Profiles > Add new profile | 1.7.6 | 8.1 Advanced Parameters > Team > Employees > Permissions | | Advanced Parameters > Multistore > Add new / edit shop group | | Advanced Parameters > Multistore > Add a new shop | | @@ -59,7 +58,7 @@ Shop parameters > Search > Search > Add new / edit alias | | Shop parameters > Search > Tags > Add new / edit tag | | | | **Catalog** | | -Orders > Invoices | 1.7.5 | 8.0 +Orders > Invoices | 1.7.5 | Orders > Delivery Slips | 1.7.5 | 8.0 Orders > Credit Slips | 1.7.7 | 1.7.8 Shipping > Preferences | 1.7.5 | 1.7.8 @@ -74,7 +73,7 @@ Catalog > Attributes & Features > Add new / edit attribute | | Catalog > Attributes & Features > Add new / edit attribute value | | Catalog > Discounts > Cart rules > Add new / edit catalog price rule | | Catalog > Discounts > Cart rules > Add new / edit cart rule | | -Payment > Preferences | 1.7.5 | 8.0 +Payment > Preferences | 1.7.5 | Customers > Addresses | 1.7.7 | 1.7.8 Customers > Addresses > Add new / edit address | 1.7.7 | 1.7.8 Customers > Customers | 1.7.6 | 1.7.8 @@ -82,7 +81,7 @@ Customers > Customers > View customer | 1.7.6 | Customers > Customers > Add new / edit customer | 1.7.6 | 1.7.8 Customer Service > Order Messages > Add new / edit order message | 1.7.7 | 1.7.8 Customer Service > Customer Service | | -Customer Service > Merchandise Returns > Edit | 8.0 | 8.0 +Customer Service > Merchandise Returns > Edit | 8.0 | | | **Improve** | | Design > Theme & Logo > Add new theme | 1.7.6 | 1.7.8 @@ -106,4 +105,3 @@ International > Taxes > Taxes | 1.7.6 | International > Taxes > Taxes > Add new / edit tax | 1.7.6 | 1.7.8 International > Taxes > Tax Rules | | International > Taxes > Tax Rules > Add new / edit tax rule group | | - diff --git a/modules/concepts/hooks/list-of-hooks/actionFormDataProviderData.md b/modules/concepts/hooks/list-of-hooks/actionFormDataProviderData.md index fad7566591..2f29280d22 100644 --- a/modules/concepts/hooks/list-of-hooks/actionFormDataProviderData.md +++ b/modules/concepts/hooks/list-of-hooks/actionFormDataProviderData.md @@ -16,7 +16,6 @@ check_exceptions: false chain: false origin: core description: '' - --- {{% hookDescriptor %}} @@ -33,3 +32,7 @@ $this->hookDispatcher->dispatchWithParameters( ] ); ``` + +## Example implementation + +This hook has been implemented as an example in our [example-modules repository](https://github.com/PrestaShop/example-modules/tree/master/demoformdataproviders). diff --git a/modules/concepts/hooks/list-of-hooks/actionFormDataProviderDefaultData.md b/modules/concepts/hooks/list-of-hooks/actionFormDataProviderDefaultData.md index a57e5dc341..184717556e 100644 --- a/modules/concepts/hooks/list-of-hooks/actionFormDataProviderDefaultData.md +++ b/modules/concepts/hooks/list-of-hooks/actionFormDataProviderDefaultData.md @@ -15,7 +15,6 @@ check_exceptions: false chain: false origin: core description: '' - --- {{% hookDescriptor %}} @@ -31,3 +30,7 @@ dispatchWithParameters( ] ) ``` + +## Example implementation + +This hook has been implemented as an example in our [example-modules repository](https://github.com/PrestaShop/example-modules/tree/master/demoformdataproviders). diff --git a/modules/sample-modules/extending-sf-form-with-upload-image-field.md b/modules/sample-modules/extending-sf-form-with-upload-image-field.md index daf9c43255..81096f71a0 100644 --- a/modules/sample-modules/extending-sf-form-with-upload-image-field.md +++ b/modules/sample-modules/extending-sf-form-with-upload-image-field.md @@ -6,7 +6,6 @@ weight: 3 # Extending Symfony form with upload image field {{< minver v="1.7.7" title="true" >}} - ## Introduction In this tutorial we are going to build a module which extends `Suppliers` form @@ -80,7 +79,6 @@ declare(strict_types=1); namespace PrestaShop\Module\DemoExtendSymfonyForm\Install; - use Db; use Module; @@ -196,6 +194,10 @@ below to `DemoExtendSymfonyForm2` class. ```php }}) - which is available for PrestaShop modules since version 1.7.6. +Let's create `SupplierExtraImage` entity class. We use [Doctrine]({{< relref "/8/modules/concepts/doctrine/" >}}) which is available for PrestaShop modules since version 1.7.6. ```php }}) in -PrestaShop Symfony pages. +Let's create hook `hookActionSupplierFormBuilderModifier` function inside Main module class. +This is a hook available for [CRUD forms]({{< relref "/8/modules/sample-modules/grid-and-identifiable-object-form-hooks-usage" >}}) in PrestaShop Symfony pages. ```php