diff --git a/docs/administration/admin_panel/admin_panel.md b/docs/administration/admin_panel/admin_panel.md index 5d12352a0c..dc5c18cad1 100644 --- a/docs/administration/admin_panel/admin_panel.md +++ b/docs/administration/admin_panel/admin_panel.md @@ -1,14 +1,14 @@ --- -description: Ibexa DXP Back Office contains managements options for permissions, users, languages, content types, as well as system information. +description: Ibexa DXP back office contains managements options for permissions, users, languages, content types, and system information. page_type: landing_page --- # Admin panel Once you set up your environment you can start your work as an administrator. -Your most useful tools can be found in **Admin Panel**. +You can find key tools in **Admin** panel. -To access Admin Panel, click the icon: ![Admin Panel Icon](admin_panel_icon.png){.inline-image}. +To access **Admin** panel, click the icon: ![Admin panel Icon](admin_panel_icon.png){.inline-image}. [[= cards([ "administration/admin_panel/users_admin_panel", @@ -18,5 +18,5 @@ To access Admin Panel, click the icon: ![Admin Panel Icon](admin_panel_icon.png) "administration/admin_panel/segments_admin_panel", "administration/admin_panel/corporate_admin_panel", "administration/admin_panel/workflow_admin_panel", - "administration/admin_panel/system_information_admin_panel", + "administration/admin_panel/system_information_admin_panel", ], columns=4) =]] diff --git a/docs/administration/admin_panel/corporate_admin_panel.md b/docs/administration/admin_panel/corporate_admin_panel.md index 016fc60e49..702a3ed0c7 100644 --- a/docs/administration/admin_panel/corporate_admin_panel.md +++ b/docs/administration/admin_panel/corporate_admin_panel.md @@ -4,12 +4,10 @@ description: You can manage companies profiles in the Admin Panel. # Corporate -You can manage companies profiles in the Admin Panel. +You can manage companies profiles in the **Admin** panel. -There, in the **Corporate** section, you can find basic information about existing companies, -for example, details, versions, locations, translations, a list of members, billing addresses -and technical details regarding the organization, such as visibility, IDs, or relations. +There, in the **Corporate** section, you can find basic information about existing companies, for example, details, versions, locations, translations, a list of members, billing addresses, and technical details regarding the organization, such as visibility, IDs, or relations. ![Corporate section](admin_panel_corporate.png "Corporate section") -See [Customer management](https://doc.ibexa.co/projects/userguide/en/latest/customer_management/manage_customers/) for further information. \ No newline at end of file +For more information, see [Customer management](https://doc.ibexa.co/projects/userguide/en/latest/customer_management/manage_customers/). \ No newline at end of file diff --git a/docs/administration/admin_panel/languages_admin_panel.md b/docs/administration/admin_panel/languages_admin_panel.md index acf71c74f1..fd6842bf40 100644 --- a/docs/administration/admin_panel/languages_admin_panel.md +++ b/docs/administration/admin_panel/languages_admin_panel.md @@ -6,16 +6,14 @@ description: Ibexa DXP offers the ability to create multiple translations of you [[= product_name =]] offers the ability to create multiple translations of your website. Which version is shown to a visitor depends on the way your installation is set up. -A new language version for the website can be added in the [Admin Panel](admin_panel.md) in the **Languages** tab. +You can add a new language version for the website in the [Admin Panel](admin_panel.md) in the **Languages** tab. -Every new language must have a name and a language code, written in the `xxx-XX` format, for example `eng-GB` etc. +Every new language must have a name and a language code, written in the `xxx-XX` format, for example `eng-GB`. ![Languages](admin_panel_languages.png "Languages") -The multilanguage system operates based on a global translation list -that contains all languages available in the installation. +The multilanguage system operates based on a global translation list that contains all languages available in the installation. After adding a language you may have to reload the application to be able to use it. -Depending on your set up, additional configuration may be necessary -for the new language to work properly, especially with SiteAccesses. +Depending on your set up, additional configuration may be necessary for the new language to work properly, especially with SiteAccesses. See [Languages](languages.md) for further information. diff --git a/docs/administration/admin_panel/roles_admin_panel.md b/docs/administration/admin_panel/roles_admin_panel.md index 84696d375d..cf26343d98 100644 --- a/docs/administration/admin_panel/roles_admin_panel.md +++ b/docs/administration/admin_panel/roles_admin_panel.md @@ -1,43 +1,44 @@ --- -description: To give users an access to your website you need to assign them Roles in the Admin Panel. +description: To give users an access to your website you need to assign them roles in the Admin Panel. --- # Roles -To give users an access to your website you need to assign them Roles in the Admin Panel. +To give users an access to your website you need to assign them roles in the **Admin** panel. ![Roles](admin_panel_roles.png "Roles") -Each Role consists of: +Each role consists of: **Policies** ![Policies](admin_panel_policies.png "Policies") -Rules that give users access to different function in a module. -You can restrict what user can do with Limitations. -The available Limitations depend on the chosen Policy. -When Policy has more than one Limitation, all of them have to apply. +Policies are the rules that give users access to different function in a module. +You can restrict what user can do with limitations. +The available limitations depend on the chosen policy. +When policy has more than one limitation, all of them have to apply. See [example use case](permission_use_cases.md#restrict-editing-to-part-of-the-tree). !!! note - Limitation specifies what a User can do, not what they can't do. - A `Location` Limitation, for example, gives the User access to content with a specific Location, - not prohibits it. See [Limitation reference](limitation_reference.md) for further information. + Limitation specifies what a user can do, not what they can't do. + A `Location` limitation, for example, gives the user access to content with a specific location, not prohibits it. + + For more information, see [Limitation reference](limitation_reference.md). **Assignments** ![Assignments](admin_panel_assignments.png "Assignments") -After you created all Policies, you can assign the Role to Users and/or User Groups with possible additional Limitations. -Every User or User Group can have multiple Roles. -A User can also belong to many groups, for example, Administrators, Editors, Subscribers. +After you created all policies, you can assign the role to users and/or user groups with possible additional limitations. +Every user or user group can have multiple roles. +A user can also belong to many groups, for example, Administrators, Editors, Subscribers. -Best practice is to avoid assigning Roles to Users directly. -Model your content (content types, Sections, Locations etc.) in a way that can be accessed by generic Roles. -That way system will be more secure and easier to manage. -This approach also improves performance. Role assignments and Policies are taken into account during search/load queries. +Best practice is to avoid assigning roles to users directly. +Model your content (for example, content types, sections, or locations) in a way that can be accessed by generic roles. +That way system is be more secure and easier to manage. +This approach also improves performance. +Role assignments and policies are taken into account during search/load queries. -See [Permissions overview](permissions.md) for further information -and [Permission use cases](permission_use_cases.md) for details on how to customize access to different parts of the Back Office. \ No newline at end of file +For more information, see [Permissions overview](permissions.md) and [Permission use cases](permission_use_cases.md). \ No newline at end of file diff --git a/docs/administration/admin_panel/segments_admin_panel.md b/docs/administration/admin_panel/segments_admin_panel.md index ebb7da216c..a3debe34a8 100644 --- a/docs/administration/admin_panel/segments_admin_panel.md +++ b/docs/administration/admin_panel/segments_admin_panel.md @@ -1,19 +1,19 @@ --- -description: You can use Segments to display specific content to specific Users. +description: You can use segments to display specific content to specific users. edition: experience --- # Segments -You can use Segments to display specific content to specific [Users](users.md). -They are used out of the box in the Targeting and Dynamic targeting blocks in the Page. +You can use segments to display specific content to specific [users](users.md). +They're used out of the box in the Targeting and Dynamic targeting blocks in the page. -Segments are collected in Segment Groups: +You can collect segments in segment groups: -![Segment Groups](admin_panel_segment_groups.png) +![Segment groups](admin_panel_segment_groups.png) -Each Segment Group can contain Segments that you can target content for. +Each segment group can contain segments that you can target content for. ![Segment](admin_panel_segment.png) -You can assign Users to Segments [through the API](segment_api.md#assigning-users). \ No newline at end of file +You can assign users to segments [through the API](segment_api.md#assigning-users). \ No newline at end of file diff --git a/docs/administration/admin_panel/system_information_admin_panel.md b/docs/administration/admin_panel/system_information_admin_panel.md index 33a88016d9..37be8c2c22 100644 --- a/docs/administration/admin_panel/system_information_admin_panel.md +++ b/docs/administration/admin_panel/system_information_admin_panel.md @@ -4,7 +4,7 @@ description: System information provides basic system information such as versio # System Information -The System Information panel in the Back Office is sourced in the [`ibexa/system-info` repository](https://github.com/ibexa/system-info). -There you will also find basic system information such as versions of all installed packages. +The System Information panel in the back office is sourced in the [`ibexa/system-info` repository](https://github.com/ibexa/system-info). +There you can also find basic system information such as versions of all installed packages. ![System Information](admin_panel_system_info.png "System Information") diff --git a/docs/administration/admin_panel/url_management_admin_panel.md b/docs/administration/admin_panel/url_management_admin_panel.md index bbe0768b4f..1b5fd61b87 100644 --- a/docs/administration/admin_panel/url_management_admin_panel.md +++ b/docs/administration/admin_panel/url_management_admin_panel.md @@ -1,12 +1,12 @@ --- -description: URL Management let you manage external URL addresses and URL wildcards. +description: URL Management lets you manage external URL addresses and URL wildcards. --- # URL Management -You can manage external URL addresses and URL wildcards in the Admin Panel. +You can manage external URL addresses and URL wildcards in the **Admin** panel. Configure URL aliases to have human-readable URL addresses throughout your system. -See [URL management](url_management.md) for further information. +For more information, see [URL management](url_management.md). ![URL Management](admin_panel_url_management.png "URL Management") \ No newline at end of file diff --git a/docs/administration/admin_panel/users_admin_panel.md b/docs/administration/admin_panel/users_admin_panel.md index fb8f25dd0b..9190dc32a8 100644 --- a/docs/administration/admin_panel/users_admin_panel.md +++ b/docs/administration/admin_panel/users_admin_panel.md @@ -1,17 +1,16 @@ --- -description: All User Groups and Users can be accessed in the Users tab. +description: You can access all users and user groups in the Users tab. --- # Users [Users](users.md) in [[= product_name =]] are treated the same way as content items. -They are organized in groups such as *Guests*, *Editors*, *Anonymous*, -which makes it easier to manage them and their permissions. -All User Groups and Users can be accessed in the Admin panel by selecting Users. +They're organized in groups such as *Guests*, *Editors*, *Anonymous*, which makes it easier to manage them and their permissions. +You can access all users and user groups in the **Admin** panel by selecting **Users**. -![Users and User Groups](admin_panel_users.png "Users and User Groups") +![Users and user groups](admin_panel_users.png "Users and user groups") !!! caution - Be careful not to delete an existing User account. - If you do this, content created by this User will be broken and the application can face malfunction. + Be careful not to delete an existing user account. + If you do this, content created by this user can be broken and the application can face malfunction. diff --git a/docs/administration/admin_panel/workflow_admin_panel.md b/docs/administration/admin_panel/workflow_admin_panel.md index 3aed53885a..85bc924ec4 100644 --- a/docs/administration/admin_panel/workflow_admin_panel.md +++ b/docs/administration/admin_panel/workflow_admin_panel.md @@ -7,6 +7,6 @@ description: The workflow functionality passes a content item version through a The workflow functionality passes a content item version through a series of stages. Each workflow consists of stages and transitions between them. -See [Workflow](workflow.md) for further information. +For more information, see [Workflow](workflow.md). ![Workflow](admin_panel_workflow.png "Workflow") \ No newline at end of file diff --git a/docs/administration/back_office/add_user_setting.md b/docs/administration/back_office/add_user_setting.md index 0d248809c9..c994960139 100644 --- a/docs/administration/back_office/add_user_setting.md +++ b/docs/administration/back_office/add_user_setting.md @@ -4,15 +4,13 @@ description: Add the option to select a custom preference in user menu. # Add user setting -## Create new User setting +## Create new user setting -You can add new preferences to the **User Settings** menu in the Back Office. +You can add new preferences to the **User Settings** menu in the back office. -To do so, create a setting class implementing two interfaces: -`ValueDefinitionInterface` and `FormMapperInterface`. +To do so, create a setting class implementing two interfaces: `ValueDefinitionInterface` and `FormMapperInterface`. -In this example the class is located in `src/Setting/Unit.php` -and enables the user to select their preference for metric or imperial unit systems. +In this example the class is located in `src/Setting/Unit.php` and enables the user to select their preference for metric or imperial unit systems. ``` php [[= include_file('code_samples/back_office/settings/src/Setting/Unit.php') =]] @@ -24,7 +22,7 @@ Register the setting as a service: [[= include_file('code_samples/back_office/settings/config/custom_services.yaml', 0, 5) =]] ``` -You can order the settings in the User menu by setting their `priority`. +You can order the settings in the **User** menu by setting their `priority`. `group` indicates the group that the setting is placed in. It can be one of the built-in groups, or a custom one. @@ -45,8 +43,7 @@ The value of the setting is accessible with `ez_user_settings['unit']`. ## Create template for editing settings -You can override a template used when editing the new setting -under the `ibexa.system..user_settings_update_view` [configuration key](configuration.md#configuration-files): +You can override a template used when editing the new setting under the `ibexa.system..user_settings_update_view` [configuration key](configuration.md#configuration-files): ``` yaml [[= include_file('code_samples/back_office/settings/config/packages/user_settings.yaml') =]] diff --git a/docs/administration/back_office/back_office.md b/docs/administration/back_office/back_office.md index e7c92f0266..8ab3551355 100644 --- a/docs/administration/back_office/back_office.md +++ b/docs/administration/back_office/back_office.md @@ -1,24 +1,21 @@ --- -description: Back Office holds the administrator and editor interface and allows creating, publishing and managing content, users, settings and so on. +description: Back office holds the administrator and editor interface and allows creating, publishing and managing content, users, settings, and more. page_type: landing_page --- -# Back Office +# Back office -The Back Office interface is produced by the [`ibexa/admin-ui` bundle](https://github.com/ibexa/admin-ui). +The back office interface is produced by the [`ibexa/admin-ui` bundle](https://github.com/ibexa/admin-ui). Additionally, it uses React-based modules that make each part of the UI extensible, and Bootstrap for styling. The interface is accessible in your browser at `http:///admin`. -To extend the Back Office with PHP code, you can use [events]([[= symfony_doc =]]/event_dispatcher.html), -either built-in Symfony events or events dispatched by the application. +To extend the back office with PHP code, you can use [events]([[= symfony_doc =]]/event_dispatcher.html), either built-in Symfony events or events dispatched by the application. -Some extensibility, such as [adding custom tags](extend_online_editor.md#configure-custom-tags), -is possible without writing your own code, with configuration and templating only. +Some extensibility, such as [adding custom tags](extend_online_editor.md#configure-custom-tags), is possible without writing your own code, with configuration and templating only. !!! note "String translations" - Refer to [Custom string translations](back_office_translations.md#custom-string-translations) - to learn how to provide string translations when extending the Back Office. + Refer to [Custom string translations](back_office_translations.md#custom-string-translations) to learn how to provide string translations when extending the back office. [[= cards([ "administration/back_office/back_office_configuration", diff --git a/docs/administration/back_office/back_office_configuration.md b/docs/administration/back_office/back_office_configuration.md index 80ae2cfccf..58a4d3beda 100644 --- a/docs/administration/back_office/back_office_configuration.md +++ b/docs/administration/back_office/back_office_configuration.md @@ -1,13 +1,13 @@ --- -title: Back Office configuration -description: Configure default upload locations, pagination limits, and more settings for the Back Office. +title: Back office configuration +description: Configure default upload locations, pagination limits, and more settings for the back office. --- -# Back Office configuration +# Back office configuration ## Pagination limits -Default pagination limits for different sections of the Back Office can be defined through respective settings in +Default pagination limits for different sections of the back office can be defined through respective settings in [`ezplatform_default_settings.yaml`](https://github.com/ibexa/admin-ui/blob/main/src/bundle/Resources/config/ezplatform_default_settings.yaml#L7) You can set the pagination limit for user settings under the `ibexa.system..pagination_user` [configuration key](configuration.md#configuration-files): @@ -41,19 +41,15 @@ ibexa: ## Copy subtree limit -Copying large subtrees can cause performance issues, so you can limit the number of content items -that can be copied at once using the `ibexa.system..subtree_operations.copy_subtree.limit` -[configuration key](configuration.md#configuration-files). +Copying large subtrees can cause performance issues, so you can limit the number of content items that can be copied at once by setting the `ibexa.system..subtree_operations.copy_subtree.limit` [configuration key](configuration.md#configuration-files). -The default value is `100`. You can set it to `-1` for no limit, -or to `0` to completely disable copying subtrees. +The default value is `100`. You can set it to `-1` for no limit, or to `0` to completely disable copying subtrees. -You can copy subtree from CLI using the command: `bin/console ibexa:copy-subtree `. +You can copy a subtree by calling the following command in CLI: `bin/console ibexa:copy-subtree `. -## Default Locations +## Default locations -Default Location IDs for [Content structure, Media and Users](locations.md#top-level-locations) in the menu are configured -using the `ibexa.system..location_ids` [configuration key](configuration.md#configuration-files): +Default location IDs for [content structure, Media, and users](locations.md#top-level-locations) in the menu are configured with the `ibexa.system..location_ids` [configuration key](configuration.md#configuration-files): ``` yaml ibexa: diff --git a/docs/administration/back_office/back_office_elements/add_drag_and_drop.md b/docs/administration/back_office/back_office_elements/add_drag_and_drop.md index 1ff686327a..1b7ec8d1d0 100644 --- a/docs/administration/back_office/back_office_elements/add_drag_and_drop.md +++ b/docs/administration/back_office/back_office_elements/add_drag_and_drop.md @@ -1,15 +1,15 @@ --- -description: Add custom drag-and-drop interactions to Back Office interface. +description: Add custom drag-and-drop interactions to back office interface. --- # Add drag and drop -You can create a generic interface for drag and drop interactions that you can reuse in many places across the Back Office. +You can create a generic interface for drag and drop interactions that you can reuse in many places across the back office. First, prepare the HTML code structure and place it in a Twig template. See the example: ```html -
diff --git a/docs/administration/back_office/back_office_elements/add_dropdowns.md b/docs/administration/back_office/back_office_elements/add_dropdowns.md index f3a41fb513..811f3fd3b7 100644 --- a/docs/administration/back_office/back_office_elements/add_dropdowns.md +++ b/docs/administration/back_office/back_office_elements/add_dropdowns.md @@ -1,10 +1,10 @@ --- -description: Add custom drop down menus to Back Office interface. +description: Add custom drop down menus to back office interface. --- # Add drop-downs -In [[= product_name =]], you can create a reusable custom drop-down and implement it anywhere in the Back Office. +In [[= product_name =]], you can create a reusable custom drop-down and implement it anywhere in the back office. Follow the steps below to learn how to integrate this component to fit it to your project needs. ## Create `` input, for example: - + {% endset %} ``` @@ -88,7 +88,8 @@ For `value`, see the example: ## Prepare custom drop-down structure -Next, prepare the component structure and place it in the template after setting the needed attributes. See the example: +Next, prepare the component structure and place it in the template after setting the needed attributes. +See the example: ```twig {% include '@ibexadesign/ui/component/dropdown/dropdown.html.twig' with { @@ -131,7 +132,7 @@ The following attributes are available: ### Initialize All drop-downs are searched and initialized automatically in `admin.dropdown.js`. -To extend or modify the search, you need to add a `custom_init` attribute to the drop-down Twig parameters. Otherwise it will be initialized two times. +To extend or modify the search, you need to add a `custom_init` attribute to the drop-down Twig parameters. Otherwise it's initialized two times. Next, run the following JavaScript code: ```javascript diff --git a/docs/administration/back_office/back_office_elements/custom_components.md b/docs/administration/back_office/back_office_elements/custom_components.md index 8c30a31eb3..f191f0a6a9 100644 --- a/docs/administration/back_office/back_office_elements/custom_components.md +++ b/docs/administration/back_office/back_office_elements/custom_components.md @@ -1,10 +1,10 @@ --- -description: Back Office components allow you to inject any custom widgets into selected places of the user interface. +description: Back office components allow you to inject any custom widgets into selected places of the user interface. --- # Custom components -The Back Office has designated places where you can use your own components. +The back office has designated places where you can use your own components. Components enable you to inject widgets (for example, **My dashboard** blocks) and HTML code (for example, a tag for loading JS or CSS files). A component is any class that implements the `Renderable` interface. @@ -37,8 +37,7 @@ App\Component\MyNewComponent: ## Base component classes -If you only need to inject a short element (for example, a Twig template or a CSS link) without writing a class, -you can make use of the following base classes: +If you only need to inject a short element (for example, a Twig template or a CSS link) without writing a class, you can make use of the following base classes: - `TwigComponent` renders a Twig template. - `LinkComponent` renders the HTML `` tag. @@ -62,7 +61,7 @@ appbundle.components.my_twig_component: This renders the `path/to/file.html.twig` template with `first_param` and `second_param` as parameters. -With `LinkComponent` and `ScriptComponent` you provide `$href` and `$src` as arguments, respectively: +With `LinkComponent` and `ScriptComponent` you provide `$href` and `$src` as arguments: ``` yaml app.components.my_link_component: diff --git a/docs/administration/back_office/back_office_elements/custom_icons.md b/docs/administration/back_office/back_office_elements/custom_icons.md index 4903333d56..574bb31b97 100644 --- a/docs/administration/back_office/back_office_elements/custom_icons.md +++ b/docs/administration/back_office/back_office_elements/custom_icons.md @@ -6,8 +6,7 @@ description: Configure custom icons to use for content types. ## Customize content type icons -To add custom icons for existing content types or custom content types in [[= product_name =]], -use the following configuration under the `ibexa.system..content_type` [configuration key](configuration.md#configuration-files): +To add custom icons for existing content types or custom content types in [[= product_name =]], use the following configuration under the `ibexa.system..content_type` [configuration key](configuration.md#configuration-files): ```yaml ibexa: @@ -22,7 +21,7 @@ Place the icon in `public/assets/images` and run `yarn encore ` after !!! note "Icons format" - To ensure proper display in the Back Office, all icons should have SVG format with `symbol`. + To ensure proper display in the back office, all icons should have SVG format with `symbol`. If you want to configure icons per SiteAccess, see [Icon sets](#icon-sets). @@ -62,7 +61,7 @@ return ( ### Icons React component -You can use a React component to change icons in Back Office and Page Builder. +You can use a React component to change icons in back office and Page Builder. The following example from the `alert.js` file shows configuration for icons in the [alert](reusable_components.md#alerts) component: diff --git a/docs/administration/back_office/back_office_elements/extending_thumbnails.md b/docs/administration/back_office/back_office_elements/extending_thumbnails.md index dd64d21b80..9155ac153a 100644 --- a/docs/administration/back_office/back_office_elements/extending_thumbnails.md +++ b/docs/administration/back_office/back_office_elements/extending_thumbnails.md @@ -1,16 +1,16 @@ --- -description: Customize thumbnails use for content items in the Back Office. +description: Customize thumbnails use for content items in the back office. --- # Extending thumbnails -The thumbnails API enable you to easily choose an image for a specific content. -If you do not want to use custom thumbnails, `ContentType` will be used instead. +The thumbnails API enable you to choose an image for a specific content. +If you don't want to use custom thumbnails, `ContentType` is used instead. -## Thumbnail mechanism +## Thumbnail mechanism The thumbnail mechanism has two layers, and each layer can have many implementations. -The mechanism checks if any of the implementations returns a field e.g. `ezimage` that has function "Can be a thumbnail" turned on. +The mechanism checks if any of the implementations returns a field, for example, `ezimage`, that has function "Can be a thumbnail" turned on. ![Can be a thumbnail setting](extending_thumbnail_can_be.png) @@ -24,19 +24,19 @@ For example for users thumbnails can be downloaded from an avatar-generating ser For this layer there are following default implementations: -- The mechanism looks for Fields that can be thumbnail, if found, the mechanism moves to the second layer. -- If there are no Fields that can be a thumbnail, the content type icon will be used as a thumbnail. +- The mechanism looks for fields that can be thumbnail, if found, the mechanism moves to the second layer. +- If there are no fields that can be a thumbnail, the content type icon is used as a thumbnail. ### Second layer -Second layer of mechanism enables selection of thumbnail from a Field that the first layer has found. -It searches the content type for all the Fields e.g. images with function "Can be a thumbnail" turned on. +Second layer of mechanism enables selection of thumbnail from a field that the first layer has found. +It searches the content type for all the fields, for example, images, with function "Can be a thumbnail" turned on. -If there is more than one Field in the content type that can be used as a thumbnail, this layer will return the first nonempty Field as a thumbnail. +If there is more than one field in the content type that can be used as a thumbnail, this layer returns the first nonempty field as a thumbnail. -This mechanism can be modified to fit your site needs, so you can decide from where and how the thumbnails will be downloaded. +This mechanism can be modified to fit your site needs, so you can decide from where and how the thumbnails is downloaded. -### Create a thumbnail mechanism +### Create a thumbnail mechanism First, create base strategy for returning custom thumbnails from a static file. Create `StaticStrategy.php` in `src/Strategy`. @@ -46,31 +46,32 @@ Create `StaticStrategy.php` in `src/Strategy`. ``` Next, add the strategy with the `ibexa.repository.thumbnail.strategy.content` tag and `priority: 100` to `config/services.yaml`: - + ```yaml [[= include_file('code_samples/back_office/thumbnails/config/custom_services.yaml') =]] ``` -Priority `100` will allow this strategy to be used first on a clean installation or before any other strategy with lower priority. +Priority `100` allows this strategy to be used first on a clean installation or before any other strategy with lower priority. -At this point you can go to the Back Office and check the results. +At this point you can go to the back office and check the results. !!! note "Thumbnail mechanism " - This strategy overrides all generated thumbnails. You can specify a specific content type. See the example [here](https://github.com/ibexa/user/blob/main/src/lib/Strategy/DefaultThumbnailStrategy.php) + This strategy overrides all generated thumbnails. You can specify a specific content type. + See the example [here](https://github.com/ibexa/user/blob/main/src/lib/Strategy/DefaultThumbnailStrategy.php) -## Other Fields as thumbnails +## Other fields as thumbnails -Any Field Type can generate a thumbnail, e.g.: +Any field type can generate a thumbnail, for example: - DateAndTime (`ezdatetime`) - you can add a mini calendar thumbnail for Appointment content type and on the day of the appointment a clock thumbnail with a specific time when it takes place - TextBlock (`eztext`) - you can add a first letter of the text block that is inside -### Add eztext Field as thumbnail +### Add eztext field as thumbnail -First, create a strategy that will add support for `eztext` as the thumbnail. -It will enable you to add a thumbnail URL in the text field. +First, create a strategy that adds support for `eztext` as the thumbnail. +It enables you to add a thumbnail URL in the text field. Add `FieldValueUrl.php` in `src/Thumbnails`. @@ -109,5 +110,5 @@ Next, add the strategy with the `ibexa.repository.thumbnail.strategy.field` tag tags: - { name: ibexa.repository.thumbnail.strategy.field, priority: 100 } ``` - -At this point you can go to the Back Office and check the results. + +At this point you can go to the back office and check the results. diff --git a/docs/administration/back_office/back_office_elements/formatting_date_and_time.md b/docs/administration/back_office/back_office_elements/formatting_date_and_time.md index 380ab8ff93..2faff86b23 100644 --- a/docs/administration/back_office/back_office_elements/formatting_date_and_time.md +++ b/docs/administration/back_office/back_office_elements/formatting_date_and_time.md @@ -1,10 +1,12 @@ --- -description: Use different formats to render dates and times in the Back Office and website front. +description: Use different formats to render dates and times in the back office and website front. --- # Formatting date and time -## Using Twig filters and PHP services +Two methods exist that allow you to specify how the date and time should be formatted. + +## With Twig filters and PHP services You can format date and time by using the following services: @@ -54,16 +56,16 @@ class MyService Then, add the following to `config/services.yaml`: ``` yaml -services: +services: App\Service\MyService: arguments: $shortDateTimeFormatter: '@ibexa.user.settings.short_datetime_format.formatter' ``` -## Using User settings menu +## Within User settings menu -Users can set their preferred date and time formats in the User settings menu. -This format is used throughout the Back Office. +Users can set their preferred date and time formats in the user settings menu. +This format is used throughout the back office. You can set the list of available formats under the `ibexa.system..user_preferences` [configuration key](configuration.md#configuration-files): diff --git a/docs/administration/back_office/back_office_elements/importing_assets_from_bundle.md b/docs/administration/back_office/back_office_elements/importing_assets_from_bundle.md index ce61d60d8c..1b4287e39a 100644 --- a/docs/administration/back_office/back_office_elements/importing_assets_from_bundle.md +++ b/docs/administration/back_office/back_office_elements/importing_assets_from_bundle.md @@ -12,7 +12,7 @@ To import assets from a bundle, configure them in an `ibexa.config.js` file that ``` js const path = require('path'); - + module.exports = (Encore) => { Encore.addEntry('', [ path.resolve(__dirname, ''), @@ -32,12 +32,9 @@ To import CSS files only, use: After you add new files, run `php bin/console cache:clear`. - For a full example of importing asset configuration, - see [`ibexa.config.js`](https://github.com/ibexa/admin-ui/blob/main/src/bundle/Resources/encore/ibexa.config.js) + For a full example of importing asset configuration, see [`ibexa.config.js`](https://github.com/ibexa/admin-ui/blob/main/src/bundle/Resources/encore/ibexa.config.js) -To edit existing configuration entries, either in the bundle's `Resources/encore/` folder, -or in the `encore` folder in the root folder of your project, -create an `ibexa.config.manager.js` file: +To edit existing configuration entries, either in the bundle's `Resources/encore/` folder, or in the `encore` folder in the root folder of your project, create an `ibexa.config.manager.js` file: ``` js const path = require('path'); @@ -70,19 +67,16 @@ module.exports = (ibexaConfig, ibexaConfigManager) => { !!! tip - If you do not know what `entryName` to use, you can use the browser's developer tools to check what files are loaded on the given page. + If you don't know what `entryName` to use, you can use the browser's developer tools to check what files are loaded on the given page. Then, use the file name as `entryName`. !!! tip After you add new files, run `php bin/console cache:clear`. - For a full example of overriding configuration, - see [`ibexa.config.manager.js`](https://github.com/ibexa/fieldtype-matrix/blob/main/src/bundle/Resources/encore/ibexa.config.manager.js). + For a full example of overriding configuration, see [`ibexa.config.manager.js`](https://github.com/ibexa/fieldtype-matrix/blob/main/src/bundle/Resources/encore/ibexa.config.manager.js). -To add a new configuration under your own namespace and with its own dependencies, -create an `ibexa.webpack.custom.config.js` file that you create either in the bundle's `Resources/encore/` folder, -or in the `encore` folder in the root directory of your project, for example: +To add a new configuration under your own namespace and with its own dependencies, create an `ibexa.webpack.custom.config.js` file that you create either in the bundle's `Resources/encore/` folder, or in the `encore` folder in the root directory of your project, for example: ``` js const Encore = require('@symfony/webpack-encore'); @@ -103,18 +97,15 @@ or in the `encore` folder in the root directory of your project, for example: !!! tip - If you don't plan to add multiple entry files on the same page in your custom configuration, - use the `disableSingleRuntimeChunk()` function to avoid adding a separate `runtime.js` file. + If you don't plan to add multiple entry files on the same page in your custom configuration, use the `disableSingleRuntimeChunk()` function to avoid adding a separate `runtime.js` file. Otherwise, your JS code may be run multiple times. By default, the `enableSingleRuntimeChunk()` function is used. ## Configuration from main project files -If you prefer to include the asset configuration in the main project files, -add it in [`webpack.config.js`](https://github.com/ibexa/recipes/blob/master/ibexa/oss/4.0/encore/webpack.config.js#L31). +If you prefer to include the asset configuration in the main project files, add it in [`webpack.config.js`](https://github.com/ibexa/recipes/blob/master/ibexa/oss/4.0/encore/webpack.config.js#L31). -To overwrite the built-in assets, use the following configuration to replace, remove or add asset files -in `webpack.config.js`: +To overwrite the built-in assets, use the following configuration to replace, remove, or add asset files in `webpack.config.js`: ``` js ibexaConfigManager.replace({ diff --git a/docs/administration/back_office/back_office_elements/reusable_components.md b/docs/administration/back_office/back_office_elements/reusable_components.md index a704dd270a..b441fb3f09 100644 --- a/docs/administration/back_office/back_office_elements/reusable_components.md +++ b/docs/administration/back_office/back_office_elements/reusable_components.md @@ -1,10 +1,10 @@ --- -description: Speed up creating Back Office templates with the help of ready-made reusable components. +description: Speed up creating back office templates with the help of ready-made reusable components. --- # Reusable components -When you extend the Back Office, you can use base Twig templates for commonly used UI components such as tables or tabs. +When you extend the back office, you can use base Twig templates for commonly used UI components such as tables or tabs. The available templates are: @@ -19,9 +19,9 @@ With `embed` you can override blocks that are defined inside the included templa The alert component has the following properties: -- `type` - available types of alert: error, info, success and warning +- `type` - available types of alert: error, info, success, and warning - `icon` - name of the icon, taken from the default icon set -- `icon_path` - full icon path, in case you do not want to use an icon from the default icon set +- `icon_path` - full icon path, in case you don't want to use an icon from the default icon set - `title` - alert title - `subtitle` - displays subtitle content - `show_subtitle_below` - default set to `false`, the subtitle is displayed next to the title @@ -53,12 +53,12 @@ Variables: |Name|Type|Values| |----|----|-----------| -|`headline` (optional)|string|if not specified, the header is not rendered| +|`headline` (optional)|string|if not specified, the header isn't rendered| |`headline_items`|array| |`view_mode`|string|`vertical`, default set to `''`| |`items`|hash|{`label`, `content_raw`, `content`}| -If `headline` is not specified, the `headline_items` is not rendered. +If `headline` isn't specified, the `headline_items` isn't rendered. ## Modal @@ -80,7 +80,7 @@ Variables: |Name|Type|Values| |----|----|-----------| |`size`|string|`small`, `large`, `extra-large`, default set to: `''`| -|`subtitle`|string|no default value, if not defined, the `subheader` is not rendered| +|`subtitle`|string|no default value, if not defined, the `subheader` isn't rendered| |`no_header`|boolean|default set to `false`| |`no_header_border`|boolean|default set to `false`| |`class`|string|default `''`| @@ -208,16 +208,16 @@ The following example shows how to render both text and hyperlink which redirect See the example below to learn how to create an action button which removes the article in the table. The table component has to be wrapped into the remove article form. -As in many cases you want a button to be disabled when no item in a table is selected and enabled otherwise, there is a built-in mechanism for this. +As in many cases you want a button to be disabled when no item in a table is selected and enabled otherwise, there is a built-in mechanism for this. To enable it you need to add the `ibexa-toggle-btn-state` CSS class to the form element alongside `data-toggle-button-id` data-attribute which holds the id of the button that should be enabled/disabled after a checkbox state change. Next, pass a button under the `action` parameter to the table headline. -Action buttons are rendered on the right side of the table headline (do not confuse it with the table header). -You can also specify headline text, which is a table title displayed above, by passing it under `headline` parameter. +Action buttons are rendered on the right side of the table headline (don't confuse it with the table header). +You can also specify headline text, which is a table title displayed above, by passing it under `headline` parameter. -You can generate various headline texts using the `results_headline` macro with a few parameters: +You can generate various headline texts by using the `results_headline` macro with a few parameters: - `count` - of all results, not only displayed on the first page - `has_filters` - when using filters @@ -230,10 +230,10 @@ Column types available for the table header : - normal content column `{ content: col_name }` (content is the title of the column) - icon column `{ has_icon: true }` - checkbox column `{ has_checkbox: true }` -- action buttons column `{ }` +- action buttons column `{ }` Additional parameters available for all of the objects mentioned earlier: - + - class (CSS class) - attr (HTML attributes) @@ -284,7 +284,7 @@ Other table component parameters include: - `attr` - (other HTML attributes applied on the HTML table element), for example: - `attr: { 'data-some-data-attribute-you-need': 'foo' }` - `table_body_class` and `table_body_attr` are the same as mentioned earlier, but applied on the table element -- `show_head_cols_if_empty` - (default: `false`), by default, when `body_rows` is empty, the table component does not show the table header, but you may want to have it because for example rows are rendered dynamically with JavaScript on the browser side. +- `show_head_cols_if_empty` - (default: `false`), by default, when `body_rows` is empty, the table component doesn't show the table header, but you may want to have it because for example rows are rendered dynamically with JavaScript on the browser side. To avoid wrapping headline inside the form, as it's done in the earlier example, you can `embed` table and override the `between_header_and_table` block: @@ -297,10 +297,11 @@ To avoid wrapping headline inside the form, as it's done in the earlier example, {% endblock %} ``` -This method is useful in case of another form inside headline actions or to avoid interferences with the form like button triggering its submission. +This method is practical in case of another form inside headline actions or to avoid interferences with the form like button triggering its submission. By default, tables are wrapped in a scrollable wrapper which prevents them from being too long. To disable it, set the `is_scrollable` parameter to `false`. + !!! tip For an example of using the table component, see [Add menu item](add_menu_item.md). @@ -317,7 +318,7 @@ The tab component supports the following variables: - `id` - tab ID - `label` - human-readable label for the tab - `active` - true if tab is active -- `content` - HTML content of tab if `tab_content` is not overridden +- `content` - HTML content of tab if `tab_content` isn't overridden - `tab_content_class` - additional CSS classes attached to `.tab-content` - `tab_content_attributes` - additional HTML attributes added to `.tab-content` diff --git a/docs/administration/back_office/back_office_menus/add_menu_item.md b/docs/administration/back_office/back_office_menus/add_menu_item.md index ff9c61555e..0c0ea85f62 100644 --- a/docs/administration/back_office/back_office_menus/add_menu_item.md +++ b/docs/administration/back_office/back_office_menus/add_menu_item.md @@ -1,14 +1,12 @@ --- -description: Create a custom menu in the Back Office. +description: Create a custom menu in the back office. --- # Add menu item -To add a new menu entry in the Back Office, you need to use an event subscriber -and subscribe to [one of the events](back_office_menus.md#menu-events) dispatched when building menus. +To add a new menu entry in the back office, you need to use an event subscriber and subscribe to [one of the events](back_office_menus.md#menu-events) dispatched when building menus. -The following example shows how to add a "Content list" item to the main top menu -and list all content items there, with a shortcut button to edit them. +The following example shows how to add a "Content list" item to the main top menu and list all content items there, with a shortcut button to edit them. ## Create event subscriber @@ -48,10 +46,7 @@ Finally, create the `templates/themes/admin/list/all_content_list.html.twig` fil [[= include_file('code_samples/back_office/menu/menu_item/templates/themes/admin/all_content_list.html.twig') =]] ``` -This template uses the [reusable table template](reusable_components.md#tables) -to render a table that fits the style of the Back Office. +This template uses the [reusable table template](reusable_components.md#tables) to render a table that fits the style of the back office. -You can configure the columns of the table in the `head_cols` variable -and the regular table rows in `body_rows`. -In this case, `body_rows` contains information about the content item provided by the controller, -and an edit button. +You can configure the columns of the table in the `head_cols` variable and the regular table rows in `body_rows`. +In this case, `body_rows` contains information about the content item provided by the controller, and an edit button. diff --git a/docs/administration/back_office/back_office_menus/back_office_menus.md b/docs/administration/back_office/back_office_menus/back_office_menus.md index 6bae43b570..b034ae674f 100644 --- a/docs/administration/back_office/back_office_menus/back_office_menus.md +++ b/docs/administration/back_office/back_office_menus/back_office_menus.md @@ -1,10 +1,10 @@ --- -description: All menus in the Back Office are based on KnpMenuBundle and you can easily extend them with new items. +description: All menus in the back office are based on KnpMenuBundle and you can easily extend them with new items. --- -# Back Office menus +# Back office menus -Back Office menus are based on the [KnpMenuBundle](https://github.com/KnpLabs/KnpMenuBundle) and are easily extensible. +Back office menus are based on the [KnpMenuBundle](https://github.com/KnpLabs/KnpMenuBundle) and they're extensible. !!! tip @@ -15,8 +15,6 @@ Menus are extensible using event subscribers, for example: ``` php [[= include_file('code_samples/back_office/menu/menu_item/src/EventSubscriber/MyMenuSubscriber.php', 0, 29) =]] - } -} ``` !!! tip @@ -37,7 +35,7 @@ You can listen to the following events: || `ConfigureMenuEvent::CONTENT_CREATE_SIDEBAR_RIGHT` | || `ConfigureMenuEvent::CONTENT_SIDEBAR_LEFT` | | Trash | `ConfigureMenuEvent::TRASH_SIDEBAR_RIGHT` | -| Section | `ConfigureMenuEvent::SECTION_EDIT_SIDEBAR_RIGHT` +| Section | `ConfigureMenuEvent::SECTION_EDIT_SIDEBAR_RIGHT` || `ConfigureMenuEvent::SECTION_CREATE_SIDEBAR_RIGHT` | | Policies and permissions | `ConfigureMenuEvent::POLICY_EDIT_SIDEBAR_RIGHT` | || `ConfigureMenuEvent::POLICY_CREATE_SIDEBAR_RIGHT` | @@ -65,10 +63,10 @@ You can listen to the following events: ## Adding menu items -To add a menu item, use the `addChild()` method. Provide the method with the new menu item's identifier -and, optionally, with parameters. +To add a menu item, use the `addChild()` method. +Provide the method with the new menu item's identifier and, optionally, with parameters. -To add an inactive menu section, do not add a route to its parameters. +To add an inactive menu section, don't add a route to its parameters. The following method adds a new menu section under **Content**, and under it, a new item with custom attributes: @@ -133,10 +131,8 @@ For example, the following code changes the default icon for the **Create conten ## Removing menu items -To remove a menu item, for example, to remove the **Copy subtree** item from the right menu in content view, -use the following event listener: +To remove a menu item, for example, to remove the **Copy subtree** item from the right menu in content view, use the following event listener: ``` php [[= include_file('code_samples/back_office/menu/menu_item/src/EventSubscriber/MyMenuSubscriber.php', 44, 45) =]] ``` - diff --git a/docs/administration/back_office/back_office_tabs/back_office_tabs.md b/docs/administration/back_office/back_office_tabs/back_office_tabs.md index 6c14247ece..5693f04af7 100644 --- a/docs/administration/back_office/back_office_tabs/back_office_tabs.md +++ b/docs/administration/back_office/back_office_tabs/back_office_tabs.md @@ -1,10 +1,10 @@ --- -description: Tabs are used for content view, in dashboard, system information and other parts of the Back Office and are extensible. +description: Tabs are used for content view, in dashboard, system information and other parts of the back office and are extensible. --- -# Back Office tabs +# Back office tabs -Many elements of the Back Office interface, such as content view, dashboard or system information, are built using tabs. +Many elements of the back office interface, such as content view, dashboard, or system information, are built with tabs. ![Tabs in System Information](tabs_system_info.png) @@ -53,10 +53,10 @@ Tabs are displayed according to this value in ascending order. !!! tip - It is good practice to reserve some distance between these values, for example to stagger them by step of 10. + It's a good practice to reserve some distance between these values, for example to stagger them by step of 10. It may come useful if you later need to place something between the existing tabs. -You can also influence tab display (for example, order tabs, remove or modify them) by using the following event listeners: +You can also influence tab display (for example, order tabs, remove, or modify them) by using the following event listeners: - `TabEvents::TAB_GROUP_PRE_RENDER` - `TabEvents::TAB_PRE_RENDER` @@ -73,4 +73,5 @@ To create a tab group, register it as a service: Tag the group with `ibexa.admin_ui.component`. `group` indicates where the group is rendered. + For a list of possible rendering places, see [Injecting custom components](custom_components.md). diff --git a/docs/administration/back_office/back_office_tabs/create_dashboard_tab.md b/docs/administration/back_office/back_office_tabs/create_dashboard_tab.md index 975755bdde..968f6fb7d9 100644 --- a/docs/administration/back_office/back_office_tabs/create_dashboard_tab.md +++ b/docs/administration/back_office/back_office_tabs/create_dashboard_tab.md @@ -1,5 +1,5 @@ --- -description: Add a new tab to the Back Office dashboard that welcomes every user after logging in. +description: Add a new tab to the back office dashboard that welcomes every user after logging in. --- # Create dashboard tab @@ -11,13 +11,10 @@ This adds a tab to the **Common content** dashboard block that displays all arti [[= include_file('code_samples/back_office/dashboard/article_tab/src/Tab/Dashboard/Everyone/EveryoneArticleTab.php') =]] ``` -This tab searches for content with content type "Article" (lines 57-60) -and renders the results using the built-in `all_content.html.twig` template, -which ensures the tab looks the same as the existing tabs (lines 71-73). +This tab searches for content with content type "Article" (lines 57-60) and uses the built-in `all_content.html.twig` template to render the results, which ensures that the tab looks the same as the existing tabs (lines 71-73). -The tab also implements OrderedTabInterface (line 17), -which enables you to define the order in which the tab is displayed on the dashboard page. -This is done using the `getOrder()` method (line 45). +The tab also implements OrderedTabInterface (line 17), which enables you to define the order in which the tab is displayed on the dashboard page. +It's done with the `getOrder()` method (line 45). Register this tab as a service: diff --git a/docs/administration/back_office/browser/add_browser_tab.md b/docs/administration/back_office/browser/add_browser_tab.md index 3492289c29..a2225e28ae 100644 --- a/docs/administration/back_office/browser/add_browser_tab.md +++ b/docs/administration/back_office/browser/add_browser_tab.md @@ -4,7 +4,8 @@ description: Add a custom tab displaying selected data to the content browser. # Add browser tab -The Universal Discovery Widget (UDW) is a separate React module. By default, it contains two tabs: Browse and Bookmarks. +The Universal Discovery Widget (UDW) is a separate React module. +By default, it contains two tabs: Browse and Bookmarks. ![UDW default tabs](udw_tabs.png) @@ -119,13 +120,14 @@ ibexaConfigManager.add({ ``` ## Check results - -In the Back Office go to **Content** -> **Dashboard**. On the top right, click the **Create content** button. -In the UDW a new **Images** tab appears, listing all images from the Repository. + +In the back office go to **Content** -> **Dashboard**. +On the top right, click the **Create content** button. +In the UDW a new **Images** tab appears, listing all images from the repository. ![Image tab in UDW](udw_image_tab.png) !!! tip - If you cannot see the results or encounter an error, clear the cache and reload the application. + If you cannot see the results or encounter an error, clear the cache and reload the application. Remember, after any change of css/js files you should always run `yarn encore dev` in the terminal. diff --git a/docs/administration/back_office/browser/browser.md b/docs/administration/back_office/browser/browser.md index fd172c62ca..1addc5b3d8 100644 --- a/docs/administration/back_office/browser/browser.md +++ b/docs/administration/back_office/browser/browser.md @@ -4,12 +4,13 @@ description: Customize the configuration of the content browser. # Browser -Browsing the content structure and selecting content from the Repository uses the module Universal Discovery Widget (UDW). UDW has an interactive interface -which allows you to create, move or copy content items. +Browsing the content structure and selecting content from the repository uses the module Universal Discovery Widget (UDW). +UDW has an interactive interface which allows you to create, move or copy content items. ## Using UDW -UDW requires that you provide configuration by using the `ibexa_udw_config` Twig helper. This configuration must be spread to the props of the component itself. +UDW requires that you provide configuration by using the `ibexa_udw_config` Twig helper. +This configuration must be spread to the props of the component itself. ```html+twig ``` -`single` configuration is one of the default configuration provided. You can also do your [own configuration](#add-new-configuration). +`single` configuration is one of the default configuration provided. +You can also do your [own configuration](#add-new-configuration). With plain JS: @@ -54,19 +56,19 @@ There you can set the following properties: |YML
React props|Values|Required|Definition| |-------------------|------|--------|----------| -|multiple
`multiple`|true
false|no|The possibility to choose multiple Locations.| +|multiple
`multiple`|true
false|no|The possibility to choose multiple locations.| |multiple_items_limit
`multipleItemsLimit`|number|no|Maximum number of items with configuration `multiple: true`.| -|root_location_id
`rootLocationId`|number|no|UDW will display Locations only below this Content Tree element.| -|starting_location_id
`startingLocationId`|number|no|This Location will be displayed as a starting Location in UDW.| +|root_location_id
`rootLocationId`|number|no|UDW displays locations only below this content tree element.| +|starting_location_id
`startingLocationId`|number|no|This location is displayed as a starting location in UDW.| |containers_only
`containersOnly`|true
false|no|When set to `true` only containers can be selected.| |allowed_content_types
`allowedContentTypes`|null
[]
[`contentTypeIdentifier`]|yes|List of allowed content types:
`null` – all content types are allowed,
`[]` – empty table, no content types are allowed.| -|active_sort_clause
`activeSortClause`|DatePublished
ContentName|no|Sort Clause by which children in the Content Tree will be sorted.| -|active_sort_order
`activeSortOrder`|ascending
descending|no|Sorting order of the children in the Content Tree.| +|active_sort_clause
`activeSortClause`|DatePublished
ContentName|no|Sort Clause by which children in the content tree is sorted.| +|active_sort_order
`activeSortOrder`|ascending
descending|no|Sorting order of the children in the content tree.| |active_tab
`activeTab`|browse
search
bookmarks|no|Starting tab in the UDW.| |active_view
`activeView`|finder
grid
tree|no|Starting view in the UDW.| -|allow_redirects
`allowRedirects`|true
false|yes|Allows to redirect content from the UDW tab to another page, for example, to Content Edit page.| -|selected_locations
`selectedLocations`|[]
[locationId]|no|Location that will be selected automatically.| -|allow_confirmation
`allowConfirmation`|true
false|yes|Shows confirmations buttons in the UDW. If set to false, it will not be possible to confirm selection.| +|allow_redirects
`allowRedirects`|true
false|yes|Allows to redirect content from the UDW tab to another page, for example, to content edit page.| +|selected_locations
`selectedLocations`|[]
[locationId]|no|Location that is selected automatically.| +|allow_confirmation
`allowConfirmation`|true
false|yes|Shows confirmations buttons in the UDW. If set to false, it's not possible to confirm selection.| ### Content on the Fly group @@ -77,7 +79,7 @@ There you can set the following properties: |preselected_language
`preselectedLanguage`|null
languageCode|yes|First language on the Content on the Fly language list:
null - language order defined in the system.| |preselected_content_type
`preselectedContentType`|null
contentTypeIdentifier|yes|Content selected in Content on the Fly.| |hidden
`hidden`|true
false|yes|Content on the Fly visibility.| -|auto_confirm_after_publish
`autoConfirmAfterPublish`|true
false|yes|If set to `true` UDW will be automatically closed after publishing the content.| +|auto_confirm_after_publish
`autoConfirmAfterPublish`|true
false|yes|If set to `true` UDW is automatically closed after publishing the content.| ### Tabs config group @@ -98,8 +100,7 @@ General configuration for tabs, for example, browse, search, bookmarks. |`title`|string|yes|The title of Universal Discovery Widget.| UDW configuration is SiteAccess-aware. For each defined SiteAccess, you need to be able to use the same configuration tree to define SiteAccess-specific config. -These settings need to be mapped to SiteAccess-aware internal parameters that -you can retrieve with the [ConfigResolver](dynamic_configuration.md#configresolver). +These settings need to be mapped to SiteAccess-aware internal parameters that you can retrieve with the [ConfigResolver](dynamic_configuration.md#configresolver). ## Add new configuration @@ -125,7 +126,7 @@ ibexa: ### Add new configuration to button -In the `ibexa_udw_config` Twig helper, define a specific part of YAML configuration that will be used to render the **Content Browser**. +In the `ibexa_udw_config` Twig helper, define a specific part of YAML configuration that is used to render the **Content Browser**. You can find Twig helper in your button template. In the example below, a key is pointing to `my_custom_udw` configuration and has additional parameter `johndoe`. @@ -141,7 +142,7 @@ In the example below, a key is pointing to `my_custom_udw` configuration and has ### Additional parameters -If an event listener catches additional parameters passed with context, it will use a configuration specified for it in the event subscriber. +If an event listener catches additional parameters passed with context, it uses a configuration specified for it in the event subscriber. In the example below, the `johndoe` parameter enables the user to choose multiple items from a **Browser window** by changing `multiple: false` from `my_custom_udw` configuration to `multiple: true`. diff --git a/docs/administration/back_office/content_tab_switcher.md b/docs/administration/back_office/content_tab_switcher.md index d1b48d2e58..f163d245e1 100644 --- a/docs/administration/back_office/content_tab_switcher.md +++ b/docs/administration/back_office/content_tab_switcher.md @@ -1,13 +1,17 @@ -# Tab switcher in Content edit page +--- +description: Tabs switcher allows separating the default field types in the content type from the field types that enhance the content with new functionalities. +--- -Tabs switcher allows separating the default Field Types in the content type from the Field Types that enhance the content with new functionalities. -The best example of such Field Types are SEO or Taxonomy, as these are not typical Field Types but a Field Types that handle functionalities for the whole Content object. +# Tab switcher in content edit page -The following example shows how to add a Meta tab with automatically assigned Taxonomy Field Type. +Tabs switcher allows separating the default field types in the content type from the field types that enhance the content with new functionalities. +The best example of such field types are SEO or Taxonomy, as these aren't typical field types but a field types that handle functionalities for the whole content object. + +The following example shows how to add a Meta tab with automatically assigned Taxonomy field type. ## Add Meta tab -Before you start adding the Meta tab, make sure the content type you want to edit has [Taxonomy Entry Assignment Field Type]([[= user_doc =]]/taxonomy/#assign-tag-to-content-from-taxonomy-tree). +Before you start adding the Meta tab, make sure the content type you want to edit has [Taxonomy Entry Assignment field type]([[= user_doc =]]/taxonomy/#assign-tag-to-content-from-taxonomy-tree). Next, provide the semantic configuration under the `ibexa.system..admin_ui_forms` [configuration key](configuration.md#configuration-files): @@ -23,18 +27,19 @@ ibexa: ``` -`ibexa_taxonomy_entry_assignment` - identifier for the Field Type +`ibexa_taxonomy_entry_assignment` - identifier for the field type -`meta` - when set to `true`, puts the declared Field Type in the Meta tab +`meta` - when set to `true`, puts the declared field type in the Meta tab ![Meta tab](tab_switcher.png) -### Configure Field groups for Meta tab +### Configure field groups for Meta tab + +The default configuration makes the `ibexa_taxonomy_entry_assignment` field always visible in the Meta tab in the content form. +With this new feature, you can indicate what field types, previously set in the back office content type, are shown in the Meta tab section in the content form. +You can automatically move all field types from Metadata group to the Meta tab in the content form. -The default configuration makes the `ibexa_taxonomy_entry_assignment` Field always visible in the Meta tab in the Content form. -With this new feature, you can indicate what Field types, previously set in the Back Office content type, are shown in the Meta tab section in the Content form. -You can automatically move all Field types from Metadata group to the Meta tab in the Content form. To do it, use the following configuration: ```yaml @@ -62,7 +67,7 @@ ibexa: ``` -The `meta_field_groups_list` configuration can be easily overriden. +The `meta_field_groups_list` configuration can be overriden. ## Add custom tab @@ -74,7 +79,7 @@ First, create an event listener in the `src/EventListener/TextAnchorMenuTabListe A new custom tab is defined in the line 28, the line 31 defines items for the second level. -For new tabs it is also required to render its section in the Content editing form. To do it, register the UI Component: +For new tabs it's also required to render its section in the content editing form. To do it, register the UI Component: ```yaml [[= include_file('code_samples/back_office/content_type/config/custom_services.yaml') =]] diff --git a/docs/administration/back_office/content_tree.md b/docs/administration/back_office/content_tree.md index 3aa7614b39..ea4b10b332 100644 --- a/docs/administration/back_office/content_tree.md +++ b/docs/administration/back_office/content_tree.md @@ -1,8 +1,8 @@ --- -description: Configure SiteAccess, displayed content items, depth and root location for the Content Tree. +description: Configure SiteAccess, displayed content items, depth and root location for the content tree. --- -# Content Tree +# Content tree With this configuration you can: @@ -10,8 +10,8 @@ With this configuration you can: - decide how many content items are displayed in the tree - set maximum depth of expanded tree - hide content types -- set a tree root Location -- override Content Tree's root for specific Locations +- set a tree root location +- override content tree's root for specific locations ```yaml ibexa: @@ -19,21 +19,21 @@ ibexa: # any SiteAccess or SiteAccess group admin_group: content_tree_module: - # defines how many children will be shown after expanding parent + # defines how many children are shown after expanding parent load_more_limit: 15 # users won't be able to load more children than that children_load_max_limit: 200 # maximum depth of expanded tree tree_max_depth: 10 - # content types to display in Content Tree, value of '*' allows all CTs to be displayed + # content types to display in content tree, value of '*' allows all CTs to be displayed allowed_content_types: '*' - # Content Tree won't display these content types, can be used only when 'allowed_content_types' is set to '*' + # content tree won't display these content types, can be used only when 'allowed_content_types' is set to '*' ignored_content_types: - post - article # ID of Location to use as tree root. If omitted - content.tree_root.location_id setting is used. tree_root_location_id: 2 - # list of Location IDs for which Content Tree's root Location will be changed + # list of Location IDs for which content tree's root Location is changed contextual_tree_root_location_ids: - 2 # Home (Content structure) - 5 # Users diff --git a/docs/administration/back_office/content_type_anchor_menu.md b/docs/administration/back_office/content_type_anchor_menu.md index 615b7cadfd..4389949d3b 100644 --- a/docs/administration/back_office/content_type_anchor_menu.md +++ b/docs/administration/back_office/content_type_anchor_menu.md @@ -1,20 +1,18 @@ --- -description: Add anchor menu to the content type configuration screen, to make Field Type settings of your choice more prominent. +description: Add anchor menu to the content type configuration screen, to make field type settings of your choice more prominent. --- # Add anchor menu to content type edit screen -With the anchor menu you can increase visibility of certain [Field Types](field_types.md), which provide more complex functionality, -by separating them from the [Field definitions](content_types.md#field-definitions) section in [content type](content_types.md) configuration screen. -One example of such Field Type would be [SEO]([[= user_doc =]]/search_engine_optimization/work_with_seo/), -because it handles functionality that applies to all content items of the content type. -You can use the anchor menu feature with other Field Types, including [custom ones](create_custom_generic_field_type.md). +With the anchor menu you can increase visibility of certain [field types](field_types.md), which provide more complex functionality, by separating them from the [field definitions](content_types.md#field-definitions) section in [content type](content_types.md) configuration screen. +One example of such field type would be [SEO]([[= user_doc =]]/search_engine_optimization/work_with_seo/), because it handles functionality that applies to all content items of the content type. +You can use the anchor menu feature with other field types, including [custom ones](create_custom_generic_field_type.md). -See the following example to learn how you can add a Field Type as an anchor menu. +See the following example to learn how you can add a field type as an anchor menu. ## Modify YAML configuration -Modify the Field Type visibility under the `ibexa.system..admin_ui_forms.content_type_edit.field_types` [configuration key](configuration.md#configuration-files): +Modify the field type visibility under the `ibexa.system..admin_ui_forms.content_type_edit.field_types` [configuration key](configuration.md#configuration-files): ```yaml ibexa: @@ -31,16 +29,17 @@ ibexa: Where keys have the following meaning: -- `field_type_identifier` - replace this key with an identifier of the Field Type that you want to make more prominent. In case of SEO, this key is `ibexa_seo`. -- `meta` - when this flag is set to `true`, it separates the Field Type from the **Field definitions** section and puts it in an anchor menu -- `position` - decides about the Field Type's position on the content type edit screen and in the content item, in relation to other Field Types +- `field_type_identifier` - replace this key with an identifier of the field type that you want to make more prominent. +In case of SEO, this key is `ibexa_seo`. +- `meta` - when this flag is set to `true`, it separates the field type from the **Field definitions** section and puts it in an anchor menu +- `position` - decides about the field type's position on the content type edit screen and in the content item, in relation to other field types -Additionally, setting `meta` to `true` adds a toggle for enabling or disabling the Field Type. +Additionally, setting `meta` to `true` adds a toggle for enabling or disabling the field type. In case of SEO, it adds the **Enable SEO for this content type** toggle. -Enable the toggle to display the SEO section on the content item edit page. +Enable the toggle to display the SEO section on the content item edit page. ![SEO anchor menu](content_type_edit_screen_anchor_menu.png) !!! note - If you add multiple Field Types as anchor menus, they are automatically displayed as separate sections. + If you add multiple field types as anchor menus, they're automatically displayed as separate sections. diff --git a/docs/administration/back_office/customize_calendar.md b/docs/administration/back_office/customize_calendar.md index 46df5d8c10..d8b1680842 100644 --- a/docs/administration/back_office/customize_calendar.md +++ b/docs/administration/back_office/customize_calendar.md @@ -75,15 +75,15 @@ To add an in-memory collection as an event source, create `src/Calendar/Holidays !!! note When creating the list of events, you must list all the `createEvent()` entities chronologically. - + For example: - + ``` php $collection = new EventCollection([ $this->createEvent("Event 1", new DateTime("2024-01-01")), $this->createEvent("Event 2", new DateTime("2024-01-02")), // ... - ``` + ``` Next, register the event source as a service: diff --git a/docs/administration/back_office/customize_search_sorting.md b/docs/administration/back_office/customize_search_sorting.md index 5978eb0430..b4502474c5 100644 --- a/docs/administration/back_office/customize_search_sorting.md +++ b/docs/administration/back_office/customize_search_sorting.md @@ -1,10 +1,10 @@ --- -description: Add a "sort by" method to the Back Office search result page. +description: Add a "sort by" method to the back office search result page. --- # Customize search sorting -You can customize the **Sort by** menu in the Back Office search result page, for example, by adding new sort criteria. +You can customize the **Sort by** menu in the back office search result page, for example, by adding new sort criteria. To do it, you must create a service that implements the `Ibexa\Contracts\Search\SortingDefinition\SortingDefinitionProviderInterface` and tag it with `ibexa.search.sorting_definition.provider`. diff --git a/docs/administration/back_office/customize_search_suggestion.md b/docs/administration/back_office/customize_search_suggestion.md index 0478a0bf33..426353baa5 100644 --- a/docs/administration/back_office/customize_search_suggestion.md +++ b/docs/administration/back_office/customize_search_suggestion.md @@ -4,8 +4,8 @@ description: Customize search suggestion configuration and sources. # Customize search suggestion -In the Back Office, when you start typing in the search field on the top bar, suggestions about what you could be looking for show up directly under the field. -For more information about using this feature to search for content, see [user documentation]([[= user_doc =]]/search/search_for_content). +In the back office, when you start typing in the search field on the top bar, suggestions about what you could be looking for show up directly under the field. +For more information about using this feature to search for content, see [User Documentation]([[= user_doc =]]/search/search_for_content). ## Configuration @@ -30,12 +30,13 @@ After this event, the suggestion collection is sorted by score and truncated to !!! tip You can list listeners and subscribers with the following command: + ``` shell php bin/console debug:event BuildSuggestionCollectionEvent ``` -The following example is boosting Product suggestions. -It's a subscriber that passes after the default one (because priority is set to zero), adds matching products at a score above the earlier Content suggestions, and avoids duplicates. +The following example is boosting product suggestions. +It's a subscriber that passes after the default one (because priority is set to zero), adds matching products at a score above the earlier content suggestions, and avoids duplicates. - If the suggestion source finds a number of matching products that is equal or greater than the `result_limit`, only those products end up in the suggestion. - If it finds less than `result_limit` products, those products are on top of the suggestion, followed by items from another suggestion source until the limit is met. @@ -85,7 +86,7 @@ services: At this point, it's possible to test the suggestion JSON. The route is `/suggestion` with a GET parameter `query` for the searched text. - For example, log in to the Back Office to have a session cookie, then access the route through the Back Office SiteAccess, such as `/admin/suggestion?query=platform`. + For example, log in to the back office to have a session cookie, then access the route through the back office SiteAccess, such as `/admin/suggestion?query=platform`. If you have a product with "platform" in its name, it is returned as the first suggestion. A JavaScript renderer displays the normalized product suggestion. @@ -103,7 +104,7 @@ It's registered as `autocomplete.renderers.` by using the type identifier })(window, document, window.ibexa, window.Routing); ``` -To fit into the Back Office design, you can take HTML structure and CSS class names from an existing suggestion template `vendor/ibexa/admin-ui/src/bundle/Resources/views/themes/admin/ui/global_search_autocomplete_content_item.html.twig`. +To fit into the back office design, you can take HTML structure and CSS class names from an existing suggestion template `vendor/ibexa/admin-ui/src/bundle/Resources/views/themes/admin/ui/global_search_autocomplete_content_item.html.twig`. To allow template override and ease HTML writing, the example is also loading a template to render the HTML. @@ -113,7 +114,7 @@ Here is a complete `assets/js/admin.search.autocomplete.product.js` from the pro [[= include_file('code_samples/back_office/search/assets/js/admin.search.autocomplete.product.js') =]] ``` -To be loaded in the Back Office layout, this file must be added to Webpack entry `ibexa-admin-ui-layout-js`. +To be loaded in the back office layout, this file must be added to Webpack entry `ibexa-admin-ui-layout-js`. At the end of `webpack.config.js`, add it by using `ibexaConfigManager`: ``` javascript diff --git a/docs/administration/back_office/multifile_upload.md b/docs/administration/back_office/multifile_upload.md index 2e4512d021..d95d61043d 100644 --- a/docs/administration/back_office/multifile_upload.md +++ b/docs/administration/back_office/multifile_upload.md @@ -9,8 +9,7 @@ It provides an interface to publish content based on dropped files while uploadi !!! caution - If you want to load the multi-file upload module, you need to load the JS code for it in your view, - as it is not available by default. + If you want to load the multi-file upload module, you need to load the JS code for it in your view, as it's not available by default. ## Use multi-file upload @@ -89,7 +88,7 @@ There are two types of properties: **required** and **optional**. ### Required properties -All of the following properties must be used, otherwise the multi-file upload does not work. +All of the following properties must be used, otherwise the multi-file upload doesn't work. - **onAfterUpload** _{Function}_ - a callback to be invoked immediately after a file has been uploaded - **adminUiConfig** _{Object}_ - UI config object. It should keep the following structure: @@ -97,21 +96,21 @@ All of the following properties must be used, otherwise the multi-file upload do - **defaultMappings** _{Array}_ - a list of file type to content type mappings Sample mapping be an object and should follow the convention: - **contentTypeIdentifier** _{String}_ - content type identifier - - **contentFieldIdentifier** _{String}_ - Field identifier - - **nameFieldIdentifier** _{String}_ - name Field identifier + - **contentFieldIdentifier** _{String}_ - field identifier + - **nameFieldIdentifier** _{String}_ - name field identifier - **mimeTypes** _{Array}_ - a list of file types assigned to a specific content type - **fallbackContentType** _{Object}_ - a fallback content type definition. Should contain the following info: - **contentTypeIdentifier** _{String}_ - content type identifier - - **contentFieldIdentifier** _{String}_ - Field identifier - - **nameFieldIdentifier** _{String}_ - name Field identifier - - **locationMappings** _{Array}_ - list of file type to content type mappings based on a Location identifier + - **contentFieldIdentifier** _{String}_ - field identifier + - **nameFieldIdentifier** _{String}_ - name field identifier + - **locationMappings** _{Array}_ - list of file type to content type mappings based on a location identifier - **maxFileSize** {Number} - maximum file size allowed for uploading. It's a number of bytes - **token** _{String}_ - CSRF token - **siteaccess** _{String}_ - SiteAccess identifier -- **parentInfo** _{Object}_ - parent Location meta information: +- **parentInfo** _{Object}_ - parent location meta information: - **contentTypeIdentifier** _{String}_ - content type identifier - **contentTypeId** _{Number}_ - content type ID - - **locationPath** _{String}_ - Location path string + - **locationPath** _{String}_ - location path string - **language** _{String}_ - language code identifier ### Optional properties @@ -120,7 +119,7 @@ Optionally, the multi-file upload module can take a following list of properties - **checkCanUpload** _{Function}_ - checks whether am uploaded file can be uploaded. The callback takes four params: - **file** _{File}_ - file object - - **parentInfo** _{Object}_ - parent Location meta information + - **parentInfo** _{Object}_ - parent location meta information - **config** _{Object}_ - Multi-file Upload module config - **callbacks** _{Object}_ - error callbacks list: **fileTypeNotAllowedCallback** and **fileSizeNotAllowedCallback** - **createFileStruct** _{Function}_ - a function that creates a _ContentCreate_ struct. The function takes two params: @@ -128,7 +127,7 @@ Optionally, the multi-file upload module can take a following list of properties - **params** _{Object}_ - params hash containing: **parentInfo** and **adminUiConfig** stored under the **config** key - **deleteFile** _{Function}_ - a function deleting content created from a given file. It takes three params: - **systemInfo** _{Object}_ - hash containing information about CSRF token and SiteAccess: **token** and **siteaccess** - - **struct** _{Object}_ - Content struct + - **struct** _{Object}_ - content struct - **callback** _{Function}_ - content deleted callback - **onPopupClose** _{Function}_ - function invoked when closing a Multi-file Upload popup. It takes one param: **itemsUploaded** - the list of uploaded items - **publishFile** _{Function}_ - publishes an uploaded file-based content item. Takes three params: diff --git a/docs/administration/back_office/notifications.md b/docs/administration/back_office/notifications.md index 8bfd64e612..fdf5f0cc0c 100644 --- a/docs/administration/back_office/notifications.md +++ b/docs/administration/back_office/notifications.md @@ -1,5 +1,5 @@ --- -description: You can send notifications to users who work with the Back Office by using notification bars or notifications in the user menu. +description: You can send notifications to users who work with the back office by using notification bars or notifications in the user menu. --- # Notifications @@ -7,18 +7,18 @@ description: You can send notifications to users who work with the Back Office b You can send two types on notifications to the users. [Notification bar](#notification-bars) is displayed in specific situations as a message bar appearing at the bottom of the page. -It appears to whoever is doing a specific operation in the Back Office. +It appears to whoever is doing a specific operation in the back office. ![Example of an info notification](notification2.png "Example of the notification bar") [Custom notifications](#create-custom-notifications) are sent to a specific user. -They will appear in their profile in the Back Office. +They appear in their profile in the back office. ![Notification in profile](notification3.png) ## Notification bars -Notifications are displayed as a message bar in the Back Office. +Notifications are displayed as a message bar in the back office. There are four types of notifications: `info`, `success`, `warning` and `error`. ### Displaying notifications from PHP @@ -53,7 +53,7 @@ Dispatch the event with `document.body.dispatchEvent(eventInfo);`. ## Create custom notifications -You can send your own custom notifications to the user which will be displayed in the user menu. +You can send your own custom notifications to the user which are displayed in the user menu. To create a new notification you must use the `createNotification(Ibexa\Contracts\Core\Repository\Values\Notification\CreateStruct $createStruct)` method from `Ibexa\Contracts\Core\Repository\NotificationService`. @@ -85,8 +85,7 @@ Finally, you need to add an entry to `config/services.yaml`: ## Notification timeout -To define the timeout for hiding Back-Office notification bars, per notification type, -use the `ibexa.system..notifications..timeout` [configuration key](configuration.md#configuration-files): +To define the timeout for hiding Back-Office notification bars, per notification type, use the `ibexa.system..notifications..timeout` [configuration key](configuration.md#configuration-files): ``` yaml ibexa: @@ -103,4 +102,5 @@ ibexa: timeout: 0 ``` -The values shown above are the defaults. `0` means the notification does not hide automatically. +The values shown above are the defaults. +`0` means the notification doesn't hide automatically. diff --git a/docs/administration/back_office/subitems_list.md b/docs/administration/back_office/subitems_list.md index 316f9dc326..209f1493d0 100644 --- a/docs/administration/back_office/subitems_list.md +++ b/docs/administration/back_office/subitems_list.md @@ -1,16 +1,15 @@ --- -description: Inject a sub-items list into your Back Office customizations. +description: Inject a sub-items list into your back office customizations. --- # Sub-items list The Sub-items List module is meant to be used as a part of the editorial interface of [[= product_name =]]. -It provides an interface for listing the sub-items of any Location. +It provides an interface for listing the sub-items of any location. !!! caution - If you want to load the Sub-items module, you need to load the JS code for it in your view, - as it is not available by default. + If you want to load the Sub-items module, you need to load the JS code for it in your view, as it's not available by default. ## Use sub-items list @@ -47,13 +46,15 @@ const attrs = { ## Properties list -The `` module can handle additional properties. There are two types of properties: **required** and **optional**. All of them are listed below. +The `` module can handle additional properties. +There are two types of properties: **required** and **optional**. +All of them are listed below. ### Required props -Without all the following properties the Sub-items module will not work. +Without all the following properties the Sub-items module cannot work. -- **parentLocationId** _{Number}_ - parent Location ID +- **parentLocationId** _{Number}_ - parent location ID - **restInfo** _{Object}_ - backend config object: - **token** _{String}_ - CSRF token - **siteaccess** _{String}_ - SiteAccess identifier @@ -69,28 +70,28 @@ Optionally, Sub-items module can take a following list of props: - **callback** _{Function}_ - a callback invoked when content info is loaded - **loadContentTypes** _{Function}_ - loads content types. Takes one param: - **callback** _{Function}_ - callback invoked when content types are loaded -- **loadLocation** _{Function}_ - loads Location. Takes four params: +- **loadLocation** _{Function}_ - loads location. Takes four params: - **restInfo** _{Object}_ - REST info params: - **token** _{String}_ - the user token - **siteaccess** _{String}_ - the current SiteAccess - **queryConfig** _{Object}_ - query config: - - **locationId** _{Number}_ - Location ID + - **locationId** _{Number}_ - location ID - **limit** _{Number}_ - content item limit - **offset** _{Number}_ - items offset - **sortClauses** _{Object}_ - the Sort Clauses, for example, {LocationPriority: 'ascending'} - - **callback** _{Function}_ - callback invoked when Location is loaded -- **updateLocationPriority** - updates item Location priority. Takes two params: + - **callback** _{Function}_ - callback invoked when location is loaded +- **updateLocationPriority** - updates item location priority. Takes two params: - **params** _{Object}_ - parameters hash containing: - **priority** _{Number}_ - priority value - - **location** _{String}_ - REST Location ID + - **location** _{String}_ - REST location ID - **token** _{String}_ - CSRF token - **siteaccess** _{String}_ - SiteAccess identifier - - **callback** _{Function}_ - callback invoked when Location priority is updated + - **callback** _{Function}_ - callback invoked when location priority is updated - **activeView** _{String}_ - active list view identifier - **extraActions** _{Array}_ - list of extra actions. Each action is an object containing: - **component** _{Element}_ - React component class - **attrs** _{Object}_ - additional component properties -- **items** _{Array}_ - list of Location's sub-items +- **items** _{Array}_ - list of location's sub-items - **limit** _{Number}_ - items limit count - **offset** _{Number}_ - items limit offset - **labels** _{Object}_ - list of module labels, see [sub.items.module.js](https://github.com/ibexa/admin-ui/blob/main/src/bundle/ui-dev/src/modules/sub-items/sub.items.module.js) for details. Contains definitions for sub components: @@ -103,8 +104,7 @@ Optionally, Sub-items module can take a following list of props: ## Reuse Sub-items list -To add a Sub-items list on a page that does not have the (right) action sidebar, you need to do one of the following things: +To add a Sub-items list on a page that doesn't have the (right) action sidebar, you need to do one of the following things: - add a `
` element with the `.ibexa-extra-actions-container` selector -- change the selector in the Sub-items settings by sending the `languageContainerSelector` prop -which takes the selector for the element that renders the `languageSelector`. +- change the selector in the Sub-items settings by sending the `languageContainerSelector` prop which takes the selector for the element that renders the `languageSelector`. diff --git a/docs/administration/configuration/configuration.md b/docs/administration/configuration/configuration.md index dfcdf6f9d7..ec026396b8 100644 --- a/docs/administration/configuration/configuration.md +++ b/docs/administration/configuration/configuration.md @@ -4,32 +4,31 @@ description: In Ibexa DXP you store and manage configuration in project files, t # Configuration -[[= product_name =]] configuration is delivered using a number of dedicated configuration files. -It contains everything from selecting the content Repository to SiteAccesses to language settings. +[[= product_name =]] configuration is delivered by means of a number of dedicated configuration files. +It contains everything from selecting the content repository to SiteAccesses to language settings. ### Configuration format -The recommended configuration format is YAML. It is used by default in the kernel (and in examples throughout the documentation). +The recommended configuration format is YAML. +It's used by default in the kernel (and in examples throughout the documentation). However, you can also use XML or PHP formats for configuration. ### Configuration files Configuration files are located in the `config` folder. -Configuration is provided per package in the `config/packages` folder, -and routes are defined per package in `config/routes`. +Configuration is provided per package in the `config/packages` folder, and routes are defined per package in `config/routes`. `config/packages/ibexa.yaml` contains basic configuration. It stores, among others, [SiteAccess](multisite.md) information and content view config. -Other configuration is provided in respective files, e.g. `config/packages/ibexa_admin_ui.yaml`, -`config/packages/ibexa_http_cache.yaml`. +Other configuration is provided in respective files, for example, `config/packages/ibexa_admin_ui.yaml`, `config/packages/ibexa_http_cache.yaml`. -Configuration can be made environment-specific using separate folders for each environment. +You can make configuration environment-specific by using separate folders for each environment. These files contain additional settings and point to the general (not environment-specific) configuration that is applied in other cases. !!! note "New configuration files" - It is good practice to provide your own configuration in separate files. + It's good practice to provide your own configuration in separate files. Any YAML files placed in the `config/packages` folder is automatically included in the system configuration. !!! tip @@ -55,12 +54,12 @@ Basic configuration handling in [[= product_name =]] is similar to what is commo You can define key/value pairs in your configuration files. Internally and by convention, keys follow a *dot syntax*, where the different segments follow your configuration hierarchy. -Keys are usually prefixed by a *namespace* corresponding to your application. All kinds of values are accepted, including arrays and deep hashes. +Keys are usually prefixed by a *namespace* corresponding to your application. +All kinds of values are accepted, including arrays and deep hashes. -For configuration that is meant to be exposed to an end-user (or end-developer), -it's usually a good idea to also [implement semantic configuration]([[= symfony_doc =]]/components/config/definition.html). +For configuration that is meant to be exposed to an end-user (or end-developer), it's usually a good idea to also [implement semantic configuration]([[= symfony_doc =]]/components/config/definition.html). -Note that you can also [implement SiteAccess-aware semantic configuration](siteaccess_aware_configuration.md). +You can also [implement SiteAccess-aware semantic configuration](siteaccess_aware_configuration.md). For example: @@ -82,7 +81,7 @@ $myParameter = $this->container->getParameter( 'myapp.parameter.name' ); For specific configuration settings, see: -- [Back Office configuration](back_office_configuration.md) +- [Back office configuration](back_office_configuration.md) - [Repository configuration](repository_configuration.md) - [Content views](template_configuration.md) - [Multisite configuration](multisite_configuration.md) diff --git a/docs/administration/configuration/dynamic_configuration.md b/docs/administration/configuration/dynamic_configuration.md index 0385ca7471..09f9cfbf42 100644 --- a/docs/administration/configuration/dynamic_configuration.md +++ b/docs/administration/configuration/dynamic_configuration.md @@ -11,7 +11,7 @@ Dynamic configuration is handled by a ConfigResolver. It exposes the `hasParameter()` and `getParameter()` methods. You can use them to check the different *scopes* available for a given *namespace* to find the appropriate parameter. -In order to work with the ConfigResolver, your dynamic settings must have the following name format: `..parameter.name`. +To work with the ConfigResolver, your dynamic settings must have the following name format: `..parameter.name`. ``` yaml parameters: @@ -27,8 +27,7 @@ parameters: myapp.default.my_param: Default value ``` -Inside a controller, in `site_group` SiteAccess, you can use the parameters in the following way -(note that the same applies for `hasParameter()`): +Inside a controller, in `site_group` SiteAccess, you can use the parameters in the following way (the same applies for `hasParameter()`): ``` php $configResolver = $this->getConfigResolver(); @@ -55,8 +54,8 @@ $myParamSettingAdmin = $configResolver->getParameter( 'my_param', 'myapp', 'admi Both `getParameter()` and `hasParameter()` can take three arguments: 1. `$paramName` - the name of the parameter -2. `$namespace` - your application namespace, `myapp` in the previous example. If null, the default namespace will be used, which is `ibexa.site_access.config` by default. -3. `$scope` - a SiteAccess name. If null, the current SiteAccess will be used. +2. `$namespace` - your application namespace, `myapp` in the previous example. If null, the default namespace is used, which is `ibexa.site_access.config` by default. +3. `$scope` - a SiteAccess name. If null, the current SiteAccess is used. ## Inject ConfigResolver into services @@ -71,13 +70,11 @@ services: You can also use the [autowire feature]([[= symfony_doc =]]/service_container/autowiring.html), by type hinting against ConfigResolverInterface. -!!! tip - - For more information about dependency injection, see [Service container](php_api.md#service-container). +For more information about dependency injection, see [Service container](php_api.md#service-container). !!! note - Do not store the retrieved config value unless you know what you are doing. + Don't store the retrieved config value unless you know what you're doing. SiteAccess can change during code execution, which means you might work on the wrong value. ``` php @@ -96,7 +93,7 @@ class Service { $this->configResolver = $configResolver; } - + public function someMethodThatNeedConfig() { $configValue = $this->configResolver->getParameter('my_param', 'myapp'); diff --git a/docs/administration/configuration/repository_configuration.md b/docs/administration/configuration/repository_configuration.md index af81c5a25d..cd496995d8 100644 --- a/docs/administration/configuration/repository_configuration.md +++ b/docs/administration/configuration/repository_configuration.md @@ -1,16 +1,17 @@ --- -description: Configure Repository connections, archive limits, Field groups and other settings. +description: Configure repository connections, archive limits, field groups and other settings. --- # Repository configuration -You can define several Repositories within a single application. However, you can only use one per site. +You can define several repositories within a single application. +However, you can only use one per site. ## Repository connection ### Using default values -To use the default Repository connection, you do not need to specify its details: +To use the default repository connection, you don't need to specify its details: ``` yaml ibexa: @@ -24,14 +25,13 @@ ibexa: !!! note "Legacy storage engine" - Legacy storage engine is the default storage engine for the Repository. + Legacy storage engine is the default storage engine for the repository. It uses [Doctrine DBAL](https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/) (Database Abstraction Layer). Database settings are supplied by [DoctrineBundle](https://github.com/doctrine/DoctrineBundle). As such, you can refer to [DoctrineBundle's documentation](https://github.com/doctrine/DoctrineBundle/blob/2.7.x/Resources/doc/configuration.rst#doctrine-dbal-configuration). -If no Repository is specified for a SiteAccess or SiteAccess group, -the first Repository defined under `ibexa.repositories` will be used: +If no repository is specified for a SiteAccess or SiteAccess group, the first repository defined under `ibexa.repositories` is used: ``` yaml ibexa: @@ -44,11 +44,11 @@ ibexa: # ... ``` -#### Multisite URI matching with multi-Repository setup +#### Multisite URI matching with multi-repository setup -You can use only one Repository (database) per domain. -This does not prohibit using [different Repositories](persistence_cache.md#multi-repository-setup) on different subdomains. -However, when using URI matching for multisite setup, all SiteAccesses sharing domain also need to share Repository. +You can use only one repository (database) per domain. +This doesn't prohibit using [different repositories](persistence_cache.md#multi-repository-setup) on different subdomains. +However, when you use URI matching for multisite setup, all SiteAccesses sharing domain also need to share repository. For example: - `ibexa.co` domain can use `ibexa_repo` @@ -57,16 +57,13 @@ For example: But the following configuration would be invalid: - `ibexa.co` domain can use `ibexa_repo` -- `ibexa.co/doc` **cannot** use `doc_repo`, as it is under the same domain. +- `ibexa.co/doc` **cannot** use `doc_repo`, as it's under the same domain. -Invalid configuration causes problems for different parts of the system, -for example back-end UI, REST interface and other non-SiteAccess-aware Symfony routes -such as `/_fos_user_context_hash` used by [HTTP cache](http_cache.md). +Invalid configuration causes problems for different parts of the system, for example, back-end UI, REST interface, and other non-SiteAccess-aware Symfony routes such as `/_fos_user_context_hash` used by [HTTP cache](http_cache.md). ### Entity manager -If you use the [Doctrine entity manager](https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/tutorials/getting-started.html#obtaining-the-entitymanager), -you are unable to connect different SiteAccesses to different databases. +If you use the [Doctrine entity manager](https://www.doctrine-project.org/projects/doctrine-orm/en/2.10/tutorials/getting-started.html#obtaining-the-entitymanager), you're unable to connect different SiteAccesses to different databases. To have this possibility, you need to use the SiteAccess-aware entity manager: `ibexa.doctrine.orm.entity_manager`. @@ -83,17 +80,15 @@ ibexa: prefix: Ibexa\Bundle\Core\Entity ``` -Refer to [DoctrineBundle documentation](https://symfony.com/doc/3.4/reference/configuration/doctrine.html) -for more information. +For more information, see [DoctrineBundle documentation](https://symfony.com/doc/3.4/reference/configuration/doctrine.html). !!! note - In contrast with DoctrineBundle, when using the SiteAccess-aware entity manager you need to explicitly set all options: - `dir` (it still accepts relative path in case of bundles), `prefix`, `type`, and `is_bundle`. + In contrast with DoctrineBundle, when you use the SiteAccess-aware entity manager you need to explicitly set all options: `dir` (it still accepts relative path in case of bundles), `prefix`, `type`, and `is_bundle`. ### Defining custom connection -You can also explicitly define a custom Repository connection: +You can also explicitly define a custom repository connection: ``` yaml doctrine: @@ -119,8 +114,8 @@ doctrine: ibexa: repositories: - first_repository: - storage: + first_repository: + storage: engine: legacy connection: my_connection_name config: {} @@ -135,7 +130,7 @@ ibexa: search: connection: my_second_connection_name another_repository: - storage: + storage: engine: legacy connection: another_connection_name config: {} @@ -161,7 +156,7 @@ SECOND_DATABASE_URL=otherdb://otheruser:otherpasswd@otherhost:otherport/otherdbn ## Field groups configuration Field groups, used in content and content type editing, can be configured under the `repositories` key. -Values entered there are Field group *identifiers*: +Values entered there are field group *identifiers*: ``` yaml repositories: @@ -171,9 +166,10 @@ repositories: default: content ``` -These identifiers can be given human-readable values and can be translated. Those values are used when editing content types. +These identifiers can be given human-readable values and can be translated. +Those values are used when editing content types. The translation domain is `ibexa_fields_groups`. -This example in `translations/ibexa_fields_groups.en.yaml` defines English names for Field groups: +This example in `translations/ibexa_fields_groups.en.yaml` defines English names for field groups: ``` yaml content: Content @@ -183,8 +179,8 @@ user_data: User data ## Limit of archived content versions -`default_version_archive_limit` controls the number of archived versions per content item that are stored in the Repository. -By default it is set to 5. This setting is configured in the following way (typically in `ibexa.yaml`): +`default_version_archive_limit` controls the number of archived versions per content item that are stored in the repository. +By default it's set to 5. This setting is configured in the following way (typically in `ibexa.yaml`): ``` yaml ibexa: @@ -199,9 +195,8 @@ This limit is enforced on publishing a new version and only covers archived vers !!! tip Don't set `default_version_archive_limit` too high. - In Legacy storage engine you will see performance degradation if you store too many versions. - The default value of 5 is the recommended value, but the less content you have overall, - the more you can increase this to, for instance, 25 or even 50. + In Legacy storage engine you can see performance degradation if you store too many versions. + The default value of 5 is the recommended value, but the less content you have overall, the more you can increase this to, for instance, 25 or even 50. ### Removing versions on publication @@ -218,8 +213,7 @@ ibexa: `remove_archived_versions_on_publish` is set to `true` by default. Set it to `false` if you have multiple older versions of content and need to avoid performance drops when publishing. -When you set the value to `false`, run [`ibexa:content:cleanup-versions`](#removing-old-versions) periodically -to make sure that content item versions that exceed the limit are removed. +When you set the value to `false`, run [`ibexa:content:cleanup-versions`](#removing-old-versions) periodically to make sure that content item versions that exceed the limit are removed. ### Removing old versions @@ -229,8 +223,8 @@ The command takes the following optional parameters: - `status` or `t` - status of versions to remove: `draft`, `archived` or `all` - `keep` or `k` - number of versions to keep -- `user` or `u` - the User that the command will be performed as. The User must have the `content/remove`, `content/read` and `content/versionread` Policies. By default the `administrator` user is applied. -- `excluded-content-types` - exclude versions of one or multiple content types from the cleanup procedure; separate multiple content types identifiers with the comma. +- `user` or `u` - the User that the command is performed as. The user must have the `content/remove`, `content/read` and `content/versionread` policies. By default the `administrator` user is applied. +- `excluded-content-types` - exclude versions of one or multiple content types from the cleanup procedure. Separate multiple content types identifiers with the comma. `ibexa:content:cleanup-versions --status --keep --user --excluded-content-types article,blog_post` @@ -250,12 +244,12 @@ ibexa: user_group_content_type_identifier: [user_group] ``` -You can override these settings if you have other content types that should be treated as users/user groups in the Back Office. -When viewing such Content in the Back Office you will be able to see e.g. the assigned Policies. +You can override these settings if you have other content types that should be treated as users/user groups in the back office. +When viewing such content in the back office you're able to see, for example, the assigned policies. ## Top-level Locations -You can change the default path for top-level Locations such as Content or Media in the Back Office, e.g.: +You can change the default path for top-level locations such as content or media in the back office, for example: ```yaml ibexa: @@ -269,8 +263,7 @@ ibexa: ## Content Scheduler snapshots Content Scheduler snapshots speed up the rendering of Content Scheduler blocks and reduce the space used in the database. -By default, five snapshots are stored, but you can modify this number with the following configuration, -depending on the complexity of the Content Scheduler blocks: +By default, five snapshots are stored, but you can modify this number with the following configuration, depending on the complexity of the Content Scheduler blocks: ``` yaml parameters: @@ -279,14 +272,13 @@ parameters: ## Repository-aware configuration -In your custom development, you can create Repository-aware configuration settings. +In your custom development, you can create repository-aware configuration settings. -This enables you to use different settings for different Repositories. +This enables you to use different settings for different repositories. !!! tip "SiteAccess-aware configuration" - If you need to use different settings per SiteAccess, not per Repository, - see [SiteAccess-aware configuration](siteaccess_aware_configuration.md). + If you need to use different settings per SiteAccess, not per repository, see [SiteAccess-aware configuration](siteaccess_aware_configuration.md). To do this, create a parser that implements `Ibexa\Bundle\Core\DependencyInjection\Configuration\RepositoryConfigParserInterface`: diff --git a/docs/administration/content_organization/content_types.md b/docs/administration/content_organization/content_types.md index 43f08cbb0d..708507f67a 100644 --- a/docs/administration/content_organization/content_types.md +++ b/docs/administration/content_organization/content_types.md @@ -5,65 +5,79 @@ description: A content type is a base for new content items. # Content types A content type is a base for new content items. -It defines what Fields will be available in the content item. +It defines what fields are available in the content item. ![Content types](admin_panel_content_types.png "Content types") -For example, a new content type called *Article* can have Fields such as title, author, body, image, etc. +For example, a new content type called *Article* can have fields such as title, author, body, or image. Based on this content type, you can create any number of content items. -content types are organized into groups. +Content types are organized into groups. ![Content type groups](admin_panel_content_type_groups.png "Content type groups") You can add your own groups here to keep your content types in better order. -For a full tutorial, see [Add a content type](first_steps.md#add-a-content-type) or follow [user documentation](https://doc.ibexa.co/projects/userguide/en/latest/content_management/create_edit_content_types/). +For a full tutorial, see [Add a content type](first_steps.md#add-a-content-type) or follow [User Documentation](https://doc.ibexa.co/projects/userguide/en/latest/content_management/create_edit_content_types/). For a detailed overview of the content model, see [Content model overview](content_model.md). ## Content type metadata Each content type is characterized by a set of metadata which define the general behavior of its instances: -**Name** – a user-friendly name that describes the content type. This name is used in the interface, but not internally by the system. It can consist of letters, digits, spaces and special characters; the maximum length is 255 characters. (Mandatory.) +**Name** – a user-friendly name that describes the content type. +This name is used in the interface, but not internally by the system. +It can consist of letters, digits, spaces, and special characters (it's mandatory and the maximum length is 255 characters). !!! note - Note that even if your content type defines a Field intended as a name for the content item (for example, a title of an article or product name), do not confuse it with this Name, which is a piece of metadata, not a Field. + Even if your content type defines a field intended as a name for the content item (for example, a title of an article or product name), don't confuse it with this Name, which is a piece of metadata, not a field. -**Identifier** – an identifier for internal use in configuration files, templates, PHP code, etc. It must be unique, can only contain lowercase letters, digits and underscores; the maximum length is 50 characters. (Mandatory.) +**Identifier** – an identifier for internal use in configuration, for example, files, templates, or PHP code. +It must be unique, can only contain lowercase letters, digits, and underscores (it's mandatory and the maximum length is 50 characters). -**Description** – a detailed description of the content type. (Optional.) +**Description** – a detailed description of the content type (optional). -**Content name pattern** – a pattern that defines what name a new content item based on this content type gets. The pattern usually consists of Field identifiers that tell the system which Fields it should use when generating the name of a content item. Each Field identifier has to be surrounded with angle brackets. Text outside the angle brackets will be included literally. If no pattern is provided, the system will automatically use the first Field. (Optional.) +**Content name pattern** – a pattern that defines what name a new content item based on this content type gets. +The pattern usually consists of field identifiers that tell the system which fields it should use when generating the name of a content item. +Each field identifier has to be surrounded with angle brackets. +Text outside the angle brackets is included literally. +If no pattern is provided, the system automatically uses the first field (optional). -**URL alias name pattern** – a pattern which controls how the virtual URLs of the Locations will be generated when content items are created based on this content type. Note that only the last part of the virtual URL is affected. The pattern works in the same way as the Content name pattern. Text outside the angle brackets will be converted using the selected method of URL transformation. If no pattern is provided, the system will automatically use the name of the content item itself. (Optional.) +**URL alias name pattern** – a pattern which controls how the virtual URLs of the locations are generated when content items are created based on this content type. +Only the last part of the virtual URL is affected. +The pattern works in the same way as the content name pattern. +Text outside the angle brackets is converted with the selected method of URL transformation. +If no pattern is provided, the system automatically uses the name of the content item itself (optional). -!!! tip "Changing URL alias and Content name patterns" +!!! tip "Changing URL alias and content name patterns" - If you change the Content name pattern or the URL alias name pattern, - existing content items will not be modified automatically. - The new pattern will only be applied after you modify the content item and save a new version. + If you change the content name pattern or the URL alias name pattern, existing content items cannot be modified automatically. + The new pattern is only applied after you modify the content item and save a new version. - The old URL aliases will continue to redirect to the same content items. + The old URL aliases continue to redirect to the same content items. **Container** – a flag which indicates if content items based on this content type are allowed to have sub-items or not (mainly relevant for actions via the UI, not validated by every PHP API). !!! note - This flag was added for convenience and only affects the interface. In other words, it doesn't control any actual low-level logic, it simply controls the way the graphical user interface behaves. + This flag was added for convenience and only affects the interface. + In other words, it doesn't control any actual low-level logic, it simply controls the way the graphical user interface behaves. -**Sort children by default by** – rule for sorting sub-items. If the instances of this content type can serve as containers, their children will be sorted according to what is selected here. +**Sort children by default by** – rule for sorting sub-items. +If the instances of this content type can serve as containers, their children are sorted according to what is selected here. -**Sort children by default in order** – another rule for sorting sub-items. This decides the sort order for the criterion chosen above. +**Sort children by default in order** – another rule for sorting sub-items. +This decides the sort order for the criterion chosen above. -**Make content available even with missing translations** – a flag which indicates if content items of this content type should be available even without a corresponding language version. See [Content availability](content_availability.md). +**Make content available even with missing translations** – a flag which indicates if content items of this content type should be available even without a corresponding language version. +See [Content availability](content_availability.md). ![Creating a new content type](admin_panel_new_content_type.png) ## Field definitions -Aside from the metadata, a content type may contain any number of Field definitions (but has to contain at least one). -They determine what Fields of what Field Types will be included in all content items based on this content type. +Aside from the metadata, a content type may contain any number of field definitions (but has to contain at least one). +They determine what fields of what field types are included in all content items based on this content type. ![Field definitions](admin_panel_field_definitions.png) @@ -71,15 +85,16 @@ They determine what Fields of what Field Types will be included in all content i !!! note - You can assign each Field defined in a content type to a group by selecting one of the groups in the Category drop-down. [Available groups can be configured in the content repository](repository_configuration.md). + You can assign each field defined in a content type to a group by selecting one of the groups in the Category drop-down. + [Available groups can be configured in the content repository](repository_configuration.md). !!! caution - In case of content types containing many Field Types you should be aware of possible memory-related issues with publishing/editing. - They are caused by the limitation of how many `$_POST` input variables can be accepted. + In case of content types containing many field types you should be aware of possible memory-related issues with publishing/editing. + They're caused by the limitation of how many `$_POST` input variables can be accepted. The easiest way to fix them is by increasing the `max_input_vars` value in the `php.ini` configuration file. - Note that this solution is not universally recommended and you're proceeding on your own risk. + This solution isn't universally recommended and you're proceeding on your own risk. Setting the limit inappropriately may damage your project or cause other issues. You may also experience performance problems with such large content types, in particular when you have many content items. @@ -87,18 +102,16 @@ They determine what Fields of what Field Types will be included in all content i ## Modifying content types -A content type and its Field definitions can be modified after creation, -even if there are already content items based on it in the system. -When a content type is modified, each of its instances will be changed as well. -If a new Field definition is added to a content type, this Field will appear (empty) in every relevant content item. -If a Field definition is deleted from the content type, all the corresponding Fields will be removed from content items of this type. +A content type and its field definitions can be modified after creation, even if there are already content items based on it in the system. +When a content type is modified, each of its instances are changed as well. +If a new field definition is added to a content type, this field appears (empty) in every relevant content item. +If a field definition is deleted from the content type, all the corresponding fields are removed from content items of this type. ## Removing content types -System content types are by default used for the File Uploads and removing them will cause errors. +System content types are by default used for the File Uploads and removing them can cause errors. -If you decide to remove a `file` or `image` content type, or change their identifiers, -you will need to change the configuration, so it reflects the available content types. +If you decide to remove a `file` or `image` content type, or change their identifiers, you need to change the configuration, so it reflects the available content types. Example configuration: diff --git a/docs/administration/content_organization/object_states.md b/docs/administration/content_organization/object_states.md index 71b5c90f86..96b304f45e 100644 --- a/docs/administration/content_organization/object_states.md +++ b/docs/administration/content_organization/object_states.md @@ -2,22 +2,22 @@ description: Object states are user-defined states that can be assigned to content items. --- -## Object States +# Object states Object states are user-defined states that can be assigned to content items. -They are contained in groups. +They're contained in groups. -![Object State group](admin_panel_object_state_groups.png "Object State group") +![Object State group](admin_panel_object_state_groups.png "Object state group") If a state group contains any states, each content item is automatically assigned a state from this group. -You can assign states to content in the Back Office in the content item's **Technical details** tab. +You can assign states to content in the back office in the content item's **Technical details** tab. -![Assigning an Object state to a content item](assigning_an_object_state.png "Assigning an Object state to a content item") +![Assigning an object state to a content item](assigning_an_object_state.png "Assigning an object state to a content item") -By default, [[= product_name =]] contains one Object state group: **Lock**, with states **Locked** and **Not locked**. +By default, [[= product_name =]] contains one object state group: **Lock**, with states **Locked** and **Not locked**. -![**Lock** Object state](object_state_lock.png "Lock Object state") +![**Lock** Object state](object_state_lock.png "Lock object state") -Object states can be used in conjunction with [permissions](permission_overview.md), in particular with the [Object State Limitation](limitation_reference.md#object-state-limitation). +Object states can be used in conjunction with [permissions](permission_overview.md), in particular with the [object state limitation](limitation_reference.md#object-state-limitation). Their specific use cases depend on your needs and the setup of your permission system. \ No newline at end of file diff --git a/docs/administration/content_organization/sections.md b/docs/administration/content_organization/sections.md index d38d4bd78b..2a2a369537 100644 --- a/docs/administration/content_organization/sections.md +++ b/docs/administration/content_organization/sections.md @@ -2,37 +2,41 @@ description: Sections are used to divide content items in the tree. --- -## Sections +# Sections -Sections are used to divide content items in the tree into groups that are more easily manageable by content editors. -Division into Sections allows you, among others, to set [permissions](permission_overview.md) for only a part of the tree. +Sections are used to divide content items in the tree into groups that are more manageable by content editors. +Division into sections allows you, among others, to set [permissions](permission_overview.md) for only a part of the tree. ![Sections screen](admin_panel_sections.png "Sections screen") -Technically, a Section is a number, a name and an identifier. -Content items are placed in Sections by being assigned the Section ID. One item can be in only one Section. +Technically, a section is a number, a name, and an identifier. +Content items are placed in sections by being assigned the section ID. +One item can be in only one section. -When a new content item is created, its Section ID is set to the default Section (which is usually Standard). -When the item is published it is assigned to the same Section as its parent. Because content must always be in a Section, unassigning happens by choosing a different Section to move it into. -If a content item has multiple Location assignments then it is always the Section ID of the item referenced by the parent of the main Location that will be used. -In addition, if the main Location of a content item with multiple Location assignments is changed then the Section ID of that item will be updated. +When a new content item is created, its section ID is set to the default section (which is usually Standard). +When the item is published it is assigned to the same section as its parent. +Because content must always be in a section, unassigning happens by choosing a different section to move it into. +If a content item has multiple location assignments then it is always the section ID of the item referenced by the parent of the main location that is used. +In addition, if the main location of a content item with multiple location assignments is changed then the section ID of that item is updated. -When content is moved to a different Location, the item itself and all of its subtree will be assigned to the Section of the new Location. -Note that it works only for copy and move; assigning a new Section to a parent content item does not affect the subtree, meaning that subtree cannot currently be updated this way. +When content is moved to a different location, the item itself and all of its subtree are assigned to the section of the new location. +It works only for copy and move. +Assigning a new section to a parent content item doesn't affect the subtree, meaning that subtree cannot currently be updated this way. -Sections can only be removed if no content items are assigned to them. Even then, it should be done carefully. -When a Section is deleted, it is only its definition itself that will be removed. -Other references to the Section will remain and thus the system will most likely lose consistency. +Sections can only be removed if no content items are assigned to them. +Even then, it should be done carefully. +When a section is deleted, it's only its definition itself that is removed. +Other references to the section remain and thus the system most likely loses consistency. !!! caution - Removing Sections may corrupt permission settings, template output and other things in the system. + Removing sections may corrupt permission settings, template output and other things in the system. -Section ID numbers are not recycled. If a Section is removed, its ID number will not be reused when a new Section is created. +Section ID numbers aren't recycled. +If a section is removed, its ID number cannot be reused when a new section is created. ### Registering users Registration form for your website is placed under this address: /register. -By default, new Users created in this way are placed in the Guest accounts group. -To give your users a possibility to register themselves, follow the instructions -on [enabling account registration](8_enable_account_registration.md). \ No newline at end of file +By default, new users created in this way are placed in the Guest accounts group. +To give your users a possibility to register themselves, follow the instructions on [enabling account registration](8_enable_account_registration.md). \ No newline at end of file diff --git a/docs/administration/dashboard/configure_default_dashboard.md b/docs/administration/dashboard/configure_default_dashboard.md index 37e810b2b7..b373f2ec06 100644 --- a/docs/administration/dashboard/configure_default_dashboard.md +++ b/docs/administration/dashboard/configure_default_dashboard.md @@ -24,35 +24,36 @@ ibexa: container_content_type_identifier: folder ``` -Configuration can be set per [SiteAccess](multisite_configuration.md#siteaccess-configuration) -or [SiteAccess group](multisite_configuration.md#siteaccess-groups). +Configuration can be set per [SiteAccess](multisite_configuration.md#siteaccess-configuration) or [SiteAccess group](multisite_configuration.md#siteaccess-groups). -All the settings in the configuration are reflected in the Back Office. +All the settings in the configuration are reflected in the back office. ## Container remote ID Defines starting location container for all the dashboards, including customized and predifined ones. -You can see it in the Admin panel, **Dashboards** section, **Dashboards** folder in the Content Tree. In the **Technical details** tab, it is defined as **Location remote ID**. +You can see it in the **Admin** panel, **Dashboards** section, **Dashboards** folder in the content tree. +In the **Technical details** tab, it is defined as **Location remote ID**. ![Container remote ID](dashboard_container_remote_id.png) ## Default dashboard remote ID -Specifies default predefined dashboard. This is the dashboard that all the users see as a starting dashboard in the Back Office. -You can see it in the Admin panel, **Dashboards** section, **Default dashboard** folder inside of **Predefined dashboards** container in the Content Tree. -In the **Technical details** tab, it is defined as **Location remote ID**. +Specifies default predefined dashboard. +All the users can see this dashboard as a starting dashboard in the back office. +You can see it in the **Admin** panel, **Dashboards** section, **Default dashboard** folder inside of **Predefined dashboards** container in the content tree. +In the **Technical details** tab, it's defined as **Location remote ID**. ## Users container remote ID Defines a container for users folders, which contain all customized dashboards. -You can see it in the Admin panel, **Dashboards** section, **User dashboards** folder inside of main **Dashboards** container in the Content Tree. -In the **Technical details** tab, it is defined as **Location remote ID**. +You can see it in the **Admin** panel, **Dashboards** section, **User dashboards** folder inside of main **Dashboards** container in the content tree. +In the **Technical details** tab, it's defined as **Location remote ID**. ## Predefined container remote ID Defines a container that contains all predefined dashboards created by Administrator. -You can see it in the Admin panel, **Dashboards** section, **Predefined dashboards** folder inside of main **Dashboards** container in the Content Tree. -In the **Technical details** tab, it is defined as **Location remote ID**. +You can see it in the **Admin** panel, **Dashboards** section, **Predefined dashboards** folder inside of main **Dashboards** container in the content tree. +In the **Technical details** tab, it's defined as **Location remote ID**. ## Section identifier @@ -61,7 +62,7 @@ Specifies the name of the [Section](sections.md). ## Content type identifier It is an identifier that represents dashboard content type. -You can find it in the Admin panel, **Dashboard content Ttpe** section, **View/Global properties** tab. +You can find it in the **Admin** panel, **Dashboard content Ttpe** section, **View/Global properties** tab. ![Content type identifier](dashboard_content_type_identifier.png) diff --git a/docs/administration/dashboard/customize_dashboard.md b/docs/administration/dashboard/customize_dashboard.md index 54a0b0f5b8..a68da7b749 100644 --- a/docs/administration/dashboard/customize_dashboard.md +++ b/docs/administration/dashboard/customize_dashboard.md @@ -10,13 +10,13 @@ Customized dashboard displays a set of widgets selected by the user. !!! tip - Detailed instruction on how to customize dashboard using Dashboard Builder is available in [[[= product_name =]] user documentation](https://doc.ibexa.co/projects/userguide/en/latest/getting_started/dashboard/work_with_dashboard/#customize-dashboard). + For detailed instruction on how to customize dashboards with the Dashboard Builder, see [User Documentation](https://doc.ibexa.co/projects/userguide/en/latest/getting_started/dashboard/work_with_dashboard/#customize-dashboard). ## Manage permissions To customize dashboard, you need to have `dashboard/cutomize` [policy](permission_overview.md). -By default, all the users belonging to the `Editors` User Group, have `Dashboard`[Role](roles_admin_panel.md) assigned, so they can edit, create, or delete dashboard. +By default, all the users belonging to the `Editors` user group, have `Dashboard`[role](roles_admin_panel.md) assigned, so they can edit, create, or delete dashboard. If, by any reason, you want to narrow this permission, you can set up specific [limitations](limitations.md). ## Add custom layout @@ -30,10 +30,10 @@ For more information, see [Customize storefront layout](customize_storefront_lay ## Create custom blocks -Dashboard builder provides set of ready-to-use blocks, for example, Common content, Quick actions, or [[= product_name =]] News. +Dashboard Builder provides set of ready-to-use blocks, for example, Common content, Quick actions, or [[= product_name =]] News. -For more information about available blocks, see [[[= product_name =]] user documentation](https://doc.ibexa.co/projects/userguide/en/latest/getting_started/dashboard/dashboard_block_reference/). +For more information about available blocks, see [User Documentation](https://doc.ibexa.co/projects/userguide/en/latest/getting_started/dashboard/dashboard_block_reference/). In addition to existing blocks available in Dashboard Builder, you can also create custom blocks. -To do it, follow the instruction on how to [create custom Page block](create_custom_page_block.md). \ No newline at end of file +To do it, follow the instruction on how to [create custom page block](create_custom_page_block.md). \ No newline at end of file diff --git a/docs/administration/project_organization/architecture.md b/docs/administration/project_organization/architecture.md index 71c2c9b128..56b723c31c 100644 --- a/docs/administration/project_organization/architecture.md +++ b/docs/administration/project_organization/architecture.md @@ -4,10 +4,10 @@ description: Ibexa DXP architecture is structured in multiple layers connected b # Architecture -[[= product_name =]] architecture is based on the philosophy to **use APIs** that will be maintained in the long term. This **makes upgrades easier and provides lossless couplings** between all parts of the architecture, at the same time improving the migration capabilities of the system. +[[= product_name =]] architecture is based on the philosophy to **use APIs** that is maintained in the long term. +This **makes upgrades easier and provides lossless couplings** between all parts of the architecture, at the same time improving the migration capabilities of the system. -The structure of an [[= product_name =]] app is based on the Symfony framework -but content management functions rely on the public PHP API. +The structure of an [[= product_name =]] app is based on the Symfony framework but content management functions rely on the public PHP API. Other applications integrate with [[= product_name =]] via REST API, which also relies on the public PHP API. ![Architecture](architecture.png "Architecture") @@ -16,15 +16,15 @@ The architecture of [[= product_name =]] is layered and uses clearly defined API | Layer | Description | |-----------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| [Back Office](back_office_configuration.md) | Back Office contains all the necessary parts to run the [[= product_name =]] Back Office interface. | +| [Back office](back_office_configuration.md) | Back office contains all the necessary parts to run the [[= product_name =]] back office interface. | | [HTTP Cache](http_cache.md)) | Symfony HTTP cache is used to manage content "view" cache with an expiration model. In addition it is extended by using FOSHttpCache to add several advanced features. | | [Controllers](controllers.md) | Controllers created by you to read information from a Request object, create and return a Response objects. | | [Twig templates](twig_function_reference.md) | Set of custom and built-in Twig templates. User interfaces are developed with the Twig template engine and query the public PHP API directly. | -| [REST API v2](rest_api_usage.md) | The REST API v2 enables you to interact with an [[= product_name =]] installation using the HTTP protocol, following a REST interaction model. | -| [GraphQL](graphql.md) | GraphQL for [[= product_name =]] exposes the domain model using the Repository, based on content type groups, content types and Field definitions. | -| [Public PHP API](php_api.md) | Public PHP API exposes the Repository which enables you to create, read, update, manage and delete all objects available in [[= product_name =]]. | +| [REST API v2](rest_api_usage.md) | The REST API v2 enables you to interact with an [[= product_name =]] installation through the HTTP protocol, following a REST interaction model. | +| [GraphQL](graphql.md) | GraphQL for [[= product_name =]] exposes the domain model using the repository, based on content type groups, content types and field definitions. | +| [Public PHP API](php_api.md) | Public PHP API exposes the repository which enables you to create, read, update, manage and delete all objects available in [[= product_name =]]. | | Business Logic | The business logic is defined in the kernel. This business logic is exposed to applications via an API. It is used to organize development of the user interface layer. | -| SPI | Service Provider Interface which defines contracts for implementing various parts of the system, including persistence layer (`SPI\Persistence`), custom Field Types, custom Limitations, etc. | +| SPI | Service Provider Interface which defines contracts for implementing various parts of the system, including persistence layer (`SPI\Persistence`), custom field types, custom limitations, and more. | | [Persistence cache](persistence_cache.md) | The implementation of SPI\Persistence that decorates the main backend implementation. | | [Search](search.md) | Search API that allows both full-text search and querying the content. | | [SQL Storage Engine](legacy_search_overview.md) | Legacy search engine is SQL-based and uses Doctrine's database connection. | diff --git a/docs/administration/project_organization/bundles.md b/docs/administration/project_organization/bundles.md index a48ecb51cf..81106c4067 100644 --- a/docs/administration/project_organization/bundles.md +++ b/docs/administration/project_organization/bundles.md @@ -10,15 +10,13 @@ You can [create bundles yourself](package_structure.md) or make use of available You can also reuse the bundles you create in other projects or share them with the community. Many [[= product_name =]] functionalities are provided through separate bundles included in the installation. -You can see the bundles that are automatically installed with [[= product_name =]] -in the respective `composer.json` files. +You can see the bundles that are automatically installed with [[= product_name =]] in the respective `composer.json` files. For example, for [[= product_name_headless =]], see the [JSON file on GitHub](https://github.com/ibexa/headless/blob/master/composer.json). !!! caution "Deprecated legacy Commerce bundles" - As of [[= product_name =]] v4.4 all `ibexa/commerce` packages are deprecated. - They are gradually replaced by their revamped counterparts and removed - completely from the product in version v5.0. + As of [[= product_name =]] v4.4 all `ibexa/commerce` packages are deprecated. + They're gradually replaced by their revamped counterparts and removed completely from the product in version v5.0. ## Working with bundles @@ -29,14 +27,13 @@ To learn how to create your own bundles, see [Symfony documentation on bundles]( ### Overriding third-party bundles -When you use an external bundle, you can override its parts, such as templates, controllers, etc. +When you use an external bundle, you can override its parts, such as templates or controllers. To do so, make use of [Symfony's bundle override mechanism]([[= symfony_doc =]]/bundles/override.html). -Note that when overriding files, the path inside your application has to correspond to the path inside the bundle. +When overriding files, the path inside your application has to correspond to the path inside the bundle. ### Removing bundles -To remove a bundle (either one you created yourself, or an out-of-the-box one that you do not need), -see the [How to Remove a Bundle]([[= symfony_doc =]]/bundles/remove.html) instruction in Symfony doc. +To remove a bundle (either one you created yourself, or an out-of-the-box one that you don't need), see the [How to Remove a Bundle]([[= symfony_doc =]]/bundles/remove.html) instruction in Symfony doc. ## Core packages @@ -46,17 +43,17 @@ see the [How to Remove a Bundle]([[= symfony_doc =]]/bundles/remove.html) instru |Bundle|Description| |---------|-----------| -|[ibexa/admin-ui](https://github.com/ibexa/admin-ui)|Back Office interface| -|[ibexa/admin-ui-assets](https://github.com/ibexa/admin-ui-assets)|Assets for the Back Office| -|[ibexa/content-forms](https://github.com/ibexa/content-forms)|Form-based integration for the Symfony Forms into Content and User objects in kernel| +|[ibexa/admin-ui](https://github.com/ibexa/admin-ui)|Back office interface| +|[ibexa/admin-ui-assets](https://github.com/ibexa/admin-ui-assets)|Assets for the back office| +|[ibexa/content-forms](https://github.com/ibexa/content-forms)|Form-based integration for the Symfony Forms into content and user objects in kernel| |[ibexa/core](https://github.com/ibexa/core)|Core of the [[= product_name =]] application| |[ibexa/core-persistence](https://github.com/ibexa/core-persistence)|Core system persistence| |[ibexa/cron](https://github.com/ibexa/cron)|Cron package for use with the `ibexa:cron:run` command| |[ibexa/design-engine](https://github.com/ibexa/design-engine)|[Design fallback system](design_engine.md)| |[ibexa/doctrine-schema](https://github.com/ibexa/doctrine-schema)| Basic abstraction layer for cross-DBMS schema import| -|[ibexa/fieldtype-matrix](https://github.com/ibexa/fieldtype-matrix)|[Matrix Field Type](matrixfield.md)| -|[ibexa/fieldtype-query](https://github.com/ibexa/fieldtype-query)|[Query Field Type](contentqueryfield.md)| -|[ibexa/fieldtype-richtext](https://github.com/ibexa/fieldtype-richtext)|Field Type for supporting rich-formatted text stored in a structured XML format| +|[ibexa/fieldtype-matrix](https://github.com/ibexa/fieldtype-matrix)|[Matrix field type](matrixfield.md)| +|[ibexa/fieldtype-query](https://github.com/ibexa/fieldtype-query)|[Query field type](contentqueryfield.md)| +|[ibexa/fieldtype-richtext](https://github.com/ibexa/fieldtype-richtext)|field type for supporting rich-formatted text stored in a structured XML format| |[ibexa/graphql](https://github.com/ibexa/graphql)|GraphQL server for [[= product_name =]]| |[ibexa/http-cache](https://github.com/ibexa/http-cache)|[HTTP cache handling](http_cache.md), using multi tagging| |[ibexa/i18n](https://github.com/ibexa/i18n)|Centralized translations to ease synchronization with Crowdin| @@ -68,22 +65,22 @@ see the [How to Remove a Bundle]([[= symfony_doc =]]/bundles/remove.html) instru |[ibexa/system-info](https://github.com/ibexa/system-info)| Information about the system [[= product_name =]] is running on| |[ibexa/user](https://github.com/ibexa/user)|User management| -## Ibexa Headless packages +## [[= product_name_headless =]] packages |Bundle|Description| |---------|-----------| |ibexa/oss|Core packages| -|ibexa/content-tree|Content Tree functionality| -|ibexa/connect|[Ibexa Connect](https://doc.ibexa.co/projects/connect/en/latest/)| +|ibexa/content-tree|content tree functionality| +|ibexa/connect|[[[= product_name_connect =]]](https://doc.ibexa.co/projects/connect/en/latest/)| |ibexa/calendar|Calendar tab with a calendar widget| |ibexa/connector-dam|Connector for DAM (Digital Asset Management) systems| |ibexa/elasticsearch|Integration with Elasticsearch search engine| |ibexa/fastly|Fastly support for `http-cache`, for use on Platform.sh or standalone| -|ibexa/icons|Icon set for the Back Office| +|ibexa/icons|Icon set for the back office| |ibexa/image-editor|[Image Editor](configure_image_editor.md)| |ibexa/installer|Provides the `ibexa:install` command| -|ibexa/measurement|Measurement Field Type and measurement product catalog attribute| -|ibexa/migrations|[Migration of Repository data](data_migration.md)| +|ibexa/measurement|Measurement field type and measurement product catalog attribute| +|ibexa/migrations|[Migration of repository data](data_migration.md)| |[ibexa/oauth2-client](oauth_client.md)|Authenticate user through a third-party OAuth 2 server, integration with [`knpuniversity/oauth2-client-bundle`](https://github.com/knpuniversity/oauth2-client-bundle)| |[ibexa/oauth2-server](oauth_server.md)|Allow resource access to OAuth 2 client| |ibexa/personalization|Functionality for personalized recommendations| @@ -92,26 +89,26 @@ see the [How to Remove a Bundle]([[= symfony_doc =]]/bundles/remove.html) instru |ibexa/seo|Search Engine Optimization (SEO) tool| |ibexa/taxonomy|Taxonomy functionality| |ibexa/tree-builder|Tree builder functionality| -|ibexa/version-comparison|Enables comparing between two versions of the same Field| +|ibexa/version-comparison|Enables comparing between two versions of the same field| |ibexa/workflow|Collaboration feature that enables you to send content draft to any user for a review or rewriting| |ibexa/recommendation-client|Client for connecting with the personalization engine **deprecated**| |ibexa/commerce-base-design|Standard design and theme for the shop **deprecated** | |ibexa/commerce-checkout|Shop checkout functionality **deprecated** | -|ibexa/commerce-fieldtypes|Shop-specific Field Types **deprecated** | +|ibexa/commerce-fieldtypes|Shop-specific field types **deprecated** | |ibexa/commerce-price-engine|Engine for handling prices **deprecated** | |ibexa/commerce-shop-ui|UI for the shop front page **deprecated** | |ibexa/commerce-shop|Main shop functionalities **deprecated** | -## Ibexa Experience packages +## [[= product_name_exp =]] packages |Bundle|Description| |---------|-----------| |ibexa/headless|Metapackage for Symfony Flex-based [[= product_name =]] Headless installation| |ibexa/corporate-account|Customer portal and corporate accounts| -|ibexa/fieldtype-address|Address handling Field Type| +|ibexa/fieldtype-address|Address handling field type| |ibexa/form-builder|Enables creating Form content items with multiple form fields| |ibexa/page-builder|Page editor| -|ibexa/fieldtype-page|Page handling Field Type| +|ibexa/fieldtype-page|Page handling field type| |ibexa/permissions|Additional permission functionalities| |ibexa/segmentation|Segment functionality for profiling the content displayed to specific users| |ibexa/site-factory|Enables configuration of sites from UI| @@ -119,18 +116,18 @@ see the [How to Remove a Bundle]([[= symfony_doc =]]/bundles/remove.html) instru |ibexa/connector-qualifio|Enables integration with [Qualifio Engage platform](https://developers.qualifio.com/docs/engage/)| -## Ibexa Commerce packages +## [[= product_name_com =]] packages |Bundle|Description| |---------|-----------| |ibexa/experience|Metapackage for Symfony Flex-based [[= product_name =]] Experience installation| |ibexa/cart|Main store functionalities| |ibexa/checkout|Store checkout functionality| -|ibexa/storefront|A store front starting kit| +|ibexa/storefront|A storefront starting kit| |ibexa/order-management|Order management| |ibexa/payment|Payment handling| |ibexa/shipping|Shipping handling| -|ibexa/commerce-admin-ui|Shop-related Back Office functionalities **deprecated** | +|ibexa/commerce-admin-ui|Shop-related back office functionalities **deprecated** | |ibexa/commerce-erp-admin|ERP connection for the shop **deprecated** | |ibexa/commerce-order-history|Order history functionality **deprecated** | |ibexa/commerce-page-builder|Shop-related Page blocks **deprecated** | diff --git a/docs/administration/project_organization/project_organization.md b/docs/administration/project_organization/project_organization.md index 0ab2682a4c..9f0a24bdfb 100644 --- a/docs/administration/project_organization/project_organization.md +++ b/docs/administration/project_organization/project_organization.md @@ -6,13 +6,13 @@ description: An Ibexa DXP project follows Symfony's directory structure to organ [[= product_name =]] is a Symfony application and follows the project structure used by Symfony. -You can see an example of organizing a simple project in the [companion repository](https://github.com/ezsystems/ezplatform-ee-beginner-tutorial/tree/v3-master) for the [Beginner tutorial](page_and_form_tutorial.md). +You can see an example of organizing a project in the [companion repository](https://github.com/ezsystems/ezplatform-ee-beginner-tutorial/tree/v3-master) for the [Beginner tutorial](page_and_form_tutorial.md). ## PHP code -The project's PHP code (controllers, event listeners, etc.) should be placed in the `src` folder. +The project's PHP code (for example, controllers or event listeners) should be placed in the `src` folder. -Reusable libraries should be packaged so that they can easily be managed using Composer. +Reusable libraries should be packaged so that they can be managed with Composer. ## Templates @@ -23,7 +23,6 @@ They can then be referenced in code without any prefix, for example `templates/ ## Assets Project assets should go into the `assets` folder. - They can be referenced as relative to the root, for example `assets/js/script.js` can be referenced as `js/script.js` from templates. All project assets are accessible through the `assets` path. @@ -32,7 +31,7 @@ All project assets are accessible through the `assets` path. If you ever remove the `assets` folder manually, you need to dump translations before performing the `yarn encore ` command: - + ``` php bin/console bazinga:js-translation:dump assets --merge-domains ``` @@ -40,12 +39,11 @@ All project assets are accessible through the `assets` path. ## Configuration You project's configuration is placed in the respective files in `config/packages`. -See [Configuration](configuration.md) for more information. +For more information, see [Configuration](configuration.md). ### Importing configuration from a bundle -If you are keeping some of your code in a bundle, dealing with core bundle semantic configuration can be tedious -if you maintain it in the main `config/packages/ibexa.yaml` configuration file. +If you're keeping some of your code in a bundle, dealing with core bundle semantic configuration can be tedious if you maintain it in the main `config/packages/ibexa.yaml` configuration file. You can import configuration from a bundle by following the Symfony tutorial [How to Import Configuration Files/Resources]([[= symfony_doc =]]/service_container/import.html). diff --git a/docs/administration/recent_activity/recent_activity.md b/docs/administration/recent_activity/recent_activity.md index 1d36b5dcf6..9ff3497970 100644 --- a/docs/administration/recent_activity/recent_activity.md +++ b/docs/administration/recent_activity/recent_activity.md @@ -4,18 +4,18 @@ description: Log and monitor activity through UI, PHP API and REST API. # Recent activity [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] -Recent activity log displays last actions in the repository (whatever their origin is, for example, Back Office, REST, migration, CLI, or CRON). +Recent activity log displays last actions in the repository (whatever their origin is, for example, back office, REST, migration, CLI, or CRON). ![Recent activity](admin_panel_recent_activity.png) -To learn more about its Back Office usage and the actions logged by default, see [Recent activity in the User documentation]([[= user_doc =]]/recent_activity/recent_activity/). +To learn more about its back office usage and the actions logged by default, see [Recent activity in User Documentation]([[= user_doc =]]/recent_activity/recent_activity/). ## Configuration and cronjob With some configuration, you can customize the log length in the database or on screen. A command maintains the log size in database, it should be scheduled through CRON. -- The configuration `ibexa.system..activity_log.pagination.activity_logs_limit` sets the number of log items shown per page in the Back Office (default value: 25). +- The configuration `ibexa.system..activity_log.pagination.activity_logs_limit` sets the number of log items shown per page in the back office (default value: 25). A log item is a group of entries, or an entry without group. - The configuration `ibexa.repositories..activity_log.truncate_after_days` sets the number of days a log entry is kept before it's deleted by the `ibexa:activity-log:truncate` command (default value: 30 days). @@ -45,13 +45,12 @@ For every exact hour, the cronjob line is: The [`activity_log/read`](policies.md#activity-log) policy gives a role the access to the **Admin** -> **Activity list**, the dashboard's **Recent activity** block, and the user profile's **Recent activity**. It can be limited to "Only own logs" ([`ActivityLogOwner`](limitation_reference.md#activitylogowner-limitation)). -The policy should be given to every roles having access to the Back Office, at least with the `ActivityLogOwner` owner limitation, -to allow them to use the "Recent activity" block in the [default dashboard](configure_default_dashboard.md) or their [custom dashboard](customize_dashboard.md). +The policy should be given to every roles having access to the back office, at least with the `ActivityLogOwner` owner limitation, to allow them to use the "Recent activity" block in the [default dashboard](configure_default_dashboard.md) or their [custom dashboard](customize_dashboard.md). This policy is required to view [activity log in user profile]([[= user_doc =]]/recent_activity/recent_activity/#user-profile), if [profile]([[= user_doc =]]/getting_started/get_started/#edit-user-profile) is enabled. !!! caution - Do not assign `activity_log/read` permission to the Anonymous role, even with the owner limitation, because this role is shared among all unauthenticated users. + Don't assign `activity_log/read` permission to the Anonymous role, even with the owner limitation, because this role is shared among all unauthenticated users. ## User privacy @@ -60,11 +59,9 @@ This policy is required to view [activity log in user profile]([[= user_doc =]]/ A username of the User who performs the action is logged. When acting through the web server, the User's IP address is also logged. Other access, such as console commands, doesn't log an IP. - Your Data Protection Officer or GDPR representative should be aware of this, - so they can ensure users are informed if needed, depending on your use case, jurisdiction, and company policy. + Your Data Protection Officer or GDPR representative should be aware of this, so they can ensure users are informed if needed, depending on your use case, jurisdiction, and company policy. - For example, if a content edition feature, such as reader's comments, is available in the front office, - the recent activity log records the front users' IPs. + For example, if a content edition feature, such as reader's comments, is available in the front office, the recent activity log records the front users' IPs. ## PHP API @@ -133,7 +130,7 @@ migration !!! caution Keep activity logging as light as possible. - Do not make database requests or heavy computation at logging time. + Don't make database requests or heavy computation at logging time. Keep them for activity log list display time. #### Create an entry @@ -166,20 +163,20 @@ This stored name can be used at the time of displaying information whether the a #### Context group If you log several related entries at once, you can group them into a context. -Context is a set of actions done for the same purpose, for example, it could group the actions of a CRON that fetches third party data and updates Content items. +Context is a set of actions done for the same purpose, for example, it could group the actions of a CRON that fetches third party data and updates content items. The built-in contexts include: -- `web` - groups actions made in the Back Office, like the update and the publishing of a new content item's version +- `web` - groups actions made in the back office, like the update and the publishing of a new content item's version - `migration` - groups every action from a migration file execution A context group counts as one item in regard to `activity_logs_limit` configuration and `ActivityLogService::findGroups`'s `$limit` argument. To open a context group, use `ActivityLogService::prepareContext` which has two arguments: -- `$source` - describes, usually through a short identifier, what is triggering the set of actions. -For example, some already existing sources are `web` (incl. actions from the Back Office), `graphql`, `rest` and `migration` +- `$source` - describes, usually through a short identifier, what is triggering the set of actions. +For example, some already existing sources are `web` (incl. actions from the back office), `graphql`, `rest` and `migration` - `$description` - an optional, more specific contextualisation. -For example, `migration` context source is associated with the migration file name in its context description +For example, `migration` context source is associated with the migration file name in its context description. To close a context group, use `ActivityLogService::dismissContext`. @@ -200,7 +197,7 @@ Context groups can't be nested. If a new context is prepared when a context is already grouping log entries, this new context is ignored. To start a new context, make sure to previously dismiss the existing one. -When displayed in the Back Office, a context group is folded below its first entry. +When displayed in the back office, a context group is folded below its first entry. The `my_feature` context from the example is folded below its first action, the `init` action. Other actions are displayed after you click the **Show more** button. @@ -208,7 +205,7 @@ Other actions are displayed after you click the **Show more** button. #### Display log entries -To display your log entry, if your object's PHP class isn't already covered, you'll have to: +To display your log entry, if your object's PHP class isn't already covered, you have to: - implement `ClassNameMapperInterface` to associate the class name with an identifier, - eventually create a `PostActivityListLoadEvent` subscriber if you need to load the object for the template, diff --git a/docs/api/event_reference/event_reference.md b/docs/api/event_reference/event_reference.md index 2bfa959037..014b9afec0 100644 --- a/docs/api/event_reference/event_reference.md +++ b/docs/api/event_reference/event_reference.md @@ -1,5 +1,5 @@ --- -description: Ibexa DXP dispatches events before and after you perform different operations in the Back Office and on the Repository. +description: Ibexa DXP dispatches events before and after you perform different operations in the back office and on the Repository. page_type: reference --- @@ -8,11 +8,9 @@ page_type: reference [[= product_name =]] dispatches events during different actions. You can subscribe to these events to extend the functionality of the system. -In most cases, two events are dispatched for every action, -one before the action is completed, and one after. +In most cases, two events are dispatched for every action, one before the action is completed, and one after. -For example, copying a content item is connected with two events: -`BeforeCopyContentEvent` and `CopyContentEvent`. +For example, copying a content item is connected with two events: `BeforeCopyContentEvent` and `CopyContentEvent`. ``` php `PolicyDraft $policyDraft`
`RoleDraft|null $updatedRoleDraft`| |`RemovePolicyByRoleDraftEvent`|`RoleService::removePolicyByRoleDraft`|`RoleDraft $roleDraft`
`PolicyDraft $policyDraft`
`RoleDraft $updatedRoleDraft`| -## Assigning Roles +## Assigning roles | Event | Dispatched by | Properties | |---|---|---| diff --git a/docs/api/event_reference/section_events.md b/docs/api/event_reference/section_events.md index 34a010d41f..dfc7234992 100644 --- a/docs/api/event_reference/section_events.md +++ b/docs/api/event_reference/section_events.md @@ -1,5 +1,5 @@ --- -description: Events that are triggered when working with Sections. +description: Events that are triggered when working with sections. page_type: reference --- @@ -14,7 +14,7 @@ page_type: reference |`BeforeUpdateSectionEvent`|`SectionService::updateSection`|`Section $section`
`SectionUpdateStruct $sectionUpdateStruct`
`Section|null $updatedSection`| |`UpdateSectionEvent`|`SectionService::updateSection`|`Section $section`
`SectionUpdateStruct $sectionUpdateStruct`
`Section $updatedSection`| -## Assigning Sections +## Assigning sections | Event | Dispatched by | Properties | |---|---|---| diff --git a/docs/api/event_reference/segmentation_events.md b/docs/api/event_reference/segmentation_events.md index 26f5ad3a6e..91967f6d4c 100644 --- a/docs/api/event_reference/segmentation_events.md +++ b/docs/api/event_reference/segmentation_events.md @@ -1,5 +1,5 @@ --- -description: Events that are triggered when working with Segments. +description: Events that are triggered when working with segments. page_type: reference --- diff --git a/docs/api/event_reference/user_events.md b/docs/api/event_reference/user_events.md index 072c661c4a..29d83c0e50 100644 --- a/docs/api/event_reference/user_events.md +++ b/docs/api/event_reference/user_events.md @@ -1,5 +1,5 @@ --- -description: Events that are triggered when working with users and User Groups. +description: Events that are triggered when working with users and user groups. page_type: reference --- @@ -14,7 +14,7 @@ page_type: reference |`BeforeDeleteUserEvent`|`UserService::deleteUser`|`User $user`
`array|null $locations`| |`DeleteUserEvent`|`UserService::deleteUser`|`User $user`
`array $locations`| -## User Groups +## User groups | Event | Dispatched by | Properties | |---|---|---| @@ -27,7 +27,7 @@ page_type: reference |`BeforeMoveUserGroupEvent`|`UserService::moveUserGroup`|`UserGroup $userGroup`
`UserGroup $newParent`| |`MoveUserGroupEvent`|`UserService::moveUserGroup`|`UserGroup $userGroup`
`UserGroup $newParent`| -## Assigning to User Groups +## Assigning to user groups | Event | Dispatched by | Properties | |---|---|---| diff --git a/docs/api/graphql/graphql.md b/docs/api/graphql/graphql.md index a2fce8c199..b3557da74a 100644 --- a/docs/api/graphql/graphql.md +++ b/docs/api/graphql/graphql.md @@ -20,45 +20,38 @@ php bin/console cache:clear ``` YAML files with the schema are located in `config/graphql/types/ibexa`. -They contain information about the domain objects and the fields -you can [query](graphql_queries.md) and [operate on](graphql_operations.md). +They contain information about the domain objects and the fields you can [query](graphql_queries.md) and [operate on](graphql_operations.md). ### Schema generation limitations -GraphQL schema cannot be generated for names that do not follow the [GraphQL specification](http://spec.graphql.org/June2018/#sec-Names), -for example names that start with a digit. +GraphQL schema cannot be generated for names that don't follow the [GraphQL specification](http://spec.graphql.org/June2018/#sec-Names), for example names that start with a digit. -This concerns image variations, content types, content type groups, product types, and Field definition identifiers. +This concerns image variations, content types, content type groups, product types, and field definition identifiers. -It is recommended to rename the relevant identifiers. Failure to generate schema is registered in logs. -To find identifiers that are not included in the schema, look for "Skipped schema generation" log messages, for example: -`Skipped schema generation for Image Variation`. +It's recommended to rename the relevant identifiers. Failure to generate schema is registered in logs. +To find identifiers that aren't included in the schema, look for "Skipped schema generation" log messages, for example: `Skipped schema generation for Image Variation`. ## Domain schema -GraphQL for [[= product_name =]] is based on the content types (including product types), content type groups, and content items -defined in the Repository. +GraphQL for [[= product_name =]] is based on the content types (including product types), content type groups, and content items defined in the repository. -For each content type the schema exposes a singular and plural field, e.g. `article` and `articles`. -Use the singular field to query a single content item, and the plural to get a whole `Connection` -(a list of content items that supports pagination). +For each content type the schema exposes a singular and plural field, for example, `article` and `articles`. +Use the singular field to query a single content item, and the plural to get a whole `Connection` (a list of content items that supports pagination). With the queries you can inspect: -- the existing types -- details of content types, and their Fields in the context of developing your own application +- the existing types +- details of content types, and their fields in the context of developing your own application -You can request additional content information such as the Section or Objects states, -available under the `_info` field. +You can request additional content information such as the section or Objects states, available under the `_info` field. You can also query content type and content type group information through the `_info` and `_types` fields. ### Repository schema -The repository schema, accessed through `_repository`, exposes the [[= product_name =]] Repository -in a manner similar to the [Public PHP API](php_api.md). +The repository schema, accessed through `_repository`, exposes the [[= product_name =]] repository in a manner similar to the [Public PHP API](php_api.md). -The `_repository` field also enables you to query e.g. Object states configured for the Repository. +The `_repository` field also enables you to query, for example, object states configured for the repository. ### Custom schemas @@ -69,8 +62,7 @@ You can also use your own [custom schema](graphql_customization.md#custom-schema GraphQL is SiteAccess-aware, but can have only one schema per installation. This means you cannot use GraphQL with multiple repositories. -When you request a URL from a SiteAccess that is different than the current one, -the API generates it for the content item's SiteAccess, with an absolute URL if necessary. +When you request a URL from a SiteAccess that is different than the current one, the API generates it for the content item's SiteAccess, with an absolute URL if necessary. ## Authentication @@ -79,8 +71,7 @@ You can get your session cookie by logging in through the interface or through a ### JWT authentication -If you have [JWT authentication](development_security.md#jwt-authentication) enabled, -you can use the following query to get your authentication token: +If you have [JWT authentication](development_security.md#jwt-authentication) enabled, you can use the following query to get your authentication token: ``` mutation CreateToken { @@ -113,7 +104,7 @@ You can access GraphQL with `/graphql`. The [GraphiQL interactive client](https://github.com/graphql/graphiql) is included in the installation. Access it through `/graphiql`. -Here you can run your queries and preview the results in an easy-to-read format. +Here you can run your queries and preview the results in a readable format. ### Reference diff --git a/docs/api/graphql/graphql_custom_ft.md b/docs/api/graphql/graphql_custom_ft.md index a71a9a78d9..30dc674d6d 100644 --- a/docs/api/graphql/graphql_custom_ft.md +++ b/docs/api/graphql/graphql_custom_ft.md @@ -1,10 +1,10 @@ --- -description: Add GraphQL support to custom Field Types. +description: Add GraphQL support to custom field types. --- -# Add GraphQL support to custom Field Types +# Add GraphQL support to custom field types -If you want to use custom Field Types in GraphQL, you need to map them. +If you want to use custom field types in GraphQL, you need to map them. Their values and field definition structure, need to be defined, to interact with them using GraphQL. For example: @@ -13,29 +13,30 @@ For example: | Text Line | string | default | `TextLineFieldDefinition` | | Relation List | `Item` `ArticleItem` `ImageItem` | customized | `RelationListFieldDefinitio` | -## Map a custom Field Type +## Map a custom field type -There are two ways of mapping a custom Field Type: +There are two ways of mapping a custom field type: - configuration - custom `FieldDefinitionMapper` -You need to write a custom `FieldDefinitionMapper` if the field definition settings and constraints impact how it is mapped to GraphQL. -For example, the selection Field Type has a "multiple" option. -If set to false, it accepts and returns a single value, -but if set to true, it accepts and returns an array of values. +You need to write a custom `FieldDefinitionMapper` if the field definition settings and constraints impact how it's mapped to GraphQL. +For example, the selection field type has a "multiple" option. +If set to false, it accepts and returns a single value, but if set to true, it accepts and returns an array of values. If your field definition doesn't require additional clarifications, you can map it with configuration. ### Map with configuration -To map a custom Field Type with configuration use a compiler pass to modify a container parameter, `ibexa.graphql.schema.content.mapping.field_definition_type`. +To map a custom field type with configuration use a compiler pass to modify a container parameter, `ibexa.graphql.schema.content.mapping.field_definition_type`. -It is a hash that maps a Field Type identifier (`ezstring`) to the following entries: +It's a hash that maps a field type identifier (`ezstring`) to the following entries: -- `value_type` - the GraphQL type values of the custom field. It can be a native type (string, int), or a custom type. If none is specified, string will be used. -- `value_resolver` - how values of this field are resolved and passed to the defined value type. If not specified, it will receive the `Field` object for the field type: `field`. -- `definition_type` - the GraphQL type the field definitions is mapped to. If not specified, it will use `FieldDefinition`. +- `value_type` - the GraphQL type values of the custom field. It can be a native type (string, int), or a custom type. If none is specified, string is used. +- `value_resolver` - how values of this field are resolved and passed to the defined value type. +If not specified, it receives the `Field` object for the field type: `field`. +- `definition_type` - the GraphQL type the field definitions is mapped to. +If not specified, it uses `FieldDefinition`. Compiler pass example that should be placed in `src/DependencyInjection/Compiler`: @@ -46,8 +47,7 @@ Compiler pass example that should be placed in `src/DependencyInjection/Compiler ### Map with a custom `FieldDefinitionMapper` The `FieldDefinitionMapper` API uses service decorators. -To register your own mapper, make it decorate the -`Ibexa\GraphQL\Schema\Domain\Content\Mapper\FieldDefinition\DecoratingFieldDefinitionMapper` service: +To register your own mapper, make it decorate the `Ibexa\GraphQL\Schema\Domain\Content\Mapper\FieldDefinition\DecoratingFieldDefinitionMapper` service: ```yaml services: @@ -59,7 +59,7 @@ services: The `$innerMapper` argument passes the decorated mapper to the constructor. You can use the `DecoratingFieldDefinitionMapper` from the `graphql` package. -It requires that you implement the `getFieldTypeIdentifier` method to tell which Field Type is covered by the mapper. +It requires that you implement the `getFieldTypeIdentifier` method to tell which field type is covered by the mapper. Add `MyCustomFieldDefinitionMapper.php` mapper to `src/GraphQL/Schema`: @@ -74,9 +74,9 @@ The `FieldDefinitionMapper` interface defines following methods: - `mapToFieldValueResolver` - returns the resolver, as an expression language string, values are resolved with - `mapToFieldDefinitionType`- returns the GraphQL type field definitions of the mapped type -Only implement methods that you need, the rest will be handled by other mappers (configuration or default). +Only implement methods that you need, the rest is handled by other mappers (configuration or default). When a mapper method is decorated, you need to call the decorated service method for unsupported types. -To do that, you need to replace `mapXXX` by the method it is in: +To do that, you need to replace `mapXXX` by the method it's in: ```php if (!$this->canMap($fieldDefinition)) { @@ -84,7 +84,7 @@ To do that, you need to replace `mapXXX` by the method it is in: } ``` -It is required for every implemented method, so that other mappers are called for the other Field Types. +It's required for every implemented method, so that other mappers are called for the other field types. The [`RelationFieldDefinitionMapper`](https://github.com/ibexa/graphql/blob/main/src/lib/Schema/Domain/Content/Mapper/FieldDefinition/RelationFieldDefinitionMapper.php) example: @@ -135,7 +135,7 @@ class RelationFieldDefinitionMapper extends DecoratingFieldDefinitionMapper impl The value type depends on the field definition allowed content types setting: -- for types that return content items if there are no restrictions, or several types are allowed, the value will be an `Item` +- for types that return content items if there are no restrictions, or several types are allowed, the value is an `Item` The cardinality (single or collection) depends on the selection limit setting: @@ -144,10 +144,10 @@ The cardinality (single or collection) depends on the selection limit setting: #### Field input mapping -The `mapToFieldValueInputType` method is used to document what input type is expected by Field Types that require a more complex input value. +The `mapToFieldValueInputType` method is used to document what input type is expected by field types that require a more complex input value. For example, `ezmatrix` generates its own input types depending on the configured columns. -Example of a `MyCustomFieldDefinitionMapper` mapper for a complex Field Type: +Example of a `MyCustomFieldDefinitionMapper` mapper for a complex field type: ```php class MyFieldDefinitionMapper extends DecoratingFieldDefinitionMapper implements FieldDefinitionMapper @@ -167,9 +167,9 @@ class MyFieldDefinitionMapper extends DecoratingFieldDefinitionMapper implements The following variables are available in the resolver's expression: -- `field` is the current field, as an extension of the API's Field object that proxies properties requests to the Field Value +- `field` is the current field, as an extension of the API's field object that proxies properties requests to the field Value - `content` is the resolved content item's `Content` -- `location` is the content item's resolved location, for more information, see [Querying Locations](graphql_queries.md#querying-locations) +- `location` is the content item's resolved location. For more information, see [Querying Locations](graphql_queries.md#querying-locations) - `item` is the content together with its location `\Ibexa\GraphQL\Value\Item` `RelationFieldValueBuilder` or `SelectionFieldValueBuilder` can be used as examples. \ No newline at end of file diff --git a/docs/api/graphql/graphql_customization.md b/docs/api/graphql/graphql_customization.md index d53d244119..5ebf97b4f0 100644 --- a/docs/api/graphql/graphql_customization.md +++ b/docs/api/graphql/graphql_customization.md @@ -10,15 +10,15 @@ You can customize the GraphQL schema that is generated from your repository. You can use it if your application requires custom GraphQL resources, for instance for Doctrine entities. -To do so, create a `config/graphql/types/Query.types.yaml` file. It will be used as the GraphQL query root. +To do so, create a `config/graphql/types/Query.types.yaml` file. It is used as the GraphQL query root. -In that file, add new fields that use any custom type or custom logic you require, based -on [overblog/GraphQLBundle](https://github.com/overblog/GraphQLBundle). +In that file, add new fields that use any custom type or custom logic you require, based on [overblog/GraphQLBundle](https://github.com/overblog/GraphQLBundle). -The custom schema should be created only after generating other schemas to avoid problems, especially if the custom schema depends on other schema elements. For example: -`Type "Domain" inherited by "Query" not found.`. +The custom schema should be created only after generating other schemas to avoid problems, especially if the custom schema depends on other schema elements. +For example, `Type "Domain" inherited by "Query" not found.`. To avoid this problem during deployment, add the generated schemas to the repository. -Update the schema in the event of any changes related to GraphQL as well as when changing the environment, for example from `dev` to `prod`. +Update the schema in the event of any changes related to GraphQL and when changing the environment, for example from `dev` to `prod`. + ### Configuration You can include the [[= product_name =]] schema in two ways: either through inheritance or composition. @@ -57,7 +57,7 @@ Query: ### Custom mutations Custom mutations are created in the same way as custom query configuration. -A `config/graphql/types/Mutation.types.yaml` file will be used as the source for mutation definitions in your schema. +A `config/graphql/types/Mutation.types.yaml` file is used as the source for mutation definitions in your schema. ``` yaml Mutation: @@ -91,8 +91,7 @@ SomethingPayload: ## Custom field name You can customize the name used by GraphQL as the content field name. - -Use this setting to avoid conflicts with Field names that derive from a content type definition. +Use this setting to avoid conflicts with field names that derive from a content type definition. ``` yaml parameters: diff --git a/docs/api/graphql/graphql_operations.md b/docs/api/graphql/graphql_operations.md index 2f506909fa..164ab3bc84 100644 --- a/docs/api/graphql/graphql_operations.md +++ b/docs/api/graphql/graphql_operations.md @@ -4,10 +4,10 @@ description: Use GraphQL operations to create, update, and delete content. # GraphQL operations -Operations on content in GraphQL are performed using [mutations](https://graphql.org/learn/queries/#mutations). +Operations on content in GraphQL are performed by using [mutations](https://graphql.org/learn/queries/#mutations). They include creating, updating, and deleting content items. -The schema contains two mutations per content type, e.g. `createFolder` and `updateFolder`. +The schema contains two mutations per content type, for example, `createFolder`, and `updateFolder`. You can also make use of the generic `deleteContent` and `uploadFiles` mutations. ## Creating content @@ -70,7 +70,7 @@ Response: } ``` -Note that the input for updating a content item is the same as when creating it, but all fields are optional. +The input for updating a content item is the same as when creating it, but all fields are optional. ## Deleting content @@ -102,7 +102,7 @@ Response: !!! note - Uploading binary files is not possible through GraphiQL. + Uploading binary files isn't possible through GraphiQL. You can use alternative third-party clients such as [Altair GraphQL](https://altairgraphql.dev/). Uploading files makes use of dedicated mutations per content type, for example: @@ -153,8 +153,8 @@ curl -v -X POST \ !!! note "Authentication" - Note that the example above requires you to set your authentication cookie in the `$AUTH_COOKIE` variable. - See [Authentication](graphql.md#authentication) for more information. + The example above requires you to set your authentication cookie in the `$AUTH_COOKIE` variable. + For more information, see [Authentication](graphql.md#authentication). ### Uploading multiple files diff --git a/docs/api/graphql/graphql_queries.md b/docs/api/graphql/graphql_queries.md index 7051db4841..20513daa6d 100644 --- a/docs/api/graphql/graphql_queries.md +++ b/docs/api/graphql/graphql_queries.md @@ -10,8 +10,7 @@ You can query a single content item or a list of content items using fields defi ### Get a content item -To get a specific content item by its content ID, Location ID, or URL alias, use its relevant singular field, -for example `article`, `folder`, `image`, etc.: +To get a specific content item by its content ID, location ID, or URL alias, use its relevant singular field, for example `article`, `folder`, or `image`. ``` { @@ -45,10 +44,10 @@ Response: } ``` -You can request any Fields of the content item. In the example above, these are `title` and `author`. +You can request any fields of the content item. In the example above, these are `title` and `author`. You can also query the generic `item` object. -The `item` object references a content item, but you can also get its [Location information](#querying-locations). +The `item` object references a content item, but you can also get its [location information](#querying-locations). The query accepts `locationId`, `remoteId`, and `urlAlias` as arguments. ``` @@ -73,7 +72,7 @@ Response: #### Get language versions -To get Fields of a content item in a specific language, use the `language` argument. +To get fields of a content item in a specific language, use the `language` argument. The language must be configured for the current SiteAccess. ``` @@ -102,11 +101,11 @@ Response: } ``` -When you do not specify a language, the response contains the most prioritized translation. +When you don't specify a language, the response contains the most prioritized translation. ### Get a group of content items -To get a list of all content items of a selected type, use the plural field, e.g. `articles`: +To get a list of all content items of a selected type, use the plural field, for example, `articles`: ``` { @@ -247,9 +246,9 @@ Response: You can get the Location object from any item by querying for `_location` or `_allLocations`. When you use `_location`, the API returns: -- the Location specified in the `locationId` or `urlAlias` argument -- the Location based on the current SiteAccess -- the main Location +- the location specified in the `locationId` or `urlAlias` argument +- the location based on the current SiteAccess +- the main location ``` { @@ -313,8 +312,7 @@ Response: ## Getting children of a Location -To get a [Location's](#querying-locations) children, -it is recommended to use the [Query Field](content_queries.md#content-query-field). +To get a [location's](#querying-locations) children, it's recommended to use the [Query field](content_queries.md#content-query-field). Alternatively, you can query the `children` property of an `item` or `content` object: @@ -608,7 +606,7 @@ To filter products based on attributes: } ``` - + If the attribute type (in this case, `measure`) cannot be found in the schema, the response is: ``` @@ -662,8 +660,7 @@ You can also query attributes by providing the attribute type: !!! note - You need to use aliases (for example, `sizeValue`) when querying attributes by the attribute type - due to the conflicting return types. + You need to use aliases (for example, `sizeValue`) when querying attributes by the attribute type due to the conflicting return types. Response: @@ -744,7 +741,7 @@ articles(sortBy:[_datePublished,_desc]) GraphQL offers [cursor-based pagination](https://graphql.org/learn/pagination/) for paginating query results. -You can paginate plural fields using `edges`: +You can paginate plural fields by using `edges`: ``` { @@ -765,8 +762,7 @@ You can paginate plural fields using `edges`: ``` This query returns the first three articles, ordered by their publication date. -If the current `Connection` (list of results) is not finished yet and there are more items to read, -`hasNextPage` will be `true`. +If the current `Connection` (list of results) isn't finished yet and there are more items to read, `hasNextPage` is `true`. For the `children` node, you can use the following pagination method: @@ -830,6 +826,6 @@ To request a specific page, provide the `cursor` as an argument to `children`: children(first: 3, after: "YXJyYXljb25uZWN0aW9uOjM=") ``` -### Get Matrix Field Type +### Get Matrix field type -To get a Matrix Field Type with GraphQL, see [Matrix Field Type reference](matrixfield.md). +To get a Matrix field type with GraphQL, see [Matrix field type reference](matrixfield.md). diff --git a/docs/api/php_api/php_api.md b/docs/api/php_api/php_api.md index eaa3815d2e..c3f7c4608c 100644 --- a/docs/api/php_api/php_api.md +++ b/docs/api/php_api/php_api.md @@ -7,15 +7,14 @@ page_type: reference The [public PHP API](../php_api_reference/) enables you to interact with [[= product_name =]]'s Repository and content model from your PHP code. -You can use it to create, read, update, manage, and delete all objects available in [[= product_name =]], namely -content and related objects such as Sections, Locations, content types, languages, etc. +You can use it to create, read, update, manage, and delete all objects available in [[= product_name =]], namely content and related objects such as sections, locations, content types, or languages. The PHP API is built on top of a layered architecture, including a persistence SPI that abstracts storage. -Using the API ensures that your code will be forward compatible with future releases based on other storage engines. +Using the API ensures that your code is forward compatible with future releases based on other storage engines. ## Using API services -The API provides access to Content, User, content types and other features through various services. +The API provides access to content, user, content types, and other features through various services. The full list of available services covers: @@ -49,12 +48,12 @@ You can access the PHP API by injecting relevant services into your code: - By using [auto-wiring]([[=symfony_doc=]]/service_container/autowiring.html), and the service classname in the `Ibexa\Contracts` namespace (see `bin/console debug:autowiring | grep Ibexa.Contracts`). - By using [service parameters]([[=symfony_doc=]]/service_container.html#service-parameters), and service aliases (see `bin/console debug:autowiring | grep ibexa.api`). -- By using the Repository's `get[ServiceName]()` methods: [`Repository::getContentService()`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-Repository.html#method_getContentService), [`getUserService()`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-Repository.html#method_getUserService), etc. - (Prefer injecting several Repository's dedicated services instead of the whole Repository if the Repository itself is not needed.) +- By using the repository's `get[ServiceName]()` methods, for example, [`Repository::getContentService()`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-Repository.html#method_getContentService), or [`getUserService()`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-Repository.html#method_getUserService). + (Prefer injecting several Repository's dedicated services instead of the whole Repository if the Repository itself isn't needed.) !!! caution - The PHP API's services can be accessed with `Ibexa\Bundle\Core\Controller::getRepository()` by extending it from a [custom controller](controllers.md), but such approach is not recommended, and you should prefer dependency injection. + The PHP API's services can be accessed with `Ibexa\Bundle\Core\Controller::getRepository()` by extending it from a [custom controller](controllers.md), but such approach isn't recommended, and you should prefer dependency injection. ## Value objects @@ -63,54 +62,49 @@ Those objects are divided into sub-namespaces, such as [`Content`](php_api_refer Each sub-namespace contains a set of value objects, such as [`Content\Content`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Content.html) or [`User\Role`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-User-Role.html). -Value objects come with their own properties, such as `$content->id` or `$location->hidden`, -as well as with methods that provide access to more related information, -such as [`Content\Relation::getSourceContentInfo()`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Relation.html#method_getSourceContentInfo) or [`User\Role::getPolicies()`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-User-Role.html#method_getPolicies). +Value objects come with their own properties, such as `$content->id` or `$location->hidden`, and with methods that provide access to more related information, such as [`Content\Relation::getSourceContentInfo()`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Relation.html#method_getSourceContentInfo) or [`User\Role::getPolicies()`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-User-Role.html#method_getPolicies). ### Creating and updating objects -Value objects fetch data from the Repository and are read-only. -To create and modify Repository values, use data structures, such as [`ContentService::newContentCreateStruct()`](https://github.com/ibexa/core/blob/v4.6.6/src/contracts/Repository/ContentService.php#L572) or [`LocationService::newLocationUpdateStruct()`](https://github.com/ibexa/core/blob/v4.6.6/src/contracts/Repository/LocationService.php#L238). +Value objects fetch data from the repository and are read-only. +To create and modify repository values, use data structures, such as [`ContentService::newContentCreateStruct()`](https://github.com/ibexa/core/blob/v4.6.6/src/contracts/Repository/ContentService.php#L572) or [`LocationService::newLocationUpdateStruct()`](https://github.com/ibexa/core/blob/v4.6.6/src/contracts/Repository/LocationService.php#L238). ### Value info objects -Some complex value objects have an `Info` counterpart, -for example [`ContentInfo`](https://github.com/ibexa/core/blob/main/src/contracts/Repository/Values/Content/ContentInfo.php) -for [`Content`](https://github.com/ibexa/core/blob/main/src/contracts/Repository/Values/Content/Content.php). +Some complex value objects have an `Info` counterpart, for example [`ContentInfo`](https://github.com/ibexa/core/blob/main/src/contracts/Repository/Values/Content/ContentInfo.php) for [`Content`](https://github.com/ibexa/core/blob/main/src/contracts/Repository/Values/Content/Content.php). These objects provide you with lower-level information. -For instance, `ContentInfo` contains `currentVersionNo` or `remoteId`, -while `Content` enables you to retrieve Fields, content type, or previous versions. +For instance, `ContentInfo` contains `currentVersionNo` or `remoteId`, while `Content` enables you to retrieve fields, content type, or previous versions. !!! note The public PHP API value objects should not be serialized. - Serialization of value objects, for example, `Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo` / `Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo` - or `Ibexa\Contracts\Core\Repository\Values\Content\Location` results in memory limit exceeded error. + Serialization of value objects, for example, `Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo` / `Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo` or `Ibexa\Contracts\Core\Repository\Values\Content\Location` results in memory limit exceeded error. ## Authentication -One of the responsibilities of the Repository is user authentication. Every action is executed *as* a user. +One of the responsibilities of the repository is user authentication. +Every action is executed *as* a user. -When using the PHP API, authentication is performed in three ways: +When you use the PHP API, authentication is performed in three ways: -- [automatically in the Back Office](#back-office-authentication) -- [using `sudo()`](#using-sudo) +- [automatically in the back office](#back-office-authentication) +- [by using `sudo()`](#using-sudo) - by [setting the Repository user](#setting-the-repository-user) -### Back Office authentication +### Back office authentication -When actions are performed through the Back Office, they are executed as the logged-in User. -This User's permissions will affect the behavior of the Repository. -The User may, for example, not be allowed to create content, or view a particular Section. +When actions are performed through the back office, they're executed as the logged-in user. +This user's permissions affects the behavior of the repository. +The user may, for example, not be allowed to create content, or view a particular section. ### Using `sudo()` To skip permission checks, you can use the `sudo()` method. It allows API execution to be performed with full access, sand-boxed. -You can use this method to perform an action that the current User does not have permissions for. +You can use this method to perform an action that the current user doesn't have permissions for. For example, to [hide a Location](managing_content.md#hiding-and-revealing-locations), use: @@ -124,14 +118,12 @@ $hiddenLocation = $repository->sudo(function (Repository $repository) use ($loca }); ``` -### Setting the Repository user +### Setting the repository user -In a command line script, the Repository runs as if executed by the anonymous user. -While [using `sudo()`](#using-sudo) is the recommended option, -you can also set the current user to a user with necessary permissions to achieve the same effect. +In a command line script, the repository runs as if executed by the anonymous user. +While [using `sudo()`](#using-sudo) is the recommended option, you can also set the current user to a user with necessary permissions to achieve the same effect. -In order to identify as a different user, you need to use the `UserService` together with `PermissionResolver` -(in the example `admin` is the login of the administrator user): +To identify as a different user, you need to use the `UserService` together with `PermissionResolver` (in the example `admin` is the login of the administrator user): ``` php [[= include_file('code_samples/api/public_php_api/src/Command/CreateContentCommand.php', 50, 52) =]] @@ -139,10 +131,10 @@ In order to identify as a different user, you need to use the `UserService` toge !!! tip - [`Ibexa\Contracts\Core\Repository\PermissionService`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-PermissionService.html) can be injected to have a Service which provides both `PermissionResolver` and `PermissionCriterionResolver`. It supports auto-wiring. + [`Ibexa\Contracts\Core\Repository\PermissionService`](php_api_reference/classes/Ibexa-Contracts-Core-Repository-PermissionService.html) can be injected to have a Service which provides both `PermissionResolver` and `PermissionCriterionResolver`. + It supports auto-wiring. -This is not required in template functions or controller code, -as the HTTP layer takes care of identifying the user, and automatically sets it in the repository. +This isn't required in template functions or controller code, as the HTTP layer takes care of identifying the user, and automatically sets it in the repository. If you want to identify a user with their credentials instead, provide them in the following way: @@ -156,10 +148,9 @@ $permissionResolver->setCurrentUserReference($user); PHP API uses [Exceptions](https://www.php.net/exceptions) to handle errors. Each API method may throw different exceptions, depending on what it does. -It is good practice to cover every exception you expect to happen. +It's good practice to cover every exception you expect to happen. -For example if you are using a command which takes the Content ID as a parameter, -the ID may either not exist, or the referenced content item may not be visible to the user. +For example if you're using a command which takes the content ID as a parameter, the ID may either not exist, or the referenced content item may not be visible to the user. Both cases should be covered with error messages: @@ -177,12 +168,13 @@ try { [[= product_name =]] uses the [Symfony service container]([[= symfony_doc =]]/service_container.html) for dependency resolution. -[Symfony dependency injection]([[= symfony_doc =]]/components/dependency_injection.html) ensures that any required services are available in your custom code -(for example, controllers) when you inject them into the constructor. +[Symfony dependency injection]([[= symfony_doc =]]/components/dependency_injection.html) ensures that any required services are available in your custom code (for example, controllers) when you inject them into the constructor. -Symfony service container uses service tags to dedicate services to a specific purpose. They are usually used for extension points. +Symfony service container uses service tags to dedicate services to a specific purpose. +They're usually used for extension points. -[[= product_name =]] exposes multiple features using service tags. For example, Field Types are tagged `ibexa.field_type`. +[[= product_name =]] uses service tags to expose multiple features. +For example, field types are tagged `ibexa.field_type`. !!! tip diff --git a/docs/api/rest_api/extending_rest_api/adding_custom_media_type.md b/docs/api/rest_api/extending_rest_api/adding_custom_media_type.md index 2d48c20b1d..0715112198 100644 --- a/docs/api/rest_api/extending_rest_api/adding_custom_media_type.md +++ b/docs/api/rest_api/extending_rest_api/adding_custom_media_type.md @@ -7,17 +7,18 @@ description: Add a custom media type to REST API request headers. In this example case, you pass a new media type in the `Accept` header of a GET request to `/content/locations/{locationPath}` route and its controller action (`Controller/Location::loadLocation`). By default, this resource takes an `application/vnd.ibexa.api.Location+xml` (or `+json`) `Accept` header. -The following example adds the handling of a new media type `application/app.api.Location+xml` (or `+json`) `Accept` header to obtain a different response using the same controller. +The following example adds the handling of a new media type `application/app.api.Location+xml` (or `+json`) `Accept` header to obtain a different response with the same controller. You need the following elements: -* A `ValueObjectVisitor` to create the new response corresponding to the new media type; -* A `ValueObjectVisitorDispatcher` to have this `ValueObjectVisitor` used to visit the default controller result; -* An `Output\Visitor` service associating this new `ValueObjectVisitorDispatcher` with the new media type. + +- `ValueObjectVisitor` - to create the new response corresponding to the new media type +- `ValueObjectVisitorDispatcher` - to have this `ValueObjectVisitor` used to visit the default controller result +- `Output\Visitor` - service associating this new `ValueObjectVisitorDispatcher` with the new media type !!! note You can change the vendor name (from default `vnd.ibexa.api` to new `app.api` like in this example), or you can create a new media type in the default vendor (like `vnd.ibexa.api.Greeting` in the [Creating a new REST resource](creating_new_rest_resource.md) example). - To do so, tag your new ValueObjectVisitor with `ibexa.rest.output.value_object.visitor` to add it to the existing `ValueObjectVisitorDispatcher`, and a new one will not be needed. + To do so, tag your new ValueObjectVisitor with `ibexa.rest.output.value_object.visitor` to add it to the existing `ValueObjectVisitorDispatcher`, and a new one isn't needed. This way, the `media-type` attribute is also easier to create, because the default `Output\Generator` uses this default vendor. This example presents creating a new vendor as a good practice, to highlight that this is custom extensions that isn't available in a regular [[= product_name =]] installation. diff --git a/docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md b/docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md index a9abbc098c..d057cb05ad 100644 --- a/docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md +++ b/docs/api/rest_api/extending_rest_api/creating_new_rest_resource.md @@ -6,14 +6,14 @@ description: Extend REST API by creating a new resource. To create a new REST resource, you need to prepare: -* The REST route leading to a controller action. -* The controller and its action. -* Optionally, one or several `InputParser` objects if the controller needs to receive a payload to treat, one or several value classes to represent this payload and potentially one or several new media types to type this payload in the `Content-Type` header. -* Optionally, one or several new value classes to represent the controller action result, their `ValueObjectVisitor` to help the generator to turn this into XML or JSON and potentially one or several new media types to claim in the `Accept` header the desired value. -* Optionally, the addition of this resource route to the REST root. +- the REST route leading to a controller action +- the controller and its action +- one or several `InputParser` objects if the controller needs to receive a payload to treat, one or several value classes to represent this payload and potentially one or several new media types to type this payload in the `Content-Type` header (optional) +- one or several new value classes to represent the controller action result, their `ValueObjectVisitor` to help the generator to turn this into XML or JSON and potentially one or several new media types to claim in the `Accept` header the desired value (optional) +- the addition of this resource route to the REST root (optional) In the following example, you add a greeting resource to the REST API. -It is available through `GET` and `POST` methods. `GET` sets default values while `POST` allows inputting custom values. +It's available through `GET` and `POST` methods. `GET` sets default values while `POST` allows inputting custom values. ## Route @@ -57,14 +57,14 @@ Having the REST controllers set as services enables using features such as the ` A REST controller should: -- return a value object and have a `Generator` and `ValueObjectVisitor`s producing the XML or JSON output; -- extend `Ibexa\Rest\Server\Controller` to inherit utils methods and properties like `InputDispatcher` or `RequestParser`. +- return a value object and have a `Generator` and `ValueObjectVisitor`s producing the XML or JSON output +- extend `Ibexa\Rest\Server\Controller` to inherit utils methods and properties like `InputDispatcher` or `RequestParser` ``` php [[= include_file('code_samples/api/rest_api/src/Rest/Controller/DefaultController.php') =]] ``` -If the returned value was depending on a Location, it could have been wrapped in a `CachedValue` to be cached by the reverse proxy (like Varnish) for future calls. +If the returned value was depending on a location, it could have been wrapped in a `CachedValue` to be cached by the reverse proxy (like Varnish) for future calls. `CachedValue` is used in the following way: @@ -101,7 +101,8 @@ services: [[= include_file('code_samples/api/rest_api/config/services.yaml', 43, 48) =]] ``` -Here, the media type is `application/vnd.ibexa.api.Greeting` plus a format. To have a different vendor than the default, you could create a new `Output\Generator` or hard-code it in the `ValueObjectVisitor` like in the [`RestLocation` example](adding_custom_media_type.md#new-restlocation-valueobjectvisitor). +Here, the media type is `application/vnd.ibexa.api.Greeting` plus a format. +To have a different vendor than the default, you could create a new `Output\Generator` or hard-code it in the `ValueObjectVisitor` like in the [`RestLocation` example](adding_custom_media_type.md#new-restlocation-valueobjectvisitor). ## InputParser @@ -186,7 +187,9 @@ ibexa_rest: href: 'router.generate("", {routeParameter: value})' ``` -The `router.generate` renders a URI based on the name of the route and its parameters. The parameter values can be a real value or a placeholder. For example, `'router.generate("ibexa.rest.load_location", {locationPath: "1/2"})'` results in `/api/ibexa/v2/content/locations/1/2` while `'router.generate("ibexa.rest.load_location", {locationPath: "{locationPath}"})'` gives `/api/ibexa/v2/content/locations/{locationPath}`. +The `router.generate` renders a URI based on the name of the route and its parameters. +The parameter values can be a real value or a placeholder. +For example, `'router.generate("ibexa.rest.load_location", {locationPath: "1/2"})'` results in `/api/ibexa/v2/content/locations/1/2` while `'router.generate("ibexa.rest.load_location", {locationPath: "{locationPath}"})'` gives `/api/ibexa/v2/content/locations/{locationPath}`. This syntax is based on Symfony's [expression language]([[= symfony_doc =]]/components/expression_language/index.html), an extensible component that allows limited/readable scripting to be used outside the code context. In this example, `app.rest.greeting` is available in every SiteAccess (`default`): diff --git a/docs/api/rest_api/rest_api_authentication.md b/docs/api/rest_api/rest_api_authentication.md index c63f13e7da..b6f458fbad 100644 --- a/docs/api/rest_api/rest_api_authentication.md +++ b/docs/api/rest_api/rest_api_authentication.md @@ -8,7 +8,7 @@ month_change: true This page refers to [REST API reference](rest_api_reference/rest_api_reference.html), where you can find detailed information about REST API resources and endpoints. -Five authentication methods are currently supported: session (default), JWT, basic, OAuth and client certificate (SSL). +Five authentication methods are currently supported: session (default), JWT, basic, OAuth, and client certificate (SSL). You can only use one of those methods at the same time. @@ -29,7 +29,7 @@ For other security related subjects, see: This authentication method requires a session cookie to be sent with each request. If you use this authentication method with a web browser, this session cookie is automatically available as soon as your visitor logs in. -Add it as a cookie to your REST requests, and the user will be authenticated. +Add it as a cookie to your REST requests to authenticate the user. Sessions are created to re-authenticate the user only (and perform authorization), not to hold session state in the service. Because of that, you can use this method as supporting AJAX-based applications even if it violates the principles of RESTful services. @@ -41,7 +41,7 @@ Enabling any other method disables session. ### Usage examples -You can create a session for a visitor even if they are not logged in by sending the **`POST`** request to `/user/sessions`. +You can create a session for a visitor even if they're not logged in by sending the **`POST`** request to `/user/sessions`. To log out, use the **`DELETE`** request on the same resource. #### Establishing session @@ -58,7 +58,7 @@ To create a session, execute the following REST request: Accept: application/vnd.ibexa.api.Session+xml Content-Type: application/vnd.ibexa.api.SessionInput+xml ``` - + ```xml @@ -66,14 +66,14 @@ To create a session, execute the following REST request: publish ``` - + ``` HTTP/1.1 201 Created Location: /user/sessions/go327ij2cirpo59pb6rrv2a4el2 Set-Cookie: eZSESSID98defd6ee70dfb1dea416=go327ij2cirpo59pb6rrv2a4el2; domain=.example.net; path=/; expires=Wed, 13-Jan-2021 22:23:01 GMT; HttpOnly Content-Type: application/vnd.ibexa.api.Session+xml ``` - + ```xml @@ -92,7 +92,7 @@ To create a session, execute the following REST request: Accept: application/vnd.ibexa.api.Session+json Content-Type: application/vnd.ibexa.api.SessionInput+json ``` - + ```json { "SessionInput": { @@ -101,14 +101,14 @@ To create a session, execute the following REST request: } } ``` - + ``` HTTP/1.1 201 Created Location: /user/sessions/go327ij2cirpo59pb6rrv2a4el2 Set-Cookie: eZSESSID98defd6ee70dfb1dea416=go327ij2cirpo59pb6rrv2a4el2; domain=.example.net; path=/; expires=Wed, 13-Jan-2021 22:23:01 GMT; HttpOnly Content-Type: application/vnd.ibexa.api.Session+xml ``` - + ```json { "Session": { @@ -127,8 +127,7 @@ To create a session, execute the following REST request: ##### Logging in with active session -Logging in is very similar to session creation, with one important detail: -the CSRF token obtained in the previous step is added to the new request through the `X-CSRF-Token` header. +Logging in is similar to session creation, with one important detail: the CSRF token obtained in the previous step is added to the new request through the `X-CSRF-Token` header. === "XML" @@ -140,7 +139,7 @@ the CSRF token obtained in the previous step is added to the new request through Cookie: eZSESSID98defd6ee70dfb1dea416=go327ij2cirpo59pb6rrv2a4el2 X-CSRF-Token: 23lk.neri34ijajedfw39orj-3j93 ``` - + ```xml @@ -148,12 +147,12 @@ the CSRF token obtained in the previous step is added to the new request through publish ``` - + ``` HTTP/1.1 200 OK Content-Type: application/vnd.ibexa.api.Session+xml ``` - + ```xml @@ -174,7 +173,7 @@ the CSRF token obtained in the previous step is added to the new request through Cookie: eZSESSID98defd6ee70dfb1dea416=go327ij2cirpo59pb6rrv2a4el2 X-CSRF-Token: 23lk.neri34ijajedfw39orj-3j93 ``` - + ```xml { "SessionInput": { @@ -183,12 +182,12 @@ the CSRF token obtained in the previous step is added to the new request through } } ``` - + ``` HTTP/1.1 200 OK Content-Type: application/vnd.ibexa.api.Session+json ``` - + ```xml { "Session": { @@ -220,8 +219,7 @@ Cookie: eZSESSID98defd6ee70dfb1dea416=go327ij2cirpo59pb6rrv2a4el2 ##### CSRF token -It can be important to keep the CSRF token (`csrfToken`) for the duration of the session, -because you must send this token in every request that uses [unsafe HTTP methods](rest_requests.md#request-method) (others than the safe GET or HEAD or OPTIONS) when a session has been established. +It can be important to keep the CSRF token (`csrfToken`) for the duration of the session, because you must send this token in every request that uses [unsafe HTTP methods](rest_requests.md#request-method) (others than the safe GET or HEAD or OPTIONS) when a session has been established. It should be sent with an `X-CSRF-Token` header. Only three built-in routes can accept unsafe methods without CSRF, the sessions routes starting with `/user/sessions` to create, refresh or delete a session. @@ -237,10 +235,10 @@ If an unsafe request is missing the CSRF token, or the token has incorrect value ##### Rich client application security concerns -The purpose of CSRF protection is to prevent users from accidentally running harmful operations by being tricked into executing an HTTP(S) request against a web applications they are logged into. -In browsers this action will be blocked by lack of CSRF token. +The purpose of CSRF protection is to prevent users from accidentally running harmful operations by being tricked into executing an HTTP(S) request against a web applications they're logged into. +In browsers this action is blocked by lack of CSRF token. -However, if you develop a rich client application (JavaScript, JAVA, iOS, Android, etc.), that is: +However, if you develop a rich client application (for example, JavaScript, JAVA, iOS, or Android), that is: - Registering itself as a protocol handler: - Exposes unsafe methods in any way @@ -252,8 +250,8 @@ Then, you have to make sure to confirm with the user if they want to perform an Example: -A rich JavaScript/web application is using `navigator.registerProtocolHandler()` to register "web+ez:" links to go against REST API. -It uses a session-based authentication, and it is in widespread use across the net, or/and it is used by everyone within a company. +A rich JavaScript/web application uses `navigator.registerProtocolHandler()` to register "web+ez:" links to go against REST API. +It uses a session-based authentication, and it's in widespread use across the net, or/and it's used by everyone within a company. A person with minimal insight into this application and the company can easily send out the following link to all employees in that company in email: `latest reports`. @@ -276,8 +274,7 @@ See [JWT authentication](#jwt-authentication) or GraphQL. ### Usage example -After you [configure JWT authentication](development_security.md#jwt-authentication) at least for REST, -you can get the JWT token through the following request: +After you [configure JWT authentication](development_security.md#jwt-authentication) at least for REST, you can get the JWT token through the following request: === "XML" @@ -287,24 +284,24 @@ you can get the JWT token through the following request: Accept: application/vnd.ibexa.api.JWT+xml Content-Type: application/vnd.ibexa.api.JWTInput+xml ``` - + Provide the username and password in the request body: - + ```xml admin publish ``` - + If credentials are valid, the server response contains a token: - + ```xml ``` - + You can then use this token in your request instead of username and password. - + ``` GET /content/locations/1/5/children Host: @@ -320,9 +317,9 @@ you can get the JWT token through the following request: Accept: application/vnd.ibexa.api.JWT+json Content-Type: application/vnd.ibexa.api.JWTInput+json ``` - + Provide the username and password in the request body: - + ```json { "JWTInput": { @@ -331,9 +328,9 @@ you can get the JWT token through the following request: } } ``` - + If credentials are valid, the server response contains a token: - + ```json { "JWT": { @@ -342,9 +339,9 @@ you can get the JWT token through the following request: } } ``` - + You can then use this token in your request instead of username and password. - + ``` GET /content/locations/1/5/children Host: @@ -367,25 +364,27 @@ If the installation has a dedicated host for REST, you can enable HTTP basic aut realm: Ibexa DXP REST API ``` -!!! caution "Back Office uses REST API" +!!! caution "Back office uses REST API" - Back Office uses the REST API too (for some parts like the Location tree or the Calendar) on its own domain. + Back office uses the REST API too (for some parts like the Location tree or the Calendar) on its own domain. - * If the Back Office SiteAccess matches `//admin.example.com` (through `Map\Host`, `HostElement` or `HostText`), it calls the REST API under `//admin.example.com/api/ibexa/v2`; - * If the Back Office SiteAccess matches `//localhost/admin` (through `URIElement`, `Map\URI` or `Regex\URI`), it calls the REST API under `//localhost/api/ibexa/v2` because SiteAccess matching with REST isn't enabled at URL level. + * If the back office SiteAccess matches `//admin.example.com` (through `Map\Host`, `HostElement` or `HostText`), it calls the REST API under `//admin.example.com/api/ibexa/v2`; + * If the back office SiteAccess matches `//localhost/admin` (through `URIElement`, `Map\URI` or `Regex\URI`), it calls the REST API under `//localhost/api/ibexa/v2` because SiteAccess matching with REST isn't enabled at URL level. - If you enable basic authentication for `pattern: ^/api/ibexa/v2` to use it in your front office across both production and development environments, your development environment's Back Office won't work correctly. - This Back Office tries to access REST through the same URL as the front office. Even when logged in Back Office and using the [X-SiteAccess header](rest_requests.md#siteaccess), the firewall blocks access to REST as you're not logged through basic authentification. Therefore, some Back Office features don't work. + If you enable basic authentication for `pattern: ^/api/ibexa/v2` to use it in your front office across both production and development environments, your development environment's back office cannot work correctly. + This back office tries to access REST through the same URL as the front office. + Even when logged in back office and using the [X-SiteAccess header](rest_requests.md#siteaccess), the firewall blocks access to REST as you're not logged through basic authentification. Therefore, some back office features don't work. - If basic authentication is used only for REST API, it's better to have a dedicated domain even on a development environment. For example, map an `api.localhost` in your `hosts` file and set the firewall for `host: ^api\.(example\.com|localhost)$`. + If basic authentication is used only for REST API, it's better to have a dedicated domain even on a development environment. + For example, map an `api.localhost` in your `hosts` file and set the firewall for `host: ^api\.(example\.com|localhost)$`. ### Usage example Basic authentication requires the username and password to be sent *(username:password)*, base64 encoded, with each request. For details, see [RFC 2617](https://datatracker.ietf.org/doc/html/rfc2617). -Most HTTP client libraries as well as REST libraries support this method. -[Creating content with binary attachments](rest_requests.md#creating-content-with-binary-attachments) has an example using basic authentication with [cURL](https://www.php.net/manual/en/book.curl.php) and its `CURLOPT_USERPWD`. +Most HTTP client libraries and REST libraries support this method. +[Creating content with binary attachments](rest_requests.md#creating-content-with-binary-attachments) is an example of using basic authentication with [cURL](https://www.php.net/manual/en/book.curl.php) and its `CURLOPT_USERPWD`. **Raw HTTP request with basic authentication** diff --git a/docs/api/rest_api/rest_api_usage/rest_api_usage.md b/docs/api/rest_api/rest_api_usage/rest_api_usage.md index f7c28459aa..656d04ac91 100644 --- a/docs/api/rest_api/rest_api_usage/rest_api_usage.md +++ b/docs/api/rest_api/rest_api_usage/rest_api_usage.md @@ -1,16 +1,15 @@ --- -description: The REST API covers objects in the Ibexa DXP Repository with regular and custom HTTP methods, such as GET or PUBLISH, as well as HTTP headers. +description: The REST API covers objects in the Ibexa DXP Repository with regular and custom HTTP methods, such as GET or PUBLISH, and HTTP headers. --- # REST API usage -The REST API in [[= product_name =]] allows you to interact with an [[= product_name =]] installation using the HTTP protocol, -following a [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) interaction model. +The REST API in [[= product_name =]] allows you to interact with an [[= product_name =]] installation by using the HTTP protocol, following a [REST](https://en.wikipedia.org/wiki/Representational_state_transfer) interaction model. Each resource (URI) interacts with a part of the system (like content, users or search). -Every interaction with the Repository than you can do from Back Office or using the [Public PHP API](php_api.md) can also be done using the REST API. +Every interaction with the repository than you can do from back office or by using the [Public PHP API](php_api.md) can also be done with the REST API. -The REST API uses HTTP methods (such as `GET` and `PUBLISH`), as well as HTTP headers to specify the type of request. +The REST API uses HTTP methods (such as `GET` and `PUBLISH`), and HTTP headers to specify the type of request. ## URIs @@ -58,7 +57,7 @@ curl -H "Accept: application/json" https://api.example.com/api/ibexa/v2/ ### Country list -Alongside regular Repository interactions, there is a REST service providing a list of countries with their names, [ISO-3166](https://en.wikipedia.org/wiki/ISO_3166) codes and International Dialing Codes (IDC). It could be useful when presenting a country options list from any application. +Alongside regular Repository interactions, there is a REST service providing a list of countries with their names, [ISO-3166](https://en.wikipedia.org/wiki/ISO_3166) codes and International Dialing Codes (IDC). You can use it when presenting a country options list from any application. This country list's URI is `/services/countries`. @@ -66,7 +65,7 @@ The ISO-3166 country codes can be represented as: - two-letter code (alpha-2) — recommended as the general purpose code - three-letter code (alpha-3) — related to the country name -- three-digit numeric code (numeric-3) — useful if you need to avoid using Latin script +- three-digit numeric code (numeric-3) — use it if you need to avoid using Latin script For details, see the [ISO-3166 glossary](https://www.iso.org/glossary-for-iso-3166.html). diff --git a/docs/api/rest_api/rest_api_usage/rest_requests.md b/docs/api/rest_api/rest_api_usage/rest_requests.md index 2e838c84d1..a0cf722df4 100644 --- a/docs/api/rest_api/rest_api_usage/rest_requests.md +++ b/docs/api/rest_api/rest_api_usage/rest_requests.md @@ -29,15 +29,14 @@ For method action details per resource, see the [REST API reference](../rest_api | [PATCH](https://datatracker.ietf.org/doc/html/rfc5789) | Custom | Update an item | No | | COPY | Custom | Duplicate an item | No | | [MOVE](https://datatracker.ietf.org/doc/html/rfc2518) | Custom | Move an item | No | -| SWAP | Custom | Swap two Locations | No | +| SWAP | Custom | Swap two locations | No | | PUBLISH | Custom | Publish an item | No | | [DELETE](https://datatracker.ietf.org/doc/html/rfc2616#section-9.7) | Standard | Remove an item | No | !!! note "Caution with custom HTTP methods" Using custom HTTP methods can cause issues with several HTTP proxies, network firewall/security solutions and simpler web servers. - To avoid issues with this, REST API allows you to set these using the HTTP header `X-HTTP-Method-Override` alongside the standard `POST` method - instead of using a custom HTTP method. For example: `X-HTTP-Method-Override: PUBLISH` + To avoid such issuess, REST API allows you to set these by using the HTTP header `X-HTTP-Method-Override` alongside the standard `POST` method instead of using a custom HTTP method. For example: `X-HTTP-Method-Override: PUBLISH` If applicable, both methods are always mentioned in the specifications. @@ -104,8 +103,8 @@ Accept: application/vnd.ibexa.api.Root+json X-Siteaccess: restapi ``` -One of the principles of REST is that the same resource (such as content item, Location, content type) should be unique. -It allows caching your REST API using a reverse proxy such as Varnish. +One of the principles of REST is that the same resource (such as content item, location, content type) should be unique. +It allows caching your REST API with a reverse proxy such as Varnish. If the same resource is available in multiple locations, cache purging is noticeably more complex. This is why SiteAccess matching with REST isn't enabled at URL level (or domain). @@ -115,21 +114,21 @@ On top of methods, HTTP request headers allow you to personalize the request's b On every resource, you can use the `Accept` header to indicate which format you want to communicate in, JSON or XML. This header is also used to specify the response type you want the server to send when multiple types are available. -- `Accept: application/vnd.ibexa.api.Content+xml` to get `Content` (full data, Fields included) as **[XML](https://www.w3.org/XML/)** -- `Accept: application/vnd.ibexa.api.ContentInfo+json` to get `ContentInfo` (metadata only) as **[JSON](https://www.json.org/)** +- `Accept: application/vnd.ibexa.api.Content+xml` to get `Content` (full data, fields included) as **[XML](https://www.w3.org/XML/)** +- `Accept: application/vnd.ibexa.api.ContentInfo+json` to get `ContentInfo` (metadata only) as **[JSON](https://www.json.org/)** Media types are also used with the [`Content-Type` header](rest_responses.md#content-type-header) to characterize a [request body](#request-body) or a [response body](rest_responses.md#response-body). See [Creating content with binary attachments](#creating-content-with-binary-attachments) below. Also see [Creating session](rest_api_authentication.md#creating-session) examples. -If the resource only returns one media type, it's also possible to skip it and to just specify the format using `application/xml` or `application/json`. +If the resource only returns one media type, it's also possible to skip it and to specify the format with `application/xml` or `application/json`. A response indicates `href`s to related resources and their media types. ### Destination The `Destination` request header is the request counterpart of the `Location` response header. -It's used for a `COPY`, `MOVE` or `SWAP` operation to indicate where the resource should be moved, copied to or swapped with by using the ID of the parent or target Location. +It's used for a `COPY`, `MOVE` or `SWAP` operation to indicate where the resource should be moved, copied to or swapped with by using the ID of the parent or target location. Examples of such requests are: @@ -143,20 +142,18 @@ The `X-Expected-User` header specifies the user needed for the request execution With this header, if the current username on server side isn't equal to `X-Expected-User` value, a `401 Unauthorized` error is returned. Without this header, the request is executed with the current user who might be unexpected (like the Anonymous user if a previous authentication has expired) and an ambiguous response might be returned as a success not informing about a wrong user. -For example, it prevents a Content request to be executed with Anonymous user in the case of an expired authentication, -and the response being a `200 OK` but missing content items due to access rights difference with the expected user. +For example, it prevents a Content request to be executed with Anonymous user in the case of an expired authentication, and the response being a `200 OK` but missing content items due to access rights difference with the expected user. ## Request body -You can pass some short scalar parameters in the URIs or as GET parameters, but other resources need heavier structured payloads passed in the request body, -in particular the ones to create (`POST`) or update (`PATCH`) items. +You can pass some short scalar parameters in the URIs or as GET parameters, but other resources need heavier structured payloads passed in the request body, in particular the ones to create (`POST`) or update (`PATCH`) items. In the [REST API reference](../rest_api_reference/rest_api_reference.html), request payload examples are given when needed. One example is the [creation of an authentication session](rest_api_authentication.md#establishing-session). -When creating a content item, a special payload is needed if the ContentType has some [Image](imagefield.md) or [BinaryFile](binaryfilefield.md) Fields as files need to be attached. See the example of a [script uploading images](#creating-content-with-binary-attachments) below. +When creating a content item, a special payload is needed if the content type has some [Image](imagefield.md) or [BinaryFile](binaryfilefield.md) fields as files need to be attached. See the example of a [script uploading images](#creating-content-with-binary-attachments) below. -When searching for content items (or Locations), the query grammar is also particular. See the [Search section](#search-views) below. +When searching for content items (or locations), the query grammar is also particular. See the [Search section](#search-views) below. ### Creating content with binary attachments @@ -194,9 +191,9 @@ Most [Sort Clauses](sort_clause_reference.md#sort-clauses) are available too. Th The search request has a `Content-Type: application/vnd.ibexa.api.ViewInput+xml` or `+json` header to specify the format of its body's payload. The root node is `` and it has two mandatory children: `` and ``. -You can add `version=1.1` to the `Content-Type` header to support the distinction between `ContentQuery` and `LocationQuery` instead of just `Query` which implicitly looks only for content items. +You can add `version=1.1` to the `Content-Type` header to support the distinction between `ContentQuery` and `LocationQuery` instead of `Query` which implicitly looks only for content items. -The following examples search for `article` and `news` typed content items everywhere or for content items of all types directly under Location `123`. All those content items must be in the `standard` Section. +The following examples search for `article` and `news` typed content items everywhere or for content items of all types directly under location `123`. All those content items must be in the `standard` section. === "XML" diff --git a/docs/api/rest_api/rest_api_usage/rest_responses.md b/docs/api/rest_api/rest_api_usage/rest_responses.md index 09d91d80da..e475ea1eb2 100644 --- a/docs/api/rest_api/rest_api_usage/rest_responses.md +++ b/docs/api/rest_api/rest_api_usage/rest_responses.md @@ -25,7 +25,7 @@ For code details per resource, see the [REST API reference](../rest_api_referenc | `409` | Conflict | The request is in conflict with another part of the repository (for example, trying to create a new item with an identifier already used). | | `415` | Unsupported Media Type | The request payload media type doesn't match the media type specified in the request header. | | `500` | Internal Server Error | The server encountered an unexpected condition, usually an exception, which prevents it from fulfilling the request, like database down, permissions or configuration error. | -| `501` | Not Implemented | Returned when the requested method hasn't yet been implemented. For [[= product_name =]], most of Users, User groups, content items, Locations and content types have been implemented. Some of their methods, as well as other features, may return a 501. | +| `501` | Not Implemented | Returned when the requested method hasn't yet been implemented. For [[= product_name =]], most of users, user groups, content items, locations and content types have been implemented. Some of their methods, and other features, may return a 501. | ## Response headers @@ -137,10 +137,7 @@ Content-Type: application/vnd.ibexa.api.Content+json [Cross-Origin Resource Sharing (CORS)](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing) can allow the REST API to be reached from a page on another domain. -!!! tip "More information about CORS" - - - [WHATWG's CORS Protocol specification](https://fetch.spec.whatwg.org/#cors-protocol) - - [Overview of CORS on developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) +For more information about CORS, see [WHATWG's CORS Protocol specification](https://fetch.spec.whatwg.org/#cors-protocol) and [Overview of CORS on developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). CORS support is provided by the third party [nelmio/cors-bundle](https://packagist.org/packages/nelmio/cors-bundle). You can read more about it in [NelmioCorsBundle's README](https://github.com/nelmio/NelmioCorsBundle/blob/master/README.md). @@ -154,9 +151,7 @@ To enable CORS, add regular expression for an allowed domain using the `.env` va For example, to allow the JS test above to be executed alongside this page, you could add the following to an `.env` file (like the `.env.local`): `CORS_ALLOW_ORIGIN=^https?://doc.ibexa.co`. -To add several domains, filter on URIs, or change the default (like not allowing all the methods), -refer to [NelmioCorsBundle Configuration Documentation](https://symfony.com/bundles/NelmioCorsBundle/current/index.html#configuration) -to learn how to edit `config/packages/nelmio_cors.yaml`. +To add several domains, filter on URIs, or change the default (like not allowing all the methods), refer to [NelmioCorsBundle Configuration Documentation](https://symfony.com/bundles/NelmioCorsBundle/current/index.html#configuration) to learn how to edit `config/packages/nelmio_cors.yaml`. ## Response body diff --git a/docs/api/rest_api/rest_api_usage/testing_rest_api.md b/docs/api/rest_api/rest_api_usage/testing_rest_api.md index 932252bad1..8c8f5c0c40 100644 --- a/docs/api/rest_api/rest_api_usage/testing_rest_api.md +++ b/docs/api/rest_api/rest_api_usage/testing_rest_api.md @@ -8,9 +8,10 @@ A standard web browser isn't sufficient to fully test the API. You can, however, try opening the root resource with it, using the session authentication: `http://example.com/api/ibexa/v2/`. Depending on how your browser understands XML, it either downloads the XML file, or opens it in the browser. -The following examples show how to interrogate the REST API using cURL, PHP or JS. +The following examples show how to interrogate the REST API with cURL, PHP or JS. -To test further, you can use browser extensions, like [Advanced REST client for Chrome](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo) or [RESTClient for Firefox](https://addons.mozilla.org/en-US/firefox/addon/restclient/), or dedicated tools. For command line users, [HTTPie](https://github.com/httpie/cli) is a good tool. +To test further, you can use browser extensions, like [Advanced REST client for Chrome](https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo) or [RESTClient for Firefox](https://addons.mozilla.org/en-US/firefox/addon/restclient/), or dedicated tools. +For command line users, [HTTPie](https://github.com/httpie/cli) is a good tool. ## CLI @@ -32,14 +33,15 @@ Open a PHP shell in a terminal with `php -a` and copy-paste this co `$resource` URI should be edited to address the right domain. -On a freshly installed [[= product_name =]], `52` is the Content ID of the home page. If necessary, substitute `52` with the Content ID of an item from your database. +On a freshly installed [[= product_name =]], `52` is the Content ID of the home page. +If necessary, substitute `52` with the content ID of an item from your database. -For a content creation example using PHP, see [Creating content with binary attachments](rest_requests.md#creating-content-with-binary-attachments) +For a content creation example that uses PHP, see [Creating content with binary attachments](rest_requests.md#creating-content-with-binary-attachments) ## JS The REST API can help you implement JavaScript / AJAX interaction. -The following example of an AJAX call retrieves `ContentInfo` (that is, metadata) for a content item: +The following example of an AJAX call retrieves `ContentInfo` (that is, metadata) for a content item. To test it, copy-paste this code into your browser console alongside a page from your website (to share the domain): @@ -47,7 +49,7 @@ To test it, copy-paste this code into your browser console alongside a page from ```javascript const resource = '/api/ibexa/v2/content/objects/52'; - + fetch(resource, { headers: {'Accept': 'application/vnd.ibexa.api.ContentInfo+json'}, }).then((response) => { @@ -63,7 +65,7 @@ To test it, copy-paste this code into your browser console alongside a page from ```javascript const resource = '/api/ibexa/v2/content/objects/52'; const request = new XMLHttpRequest(); - + request.open('GET', resource, true); request.setRequestHeader('Accept', 'application/vnd.ibexa.api.ContentInfo+json'); request.onload = function () { @@ -72,6 +74,7 @@ To test it, copy-paste this code into your browser console alongside a page from request.send(); ``` -On a freshly installed [[= product_name =]], `52` is the Content ID of the home page. If necessary, substitute `52` with the Content ID of an item from your database. +On a freshly installed [[= product_name =]], `52` is the Content ID of the home page. +If necessary, substitute `52` with the Content ID of an item from your database. You can edit the `resource` URI to address another domain, but [cross-origin requests](rest_responses.md#cross-origin) must be allowed first. diff --git a/docs/cdp/cdp.md b/docs/cdp/cdp.md index 10bc9f69f4..51259b70bb 100644 --- a/docs/cdp/cdp.md +++ b/docs/cdp/cdp.md @@ -5,21 +5,18 @@ edition: experience # Customer Data Platform (CDP) -## What is Ibexa CDP +## What is [[= product_name_cdp =]] -[[= product_name_cdp =]] helps you solve one of the hardest challenges facing business world today: -building unique experiences for your customers. -With [[= product_name_cdp =]] you will be able to track and aggregate data of your customers' activity on multiple channels. -It will allow you to create individual customer profiles that enable you to personalize their experience on your platform. +[[= product_name_cdp =]] helps you solve one of the hardest challenges facing business world today: building unique experiences for your customers. +With [[= product_name_cdp =]] you're able to track and aggregate data of your customers' activity on multiple channels. +It allows you to create individual customer profiles that enable you to personalize their experience on your platform. ![Ibexa CDP control panel](img/cdp_control_panel.png) ## How it works -[[= product_name_cdp =]] unifies customer data across your organization -to help you activate your users and provide them with real-time engagement. -With defined audiences you can target your user segments at the right time, -through the most used channel, with the relevant message, content, or products. +[[= product_name_cdp =]] unifies customer data across your organization to help you activate your users and provide them with real-time engagement. +With defined audiences you can target your user segments at the right time, through the most used channel, with the relevant message, content, or products. The customer data are collected through the system of trackers embedded in different parts of your page. For more information on activation and trackers, see [CDP activation documentation](cdp_activation.md). diff --git a/docs/cdp/cdp_activation/cdp_add_clientside_tracking.md b/docs/cdp/cdp_activation/cdp_add_clientside_tracking.md index 6abea51f78..7ab8db8878 100644 --- a/docs/cdp/cdp_activation/cdp_add_clientside_tracking.md +++ b/docs/cdp/cdp_activation/cdp_add_clientside_tracking.md @@ -6,12 +6,12 @@ edition: experience # Add Client-side Tracking The final step is setting up a tracking script. -It requires a head tracking script between the `` tags on your website, -a main script after the head script, and cookie consent. +It requires a head tracking script between the `` tags on your website, a main script after the head script, and cookie consent. + For more information about setting up a tracking script, see [a tutorial in Raptor documentation](https://support.raptorsmartadvisor.com/hc/en-us/articles/9563346335004-Client-Side-Tracking). Now, you need to add a tracker to specific places in your website where you want to track users. -For example, add this tracker to the Landing Page template to track user entrances. +For example, add this tracker to the landing page template to track user entrances. ```js raptor.trackEvent('visit', ..., ...); diff --git a/docs/cdp/cdp_activation/cdp_configuration.md b/docs/cdp/cdp_activation/cdp_configuration.md index 52c04f243c..cba8400133 100644 --- a/docs/cdp/cdp_activation/cdp_configuration.md +++ b/docs/cdp/cdp_activation/cdp_configuration.md @@ -36,7 +36,7 @@ ibexa: - `account_number` - a [number](#account-number) obtained from Accounts settings in [[= product_name_cdp =]] dashboard - `stream_id` - stream ID generated when importing data from the stream file in Data Manage - `activations` - activation details. You can configure multiple activations. They have to be of type `Ibexa` in [[= product_name =]] dashboard -- `client_id` and `client_secret` - client credentials are used to authenticate against the Webhook endpoint. Make sure they are random and secure +- `client_id` and `client_secret` - client credentials are used to authenticate against the Webhook endpoint. Make sure they're random and secure - `segment_group_identifier` - a [location](#segment-group) to which CDP data is imported ## Account number @@ -52,15 +52,15 @@ A pop-up window displays a list of all available accounts and their numbers. ## Segment group -Create a segment group in the Back Office. +Create a segment group in the back office. It serves as a container for all segments data generated by [[= product_name_cdp =]]. Go to **Admin** -> **Segments** and select **Create**. Fill in name and identifier for a segment group. -Choose wisely, as once connected to CDP Segment Group cannot be changed. +Choose wisely, as once connected to CDP segment group cannot be changed. -!!! caution "[[= product_name_cdp =]] Segment Group" +!!! caution "[[= product_name_cdp =]] segment group" - After you create the Segment Group in the Back Office and connect it to [[= product_name_cdp =]], you cannot change it in any way, including edit its name. + After you create the segment group in the back office and connect it to [[= product_name_cdp =]], you cannot change it in any way, including edit its name. ![Creating a new segment group](cdp_create_segment_group.png) diff --git a/docs/cdp/cdp_activation/cdp_data_export.md b/docs/cdp/cdp_activation/cdp_data_export.md index c87d40f493..bf7614765d 100644 --- a/docs/cdp/cdp_activation/cdp_data_export.md +++ b/docs/cdp/cdp_activation/cdp_data_export.md @@ -5,20 +5,18 @@ edition: experience # Data export -You need to specify a source of the user data that [[= product_name_cdp =]] will connect to. +You need to specify a source of the user data that [[= product_name_cdp =]] connects to. To do so, go to **Data Manager** in **Tools** section and select **Create new dataflow**. -It will take you to a Dataflow Creator, where in five steps you will set up a data streaming. +It takes you to a Dataflow Creator, where in five steps you can set up a data streaming. ## General Information -In the **General Information** section, specify dataflow name, -choose **Stream File** as a source of user data and **CDP** as a destination, -where they will be sent for processing. -Currently, only Stream File transport is supported and can be initialized from the configuration. +In the **General Information** section, specify dataflow name, choose **Stream File** as a source of user data and **CDP** as a destination, where they're sent for processing. +Currently, only Stream File transport is supported and can be initialized from the configuration. ## Download -In the **Download** section, select **Stream file**. +In the **Download** section, select **Stream file**. Copy generated steam ID and paste it into the configuration file under `stream_id`. It allows you to establish a datastream from the Streaming API into the Data Manager. @@ -48,16 +46,16 @@ The first one is used to send the test user data to the Data Manager. If it passes a validation test in the **Activation** section, use the latter one to send a full version. Next, go back to [[= product_name_cdp =]] and select **Validate & download**. -If the file passes, you will see a confirmation message. +If the file passes, you can see a confirmation message. Now, you can go to the **File mapping** section. ## File mapping Mapping is completed automatically, the system fills all required information and shows available columns with datapoints on the right. You can change their names if needed or disallow empty fields by checking **Mandatory**. -If the provided file contains empty values, this option is not available. +If the provided file contains empty values, this option isn't available. -If provided file is not recognized, the system will require you to fill in the parsing-options manually or select an appropriate format. +If provided file isn't recognized, the system requires you to fill in the parsing-options manually or select an appropriate format. If you make any alterations, select the **Parse File** to generate columns with new data. ## Transform & Map @@ -66,8 +64,8 @@ In the **Transform & Map** section you transform data and map it to a schema. At this point, you can map **email** to **email** and **id** to **integer** fields to get custom columns. Next, select **Create schema based on the downloaded columns**. -It will move you to Schema Creator. -There, choose **PersonalData** as a parent and name the schema. +It moves you to Schema Creator. +There, choose **PersonalData** as a parent and name the schema. ![Create new schema](cdp_create_new_schema.png) @@ -75,12 +73,11 @@ Next, select all the columns and set Person Identifier as **userid**. ![Person Identifier](cdp_person_identifier.png) -If you used PersonData or Catalog type schemas, the system will require -specifying the Write Mode that will be applied to them. +If you used PersonData or Catalog type schemas, the system requires specifying the Write Mode that is applied to them. **Append** (default one) allows new data to overwrite the old one but leaves existing entries unaffected. All entries are stored in the dataset, unchanged by updating dataflow. -For example, if a customer unsubscribes a newsletter, their email will remain in the system. +For example, if a customer unsubscribes a newsletter, their email remains in the system. **Overwrite** completely removes the original dataset and replaces it with the new one every time the dataflow runs. Next, select **userid** from a **Schema columns section** on the right and map it to **id**. @@ -89,7 +86,7 @@ Next, select **userid** from a **Schema columns section** on the right and map i ## Activation -In this section you will test the dataflow with provided test user data. +In this section you can test the dataflow with provided test user data. If everything passes, go to your installation and export production data with this command: ```bash @@ -101,7 +98,7 @@ Now you can run and activate the dataflow. ## Build new Audience/Segment Go to the **Audience Builder** and select **Build new audience**. -When naming the audience remember, you will need to find it in a drop-down list during activation. +When naming the audience remember, you need to find it in a drop-down list during activation. There, you can choose conditions from `did`, `did not` or `have`. The conditions `did` and `did not` allow you to use events like buy, visit or add to a cart from online tracking. - `have` conditions are tied to personal characteristics and can be used to track the sum of all buys or top-visited categories. @@ -121,9 +118,12 @@ Specify name of your activation, select `userid` as **Person Identifier** and cl Next, you can fill in **Ibexa information** they must match the ones provided in the YAML configuration: -- **Client Secret** and **Client ID** - are used to authenticate against Webhook endpoint. In the configuration they are taken from environment variables in `.env` file. +- **Client Secret** and **Client ID** - are used to authenticate against Webhook endpoint. +In the configuration they're taken from environment variables in `.env` file. + +- **Segment Group Identifier** - identifier of the segment group in [[= product_name =]]. +It points to a segment group where all the CDP audiences are stored. -- **Segment Group Identifier** - identifier of the segment group in [[= product_name =]]. It points to a segment group where all the CDP audiences will be stored. - **Base URL** - URL of your instance with added `/cdp/webhook` at the end. ![Ibexa Information - Activation](cdp_activation_ibexa_info.png) diff --git a/docs/cdp/cdp_data_customization.md b/docs/cdp/cdp_data_customization.md index 2d3c76ce4d..e2f8259135 100644 --- a/docs/cdp/cdp_data_customization.md +++ b/docs/cdp/cdp_data_customization.md @@ -5,16 +5,16 @@ edition: experience # Data customization ​ -You can customize Content and Product data exported to CDP and you can control what Field Type information you want to export. -By default, custom Field Types have basic export functionality. +You can customize content and product data exported to CDP and you can control what field type information you want to export. +By default, custom field types have basic export functionality. It casts their `Value` object to string, thanks to `\Stringable` implementation. ​ -## Export Field Types +## Export field types ​ -Field Types are exported with metadata, for example, ID, Field Definition name, type, value. -You can also provide your own `\Ibexa\Contracts\Cdp\Export\Content\FieldProcessorInterface` instance to extend metadata. -The provided implementation has to be defined as a service and tagged with `ibexa.cdp.export.content.field_processor`. -Additionally, you can specify `priority` to override the default behavior. +Field types are exported with metadata, for example, ID, field definition name, type, or value. +You can also provide your own `\Ibexa\Contracts\Cdp\Export\Content\FieldProcessorInterface` instance to extend metadata. +The provided implementation has to be defined as a service and tagged with `ibexa.cdp.export.content.field_processor`. +Additionally, you can specify `priority` to override the default behavior. All system Field Processors use `-100` priority, and any higher priority value overrides them. The interface is plain and has two methods that you need to provide: @@ -22,7 +22,7 @@ The interface is plain and has two methods that you need to provide: - **supports** - decides whether your `FieldProcessor` can work with the `Field` instance. - **process** - takes `Field` instance and then returns a flat array of scalar values that are combined with the payload data. ​ -A common Field Type is serialized to: +A common field type is serialized to: ​ ```json { @@ -43,14 +43,14 @@ A common Field Type is serialized to: Field identifier is a prefix that is automatically added to each key. You can only use scalar values. ​ -### Built in Field Processors for custom Field Types +### Built in Field Processors for custom field types ​ You can provide your own CDP export functionality by using one of the system Field Processors: #### `\Ibexa\Cdp\Export\Content\FieldProcessor\SkippingFieldProcessor`. ​ -It results in the Field Type being excluded from the exported payload. -To avoid adding the Field Type data to the payload, register a new service as follows: +It results in the field type being excluded from the exported payload. +To avoid adding the field type data to the payload, register a new service as follows: ​ ```yaml custom_fieldtype.cdp.export.field_processor: @@ -62,32 +62,32 @@ custom_fieldtype.cdp.export.field_processor: - { name: 'ibexa.cdp.export.content.field_processor', priority: 0 } ``` ​ -## Export Field Type values +## Export field type values ​ -To customize export of Field Type values, provide your own `\Ibexa\Contracts\Cdp\Export\Content\FieldValueProcessorInterface` instance. -New implementation has to be registered as a service manually or by using autoconfiguration. +To customize export of field type values, provide your own `\Ibexa\Contracts\Cdp\Export\Content\FieldValueProcessorInterface` instance. +New implementation has to be registered as a service manually or by using autoconfiguration. The service has to use the tag `ibexa.cdp.export.content.field_value_processor`. You can also provide `priority` property to override other Field Value Processors. ​ * `FieldValueProcessorInterface::process` - takes `Field` instance and returns an `array` with scalar values that are applied to export data payload. -If the Field Type returns a single value, provides a `value` key in the array. +If the field type returns a single value, provides a `value` key in the array. You can return multiple values. * `FieldValueProcessorInterface::supports` - decides whether `FieldValueProcessor` can work with the `Field`. ​ -### Built in Field Value Processors for custom Field Types +### Built in Field Value Processors for custom field types ​ -Several system Field Value Processors either work by default or can be registered for custom Field Types: +Several system Field Value Processors either work by default or can be registered for custom field types: ​ #### `\Ibexa\Cdp\Export\Content\FieldValueProcessor\CastToStringFieldValueProcessor` ​ -This Processor is a default one, as long as no other Processor with higher priority is registered. It makes `\Stringable` implementation of the Field Type `\Ibexa\Core\FieldType\Value` object to use it as a value in the final payload. +This Processor is a default one, as long as no other Processor with higher priority is registered. It makes `\Stringable` implementation of the field type `\Ibexa\Core\FieldType\Value` object to use it as a value in the final payload. ​ #### `\Ibexa\Cdp\Export\Content\FieldValueProcessor\JsonHashFieldValueProcessor` ​ -This Processor generates JSON data from hash representation of the Field Type (it uses `\Ibexa\Contracts\Core\FieldType\FieldType::toHash` method). +This Processor generates JSON data from hash representation of the field type (it uses `\Ibexa\Contracts\Core\FieldType\FieldType::toHash` method). -!!! warning +!!! caution CDP doesn't support column mapping, which allows you to match records on JSON data directly. diff --git a/docs/cdp/cdp_data_export_schedule.md b/docs/cdp/cdp_data_export_schedule.md index 3e277bca91..7102d57bc7 100644 --- a/docs/cdp/cdp_data_export_schedule.md +++ b/docs/cdp/cdp_data_export_schedule.md @@ -7,7 +7,7 @@ edition: experience ## Configuration key -Configuration in [[= product_name_cdp =]] allows you to automate the process of exporting Content, Users and Products. +Configuration in [[= product_name_cdp =]] allows you to automate the process of exporting content, users, and products. An `ibexa_cdp.data_export` [configuration key](configuration.md#configuration-files) looks as below: ```yaml @@ -37,7 +37,7 @@ ibexa_cdp: options: '--stream-id=00000000-00000000-00000000-00000000 --product-type=computer --no-draft' ``` -Under the `schedule` setting you can find separate sections for exporting User, Content, and Product. +Under the `schedule` setting you can find separate sections for exporting user, content, and product. Structure of each section is exactly the same and includes `interval` and `options` elements: - `interval` - sets the frequency of the command invoke, for example, '*/30 * * * *' means "every 30 minutes", '0 */12 * * *' means "every 12th hour". diff --git a/docs/cdp/cdp_guide.md b/docs/cdp/cdp_guide.md index fbfb7a6970..97c30501e9 100644 --- a/docs/cdp/cdp_guide.md +++ b/docs/cdp/cdp_guide.md @@ -11,17 +11,19 @@ edition: experience By using [[= product_name_cdp =]] you can monitor and compile data about your customers' activity on multiple channels. It also allows you to create individual customer profiles so you can customize their experience on your platform. -With [[= product_name_cdp =]] you can store and manage large volumes of customer data in a structured manner. This central data storage supports business growth with a scalable infrastructure, helping to futureproof your business. +With [[= product_name_cdp =]] you can store and manage large volumes of customer data in a structured manner. +This central data storage supports business growth with a scalable infrastructure, helping to futureproof your business. You can get customer data from both online and offline data sources. -It includes first, second, and third-party data from multiple sources such as transactional systems, website tracking and behavior, POS, CRM, and others. +It includes first, second, and third-party data from multiple sources such as transactional systems, website tracking, and behavior, POS, CRM, and others. ## Availability [[= product_name_cdp =]] is available in [[= product_name_exp =]] and [[= product_name_com =]] editions. -## How does Ibexa CDP work +## How does [[= product_name_cdp =]] work -[[= product_name_cdp =]] unifies customer data throughout your whole organization. It helps you activate your users and give them real-time interaction. +[[= product_name_cdp =]] unifies customer data throughout your whole organization. +It helps you activate your users and give them real-time interaction. You can target certain user segments with the appropriate message, content, or products at the right time through the most used channels by using specified audiences. Customer data is gathered through a system of trackers embedded in various areas of your website. @@ -29,14 +31,18 @@ Customer data is gathered through a system of trackers embedded in various areas ### Installation and configuration -To start using [[= product_name_cdp =]], first you need to contact your sales representative, who provides you with a link to [register your [[= product_name_cdp =]] account](https://doc.ibexa.co/en/latest/cdp/cdp_installation/#register-in-ibexa-cdp-dashboard). When you're done with registration process, you'll be able to access a separate instance with the data needed to configure, activate, and use this feature. +To start using [[= product_name_cdp =]], first you need to contact your sales representative, who provides you with a link to [register your [[= product_name_cdp =]] account](https://doc.ibexa.co/en/latest/cdp/cdp_installation/#register-in-ibexa-cdp-dashboard). +When you're done with registration process, you're able to access a separate instance with the data needed to configure, activate, and use this feature. -After your account is created, you can [download and install the [[= product_name_cdp =]] package](https://doc.ibexa.co/en/latest/cdp/cdp_installation/#install-cdp-package) that is opt-in and needs to be downloaded separately. Last step is to go through the [configuration process](https://doc.ibexa.co/en/latest/cdp/cdp_activation/cdp_configuration/). +After your account is created, you can [download and install the [[= product_name_cdp =]] package](https://doc.ibexa.co/en/latest/cdp/cdp_installation/#install-cdp-package) that is opt-in and needs to be downloaded separately. +Last step is to go through the [configuration process](https://doc.ibexa.co/en/latest/cdp/cdp_activation/cdp_configuration/). ### Customer profile -In [[= product_name_cdp =]] you can build 360° customer profiles. It unifies customer data from different sources to help you understand your prospects and customer needs. -After you get customer data, you can unify and match customer profiles based on their preferences and habits. You can create and analyze complete, 360° customer profiles based on demographics, interactions, behaviors, and transactional data. +In [[= product_name_cdp =]] you can build 360° customer profiles. +It unifies customer data from different sources to help you understand your prospects and customer needs. +After you get customer data, you can unify and match customer profiles based on their preferences and habits. +You can create and analyze complete, 360° customer profiles based on demographics, interactions, behaviors, and transactional data. This approach helps you create a single customer view. ![Customer profile](img/customer_profile.png) @@ -47,9 +53,10 @@ To create a personalized customer experience, you need to group your clients int [[= product_name =]] comes with a ready solution - segment groups. Segment group information is reused by various [[= product_name =]] functionalities, such as [Personalization](personalization_guide.md) or content targeting. -You can [create a segment group](https://doc.ibexa.co/projects/userguide/en/latest/personalization/segment_management/) in the Back Office of [[= product_name =]]. It serves as a container for all segments data generated by [[= product_name_cdp =]]. +You can [create a segment group](https://doc.ibexa.co/projects/userguide/en/latest/personalization/segment_management/) in the back office of [[= product_name =]]. +It serves as a container for all segments data generated by [[= product_name_cdp =]]. When you create a segment group, you need to provide its name and identifier. -Be careful while doing so, as after you create the segment group in the Back Office and connect it to [[= product_name_cdp =]], you cannot change it in any way, including edit its name. +Be careful while doing so, as after you create the segment group in the back office and connect it to [[= product_name_cdp =]], you cannot change it in any way, including edit its name. Remember to add a segment group identifier to the configuration, under the `segment_group_identifier` field. @@ -57,14 +64,16 @@ Remember to add a segment group identifier to the configuration, under the `segm ### Data export -Configuration in [[= product_name_cdp =]] allows you to automate the process of exporting Content, Users, and Products. -An `ibexa_cdp.data_export` [configuration key](https://doc.ibexa.co/en/latest/cdp/cdp_data_export_schedule/#configuration-key) includes the `schedule` setting where you can find separate sections for exporting User, Content, and Product. Structure of each section is exactly the same and includes `interval` and `options` elements: +Configuration in [[= product_name_cdp =]] allows you to automate the process of exporting content, users, and products. +An `ibexa_cdp.data_export` [configuration key](https://doc.ibexa.co/en/latest/cdp/cdp_data_export_schedule/#configuration-key) includes the `schedule` setting where you can find separate sections for exporting user, content, and product. +Structure of each section is exactly the same and includes `interval` and `options` elements: -- `interval` - sets the frequency of the command invoke using cron expressions, for example, '*/30 * * * *' means "every 30 minutes", '0 */12 * * *' means "every 12th hour". +- `interval` - sets the frequency at which the command is invoked, uses cron expressions, for example, '*/30 * * * *' means "every 30 minutes", '0 */12 * * *' means "every 12th hour" -- `options` - allows you to add arguments that have to be passed to the export command. +- `options` - allows you to add arguments that have to be passed to the export command -This configuration allows you to provide multiple export workflows with parameters. It's important, because all the types of content/product must have their own parameters on the CDP side, where each has a different Stream ID key and different required values configured per data source. +This configuration allows you to provide multiple export workflows with parameters. +It's important, because all the types of content/product must have their own parameters on the CDP side, where each has a different Stream ID key and different required values configured per data source. Regarding data export, currently, only Stream File transport is supported and can be initialized from the configuration. @@ -72,8 +81,9 @@ For more information, see [CDP data export](https://doc.ibexa.co/en/latest/cdp/c ### Data customization -​You can customize Content and Product data exported to [[= product_name_cdp =]] and control what Field Type information you want to export. -With [[= product_name_cdp =]], you can export Field Types and Field Type values. They are exported with metadata and attributes, for example, ID, Field Definition name, type, value. +​You can customize content and product data exported to [[= product_name_cdp =]] and control what field type information you want to export. +With [[= product_name_cdp =]], you can export field types and field type values. +They're exported with metadata and attributes, for example, ID, field definition name, type, or value. For more information, see [data customization](https://doc.ibexa.co/en/latest/cdp/cdp_data_customization/#data-customization) documentation in Developer Documentation. @@ -86,7 +96,8 @@ For more information, see [CDP add client-side tracking](https://doc.ibexa.co/en In the Audience Builder, you can create audiences - groups of users that meet the assumed conditions. You can choose specific conditions: `did`, `did not`, or `have`. -The conditions `did` and `did not` allow you to use events like buy, visit or add to a cart from online tracking. The `have` conditions are tied to personal characteristics and can be used to track the sum of all buys or top-visited categories. +The conditions `did` and `did not` allow you to use events like buy, visit or add to a cart from online tracking. +The `have` conditions are tied to personal characteristics and can be used to track the sum of all buys or top-visited categories. You can also connect created audiences to the activations. @@ -103,7 +114,7 @@ Build extensive customer profiles that include their interactions, habits, and p ### Segment groups Provide a personalized customer experience, group your clients into specified audiences, and provide recommendations depending on the user data. -Create Segment groups to deliver personalized campaigns to boost engagement and conversion rates. +Create segment groups to deliver personalized campaigns to boost engagement and conversion rates. ### Audience Builder @@ -111,12 +122,13 @@ Create user groups - audiences - based on conditions and events. ### Data export -Export data regarding Content, Users, and Products. Data export includes automatic file mapping. +Export data regarding content, users, and products. +Data export includes automatic file mapping. Analyze customer data, track campaigns, and discover the most effective strategies to boost performance. ### Data customization -Customize data to control what Field Type information you want to export. +Customize data to control what field type information you want to export. ### Real-time action diff --git a/docs/cdp/cdp_installation.md b/docs/cdp/cdp_installation.md index a87f1136fd..25cf4d2573 100644 --- a/docs/cdp/cdp_installation.md +++ b/docs/cdp/cdp_installation.md @@ -3,17 +3,15 @@ description: Installation of standalone Ibexa CDP package. edition: experience --- -# Ibexa CDP installation +# [[= product_name_cdp =]] installation There are three steps required to install [[= product_name_cdp =]]. -First, you need to register your [[= product_name_cdp =]] account, then you can download a CDP package and update the configuration. +First, you need to register your [[= product_name_cdp =]] account, then you can download a CDP package and update the configuration. -## Register in Ibexa CDP dashboard +## Register in [[= product_name_cdp =]] dashboard -If you decide to acquire [[= product_name_cdp =]] contact your sales representative, -they will provide you with a registration link to [[= product_name_cdp =]]. -After registration, you will get access to a separate instance -where you will find data required for configuring, activating and using this feature. +If you decide to acquire [[= product_name_cdp =]] contact your sales representative, they provide you with a registration link to [[= product_name_cdp =]]. +After registration, you get access to a separate instance where you can find data required for configuring, activating, and using this feature. ## Install CDP package @@ -25,9 +23,8 @@ To download it run: composer require ibexa/cdp ``` -Flex will install and activate the package. -After an installation process is finished, go to `config/packages/security.yaml` -and uncomment `ibexa_cdp` rule. +Flex installs and activates the package. +After an installation process is finished, go to `config/packages/security.yaml` and uncomment `ibexa_cdp` rule. ```yaml ibexa_cdp: diff --git a/docs/commerce/cart/cart.md b/docs/commerce/cart/cart.md index 61781b7578..da2e07f345 100644 --- a/docs/commerce/cart/cart.md +++ b/docs/commerce/cart/cart.md @@ -1,14 +1,12 @@ --- -description: The cart component covers adding items to the shopping cart, as well as previewing and modifying the cart information. +description: The cart component covers adding items to the shopping cart, and previewing or modifying the cart information. edition: commerce --- # Cart -The cart component is a foundation of the Commerce offering delivered as part -of [[= product_name =]]. -It covers actions related to the creation and handling of a list of products -that the buyer intends to purchase. +The cart component is a foundation of the Commerce offering delivered as part of [[= product_name_com =]]. +It covers actions related to the creation and handling of a list of products that the buyer intends to purchase. The component exposes the following: @@ -27,42 +25,34 @@ Cart constructor takes the following arguments: ## Cart data handling -Cart data is handled by two storages, depending on whether the buyer is anonymous -or has been authenticated. -Information that relates to anonymous users is stored in the PHP session, while -registered user data is stored in a database. +Cart data is handled by two storages, depending on whether the buyer is anonymous or has been authenticated. +Information that relates to anonymous users is stored in the PHP session, while registered user data is stored in a database. -By default, anonymous users can add items to cart, but to display the cart view, -they have to log in and transition into an authenticated user. +By default, anonymous users can add items to cart, but to display the cart view, they have to log in and transition into an authenticated user. -!!! note +!!! note - For information about roles and permissions that control access to the cart, - see [Permission use cases](permission_use_cases.md#commerce). + For information about roles and permissions that control access to the cart, see [Permission use cases](permission_use_cases.md#commerce). ### Cart data merging -When a buyer browses the storefront anonymously and fills the cart with items, -anonymous cart data is stored in the PHP session storage. -Then, when an anonymous user logs into the storefront, cart data from the PHP session -storage is persisted and merged with any cart information that might already exist in the database for this authenticated user. +When a buyer browses the storefront anonymously and fills the cart with items, anonymous cart data is stored in the PHP session storage. +Then, when an anonymous user logs into the storefront, cart data from the PHP session storage is persisted and merged with any cart information that might already exist in the database for this authenticated user. If no previous cart data exists, a new cart is created. ### Cart data validation -When a buyer tries to add products to the cart, increase cart item quantity or proceed to checkout, the cart component performs cart item validation and checks whether: +When a buyer tries to add products to the cart, increase cart item quantity, or proceed to checkout, the cart component performs cart item validation and checks whether: -- the product is available -- the requested quantity of product is available -- the product is available at a price in the currency selected for the cart +- the product is available +- the requested quantity of product is available +- the product is available at a price in the currency selected for the cart ## Front-end perspective -From the front-end perspective, the cart consists of a main `Cart` object -and several widgets. -`Cart` is a standalone JavaScript object that manages cart data and has no user interface, -while widgets consist of JavaScript code and accompanying Twig templates. +From the front-end perspective, the cart consists of a main `Cart` object and several widgets. +`Cart` is a standalone JavaScript object that manages cart data and has no user interface, while widgets consist of JavaScript code and accompanying Twig templates. ### Cart service object @@ -85,12 +75,11 @@ document.body.addEventListener( ); ``` -### Cart service +### Cart service -The Cart package provides `Ibexa\Contracts\Cart\CartServiceInterface` Symfony service, -which is the entrypoint for calling the [backend API](cart_api.md). +The Cart package provides `Ibexa\Contracts\Cart\CartServiceInterface` Symfony service, which is the entrypoint for calling the [backend API](cart_api.md). -You can import the service using the following code: +You can import the service with the following code: ```js import * as cartService from '@ibexa-cart/src/bundle/Resources/public/js/service/cart'; @@ -103,7 +92,7 @@ cartService.deleteCartEntry(cartIdentifier, entryIdentifier); ``` Every cart service function returns a `Promise` object with a parsed response. -When the request is not `OK`, it can throw an error with the response `statusText`. +When the request isn't `OK`, it can throw an error with the response `statusText`. - `loadUserCarts(ownerId)` - loads 10 user carts - `loadCartSummary(cartIdentifier)` - load cart summary data diff --git a/docs/commerce/cart/cart_api.md b/docs/commerce/cart/cart_api.md index a849759cd6..afcb234c8f 100644 --- a/docs/commerce/cart/cart_api.md +++ b/docs/commerce/cart/cart_api.md @@ -16,7 +16,7 @@ To get carts and work with them, use the `Ibexa\Contracts\Cart\CartServiceInterf - carts of registered users use database-based storage - anonymous user carts are stored in the PHP session -From the developer's perspective, carts and entries are referenced with a UUID identifier. +From the developer's perspective, carts and entries are referenced with a UUID identifier. ## Get single cart by identifier @@ -28,7 +28,7 @@ To access a single cart, use the `CartServiceInterface::getCart` method: ## Get multiple carts -To fetch multiple carts, use the `CartServiceInterface::findCarts` method. +To fetch multiple carts, use the `CartServiceInterface::findCarts` method. It follows the same search Query pattern as other APIs: ``` php @@ -40,8 +40,7 @@ It follows the same search Query pattern as other APIs: ## Create cart -To create a cart, use the `CartServiceInterface::createCart` method and provide -it with `Ibexa\Contracts\Cart\Value\CartCreateStruct` that contains metadata (name, currency, owner): +To create a cart, use the `CartServiceInterface::createCart` method and provide it with `Ibexa\Contracts\Cart\Value\CartCreateStruct` that contains metadata (name, currency, owner): ``` php [[= include_file('code_samples/api/commerce/src/Command/CartCommand.php', 8, 9) =]] @@ -52,9 +51,8 @@ it with `Ibexa\Contracts\Cart\Value\CartCreateStruct` that contains metadata (na ## Update cart metadata -You can update cart metadata after the cart is created. -You could do it to support a scenario when, for example, the user changes a currency -and the cart should recalculate all item prices to a new currency. +You can update cart metadata after the cart is created. +You could do it to support a scenario when, for example, the user changes a currency and the cart should recalculate all item prices to a new currency. To update cart metadata, use the `CartServiceInterface::updateCartMetadata` method: ``` php @@ -79,8 +77,7 @@ $cart = $cartService->updateCartMetadata($cart, $updateMetadataStruct); ## Delete cart -To delete a cart permanently, use the `CartServiceInterface::deleteCart` method -and pass the `CartInterface` object: +To delete a cart permanently, use the `CartServiceInterface::deleteCart` method and pass the `CartInterface` object: ``` php [[= include_file('code_samples/api/commerce/src/Command/CartCommand.php', 88, 89) =]] @@ -89,8 +86,7 @@ and pass the `CartInterface` object: ## Empty cart -To remove all products from the cart in a single operation, use the -`CartServiceInterface::emptyCart` method: +To remove all products from the cart in a single operation, use the `CartServiceInterface::emptyCart` method: ``` php [[= include_file('code_samples/api/commerce/src/Command/CartCommand.php', 88, 89) =]] @@ -99,12 +95,10 @@ To remove all products from the cart in a single operation, use the ## Check cart validity -Items in cart can become invalid, for example, when item price is unavailable -in cart currency, or the product is no longer available. -To prevent checking out a cart with invalid items, check cart validity first. -To validate the cart, use the `CartServiceInterface::validateCart` method. -Validation is done with help from the `symfony/validator` component, and the method -returns a `Symfony\Component\Validator\ConstraintViolationListInterface` object. +Items in cart can become invalid, for example, when item price is unavailable in cart currency, or the product is no longer available. +To prevent checking out a cart with invalid items, check cart validity first. +To validate the cart, use the `CartServiceInterface::validateCart` method. +Validation is done with help from the `symfony/validator` component, and the method returns a `Symfony\Component\Validator\ConstraintViolationListInterface` object. ``` php [[= include_file('code_samples/api/commerce/src/Command/CartCommand.php', 88, 89) =]] @@ -113,9 +107,8 @@ returns a `Symfony\Component\Validator\ConstraintViolationListInterface` object. ## Add entry to cart -To add entries (products) to the cart, create an `Ibexa\Contracts\Cart\Value\EntryAddStruct`, -where you specify the requested quantity of the product. -Then pass it to the `CartServiceInterface::addEntry` method: +To add entries (products) to the cart, create an `Ibexa\Contracts\Cart\Value\EntryAddStruct`, where you specify the requested quantity of the product. +Then pass it to the `CartServiceInterface::addEntry` method: ``` php [[= include_file('code_samples/api/commerce/src/Command/CartCommand.php', 11, 12) =]] @@ -139,9 +132,8 @@ To remove an entry from the cart, use the `CartServiceInterface::removeEntry` me ## Update entry metadata -Entries have their own metadata, for example, quantity. -To change entry metadata, use the `CartServiceInterface::updateEntry` method -and provide it with `Ibexa\Contracts\Cart\Value\EntryUpdateStruct`. +Entries have their own metadata, for example, quantity. +To change entry metadata, use the `CartServiceInterface::updateEntry` method and provide it with `Ibexa\Contracts\Cart\Value\EntryUpdateStruct`. ``` php [[= include_file('code_samples/api/commerce/src/Command/CartCommand.php', 12, 13) =]] @@ -170,9 +162,8 @@ $createStruct->setContext(new ArrayMap([ $cart = $cartService->createCart($createStruct); ``` -In the above example, you create a cart using the `CartCreateStruct`, -and set the context data using the `setContext` method. -You've also added "X1MF7699" coupon code as context data to the cart. +In the above example, you create a cart with the `CartCreateStruct` method, and set the context data with `setContext`. +You also add "X1MF7699" coupon code as context data to the cart. ### Adding context data to cart entry @@ -187,13 +178,13 @@ $entryAddStruct->setContext(new ArrayMap([ $cartService->addEntry($cart, $entryAddStruct); ``` -In the above example, you create a cart entry using the `EntryAddStruct`. +In the above example, you create a cart entry by using the `EntryAddStruct` method. The `setContext` method allows you to attach context data to the cart entry. -In this case, you've attached a "tshirt_text" attribute to the cart entry, which might represent custom text for a T-shirt. +In this case, you attach a "tshirt_text" attribute to the cart entry, which might represent custom text for a T-shirt. ## Merge carts -To combine the contents of multiple shopping carts into a target cart, use the `CartServiceInterface::mergeCarts` method. +To combine the contents of multiple shopping carts into a target cart, use the `CartServiceInterface::mergeCarts` method. This operation is helpful when you want to consolidate items from a reorder cart and a current cart into a single order. ```php diff --git a/docs/commerce/cart/quick_order.md b/docs/commerce/cart/quick_order.md index 486aed6f0d..ec1b5ae68d 100644 --- a/docs/commerce/cart/quick_order.md +++ b/docs/commerce/cart/quick_order.md @@ -19,7 +19,7 @@ Customers can use one or both of the following methods to specify products and p 2\. Provides products' SKU and quantity. At this point, no validation is provided. -![Customer enters individual products](img/quick_order_list.png) +![Customer enters individual products](img/quick_order_list.png) 3\. Customer clicks **Add to cart** to add items to the cart and finish an ordering process. @@ -31,15 +31,15 @@ Customers can use one or both of the following methods to specify products and p 2\. Downloads a sample file from **Add your order** section. -3\. Uses the template to fill in their order with products' SKU and quantity. +3\. Uses the template to fill in their order with products' SKU and quantity. 4\. Uploads the filled in quick order file back to the system by drag and drop or file selection. -5\. The file name appears in the **Add your order** section. At this point, only file validation is provided. The SKUs or product availability is not validated. +5\. The file name appears in the **Add your order** section. At this point, only file validation is provided. The SKUs or product availability isn't validated. ![Customer uploads list of products](img/quick_order_add_order.png) -6\. Customer clicks **Add to cart** to add items to the cart and finish an ordering process. +6\. Customer clicks **Add to cart** to add items to the cart and finish an ordering process. 7\. In the cart section, the file format and provided data are validated, the availability of the entered product is checked, and the customer is informed if any of them is unavailable or quantity is insufficient. diff --git a/docs/commerce/checkout/checkout.md b/docs/commerce/checkout/checkout.md index a0efde604e..bd19cc8ecd 100644 --- a/docs/commerce/checkout/checkout.md +++ b/docs/commerce/checkout/checkout.md @@ -5,65 +5,55 @@ edition: commerce # Checkout -Checkout is a crucial component of the Commerce offering delivered as part -of [[= product_name =]]. -In a course of a multi-step process, it collects necessary transaction data, such -as billing and shipping addresses, and payment and shipping information. +Checkout is a crucial component of the Commerce offering delivered as part of [[= product_name_com =]]. +In a course of a multi-step process, it collects necessary transaction data, such as billing and shipping addresses, payment and shipping information. -From the front-end perspective, it is a reusable component that provides access -to the workflow and allows buyers to place an order for cart items. +From the front-end perspective, it's a reusable component that provides access to the workflow and allows buyers to place an order for cart items. ![Address selection stage](checkout.png "Checkout stages") -Depending on the model of shopping process that you need to use, the checkout -process can range between a straightforward and extremely complicated one. +Depending on the model of shopping process that you need to use, the checkout process can range between a straightforward and extremely complicated one. To allow for this variation, the component is highly configurable and extensible: -- Like the editorial workflow, it relies on [Symfony Workflow]([[= symfony_doc =]]/components/workflow.html) +- Like the editorial workflow, it relies on [Symfony Workflow]([[= symfony_doc =]]/components/workflow.html) - It exposes [PHP API](checkout_api.md) that allows for workflow manipulation - It exposes Twig functions used for checkout rendering In a default implementation, users go through a series of steps. -They first select a billing and shipping address, then select shipping and payment -methods, later they review summary and confirm their choices, to finally receive -a simulated order confirmation. +They first select a billing and shipping address, then select shipping and payment methods, later they review summary, and confirm their choices, to finally receive a simulated order confirmation. -Until the checkout process is complete, at any point of the process, users can -go back to the cart and modify cart information, for example, cart item quantities. -They can also navigate back and forth between checkout steps, with an exception -of the "Checkout complete" step, which always ends the process. +Until the checkout process is complete, at any point of the process, users can go back to the cart and modify cart information, for example, cart item quantities. +They can also navigate back and forth between checkout steps, with an exception of the "Checkout complete" step, which always ends the process. You can modify these steps according to your needs. For more information, see [Configure checkout](configure_checkout.md). -## Shipping and billing address assignment logic +## Shipping and billing address assignment logic -As far as shipping details are concerned, checkout can behave differently, depending -on whether the buyer is a corporate account member, a registered customer, or -an individual. +As far as shipping details are concerned, checkout can behave differently, depending on whether the buyer is a corporate account member, a registered customer, or an individual. -- Corporate account members will see a company's billing address, and several shipping addresses to pick from, as predefined in the company profile. -- Registered customers will be able see and modify the addresses that they defined at registration -- Individuals will be able to enter both addresses at checkout +- Corporate account members can see a company's billing address, and several shipping addresses to pick from, as predefined in the company profile. +- Registered customers are able see and modify the addresses that they defined at registration +- Individuals are able to enter both addresses at checkout For more information about shipping and billing addresses, see [Configure checkout](configure_checkout.md#configure-shipping-and-billing-address-field-format). ## Virtual Products checkout -Virtual product is a special type of a [product](products.md). Virtual products are non-tangible items such as memberships, services, warranties. +Virtual product is a special type of a [product](products.md). Virtual products are non-tangible items such as memberships, services, warranties. They can be sold individually, or as part of a product bundle. Virtual products don’t require shipment when they're purchased individually. -While purchasing virtual product, you only have to fill in the billing address and select relevant payment method. +While purchasing virtual product, you only have to fill in the billing address and select relevant payment method. ![`Virtual product purchasing`](virtual_product_purchase.png "Virtual product purchasing") ## Reorder Reorder functions as the variant for the checkout workflow and is accessible solely to logged-in users. -It initiates from the user's order history, where they can click **Reorder** and trigger the flow. -Next, the user is moved to cart where the system validates the order against existing stock. +It initiates from the user's order history, where they can click **Reorder** and trigger the flow. +Next, the user is moved to cart where the system validates the order against existing stock. If everything is available, customer can move to payment and summary. -The system pre-fills address, shipping method, and payment details using information from the past order. +The system uses information from the past order to pre-fill address, shipping method, and payment details. For more information, see [reorder documentation](reorder.md). \ No newline at end of file diff --git a/docs/commerce/checkout/checkout_api.md b/docs/commerce/checkout/checkout_api.md index 6195384801..b45f220587 100644 --- a/docs/commerce/checkout/checkout_api.md +++ b/docs/commerce/checkout/checkout_api.md @@ -7,18 +7,15 @@ edition: commerce To get checkouts and manage them, use the `Ibexa\Contracts\Checkout\CheckoutServiceInterface` interface. -With `CheckoutServiceInterface`, you manipulate checkouts that are stored in sessions. -Checkouts are containers for the `Ibexa\Contracts\Cart\Value\CartInterface` object -and all the data provided at each step of the [configurable checkout process](configure_checkout.md). +With `CheckoutServiceInterface`, you manipulate checkouts that are stored in sessions. +Checkouts are containers for the `Ibexa\Contracts\Cart\Value\CartInterface` object and all the data provided at each step of the [configurable checkout process](configure_checkout.md). -The checkout process relies on Symfony Workflow, and you can customize each of its steps. -Each checkout step has its own controller that allows adding forms and external API calls -that process data and pass them to `CheckoutService`. -Completing a step results in submitting a form and updating the current checkout object. -At this point Symfony Workflow advances, the next controller takes over, and the -whole process continues. +The checkout process relies on Symfony Workflow, and you can customize each of its steps. +Each checkout step has its own controller that allows adding forms and external API calls that process data and pass them to `CheckoutService`. +Completing a step results in submitting a form and updating the current checkout object. +At this point Symfony Workflow advances, the next controller takes over, and the whole process continues. -From the developer's perspective, checkouts are referenced with an UUID identifier. +From the developer's perspective, checkouts are referenced with an UUID identifier. ## Get single checkout by identifier @@ -30,9 +27,8 @@ To access a single checkout, use the `CheckoutServiceInterface::getCheckout` met ## Get single checkout for specific cart -To fetch checkout for a cart that already exists, use the `CheckoutServiceInterface::getCheckoutForCart` method. -It can be useful when you want to initiate the checkout process right after -products are successfully added to a cart. +To fetch checkout for a cart that already exists, use the `CheckoutServiceInterface::getCheckoutForCart` method. +You can use it when you want to initiate the checkout process right after products are successfully added to a cart. ``` php [[= include_file('code_samples/api/commerce/src/Controller/CustomCheckoutController.php', 26, 30) =]] @@ -40,8 +36,7 @@ products are successfully added to a cart. ## Create checkout -To create a checkout, use the `CheckoutServiceInterface::createCheckout` method and -provide it with a `CheckoutCreateStruct` struct that contains a `CartInterface` object. +To create a checkout, use the `CheckoutServiceInterface::createCheckout` method and provide it with a `CheckoutCreateStruct` struct that contains a `CartInterface` object. ``` php [[= include_file('code_samples/api/commerce/src/Controller/CustomCheckoutController.php', 35, 41) =]] @@ -50,12 +45,10 @@ provide it with a `CheckoutCreateStruct` struct that contains a `CartInterface` ## Update checkout You can update the collected data after the checkout is created. -The data is stored within the `CheckoutInterface::context` object. -The last update time and status are also stored. +The data is stored within the `CheckoutInterface::context` object. +The last update time and status are also stored. -To update the checkout, use the `CheckoutServiceInterface::updateCheckout` method -and provide it with the `CheckoutUpdateStruct` struct that contains data collected at each -step of the workflow, as well as a transition name to identify what step will follow. +To update the checkout, use the `CheckoutServiceInterface::updateCheckout` method and provide it with the `CheckoutUpdateStruct` struct that contains data collected at each step of the workflow, and a transition name to identify what step follows. All data is placed in session storage. diff --git a/docs/commerce/checkout/configure_checkout.md b/docs/commerce/checkout/configure_checkout.md index b9d50a9dc9..4079c6da97 100644 --- a/docs/commerce/checkout/configure_checkout.md +++ b/docs/commerce/checkout/configure_checkout.md @@ -5,40 +5,39 @@ edition: commerce # Configure checkout -When you work with your Commerce implementation, you can review and modify -the checkout configuration. +When you work with your Commerce implementation, you can review and modify the checkout configuration. -!!! note "Permissions" +!!! note "Permissions" When you modify the workflow configuration, make sure you properly set user [permissions](permission_use_cases.md#commerce) to the checkout component. ## Configure checkout workflow Checkout workflow relies on [Symfony Workflow]([[= symfony_doc =]]/components/workflow.html). -Each transition represents a separate checkout step. +Each transition represents a separate checkout step. -By default, the checkout process is configured to render each step based on a separate -set of libraries and templates. +By default, the checkout process is configured to render each step based on a separate set of libraries and templates. Each checkout step is handled by a controller that you configure in workflow metadata. -Custom workflow implementations are defined under the `framework.workflows` key, -and they must support the `Ibexa\Contracts\Checkout\Value\CheckoutInterface`. +Custom workflow implementations are defined under the `framework.workflows` key, and they must support the `Ibexa\Contracts\Checkout\Value\CheckoutInterface`. The default fallback workflow is `ibexa_checkout`, which is prepended at bundle level. The `checkout.workflow` parameter is repository-aware. -To customize your configuration, place it in a YAML file, under the `framework.workflows.` key, and reference it with `ibexa.repositories..checkout.workflow: your_workflow_name`. +To customize your configuration, place it in a YAML file, under the `framework.workflows.` key, and reference it with `ibexa.repositories..checkout.workflow: your_workflow_name`. The system can then identify which of your configured workflows handles the checkout process. -!!! note +!!! note When you modify or create a controller, to ensure that no user data is lost, extend the `Ibexa\Bundle\Checkout\Controller\AbstractStep` controller and call the `advance()` method. Each step configuration includes the following settings: -- `controller` - A mandatory setting pointing to a library that governs the behavior of the process. The controller contains all the required business logic and submits the whole step, so that a transition can happen. -- `next_step` - An optional name of the next workflow transition. If not provided, the next workflow-enabled transition is processed. +- `controller` - A mandatory setting pointing to a library that governs the behavior of the process. +The controller contains all the required business logic and submits the whole step, so that a transition can happen. +- `next_step` - An optional name of the next workflow transition. +If not provided, the next workflow-enabled transition is processed. - `label` - An optional name of the step that can be displayed in the Twig helper. -- `translation_domain` - A optional setting that defines the domain for a site with translated content. By default it is set to `checkout`. +- `translation_domain` - A optional setting that defines the domain for a site with translated content. By default it's set to `checkout`. ### Checkout customization example @@ -51,14 +50,12 @@ For more information, see [Work with shipping methods]([[= user_doc =]]/commerce ## Configure shipping and billing address field format -In your implementation, you may need to create custom format configurations -for the shipping or billing address fields, for example, to use different address -formats based on the buyer's geographical location. +In your implementation, you may need to create custom format configurations for the shipping or billing address fields, for example, to use different address formats based on the buyer's geographical location. -Field formats for the billing and shipping addresses comply with the [FieldType Address](addressfield.md#formats) specification and can be controlled with the `billing_address_format` and `shipping_address_format` flags, respectively. +Field formats for the billing and shipping addresses comply with the [FieldType Address](addressfield.md#formats) specification and can be controlled with the `billing_address_format` and `shipping_address_format` flags. They fall back to `billing` and `shipping` predefined formats by default: -- `billing` is part of the `ibexa/corporate-accounts` repository -- `shipping` is part of the `ibexa/checkout` bundle's default configuration +- `billing` is part of the `ibexa/corporate-accounts` repository +- `shipping` is part of the `ibexa/checkout` bundle's default configuration To modify address formats you create custom ones. \ No newline at end of file diff --git a/docs/commerce/checkout/customize_checkout.md b/docs/commerce/checkout/customize_checkout.md index 0f4e665208..8f998c6573 100644 --- a/docs/commerce/checkout/customize_checkout.md +++ b/docs/commerce/checkout/customize_checkout.md @@ -5,8 +5,7 @@ edition: commerce # Customize checkout -When you work with your Commerce implementation, you can review and modify -the checkout configuration. +When you work with your Commerce implementation, you can review and modify the checkout configuration. Checkout is an essential component of the Commerce offering. It collects data that is necessary to create an order, including: @@ -17,44 +16,39 @@ It collects data that is necessary to create an order, including: It could also collect any other information that you find necessary. -Depending on your needs, the checkout process can be either complicated or very simple. -For example, if the website is selling airline tickets, you may need several [additional steps](#add-checkout-step) -with passengers defining their special needs. -On the other side of the spectrum would be a store that sells books with personal pickup, -where [one page checkout](#create-a-one-page-checkout) would be enough. +Depending on your needs, the checkout process can be either complex or straightforward. +For example, if the website is selling airline tickets, you may need several [additional steps](#add-checkout-step) with passengers defining their special needs. +On the other side of the spectrum would be a store that sells books with personal pickup, where [one page checkout](#create-a-one-page-checkout) would be enough. -There are several factors that make checkout particularly flexible and customizable: +Several factors make checkout particularly flexible and customizable: -- it is based on Symfony workflow +- it's based on Symfony workflow - it exposes a variety of APIs - it exposes Twig functions that help you render the steps -The most important contract exposed by the package is the `CheckoutServiceInterface` interface. -It exposes a number of methods that you can call, for example, to load checkouts based -on checkout identifier or for a specific cart. -Other methods help you create, update, or delete checkouts. +The most important contract exposed by the package is the `CheckoutServiceInterface` interface. +It exposes a number of methods that you can call, for example, to load checkouts based on checkout identifier or for a specific cart. +Other methods help you create, update, or delete checkouts. For more information, see [Checkout API](checkout_api.md). ## Add checkout step By default, [[= product_name =]] comes with a multi-step checkout process, which you can expand by adding steps. -For example, if you were creating a project for selling theater tickets, you could add a step -that allows users to select their seats. +For example, if you were creating a project for selling theater tickets, you could add a step that allows users to select their seats. ### Define workflow -You can create workflow definitions under the `framework.workflows` [configuration key](configuration.md#configuration-files). -Each workflow definition consists of a series of steps as well as a series of transitions between the steps. +You can create workflow definitions under the `framework.workflows` [configuration key](configuration.md#configuration-files). +Each workflow definition consists of a series of steps and a series of transitions between the steps. -To create a new workflow, for example, `seat_selection_checkout`, use the default workflow that comes with the storefront module as a basis, -and add a `seat_selected` step. +To create a new workflow, for example, `seat_selection_checkout`, use the default workflow that comes with the storefront module as a basis, and add a `seat_selected` step. ``` yaml hl_lines="3 15" [[= include_file('code_samples/front/shop/checkout/config/packages/checkout.yaml', 17, 19) =]] [[= include_file('code_samples/front/shop/checkout/config/packages/checkout.yaml', 38, 54) =]] ``` -Then, add a list of transitions. +Then, add a list of transitions. When defining a new transition, within its metadata, map the transition to its controller, and set other necessary details, such as the next step and label. ``` yaml hl_lines="2 12" @@ -68,9 +62,8 @@ In this case, you want users to select seats in the audience. In the `src/Controller/Checkout/Step` folder, create a file that resembles the following example. -The controller contains a Symfony form that collects user selections. -It can reuse fields and functions that come from the checkout component, for example, -after you check whether the form is valid, use the `AbstractStepController::advance` method to go to the next step of the process. +The controller contains a Symfony form that collects user selections. +It can reuse fields and functions that come from the checkout component, for example, after you check whether the form is valid, use the `AbstractStepController::advance` method to go to the next step of the process. ``` php hl_lines="23 24" [[= include_file('code_samples/front/shop/checkout/src/Controller/Checkout/Step/SelectSeatStepController.php') =]] @@ -103,7 +96,7 @@ In `assets/styles/checkout.css`, add styles required to properly display your te Remember to [add the new asset file to your Webpack configuration](assets.md#configure-assets). -### Select supported workflow +### Select supported workflow Next, you must inform the application that the configured workflow is used in your repository. @@ -112,14 +105,14 @@ You do it in repository configuration, under the `ibexa.repositories.: + : checkout: workflow: new_workflow ``` @@ -274,31 +265,31 @@ When you have multiple checkout workflows, you can specify which one to use by p ``` -With this setup, you can specify which workflow to use by clicking the button or link that starts the checkout. +With this setup, you can specify which workflow to use by clicking the button or link that starts the checkout. The argument passed determines which workflow is used, providing flexibility in workflow selection. -## Define custom Address Field Type formats +## Define custom Address field type formats -To create custom Address Field Type formats to be used in checkout, make the following changes in the project configuration files. +To create custom Address field type formats to be used in checkout, make the following changes in the project configuration files. First, define custom format configuration keys for `billing_address_format` and `shipping_address_format`: -``` yaml +``` yaml ibexa: repositories: : checkout: #"billing" by default - billing_address_format: - #"shipping" by default - shipping_address_format: + billing_address_format: + #"shipping" by default + shipping_address_format: #used in registration, uses given shipping/billing addresses to pre-populate address forms in select_address checkout step, "customer" by default - customer_content_type: + customer_content_type: ``` -Then, define custom address formats, which, for example, do not include the `locality` field: +Then, define custom address formats, which, for example, don't include the `locality` field: -``` yaml +``` yaml ibexa_field_type_address: formats: : @@ -309,7 +300,7 @@ ibexa_field_type_address: - postal_code - email - phone_number - + : country: default: diff --git a/docs/commerce/checkout/reorder.md b/docs/commerce/checkout/reorder.md index b9e3a96f00..9a03ec3d6a 100644 --- a/docs/commerce/checkout/reorder.md +++ b/docs/commerce/checkout/reorder.md @@ -43,7 +43,7 @@ Below, you can find a few examples that demonstrate how you can modify this feat ### Customize reorder You can modify workflow under the `framework.workflows` [configuration key](configuration.md#configuration-files). -Each workflow definition consists of a series of steps as well as a series of transitions between the steps. +Each workflow definition consists of a series of steps and a series of transitions between the steps. Below example shows how to set up `can_be_reordered` flag for specific order statuses. @@ -73,10 +73,10 @@ Reorder comes with the dedicated `Ibexa\Contracts\Checkout\Reorder\ReorderServic It contains helper methods and facades added over existing API to ease the order manipulation process. The following methods can be used to modify the reorder flow to fit your business needs: -#### `ReorderService:addToCartFromOrder` +#### `ReorderService:addToCartFromOrder` Allows you to add items from a previous order to a cart. -It uses historical data from previously ordered items even if they are no longer available. +It uses historical data from previously ordered items even if they're no longer available. Those items are validated against available stock. The method uses the following parameters: @@ -96,7 +96,7 @@ The method uses the following parameters: - `$sourceOrder` (OrderInterface) - the source order from which context is copied - `$targetCheckout` (CheckoutInterface) - the target checkout to which context is copied -#### `ReorderService:createReorderCart` +#### `ReorderService:createReorderCart` Creates a new shopping cart for reordering items from a past order in the same currency. The method uses the following parameters: diff --git a/docs/commerce/commerce.md b/docs/commerce/commerce.md index abd000ed13..7e087baf64 100644 --- a/docs/commerce/commerce.md +++ b/docs/commerce/commerce.md @@ -6,46 +6,46 @@ page_type: landing_page # Commerce -The commerce component of [[= product_name =]] covers various areas of managing an e-commerce presence: from configuring payment and shipping methods, through processing a transaction (listing available products, adding products to a cart, processing checkout and sending confirmation), all the way to order management. +The commerce component of [[= product_name =]] covers various areas of managing an e-commerce presence: from configuring payment and shipping methods, through processing a transaction (listing available products, adding products to a cart, processing checkout, and sending confirmation), all the way to order management. [[= cards([ -"commerce/cart/cart", -"commerce/checkout/checkout", -"commerce/order_management/order_management", -"commerce/payment/payment", -"commerce/shipping_management/shipping_management", -"commerce/storefront/storefront", -"commerce/transactional_emails/transactional_emails" + "commerce/cart/cart", + "commerce/checkout/checkout", + "commerce/order_management/order_management", + "commerce/payment/payment", + "commerce/shipping_management/shipping_management", + "commerce/storefront/storefront", + "commerce/transactional_emails/transactional_emails", ], columns=4) =]] ## Configure [[= cards([ -"commerce/checkout/configure_checkout", -"commerce/order_management/configure_order_management", -"commerce/payment/configure_payment", -"commerce/shipping_management/configure_shipment", -"commerce/storefront/configure_storefront" + "commerce/checkout/configure_checkout", + "commerce/order_management/configure_order_management", + "commerce/payment/configure_payment", + "commerce/shipping_management/configure_shipment", + "commerce/storefront/configure_storefront", ], columns=4) =]] ## Extend [[= cards([ -"commerce/checkout/customize_checkout", -"commerce/payment/extend_payment", -"commerce/shipping_management/extend_shipping", -"commerce/storefront/extend_storefront", -"commerce/transactional_emails/extend_transactional_emails" + "commerce/checkout/customize_checkout", + "commerce/payment/extend_payment", + "commerce/shipping_management/extend_shipping", + "commerce/storefront/extend_storefront", + "commerce/transactional_emails/extend_transactional_emails", ], columns=4) =]] ## Explore Commerce API [[= cards([ -"commerce/cart/cart_api", -"commerce/checkout/checkout_api", -"commerce/order_management/order_management_api", -"commerce/payment/payment_api", -"commerce/payment/payment_method_api", -"commerce/shipping_management/shipping_method_api", -"commerce/shipping_management/shipment_api" + "commerce/cart/cart_api", + "commerce/checkout/checkout_api", + "commerce/order_management/order_management_api", + "commerce/payment/payment_api", + "commerce/payment/payment_method_api", + "commerce/shipping_management/shipping_method_api", + "commerce/shipping_management/shipment_api", ], columns=4) =]] diff --git a/docs/commerce/order_management/configure_order_management.md b/docs/commerce/order_management/configure_order_management.md index 5ea1d87c64..1909d304f0 100644 --- a/docs/commerce/order_management/configure_order_management.md +++ b/docs/commerce/order_management/configure_order_management.md @@ -7,18 +7,18 @@ edition: commerce When you work with your Commerce implementation, you can modify and customize the order processing configuration. -!!! note "Permissions" +!!! note "Permissions" When you modify the workflow configuration, make sure you properly set user [permissions](permission_use_cases.md#commerce) for the Order management component. ## Configure order processing workflow Order processing workflow relies on a [Symfony Workflow]([[= symfony_doc =]]/components/workflow.html). -Each transition represents a separate order processing step. +Each transition represents a separate order processing step. ### Default order processing configuration -The default order processing workflow is called `ibexa_order`. +The default order processing workflow is called `ibexa_order`. To see the default workflow configuration, in your project directory, go to: `vendor/Ibexa/order-management/src/bundle/Resources/config/prepend.yaml`. The default workflow uses keys defined in `src/lib/Value/Status.php` file as place and transition names, for example, `PENDING_PLACE` translates into `pending`. @@ -27,8 +27,8 @@ You can replace the default workflow configuration with a custom one if needed. ### Custom order processing workflows -You define custom workflow implementations under the `framework.workflows` key. -If your installation supports multiple languages, for each place in the workflow, you can define a label that is pulled from a XLIFF file based on the [translation domain setting](back_office_translations.md). +You define custom workflow implementations under the `framework.workflows` key. +If your installation supports multiple languages, for each place in the workflow, you can define a label that is pulled from a XLIFF file based on the [translation domain setting](back_office_translations.md). You can also define colors that are used for status labels. To customize your configuration, place it under the `framework.workflows.` [configuration key](configuration.md#configuration-files): @@ -45,8 +45,7 @@ Then reference it with `ibexa.repositories..order_management.wo ### Define cancel order -You can define a status and transition in which the order can be canceled -by modifying workflow under the `framework.workflows` [configuration key](configuration.md#configuration-files). +You can define a status and transition in which the order can be canceled by modifying workflow under the `framework.workflows` [configuration key](configuration.md#configuration-files). ```yaml framework: @@ -61,5 +60,5 @@ framework: By default, the component integration mechanism reduces product stock values when an order is made (in status "pending") and reverts it to the original value when an order is cancelled. In your implementation, you may want the reduction/restoration of stock to happen at other stages of the order fulfillment process. -For this to happen, place the `reduce_stock: true` and/or `restore_stock: true` keys in other places of the workflow. +For this to happen, place the `reduce_stock: true` and/or `restore_stock: true` keys in other places of the workflow. Make sure that either of these keys is used only once. diff --git a/docs/commerce/order_management/order_management.md b/docs/commerce/order_management/order_management.md index b49dc30fbd..b43dc13654 100644 --- a/docs/commerce/order_management/order_management.md +++ b/docs/commerce/order_management/order_management.md @@ -5,7 +5,7 @@ edition: commerce # Order management -The order management component enables users to search for orders and filter search results. +The order management component enables users to search for orders and filter search results. Depending on their role, users can also track the status of their orders, review order details, and cancel orders. From the development perspective, the component enables customization of the order management workflow and integration with external systems to exchange order information. @@ -15,7 +15,6 @@ The component exposes the following: - [PHP API](order_management_api.md) that allows for managing orders - [REST API](../../api/rest_api/rest_api_reference/rest_api_reference.html#orders) that helps get order information over HTTP -### Order management service +### Order management service -The Order Management package provides the `Ibexa\Contracts\OrderManagement\OrderServiceInterface` service, -which is the entrypoint for calling the [backend API](order_management_api.md). +The Order Management package provides the `Ibexa\Contracts\OrderManagement\OrderServiceInterface` service, which is the entrypoint for calling the [backend API](order_management_api.md). diff --git a/docs/commerce/order_management/order_management_api.md b/docs/commerce/order_management/order_management_api.md index ae630397e7..57e2ff2dff 100644 --- a/docs/commerce/order_management/order_management_api.md +++ b/docs/commerce/order_management/order_management_api.md @@ -11,7 +11,7 @@ edition: commerce To get orders and manage them, use the `Ibexa\Contracts\OrderManagement\OrderServiceInterface` interface. -## Get single order +## Get single order ### Get single order by identifier @@ -31,7 +31,7 @@ To access a single order by using its numerical ID, use the `OrderService::getOr ## Get multiple orders -To fetch multiple orders, use the `OrderService::findOrders` method. +To fetch multiple orders, use the `OrderService::findOrders` method. It follows the same search query pattern as other APIs: ``` php @@ -43,8 +43,7 @@ It follows the same search query pattern as other APIs: ## Create order -To create an order, use the `OrderService::createOrder` method and provide -it with the `Ibexa\Contracts\OrderManagement\Value\OrderCreateStruct` object that contains a list of products, purchased quantities, product and total prices, as well as tax amounts. +To create an order, use the `OrderService::createOrder` method and provide it with the `Ibexa\Contracts\OrderManagement\Value\OrderCreateStruct` object that contains a list of products, purchased quantities, product, total prices, and tax amounts. ``` php [[= include_file('code_samples/api/commerce/src/Command/OrderCommand.php', 97, 108) =]] @@ -52,8 +51,8 @@ it with the `Ibexa\Contracts\OrderManagement\Value\OrderCreateStruct` object tha ## Update order -You can update the order after it is created. -You could do it to support a scenario when, for example, the order is processed manually and its status has to be changed in the system. +You can update the order after it's created. +You could do it to support a scenario when, for example, the order is processed manually and its status has to be changed in the system. To update order information, use the `OrderService::updateOrder` method: ``` php diff --git a/docs/commerce/payment/configure_payment.md b/docs/commerce/payment/configure_payment.md index df0b3b6f61..8cdca2e74f 100644 --- a/docs/commerce/payment/configure_payment.md +++ b/docs/commerce/payment/configure_payment.md @@ -7,14 +7,14 @@ edition: commerce When you work with your Commerce implementation, you can review and modify the payment configuration. -!!! note "Permissions" +!!! note "Permissions" When you modify the workflow configuration, make sure you properly set user [permissions](permission_use_cases.md#commerce) for the Payment component. ## Configure payment workflow Payment workflow relies on a [Symfony Workflow]([[= symfony_doc =]]/components/workflow.html). -Each transition represents a separate payment step. +Each transition represents a separate payment step. ### Default payment workflow configuration @@ -25,16 +25,16 @@ You can replace the default workflow configuration with a custom one if needed. ### Custom payment workflows -You define custom workflow implementations under the `framework.workflows` key. +You define custom workflow implementations under the `framework.workflows` key. They must support the `Ibexa\Contracts\Checkout\Value\CheckoutInterface`. -If your installation supports multiple languages, for each place in the workflow, you can define a label that is pulled from an XLIFF file based on the translation domain setting. +If your installation supports multiple languages, for each place in the workflow, you can define a label that is pulled from an XLIFF file based on the translation domain setting. You can also define colors that are used for status labels. The `primary_color` key defines a color of the font used for the label, while the `secondary_color` key defines a color of its background. -Additionally, you can decide whether users can manually transition between places. -You do this by setting a value for the `exposed` key. -If you set it to `true`, a button is displayed in the UI that triggers the transition. +Additionally, you can decide whether users can manually transition between places. +You do this by setting a value for the `exposed` key. +If you set it to `true`, a button is displayed in the UI that triggers the transition. Otherwise, the transition can only be triggered by means of the API. ``` yaml diff --git a/docs/commerce/payment/extend_payment.md b/docs/commerce/payment/extend_payment.md index 69d1407f0f..17ec29cf41 100644 --- a/docs/commerce/payment/extend_payment.md +++ b/docs/commerce/payment/extend_payment.md @@ -5,9 +5,10 @@ edition: commerce # Extend Payment -There are different ways you can extend your Payment module implementation. -One of them is to create a custom payment method type. -The other is attaching custom data to a payment. +You can extend your Payment module implementation: + +- by creating a custom payment method type +- by attaching custom data to a payment You can also [customize the payment processing workflow](configure_payment.md#custom-payment-workflows). @@ -18,7 +19,7 @@ Code samples below show how this could be done if your organization wants to use !!! note "Gateway integration requirement" - [[= product_name =]] does not come with gateway redirects. Whether you are an integrator or an end customer, it is your responsibility to implement payment gateway integration. + [[= product_name =]] doesn't come with gateway redirects. Whether you're an integrator or an end customer, it's your responsibility to implement payment gateway integration. ### Define custom payment method type @@ -66,7 +67,7 @@ Then, register `OptionsFormMapper` a service: ### Create options validator -You might want to make sure that data provided by the user is validated. +You might want to make sure that data provided by the user is validated. To do that, create an options validator that checks user input against the constraints and dispatches an error when needed. ``` php diff --git a/docs/commerce/payment/payment.md b/docs/commerce/payment/payment.md index 269ae27d96..4ea3b52057 100644 --- a/docs/commerce/payment/payment.md +++ b/docs/commerce/payment/payment.md @@ -1,12 +1,12 @@ --- -description: The payment component covers defining and managing payment methods as well as managing payments and their lifecycle. +description: The payment component covers defining and managing payment methods, together with managing payments and their lifecycle. edition: commerce --- # Payment With the Payment component users can define and manage payment methods, create and manage payments, search for payment methods and payments, and filter payment search results. -Depending on their role, users can also enable or disable payment methods, modify payment information, as well as cancel payments. +Depending on their role, users can also enable or disable payment methods, modify payment information, and cancel payments. Available payment method types: diff --git a/docs/commerce/payment/payment_api.md b/docs/commerce/payment/payment_api.md index 0909cf85c1..4c5c90c414 100644 --- a/docs/commerce/payment/payment_api.md +++ b/docs/commerce/payment/payment_api.md @@ -7,10 +7,10 @@ edition: commerce To get payments and manage them, use the `Ibexa\Contracts\Payment\PaymentServiceInterface` interface. -By default, UUID is used to generate payment identifiers. +By default, UUID is used to generate payment identifiers. You can change that by providing a custom payment identifier in `Ibexa\Contracts\Payment\Payment\PaymentCreateStruct` or `Ibexa\Contracts\Payment\Payment\PaymentUpdateStruct`. -## Get single payment +## Get single payment ### Get single payment by ID @@ -30,7 +30,7 @@ To access a single payment by using its string identifier, use the `PaymentServi ## Get multiple payments -To fetch multiple payments, use the `PaymentServiceInterface::findPayments` method. +To fetch multiple payments, use the `PaymentServiceInterface::findPayments` method. It follows the same search query pattern as other APIs: ``` php @@ -39,8 +39,7 @@ It follows the same search query pattern as other APIs: ## Create payment -To create a payment, use the `PaymentServiceInterface::createPayment` method and provide it with -the `Ibexa\Contracts\Payment\Payment\PaymentCreateStruct` object that takes the following arguments: `method`, `order` and `amount`. +To create a payment, use the `PaymentServiceInterface::createPayment` method and provide it with the `Ibexa\Contracts\Payment\Payment\PaymentCreateStruct` object that takes the following arguments: `method`, `order` and `amount`. ``` php [[= include_file('code_samples/api/commerce/src/Command/PaymentCommand.php', 94, 94) =]] @@ -49,8 +48,8 @@ the `Ibexa\Contracts\Payment\Payment\PaymentCreateStruct` object that takes the ## Update payment -You can update payment information after the payment is created. -You could do it to support a scenario when, for example, an online payment failed, has been processed by using other means, and its status has to be updated in the system. +You can update payment information after the payment is created. +You could do it to support a scenario when, for example, an online payment failed, has been processed by using other means, and its status has to be updated in the system. The `Ibexa\Contracts\Payment\Payment\PaymentUpdateStruct` object takes the following arguments: `transition`, `identifier`, and `context`. To update payment information, use the `PaymentServiceInterface::updatePayment` method: @@ -61,6 +60,7 @@ To update payment information, use the `PaymentServiceInterface::updatePayment` ## Delete payment To delete a payment from the system, use the `PaymentServiceInterface::deletePayment` method: + ``` php [[= include_file('code_samples/api/commerce/src/Command/PaymentCommand.php', 114, 115) =]] ``` diff --git a/docs/commerce/payment/payment_method_api.md b/docs/commerce/payment/payment_method_api.md index 4364438c24..1edd74c98e 100644 --- a/docs/commerce/payment/payment_method_api.md +++ b/docs/commerce/payment/payment_method_api.md @@ -8,10 +8,10 @@ edition: commerce !!! tip "Order management REST API" To learn how to manage payment methods with the REST API, see the [REST API reference](../../api/rest_api/rest_api_reference/rest_api_reference.html#payment-methods). - + To get payment methods and manage them, use the `Ibexa\Contracts\Payment\PaymentMethodServiceInterface` interface. -From the developer's perspective, payment methods are referenced with identifiers defined manually at method creation stage in user interface. +From the developer's perspective, payment methods are referenced with identifiers defined manually at method creation stage in user interface. !!! note "Support for multilingual applications" @@ -39,7 +39,8 @@ To access a single payment method by using its numerical ID, use the `PaymentMet ## Get multiple payment methods -To fetch multiple payment methods, use the `PaymentMethodService::findPaymentMethods` method. +To fetch multiple payment methods, use the `PaymentMethodService::findPaymentMethods` method. + It follows the same search query pattern as other APIs: ``` php @@ -48,9 +49,14 @@ It follows the same search query pattern as other APIs: ## Create payment method -To create a payment method, use the `PaymentMethodService::createPaymentMethod` method and provide it with -an `Ibexa\Contracts\Payment\PaymentMethod\PaymentMethodCreateStruct` object that takes the following parameters: -`identifier` string, `type` TypeInterface object, `names` array of string values, `descriptions` array of string values, `enabled` boolean value, and an `options` object. +To create a payment method, use the `PaymentMethodService::createPaymentMethod` method and provide it with an `Ibexa\Contracts\Payment\PaymentMethod\PaymentMethodCreateStruct` object that takes the following parameters: + +- `identifier` string +- `type` TypeInterface object +- `names` array of string values +- `descriptions` array of string values +- `enabled` boolean value +- `options` object. ``` php [[= include_file('code_samples/api/commerce/src/Command/PaymentMethodCommand.php', 58, 59) =]][[= include_file('code_samples/api/commerce/src/Command/PaymentMethodCommand.php', 77, 87) =]] @@ -58,8 +64,9 @@ an `Ibexa\Contracts\Payment\PaymentMethod\PaymentMethodCreateStruct` object that ## Update payment method -You can update the payment method after it is created. +You can update the payment method after it's created. An `Ibexa\Contracts\Payment\PaymentMethod\PaymentMethodUpdateStruct` object can take the following arguments: `identifier` string, `names` array of string values, `descriptions` array of string values, `enabled` boolean value, and an `options` object. + To update payment method information, use the `PaymentMethodServiceInterface::updatePaymentMethod` method: ``` php @@ -76,6 +83,7 @@ To delete a payment method from the system, use the `PaymentMethodService::delet ## Check whether payment method is used To check whether a payment method is used, for example, before you delete it, use the `PaymentMethodService::isPaymentMethodUsed` method: + ``` php [[= include_file('code_samples/api/commerce/src/Command/PaymentMethodCommand.php', 109, 122) =]] ``` \ No newline at end of file diff --git a/docs/commerce/payment/payment_method_filtering.md b/docs/commerce/payment/payment_method_filtering.md index 0458e6b9ac..b26cf1903e 100644 --- a/docs/commerce/payment/payment_method_filtering.md +++ b/docs/commerce/payment/payment_method_filtering.md @@ -10,8 +10,8 @@ To allow this filtering, you need to create a custom payment method type and reg ## Create custom payment method type -There are different ways you can extend your Payment module implementation. -One of them is to [create a custom payment method type](extend_payment.md). +You can extend your Payment module implementation in different ways. +One of them is to [create a custom payment method type](extend_payment.md). The following example shows, how to create `New Payment Method Type`. diff --git a/docs/commerce/payment/payum_integration.md b/docs/commerce/payment/payum_integration.md index c6fd3fa5e3..07eeb2c09e 100644 --- a/docs/commerce/payment/payum_integration.md +++ b/docs/commerce/payment/payum_integration.md @@ -27,7 +27,9 @@ payum: ## Workflow mapping In [[= product_name =]], the default payment workflow has certain places, such as `pending`, `failed`, `paid`, or `cancelled`, and their corresponding transitions. -However, for your application to use other transitions and places, for example, `authorized`, `notified`, `refunded` etc., and to present them in the user interface, you need to: + +However, for your application to use other transitions and places, for example, `authorized`, `notified`, or `refunded`, and to present them in the user interface, you need to: + - override the default payment workflow - create a custom workflow and enable it by using semantic configuration @@ -75,5 +77,5 @@ For a list of events, see [Event dispatcher](https://github.com/Payum/Payum/blob !!! caution In certain cases, depending on the payment processing service, when a customer closes the payment page in a browser and the bank has not processed the payment yet, the payment status can remain unchanged. - Depending on how your checkout process is configured, it may result in unwanted effects, for example, cause that the cart does not purge after the purchase. + Depending on how your checkout process is configured, it may result in unwanted effects, for example, cause that the cart doesn't purge after the purchase. Make sure that you account for this fact in your implementation. diff --git a/docs/commerce/shipping_management/configure_shipment.md b/docs/commerce/shipping_management/configure_shipment.md index f6e13aa85f..14b9f71dd6 100644 --- a/docs/commerce/shipping_management/configure_shipment.md +++ b/docs/commerce/shipping_management/configure_shipment.md @@ -5,17 +5,16 @@ edition: commerce # Configure shipping -When you work with your Commerce implementation, you can review and modify -the shipping configuration. +When you work with your Commerce implementation, you can review and modify the shipping configuration. -!!! note "Permissions" +!!! note "Permissions" When you modify the workflow configuration, make sure you properly set user [permissions](permission_use_cases.md#commerce) for the shipping component. ## Configure shipment workflow Shipment workflow relies on a [Symfony Workflow]([[= symfony_doc =]]/components/workflow.html). -Each transition represents a separate shipment step. +Each transition represents a separate shipment step. The default fallback workflow is `ibexa_shipment`, which is prepended at bundle level. @@ -23,11 +22,11 @@ The default fallback workflow is `ibexa_shipment`, which is prepended at bundle The default payment workflow configuration is called `ibexa_shipment`, you can replace it with your custom workflow identifier if needed. -o see the default workflow, in your project directory, navigate to the following file: `vendor/Ibexa/shipping/src/bundle/Resources/config/workflow.yaml`. +To see the default workflow, in your project directory, navigate to the following file: `vendor/Ibexa/shipping/src/bundle/Resources/config/workflow.yaml`. ### Custom shipment workflows -You define custom workflow implementations under the `framework.workflows` [configuration key](configuration.md#configuration-files). +You define custom workflow implementations under the `framework.workflows` [configuration key](configuration.md#configuration-files). The `shipping.shipment_workflow` parameter is repository-aware. To customize your configuration, place it under the `framework.workflows.` [configuration key](configuration.md#configuration-files): diff --git a/docs/commerce/shipping_management/extend_shipping.md b/docs/commerce/shipping_management/extend_shipping.md index aa690df237..8da9d82183 100644 --- a/docs/commerce/shipping_management/extend_shipping.md +++ b/docs/commerce/shipping_management/extend_shipping.md @@ -5,7 +5,8 @@ edition: commerce # Extend shipping -There are different ways in which you can extend or customize your Shipping module implementation. +You can extend or customize your Shipping module implementation in different ways. + Here, you can learn about the following ideas to make your Commerce solution more powerful: - create a custom shipping method type @@ -16,12 +17,12 @@ You can also [customize the shipment processing workflow](configure_shipment.md# ## Create custom shipping method type -If your application needs shipping methods of other type than the default ones, you can create custom shipping method types. +If your application needs shipping methods of other type than the default ones, you can create custom shipping method types. See the code samples below to learn how to do it. - + ### Define custom shipping method type class -Create a definition of the shipping method type. +Create a definition of the shipping method type. Use a built-in type factory to define the class in `config/services.yaml`: ``` yaml @@ -34,7 +35,7 @@ At this point a custom shipping method type should be visible on the **Create sh ### Create options form -To let users create shipping methods of a custom type within the user interface, you need a Symfony form type. +To let users create shipping methods of a custom type within the user interface, you need a Symfony form type. Create a `src/ShippingMethodType/Form/Type/CustomShippingMethodOptionsType.php` file with a form type. Next, define a name of the custom shipping method type in the file, by using the `getTranslationMessages` method. @@ -61,11 +62,12 @@ At this point you should be able to create a shipping method based on a custom s !!! note - To use this example, you must have regions. If you don't have regions, refer to [Enable purchasing products](enable_purchasing_products.md) for instructions on how to add them. + To use this example, you must have regions. + If you don't have regions, refer to [Enable purchasing products](enable_purchasing_products.md) for instructions on how to add them. ### Create options validator -You might want to validate the data provided by the user against certain constraints. +You might want to validate the data provided by the user against certain constraints. Here, you create an options validator class that checks whether the user provided the `customer_identifier` value and dispatches an error when needed. Use the type factory to define a compound validator class in `config/services.yaml`: @@ -107,7 +109,7 @@ Then, register the storage converter as a service: [[= include_file('code_samples/front/shop/shipping/config/services.yaml', 0, 1) =]][[= include_file('code_samples/front/shop/shipping/config/services.yaml', 25, 28) =]] ``` -#### Storage definition +#### Storage definition Now, create a storage definition class and a corresponding schema. The table stores information specific for the custom shipping method type. @@ -118,7 +120,7 @@ The table stores information specific for the custom shipping method type. `CREATE TABLE ibexa_shipping_method_region_custom(id int auto_increment primary key, customer_id text, shipping_method_region_id int);` -Create a `src/ShippingMethodType/Storage/StorageDefinition.php` file with a storage definition: +Create a `src/ShippingMethodType/Storage/StorageDefinition.php` file with a storage definition: ``` php [[= include_file('code_samples/front/shop/shipping/src/ShippingMethodType/Storage/StorageDefinition.php') =]] @@ -152,7 +154,7 @@ Register the voter as a service: [[= include_file('code_samples/front/shop/shipping/config/services.yaml', 0, 1) =]][[= include_file('code_samples/front/shop/shipping/config/services.yaml', 31, 34) =]] ``` -## Display shipping method parameters in details view +## Display shipping method parameters in details view You can extend the default shipping method details view by making shipping method visible on the **Cost** tab. To do this, create a `src/ShippingMethodType/Cost/CustomCostFormatter.php` file with a formatter class: @@ -173,5 +175,5 @@ You should now see the parameter, in this case it's a customer identifier, displ !!! note "Non-matching label" - This section does not discuss overriding the default form, therefore the alphanumerical customer identifier is shown under the **Cost value** label. + This section doesn't discuss overriding the default form, therefore the alphanumerical customer identifier is shown under the **Cost value** label. For more information about working with forms, see [Page and Form tutorial](../../tutorials/page_and_form_tutorial/5_create_newsletter_form.md). diff --git a/docs/commerce/shipping_management/shipment_api.md b/docs/commerce/shipping_management/shipment_api.md index 49d92c893e..961826a2d8 100644 --- a/docs/commerce/shipping_management/shipment_api.md +++ b/docs/commerce/shipping_management/shipment_api.md @@ -9,7 +9,7 @@ To get shipments and manage them, use the `Ibexa\Contracts\Shipping\ShipmentServ From the developer's perspective, shipments are referenced with a UUID identifier. -## Get single shipment +## Get single shipment ### Get single shipment by identifier @@ -29,7 +29,7 @@ To access a single shipment by using its numerical id, use the `ShipmentService: ## Get multiple shipments -To fetch multiple shipments, use the `ShipmentService::findShipments` method. +To fetch multiple shipments, use the `ShipmentService::findShipments` method. It follows the same search query pattern as other APIs: ``` php @@ -38,8 +38,7 @@ It follows the same search query pattern as other APIs: ## Create shipment -To create a shipment, use the `ShipmentService::createShipment` method and provide it with -an `Ibexa\Contracts\Shipping\Value\ShipmentCreateStruct` object that takes two parameters, a `shippingMethod` string and a `Money` object. +To create a shipment, use the `ShipmentService::createShipment` method and provide it with an `Ibexa\Contracts\Shipping\Value\ShipmentCreateStruct` object that takes two parameters, a `shippingMethod` string and a `Money` object. ``` php [[= include_file('code_samples/api/commerce/src/Command/ShipmentCommand.php', 101, 115) =]] @@ -47,8 +46,8 @@ an `Ibexa\Contracts\Shipping\Value\ShipmentCreateStruct` object that takes two p ## Update shipment -You can update the shipment after it is created. -You could do it to support a scenario when, for example, the shipment is processed offline and its status has to be updated in the system. +You can update the shipment after it's created. +You could do it to support a scenario when, for example, the shipment is processed offline and its status has to be updated in the system. To update shipment information, use the `ShipmentService::updateShipment` method: ``` php diff --git a/docs/commerce/shipping_management/shipping_management.md b/docs/commerce/shipping_management/shipping_management.md index 611efe3c54..07e785ab38 100644 --- a/docs/commerce/shipping_management/shipping_management.md +++ b/docs/commerce/shipping_management/shipping_management.md @@ -1,11 +1,11 @@ --- -description: The shipping component covers defining and managing shipping methods as well as managing shipments and their lifecycle. +description: The shipping component covers defining and managing shipping methods, together with managing shipments and their lifecycle. edition: commerce --- # Shipping -The shipping component enables users to define and manage shipping methods of different types, as well as create and manage shipments, search for shipments and filter search results. +The shipping component enables users to define and manage shipping methods of different types, create and manage shipments, search for shipments, and filter search results. Depending on their role, users can also enable or disable shipping methods, change status of shipments, and cancel shipments. !!! note "Shipping method types" diff --git a/docs/commerce/shipping_management/shipping_method_api.md b/docs/commerce/shipping_management/shipping_method_api.md index ed387a19a3..b276ddcf84 100644 --- a/docs/commerce/shipping_management/shipping_method_api.md +++ b/docs/commerce/shipping_management/shipping_method_api.md @@ -7,7 +7,7 @@ edition: commerce To get shipping methods and manage them, use the `Ibexa\Contracts\Shipping\ShippingMethodServiceInterface` interface. -Shipping methods are referenced with identifiers defined manually at method creation stage in user interface. +Shipping methods are referenced with identifiers defined manually at method creation stage in user interface. ## Get shipping method @@ -31,7 +31,7 @@ The method takes a string as `$id` parameter and uses a prioritized language fro ## Get multiple shipping methods -To fetch multiple shipping methods, use the `ShippingMethodServiceInterface::getShippingMethod` method. +To fetch multiple shipping methods, use the `ShippingMethodServiceInterface::getShippingMethod` method. It follows the same search query pattern as other APIs: ``` php diff --git a/docs/commerce/storefront/configure_storefront.md b/docs/commerce/storefront/configure_storefront.md index 802646b7d0..e291ad6ea8 100644 --- a/docs/commerce/storefront/configure_storefront.md +++ b/docs/commerce/storefront/configure_storefront.md @@ -8,9 +8,9 @@ The Storefront is accessible under the `/product-catalog`. ## Catalog configuration -With the `ibexa/storefront` package, you can configure the product catalog and make it available to your shop users. +With the `ibexa/storefront` package, you can configure the product catalog and make it available to your shop users. -Before you start configuring the Storefront, make sure you have created, configured and published [catalogs](https://doc.ibexa.co/projects/userguide/en/latest/pim/work_with_catalogs/#create-catalogs) in the Back Office. +Before you start configuring the Storefront, make sure you have created, configured, and published [catalogs](https://doc.ibexa.co/projects/userguide/en/latest/pim/work_with_catalogs/#create-catalogs) in the back office. The configuration is available under the `ibexa.system..storefront.catalog` [configuration key](configuration.md#configuration-files). It accepts the following values: @@ -96,7 +96,7 @@ ibexa: site_group: user_settings_groups: - location - - custom_group + - custom_group ``` By default, only the `location` user settings is provided: @@ -106,4 +106,3 @@ By default, only the `location` user settings is provided: - Short date and time format - Long date and time format - Language - diff --git a/docs/commerce/storefront/extend_storefront.md b/docs/commerce/storefront/extend_storefront.md index 980e51de1d..8b4ca37b6c 100644 --- a/docs/commerce/storefront/extend_storefront.md +++ b/docs/commerce/storefront/extend_storefront.md @@ -11,9 +11,9 @@ With the `ibexa\storefront` package come the following built-in menus: | Item | Value | Description | |------------|----------|---------| -| [Breadcrumbs](#breadcrumbs-menu)| - | Renders breadcrumbs for Content Tree Root, Taxonomy Entry, Product, User settings and User settings group | -| [Taxonomy](#taxonomy-menu)| - | It can render a menu for product categories or tags | -| Currency| `currency_menu` | Renders a menu to change the active currency | +| [Breadcrumbs](#breadcrumbs-menu)| - | Renders breadcrumbs for content tree root, Taxonomy Entry, product, user settings, and user settings group | +| [Taxonomy](#taxonomy-menu)| - | It can render a menu for product categories or tags | +| Currency| `currency_menu` | Renders a menu to change the active currency | | Language| `language_menu` | Renders a menu to change the active language | | Region | `region_menu` | Renders a menu to change the active region | @@ -56,8 +56,8 @@ See the usage example: ```html+twig {% set categories_menu = knp_menu_get( - 'ibexa_storefront.menu.taxonomy', - [], + 'ibexa_storefront.menu.taxonomy', + [], { parent: category, depth: 3 diff --git a/docs/commerce/storefront/storefront.md b/docs/commerce/storefront/storefront.md index 1500ce6261..5eac432f3e 100644 --- a/docs/commerce/storefront/storefront.md +++ b/docs/commerce/storefront/storefront.md @@ -6,8 +6,7 @@ edition: commerce # Storefront The Storefront package provides a starting kit for the developers. -It is a set of components that serves as a basis, which developers can -customize and extend to create their own implementation of a web store. +It's a set of components that serves as a basis, which developers can customize and extend to create their own implementation of a web store. ## Default UI components @@ -26,9 +25,9 @@ You can modify them when you build your own web store. | Mini cart widget | Consists of a counter that displays a total number of items added to a cart. | |Orders list|Displays a list of orders with such information as status, date, value, order ID. | | Product category page | Displays products that belong to a specific category. | -| Product filters component | Allows for narrowing the list of products displayed in the listing by using different filters, such as product type, availability and price. | +| Product filters component | Allows for narrowing the list of products displayed in the listing by using different filters, such as product type, availability, and price. | | Product listing page | Allows for browsing through products, displays product name, code, price, and image. | -| Region menu | Enables selecting between regions, to dynamically change the contents of the product listing page. | +| Region menu | Enables selecting between regions, to dynamically change the contents of the product listing page. | | Reorder |Allows logged-in users to repurchase previously bought items. | |Searching and filtering of orders| Allows logged-in users to search and filter their past orders on the orders page.| | Search for specific product component | Allows for searching for products, for example on the product listing page. | diff --git a/docs/commerce/transactional_emails/extend_transactional_emails.md b/docs/commerce/transactional_emails/extend_transactional_emails.md index 52f5ac954b..665ed1cb9a 100644 --- a/docs/commerce/transactional_emails/extend_transactional_emails.md +++ b/docs/commerce/transactional_emails/extend_transactional_emails.md @@ -28,13 +28,13 @@ framework: ## Define additional variables [[= product_name =]] comes with a predefined [set of variables](transactional_emails_parameters.md) that you can use when building a template for your transactional email campaign at Actito. -If this list is not sufficient, you can use Events to include additional variables: +If this list isn't sufficient, you can use Events to include additional variables: ```php contentService->loadVersionInfo($contentInfo, 2); `loadRelationList` provides an iterable [`RelationList`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-RelationList.html) object listing [`Relation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Relation.html) objects. `Relation` has two main properties: `destinationContentInfo`, and `sourceContentInfo`. -It also holds the [relation type](content_relations.md), -and the optional Field this relation is made with. +It also holds the [relation type](content_relations.md), and the optional field this relation is made with. ### Owning user @@ -130,14 +120,11 @@ You can use the `getOwner` method of the `ContentInfo` object to load the conten [[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 109, 110) =]] ``` -To get the creator of the current version and not the content item's owner, -you need to use the `creatorId` property from the current version's `VersionInfo` object. +To get the creator of the current version and not the content item's owner, you need to use the `creatorId` property from the current version's `VersionInfo` object. ### Section -You can find the Section to which a content item belongs through -the [`getSection`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentInfo.html#method_getSection) method -of the ContentInfo object: +You can find the section to which a content item belongs through the [`getSection`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentInfo.html#method_getSection) method of the ContentInfo object: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 112, 113) =]] @@ -145,23 +132,22 @@ of the ContentInfo object: !!! note - Note that requesting Section data may be impossible for an anonymous user. + Requesting section data may be impossible for an anonymous user. Make sure to [authenticate](php_api.md#setting-the-repository-user) as a user with sufficient permissions. ### Object states -You can retrieve [Object states](object_states.md) of a content item -using [`ObjectStateService::getContentState`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_getContentState). -You need to provide it with the Object state group. -All Object state groups can be retrieved through [`loadObjectStateGroups`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_loadObjectStateGroups). +You can retrieve [object states](object_states.md) of a content item using [`ObjectStateService::getContentState`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_getContentState). +You need to provide it with the object state group. +All object state groups can be retrieved through [`loadObjectStateGroups`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_loadObjectStateGroups). ``` php [[= include_file('code_samples/api/public_php_api/src/Command/ViewContentMetaDataCommand.php', 115, 120) =]] ``` -## Viewing content with Fields +## Viewing content with fields -To retrieve the Fields of the selected content item, you can use the following command: +To retrieve the fields of the selected content item, you can use the following command: ```php hl_lines="13-14 16-22" [[= include_file('code_samples/api/public_php_api/src/Command/ViewContentCommand.php', 4, 7) =]] // ... @@ -172,12 +158,12 @@ To retrieve the Fields of the selected content item, you can use the following c Line 9 shows how [`ContentService::loadContent`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html#method_loadContent) loads the content item provided to the command. Line 14 makes use of the [`ContentTypeService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentTypeService.html) to retrieve the content type of the requested item. -Lines 12-19 iterate over Fields defined by the content type. -For each Field they print out its identifier, and then using [`FieldTypeService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-FieldTypeService.html) retrieve the Field's value and print it out to the console. +Lines 12-19 iterate over fields defined by the content type. +For each field they print out its identifier, and then using [`FieldTypeService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-FieldTypeService.html) retrieve the field's value and print it out to the console. ## Viewing content in different languages -The Repository is SiteAccess-aware, so languages defined by the SiteAccess are automatically taken into account when loading content. +The repository is SiteAccess-aware, so languages defined by the SiteAccess are automatically taken into account when loading content. To load a specific language, provide its language code when loading the content item: @@ -193,8 +179,7 @@ $contentService->loadContent($content->id, Language::ALL); ## Getting all content in a subtree -To go through all the content items contained in a subtree, -you need to use the [`LocationService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html). +To go through all the content items contained in a subtree, you need to use the [`LocationService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html). ``` php hl_lines="5 15" [[= include_file('code_samples/api/public_php_api/src/Command/BrowseLocationsCommand.php', 30, 49) =]] @@ -202,41 +187,38 @@ you need to use the [`LocationService`](../../api/php_api/php_api_reference/clas `loadLocation` (line 15) returns a value object, here a `Location`. -[`LocationService::loadLocationChildren`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_loadLocationChildren) (line 5) -returns a [`LocationList`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-LocationList.html) value object that you can iterate over. +[`LocationService::loadLocationChildren`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_loadLocationChildren) (line 5) returns a [`LocationList`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-LocationList.html) value object that you can iterate over. !!! note Refer to [Searching](search_api.md) for information on more complex search queries. -## Getting parent Location +## Getting parent location -To get the parent Location of content, you first need to determine which Location is the main one, -in case the content item has multiple Locations. +To get the parent location of content, you first need to determine which location is the main one, in case the content item has multiple locations. You can do it through the `getMainLocation` method of the ContentInfo object. -Next, use the `getParentLocation` method of the Location object to access the parent Location: +Next, use the `getParentLocation` method of the location object to access the parent location: ``` php $mainLocation = $contentInfo->getMainLocation(); $output->writeln("Parent Location: " . $mainLocation->getParentLocation()->pathString); ``` -## Getting content from a Location +## Getting content from a location -When dealing with Location objects (and Trash objects), you can get access to content item directly using `$location->getContent`. +When dealing with location objects (and Trash objects), you can get access to content item directly using `$location->getContent`. In Twig this can also be accessed by `location.content`. - -This is a lazy property. It will trigger loading of content when first used. -In case of bulk of Locations coming from Search or Location Service, -the Content will also be loaded in bulk for the whole Location result set. +This is a lazy property. +It triggers loading of content when first used. +In case of bulk of locations coming from Search or location Service, the content is also loaded in bulk for the whole location result set. ## Comparing content versions You can compare two versions of a content item using the `VersionComparisonService`. The versions must have the same language. -For example, to get the comparison between the `name` Field of two versions: +For example, to get the comparison between the `name` field of two versions: ```php $versionFrom = $this->contentService->loadVersionInfo($contentInfo, $versionFromId); @@ -245,8 +227,7 @@ $versionTo = $this->contentService->loadVersionInfo($contentInfo, $versionToId); $nameComparison = $this->comparisonService->compare($versionFrom, $versionTo)->getFieldValueDiffByIdentifier('name')->getComparisonResult(); ``` -`getComparisonResult` returns a `ComparisonResult` object, which depends on the Field Type being compared. -In the example of a Text Line (ezstring) Field, it is an array of `StringDiff` objects. +`getComparisonResult` returns a `ComparisonResult` object, which depends on the field type being compared. +In the example of a Text Line (ezstring) field, it's an array of `StringDiff` objects. -Each diff contains a section of the Field to compare (e.g. a part of a text line) -and its status, which can be "unchanged", "added" or "removed". +Each diff contains a section of the field to compare (for example, a part of a text line) and its status, which can be "unchanged", "added" or "removed". diff --git a/docs/content_management/content_api/creating_content.md b/docs/content_management/content_api/creating_content.md index 825096fe11..ce3f920b6c 100644 --- a/docs/content_management/content_api/creating_content.md +++ b/docs/content_management/content_api/creating_content.md @@ -6,7 +6,7 @@ description: Create, publish, update and translate content items by using the PH !!! note - Creating most objects will be impossible for an anonymous user. + Creating most objects is impossible for an anonymous user. Make sure to [authenticate](php_api.md#setting-the-repository-user) as a user with sufficient permissions. !!! tip "Content REST API" @@ -25,40 +25,39 @@ returns a new [`ContentCreateStruct`](../../api/php_api/php_api_reference/classe ``` This command creates a draft using [`ContentService::createContent`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html#method_createContent) (line 7). -This method must receive a `ContentCreateStruct` and an array of Location structs. +This method must receive a `ContentCreateStruct` and an array of location structs. `ContentCreateStruct` (which extends `ContentStruct`) is created through [`ContentService::newContentCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html#method_newContentCreateStruct) (line 2), which receives the content type and the primary language for the content item. For information about translating a content item into other languages, see [Translating content](#translating-content). -[`ContentStruct::setField`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentStruct.html#method_setField) (line 3) enables you to define the Field values. -When the Field accepts a simple value, you can provide it directly, as in the example above. -For some Field Types, for example [images](#creating-an-image), you need to provide an instance of a Value type. +[`ContentStruct::setField`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentStruct.html#method_setField) (line 3) enables you to define the field values. +When the field accepts a simple value, you can provide it directly, as in the example above. +For some field types, for example [images](#creating-an-image), you need to provide an instance of a Value type. ### Creating an image -Image Field Type requires an instance of its Value type, which you must provide to the [`ContentStruct::setField`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentStruct.html#method_setField) method. -Therefore, when creating a content item of the Image type (or any other content type with an `image` Field Type), +Image field type requires an instance of its Value type, which you must provide to the [`ContentStruct::setField`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentStruct.html#method_setField) method. +Therefore, when creating a content item of the Image type (or any other content type with an `image` field type), the `ContentCreateStruct` is slightly more complex than in the previous example: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/CreateImageCommand.php', 56, 69) =]] ``` -Value of the Image Field Type contains the path to the image file, as well as other basic information -based on the input file. +Value of the Image field type contains the path to the image file and other basic information based on the input file. ### Creating content with RichText -The RichText Field accepts values in a custom flavor of [Docbook](https://github.com/docbook/wiki/wiki) format. -For example, to add a simple RichText paragraph, provide the following as input: +The RichText field accepts values in a custom flavor of [Docbook](https://github.com/docbook/wiki/wiki) format. +For example, to add a RichText paragraph, provide the following as input: ``` xml
Description of your content item.
``` To learn more about the format and how it represents different elements of rich text, see -[RichText Field Type reference](richtextfield.md#custom-docbook-format). +[RichText field type reference](richtextfield.md#custom-docbook-format). ## Publishing a draft diff --git a/docs/content_management/content_api/managing_content.md b/docs/content_management/content_api/managing_content.md index 97daad2a6a..e7be659c7b 100644 --- a/docs/content_management/content_api/managing_content.md +++ b/docs/content_management/content_api/managing_content.md @@ -1,87 +1,75 @@ --- -description: PHP API enables managing content Locations, content types, as well as content in Trash and Calendar events. +description: PHP API enables managing content Locations, content types, content in Trash, and Calendar events. --- # Managing content ## Locations -You can manage [Locations](locations.md) that hold content -using [`LocationService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html). +You can manage [locations](locations.md) that hold content using [`LocationService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html). !!! tip "Location REST API" - To learn how to manage Locations using the REST API, see [REST API reference](../../api/rest_api/rest_api_reference/rest_api_reference.html#managing-content-create-new-location-for-content-item). + To learn how to manage locations using the REST API, see [REST API reference](../../api/rest_api/rest_api_reference/rest_api_reference.html#managing-content-create-new-location-for-content-item). -### Adding a new Location to a content item +### Adding a new location to a content item -Every published content item must have at least one Location. -One content item can have more that one Location, which means it is presented in more than one place -in the content tree. +Every published content item must have at least one location. +One content item can have more that one location, which means it's presented in more than one place in the content tree. -Creating a new Location, like creating content, requires using a struct, -because a Location value object is read-only. +Creating a new location, like creating content, requires using a struct, because a location value object is read-only. -To add a new Location to existing content you need to create -a [`LocationCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-LocationCreateStruct.html) -and pass it to the [`LocationService::createLocation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_createLocation) method: +To add a new location to existing content you need to create a [`LocationCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-LocationCreateStruct.html) and pass it to the [`LocationService::createLocation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_createLocation) method: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/AddLocationToContentCommand.php', 50, 51) =]] [[= include_file('code_samples/api/public_php_api/src/Command/AddLocationToContentCommand.php', 55, 57) =]] ``` -`LocationCreateStruct` must receive the parent Location ID. -It sets the `parentLocationId` property of the new Location. +`LocationCreateStruct` must receive the parent location ID. +It sets the `parentLocationId` property of the new location. -You can also provide other properties for the Location, otherwise they will be set to their defaults: +You can also provide other properties for the location, otherwise they're set to their defaults: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/AddLocationToContentCommand.php', 52, 54) =]] ``` -### Changing the main Location +### Changing the main location -When a content item has more that one Location, one Location is always considered the main one. -You can change the main Location using [`ContentService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html), -by updating the `ContentInfo` with a [`ContentUpdateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentUpdateStruct.html) -that sets the new main Location: +When a content item has more that one location, one location is always considered the main one. +You can change the main location using [`ContentService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ContentService.html), by updating the `ContentInfo` with a [`ContentUpdateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentUpdateStruct.html) that sets the new main location: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/SetMainLocationCommand.php', 48, 52) =]] ``` -### Hiding and revealing Locations +### Hiding and revealing locations -To hide or reveal (unhide) a Location you need to make use of -[`LocationService::hideLocation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_hideLocation) -or [`LocationService::unhideLocation`:](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_unhideLocation) +To hide or reveal (unhide) a location you need to make use of [`LocationService::hideLocation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_hideLocation) or [`LocationService::unhideLocation`:](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_unhideLocation) ``` php [[= include_file('code_samples/api/public_php_api/src/Command/HideLocationCommand.php', 46, 47) =]][[= include_file('code_samples/api/public_php_api/src/Command/HideLocationCommand.php', 49, 50) =]] ``` -See [Location visibility](locations.md#location-visibility) for detailed information -on the behavior of visible and hidden Locations. +See [location visibility](locations.md#location-visibility) for detailed information on the behavior of visible and hidden Locations. -### Deleting a Location +### Deleting a location -You can remove a Location either by deleting it, or sending it to Trash. +You can remove a location either by deleting it, or sending it to Trash. Deleting makes use of [`LocationService::deleteLocation()`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_deleteLocation). -It permanently deletes the Location, together with its whole subtree. +It permanently deletes the location, together with its whole subtree. -Content which has only this one Location will be permanently deleted as well. -Content which has more Locations will be still available in its other Locations. -If you delete the [main Location](#changing-the-main-location) of a content item that has more Locations, -another Location will become the main one. +Content which has only this one location is permanently deleted as well. +Content which has more locations is still available in its other locations. +If you delete the [main location](#changing-the-main-location) of a content item that has more locations, another location becomes the main one. ``` php [[= include_file('code_samples/api/public_php_api/src/Command/DeleteContentCommand.php', 44, 45) =]] ``` -To send the Location and its subtree to Trash, -use [`TrashService::trash`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-TrashService.html#). +To send the location and its subtree to Trash, use [`TrashService::trash`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-TrashService.html#). Items in Trash can be later [restored, or deleted permanently](#trash). ``` php @@ -90,24 +78,22 @@ Items in Trash can be later [restored, or deleted permanently](#trash). ### Moving and copying a subtree -You can move a Location with its whole subtree using [`LocationService::moveSubtree`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_moveSubtree): +You can move a location with its whole subtree using [`LocationService::moveSubtree`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_moveSubtree): ``` php [[= include_file('code_samples/api/public_php_api/src/Command/MoveContentCommand.php', 46, 49) =]] ``` -[`LocationService::copySubtree`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_copySubtree) is used in the same way, -but it copies the Location and its subtree instead of moving it. +[`LocationService::copySubtree`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LocationService.html#method_copySubtree) is used in the same way, but it copies the location and its subtree instead of moving it. !!! tip - To copy a subtree you can also make use of the built-in `copy-subtree` command: - `bin/console ibexa:copy-subtree `. + To copy a subtree you can also make use of the built-in `copy-subtree` command: `bin/console ibexa:copy-subtree `. !!! note - [Copy subtree limit](back_office_configuration.md#copy-subtree-limit) only applies to operations in the Back Office. - It is ignored when copying subtrees using the PHP API. + [Copy subtree limit](back_office_configuration.md#copy-subtree-limit) only applies to operations in the back office. + It's ignored when copying subtrees using the PHP API. ## Trash @@ -115,26 +101,25 @@ but it copies the Location and its subtree instead of moving it. To learn how to manage Trash using the REST API, see [REST API reference](../../api/rest_api/rest_api_reference/rest_api_reference.html#managing-content-list-trash-items). -To empty the Trash (remove all Locations in Trash), use [`TrashService::emptyTrash`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-TrashService.html#method_emptyTrash), -which takes no arguments. +To empty the Trash (remove all locations in Trash), use [`TrashService::emptyTrash`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-TrashService.html#method_emptyTrash), which takes no arguments. You can recover an item from Trash using [`TrashService::recover`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-TrashService.html#method_recover). You must provide the method with the ID of the object in Trash. -Trash Location is identical to the origin Location of the object. +Trash location is identical to the origin location of the object. ``` php [[= include_file('code_samples/api/public_php_api/src/Command/TrashContentCommand.php', 64, 65) =]] ``` -The content item will be restored under its previous Location. -You can also provide a different Location to restore in as a second argument: +The content item is restored under its previous location. +You can also provide a different location to restore in as a second argument: ``` php $newParent = $this->locationService->loadLocation($location); $this->trashService->recover($trashItem, $newParent); ``` -You can also search through Trash items and sort the results using several public PHP API search criteria and sort clauses that have been exposed for `TrashService` queries. +You can also search through Trash items and sort the results using several public PHP API Search Criteria and Sort Clauses that have been exposed for `TrashService` queries. For more information, see [Searching in trash](search_api.md#searching-in-trash). ## Content types @@ -150,13 +135,13 @@ To operate on content types, you need to make use of [`ContentTypeService`](../. Adding a new content type, like creating content, must happen with the use of a struct, because a content type value object is read-only. In this case you use [`ContentTypeCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-ContentTypeCreateStruct.html). -A content type must have at least one name, in the main language, and at least one Field definition. +A content type must have at least one name, in the main language, and at least one field definition. ``` php [[= include_file('code_samples/api/public_php_api/src/Command/CreateContentTypeCommand.php', 59, 69) =]][[= include_file('code_samples/api/public_php_api/src/Command/CreateContentTypeCommand.php', 76, 85) =]] ``` -You can specify more details of the Field definition in the create struct, for example: +You can specify more details of the field definition in the create struct, for example: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/CreateContentTypeCommand.php', 67, 77) =]] @@ -170,8 +155,7 @@ To copy a content type, use [`ContentTypeService::copyContentType`](../../api/ph [[= include_file('code_samples/api/public_php_api/src/Command/CreateContentTypeCommand.php', 89, 90) =]] ``` -The copy will automatically be given an identifier based on the original content type identifier -and the copy's ID, for example: `copy_of_folder_21`. +The copy is automatically getting an identifier based on the original content type identifier and the copy's ID, for example: `copy_of_folder_21`. To change the identifier of the copy, use a [`ContentTypeUpdateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-ContentTypeUpdateStruct.html): @@ -196,14 +180,13 @@ You need to provide the method with an EventQuery, which takes a date range and [[= include_file('code_samples/api/public_php_api/src/Command/CalendarCommand.php', 39, 50) =]] ``` -You can also get the first and last event in the list by using the `first()` and `last()` methods of an `EventCollection` (`Ibexa\Contracts\Calendar\EventCollection`) respectively: +You can also get the first and last event in the list by using the `first()` and `last()` methods of an `EventCollection` (`Ibexa\Contracts\Calendar\EventCollection`): ``` php [[= include_file('code_samples/api/public_php_api/src/Command/CalendarCommand.php', 51, 53) =]] ``` -You can process the events in a collection using the `find(Closure $predicate)`, `filter(Closure $predicate)`, -`map(Closure $callback)` or `slice(int $offset, ?int $length = null)` methods of `EventCollection`, for example: +You can process the events in a collection using the `find(Closure $predicate)`, `filter(Closure $predicate)`, `map(Closure $callback)` or `slice(int $offset, ?int $length = null)` methods of `EventCollection`, for example: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/CalendarCommand.php', 54, 57) =]] @@ -211,9 +194,9 @@ You can process the events in a collection using the `find(Closure $predicate)`, ### Performing calendar actions -You can perform a calendar action (e.g. reschedule or unschedule calendar events) using the `CalendarServiceInterface::executeAction()` method. +You can perform a calendar action (for example, reschedule or unschedule calendar events) using the `CalendarServiceInterface::executeAction()` method. You must pass an `Ibexa\Contracts\Calendar\EventAction\EventActionContext` instance as argument. -`EventActionContext` defines events on which the action is performed, as well as action-specific parameters e.g. a new date: +`EventActionContext` defines events on which the action is performed, and action-specific parameters, for example, a new date: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/CalendarCommand.php', 59, 61) =]] diff --git a/docs/content_management/content_availability.md b/docs/content_management/content_availability.md index 3377d61242..9b3ac0ebe4 100644 --- a/docs/content_management/content_availability.md +++ b/docs/content_management/content_availability.md @@ -7,19 +7,19 @@ description: Control the availability of content items with relation to translat The Default content availability flag enables you to control whether content is available when its translation is missing. You can set the flag in content type definition by checking the "Make content available even with missing translations" option. -It is automatically applied to any new content item of this Type. +It's automatically applied to any new content item of this Type. ![Default content availability](availability_flag.png "Default content availability") -A content item with this flag will be available in its main language -even if it is not translated into the language of the current SiteAccess. +A content item with this flag is available in its main language +even if it's not translated into the language of the current SiteAccess. -Without the flag, a content item will not be available at all if it does not have a language version +Without the flag, a content item isn't available at all if it doesn't have a language version corresponding to the current SiteAccess. !!! note - There is currently no way in the Back Office to edit the Content availability flag + There is currently no way in the back office to edit the Content availability flag for an already published content item. To do this via [PHP API](creating_content.md#updating-content), set the [`alwaysAvailable` property](../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentMetadataUpdateStruct.html#property_alwaysAvailable) of the Content metadata. @@ -33,5 +33,5 @@ For example, you can assign the flag to a Blog content type which is intended to in multiple languages. If the Blog is in English only, it would not be visible for readers using the Norwegian or German SiteAcceses. However, if you set the default availability flag for the Blog content type, -it will be displayed to them in English (if it is set as a main language) and will enable the users to browse individual +it's displayed to them in English (if it's set as a main language) and enables the users to browse individual posts in other languages. diff --git a/docs/content_management/content_management.md b/docs/content_management/content_management.md index eddb961b85..d83dda3271 100644 --- a/docs/content_management/content_management.md +++ b/docs/content_management/content_management.md @@ -1,5 +1,5 @@ --- -description: Manage content in Ibexa DXP by learning about the content model, Field Types, pages, forms, workflows, and so on. +description: Manage content in Ibexa DXP by learning about the content model, field types, pages, forms, workflows, and more. page_type: landing_page --- diff --git a/docs/content_management/content_management_api/bookmark_api.md b/docs/content_management/content_management_api/bookmark_api.md index 7411ed8d09..b9c7ef8382 100644 --- a/docs/content_management/content_management_api/bookmark_api.md +++ b/docs/content_management/content_management_api/bookmark_api.md @@ -1,11 +1,10 @@ --- -description: You can use the PHP API to view the bookmark list, as well as add and remove content from it. +description: You can use the PHP API to view the bookmark list, and add or remove content from it. --- # Bookmark API -[`BookmarkService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-BookmarkService.html) -enables you to read, add and remove bookmarks from content. +[`BookmarkService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-BookmarkService.html) enables you to read, add and remove bookmarks from content. !!! tip "Bookmark REST API" @@ -17,14 +16,13 @@ To view a list of all bookmarks, use [`BookmarkService::loadBookmarks`](../../ap [[= include_file('code_samples/api/public_php_api/src/Command/BookmarkCommand.php', 43, 50) =]] ``` -You can add a bookmark to a content item by providing its Location object -to the [`BookmarkService::createBookmark`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-BookmarkService.html#method_createBookmark) method: +You can add a bookmark to a content item by providing its Location object to the [`BookmarkService::createBookmark`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-BookmarkService.html#method_createBookmark) method: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/BookmarkCommand.php', 37, 40) =]] ``` -You can remove a bookmark from a Location with [`BookmarkService::deleteBookmark`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-BookmarkService.html#method_deleteBookmark): +You can remove a bookmark from a location with [`BookmarkService::deleteBookmark`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-BookmarkService.html#method_deleteBookmark): ``` php [[= include_file('code_samples/api/public_php_api/src/Command/BookmarkCommand.php', 52, 53) =]] diff --git a/docs/content_management/content_management_api/object_state_api.md b/docs/content_management/content_management_api/object_state_api.md index 28d0a73b0a..9adc830692 100644 --- a/docs/content_management/content_management_api/object_state_api.md +++ b/docs/content_management/content_management_api/object_state_api.md @@ -1,53 +1,46 @@ --- -description: You can manage Object states via the PHP API, including creating Object states and state groups and assigning them to content items. +description: You can manage object states via the PHP API, including creating object states and state groups and assigning them to content items. --- # Object state API [Object states](object_states.md) enable you to set a custom state to any content. -States are grouped into Object state groups. +States are grouped into object state groups. You can manage Object states by using the PHP API by using `ObjectStateService`. !!! tip "Object state REST API" - To learn how to manage Object states using the REST API, see [REST API reference](../../api/rest_api/rest_api_reference/rest_api_reference.html#managing-content-get-object-states-of-content-item). + To learn how to manage object states using the REST API, see [REST API reference](../../api/rest_api/rest_api_reference/rest_api_reference.html#managing-content-get-object-states-of-content-item). -## Getting Object state information +## Getting object state information -You can use the [`ObjectStateService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html) -to get information about Object state groups or Object states. +You can use the [`ObjectStateService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html) to get information about object state groups or object states. ``` php [[= include_file('code_samples/api/public_php_api/src/Command/ObjectStateCommand.php', 48, 53) =]] ``` -## Creating Object states +## Creating object states -To create an Object state group and add Object states to it, -you need to make use of the [`ObjectStateService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html): +To create an object state group and add object states to it, you need to make use of the [`ObjectStateService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html): ``` php [[= include_file('code_samples/api/public_php_api/src/Command/ObjectStateCommand.php', 57, 61) =]] ``` -[`ObjectStateService::createObjectStateGroup`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_createObjectStateGroup) -takes as argument an [`ObjectStateGroupCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ObjectState-ObjectStateGroupCreateStruct.html), -in which you need to specify the identifier, default language and at least one name for the group. +[`ObjectStateService::createObjectStateGroup`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_createObjectStateGroup) takes as argument an [`ObjectStateGroupCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ObjectState-ObjectStateGroupCreateStruct.html), in which you need to specify the identifier, default language and at least one name for the group. -To create an Object state inside a group, -use [`ObjectStateService::newObjectStateCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_newObjectStateCreateStruct) -and provide it with an `ObjectStateCreateStruct`: +To create an object state inside a group, use [`ObjectStateService::newObjectStateCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_newObjectStateCreateStruct) and provide it with an `ObjectStateCreateStruct`: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/ObjectStateCommand.php', 63, 67) =]] ``` -## Assigning Object state +## Assigning object state -To assign an Object state to a content item, -use [`ObjectStateService::setContentState`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_setContentState). -Provide it with a `ContentInfo` object of the content item, the Object state group and the Object state: +To assign an object state to a content item, use [`ObjectStateService::setContentState`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-ObjectStateService.html#method_setContentState). +Provide it with a `ContentInfo` object of the content item, the object state group and the object state: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/ObjectStateCommand.php', 77, 82) =]] diff --git a/docs/content_management/content_management_api/section_api.md b/docs/content_management/content_management_api/section_api.md index 4bdc917f1a..186415297c 100644 --- a/docs/content_management/content_management_api/section_api.md +++ b/docs/content_management/content_management_api/section_api.md @@ -1,53 +1,49 @@ --- -description: PHP API enables you to create Sections, assign content to them as well as get various information about the Section. +description: PHP API enables you to create sections, assign content to them, and get various information about the section. --- # Section API -[Sections](sections.md) enable you to divide content into groups -which can later be used, for example, as basis for permissions. +[Sections](sections.md) enable you to divide content into groups which can later be used, for example, as basis for permissions. -You can manage Sections by using the PHP API by using `SectionService`. +You can manage sections by using the PHP API by using `SectionService`. !!! tip "Section REST API" - To learn how to manage Sections using the REST API, see [REST API reference](../../api/rest_api/rest_api_reference/rest_api_reference.html#managing-content-get-sections). + To learn how to manage sections using the REST API, see [REST API reference](../../api/rest_api/rest_api_reference/rest_api_reference.html#managing-content-get-sections). -## Creating Sections +## Creating sections -To create a new Section, you need to make use of the [`SectionCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-SectionCreateStruct.html) -and pass it to the [`SectionService::createSection`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SectionService.html#method_createSection) method: +To create a new section, you need to make use of the [`SectionCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-SectionCreateStruct.html) and pass it to the [`SectionService::createSection`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SectionService.html#method_createSection) method: -``` php +``` php [[= include_file('code_samples/api/public_php_api/src/Command/SectionCommand.php', 58, 62) =]] ``` -## Getting Section information +## Getting section information -You can use `SectionService` to retrieve Section information such as whether it is in use: +You can use `SectionService` to retrieve section information such as whether it's in use: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/SectionCommand.php', 76, 81) =]] ``` -## Listing content in a Section +## Listing content in a section -To list content items assigned to a Section you need to make a [query](search_api.md) -for content belonging to this section, by applying the [`SearchService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SearchService.html). +To list content items assigned to a section you need to make a [query](search_api.md) for content belonging to this section, by applying the [`SearchService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SearchService.html). You can also use the query to get the total number of assigned content items: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/SectionCommand.php', 69, 75) =]][[= include_file('code_samples/api/public_php_api/src/Command/SectionCommand.php', 82, 86) =]] ``` -## Assigning Section to content +## Assigning section to content -To assign content to a Section, use the [`SectionService::assignSection`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SectionService.html#method_assignSection) method. -You need to provide it with the `ContentInfo` object of the content item, -and the [`Section`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Section.html) object: +To assign content to a section, use the [`SectionService::assignSection`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SectionService.html#method_assignSection) method. +You need to provide it with the `ContentInfo` object of the content item, and the [`Section`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Section.html) object: ``` php [[= include_file('code_samples/api/public_php_api/src/Command/SectionCommand.php', 64, 67) =]] ``` -Note that assigning a Section to content does not automatically assign it to the content item's children. +Assigning a section to content doesn't automatically assign it to the content item's children. diff --git a/docs/content_management/content_management_guide.md b/docs/content_management/content_management_guide.md index b6385a05a5..a938d6d48f 100644 --- a/docs/content_management/content_management_guide.md +++ b/docs/content_management/content_management_guide.md @@ -8,9 +8,8 @@ description: Read the content management product guide and learn how to create, The term “content management” covers all the tasks that you need to perform to create, edit and present content to its intended audience. -The content management model applied in [[= product_name =]] lies at the foundation of the entire system. -A system that relies on roles and permissions controls access to content items and is granular and powerful enough to be used in managing user accounts, -corporate accounts, products, or process definitions. +The content management model applied in [[= product_name =]] lies at the foundation of the entire system. +A system that relies on roles and permissions controls access to content items and is granular and powerful enough to be used in managing user accounts, corporate accounts, products, or process definitions. ## Availability @@ -26,91 +25,86 @@ Content management capabilities are available in all [[= product_name =]] editio - articles or posts - products - forms -- media (images, videos, etc.) +- media (for example, images or videos) - user accounts -You can set up content structure, define the templates to be filled with content, and assign different areas of the structure to your editors. +You can set up content structure, define the templates to be filled with content, and assign different areas of the structure to your editors. Next steps would be to create the actual content, and then classify content items, and organize them as necessary. You can then publish the content directly, by building a website or a web store, or by using external systems together with a [headless CMS](https://developers.ibexa.co/headless-cms) that relies on the [[= product_name =]] technology. ## Content structure -All content in [[= product_name =]] is organized hierarchically, into what is called a [**Content Tree**](content_tree.md). +All content in [[= product_name =]] is organized hierarchically, into what is called a [**content tree**](content_tree.md). This tree-like structure repeats throughout the system, and applies to content, taxonomies, categories, and the like. -Traditional as the structure may look, with relations and multiple location support, -a single content item can be referenced by another content item and accessed from different places of the tree, -which allows you to build complex architectures with multiple locales and output channels. +Traditional as the structure may look, with relations and multiple location support, a single content item can be referenced by another content item and accessed from different places of the tree, which allows you to build complex architectures with multiple locales and output channels. ![Content structure in a Content Browser](img/content_tree.png) ## Content model -A structure of elements that *store* content information is referred to as the **content model**. -[[= product_name =]] comes with a predefined content model that includes a broad set of various Field Types and several content types. +A structure of elements that *store* content information is referred to as the **content model**. +[[= product_name =]] comes with a predefined content model that includes a broad set of various field types and several content types. -You can customize and adapt the content model to your organization's needs and the type of output channel that you use. -If need be, development teams can [create new Field Types](creating_a_point2d_field_type.md), to enhance editor and visitor experiences. -Content managers or even editors can then apply such Field Types when they modify existing or create new content types. +You can customize and adapt the content model to your organization's needs and the type of output channel that you use. +If need be, development teams can [create new field types](creating_a_point2d_field_type.md), to enhance editor and visitor experiences. +Content managers or even editors can then apply such field types when they modify existing or create new content types. The editing interface lets all users, including those with no coding experience, create or modify certain areas of the content model. For technical details, see [a Content model](content_model.md#content-model). -### Field Types +### Field types -[Field Types](field_types.md) are the smallest elements of the content model’s structure. -[[= product_name =]] comes with many built-in Field Types that cover most common needs, -for example, Text line, RichText, Integer, Measurement, Map location, etc. +[Field types](field_types.md) are the smallest elements of the content model’s structure. +[[= product_name =]] comes with many built-in field types that cover most common needs, for example, Text line, RichText, Integer, Measurement, or Map location. Their role is to: - store data - validate input data - make the data searchable -- display Fields of a given Field Type +- display fields of a given field type -For a complete list of available Field Types, see [Field Type reference](field_type_reference.md). +For a complete list of available field types, see [field type reference](field_type_reference.md). -![Field Types and Fields](img/field_types.png) +![Field types and fields](img/field_types.png) ### Fields -Once you use a Field Type to design and build a content type definition, and define its settings, it becomes a Field. +Once you use a field type to design and build a content type definition, and define its settings, it becomes a field. -Fields can be as simple as Name, based on a Text line Field Type, or as complex as Page, -based on a Landing Page Field Type, with multiple options to set and choose from: +Fields can be as simple as Name, based on a Text line field type, or as complex as page, based on a landing page field type, with multiple options to set and choose from: -![Landing Page Field settings](img/fields.png) +![Landing page field settings](img/fields.png) ### Content types -Life gets easier when you have templates to fill in with content. Content types are such templates, which editors use to create content items. -Content types define what Fields are available in the content item. +Life gets easier when you have templates to fill in with content. Content types are such templates, which editors use to create content items. +Content types define what fields are available in the content item. -[[= product_name =]] comes with several basic content types, and creating new ones, editing, -and deleting them is done by using a visual interface, with no coding skills needed. +[[= product_name =]] comes with several basic content types, and creating new ones, editing, and deleting them is done by using a visual interface, with no coding skills needed. ![Content types vs. content items](img/content_types.png) ### Content items -Content items are pieces of content, such as, for example, products, articles, blog posts, or media. -In [[= product_name =]], everything is a content item — not just pages, articles or products, but also all media (images, videos, etc.) or even User accounts. +Content items are pieces of content, such as, for example, products, articles, blog posts, or media. +In [[= product_name =]], everything is a content item — not only pages, articles or products, but also all media (for example, images or videos) or even user accounts. -Each content item, apart from its name and identifier, contains a composition of Fields, which differs depending on the type of content. -For example, articles might have a title, an author, a body, and an image, while products may have a name, category, price, size, color, etc. +Each content item, apart from its name and identifier, contains a composition of fields, which differs depending on the type of content. +For example, articles might have for example, a title, an author, a body, and an image, while products may have, for example, a name, category, price, size, or color. ### Forms -Forms could be seen as a special kind of content items, because their role is to gather information from website users and not present it. -You create them from basic form fields available in [[= product_name =]]. +Forms could be seen as a special kind of content items, because their role is to gather information from website users and not present it. +You create them from basic form fields available in [[= product_name =]]. By adding forms to the website, you can increase the website’s functionality and improve user experience. Certain editions of [[= product_name =]] come with a visual [Form Builder]([[= user_doc =]]/content_management/work_with_forms/). ## Content management capabilities -Each content item has at least one location within the Content Tree, and can have several versions and multiple translations. +Each content item has at least one location within the content tree, and can have several versions and multiple translations. It can also have related assets, such as images or other media, and assigned keywords, or tags. You can use these characteristics in combination with system features to create the most comprehensive and functional digital presence for your organization. @@ -119,21 +113,21 @@ You can use these characteristics in combination with system features to create #### Locations -When a content item is created and published, it is assigned a place in the Content Tree, designated by a Location ID. -A single content item can have more than one Location ID, which means that the same content can be found on different branches of the tree. +When a content item is created and published, it's assigned a place in the content tree, designated by a location ID. +A single content item can have more than one location ID, which means that the same content can be found on different branches of the tree. However, a single location can have only one content item assigned to it. ![Locations](img/locations.png) Locations can be used to control the availability of content items to end users: -you can [hide specific locations]([[= user_doc =]]/content_management/content_organization/manage_locations_urls/#hide-locations) of a content item, while others remain available. +you can [hide specific locations]([[= user_doc =]]/content_management/content_organization/manage_locations_urls/#hide-locations) of a content item, while others remain available. By [swapping locations]([[= user_doc =]]/content_management/content_organization/manage_locations_urls/#swap-locations), you can immediately replace an obsolete version of a content item with an updated one. #### Versions -Content items can have several [versions]([[= user_doc =]]/content_management/content_versions/). -By default, there are three version statuses available: draft, published, and archived. -Before they are published, drafts can be routed between different user roles for review and approval. +Content items can have several [versions]([[= user_doc =]]/content_management/content_versions/). +By default, there are three version statuses available: draft, published, and archived. +Before they're published, drafts can be routed between different user roles for review and approval. ![Versions](img/versions.png) @@ -141,7 +135,7 @@ Editors can [compare different content item versions]([[= user_doc =]]/content_m #### Translations -Content items can have more than one [translation]([[= user_doc =]]/content_management/translate_content/). +Content items can have more than one [translation]([[= user_doc =]]/content_management/translate_content/). If a website has different fronts, for different locales, and different language versions of content exist, [[= product_name =]] serves the one that matches the locale. ![Translations](img/translations.png) @@ -150,18 +144,18 @@ Editors can compare different translations of the same content items with the Co #### Relations -A [relation](content_relations.md) can exist between any two content items in the Content Tree. -For example, blog posts featured in the website's main page are in a relation with the page that they are embedded in. -Or, instead of direct attachments, an article can use images that are separate content items outside the article and are referenced through a relation. +A [relation](content_relations.md) can exist between any two content items in the content tree. +For example, blog posts featured in the website's main page are in a relation with the page that they're embedded in. +Or, instead of direct attachments, an article can use images that are separate content items outside the article, and are referenced through a relation. ## Content arrangement -In [[= product_name =]], content items can be moved and copied between branches of the Content Tree. -These operations, like in your computer’s file system, can apply both to individual content items as well as folders or groups. +In [[= product_name =]], content items can be moved and copied between branches of the content tree. +These operations, like in your computer’s file system, can apply both to individual content items and folders or groups. ![Content organization operations](img/content_arrangement.png) -Content items can be hidden when necessary, for example, until a certain event, like a Holiday Sale or Board announcement comes. Hidden content items are not visible to website visitors and are greyed out in the Content Tree. +Content items can be hidden when necessary, for example, until a certain event, like a Holiday Sale, or Board announcement comes. Hidden content items aren't visible to website visitors and are greyed out in the content tree. ![Hidden content item](img/hidden_content_item.png) @@ -175,81 +169,79 @@ There are multiple tools within [[= product_name =]] that help content managers ### Taxonomy -With taxonomy you can create tags or keywords within a tree structure and assign them to content items. +With taxonomy you can create tags or keywords within a tree structure and assign them to content items. This way you can classify content and make it easier for end users to find the content they need, or browse and view content from a category that suits them best. ![Taxonomy principles](img/taxonomy.png) ### Access control -When your [[= product_name =]] instance has multiple contributors and visitors, administrators can give them access to different areas of the website and different capabilities. -It is done by creating Roles, with each role having a different set of [permissions](permission_overview.md), the most fitting example being the `content/edit` permission limited to an `Articles/BookReviews/Historical` subtree of the Content Tree. +When your [[= product_name =]] instance has multiple contributors and visitors, administrators can give them access to different areas of the website and different capabilities. +It's done by creating roles, with each role having a different set of [permissions](permission_overview.md), the most fitting example being the `content/edit` permission limited to an `Articles/BookReviews/Historical` subtree of the content tree. -In the next steps, after you create User groups, you’d assign Roles to these groups, and add individual users to each of such groups. +In the next steps, after you create user groups, you’d assign roles to these groups, and add individual users to each of such groups. For more technical information about permissions and limitations, see [Permission use cases](permission_use_cases.md). There are, however, mechanisms to control access to content with even more convenience. ### Sections -You can divide your Content Tree into nominal parts to better organize it. -Once you have defined sections, for example, Media or Forms, and assigned them to content items, -you can decide which Roles have access to which Section of the tree. +You can divide your content tree into nominal parts to better organize it. +Once you have defined sections, for example, Media or Forms, and assigned them to content items, you can decide which roles have access to which section of the tree. -The setting is inherited, which means that a child content item inherits a value of this setting from its parent. -Changing a Section setting does not result in moving a content item to a different location within a Content Tree. +The setting is inherited, which means that a child content item inherits a value of this setting from its parent. +Changing a section setting doesn't result in moving a content item to a different location within a content tree. ![Members of the Media Section](img/sections.png) ### Object states -While reviewing the details of each individual content item in your Content Tree, you can assign a state to it, for example, “Locked” or “Not locked”. -Then you can set a permission that allows or denies users access to content items in a specific state. -This setting is not inherited. +While reviewing the details of each individual content item in your content tree, you can assign a state to it, for example, “Locked” or “Not locked”. +Then you can set a permission that allows or denies users access to content items in a specific state. +This setting isn't inherited. ![Object states in content item’s Details](img/object_states.png) ### User segments -Although segments are not meant to classify content, they could fall into this category, because their role is about targeting users, and not controlling their access to content. -With segments, you can reach specific groups, or categories, of visitors with specific information about content or products that could be of their interest. +Although segments aren't meant to classify content, they could fall into this category, because their role is about targeting users, and not controlling their access to content. +With segments, you can reach specific groups, or categories, of visitors with specific information about content or products that could be of their interest. For example, you can build Pages that contain different recommendations, depending on who is visiting them. -![A Segment Group with two user segments](img/user_segments.png) +![A segment group with two user segments](img/user_segments.png) ## How to get started -Once you have integrated the headless implementation, installed a local instance of [[= product_name =]] or set up an instance on [[= product_name_cloud =]], you are ready to employ the content management features to good use. +Once you have integrated the headless implementation, installed a local instance of [[= product_name =]] or set up an instance on [[= product_name_cloud =]], you're ready to employ the content management features to good use. Since content management is an ongoing process, and, in your implementation, you might prefer focusing on other areas of configuration, the order of operations below is by all means conventional. **1\. Create a content model** -Any content that you might want to deliver to a viewer can be structured and split into smaller elements. +Any content that you might want to deliver to a viewer can be structured and split into smaller elements. Reverse-engineer the intended concepts into individual fields, which can be categorized, and then picked from categories and combined into content items. -Reuse existing Fields Types or [customize them to fit your needs](create_custom_generic_field_type.md), then [create content types]([[= user_doc =]]/content_management/create_edit_content_items/). +Reuse existing fields types or [customize them to fit your needs](create_custom_generic_field_type.md), then [create content types]([[= user_doc =]]/content_management/create_edit_content_items/). **2\. Define permissions** -Although this step is not directly related to content management, -it is a good time to [set up user roles and permissions]([[= user_doc =]]/permission_management/work_with_permissions/), which users would need to work with content. +Although this step isn't directly related to content management, it's a good time to [set up user roles and permissions]([[= user_doc =]]/permission_management/work_with_permissions/), which users would need to work with content. **3\. Author content** -[Create various content items]([[= user_doc =]]/content_management/create_edit_content_items/), such as pages, articles, forms, or media. While you fill Fields with content, several actions are there to help you with your task. +[Create various content items]([[= user_doc =]]/content_management/create_edit_content_items/), such as pages, articles, forms, or media. While you fill fields with content, several actions are there to help you with your task. You can pause and resume the work, preview the results, or send content for review. ![Send to review](img/send_to_review.png) **4\. Publish** -Again, this is not part of content management, but at this point you can [publish]([[= user_doc =]]/content_management/publish_instantly/) it right away or [schedule content for publication]([[= user_doc =]]/content_management/schedule_publishing/). +Again, this isn't part of content management, but at this point you can [publish]([[= user_doc =]]/content_management/publish_instantly/) it right away or [schedule content for publication]([[= user_doc =]]/content_management/schedule_publishing/). **5\. Organize content** -Organize the content of your website by copying or moving content items, [controlling Locations and URL addresses]([[= user_doc =]]/content_management/content_organization/manage_locations_urls/). -Then work with Tags, Sections and Object States to [classify]([[= user_doc =]]/content_management/content_organization/classify_content/#sections) it. +Organize the content of your website by copying or moving content items, [controlling Locations and URL addresses]([[= user_doc =]]/content_management/content_organization/manage_locations_urls/). +Then work with Tags, sections and object states to [classify]([[= user_doc =]]/content_management/content_organization/classify_content/#sections) it. ## Benefits @@ -267,21 +259,15 @@ The most important benefits of using Content management capabilities of [[= prod ### Corporate website -The most common use case for a comprehensive content management system like [[= product_name =]] would be creating and maintaining a multinational company’s digital presence, -with both public and intranet channels, multiple websites with overlapping content structures, -and business partners and end-customers alike wanting to connect through different channels to access public and classified content. +The most common use case for a comprehensive content management system like [[= product_name =]] would be creating and maintaining a multinational company’s digital presence, with both public and intranet channels, multiple websites with overlapping content structures, and business partners and end-customers alike wanting to connect through different channels to access public and classified content. ### B2C web store Content management could lie at a foundation of a successful global web store, where customers connect through localized websites and branded mobile apps: -individual products can have multiple variants with differing related assets, -product descriptions must be available in multiple language versions, -and access to certain areas of the store depends on both a country and a segment that the customer comes from. +individual products can have multiple variants with differing related assets, product descriptions must be available in multiple language versions, and access to certain areas of the store depends on both a country and a segment that the customer comes from. ### B2B store -Extensive content management capabilities would prove themselves in a setting, -where multiple buyers from different partner companies connect to an industry leader’s trading website, -and they expect to find well organized SKU catalogs that contain basic product information. -From there they would like to access detailed specifications, white papers and application notes. +Extensive content management capabilities would prove themselves in a setting, where multiple buyers from different partner companies connect to an industry leader’s trading website, and they expect to find well organized SKU catalogs that contain basic product information. +From there they would like to access detailed specifications, white papers and application notes. The same products could come with different brands and at different price points, depending on the customer segment or origin. diff --git a/docs/content_management/content_model.md b/docs/content_management/content_model.md index 3839989436..5eb8ec661c 100644 --- a/docs/content_management/content_model.md +++ b/docs/content_management/content_model.md @@ -1,5 +1,5 @@ --- -description: Ibexa DXP's content model relies on content items that are instances of content types and contain content Fields. +description: Ibexa DXP's content model relies on content items that are instances of content types and contain content fields. --- # Content model @@ -7,12 +7,12 @@ description: Ibexa DXP's content model relies on content items that are instance ## Content model overview The content structure in [[= product_name =]] is based on content items. -A content item represents a single piece of content: an article, a blog post, an image, a product, etc. +A content item represents a single piece of content, for example, an article, a blog post, an image, or a product. Each content item is an instance of a content type. !!! tip - An introduction to the content model for non-developer users is available in [[[= product_name =]] user documentation](https://doc.ibexa.co/projects/userguide/en/latest/content_management/content_model/). + An introduction to the content model for non-developer users is available in User Documentation](https://doc.ibexa.co/projects/userguide/en/latest/content_management/content_model/). ## Content items @@ -20,14 +20,14 @@ A content item consists of: - [Content information](#content-information) - [Fields](#fields), defined by the [content type](content_types.md). -The Fields can cover data ranging from single variables and text lines to media files or blocks of formatted text. +The fields can cover data ranging from single variables and text lines to media files or blocks of formatted text. #### Content information General information about a content item is stored in a [`ContentInfo`](../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentInfo.html) object. -`ContentInfo` does not include Fields. It contains following information: +`ContentInfo` doesn't include fields. It contains following information: -**`id`** - the unique ID of the Content object. These numbers are not recycled, so if an item is deleted, its ID will not be reused when a new one is created. +**`id`** - the unique ID of the Content object. These numbers aren't recycled, so if an item is deleted, its ID isn't reused when a new one is created. **`contentTypeId`** - the unique numerical ID of the content type, on which the content item is based. @@ -36,104 +36,104 @@ The name is in the main language of the content item. !!! note - `name` is always searchable, even if the Field(s) used to generate it are not. + `name` is always searchable, even if the field(s) used to generate it aren't. -**`sectionId`** - the unique number of the Section to which the content item belongs. -New content items are placed in the Standard Section by default. -This behavior can be changed, but content must always belong to some Section. -See [Sections](sections.md) for more information. +**`sectionId`** - the unique number of the section to which the content item belongs. +New content items are placed in the Standard section by default. +This behavior can be changed, but content must always belong to some section. + +For more information, see [Sections](sections.md). **`currentVersionNo`** - current version number is the number of the published version or of a newly created draft (which is 1). **`published`** - true if a published version exists, otherwise false. -**`ownerId`** - ID of the User who initially created the content item. -It is set by the system the first time the content item is published. -The ownership of an item cannot be modified and will not change even if the owner is removed from the system. +**`ownerId`** - ID of the user who initially created the content item. +It's set by the system the first time the content item is published. +The ownership of an item cannot be modified and doesn't change even if the owner is removed from the system. **`modificationDate`** - date and time when the content item was last modified. -This is set by the system and cannot be modified manually, but will change every time the item is published again. +It's set by the system and cannot be modified manually, but changes every time the item is published again. **`publishedDate`** - date and time when the content item was published for the first time. -This is set by the system and cannot be modified. +It's set by the system and cannot be modified. **`alwaysAvailable`** - indicates if the content item is shown in the main language when it's not present in another requested language. -It is [set per content type](content_availability.md). +It's [set per content type](content_availability.md). **`remoteId`** - a global unique ID of the content item. Accepts up to 100 characters. Cannot contain non-printable characters and control sequences (anything in ASCII range `\x00` - `\x1F`). -It's recommended to either let this value be generated by the Public PHP API as an MD5 hash, or at least to generate it as a hash (e.g. one from SHA family). +It's recommended to either let this value be generated by the Public PHP API as an MD5 hash, or at least to generate it as a hash (for example, one from SHA family). **`mainLanguageCode`** - the main language code of the content item. -If the `alwaysAvailable` flag is set to true, the content item is shown in this language when the requested language does not exist. +If the `alwaysAvailable` flag is set to true, the content item is shown in this language when the requested language doesn't exist. -**`mainLocationId`** - identifier of the content item's main [Location](locations.md). +**`mainLocationId`** - identifier of the content item's main [location](locations.md). **`status`** - status of the content item. It can have three statuses: 0 – *draft*, 1 – *published* and 2 – *archived*. When an item is created, its status is set to *draft*. After publishing the status changes to *published*. When a published content item is moved to Trash, the item becomes *archived*. -If a published item is removed from the Trash (or removed without being put in the Trash first), it is permanently deleted. +If a published item is removed from the Trash (or removed without being put in the Trash first), it's permanently deleted. ![Diagram of an example content item](content_model_item_diagram.png) -The Fields of a content item are defined by the content type to which the content item belongs. -s +The fields of a content item are defined by the content type to which the content item belongs. + ## Fields -A Field is the smallest unit of storage in the content model and the building block of all content items. Every Field belongs to a Field Type. +A field is the smallest unit of storage in the content model and the building block of all content items. Every field belongs to a field type. -Beyond the built-in set of Field Types, you can [create your own](create_custom_generic_field_type.md). +Beyond the built-in set of field types, you can [create your own](create_custom_generic_field_type.md). ### Field value validation -The values entered in a Field may undergo validation, which means the system makes sure that they are correct for the chosen Field Type and can be used without a problem. +The values entered in a field may undergo validation, which means the system makes sure that they're correct for the chosen field type and can be used without a problem. -Validation depends on the settings of a particular Field Type. It cannot be turned off for a Field if its Field Type supports it. +Validation depends on the settings of a particular field type. It cannot be turned off for a field if its field type supports it. ### Field details -Aside from the Field Type, the Field definition in a content type provides the following information: +Aside from the field type, the field definition in a content type provides the following information: -**Name** – a user-friendly name that describes the Field. This name is used in the interface, but not internally by the system. It can consist of letters, digits, spaces and special characters; the maximum length is 255 characters. If no name is provided, a unique one is automatically generated. +**Name** – a user-friendly name that describes the field. This name is used in the interface, but not internally by the system. It can consist of letters, digits, spaces, and special characters (the maximum length is 255 characters). If no name is provided, a unique one is automatically generated. -**Identifier** – an identifier for internal use in configuration files, templates, PHP code, etc. It can only contain lowercase letters, digits and underscores; the maximum length is 50 characters. This identifier is also used in name patterns for the content type. +**Identifier** – an identifier for internal use, for example, in configuration files, templates, or PHP code. It can only contain lowercase letters, digits and underscores (the maximum length is 50 characters). This identifier is also used in name patterns for the content type. -**Description** – a detailed description of the Field. +**Description** – a detailed description of the field. -**Required** – a flag which indicates if the Field is required for the system to accept the content item. By default, if a Field is flagged as Required, a user will not be able to publish a content item without filling in this Field. +**Required** – a flag which indicates if the field is required for the system to accept the content item. By default, if a field is flagged as Required, a user isn't able to publish a content item without filling in this field. !!! note - You can use the `ContentService::validate()` method to decide whether the required Fields or whole content items are checked for - completeness at other stages of the editing process. + You can use the `ContentService::validate()` method to decide whether the required fields or whole content items are checked for completeness at other stages of the editing process. - The Required flag is in no way related to Field validation. A Field's value is validated whether the Field is set as required or not. + The Required flag is in no way related to field validation. A field's value is validated whether the field is set as required or not. -**[Searchable](search.md)** – a flag which indicates if the value of the Field will be indexed for searching. +**[Searchable](search.md)** – a flag which indicates if the value of the field is indexed for searching. -The Searchable flag is not available for some Fields, because some Field Types do not allow searching through their values. +The Searchable flag isn't available for some fields, because some field types don't allow searching through their values. -**[Translatable](languages.md)** – a flag which indicates if the value of the Field can be translated. This is independent of the Field Type, which means that even Fields such as "Float" or "Image" can be set as translatable. +**[Translatable](languages.md)** – a flag which indicates if the value of the field can be translated. It's independent of the field type, which means that even fields such as "Float" or "Image" can be set as translatable. -Depending on the Field Type, there may also be other, specific information to fill in. For example, the "Country" Field Type allows you to select the default country, as well as to allow selecting multiple countries at the same time. +Depending on the field type, there may also be other, specific information to fill in. For example, the "Country" field type allows you to select the default country, and to allow selecting multiple countries at the same time. ![Diagram of content model](content_model_diagram.png) !!! tip - You can disable the possibility to edit specific Field details per Field Type by [adding custom service definition for `ModifyFieldDefinitionsCollectionTypeExtension`](customize_field_type_metadata.md). + You can disable the possibility to edit specific field details per field type by [adding custom service definition for `ModifyFieldDefinitionsCollectionTypeExtension`](customize_field_type_metadata.md). ## Content versions Each content item can have multiple versions. Each version has one of the following statuses: *draft*, *archived* or *published*. -A new version is created every time a content item is edited. The previous published version is not modified. +A new version is created every time a content item is edited. The previous published version isn't modified. Only one version can be published at the same time. When you publish a new version, the previous published version changes its status to Archived. The number of preserved archived versions is set in `ibexa.repositories.default.options.default_version_archive_limit`. -By default it is set to 5. +By default it's set to 5. A new version is also created when a new [language](languages.md) is added to the content item. @@ -141,4 +141,4 @@ A new version is also created when a new [language](languages.md) is added to th Products are a special type of content that holds products you can manage in the built-in PIM system. -See [PIM](pim.md) for more information. +For more information, see [PIM](pim.md). diff --git a/docs/content_management/content_relations.md b/docs/content_management/content_relations.md index 6170b4b5bc..3ec699cf89 100644 --- a/docs/content_management/content_relations.md +++ b/docs/content_management/content_relations.md @@ -1,32 +1,32 @@ --- -description: Content Relations control links between different content items, either created explicitly or by linking inside RichText Fields. +description: Content Relations control links between different content items, either created explicitly or by linking inside RichText fields. --- # Content Relations -Content items are located in a tree structure through the Locations they are placed in. +Content items are located in a tree structure through the locations they're placed in. However, content items themselves can also be related to one another. ![Content Relations](content_management_relations.png "Content Relations") -A **Relation** can exist between any two content items in the Repository. -For example, images are linked to news articles they are used in. +A **Relation** can exist between any two content items in the repository. +For example, images are linked to news articles they're used in. Instead of using a fixed set of image attributes, the images are stored as separate content items outside the article. -There are different types of Relations available in the system. -Content can have Relations on item or on Field level. +In the system you can find different types of Relations. +Content can have Relations on item or on field level. -*Relations at Field level* are created using one of two special Field Types: Content relation (single) and Content relations (multiple). -These Fields allow you to select one or more other content items in the Field value, which will be linked to these Fields. +*Relations at field level* are created using one of two special field types: Content relation (single) and Content relations (multiple). +These fields allow you to select one or more other content items in the field value, which are linked to these fields. *Relations at content item level* can be of three different types: - *Common Relations* are created between two content items using the public PHP API. -- *RichText linked Relations* are created using a Field of the RichText type. -When an internal link (a link to another Location or content item) is placed in a RichText Field, +- *RichText linked Relations* are created using a field of the RichText type. +When an internal link (a link to another location or content item) is placed in a RichText field, the system automatically creates a Relation. The Relation is automatically removed from the system when the link is removed from the content item. -- *RichText embedded Relations* also use a RichText Field. -When an Embed element is placed in a RichText Field, the system automatically creates a Relation -between the embedded content item and the one with the RichText Field. +- *RichText embedded Relations* also use a RichText field. +When an Embed element is placed in a RichText field, the system automatically creates a Relation +between the embedded content item and the one with the RichText field. The Relation is automatically removed from the system when the link is removed from the content item. diff --git a/docs/content_management/data_migration/add_data_migration_matcher.md b/docs/content_management/data_migration/add_data_migration_matcher.md index 32544b020b..7515fa3b56 100644 --- a/docs/content_management/data_migration/add_data_migration_matcher.md +++ b/docs/content_management/data_migration/add_data_migration_matcher.md @@ -4,16 +4,14 @@ description: Create a matcher for handling data migrations. # Create data migration matcher -[Matchers in data migrations](exporting_data.md#match-property) enable you to select which data from the Repository to export. - +[Matchers in data migrations](exporting_data.md#match-property) enable you to select which data from the repository to export. In addition to the built-in matchers, you can create custom matchers for content. -The following example creates a matcher for Section identifiers. +The following example creates a matcher for section identifiers. ## Create normalizer To do this, first add a normalizer which handles the conversion between objects and the YAML format used for data migration. - Matchers are instances of `FilteringCriterion`, so a custom normalizer needs to denormalize into an instance of `FilteringCriterion`. !!! tip "Normalizers" diff --git a/docs/content_management/data_migration/create_data_migration_action.md b/docs/content_management/data_migration/create_data_migration_action.md index cc4e2e8597..db80b4f553 100644 --- a/docs/content_management/data_migration/create_data_migration_action.md +++ b/docs/content_management/data_migration/create_data_migration_action.md @@ -25,7 +25,7 @@ in `src/Migrations/Action/AssignSectionDenormalizer.php`: [[= include_file('code_samples/data_migration/src/Migrations/Action/AssignSectionDenormalizer.php') =]] ``` -Then, tag the action denormalizer so it is recognized by the serializer used for migrations. +Then, tag the action denormalizer so it's recognized by the serializer used for migrations. ``` yaml [[= include_file('code_samples/data_migration/config/custom_services.yaml', 0, 5) =]] @@ -37,8 +37,7 @@ And finally, add an executor to perform the action, in `src/Migrations/Action/As [[= include_file('code_samples/data_migration/src/Migrations/Action/AssignSectionExecutor.php') =]] ``` -Tag the executor with `ibexa.migrations.executor.action.` tag, where `` is the "type" of the step -that executor works with (`content`, `content_type`, `location`, and so on). +Tag the executor with `ibexa.migrations.executor.action.` tag, where `` is the "type" of the step that executor works with (for example, `content`, `content_type`, or `location`). The tag has to have a `key` property with the action type. ```yaml diff --git a/docs/content_management/data_migration/create_data_migration_step.md b/docs/content_management/data_migration/create_data_migration_step.md index bd777713cf..70499cea71 100644 --- a/docs/content_management/data_migration/create_data_migration_step.md +++ b/docs/content_management/data_migration/create_data_migration_step.md @@ -12,8 +12,7 @@ To create a custom migration step, you need: - A step normalizer, to convert YAML definition into your step class. - A step executor, to handle the step. -The following example shows how to create a step that replaces all `ezstring` Fields -that have an old company name with "New Company Name". +The following example shows how to create a step that replaces all `ezstring` fields that have an old company name with "New Company Name". ## Create step class @@ -32,7 +31,7 @@ in `src/Migrations/Step/ReplaceNameStepNormalizer.php`: [[= include_file('code_samples/data_migration/src/Migrations/Step/ReplaceNameStepNormalizer.php') =]] ``` -Then, tag the step normalizer, so it is recognized by the serializer used for migrations. +Then, tag the step normalizer, so it's recognized by the serializer used for migrations. ``` yaml [[= include_file('code_samples/data_migration/config/custom_services.yaml', 18, 23) =]] diff --git a/docs/content_management/data_migration/data_migration.md b/docs/content_management/data_migration/data_migration.md index c30522a796..d3230cc111 100644 --- a/docs/content_management/data_migration/data_migration.md +++ b/docs/content_management/data_migration/data_migration.md @@ -1,5 +1,5 @@ --- -description: Data migration enables you to import and export Repository data by using YAML files. +description: Data migration enables you to import and export repository data by using YAML files. page_type: landing_page --- @@ -7,15 +7,14 @@ page_type: landing_page Data migration allows exporting and importing selected data from an [[= product_name =]] installation. -[*Exporting*](exporting_data.md) data consists in saving selected Repository information in YAML format. -[*Importing*](importing_data.md) reads migration YAML files and creates or modifies Repository content based on them. -You can migrate your Repository data, that is content items, as well as content types, languages, Object states, Sections, and so on, -between installations. +[*Exporting*](exporting_data.md) data consists in saving selected repository information in YAML format. +[*Importing*](importing_data.md) reads migration YAML files and creates or modifies repository content based on them. +Between installation, you can migrate your repository data, for example, content items, content types, languages, object states, or sections. You can use migrations in projects that require the same data to be present across multiple instances. -They can be useful for project templates. Migrations are able to store shared data, so they can be applied for each new project you start, -or incrementally upgrade older projects to your new standard, if needed. -They are a developer-friendly tool that allows you to share data without writing code. +You can use them for project templates. +Migrations are able to store shared data, so they can be applied for each new project you start, or incrementally upgrade older projects to your new standard, if needed. +They're a developer-friendly tool that allows you to share data without writing code. You can run data migrations either with a command, or with the [PHP API](data_migration_api.md). diff --git a/docs/content_management/data_migration/data_migration_actions.md b/docs/content_management/data_migration/data_migration_actions.md index 0b0b986a42..8b33941835 100644 --- a/docs/content_management/data_migration/data_migration_actions.md +++ b/docs/content_management/data_migration/data_migration_actions.md @@ -1,5 +1,5 @@ --- -description: Data migration actions enable you to run special operations while executing data migrations, such as assigning Roles, Sections, Objects states, and so on. +description: Data migration actions enable you to run special operations while executing data migrations, such as assigning roles, sections, Objects states, and more. page_type: reference month_change: true --- @@ -18,12 +18,12 @@ You can find which migration steps support actions in the table below: | `user_group` |✔|✔|| | `company` |✔||| -Actions are optional operations that can be run after the main "body" of a migration has been executed -(that is, content has been created / updated, Object state has been added, and so on). +Actions are optional operations that can be run after the main "body" of a migration has been executed (for example, content has been created / updated, object state has been added). Their purpose is to allow additional operations to be performed as part of this particular migration. -They are executed inside the same transaction, so in the event of failure they cause database rollback to occur. +They're executed inside the same transaction, so in the event of failure they cause database rollback to occur. For example, when updating a content type object, some fields might be removed: + ``` yaml - type: content_type @@ -41,9 +41,9 @@ For example, when updating a content type object, some fields might be removed: When executed, this migration: - Finds content type using its identifier (`article`) -- Assigns content type Group "Media" -- Removes it from content type Group "Content" -- Removes the `short_title` Field +- Assigns content type group "Media" +- Removes it from content type group "Content" +- Removes the `short_title` field - Removes its existing drafts, if any. ## Available migration actions @@ -63,12 +63,11 @@ The following migration actions are available out of the box: - `assign_role_to_user` (Role Create / Update) - `assign_role_to_user_group` (Role Create / Update) - `assign_user_to_role` (User Create / Update) -- `assign_user_group_to_role` (User Group Create / Update) -- `unassign_role_user_group` (User Group Update) +- `assign_user_group_to_role` (User group Create / Update) +- `unassign_role_user_group` (User group Update) -In contrast with Kaliop migrations, actions provide you with ability to perform additional operations and extend -the migration functionality. -See [creating your own Actions](create_data_migration_action.md). +In contrast with Kaliop migrations, actions provide you with ability to perform additional operations and extend the migration functionality. +For more information, see [creating your own Actions](create_data_migration_action.md). ## Action usage examples @@ -134,14 +133,14 @@ mode: Create and Update mode: Create and Update ``` yaml - actions: - - + actions: + - action: assign_user_to_role identifier: foo - - + - action: assign_user_to_role id: 2 - - + - action: assign_user_to_role id: 2 limitation: @@ -150,7 +149,7 @@ mode: Create and Update - 1 ``` -### User Groups +### User groups mode: Create and Update ``` yaml @@ -161,7 +160,7 @@ mode: Create and Update - action: assign_user_group_to_role id: 2 - - + - action: assign_user_group_to_role id: 1 limitation: @@ -172,7 +171,7 @@ mode: Create and Update !!! note - In the `assign_user_group_to_role` action, Limitation type Section can only use Section ID. + In the `assign_user_group_to_role` action, limitation type section can only use section ID. mode: Update ``` yaml @@ -184,4 +183,4 @@ mode: Update !!! note - In the `unassign_role_user_group` action, the ID is Role assignment ID from the `ezuser_role` table. + In the `unassign_role_user_group` action, the ID is role assignment ID from the `ezuser_role` table. diff --git a/docs/content_management/data_migration/data_migration_api.md b/docs/content_management/data_migration/data_migration_api.md index 01e84812c1..e80225e725 100644 --- a/docs/content_management/data_migration/data_migration_api.md +++ b/docs/content_management/data_migration/data_migration_api.md @@ -8,8 +8,7 @@ You can use the PHP API to manage and run [data migrations](data_migration.md). ## Getting migration information -To list all migration files available in the directory defined in configuration (by default, `src/Migrations/Ibexa`), -use the `MigrationService:listMigrations()` method: +To list all migration files available in the directory defined in configuration (by default, `src/Migrations/Ibexa`), use the `MigrationService:listMigrations()` method: ``` php [[= include_file('code_samples/api/migration/src/Command/MigrationCommand.php', 30, 33) =]] diff --git a/docs/content_management/data_migration/exporting_data.md b/docs/content_management/data_migration/exporting_data.md index 082c33a1c6..7cb301514d 100644 --- a/docs/content_management/data_migration/exporting_data.md +++ b/docs/content_management/data_migration/exporting_data.md @@ -1,5 +1,5 @@ --- -description: Export Repository data to use in future data migrations. +description: Export repository data to use in future data migrations. page_type: reference --- @@ -7,10 +7,9 @@ page_type: reference To see an example of migrations in action, export data already present in your installation. -To export Repository content, use the `ibexa:migrations:generate` command. -This command generates a YAML file with the requested part of the Repository. -The file is located by default in the `src/Migrations/Ibexa/migrations` folder -or in [a custom folder that you configure](managing_migrations.md#migration-folders). +To export repository content, use the `ibexa:migrations:generate` command. +This command generates a YAML file with the requested part of the repository. +The file is located by default in the `src/Migrations/Ibexa/migrations` folder or in [a custom folder that you configure](managing_migrations.md#migration-folders). You can later use this file to import the data. ``` bash @@ -70,13 +69,12 @@ You can treat it as a template for another content item for user group. For example, you could: - Remove `references` if you don't intend to store IDs for future use (see [migration references](managing_migrations.md#references)) -- Remove `publicationDate`, `modificationDate`, `locationRemoteId`, - as those are generated if not passed (just like in PHP API) +- Remove `publicationDate`, `modificationDate`, `locationRemoteId`, as those are generated if not passed (like in PHP API) - Add [`actions`](data_migration_actions.md) - Add fields for other languages present in the system. Similarly, you can create update and delete operations. -They are particularly useful combined with `match-property`. +They're particularly functional combined with `match-property`. This option is automatically added as part of `match` expression in the update/delete migration: ``` bash @@ -128,7 +126,7 @@ php bin/console ibexa:migrations:generate --type=content_type --mode=update --ma ``` -Note that you should test your migrations. See [Importing data](importing_data.md). +You should test your migrations. See [Importing data](importing_data.md). !!! tip @@ -137,11 +135,11 @@ Note that you should test your migrations. See [Importing data](importing_data.m !!! caution [`--siteaccess` option](#siteaccess) usage can be relevant when multiple languages or multiple repositories are used. - To prevent translation loss, it is recommended that you use the SiteAccess that has all the languages used in your implementation, most likely the Back Office one. + To prevent translation loss, it's recommended that you use the SiteAccess that has all the languages used in your implementation, most likely the back office one. ## type -The mandatory `--type` option defines the type of Repository data to export. +The mandatory `--type` option defines the type of repository data to export. The following types are available: - `content` @@ -161,18 +159,18 @@ The following types are available: - `segment_group` - `company` -If you do not provide the `--type` option, the command asks you to select a type of data. +If you don't provide the `--type` option, the command asks you to select a type of data. ## mode The mandatory `--mode` option defines the action that importing the file performs. The following modes are available: -- `create` - creates new items -- `update` - updates an existing item. Only covers specified fields and properties. If the item does not exist, causes an error. -- `delete` - deletes an existing item. If the item does not exist, causes an error. +- `create` - creates new items. +- `update` - updates an existing item. Only covers specified fields and properties. If the item doesn't exist, causes an error. +- `delete` - deletes an existing item. If the item doesn't exist, causes an error. -If you do not provide the `--mode` option, the command asks you to select the mode. +If you don't provide the `--mode` option, the command asks you to select the mode. The following combinations of types are modes are available: @@ -200,7 +198,7 @@ The following combinations of types are modes are available: The optional `--siteaccess` option enables you to export (or import) data in a SiteAccess configuration's context. If not provided, the [default SiteAccess](multisite_configuration.md#default-siteaccess) is used. -It is recommended that you use the SiteAccess of the target repository's Back Office. +It's recommended that you use the SiteAccess of the target repository's back office. Specifying the SiteAccess can be mandatory, for example, when you use several SiteAccesses to handle [several languages](languages.md#using-siteaccesses-for-handling-translations). Export and import commands only work with languages supported by the context SiteAccess. @@ -210,7 +208,7 @@ This option is also important if you use [several repositories with their own da ## match-property -The optional `--match-property` option, together with `value`, enables you to select which data from the Repository to export. +The optional `--match-property` option, together with `value`, enables you to select which data from the repository to export. `match-property` defines what property should be used as a criterion for selecting data. The following properties are available (per type): @@ -269,7 +267,7 @@ You can extend the list of available matchers by creating [a custom one](add_dat ## value -The optional `--value` option, together with `match-property`, filters the Repository content that the command exports. +The optional `--value` option, together with `match-property`, filters the repository content that the command exports. `value` defines which values of the `match-property` should be included in the export. For example, to export only Article content items, use the `content_type_identifier` match property with `article` as the value: @@ -292,15 +290,13 @@ php bin/console ibexa:migrations:generate --type=content --mode=create --file=my !!! note - When migrating multiple files at once (for example when calling `ibexa:migrations:migrate` without options), - they are executed in alphabetical order. + When migrating multiple files at once (for example when calling `ibexa:migrations:migrate` without options), they're executed in alphabetical order. ## user-context -The optional `--user-context` option enables you to run the export command as a specified User. -The command only exports Repository data that the selected User has access to. -By default the admin account is used, unless specifically overridden by this option or in -bundle configuration (`ibexa_migrations.default_user_login`). +The optional `--user-context` option enables you to run the export command as a specified user. +The command only exports repository data that the selected user has access to. +By default the admin account is used, unless specifically overridden by this option or in bundle configuration (`ibexa_migrations.default_user_login`). ``` bash php bin/console ibexa:migrations:generate --type=content --mode=create --user-context=jessica_andaya diff --git a/docs/content_management/data_migration/importing_data.md b/docs/content_management/data_migration/importing_data.md index 408dd64040..4f73164b8c 100644 --- a/docs/content_management/data_migration/importing_data.md +++ b/docs/content_management/data_migration/importing_data.md @@ -1,18 +1,16 @@ --- -description: Import data into your Repository from prepared YAML files. +description: Import data into your repository from prepared YAML files. page_type: reference month_change: false --- # Importing data -To import data from YAML migration files into Repository, you run the `ibexa:migrations:migrate` command. +To import data from YAML migration files into repository, you run the `ibexa:migrations:migrate` command. The `ibexa:migrations:import` command automatically places migration files in the correct folder. -Alternatively, you can place the files manually in the `src/Migrations/Ibexa/migrations` folder -or in [a custom folder that you configure](managing_migrations.md#migration-folders), -and specify the file name within this folder as parameter. +Alternatively, you can place the files manually in the `src/Migrations/Ibexa/migrations` folder or in [a custom folder that you configure](managing_migrations.md#migration-folders), and specify the file name within this folder as parameter. If you don't specify the file, all files within this directory are used. ``` bash @@ -20,17 +18,14 @@ php bin/console ibexa:migrations:migrate --file=my_data_export.yaml --siteaccess ``` Migrations store execution metadata in the `ibexa_migrations` database table. -This allows incremental upgrades: -the `ibexa:migrations:migrate` command ignores files that it had previously executed. +This allows incremental upgrades: the `ibexa:migrations:migrate` command ignores files that it had previously executed. The [`--siteaccess` option](exporting_data.md#siteaccess) usage can be relevant when multiple languages or multiple repositories are used. ## Migration step -A data migration step is a single operation in data migration process -that combines a mode (for example: `create`, `update`, `delete`) -and a type (for example: `content`, `section`, `currency`), -with optional additional information depending on the specific step. +A data migration step is a single operation in data migration process that combines a mode (for example: `create`, `update`, `delete`) +and a type (for example: `content`, `section`, `currency`), with optional additional information depending on the specific step. In a migration file, a step is an array item starting with the mandatory properties `type` and `mode`, for example: @@ -88,8 +83,7 @@ A repeatable migration performs the defined migration steps as many times as the !!! tip - You can use repeatable migration steps, for example, - to quickly generate large numbers of content items for testing purposes. + You can use repeatable migration steps, for example, to quickly generate large numbers of content items for testing purposes. You can vary the operations using the iteration counter. @@ -123,12 +117,11 @@ Then, you can use `faker()` in expressions, for example: [[= include_file('code_samples/data_migration/examples/repeatable_step.yaml', 16, 19) =]] ``` -This step generates Field values with fake personal names. +This step generates field values with fake personal names. ### Expression syntax -You can use [Symfony expression syntax]([[= symfony_doc =]]/reference/formats/expression_language.html) in data migrations, -like in [repeatable steps](#repeatable-steps), where you can use it to generate varied content in migration steps. +You can use [Symfony expression syntax]([[= symfony_doc =]]/reference/formats/expression_language.html) in data migrations, like in [repeatable steps](#repeatable-steps), where you can use it to generate varied content in migration steps. The expression syntax uses the following structure: `### ###` @@ -189,8 +182,7 @@ Built-in expression language functions that are tagged with `ibexa.migrations.te #### Custom functions -To add custom functionality into Migration's expression language declare it as a service -and tag it with `ibexa.migrations.template.expression_language.function`. +To add custom functionality into Migration's expression language declare it as a service and tag it with `ibexa.migrations.template.expression_language.function`. Example: @@ -214,8 +206,7 @@ ibexa.migrations.template.faker: function: faker ``` -Service-based functions can be also added, but they must be callable, -requiring either an `__invoke` function or a wrapping service with one. +Service-based functions can be also added, but they must be callable, requiring either an `__invoke` function or a wrapping service with one. ## Migration examples @@ -223,11 +214,11 @@ The following examples show what data you can import using data migrations. ### Content types -The following example shows how to create a content type with two Field definitions. +The following example shows how to create a content type with two field definitions. The required metadata keys are: `identifier`, `mainTranslation`, `contentTypeGroups` and `translations`. -The default values of Field definition properties mirror the underlying PHP API, for example: +The default values of field definition properties mirror the underlying PHP API, for example: - `translatable` defaults to `true` - `required` defaults to `false` @@ -240,13 +231,10 @@ The default values of Field definition properties mirror the underlying PHP API, The following example shows how to create two content items: a folder and an article inside it. -When creating a content item, three metadata keys are required: -`contentType`, `mainTranslation`, and `parentLocationId`. +When creating a content item, three metadata keys are required: `contentType`, `mainTranslation`, and `parentLocationId`. -To use the Location ID of the folder, which is created automatically by the system, -you can use a [reference](managing_migrations.md#references). -In this case you assign the `parent_folder_location_id` reference name to the Location ID, -and then use it when creating the article. +To use the location ID of the folder, which is created automatically by the system, you can use a [reference](managing_migrations.md#references). +In this case you assign the `parent_folder_location_id` reference name to the location ID, and then use it when creating the article. ``` yaml hl_lines="15 24" [[= include_file('code_samples/data_migration/examples/create_parent_and_child_content.yaml') =]] @@ -254,8 +242,7 @@ and then use it when creating the article. ### Images -The following example shows how to migrate an `example-image.png` located in -`public/var/site/storage/images/3/8/3/0/383-1-eng-GB` without manually placing it in the appropriate path. +The following example shows how to migrate an `example-image.png` located in `public/var/site/storage/images/3/8/3/0/383-1-eng-GB` without manually placing it in the appropriate path. To prevent the manual addition of images to specific DFS or local locations, such as `public/var/site/storage/images/` you can move image files to, for example `src/Migrations/images`. Adjust the migration file and configure the `image` field data as follows: @@ -269,41 +256,39 @@ Adjust the migration file and configure the `image` field data as follows: path: src/Migrations/images/example-image.png ``` -This migration copies the image to the appropriate directory, -in this case `public/var/site/storage/images/3/8/3/0/254-1-eng-GB/example-image.png`, -enabling swift file migration regardless of storage (local, DFS). +This migration copies the image to the appropriate directory, in this case `public/var/site/storage/images/3/8/3/0/254-1-eng-GB/example-image.png`, enabling swift file migration regardless of storage (local, DFS). ### Roles -The following example shows how to create a Role. -A Role requires the `identifier` metadata key. +The following example shows how to create a role. +A role requires the `identifier` metadata key. -For each Policy assigned to the Role, you select the module and function, with optional Limitations. +For each policy assigned to the role, you select the module and function, with optional limitations. -The following example shows the creation of a `Contributor` Role: +The following example shows the creation of a `Contributor` role: ``` yaml [[= include_file('code_samples/data_migration/examples/create_role.yaml') =]] ``` -To update an existing Role, two policies' modes are available: +To update an existing role, two policies' modes are available: - `replace`: (default) All existing policies are replaced by the ones from the migration. - `append`: Migration policies are added while already existing ones are kept. -The following example shows how to replace the policies of the existing `Editor` Role: +The following example shows how to replace the policies of the existing `Editor` role: ``` yaml [[= include_file('code_samples/data_migration/examples/update_role.yaml', 0, 16) =]] ``` -The following example shows the addition of a policy to the `Anonymous` Role: +The following example shows the addition of a policy to the `Anonymous` role: ``` yaml hl_lines="7" [[= include_file('code_samples/data_migration/examples/update_role.yaml', 18, 32) =]] ``` -The following example shows how to delete the `Contributor` Role: +The following example shows how to delete the `Contributor` role: ``` yaml [[= include_file('code_samples/data_migration/examples/delete_role.yaml') =]] @@ -326,7 +311,7 @@ The following example shows how to create a user. The required metadata keys are: `login`, `email`, `password`, `enabled`, `mainLanguage`, and `contentType`. You also need to provide the user group's remote content ID. -You can use an [action](data_migration_actions.md) to assign a Role to the user. +You can use an [action](data_migration_actions.md) to assign a role to the user. ``` yaml hl_lines="22-23" [[= include_file('code_samples/data_migration/examples/create_user.yaml') =]] @@ -366,7 +351,7 @@ The following example shows how to create a product type. The main part of the migration file is the same as when creating a regular content type. -A product type must also contain the definition for an `ibexa_product_specification` Field. +A product type must also contain the definition for an `ibexa_product_specification` field. `fieldSettings` contains information about the product attributes. ``` yaml @@ -397,7 +382,7 @@ The following example creates an image [content item](#content-items) from a loc [[= include_file('code_samples/data_migration/examples/create_product_asset.yaml') =]] ``` -This migration uses a [reference](managing_migrations.md#references) to store the created image Content ID, and then uses it while creating the asset. +This migration uses a [reference](managing_migrations.md#references) to store the created image content ID, and then uses it while creating the asset. It uses an [expression syntax](#expression-syntax) to [concat (`~`)]([[= symfony_doc =]]/reference/formats/expression_language.html#string-operators) the mandatory scheme `ezcontent://` and the image content ID through the [`reference` function](#built-in-functions) used on the reference's name. @@ -481,7 +466,7 @@ If the content type associated with the tags is changed, the configuration shoul If there are multiple taxonomies, the `taxonomy` field is then necessary here (line 21). -You can use the following example to assign tags to a Content (content type Article has an additional Field): +You can use the following example to assign tags to a Content (content type Article has an additional field): ``` yaml [[= include_file('code_samples/data_migration/examples/assign_tag.yaml') =]] diff --git a/docs/content_management/data_migration/managing_migrations.md b/docs/content_management/data_migration/managing_migrations.md index 480c443bbd..6a91a22f37 100644 --- a/docs/content_management/data_migration/managing_migrations.md +++ b/docs/content_management/data_migration/managing_migrations.md @@ -7,9 +7,7 @@ month_change: false ## Converting migration files -If you want to convert a file from the format used by the -[Kaliop migration bundle](https://github.com/kaliop-uk/ezmigrationbundle) -to the current migration format, use the `ibexa:migrations:kaliop:convert` command. +If you want to convert a file from the format used by the [Kaliop migration bundle](https://github.com/kaliop-uk/ezmigrationbundle) to the current migration format, use the `ibexa:migrations:kaliop:convert` command. The source file must use Kaliop mode and type combinations. The converter handles Kaliop types that are different from [[= product_name_base =]] types. @@ -24,12 +22,11 @@ You can also convert multiple files using `ibexa:migrations:kaliop:bulk-convert` php bin/console ibexa:migrations:kaliop:bulk-convert --recursive kaliop_files ibexa_files ``` -If you do not specify the output folder, the command overwrites the input files. +If you don't specify the output folder, the command overwrites the input files. ## Adding migration files -Use the `ibexa:migrations:import` command to add files to the migration folder defined in configuration -(by default, `src/Migrations/Ibexa/migrations`). +Use the `ibexa:migrations:import` command to add files to the migration folder defined in configuration (by default, `src/Migrations/Ibexa/migrations`). ``` bash php bin/console ibexa:migrations:import my_data_export.yaml @@ -37,8 +34,7 @@ php bin/console ibexa:migrations:import my_data_export.yaml ## Checking migration status -To check the status of migration files in the migration folder defined in configuration, -run the following command: +To check the status of migration files in the migration folder defined in configuration, run the following command: ``` bash php bin/console ibexa:migrations:status @@ -85,11 +81,10 @@ bin/console config:dump-reference ibexa_migrations References are key-value pairs necessary when one migration depends on another. -Since some migrations generate object properties (like IDs) during their execution, which cannot be known in advance, -references provide migrations with the ability to use previously created object properties in further migrations. +Since some migrations generate object properties (like IDs) during their execution, which cannot be known in advance, references provide migrations with the ability to use previously created object properties in further migrations. They can be subsequently used by passing them in their desired place with `reference:` prefix. -The example below creates a content item of type "folder", and stores its Location path as `"ref_path__folder__media"`. +The example below creates a content item of type "folder", and stores its location path as `"ref_path__folder__media"`. Then this reference is reused as part of a new role, as a limitation. ```yaml @@ -142,14 +137,13 @@ Then this reference is reused as part of a new role, as a limitation. ``` -By default, reference files are located in a separate directory `src/Migrations/Ibexa/references` -(see [previewing reference](#preview-configuration) -`ibexa_migrations.migration_directory` and `ibexa_migrations.references_files_subdir` options). +By default, reference files are located in a separate directory `src/Migrations/Ibexa/references` (for more information, see [previewing reference](#preview-configuration) `ibexa_migrations.migration_directory` and `ibexa_migrations.references_files_subdir` options). -Reference files are **NOT** loaded by default. A separate step (type: "reference", mode: "load", with filename as "value") -is required. Similarly, saving a reference file is done using type: "reference", mode: "save" step, with filename. +Reference files are **NOT** loaded by default. A separate step (type: "reference", mode: "load", with filename as "value") is required. +Similarly, saving a reference file is done using type: "reference", mode: "save" step, with filename. For example: + ```yaml - type: reference @@ -159,14 +153,14 @@ For example: - type: reference mode: save - # You can also use 'references.yaml', in this case it is overridden + # You can also use 'references.yaml', in this case it's overridden filename: 'new_references.yaml' ``` !!! note - You don't need to save references if they are used in the same migration file. - References are stored in memory during migration, whether they are used or not. + You don't need to save references if they're used in the same migration file. + References are stored in memory during migration, whether they're used or not. ## Available reference types diff --git a/docs/content_management/field_types/create_custom_field_type_comparison.md b/docs/content_management/field_types/create_custom_field_type_comparison.md index fbced9c5e0..7a3a036a9f 100644 --- a/docs/content_management/field_types/create_custom_field_type_comparison.md +++ b/docs/content_management/field_types/create_custom_field_type_comparison.md @@ -1,18 +1,18 @@ --- -description: Enable comparison of content Fields based on a custom Field Type. +description: Enable comparison of content fields based on a custom field type. --- -# Create custom Field Type comparison +# Create custom field type comparison -In the Back Office, you can compare the contents of Fields. -Comparing is possible only between two versions of the same Field that are in the same language. +In the back office, you can compare the contents of fields. +Comparing is possible only between two versions of the same field that are in the same language. -You can add the possibility to compare custom and other unsupported Field Types. +You can add the possibility to compare custom and other unsupported field types. !!! note - The following task uses the [custom "Hello World" Field Type](create_custom_generic_field_type.md). - The configuration is based on the comparison mechanism created for the `ezstring` Field Type. + The following task uses the [custom "Hello World" field type](create_custom_generic_field_type.md). + The configuration is based on the comparison mechanism created for the `ezstring` field type. ## Create Comparable class @@ -42,10 +42,10 @@ Next, create a `src/FieldType/HelloWorld/Comparison/Value.php` file that holds t ## Create comparison engine -The comparison engine handles the operations required for comparing the contents of Fields. -Each Field Type requires a separate comparison engine, which implements the `Ibexa\Contracts\VersionComparison\Engine\FieldTypeComparisonEngine` interface. +The comparison engine handles the operations required for comparing the contents of fields. +Each field type requires a separate comparison engine, which implements the `Ibexa\Contracts\VersionComparison\Engine\FieldTypeComparisonEngine` interface. -For the "Hello World" Field Type, create the following comparison engine based on the engine for the TextLine Field Type. +For the "Hello World" field type, create the following comparison engine based on the engine for the TextLine field type. Place it in `src/FieldType/HelloWorld/Comparison/HelloWorldComparisonEngine.php`: ``` php diff --git a/docs/content_management/field_types/create_custom_generic_field_type.md b/docs/content_management/field_types/create_custom_generic_field_type.md index 465fa77d1c..e97f21329c 100644 --- a/docs/content_management/field_types/create_custom_generic_field_type.md +++ b/docs/content_management/field_types/create_custom_generic_field_type.md @@ -1,25 +1,25 @@ --- -description: Create a new Field Type based on the Generic Field Type. +description: Create a new field type based on the Generic field type. --- -# Create custom generic Field Type +# Create custom generic field type -The Generic Field Type is an abstract implementation of Field Types holding structured data for example, address. -You can use it as a base for custom Field Types. -The Generic Field Type comes with the implementation of basic methods, +The Generic field type is an abstract implementation of field types holding structured data for example, address. +You can use it as a base for custom field types. +The Generic field type comes with the implementation of basic methods, reduces the number of classes which must be created, and simplifies the tagging process. !!! tip - You should not use the Generic Field Type when you need a very specific implementation or complete control over the way data is stored. + You should not use the Generic field type when you need a very specific implementation or complete control over the way data is stored. [[= include_file('docs/snippets/simple_hash_value_caution.md') =]] ## Define value object First, create `Value.php` in the `src/FieldType/HelloWorld` directory. -The Value class of a Field Type contains only the basic logic of a Field Type, the rest of it is handled by the `Type` class. -For more information about Field Type Value see [Value handling](type_and_value.md#value-handling). +The Value class of a field type contains only the basic logic of a field type, the rest of it's handled by the `Type` class. +For more information about field type Value, see [Value handling](type_and_value.md#value-handling). The `HelloWorld` Value class should contain: @@ -32,18 +32,16 @@ The `HelloWorld` Value class should contain: ## Define fields and configuration -Next, implement a definition of a Field Type extending the Generic Field Type in the `src/FieldType/HelloWorld/Type.php` class. -It provides settings for the Field Type and an implementation of the `Ibexa\Contracts\Core\FieldType\FieldType` abstract class. +Next, implement a definition of a field type extending the Generic field type in the `src/FieldType/HelloWorld/Type.php` class. +It provides settings for the field type and an implementation of the `Ibexa\Contracts\Core\FieldType\FieldType` abstract class. ```php [[= include_file('code_samples/field_types/generic_ft/src/FieldType/HelloWorld/Type.php', 0, 6) =]][[= include_file('code_samples/field_types/generic_ft/src/FieldType/HelloWorld/Type.php', 9, 16) =]]} ``` -!!! tip - - For more information about the Type class of a Field Type, see [Type class](type_and_value.md#type-class). +For more information about the Type class of a field type, see [Type class](type_and_value.md#type-class). -Next, register the Field Type as a service and tag it with `ibexa.field_type`: +Next, register the field type as a service and tag it with `ibexa.field_type`: ```yaml [[= include_file('code_samples/field_types/generic_ft/config/custom_services.yaml', 0, 5) =]] @@ -52,13 +50,13 @@ Next, register the Field Type as a service and tag it with `ibexa.field_type`: ## Define form for value object Create a `src/Form/Type/HelloWorldType.php` form. -It enables you to edit the new Field Type. +It enables you to edit the new field type. ```php [[= include_file('code_samples/field_types/generic_ft/src/Form/Type/HelloWorldType.php') =]] ``` -Now you can map Field definitions into Symfony forms with FormMapper. +Now you can map field definitions into Symfony forms with FormMapper. Add the `mapFieldValueForm()` method required by `FieldValueFormMapperInterface` and the required `use` statements to `src/FieldType/HelloWorld/Type.php`: @@ -66,9 +64,7 @@ and the required `use` statements to `src/FieldType/HelloWorld/Type.php`: [[= include_file('code_samples/field_types/generic_ft/src/FieldType/HelloWorld/Type.php') =]] ``` -!!! tip - - For more information about the FormMappers see [Field Type form and template](form_and_template.md). +For more information about the FormMappers, see [field type form and template](form_and_template.md). Next, add the `ibexa.admin_ui.field_type.form.mapper.value` tag to the service definition: @@ -80,7 +76,7 @@ Next, add the `ibexa.admin_ui.field_type.form.mapper.value` tag to the service d ### Create a template -Create a template for the new Field Type. It defines the default rendering of the `HelloWorld` field. +Create a template for the new field type. It defines the default rendering of the `HelloWorld` field. In the `templates/themes/standard/field_types` directory create a `field_type.html.twig` file: ```html+twig @@ -97,7 +93,7 @@ Provide the template mapping under the `ibexa.system..field_templates` [c ## Final results -Finally, you should be able to add a new content type in the Back Office interface. +Finally, you should be able to add a new content type in the back office interface. Navigate to **Content types** tab and under **Content** category create a new content type: ![Creating new content type](extending_field_type_create.png) @@ -110,4 +106,4 @@ After saving, your **Hello World** content type should be available under **Cont ![Creating Hello World](extending_field_type_hello_world.png) -For more detailed tutorial on Generic Field Type follow [Creating a Point 2D Field Type](creating_a_point2d_field_type.md). +For more detailed tutorial on Generic field type follow [Creating a Point 2D field type](creating_a_point2d_field_type.md). diff --git a/docs/content_management/field_types/customize_field_type_metadata.md b/docs/content_management/field_types/customize_field_type_metadata.md index 53a179097c..88d9d8fc0e 100644 --- a/docs/content_management/field_types/customize_field_type_metadata.md +++ b/docs/content_management/field_types/customize_field_type_metadata.md @@ -1,16 +1,15 @@ --- -description: You can customize which Field Type metadata should be disabled in the Back Office. +description: You can customize which field type metadata should be disabled in the back office. --- -# Customize Field Type metadata +# Customize field type metadata -When creating a content type definition, you add Fields and configure their metadata, -such as whether they are required, translatable, and so on. +When creating a content type definition, you add fields and configure their metadata, for example, whether they're required or translatable. -If needed, you can customize that some of those options are disabled in the Back Office for specific Field Types. -To do this, add custom service definition for `ModifyFieldDefinitionsCollectionTypeExtension` +If needed, you can customize that some of those options are disabled in the back office for specific field types. +To do this, add custom service definition for `ModifyFieldDefinitionsCollectionTypeExtension`. -For example, this configuration means that no Image Field can be set as required in the definition of a content type: +For example, this configuration means that no Image field can be set as required in the definition of a content type: ``` yaml services: @@ -24,13 +23,13 @@ services: - form.type_extension ``` -`fieldTypeIdentifier` refers to the identifier of the Field Type, in this case `ezimage`. +`fieldTypeIdentifier` refers to the identifier of the field type, in this case `ezimage`. `modifiedOptions` lists the changes you want to make. The following options are available: -- `disable_identifier_field` - disables changing the Field identifier -- `disable_required_field` - disables setting the Field as required -- `disable_translatable_field` - disables setting the Field as translatable -- `disable_remove` - disables removing the Field from content type definition (after it has been saved) +- `disable_identifier_field` - disables changing the field identifier +- `disable_required_field` - disables setting the field as required +- `disable_translatable_field` - disables setting the field as translatable +- `disable_remove` - disables removing the field from content type definition (after it has been saved) -![Image Field with disabled required option](disable-required-field.png) +![Image field with disabled required option](disable-required-field.png) diff --git a/docs/content_management/field_types/field_type_reference/addressfield.md b/docs/content_management/field_types/field_type_reference/addressfield.md index a0d7665a08..acac7e3618 100644 --- a/docs/content_management/field_types/field_type_reference/addressfield.md +++ b/docs/content_management/field_types/field_type_reference/addressfield.md @@ -1,16 +1,16 @@ -# Address Field Type +# Address field type -This Field represents and handles address fields. -It allows you to customize address Fields per country. +This field represents and handles address fields. +It allows you to customize address fields per country. | Name | Internal name | Expected input | |-----------|-----------------|-----------------------------| | `Address` | `ibexa_address` | `string`, `string`, `array` | -The Address Field Type is available via the Address Bundle +The Address field type is available via the Address Bundle provided by the `ibexa/fieldtype-address` package. -## PHP API Field Type +## PHP API field type ### Inputs: @@ -36,9 +36,9 @@ new FieldType\Value( ### Validation -This Field Type validates whether `Country` and `Name` fields have been filled out. +This field type validates whether `Country` and `Name` fields have been filled out. -### Value Object +### Value object #### Properties @@ -67,7 +67,7 @@ formats: - postal_code ``` -#### Modifying Field configuration +#### Modifying field configuration ```yaml formats: diff --git a/docs/content_management/field_types/field_type_reference/authorfield.md b/docs/content_management/field_types/field_type_reference/authorfield.md index fc33732642..d3097aea82 100644 --- a/docs/content_management/field_types/field_type_reference/authorfield.md +++ b/docs/content_management/field_types/field_type_reference/authorfield.md @@ -1,14 +1,14 @@ -# Author Field Type +# Author field type -This Field Type allows the storage and retrieval of one or more authors. For each author, it can handle a name and an email address. It is typically used to store information about additional authors who have written/created different parts of a content item. +This field type allows the storage and retrieval of one or more authors. For each author, it can handle a name and an email address. It's typically used to store information about additional authors who have written/created different parts of a content item. | Name | Internal name | Expected input | Output | |----------|---------------|----------------|----------| | `Author` | `ezauthor` | mixed | `string` | -## PHP API Field Type +## PHP API field type -### Value Object +### Value object ##### Properties @@ -62,11 +62,11 @@ Example: `John Doe john@doe.com` ### Validation -This Field Type does not perform any special validation of the input value. +This field type doesn't perform any special validation of the input value. ### Settings -The Field definition of this Field Type can be configured with a single option: +The Field definition of this field type can be configured with a single option: |Name|Type|Default value|Description| |------|------|------|------| @@ -76,11 +76,11 @@ Following `defaultAuthor` default value options are available as constants in |Constant|Description| |------|------| -|`DEFAULT_VALUE_EMPTY`|Default value will be empty.| -|`DEFAULT_CURRENT_USER`|Default value will use currently logged user.| +|`DEFAULT_VALUE_EMPTY`|Default value is empty.| +|`DEFAULT_CURRENT_USER`|Default value uses currently logged user.| ``` php -// Author Field Type example settings +// Author field type example settings use Ibexa\Core\FieldType\Author\Type; diff --git a/docs/content_management/field_types/field_type_reference/binaryfilefield.md b/docs/content_management/field_types/field_type_reference/binaryfilefield.md index b64cff6897..974717146d 100644 --- a/docs/content_management/field_types/field_type_reference/binaryfilefield.md +++ b/docs/content_management/field_types/field_type_reference/binaryfilefield.md @@ -1,27 +1,28 @@ -# BinaryFile Field Type +# BinaryFile field type -This Field Type represents and handles a single binary file. It also counts the number of times the file has been downloaded from the `content/download` module. +This field type represents and handles a single binary file. It also counts the number of times the file has been downloaded from the `content/download` module. -It is capable of handling virtually any file type and is typically used for storing legacy document types such as PDF files, Word documents, spreadsheets, etc. The maximum allowed file size is determined by the "Max file size" class attribute edit parameter and the `upload_max_filesize` directive in the main PHP configuration file (`php.ini`). +It's capable of handling virtually any file type and is typically used for storing legacy document types, for example, PDF files, Word documents, or spreadsheets. +The maximum allowed file size is determined by the "Max file size" class attribute edit parameter and the `upload_max_filesize` directive in the main PHP configuration file (`php.ini`). | Name | Internal name | Expected input | Output | |--------------|----------------|----------------|---------| | `BinaryFile` | `ezbinaryfile` | mixed | mixed | -## PHP API Field Type +## PHP API field type -### Value Object +### Value object #### Properties -Note that both `BinaryFile` and `Media` Value and Type inherit from the `BinaryBase` abstract Field Type, and share common properties. +Both `BinaryFile` and `Media` Value and Type inherit from the `BinaryBase` abstract field type, and share common properties. `Ibexa\Core\FieldType\BinaryFile\Value` offers the following properties: |Attribute|Type|Description|Example| |------|------|------|------| |`id`|string|Binary file identifier. This ID depends on the [IO Handler](clustering.md#dfs-io-handler) that is being used. With the native, default handlers (FileSystem and Legacy), the ID is the file path, relative to the binary file storage root dir (`var//storage/original` by default).|application/63cd472dd7.pdf| -|`fileName`|string|The human-readable file name, as exposed to the outside. Used when sending the file for download in order to name the file.|20130116_whitepaper.pdf| +|`fileName`|string|The human-readable file name, as exposed to the outside. Used when sending the file for download to name the file.|20130116_whitepaper.pdf| |`fileSize`|int|File size, in bytes.|1077923| |`mimeType`|string|The file's MIME type.|application/pdf| |`uri`|string|The binary file's `content/download` URI. If the URI doesn't include a host or protocol, it applies to the request domain.|/content/download/210/2707| @@ -59,11 +60,11 @@ To use a remote file, you have to download it locally first, then remove it afte ## REST API specifics -Used in the REST API, a BinaryFile Field will mostly serialize the hash described above. However there are a couple specifics worth mentioning. +Used in the REST API, a BinaryFile field mostly serializes the hash described above. However there are a couple specifics worth mentioning. ### Reading content: `url` property -When reading the contents of a Field of this type, an extra key is added: `url`. This key gives you the absolute file URL, protocol and host included. +When reading the contents of a field of this type, an extra key is added: `url`. This key gives you the absolute file URL, protocol and host included. Example: `http://example.com/var/ezdemo_site/storage/original/application/63cd472dd7819da7b75e8e2fee507c68.pdf` diff --git a/docs/content_management/field_types/field_type_reference/checkboxfield.md b/docs/content_management/field_types/field_type_reference/checkboxfield.md index c68e04abd5..1e697f5e7f 100644 --- a/docs/content_management/field_types/field_type_reference/checkboxfield.md +++ b/docs/content_management/field_types/field_type_reference/checkboxfield.md @@ -1,18 +1,18 @@ -# Checkbox Field Type +# Checkbox field type -The Checkbox Field Type stores the current status for a checkbox input, checked or unchecked, by storing a boolean value. +The Checkbox field type stores the current status for a checkbox input, checked or unchecked, by storing a boolean value. | Name | Internal name | Expected input type | |------------|---------------|---------------------| | `Checkbox` | `ezboolean` | `boolean` | -## PHP API Field Type  +## PHP API field type  ### Value object ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Default value | Description| |----------|-----------|---------------|------------| @@ -46,4 +46,4 @@ $checkboxValue = new Checkbox\Value( true ); ##### String representation -As this Field Type is not a string but a boolean, it will return "1" (true) or "0" (false) in cases where it is cast to string, and it is never considered empty. +As this field type isn't a string but a boolean, it returns "1" (true) or "0" (false) in cases where it's cast to string, and it's never considered empty. diff --git a/docs/content_management/field_types/field_type_reference/contentqueryfield.md b/docs/content_management/field_types/field_type_reference/contentqueryfield.md index a590ed9a3e..6d5da60186 100644 --- a/docs/content_management/field_types/field_type_reference/contentqueryfield.md +++ b/docs/content_management/field_types/field_type_reference/contentqueryfield.md @@ -1,12 +1,11 @@ -# Content query Field Type +# Content query field type -This Field Type maps an executable Repository query to a Field. +This field type maps an executable repository query to a field. | Name | Internal name | Expected input | |-----------|---------------|----------------| | `Content query` | `ezcontentquery` | `string` | -The Content query Field Type is available via the Query Field Type Bundle -provided by the [fieldtype-query](https://github.com/ibexa/fieldtype-query) package. +The Content query field type is available via the Query field type Bundle provided by the [fieldtype-query](https://github.com/ibexa/fieldtype-query) package. -For information about the Field Type's usage, see [Content queries](content_queries.md#content-query-field). +For information about the field type's usage, see [Content queries](content_queries.md#content-query-field). diff --git a/docs/content_management/field_types/field_type_reference/countryfield.md b/docs/content_management/field_types/field_type_reference/countryfield.md index 7b2854c960..93d7e219a8 100644 --- a/docs/content_management/field_types/field_type_reference/countryfield.md +++ b/docs/content_management/field_types/field_type_reference/countryfield.md @@ -1,12 +1,12 @@ -# Country Field Type +# Country field type -This Field Type represents one or multiple countries. +This field type represents one or multiple countries. | Name | Internal name | Expected input | |-----------|---------------|----------------| | `Country` | `ezcountry` | `array` | -## PHP API Field Type  +## PHP API field type  ### Input expectations @@ -23,15 +23,15 @@ Example array: ]; ``` -When you set an array directly on a Content Field you don't need to provide all this information, the Field Type will assume it is a hash and in this case will accept a simplified structure described below under [Hash format](#hash-format). +When you set an array directly on a content field you don't need to provide all this information, the field type assumes it's a hash and in this case accepts a simplified structure described below under [Hash format](#hash-format). ### Validation -This Field Type validates whether multiple countries are allowed by the Field definition, and whether the [Alpha2](https://www.iso.org/iso-3166-country-codes.html) is valid according to the countries configured in [[= product_name =]]. +This field type validates whether multiple countries are allowed by the field definition, and whether the [Alpha2](https://www.iso.org/iso-3166-country-codes.html) is valid according to the countries configured in [[= product_name =]]. ### Settings -The Field definition of this Field Type can be configured with one option: +The field definition of this field type can be configured with one option: | Name | Type | Default value | Description| |--------------|-----------|---------------|------------| @@ -46,20 +46,21 @@ $settings = [ ### Hash format -The format used for serialization is simpler than the full format. It is also available when setting value on the content Field, by setting the value to an array instead of the Value object. Example of that shown below: +The format used for serialization is simpler than the full format. +It's also available when setting value on the content field, by setting the value to an array instead of the value object. Example of that shown below: ``` php // Value object content example $content->fields["countries"] = [ "JP", "NO" ]; ``` -The format used by the toHash method is the Alpha2 value, however the input is capable of accepting either Name, Alpha2 or Alpha3 value as shown below in the Value object section. +The format used by the toHash method is the Alpha2 value, however the input is capable of accepting either Name, Alpha2, or Alpha3 value as shown below in the value object section. ### Value object ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |--------------|-----------|------------| @@ -79,7 +80,8 @@ $value->countries = [ ##### Constructor -The `Country\Value` constructor will initialize a new Value object with the value provided. It expects an array as input. +The `Country\Value` constructor initializes a new value object with the value provided. +It expects an array as input. ``` php // Constructor example diff --git a/docs/content_management/field_types/field_type_reference/customergroupfield.md b/docs/content_management/field_types/field_type_reference/customergroupfield.md index 6c0ee986c4..6cd3d118dd 100644 --- a/docs/content_management/field_types/field_type_reference/customergroupfield.md +++ b/docs/content_management/field_types/field_type_reference/customergroupfield.md @@ -1,18 +1,18 @@ -# Customer group Field +# Customer group field -This Field Type represents a customer group that a user belongs to. +This field type represents a customer group that a user belongs to. | Name | Internal name | Expected input type | |--------|---------------|---------------------| | `Customer group` | `ibexa_customer_group` | `int` or null | -## PHP API Field Type +## PHP API field type ### Value object ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |----------|----------|------------| diff --git a/docs/content_management/field_types/field_type_reference/dateandtimefield.md b/docs/content_management/field_types/field_type_reference/dateandtimefield.md index 16a5eb92b4..6b30bd1780 100644 --- a/docs/content_management/field_types/field_type_reference/dateandtimefield.md +++ b/docs/content_management/field_types/field_type_reference/dateandtimefield.md @@ -1,18 +1,18 @@ -# DateAndTime Field Type +# DateAndTime field type -This Field Type represents a full date and time information. +This field type represents a full date and time information. | Name | Internal name | Expected input type | |---------------|---------------|---------------------| | `DateAndTime` | `ezdatetime` | mixed | -## PHP API Field Type  +## PHP API field type  ### Input expectations -If input value is of type `string` or `integer`, it will be passed directly to the [PHP's built-in `\DateTime` class constructor](https://www.php.net/manual/en/datetime.construct.php), therefore the same input format expectations apply. +If input value is of type `string` or `integer`, it's passed directly to the [PHP's built-in `\DateTime` class constructor](https://www.php.net/manual/en/datetime.construct.php), therefore the same input format expectations apply. -It is also possible to directly pass an instance of `\DateTime`. +It's also possible to directly pass an instance of `\DateTime`. |Type|Example| |------|------| @@ -24,7 +24,7 @@ It is also possible to directly pass an instance of `\DateTime`. ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |----------|-------------|------------| @@ -32,11 +32,11 @@ The Value class of this Field Type contains the following properties: ##### Constructor -The constructor for this value object will initialize a new Value object with the value provided. It accepts an instance of PHP's built-in `\DateTime` class. +The constructor for this value object initializes a new value object with the value provided. It accepts an instance of PHP's built-in `\DateTime` class. ##### String representation -String representation of the date value will generate the date string in the format `D Y-d-m H:i:s` as accepted by [PHP's built-in `date()` function](https://www.php.net/manual/en/function.date.php). +String representation of the date value generates the date string in the format `D Y-d-m H:i:s` as accepted by [PHP's built-in `date()` function](https://www.php.net/manual/en/function.date.php). |Character|Description|Example| |---------|----------|--------| @@ -52,12 +52,12 @@ Example: `Wed 2016-22-05 12:19:18` ### Hash format -Hash value of this Field Type is an array with two keys: +Hash value of this field type is an array with two keys: |Key|Type| Description |Example| |------|------|---------------------------------------------------------------------------------------------------------------------------------------------------------|------| |`timestamp`|`integer`| Time information in [Unix format timestamp](https://en.wikipedia.org/wiki/Unix_time). |`1400856992`| -|`rfc850`|`string`| Time information as a string in [RFC 850 date format](https://datatracker.ietf.org/doc/html/rfc850). As input, this will have precedence over the timestamp value. |`"Friday, 23-May-14 14:56:14 GMT+0000"`| +|`rfc850`|`string`| Time information as a string in [RFC 850 date format](https://datatracker.ietf.org/doc/html/rfc850). As input, this has precedence over the timestamp value. |`"Friday, 23-May-14 14:56:14 GMT+0000"`| ``` php $hash = [ @@ -68,25 +68,25 @@ $hash = [ ### Validation -This Field Type does not perform any special validation of the input value. +This field type doesn't perform any special validation of the input value. ### Settings -The Field definition of this Field Type can be configured with several options: +The field definition of this field type can be configured with several options: |Name|Type|Default value|Description| |------|------|------|------| |`useSeconds`|`boolean`|`false`|Used to control displaying of seconds in the output.| -|`defaultType`|`mixed`|`Type::DEFAULT_EMPTY`|One of the `DEFAULT_*` constants, used by the administration interface for setting the default Field value. See below for more details.| -|`dateInterval`|`null|\DateInterval`|`null`|This setting complements `defaultType` setting and can be used only when the latter is set to `Type::DEFAULT_CURRENT_DATE_ADJUSTED`. In that case the default input value when using administration interface will be adjusted by the given `\DateInterval`.| +|`defaultType`|`mixed`|`Type::DEFAULT_EMPTY`|One of the `DEFAULT_*` constants, used by the administration interface for setting the default field value. See below for more details.| +|`dateInterval`|`null|\DateInterval`|`null`|This setting complements `defaultType` setting and can be used only when the latter is set to `Type::DEFAULT_CURRENT_DATE_ADJUSTED`. In that case the default input value when using administration interface is adjusted by the given `\DateInterval`.| Following `defaultType` default value options are available as constants in the `Ibexa\Core\FieldType\DateAndTime\Type` class: |Constant|Description| |------|------| -|`DEFAULT_EMPTY`|Default value will be empty.| -|`DEFAULT_CURRENT_DATE`|Default value will use current date.| -|`DEFAULT_CURRENT_DATE_ADJUSTED`|Default value will use current date, adjusted by the interval defined in `dateInterval` setting.| +|`DEFAULT_EMPTY`|Default value is empty.| +|`DEFAULT_CURRENT_DATE`|Default value uses current date.| +|`DEFAULT_CURRENT_DATE_ADJUSTED`|Default value uses current date, adjusted by the interval defined in `dateInterval` setting.| ``` php // DateAndTime FieldType example settings @@ -102,11 +102,11 @@ $settings = [ ## Template rendering -The template called by the [`ibexa_render_field()` Twig function](field_twig_functions.md#ibexa_render_field) while rendering a Date Field has access to the following parameters: +The template called by the [`ibexa_render_field()` Twig function](field_twig_functions.md#ibexa_render_field) while rendering a Date field has access to the following parameters: | Parameter | Type | Default | Description| |-----------|----------|---------|------------| -| `locale` | `string` |   n/a | Internal parameter set by the system based on current request locale or if not set calculated based on the language of the Field. | +| `locale` | `string` |   n/a | Internal parameter set by the system based on current request locale or if not set calculated based on the language of the field. | Example: diff --git a/docs/content_management/field_types/field_type_reference/datefield.md b/docs/content_management/field_types/field_type_reference/datefield.md index 88cdf96804..8938fd704f 100644 --- a/docs/content_management/field_types/field_type_reference/datefield.md +++ b/docs/content_management/field_types/field_type_reference/datefield.md @@ -1,18 +1,18 @@ -# Date Field Type +# Date field type -This Field Type represents a date without time information. +This field type represents a date without time information. | Name | Internal name | Expected input type | |--------|---------------|---------------------| | `Date` | `ezdate` | mixed | -#### PHP API Field Type  +#### PHP API field type  ### Input expectations -If input value is in `string` or `integer` format, it will be passed directly to [PHP's built-in `\DateTime` class constructor](https://www.php.net/manual/en/datetime.construct.php), therefore the same input format expectations apply. +If input value is in `string` or `integer` format, it's passed directly to [PHP's built-in `\DateTime` class constructor](https://www.php.net/manual/en/datetime.construct.php), therefore the same input format expectations apply. -It is also possible to directly pass an instance of `\DateTime`. +It's also possible to directly pass an instance of `\DateTime`. |Type|Example| |------|------| @@ -22,21 +22,21 @@ It is also possible to directly pass an instance of `\DateTime`. Time information is **not stored**. -Before storing, the provided input value will be set to the beginning of the day in the given or the environment timezone. +Before storing, the provided input value is set to the beginning of the day in the given or the environment timezone. ### Value object ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |----------|-------------|------------| -| `$date` | `\DateTime` | This property will be used for the text content. | +| `$date` | `\DateTime` | This property is used for the text content. | ##### String representation -String representation of the date value will generate the date string in the format "l d F Y" as accepted by [PHP's built-in `date()` function](https://www.php.net/manual/en/function.date.php). +String representation of the date value generates the date string in the format "l d F Y" as accepted by [PHP's built-in `date()` function](https://www.php.net/manual/en/function.date.php). |Character|Description|Example| |---------|----------|--------| @@ -49,16 +49,17 @@ Example: `Wednesday 22 May 2016` ##### Constructor -The constructor for this value object will initialize a new Value object with the value provided. It accepts an instance of [PHP's built-in `\DateTime` class](https://www.php.net/manual/en/datetime.construct.php). +The constructor for this value object initializes a new value object with the value provided. +It accepts an instance of [PHP's built-in `\DateTime` class](https://www.php.net/manual/en/datetime.construct.php). ### Hash format -Hash value of this Field Type is an array with two keys: +Hash value of this field type is an array with two keys: |Key|Type| Description |Example| |------|------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|------| |`timestamp`|`integer`| Time information in [unix format timestamp](https://en.wikipedia.org/wiki/Unix_time). |`1400856992`| -|`rfc850`|`string`| Time information as a string in [RFC 850 date format](https://datatracker.ietf.org/doc/html/rfc850). As input, this will have higher precedence over the timestamp value. |`"Friday, 23-May-14 14:56:14 GMT+0000"`| +|`rfc850`|`string`| Time information as a string in [RFC 850 date format](https://datatracker.ietf.org/doc/html/rfc850). As input, this has higher precedence over the timestamp value. |`"Friday, 23-May-14 14:56:14 GMT+0000"`| ``` php // Example of the hash value in PHP @@ -70,25 +71,25 @@ $hash = [ ### Validation -This Field Type does not perform any special validation of the input value. +This field type doesn't perform any special validation of the input value. ### Settings -The Field definition of this Field Type can be configured with a single option: +The field definition of this field type can be configured with a single option: |Name|Type|Default value|Description| |------|------|------|------| -|`defaultType`|`mixed`|`Type::DEFAULT_EMPTY`|One of the `DEFAULT_*` constants, used by the administration interface for setting the default Field value. See below for more details.| +|`defaultType`|`mixed`|`Type::DEFAULT_EMPTY`|One of the `DEFAULT_*` constants, used by the administration interface for setting the default field value. See below for more details.| Following `defaultType` default value options are available as constants in the `Ibexa\Core\FieldType\Date\Type` class: |Constant|Description| |------|------| -|`DEFAULT_EMPTY`|Default value will be empty.| -|`DEFAULT_CURRENT_DATE`|Default value will use current date.| +|`DEFAULT_EMPTY`|Default value is empty.| +|`DEFAULT_CURRENT_DATE`|Default value uses current date.| ``` php -// Date Field Type example settings +// Date field type example settings use Ibexa\Core\FieldType\Date\Type; @@ -99,11 +100,11 @@ $settings = [ ## Template rendering -The template called by [the `ibexa_render_field()` Twig function](field_twig_functions.md#ibexa_render_field) while rendering a Date Field has access to the following parameters: +The template called by [the `ibexa_render_field()` Twig function](field_twig_functions.md#ibexa_render_field) while rendering a Date field has access to the following parameters: | Parameter | Type |Description| |-----------|----------|------------| -| `locale` | `string` |Internal parameter set by the system based on current request locale or if not set, calculated based on the language of the Field. | +| `locale` | `string` |Internal parameter set by the system based on current request locale or if not set, calculated based on the language of the field. | Example: diff --git a/docs/content_management/field_types/field_type_reference/emailaddressfield.md b/docs/content_management/field_types/field_type_reference/emailaddressfield.md index 9bea73c042..a23a84885f 100644 --- a/docs/content_management/field_types/field_type_reference/emailaddressfield.md +++ b/docs/content_management/field_types/field_type_reference/emailaddressfield.md @@ -1,22 +1,22 @@ -# EmailAddress Field Type +# EmailAddress field type -The EmailAddress Field Type represents an email address, in the form of a string. +The EmailAddress field type represents an email address, in the form of a string. | Name | Internal name | Expected input type | |----------------|---------------|---------------------| | `EmailAddress` | `ezemail` | `string` | -## PHP API Field Type  +## PHP API field type  ### Value object ##### Properties -The `Value` class of this Field Type contains the following properties: +The `Value` class of this field type contains the following properties: | Property | Type | Description| |----------|----------|------------| -| `$email` | `string` | This property will be used for the input string provided as email address. | +| `$email` | `string` | This property is used for the input string provided as email address. | ``` php // Value object content example @@ -32,7 +32,8 @@ $emailaddressValue->email = "someuser@example.com"; ##### Constructor -The `EmailAddress\Value` constructor will initialize a new Value object with the value provided. It accepts a string as input. +The `EmailAddress\Value` constructor initializes a new value object with the value provided. +It accepts a string as input. ``` php // Constructor example @@ -45,21 +46,21 @@ $emailaddressValue = new Type\Value( "someuser@example.com" ); ##### String representation -String representation of the Field Type's Value object is the email address contained in it. +String representation of the field type's value object is the email address contained in it. Example: `someuser@example.com` ### Hash format -Hash value for this Field Type's Value is simply the email address as a string. +Hash value for this field type's Value is simply the email address as a string. Example: `someuser@example.com` ### Validation -This Field Type uses the `EmailAddressValidator` validator as a resource which will test the string supplied as input against a pattern, to make sure that a valid email address has been provided. +This field type uses the `EmailAddressValidator` validator as a resource which tests the string supplied as input against a pattern, to make sure that a valid email address has been provided. If the validations fail, a `ValidationError` is thrown, specifying the error message. ### Settings -This Field Type does not support settings. +This field type doesn't support settings. diff --git a/docs/content_management/field_types/field_type_reference/field_type_reference.md b/docs/content_management/field_types/field_type_reference/field_type_reference.md index d518fa1837..a9b11eb2c6 100644 --- a/docs/content_management/field_types/field_type_reference/field_type_reference.md +++ b/docs/content_management/field_types/field_type_reference/field_type_reference.md @@ -1,29 +1,34 @@ --- -description: Ibexa DXP offers a range of built-in Field Types that cover most common needs when creating content. +description: Ibexa DXP offers a range of built-in field types that cover most common needs when creating content. page_type: reference --- -# Field Type reference +# Field type reference -A Field Type is the underlying building block of the content model. It consists of two entities: Field value and Field definition. Field value is determined by values entered into the Content Field. Field definition is provided by the content type, and holds any user defined rules used by Field Type to determine how a Field Value is validated, stored, retrieved, formatted and so on. +A field type is the underlying building block of the content model. +It consists of two entities: field value and field definition. +Field value is determined by values entered into the content field. +Field definition is provided by the content type, and holds any user defined rules used by field type to determine how a field value is, for example, validated, stored, retrieved, or formatted. -[[= product_name =]] comes with a collection of Field Types that can be used to build powerful and complex content structures. In addition, it is possible to extend the system by creating custom types for special needs. +[[= product_name =]] comes with a collection of field types that can be used to build powerful and complex content structures. +In addition, it's possible to extend the system by creating custom types for special needs. !!! tip - For general Field Type documentation, see [Field Type](field_types.md). + For general field type documentation, see [field type](field_types.md). -Custom Field Types have to be programmed in PHP. However, the built-in Field Types are usually sufficient enough for typical scenarios. The following table gives an overview of the supported Field Types that come with [[= product_name =]]. +Custom field types have to be programmed in PHP. However, the built-in field types are usually sufficient enough for typical scenarios. +The following table gives an overview of the supported field types that come with [[= product_name =]]. -## Available Field Types +## Available field types -| Field Type | Description | Searchable in Legacy Storage engine | Searchable with Solr/Elasticsearch | +| Field type | Description | Searchable in Legacy Storage engine | Searchable with Solr/Elasticsearch | |------------|-------------|-------------------------------------|----------------------| | [Author](authorfield.md) | Stores a list of authors, each consisting of author name and author email. | No | Yes | | [BinaryFile](binaryfilefield.md) | Stores a file.| Yes | Yes | | [Checkbox](checkboxfield.md) | Stores a boolean value. | Yes | Yes | -| [Content query](contentqueryfield.md) | Maps an executable Repository query to a Field. | No | No | +| [Content query](contentqueryfield.md) | Maps an executable repository query to a field. | No | No | | [Country](countryfield.md) | Stores country names as a string. | Yes[^1^](#1-note-on-legacy-search-engine) | Yes | | [Customer group](customergroupfield.md) | Stores customer group to which a user belongs. | [DateAndTime](dateandtimefield.md) | Stores a full date including time information. | Yes | Yes | @@ -40,7 +45,7 @@ Custom Field Types have to be programmed in PHP. However, the built-in Field Ty | [Matrix](matrixfield.md) | Represents and handles a table of rows and columns of data. | No | No | | [Measurement](measurementfield.md) | Validates and stores a unit of measure, and either a single measurement value, or top and bottom values of a measurement range. | Yes | Yes | | [Media](mediafield.md) | Validates and stores a media file. | No | Yes | -| [Null](nullfield.md) | Used as fallback for missing Field Types and for testing purposes. | N/A | N/A | +| [Null](nullfield.md) | Used as fallback for missing field types and for testing purposes. | N/A | N/A | | [Page](pagefield.md) | Stores a Page with a layout consisting of multiple zones. | N/A | N/A | | [Relation](relationfield.md) | Validates and stores a relation to a content item. | Yes, with both [`Field`](fieldrelation_criterion.md) Criteria | Yes | | [RelationList](relationlistfield.md) | Validates and stores a list of relations to content items. | Yes, with [`FieldRelation` Criterion](fieldrelation_criterion.md) | Yes | @@ -60,8 +65,6 @@ Custom Field Types have to be programmed in PHP. However, the built-in Field Ty **^[1]^ Note on Legacy Search Engine** -Legacy Search/Storage Engine index is limited to 255 characters in database design, -so formatted and unformatted text blocks will only index the first part. -In case of multiple selection Field Types like Keyword, Selection, Country, etc., -only the first choices are indexed. They are indexed only as a text blob separated by string separator. -Proper indexing of these Field Types is done with [Solr Search engine](solr_overview.md). +Legacy Search/Storage Engine index is limited to 255 characters in database design, so formatted and unformatted text blocks only index the first part. +In case of multiple selection field types like, for example, Keyword, Selection, or Country, only the first choices are indexed. they're indexed only as a text blob separated by string separator. +Proper indexing of these field types is done with [Solr Search engine](solr_overview.md). diff --git a/docs/content_management/field_types/field_type_reference/floatfield.md b/docs/content_management/field_types/field_type_reference/floatfield.md index 8711bb0606..e544384a7b 100644 --- a/docs/content_management/field_types/field_type_reference/floatfield.md +++ b/docs/content_management/field_types/field_type_reference/floatfield.md @@ -1,16 +1,16 @@ -# Float Field Type +# Float field type -This Field Type stores numeric values which are provided as floats. +This field type stores numeric values which are provided as floats. | Name | Internal name | Expected input | |---------|---------------|----------------| | `Float` | `ezfloat` | `float` | -## PHP API Field Type  +## PHP API field type  ### Input expectations -The Field Type expects a number as input. Both decimal and integer numbers are accepted. +The field type expects a number as input. Both decimal and integer numbers are accepted. |Type|Example| |------|------| @@ -21,11 +21,11 @@ The Field Type expects a number as input. Both decimal and integer numbers are a ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |----------|---------|------------| -| `$value` | `float` | This property will be used to store the value provided as a float. | +| `$value` | `float` | This property is used to store the value provided as a float. | ``` php // Value object content example @@ -40,7 +40,8 @@ $float->value = 284.773 ##### Constructor -The `Float\Value` constructor will initialize a new Value object with the value provided. It expects a numeric value with or without decimals. +The `Float\Value` constructor initializes a new value object with the value provided. +It expects a numeric value with or without decimals. ``` php // Constructor example @@ -53,12 +54,12 @@ $floatValue = new Type\Value( 284.773 ); ### Validation -This Field Type supports `FloatValueValidator`, defining maximum and minimum float value: +This field type supports `FloatValueValidator`, defining maximum and minimum float value: |Name|Type|Default value|Description| |------|------|------|------| -|`minFloatValue`|`float`|`null|This setting defines the minimum value this Field Type will allow as input.| -|`maxFloatValue`|`float`|`null|This setting defines the maximum value this Field Type will allow as input.| +|`minFloatValue`|`float`|`null|This setting defines the minimum value this field type which is allowed as input.| +|`maxFloatValue`|`float`|`null|This setting defines the maximum value this field type which is allowed as input.| ``` php // Validator configuration example in PHP @@ -79,4 +80,4 @@ $floatFieldCreateStruct->validatorConfiguration = [ ### Settings -This Field Type does not support settings. +This field type doesn't support settings. diff --git a/docs/content_management/field_types/field_type_reference/formfield.md b/docs/content_management/field_types/field_type_reference/formfield.md index 4670ffe463..00a3081439 100644 --- a/docs/content_management/field_types/field_type_reference/formfield.md +++ b/docs/content_management/field_types/field_type_reference/formfield.md @@ -2,9 +2,9 @@ edition: experience --- -# Form Field Type +# Form field type -The Form Field Type stores a Form consisting of one or more form fields. +The Form field type stores a Form consisting of one or more form fields. | Name | Internal name | |--------|---------------| @@ -12,4 +12,4 @@ The Form Field Type stores a Form consisting of one or more form fields. -See [Forms](work_with_forms.md) for more information about working with Forms. +For more information about working with Forms, see [Forms](work_with_forms.md). diff --git a/docs/content_management/field_types/field_type_reference/imageassetfield.md b/docs/content_management/field_types/field_type_reference/imageassetfield.md index 11608ca015..a81e3d7714 100644 --- a/docs/content_management/field_types/field_type_reference/imageassetfield.md +++ b/docs/content_management/field_types/field_type_reference/imageassetfield.md @@ -1,6 +1,7 @@ -# ImageAsset Field Type +# ImageAsset field type -ImageAsset Field Type enables storing images in independent content items of a generic Image content type, in the media library. It makes them reusable across system. +ImageAsset field type enables storing images in independent content items of a generic Image content type, in the media library. +It makes them reusable across system. ### Input expectations @@ -8,7 +9,7 @@ Example array: |Type|Description|Example| |------|------|------| -|`Ibexa\Core\FieldType\ImageAsset\Value`|ImageAsset Field Type value object.|See below.| +|`Ibexa\Core\FieldType\ImageAsset\Value`|ImageAsset field type value object.|See below.| |`Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo`|ContentInfo instance of the Asset content item. |n/a| |`string`| ID of the Asset content item. |`"150"`| |`integer`| ID of the Asset content item. | `150`| @@ -33,7 +34,8 @@ $imageAssetValue->alternativeText = "Picture of an apple."; ##### Constructor -The `ImageAsset\Value` constructor will initialize a new value object with the value provided. It expects an ID of a content item representing asset and the alternative text. +The `ImageAsset\Value` constructor initializes a new value object with the value provided. +It expects an ID of a content item representing asset and the alternative text. ``` php // Constructor example @@ -44,13 +46,13 @@ $imageAssetValue = new ImageAsset\Value($contentInfo->id, "Picture of an apple. ### Validation -This Field Type validates if: +This field type validates if: - `destinationContentId` points to a content item which has correct content type ### Configuration -ImageAsset Field Type allows configuring the following options: +ImageAsset field type allows configuring the following options: |Name|Description|Default value| |----|-----------|-------------| @@ -73,14 +75,15 @@ ibexa: parent_location_id: 106 ``` -## Customizing ImageAsset Field Type rendering +## Customizing ImageAsset field type rendering -Internally the Image Asset Type is rendered via subrequest (similar to other relation types). Rendering customization is possible by configuring view type `asset_image`: +Internally the Image Asset Type is rendered via subrequest (similar to other relation types). +Rendering customization is possible by configuring view type `asset_image`: ```php ibexa: system: - default: + default: content_view: asset_image: default: @@ -90,4 +93,4 @@ ibexa: ## Generating image variation from the Image Asset -Thanks to the `Ibexa\Bundle\Core\Imagine\ImageAsset` decorator you can work with `Ibexa\Contracts\Core\Variation` in the same way as with [Image Field Type](imagefield.md). +Thanks to the `Ibexa\Bundle\Core\Imagine\ImageAsset` decorator you can work with `Ibexa\Contracts\Core\Variation` in the same way as with [Image field type](imagefield.md). diff --git a/docs/content_management/field_types/field_type_reference/imagefield.md b/docs/content_management/field_types/field_type_reference/imagefield.md index b295b77040..b28392c6a2 100644 --- a/docs/content_management/field_types/field_type_reference/imagefield.md +++ b/docs/content_management/field_types/field_type_reference/imagefield.md @@ -1,25 +1,25 @@ -# Image Field Type +# Image field type -The Image Field Type allows you to store an image file. +The Image field type allows you to store an image file. | Name | Internal name | |---------|---------------| | `Image` | `ezimage` | -A **variation service** handles the conversion of the original image into different formats and sizes through a set of preconfigured named variations: large, small, medium, black and white thumbnail, etc. +A **variation service** handles the conversion of the original image into different formats and sizes through a set of preconfigured named variations, for example, large, small, medium, or black and white thumbnail. -## PHP API Field Type +## PHP API field type ### Value object -The `value` property of an Image Field returns an `Ibexa\Core\FieldType\Image\Value` object with the following properties: +The `value` property of an Image field returns an `Ibexa\Core\FieldType\Image\Value` object with the following properties: ##### Properties |Property|Type|Example|Description| |------|------|------|------| |`id`|string|`0/8/4/1/1480-1-eng-GB/image.png`|The image's unique identifier. Usually the path, or a part of the path. To get the full path, use the `uri` property.| -|`alternativeText`|string|`Picture of an apple.`|The alternative text, as entered in the Field's properties. This property is optional. It is recommended that you require the alternative text for an image when you add the Image Field to a content type, by selecting the "Alternative text is required" checkbox.| +|`alternativeText`|string|`Picture of an apple.`|The alternative text, as entered in the field's properties. This property is optional. It's recommended that you require the alternative text for an image when you add the Image field to a content type, by selecting the "Alternative text is required" checkbox.| |`fileName`|string|`image.png`|The original image's filename, without the path.| |`fileSize`|int|`37931`|The original image's size, in bytes.| |`uri`|string|`var/ezdemo_site/storage/images/0/8/4/1/1480-1-eng-GB/image.png`|The original image's URI.| @@ -30,24 +30,26 @@ The `value` property of an Image Field returns an `Ibexa\Core\FieldType\Image\V !!! caution - Properties marked with an asterisk are currently unsupported. They are available but their value is always `null`. + Properties marked with an asterisk are currently unsupported. + They're available but their value is always `null`. Follow [EZP-27987](https://issues.ibexa.co/browse/EZP-27987) for future progress on this issue. ### Settings -This Field Type does not support settings. +This field type doesn't support settings. -### Image Variations +### Image variations -Using the variation Service, variations of the original image can be obtained. They are `Ibexa\Contracts\Core\Variation\Values\ImageVariation` objects with the following properties: +Using the variation Service, variations of the original image can be obtained. +They're `Ibexa\Contracts\Core\Variation\Values\ImageVariation` objects with the following properties: | Property | Type | Example | Description| |----------------|----------|----------|------------| | `width`* | int | `null` | The variation's width in pixels. For more details see Caution note below.| | `height`* | int | `null` | The variation's height in pixels. For more details see Caution note below.| -| `name` | string | `medium` | The variation's identifier, name of the image alias.| -| `info` | mixed |n/a| Extra information about the image, depending on the image type, such as EXIF data. If there is no information, the `info` value will be `null`.| +| `name` | string | `medium` | The variation's identifier, name of the image variation.| +| `info` | mixed |n/a| Extra information about the image, depending on the image type, such as EXIF data. If there is no information, the `info` value is `null`.| | `fileSize` | int |`31010` |Size (in byte) of current variation.| | `mimeType` | string |`image/png`|The MIME type.| | `fileName` | string |`my_image.png`|The name of the file.| @@ -57,35 +59,36 @@ Using the variation Service, variations of the original image can be obtained. T !!! caution - Properties marked with an asterisk are currently unsupported. They are available but their value is always `null`. + Properties marked with an asterisk are currently unsupported. + They're available but their value is always `null`. Follow [EZP-27987](https://issues.ibexa.co/browse/EZP-27987) for future progress on this issue. ### Field Definition options -The Image Field Type supports one `FieldDefinition` option: the maximum size for the file. +The Image field type supports one `FieldDefinition` option: the maximum size for the file. -!!!note +!!! note Maximum size is rounded to 1 MB (legacy storage limitation). !!! note - As the default value for maximum size is set to 10MB, we recommend setting the `upload_max_filesize` key in the `php.ini` configuration file to a value equal to or higher than that. It will prevent validation errors while editing content types. + As the default value for maximum size is set to 10MB, we recommend setting the `upload_max_filesize` key in the `php.ini` configuration file to a value equal to or higher than that. It prevents validation errors while editing content types. -## Using an Image Field +## Using an Image field To read more about handling images and image variations, see the [Images documentation](images.md). ### Template Rendering -When displayed using `ibexa_render_field`, an Image Field will output this type of HTML: +When displayed using `ibexa_render_field`, an Image field outputs this type of HTML: ``` html+twig Alternative text ``` -The template called by the [`ibexa_render_field()` Twig function](field_twig_functions.md#ibexa_render_field) while rendering a Image Field accepts the following parameters: +The template called by the [`ibexa_render_field()` Twig function](field_twig_functions.md#ibexa_render_field) while rendering a Image field accepts the following parameters: | Parameter | Type | Default | Description | |-----------|----------|----------------|-------------| @@ -100,7 +103,7 @@ Example:  {{ ibexa_render_field( content, 'image', { 'parameters':{ 'alias': 'imagelarge', 'width': 400, 'height': 400 } } ) }} ``` -The raw Field can also be used if needed. Image variations for the Field's content can be obtained using the `ibexa_image_alias` Twig helper: +The raw field can also be used if needed. Image variations for the field's content can be obtained using the `ibexa_image_alias` Twig helper: ``` html+twig {% set imageAlias = ibexa_image_alias( field, versionInfo, 'medium' ) %} @@ -114,7 +117,8 @@ The variation's properties can be used to generate the required output: ### With the REST API -Image Fields within REST are exposed by the `application/vnd.ibexa.api.Content` media-type. An Image Field will look like this: +Image Fields within REST are exposed by the `application/vnd.ibexa.api.Content` media-type. +An Image field looks like this: ``` xml @@ -140,7 +144,9 @@ Image Fields within REST are exposed by the `application/vnd.ibexa.api.Content` ``` -Children of the `fieldValue` node will list the general properties of the Field's original image (`fileSize`, `fileName`, `inputUri`, etc.), as well as variations. For each variation, a URI is provided. Requested through REST, this resource will generate the variation if it doesn't exist yet, and list the variation details: +Children of the `fieldValue` node list the general properties of the field's original image (for example, `fileSize`, `fileName`, or `inputUri`), and its variations. +For each variation, a URI is provided. +Requested through REST, this resource generates the variation if it doesn't exist yet, and list the variation details: ``` xml @@ -156,7 +162,8 @@ Children of the `fieldValue` node will list the general properties of the Field' #### Getting an image variation -The variation service, `ibexa.field_type.ezimage.variation_service`, can be used to generate/get variations for a Field. It expects a VersionInfo, the Image Field, and the variation name as a string (`large`, `medium`, etc.): +The variation service, `ibexa.field_type.ezimage.variation_service`, can be used to generate/get variations for a field. +It expects a VersionInfo, the Image field, and the variation name as a string (`large`, `medium`, and more.): ``` php $variation = $imageVariationHandler->getVariation( @@ -170,7 +177,8 @@ echo $variation->uri; ### From PHP -As for any Field Type, there are several ways to input content to a Field. For an Image, the quickest is to call `setField()` on the ContentStruct: +As for any field type, there are several ways to input content to a field. +For an Image, the quickest is to call `setField()` on the ContentStruct: ``` php $createStruct = $contentService->newContentCreateStruct( @@ -181,7 +189,8 @@ $createStruct = $contentService->newContentCreateStruct( $createStruct->setField( 'image', '/tmp/image.png' ); ``` -In order to customize the Image's alternative texts, you must first get an `Image\Value` object, and set this property. For that, you can use the `Image\Value::fromString()` method that accepts the path to a local file: +To customize the Image's alternative texts, you must first get an `Image\Value` object, and set this property. +For that, you can use the `Image\Value::fromString()` method that accepts the path to a local file: ``` php $createStruct = $contentService->newContentCreateStruct( @@ -211,9 +220,11 @@ $createStruct->setField( 'image', $imageValue ); ### From REST -The REST API expects Field values to be provided in a hash-like structure. Those keys are identical to those expected by the `Image\Value` constructor: `fileName`, `alternativeText`. In addition, image data can be provided using the `data` property, with the image's content encoded as base64. +The REST API expects field values to be provided in a hash-like structure. +Those keys are identical to those expected by the `Image\Value` constructor: `fileName`, `alternativeText`. +In addition, image data can be provided using the `data` property, with the image's content encoded as base64. -#### Creating an Image Field +#### Creating an Image field ``` @@ -236,9 +247,11 @@ The REST API expects Field values to be provided in a hash-like structure. Those ``` -### Updating an Image Field +### Updating an Image field -Updating an Image Field requires that you re-send existing data. This can be done by re-using the Field obtained via REST, **removing the variations key**, and updating `alternativeText`, `fileName` or `data`. If you do not want to change the image itself, do not provide the `data` key. +Updating an Image field requires that you re-send existing data. +This can be done by re-using the field obtained via REST, **removing the variations key**, and updating `alternativeText`, `fileName` or `data`. +If you don't want to change the image itself, don't provide the `data` key. ``` xml @@ -277,11 +290,11 @@ With the following values: - `VersionNumber` = `1` - `LanguageCode` = `eng-GB` -Images will be stored in `web/var/ezdemo_site/storage/images/0/8/4/1/1480-1-eng-GB`. +Images are stored in `web/var/ezdemo_site/storage/images/0/8/4/1/1480-1-eng-GB`. -Using the Field ID digits in reverse order as the folder structure maximizes sharding of files through multiple folders on the filesystem. +Using the field ID digits in reverse order as the folder structure maximizes sharding of files through multiple folders on the filesystem. -Within this folder, images will be named like the uploaded file, suffixed with an underscore and the variation name: +Within this folder, images are named like the uploaded file, suffixed with an underscore, and the variation name: - `MyImage.png` - `MyImage_large.png` diff --git a/docs/content_management/field_types/field_type_reference/integerfield.md b/docs/content_management/field_types/field_type_reference/integerfield.md index 3ecf391eff..11f1357ecd 100644 --- a/docs/content_management/field_types/field_type_reference/integerfield.md +++ b/docs/content_management/field_types/field_type_reference/integerfield.md @@ -1,12 +1,12 @@ -# Integer Field Type +# Integer field type -This Field Type represents an integer value. +This field type represents an integer value. | Name | Internal name | Expected input | |-----------|---------------|----------------| | `Integer` | `ezinteger` | `integer` | -## PHP API Field Type  +## PHP API field type  ### Input expectations @@ -18,7 +18,7 @@ This Field Type represents an integer value. ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |----------|-------|------------| @@ -31,7 +31,8 @@ $integer->value = 8 ##### Constructor -The `Integer\Value` constructor will initialize a new Value object with the value provided. It expects a numeric, integer value. +The `Integer\Value` constructor initializes a new value object with the value provided. +It expects a numeric, integer value. ``` php // Constructor example @@ -43,24 +44,24 @@ $integerValue = new Integer\Value( 8 ); ### Hash format -Hash value of this Field Type is an integer value as a string. +Hash value of this field type is an integer value as a string. Example: `"8"` ### String representation -String representation of the Field Type's value will return the integer value as a string. +String representation of the field type's value returns the integer value as a string. Example: `"8"` ### Validation -This Field Type supports `IntegerValueValidator`, defining maximum and minimum float value: +This field type supports `IntegerValueValidator`, defining maximum and minimum float value: |Name|Type|Default value|Description| |------|------|------|------| -|`minIntegerValue`|`int`|`0`|This setting defines the minimum value this Field Type will allow as input.| -|`maxIntegerValue`|`int`|`null`|This setting defines the maximum value this Field Type will allow as input.| +|`minIntegerValue`|`int`|`0`|This setting defines the minimum value this field type which is allowed as input.| +|`maxIntegerValue`|`int`|`null`|This setting defines the maximum value this field type which is allowed as input.| ``` php // Example of validator configuration in PHP @@ -72,4 +73,4 @@ $validatorConfiguration = [ ### Settings -This Field Type does not support settings. +This field type doesn't support settings. diff --git a/docs/content_management/field_types/field_type_reference/isbnfield.md b/docs/content_management/field_types/field_type_reference/isbnfield.md index 4ce1cca247..98e9a23ad7 100644 --- a/docs/content_management/field_types/field_type_reference/isbnfield.md +++ b/docs/content_management/field_types/field_type_reference/isbnfield.md @@ -1,22 +1,22 @@ -# ISBN Field Type +# ISBN field type -This Field Type represents an ISBN string either an ISBN-10 or ISBN-13 format. +This field type represents an ISBN string either an ISBN-10 or ISBN-13 format. | Name | Internal name | Expected input type | |--------|---------------|---------------------| | `ISBN` | `ezisbn` | `string` | -## PHP API Field Type  +## PHP API field type  ### Value object ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |----------|----------|------------| -| `$isbn` | `string` | This property will be used for the ISBN string. | +| `$isbn` | `string` | This property is used for the ISBN string. | ##### String representation @@ -24,11 +24,13 @@ An ISBN's string representation is the `$isbn` property's value, as a string. ##### Constructor -The constructor for this value object will initialize a new Value object with the value provided. It accepts a string as argument and will set it to the `isbn` attribute. +The constructor for this value object initializes a new value object with the value provided. +It accepts a string as argument and sets it to the `isbn` attribute. ### Validation -The input passed into this Field Type is subject of ISBN validation depending on the Field settings in its FieldDefinition stored in the content type. An example of this Field setting is shown below and will control if input is validated as ISBN-13 or ISBN-10: +The input passed into this field type is subject of ISBN validation depending on the field settings in its FieldDefinition stored in the content type. +An example of this field setting is shown below and controls if input is validated as ISBN-13 or ISBN-10: ``` php Array diff --git a/docs/content_management/field_types/field_type_reference/keywordfield.md b/docs/content_management/field_types/field_type_reference/keywordfield.md index 2d9d67f8c1..5e2d67bd69 100644 --- a/docs/content_management/field_types/field_type_reference/keywordfield.md +++ b/docs/content_management/field_types/field_type_reference/keywordfield.md @@ -1,12 +1,12 @@ -# Keyword Field Type +# Keyword field type -This Field Type stores one or several comma-separated keywords as a string or array of strings. +This field type stores one or several comma-separated keywords as a string or array of strings. | Name | Internal name | Expected input| |-----------|---------------|---------------| | `Keyword` | `ezkeyword` | `string[]|string` | -## PHP API Field Type  +## PHP API field type  ### Input expectations @@ -20,7 +20,7 @@ This Field Type stores one or several comma-separated keywords as a string or ar ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |----------|------------|------------| @@ -39,7 +39,7 @@ $keyword->value = [ "php", "css3", "html5", "Ibexa Platform" ]; #### Constructor -The `Keyword\Value` constructor will initialize a new Value object with the value provided. +The `Keyword\Value` constructor initializes a new value object with the value provided. It expects a list of keywords, either comma-separated in a string or as an array of strings. diff --git a/docs/content_management/field_types/field_type_reference/maplocationfield.md b/docs/content_management/field_types/field_type_reference/maplocationfield.md index 691184cb13..b7cf7b8c18 100644 --- a/docs/content_management/field_types/field_type_reference/maplocationfield.md +++ b/docs/content_management/field_types/field_type_reference/maplocationfield.md @@ -1,6 +1,6 @@ -# MapLocation Field Type +# MapLocation field type -This Field Type represents a geographical location. +This field type represents a geographical location. As input it expects three values: @@ -11,7 +11,7 @@ As input it expects three values: |---------------|------------------|----------------| | `MapLocation` | `ezgmaplocation` | `mixed` | -## PHP API Field Type  +## PHP API field type  ### Input expectations @@ -23,7 +23,7 @@ As input it expects three values: ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: |Property|Type|Description| |------|------|------| @@ -33,7 +33,8 @@ The Value class of this Field Type contains the following properties: ##### Constructor -The `MapLocation\Value` constructor will initialize a new Value object with values provided as hash. Accepted keys are `latitude` (`float`), `longitude` (`float`), `address` (`string`). +The `MapLocation\Value` constructor initializes a new value object with values provided as hash. +Accepted keys are `latitude` (`float`), `longitude` (`float`), `address` (`string`). ``` php // Constructor example @@ -50,7 +51,7 @@ $MapLocationValue = new MapLocation\Value( ## Template rendering -The template called by [the `ibexa_render_field()` Twig function](field_twig_functions.md#ibexa_render_field) while rendering a Map Location Field accepts the following parameters: +The template called by [the `ibexa_render_field()` Twig function](field_twig_functions.md#ibexa_render_field) while rendering a Map location field accepts the following parameters: |Parameter|Type|Default|Description| |------|------|------|------| @@ -70,5 +71,4 @@ Example: !!! note - The option to automatically get user coordinates through the "Locate me" button - is only available when the Back Office is served through the `https://` protocol. + The option to automatically get user coordinates through the "Locate me" button is only available when the back office is served through the `https://` protocol. diff --git a/docs/content_management/field_types/field_type_reference/matrixfield.md b/docs/content_management/field_types/field_type_reference/matrixfield.md index 7bede9a995..a4c32f6401 100644 --- a/docs/content_management/field_types/field_type_reference/matrixfield.md +++ b/docs/content_management/field_types/field_type_reference/matrixfield.md @@ -1,15 +1,14 @@ -# Matrix Field Type +# Matrix field type -This Field represents and handles a table of rows and columns of data. +This field represents and handles a table of rows and columns of data. | Name | Internal name | Expected input | |----------|---------------|----------------| | `Matrix` | `ezmatrix` | `array` | -The Matrix Field Type is available via the Matrix Bundle -provided by the [ibexa/fieldtype-matrix](https://github.com/ibexa/fieldtype-matrix) package. +The Matrix field type is available via the Matrix Bundle provided by the [ibexa/fieldtype-matrix](https://github.com/ibexa/fieldtype-matrix) package. -## PHP API Field Type +## PHP API field type ### Input expectations @@ -27,7 +26,7 @@ new FieldType\Value([ ]); ``` -### Value Object +### Value object `Ibexa\FieldTypeMatrix\FieldType\Value` offers the following properties: @@ -37,13 +36,15 @@ new FieldType\Value([ ### Validation -The minimum number of rows is set on content type level for each Field. +The minimum number of rows is set on content type level for each field. -Validation checks for empty rows. A row is considered empty if it contains only empty cells (or cells containing only spaces). Empty rows are removed. +Validation checks for empty rows. +A row is considered empty if it contains only empty cells (or cells containing only spaces). +Empty rows are removed. -If, after removing empty rows, the number of rows does not fulfill the configured `Minimum number of rows`, the Field will not validate. +If, after removing empty rows, the number of rows doesn't fulfill the configured `Minimum number of rows`, the field doesn't validate. -For example, the following input will not validate if `Minimum number of rows` is set to 3, because the second row is empty: +For example, the following input doesn't validate if `Minimum number of rows` is set to 3, because the second row is empty: ```php new FieldType\Value([ @@ -53,15 +54,15 @@ new FieldType\Value([ ]); ``` -## GraphQL Field Type operations +## GraphQL field type operations -To get a Field of the Matrix Field Type with GraphQL, you will need to specify a Content ID, a content type, and a Field Type. +To get a field of the Matrix field type with GraphQL, you need to specify a content ID, a content type, and a field type. -The types that are returned are named after the Type and the Field: +The types that are returned are named after the Type and the field: - `{TypeIdentifier}{FieldIdentifier}Row` -The example below shows a GraphQL query for a Recipe content item (belonging to a content type with a Matrix Field added), that has two Fields: +The example below shows a GraphQL query for a Recipe content item (belonging to a content type with a Matrix field added), that has two fields: - `name`: `ezstring` - `ingredients`: `ezmatrix` with two columns: `ingredient` and `quantity` @@ -80,7 +81,7 @@ The example below shows a GraphQL query for a Recipe content item (belonging to } ``` -The Type returned for the Matrix Field exposes columns defined in the Field definition: +The Type returned for the Matrix field exposes columns defined in the field definition: ``` { @@ -104,9 +105,10 @@ The Type returned for the Matrix Field exposes columns defined in the Field defi } ``` -### Query for the Field Type and Field definition's details +### Query for the field type and field definition's details -With this query you can inspect details of specific content type. In case of a Matrix Field, you can ask for the list of columns, their names and identifiers. +With this query you can inspect details of specific content type. +In case of a Matrix field, you can ask for the list of columns, their names, and identifiers. ``` { @@ -128,7 +130,7 @@ With this query you can inspect details of specific content type. In case of a M } ``` -The response will list the exposed Field Type settings: +The response lists the exposed field type settings: - minimumRows - columns @@ -167,12 +169,12 @@ Example response: ### Mutation -To create a Matrix Field Type you need to define Field Type and Field definition identifiers. -The types that are used for input are named after the Type and the Field: +To create a Matrix field type you need to define field type and field definition identifiers. +The types that are used for input are named after the Type and the field: -- `{TypeIdentifier}{FieldIdentifier}RowInput` e.g. `dish.nutritionFacts`, `event.agenda`: `DishNutritionFactsRowInput`, `EventAgendaRowInput` +- `{TypeIdentifier}{FieldIdentifier}RowInput`, for example, `dish.nutritionFacts`, `event.agenda`: `DishNutritionFactsRowInput`, `EventAgendaRowInput` -The example below shows how to create a Recipe content item (belonging to a content type with a Matrix Field Type added) that has two Fields: +The example below shows how to create a Recipe content item (belonging to a content type with a Matrix field type added) that has two fields: - `name`: `"Cake Ingredient List"` - `ingredients`: `ezmatrix` with two columns: `ingredient` and `quantity` @@ -195,7 +197,7 @@ The example below shows how to create a Recipe content item (belonging to a cont } ``` -The response will confirm creation of the new Recipe Field: +The response confirms creation of the new Recipe field: ``` { diff --git a/docs/content_management/field_types/field_type_reference/measurementfield.md b/docs/content_management/field_types/field_type_reference/measurementfield.md index 317db3ebcf..6b34a5a50c 100644 --- a/docs/content_management/field_types/field_type_reference/measurementfield.md +++ b/docs/content_management/field_types/field_type_reference/measurementfield.md @@ -1,14 +1,13 @@ -# Measurement Field Type +# Measurement field type -The Measurement Field Type represents measurement information. -It stores the unit of measure, and either a single measurement value, -or a pair of values that defines a range. +The Measurement field type represents measurement information. +It stores the unit of measure, and either a single measurement value, or a pair of values that defines a range. | Name | Internal name | Expected input type | |---------------|---------------------|----------------------------------------------------| | `Measurement` | `ibexa_measurement` | `Ibexa\Contracts\Measurement\Value\ValueInterface` | -## PHP API Field Type +## PHP API field type ### Input expectations @@ -19,8 +18,7 @@ The service contains the following API endpoints: - `buildSimpleValue` that is used to handle a single value - `buildRangeValue` that is used to handle a range -Assuming that the service exists as `$measurementService`, the expected input -examples are as follows: +Assuming that the service exists as `$measurementService`, the expected input examples are as follows: | Type | Example | |---------------------------------------------------------|---------------------------------------------------------------------| @@ -31,7 +29,7 @@ examples are as follows: ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description | |----------|--------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -39,8 +37,7 @@ The Value class of this Field Type contains the following properties: ##### Constructor -The `Measurement\Value` constructor for this value object initializes a new value -object with the value provided. +The `Measurement\Value` constructor for this value object initializes a new value object with the value provided. As its first argument it accepts an object of `Ibexa\Contracts\Measurement\Value\ValueInterface` type. Depending on the selected input type, the object resembles the following examples: @@ -78,13 +75,11 @@ $measurementValue = new Measurement\Value( ### Validation -The Measurement Field Type validates measurement types and units passed within -the value object against a list of the ones that the system supports, which can -be found in the `vendor/ibexa/measurement/src/bundle/Resources/config/builtin_units.yaml` file. +The Measurement field type validates measurement types and units passed within the value object against a list of the ones that the system supports, which can be found in the `vendor/ibexa/measurement/src/bundle/Resources/config/builtin_units.yaml` file. ### Modify and add Measurement types and units -You can extend the default list of Measurement types and units by modifying the existing entries or adding new ones. +You can extend the default list of Measurement types and units by modifying the existing entries or adding new ones. To do this, you modify the YAML configuration. To override an existing designation of the unit of measure by changing the symbol that corresponds to a nautical unit of speed, and to add a rotational speed unit, add the following lines to your [YAML configuration](configuration.md#configuration-files): @@ -121,12 +116,11 @@ ibexa: - my_unit ``` -The configuration also requires that exactly one unit needs -to be marked as `is_base_unit` as in highlighted line above. +The configuration also requires that exactly one unit needs to be marked as `is_base_unit` as in highlighted line above. !!! note - To be available for selection in the Back Office, each new Measurement type or unit must be enabled for the Back Office SiteAccess. + To be available for selection in the back office, each new Measurement type or unit must be enabled for the back office SiteAccess. Next, you need to define how the new unit should be converted under the `ibexa.system..ibexa_measurement` [configuration key](configuration.md#configuration-files): diff --git a/docs/content_management/field_types/field_type_reference/mediafield.md b/docs/content_management/field_types/field_type_reference/mediafield.md index bbb39c5adf..26e220ccbd 100644 --- a/docs/content_management/field_types/field_type_reference/mediafield.md +++ b/docs/content_management/field_types/field_type_reference/mediafield.md @@ -1,8 +1,8 @@ -# Media Field Type +# Media field type -This Field Type represents and handles a media (audio/video) binary file. +This field type represents and handles a media (audio/video) binary file. -It is capable of handling the following types of files: +It's capable of handling the following types of files: - Apple QuickTime - Adobe Flash @@ -16,14 +16,14 @@ It is capable of handling the following types of files: |---------|---------------|----------------| | `Media` | `ezmedia` | mixed | -## PHP API Field Type  +## PHP API field type  ### Input expectations | Type | Description | Example| |------|-------------|--------| | `string` | Path to the media file.| `/Users/jane/butterflies.mp4` | -| `Ibexa\Core\FieldType\Media\Value` | Media Field Type Value Object with path to the media file as the value of `id` property. | See below. | +| `Ibexa\Core\FieldType\Media\Value` | Media field type value object with path to the media file as the value of `id` property. | See below. | ### Value object @@ -31,7 +31,7 @@ It is capable of handling the following types of files: `Ibexa\Core\FieldType\Media\Value` offers the following properties. -Note that both `Media` and `BinaryFile` Value and Type inherit from the `BinaryBase` abstract Field Type and share common properties. +Both `Media` and `BinaryFile` Value and Type inherit from the `BinaryBase` abstract field type and share common properties. |Property|Type|Description|Example| |------|------|------|------| @@ -65,14 +65,14 @@ The hash format mostly matches the value object. It has the following keys: ### Validation -The Field Type supports `FileSizeValidator`, defining maximum size of media file in bytes: +The field type supports `FileSizeValidator`, defining maximum size of media file in bytes: |Name|Type|Default value|Description| |------|------|------|------| |`maxFileSize`|`int`|`false`|Maximum size of the file in bytes.| ``` php -// Example of using Media Field Type validator in PHP +// Example of using Media field type validator in PHP use Ibexa\Core\FieldType\Media\Type; @@ -89,7 +89,7 @@ $mediaFieldCreateStruct->validatorConfiguration = [ ### Settings -The Field Type supports the `mediaType` setting, defining how the media file should be handled in output. +The field type supports the `mediaType` setting, defining how the media file should be handled in output. |Name|Type|Default value|Description| |------|------|------|------| @@ -108,7 +108,7 @@ List of all available `mediaType` constants is defined in the `Ibexa\Core\Fiel |`TYPE_HTML5_AUDIO`|HTML5 Audio| ``` php -// Example of using Media Field Type settings in PHP +// Example of using Media field type settings in PHP use Ibexa\Core\FieldType\Media\Type;   diff --git a/docs/content_management/field_types/field_type_reference/nullfield.md b/docs/content_management/field_types/field_type_reference/nullfield.md index 9171e2294c..eb00b59224 100644 --- a/docs/content_management/field_types/field_type_reference/nullfield.md +++ b/docs/content_management/field_types/field_type_reference/nullfield.md @@ -1,6 +1,6 @@ -# Null Field Type +# Null field type -This Field Type is used as fallback for migration scenarios, and for testing purposes. +This field type is used as fallback for migration scenarios, and for testing purposes. | Name | Internal name | Expected input type | |--------|---------------|---------------------| @@ -8,18 +8,20 @@ This Field Type is used as fallback for migration scenarios, and for testing pur ## Description -The Null Field Type serves as an aid when migrating from eZ Publish Platform and earlier legacy versions. It is a dummy for legacy Field Types that are not implemented in [[= product_name =]]. +The Null field type serves as an aid when migrating from eZ Publish Platform and earlier legacy versions. +It's a dummy for legacy field types that aren't implemented in [[= product_name =]]. -Null Field Type will accept anything provided as a value and is usually combined with: +Null field type accepts anything provided as a value and is usually combined with: -- NullConverter: Makes it not store anything to the legacy storage engine (database), nor will it read any data. +- NullConverter: Makes it not store anything to the legacy storage engine (database), nor it reads any data. - Unindexed: Indexable class making sure nothing is indexed to configured search engine. -This Field Type does not have its own fixed internal name. Its identifier is instead configured as needed by passing it as an argument to the constructor. +This field type doesn't have its own fixed internal name. +Its identifier is instead configured as needed by passing it as an argument to the constructor. -### Example for usage of Null Field Type +### Example for usage of Null field type -The following example shows how an `example` Field Type could be configured as a Null Field Type: +The following example shows how an `example` field type could be configured as a Null field type: ``` yaml # Null Fieldtype example configuration diff --git a/docs/content_management/field_types/field_type_reference/pagefield.md b/docs/content_management/field_types/field_type_reference/pagefield.md index fd1600083e..fa67799a68 100644 --- a/docs/content_management/field_types/field_type_reference/pagefield.md +++ b/docs/content_management/field_types/field_type_reference/pagefield.md @@ -2,11 +2,12 @@ edition: experience --- -# Page Field Type +# Page field type -Page Field Type represents a Page with a layout consisting of multiple zones. Each zone can in turn contain blocks. +Page field type represents a page with a layout consisting of multiple zones. +Each zone can in turn contain blocks. -Page Field Type is only used in the Page content type that is included in [[= product_name_exp =]]. +Page field type is only used in the page content type that is included in [[= product_name_exp =]]. | Name | Internal name | Expected input | |----------------|-----------------|-----------------| @@ -14,27 +15,29 @@ Page Field Type is only used in the Page content type that is included in [[= pr !!! caution "Page Builder" - If you create content type with both `ezlandingpage` and `ezuser` Field Types, - you will not be redirected to Page Builder after selecting `Edit` or `Create`. - This is caused by `ezuser` Field Type which requires separate handling. You will be redirected to the standard Back Office edit or create mode. + If you create content type with both `ezlandingpage` and `ezuser` field types, you aren't redirected to Page Builder after selecting `Edit` or `Create`. + This is caused by `ezuser` field type which requires separate handling. + You're redirected to the standard back office edit or create mode. ## Layout and zones -Layout defines how a Page is divided into zones. +Layout defines how a page is divided into zones. -The placement of zones is defined in a template which is a part of the layout configuration. You can modify the template in order to define your own zone layout. +The placement of zones is defined in a template which is a part of the layout configuration. +You can modify the template to define your own zone layout. -For information on how to create and configure new blocks for the Page, see [Page layouts](render_page.md#render-a-layout). +For information on how to create and configure new blocks for the page, see [Page layouts](render_page.md#render-a-layout). ## Blocks -For information on how to create and configure new blocks for the Page, see [Create custom Page block](create_custom_page_block.md). +For information on how to create and configure new blocks for the page, see [Create custom Page block](create_custom_page_block.md). -## Rendering Pages +## Rendering pages Page rendering takes place while editing or viewing. -When rendering a Page, its zones are passed to the layout as a `zones` array with a `blocks` array each. You can access them using twig (e.g. `{{ zones[0].id }}` ). +When rendering a page, its zones are passed to the layout as a `zones` array with a `blocks` array each. +You can access them using twig (for example, `{{ zones[0].id }}` ). Each div that's a zone should have the `data-ibexa-zone-id` attribute with zone ID as a value for a zone container. @@ -44,7 +47,7 @@ The `renderAction` has the following parameters: |Parameter|Description| |---------|-----------| -|`locationId`|ID of the Location of the content item which can be accessed by `contentInfo.id`| +|`locationId`|ID of the location of the content item which can be accessed by `contentInfo.id`| |`blockId`|ID of the block which you want to render.| |`versionNo`|Version number of the content item to render.| |`languageCode`|Language code of the content item to render.| diff --git a/docs/content_management/field_types/field_type_reference/relationfield.md b/docs/content_management/field_types/field_type_reference/relationfield.md index 8521f48a97..be684274cb 100644 --- a/docs/content_management/field_types/field_type_reference/relationfield.md +++ b/docs/content_management/field_types/field_type_reference/relationfield.md @@ -1,12 +1,12 @@ -# Relation Field Type +# Relation field type -This Field Type makes it possible to store and retrieve the value of a relation to another content item. +This field type makes it possible to store and retrieve the value of a relation to another content item. | Name | Internal name | Expected input | |------------|--------------------|----------------| | `Relation` | `ezobjectrelation` | mixed | -## PHP API Field Type +## PHP API field type ### Input expectations @@ -19,7 +19,7 @@ This Field Type makes it possible to store and retrieve the value of a relation ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property|Type| Description| |---------|-----|-----------| @@ -33,7 +33,7 @@ $relation->destinationContentId = $contentInfo->id; ##### Constructor -The `Relation\Value` constructor will initialize a new Value object with the value provided. It expects a mixed value. +The `Relation\Value` constructor initializes a new value object with the value provided. It expects a mixed value. ``` php // Constructor example @@ -44,11 +44,11 @@ $relationValue = new Relation\Value( $contentInfo->id ); ### Validation -This Field Type validates whether the provided relation exists, but before that it will check that the value is either a string or an int. +This field type validates whether the provided relation exists, but before that it checks that the value is either a string or an int. ### Settings -The Field definition of this Field Type can be configured with three options: +The field definition of this field type can be configured with three options: |Name|Type|Default value|Description| |------|------|------|------| diff --git a/docs/content_management/field_types/field_type_reference/relationlistfield.md b/docs/content_management/field_types/field_type_reference/relationlistfield.md index 44638a8393..86ef67f760 100644 --- a/docs/content_management/field_types/field_type_reference/relationlistfield.md +++ b/docs/content_management/field_types/field_type_reference/relationlistfield.md @@ -1,12 +1,12 @@ -# RelationList Field Type +# RelationList field type -This Field Type makes it possible to store and retrieve values of a relation to other content items. +This field type makes it possible to store and retrieve values of a relation to other content items. | Name | Internal name | Expected input | |----------------|------------------------|----------------| | `RelationList` | `ezobjectrelationlist` | `mixed` | -## PHP API Field Type  +## PHP API field type  ### Input expectations @@ -15,7 +15,7 @@ This Field Type makes it possible to store and retrieve values of a relation to |`int|string`|ID of the related content item|`42`| |`array`|An array of related Content IDs|`[ 24, 42 ]`| |`Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo`|ContentInfo instance of the related Content|n/a| -|`Ibexa\Core\FieldType\RelationList\Value`|RelationList Field Type Value Object|See below.| +|`Ibexa\Core\FieldType\RelationList\Value`|RelationList field type value object|See below.| ### Value Object @@ -38,7 +38,8 @@ $relationList->destinationContentId = [ ##### Constructor -The `RelationList\Value` constructor will initialize a new Value object with the value provided. It expects a mixed array as value. +The `RelationList\Value` constructor initializes a new value object with the value provided. +It expects a mixed array as value. ``` php //Constructor example @@ -55,20 +56,20 @@ $relationListValue = new RelationList\Value( ### Validation -This Field Type validates if: +This field type validates if: -- the `selectionMethod` specified is `\Ibexa\Core\FieldType\RelationList\Type::SELECTION_BROWSE` or `\Ibexa\Core\FieldType\RelationList\Type::SELECTION_DROPDOWN`. A validation error is thrown if the value does not match. +- the `selectionMethod` specified is `\Ibexa\Core\FieldType\RelationList\Type::SELECTION_BROWSE` or `\Ibexa\Core\FieldType\RelationList\Type::SELECTION_DROPDOWN`. A validation error is thrown if the value doesn't match. - the `selectionDefaultLocation` specified is `null`, `string` or `integer`. If the type validation fails a validation error is thrown. - the value specified in `selectionContentTypes` is an `array`. If not, a validation error in given. -- the number of content items selected in the Field is not greater than the `selectionLimit`. +- the number of content items selected in the field isn't greater than the `selectionLimit`. !!! note - The dropdown selection method is not implemented yet. + The dropdown selection method isn't implemented yet. ### Settings -The Field definition of this Field Type can be configured with the following options: +The field definition of this field type can be configured with the following options: |Name|Type|Default value|Description| |------|------|------|------| @@ -80,14 +81,14 @@ Following selection methods are available: | Name| Description| |-----|------------| -| `SELECTION_BROWSE` | Selection will use browse mode.| +| `SELECTION_BROWSE` | Selection uses browse mode.| | `SELECTION_DROPDOWN` | *Not implemented yet* | ### Validators |Name|Type|Default value|Description| |------|------|------|------| -|`RelationListValueValidator[selectionLimit]`|`integer`|`0`|The number of content items that can be selected in the Field. When set to 0, any number can be selected.| +|`RelationListValueValidator[selectionLimit]`|`integer`|`0`|The number of content items that can be selected in the field. When set to 0, any number can be selected.| ``` php // Example of using settings and validators configuration in PHP diff --git a/docs/content_management/field_types/field_type_reference/richtextfield.md b/docs/content_management/field_types/field_type_reference/richtextfield.md index 67a0414638..c4c5f6e8a1 100644 --- a/docs/content_management/field_types/field_type_reference/richtextfield.md +++ b/docs/content_management/field_types/field_type_reference/richtextfield.md @@ -1,14 +1,14 @@ -# RichText Field Type +# RichText field type -The RichText Field Type is available via the RichText Field Type Bundle provided by the [ibexa/fieldtype-richtext](https://github.com/ibexa/fieldtype-richtext) package. +The RichText field type is available via the RichText field type Bundle provided by the [ibexa/fieldtype-richtext](https://github.com/ibexa/fieldtype-richtext) package. -This Field Type validates and stores structured rich text, and exposes it in several formats. +This field type validates and stores structured rich text, and exposes it in several formats. |Name|Internal name|Expected input| |------|------|------| |`RichText`|`ezrichtext`|mixed| -## PHP API Field Type +## PHP API field type ### Value object @@ -22,19 +22,19 @@ This Field Type validates and stores structured rich text, and exposes it in sev |Type|Description| |------|------| -|`string`|XML document in one of the Field Type's input formats as a string.| -|`DOMDocument`|XML document in one of the Field Type's input formats as a `DOMDocument` object.| -|`Ibexa\FieldTypeRichText\FieldType\RichText\Value`|An instance of the Field Type's `Value` object.| +|`string`|XML document in one of the field type's input formats as a string.| +|`DOMDocument`|XML document in one of the field type's input formats as a `DOMDocument` object.| +|`Ibexa\FieldTypeRichText\FieldType\RichText\Value`|An instance of the field type's `Value` object.| ##### Input formats -The Field Type expects an XML value as input, in the form of a string, `DOMDocument` object, or Field Type's `Value` object. -The Field Type's `Value` object must hold the value in the Field Type's [internal format](#internal-format). -For a string of a `DOMDocument` object, if the input does not conform to this format, it is converted into it. +The field type expects an XML value as input, in the form of a string, `DOMDocument` object, or field type's `Value` object. +The field type's `Value` object must hold the value in the field type's [internal format](#internal-format). +For a string of a `DOMDocument` object, if the input doesn't conform to this format, it's converted into it. ##### Internal format -As its internal format, the RichText Field Type uses a [custom flavor of the DocBook format](#custom-docbook-format). +As its internal format, the RichText field type uses a [custom flavor of the DocBook format](#custom-docbook-format). ``` xml @@ -64,11 +64,9 @@ The XHTML5 format is used by the Online Editor. !!! caution - The custom DocBook format described below is subject to change - and is not covered by backwards compatibility promise. + The custom DocBook format described below is subject to change and isn't covered by backwards compatibility promise. -You can use the [[= product_name_base =]] flavor of the DocBook format in PHP API and in REST API requests -by providing the DocBook content as a string. +You can use the [[= product_name_base =]] flavor of the DocBook format in PHP API and in REST API requests by providing the DocBook content as a string. The following example shows how to pass DocBook content to a [create struct](creating_content.md#creating-content-item-draft): @@ -106,10 +104,10 @@ When creating RichText content with the REST API, use the `xml` key of the `fiel The RichText format enriches [DocBook](https://docbook.org/) with the following custom elements: -- `section` - main element of a RichText Field +- `section` - main element of a RichText field - `ezembed` - holds embedded images - `ezembedinline` - holds embedded content items -- `eztemplate` - holds custom tags, including built-in custom tags for embedded Facebook, Twitter and YouTube content +- `eztemplate` - holds custom tags, including built-in custom tags for embedded Facebook, Twitter, and YouTube content - `eztemplateinline` - holds inline custom tags - `ezconfig` - contains configuration for custom tags and other elements - `ezvalue` - contains values for other elements, such as `ezconfig` or `ezembed` @@ -117,7 +115,7 @@ The RichText format enriches [DocBook](https://docbook.org/) with the following !!! note "Unsupported DocBook elements" - Some DocBook elements are not supported by RichText. + Some DocBook elements aren't supported by RichText. Refer to [`ezpublish.rng`](https://github.com/ibexa/fieldtype-richtext/blob/main/src/bundle/Resources/richtext/schemas/docbook/ezpublish.rng#L137) for a full list. ### Online Editor elements diff --git a/docs/content_management/field_types/field_type_reference/selectionfield.md b/docs/content_management/field_types/field_type_reference/selectionfield.md index 1cb30bb086..bff58da6ab 100644 --- a/docs/content_management/field_types/field_type_reference/selectionfield.md +++ b/docs/content_management/field_types/field_type_reference/selectionfield.md @@ -1,12 +1,12 @@ -# Selection Field Type +# Selection field type -The Selection Field Type stores single selections or multiple choices from a list of options, by populating a hash with the list of selected values. +The Selection field type stores single selections or multiple choices from a list of options, by populating a hash with the list of selected values. | Name | Internal name | Expected input type | |-------------|---------------|---------------------| | `Selection` | `ezselection` | mixed | -## PHP API Field Type +## PHP API field type ### Input expectations @@ -18,7 +18,7 @@ The Selection Field Type stores single selections or multiple choices from a ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |--------------|---------|------------| @@ -47,13 +47,13 @@ $selectionValue = new Selection\Value( [ 1, 2 ] ); ##### String representation -String representation of this Field Type is its list of selections as a string, concatenated with a comma. +String representation of this field type is its list of selections as a string, concatenated with a comma. Example: `"1,2,24,42"` ### Hash format -Hash format of this Field Type is the same as Value object's `selection` property. +Hash format of this field type is the same as value object's `selection` property. ``` php // Example of value in hash format @@ -63,18 +63,19 @@ $hash = [ 1, 2 ]; ### Validation -This Field Type validates the input, verifying if all selected options exist in the Field definition and checks if multiple selections are allowed in the Field definition. -If any of these validations fail, a `ValidationError` is thrown, specifying the error message. When option validation fails, a list with the invalid options is also presented. +This field type validates the input, verifying if all selected options exist in the field definition and checks if multiple selections are allowed in the field definition. +If any of these validations fail, a `ValidationError` is thrown, specifying the error message. +When option validation fails, a list with the invalid options is also presented. ### Settings | Name | Type | Default value | Description| |--------------|-----------|---------------|------------| | `isMultiple` | `boolean` | `false` | Used to allow or prohibit multiple selection from the option list. | -| `options` | `hash` | `[]` | Stores the list of options defined in the Field definition. | +| `options` | `hash` | `[]` | Stores the list of options defined in the field definition. | ``` php -// Selection Field Type example settings +// Selection field type example settings use Ibexa\Core\FieldType\Selection\Type; diff --git a/docs/content_management/field_types/field_type_reference/sesexternaldata.md b/docs/content_management/field_types/field_type_reference/sesexternaldata.md index 70e2ce64ba..e5465c373d 100644 --- a/docs/content_management/field_types/field_type_reference/sesexternaldata.md +++ b/docs/content_management/field_types/field_type_reference/sesexternaldata.md @@ -1,19 +1,19 @@ # SesExternalData -Field Type `sesexternaldatatype` uses external storage to store data. +Field type `sesexternaldatatype` uses external storage to store data. The data is stored in the `ses_externaldata` table with the following structure: |Field|Type|Description| |--- |--- |--- | |`sku`|char(40)|Unique ID of the Product category (CatalogElement).| -|`identifier`|char(40)|ID of the Field.| +|`identifier`|char(40)|ID of the field.| |`language_code`|char(8)|Language code, for example, `ger-DE`.| |`ses_field_type`|char(20)|The data type used for this data.| |`content`|longtext|Serialized data in string format.| ## Storing data in `ses_externaldata` -Data that is stored in the `ses_externaldata` table must be either a simple datatype: int, float, bool or a Field Type. +Data that is stored in the `ses_externaldata` table must be either a simple datatype: int, float, bool, or a field type. -Field Type data is stored in the database in serialized form by using the `toHash()` method. +Field type data is stored in the database in serialized form by using the `toHash()` method. Simple data types (int, float, bool) are stored in serialized form. diff --git a/docs/content_management/field_types/field_type_reference/sesprofiledata.md b/docs/content_management/field_types/field_type_reference/sesprofiledata.md index 05c8226b87..c836bbd15b 100644 --- a/docs/content_management/field_types/field_type_reference/sesprofiledata.md +++ b/docs/content_management/field_types/field_type_reference/sesprofiledata.md @@ -1,11 +1,11 @@ # SesProfileData -This Field Type stores [`CustomerProfileData`] in the User content type. +This field type stores [`CustomerProfileData`] in the User content type. `CustomerProfileData` must be stored as a serialized string in base64 format, -because it is impossible to store special HTML characters (`<`,`>`, `""`,`''`, `&`) in a text or text area field. +because it's impossible to store special HTML characters (`<`,`>`, `""`,`''`, `&`) in a text or text area field. The name of the customer (taken from the contact section) can be used for lists. To do it, use the name pattern in the content type definition of the User content type. -`customer_profile_data` is the identifier of the Field where the profile data is stored. +`customer_profile_data` is the identifier of the field where the profile data is stored. diff --git a/docs/content_management/field_types/field_type_reference/sesselection.md b/docs/content_management/field_types/field_type_reference/sesselection.md index 5c8690751c..b978a19e71 100644 --- a/docs/content_management/field_types/field_type_reference/sesselection.md +++ b/docs/content_management/field_types/field_type_reference/sesselection.md @@ -1,12 +1,11 @@ # SesSelection -This Field Type stores a single selection choice. +This field type stores a single selection choice. -The SesSelection Field Type is configured in a YAML file, -unlike the [Selection Field Type](selectionfield.md). -This way, you can set up SiteAccess-specific selection Field Types. +The SesSelection field type is configured in a YAML file, unlike the [Selection field type](selectionfield.md). +This way, you can set up SiteAccess-specific selection field types. -The Field Type must be configured per attribute: +The field type must be configured per attribute: ``` yaml ibexa.commerce.site_access.config.core.default.sesselection.news_type: @@ -18,6 +17,6 @@ ibexa.commerce.site_access.config.core.default.sesselection.news_type: culture: culture ``` -The `translation_context` key, which identifies the context used for translating the labels, is optional. +The `translation_context` key, which identifies the context used for translating the labels, is optional. -To add a SesSelection Field to a content type, make sure the Field's identifier is the same as the configuration key (in the example above, `news_type`). +To add a SesSelection field to a content type, make sure the field's identifier is the same as the configuration key (in the example above, `news_type`). diff --git a/docs/content_management/field_types/field_type_reference/specificationstype.md b/docs/content_management/field_types/field_type_reference/specificationstype.md index 291d126dea..205526c3b6 100644 --- a/docs/content_management/field_types/field_type_reference/specificationstype.md +++ b/docs/content_management/field_types/field_type_reference/specificationstype.md @@ -1,10 +1,10 @@ # SpecificationsType -This Field Type stores a structured list of attributes for products. +This field type stores a structured list of attributes for products. !!! caution "Field naming" - A Field of the SpecificationsType must have `ses_specifications` as its Field identifier. + A field of the SpecificationsType must have `ses_specifications` as its field identifier. The data is stored in JSON format. diff --git a/docs/content_management/field_types/field_type_reference/taxonomyentryassignmentfield.md b/docs/content_management/field_types/field_type_reference/taxonomyentryassignmentfield.md index d8bc3e71fc..d7e96e85fe 100644 --- a/docs/content_management/field_types/field_type_reference/taxonomyentryassignmentfield.md +++ b/docs/content_management/field_types/field_type_reference/taxonomyentryassignmentfield.md @@ -1,21 +1,21 @@ -# TaxonomyEntryAssignment Field Type +# TaxonomyEntryAssignment field type -`TaxonomyEntryAssignment` Field is used to integrate content with the Taxonomy module. -It allows you to select tags or categories and assign them to content. -This Field Type assigns tags to the content in the data action, so then you can use `TaxonomyService` on this content item. +`TaxonomyEntryAssignment` field is used to integrate content with the Taxonomy module. +It allows you to select tags or categories and assign them to content. +This field type assigns tags to the content in the data action, so then you can use `TaxonomyService` on this content item. !!! caution "Duplicate taxonomy fields" - Because tags are assigned per content item, not per Field, you cannot use two **Taxonomy Entry Assignment** Fields with the same taxonomy type in one content type. + Because tags are assigned per content item, not per field, you cannot use two **Taxonomy Entry Assignment** fields with the same taxonomy type in one content type. -To be able to assign tags to the content, first, you need to add a `TaxonomyEntryAssignment` Field to the content type definition. +To be able to assign tags to the content, first, you need to add a `TaxonomyEntryAssignment` field to the content type definition. | Name | Internal name | Expected input | |--------------------------|----------------------------------|----------------| | `TaxonomyEntryAssignment`| `ibexa_taxonomy_entry_assignment`| array with `taxonomyEntries` and `taxonomy` keys| -## PHP API Field Type  +## PHP API field type  ### Input expectations @@ -33,7 +33,7 @@ new \Ibexa\Taxonomy\FieldType\TaxonomyEntryAssignment\Value( $taxonomyEntry2, // ... ], - 'tags', + 'tags', ); ``` @@ -52,7 +52,7 @@ Example using array: |Property|Type|Description| |--------|----|-----------| |`taxonomyEntry`|array of `Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry`|Stores selected taxonomy entry.| -|`taxonomy`|`string`|Stores the taxonomy identifier, all `taxonomyEntries` have to be assigned to this taxonomy and the identifier has to match the settings of the Field Type in content type configuration.| +|`taxonomy`|`string`|Stores the taxonomy identifier, all `taxonomyEntries` have to be assigned to this taxonomy and the identifier has to match the settings of the field type in content type configuration.| #### Constructor @@ -60,8 +60,8 @@ The constructor accepts `taxonomyEntries` and `taxonomy` as described above. #### String representation -If the Field has no entries - empty string. -If the Field has entries (for example: "Cars and 5 more") - a string displaying the first taxonomy entry and the number of rest of the entries. +If the field has no entries - empty string. +If the field has entries (for example: "Cars and 5 more") - a string displaying the first taxonomy entry and the number of rest of the entries. #### Hash format @@ -72,7 +72,7 @@ An array of: #### Validation -The Field Type validates if all Taxonomy Entries from the value are assigned to the configured taxonomy. +The field type validates if all Taxonomy Entries from the value are assigned to the configured taxonomy. #### Settings diff --git a/docs/content_management/field_types/field_type_reference/taxonomyentryfield.md b/docs/content_management/field_types/field_type_reference/taxonomyentryfield.md index 8e7f2bcfa2..911ae9cff5 100644 --- a/docs/content_management/field_types/field_type_reference/taxonomyentryfield.md +++ b/docs/content_management/field_types/field_type_reference/taxonomyentryfield.md @@ -1,17 +1,17 @@ -# TaxonomyEntry Field Type +# TaxonomyEntry field type -`TaxonomyEntry` is a general purpose Field Type that can store only one taxonomy entry (for example, tag or product category). -It is used as a parent for a tag or category. +`TaxonomyEntry` is a general purpose field type that can store only one taxonomy entry (for example, tag or product category). +It's used as a parent for a tag or category. | Name | Internal name | Expected input | |----------------|-----------------------|----------------| | `TaxonomyEntry`| `ibexa_taxonomy_entry`| `array`| -## PHP API Field Type  +## PHP API field type  ### Input expectations -A `TaxonomyEntry` Field accepts an array with an `Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry` object. +A `TaxonomyEntry` field accepts an array with an `Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry` object. | Type | Description | Example | |--------|-----------------|-----------------| @@ -69,7 +69,7 @@ No validation. #### Settings -The Field definition of this Field Type can be configured with the following options: +The field definition of this field type can be configured with the following options: |Name|Type|Default value|Description| |------|------|------|------| diff --git a/docs/content_management/field_types/field_type_reference/textblockfield.md b/docs/content_management/field_types/field_type_reference/textblockfield.md index 4950e6a5e5..7c1ed868d3 100644 --- a/docs/content_management/field_types/field_type_reference/textblockfield.md +++ b/docs/content_management/field_types/field_type_reference/textblockfield.md @@ -1,12 +1,12 @@ -# TextBlock Field Type +# TextBlock field type -The Field Type handles a block of multiple lines of unformatted text. It is capable of handling up to 16,777,216 characters. +The field type handles a block of multiple lines of unformatted text. It's capable of handling up to 16,777,216 characters. | Name | Internal name | Expected input type | |-------------|---------------|---------------------| | `TextBlock` | `eztext` | `string` | -## PHP API Field Type +## PHP API field type ### Input expectations @@ -18,11 +18,11 @@ The Field Type handles a block of multiple lines of unformatted text. It is cap ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: |Property|Type|Description| |--------|----|-----------| -|`$text`|`string`|This property will be used for the text content.| +|`$text`|`string`|This property is used for the text content.| ##### String representation @@ -30,11 +30,12 @@ A TextBlock's string representation is the `$text` property's value, as a string ##### Constructor -The constructor for this Value object will initialize a new Value object with the value provided. It accepts a string as argument and will import it to the `$text` attribute. +The constructor for this value object initializes a new value object with the value provided. +It accepts a string as argument and imports it to the `$text` attribute. ### Validation -This Field Type does not perform any special validation of the input value. +This field type doesn't perform any special validation of the input value. ### Settings diff --git a/docs/content_management/field_types/field_type_reference/textlinefield.md b/docs/content_management/field_types/field_type_reference/textlinefield.md index 6863df8529..4b2e252344 100644 --- a/docs/content_management/field_types/field_type_reference/textlinefield.md +++ b/docs/content_management/field_types/field_type_reference/textlinefield.md @@ -1,22 +1,23 @@ -# TextLine Field Type +# TextLine field type -This Field Type makes possible to store and retrieve a single line of unformatted text. It is capable of handling up to 255 characters. +This field type makes possible to store and retrieve a single line of unformatted text. +It's capable of handling up to 255 characters. | Name | Internal name | Expected input type | |------------|---------------|---------------------| | `TextLine` | `ezstring` | `string` | -## PHP API Field Type +## PHP API field type ### Value object ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |----------|----------|------------| -| `$text` | `string` | This property will be used for the text content. | +| `$text` | `string` | This property is used for the text content. | ##### String representation @@ -24,12 +25,15 @@ A TextLine's string representation is the `$text` property's value, as a string. ##### Constructor -The constructor for this Value object will initialize a new Value object with the value provided. It accepts a string as argument and will import it to the `$text` attribute. +The constructor for this value object initializes a new value object with the value provided. +It accepts a string as argument and imports it to the `$text` attribute. ### Validation -The input passed into this Field Type is subject to validation by the `StringLengthValidator`. The length of the string provided must be between the minimum length defined in `minStringLength` and the maximum defined in `maxStringLength`. The default value for both properties is 0, which means that the validation is disabled by default. -To set the validation properties, the `validateValidatorConfiguration()` method needs to be inspected, which will receive an array with `minStringLength` and `maxStringLength` like in the following representation: +The input passed into this field type is subject to validation by the `StringLengthValidator`. +The length of the string provided must be between the minimum length defined in `minStringLength` and the maximum defined in `maxStringLength`. +The default value for both properties is 0, which means that the validation is disabled by default. +To set the validation properties, the `validateValidatorConfiguration()` method needs to be inspected, which receives an array with `minStringLength` and `maxStringLength` like in the following representation: ``` Array diff --git a/docs/content_management/field_types/field_type_reference/timefield.md b/docs/content_management/field_types/field_type_reference/timefield.md index ca69490f4e..370d836f7a 100644 --- a/docs/content_management/field_types/field_type_reference/timefield.md +++ b/docs/content_management/field_types/field_type_reference/timefield.md @@ -1,6 +1,6 @@ -# Time Field Type +# Time field type -This Field Type represents time information. +This field type represents time information. Date information is **not stored**. @@ -10,13 +10,13 @@ What is stored is the number of seconds, calculated from the beginning of the da |--------|---------------|---------------------| | `Time` | `eztime` | mixed | -## PHP API Field Type +## PHP API field type ### Input expectations -If input value is of type `string` or `integer`, it will be passed directly to the [PHP's built-in `\DateTime` class](https://www.php.net/manual/en/datetime.construct.php) constructor, therefore the same input format expectations apply. +If input value is of type `string` or `integer`, it's passed directly to the [PHP's built-in `\DateTime` class](https://www.php.net/manual/en/datetime.construct.php) constructor, therefore the same input format expectations apply. -It is also possible to directly pass an instance of `\DateTime`. +It's also possible to directly pass an instance of `\DateTime`. |Type|Example| |------|------| @@ -28,7 +28,7 @@ It is also possible to directly pass an instance of `\DateTime`. ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |----------|----------------|------------| @@ -36,11 +36,12 @@ The Value class of this Field Type contains the following properties: ##### Constructor -The constructor for this Value object will initialize a new Value object with the value provided. It accepts an integer representing the number of seconds since the beginning of the day. +The constructor for this value object initializes a new value object with the value provided. +It accepts an integer representing the number of seconds since the beginning of the day. ##### String representation -String representation of the date value will generate the date string in the format "H:i:s" as accepted by [PHP's built-in `date()` function](https://www.php.net/manual/en/function.date.php). +String representation of the date value generates the date string in the format "H:i:s" as accepted by [PHP's built-in `date()` function](https://www.php.net/manual/en/function.date.php). |Character|Description|Example| |---------|----------|--------| @@ -58,11 +59,11 @@ Example: `36000` ### Validation -This Field Type does not perform validation of the input value. +This field type doesn't perform validation of the input value. ### Settings -The Field definition of this Field Type can be configured with several options: +The Field definition of this field type can be configured with several options: |Name|Type|Default value|Description| |------|------|------|------| @@ -70,7 +71,7 @@ The Field definition of this Field Type can be configured with several options: |`defaultType`|`Type::DEFAULT_EMPTY Type::DEFAULT_CURRENT_TIME`|`Type::DEFAULT_EMPTY`|The constant used here defines default input value when using back-end interface.| ``` php -// Time Field Type example settings +// Time field type example settings use Ibexa\Core\FieldType\Time\Type; $settings = [ @@ -80,11 +81,11 @@ $settings = [ ## Template rendering -The template called by [the `ibexa_render_field()` Twig function](field_twig_functions.md#ibexa_render_field) while rendering a Date Field has access to the following parameters: +The template called by [the `ibexa_render_field()` Twig function](field_twig_functions.md#ibexa_render_field) while rendering a Date field has access to the following parameters: | Parameter | Type | Default | Description| |-----------|----------|---------|------------| -| `locale` | `string` |   n/a | Internal parameter set by the system based on current request locale or, if not set, calculated based on the language of the Field. | +| `locale` | `string` |   n/a | Internal parameter set by the system based on current request locale or, if not set, calculated based on the language of the field. | Example: diff --git a/docs/content_management/field_types/field_type_reference/urlfield.md b/docs/content_management/field_types/field_type_reference/urlfield.md index 340940566a..b9ead6f12c 100644 --- a/docs/content_management/field_types/field_type_reference/urlfield.md +++ b/docs/content_management/field_types/field_type_reference/urlfield.md @@ -1,12 +1,13 @@ -# URL Field Type +# URL field type -This Field Type makes it possible to store and retrieve a URL. It is formed by the combination of a link and the respective text. +This field type makes it possible to store and retrieve a URL. +It's formed by the combination of a link and the respective text. | Name | Internal name | Expected input | |-------|---------------|----------------| | `Url` | `ezurl` | `string` | -## PHP API Field Type +## PHP API field type ### Input expectations @@ -19,12 +20,12 @@ This Field Type makes it possible to store and retrieve a URL. It is formed by t ##### Properties -The Value class of this Field Type contains the following properties: +The Value class of this field type contains the following properties: | Property | Type | Description| |----------|----------|------------| -| `$link` | `string` | This property stores the link provided to the value of this Field Type. | -| `$text` | `string` | This property stores the text to represent the stored link provided to the value of this Field Type. | +| `$link` | `string` | This property stores the link provided to the value of this field type. | +| `$text` | `string` | This property stores the text to represent the stored link provided to the value of this field type. | ``` php // Value object content example @@ -35,7 +36,8 @@ $url->text = "Ibexa"; ##### Constructor -The `Url\Value` constructor initializes a new Value object with the provided value. It expects two comma-separated strings, corresponding to the link and text. +The `Url\Value` constructor initializes a new value object with the provided value. +It expects two comma-separated strings, corresponding to the link and text. ``` php // Constructor example @@ -61,8 +63,8 @@ $hash = [ ### Validation -This Field Type does not perform validation. +This field type doesn't perform validation. ### Settings -This Field Type does not have settings. +This field type doesn't have settings. diff --git a/docs/content_management/field_types/field_type_reference/userfield.md b/docs/content_management/field_types/field_type_reference/userfield.md index eb338db903..e1ffad6c99 100644 --- a/docs/content_management/field_types/field_type_reference/userfield.md +++ b/docs/content_management/field_types/field_type_reference/userfield.md @@ -1,14 +1,14 @@ -# User Field Type +# User field type -This Field Type validates and stores information about a user. +This field type validates and stores information about a user. | Name | Internal name | Expected input | |--------|---------------|----------------| | `User` | `ezuser` | ignored | -## PHP API Field Type +## PHP API field type -### Value Object +### Value object |Property|Type|Description|Example| |------|------|------|------| @@ -30,9 +30,11 @@ This Field Type validates and stores information about a user. !!! caution - Old password hash types like MD5 have numerical hash type value from 1 to 5. These types were deprecated in v1.13 and removed in v3.0. + Old password hash types like MD5 have numerical hash type value from 1 to 5. + These types were deprecated in v1.13 and removed in v3.0. Between v1.13 and v3.0 it was possible to update hashes automatically when users logged in. - Since v3.0, login is only possible with hash type 6 or larger. Automatic updates of older types on login are not possible anymore. + Since v3.0, login is only possible with hash type 6 or larger. + Automatic updates of older types on login aren't possible anymore. A mass migration of all hashes has never been possible, because this would require knowing the passwords, which only users themselves do. Users who still have an old, unsupported password hash type can request a new, valid password using the "Forgot password" feature. diff --git a/docs/content_management/field_types/field_type_search.md b/docs/content_management/field_types/field_type_search.md index 2b5601eede..63c511aa2b 100644 --- a/docs/content_management/field_types/field_type_search.md +++ b/docs/content_management/field_types/field_type_search.md @@ -1,23 +1,25 @@ --- -description: To be searchable, a Field Type must implement the Indexable interface. +description: To be searchable, a field type must implement the Indexable interface. --- -# Field Type searching +# Field type searching -Fields, or a custom Field Type, might contain or maintain data relevant for user searches. -To make the search engine aware of the data in your Field Type you need to implement an additional interface and register the implementation. +Fields, or a custom field type, might contain or maintain data relevant for user searches. +To make the search engine aware of the data in your field type you need to implement an additional interface and register the implementation. ## `Indexable` interface -The `Ibexa\Contracts\Core\FieldType\Indexable` interface defines the methods below which are required if the Field Type provides data relevant to search engines. +The `Ibexa\Contracts\Core\FieldType\Indexable` interface defines the methods below which are required if the field type provides data relevant to search engines. ### `getIndexData(Field $field, FieldDefinition $fieldDefinition)` -This method returns the actual index data for the provided `Ibexa\Contracts\Core\Persistence\Content\Field`. The index data consists of an array of `Ibexa\Contracts\Core\Search\Field` instances. They are described below in further detail. +This method returns the actual index data for the provided `Ibexa\Contracts\Core\Persistence\Content\Field`. +The index data consists of an array of `Ibexa\Contracts\Core\Search\Field` instances. +They're described below in further detail. ### `getIndexDefinition()` -To be able to query data properly an indexable Field Type also is required to return search specification. You must return an associative array of `Ibexa\Contracts\Core\Search\FieldType` instances from this method, which could look like: +To be able to query data properly an indexable field type also is required to return search specification. You must return an associative array of `Ibexa\Contracts\Core\Search\FieldType` instances from this method, which could look like: ``` [ @@ -26,19 +28,25 @@ To be able to query data properly an indexable Field Type also is required to re ] ``` -This example from the `Url` Field Type shows that the Field Type will always return two indexable values, both strings. They have the names `url` and `text` respectively. +This example from the `Url` field type shows that the field type always returns two indexable values, both strings. +They have the names `url` and `text` respectively. ### `getDefaultMatchField()` -This method retrieves the name of the default Field to be used for matching. As Field Types can index multiple Fields (see [MapLocation](maplocationfield.md) Field Type's implementation of this interface), this method is used to define the default field for matching. The default Field is typically used by the [`Field` Search Criterion](field_criterion.md). +This method retrieves the name of the default field to be used for matching. +As field types can index multiple fields (see [MapLocation](maplocationfield.md) field type's implementation of this interface), this method is used to define the default field for matching. +Default field is typically used by the [`Field` Search Criterion](field_criterion.md). ### `getDefaultSortField()` -This method gets name of the default Field to be used for sorting. As Field Types can index multiple Fields (see [MapLocation](maplocationfield.md) Field Type's implementation of this interface), this method is used to define default field for sorting. Default Field is typically used by the [`Field` Sort Clause](field_sort_clause.md). +This method gets name of the default field to be used for sorting. +As field types can index multiple fields (see [MapLocation](maplocationfield.md) field type's implementation of this interface), this method is used to define default field for sorting. +Default field is typically used by the [`Field` Sort Clause](field_sort_clause.md). ## Register `Indexable` implementations -Implement `Ibexa\Contracts\Core\FieldType\Indexable` as an extra service and register this Service using the `ibexa.field_type.indexable` tag. Example from [`indexable_fieldtypes.yaml`](https://github.com/ibexa/core/blob/main/src/lib/Resources/settings/indexable_fieldtypes.yml): +Implement `Ibexa\Contracts\Core\FieldType\Indexable` as an extra service and register this Service using the `ibexa.field_type.indexable` tag. +Example from [`indexable_fieldtypes.yaml`](https://github.com/ibexa/core/blob/main/src/lib/Resources/settings/indexable_fieldtypes.yml): ``` yaml Ibexa\Core\FieldType\Keyword\SearchField: @@ -47,52 +55,55 @@ Ibexa\Core\FieldType\Keyword\SearchField: - {name: ibexa.field_type.indexable, alias: ezkeyword} ``` -Note that `alias` should be the same as Field Type ID. +The `alias` should be the same as field type ID. -## Search Field values +## Search field values -The search Field values returned by the `getIndexData` method are simple value objects consisting of the following properties: +The search field values returned by the `getIndexData` method are simple value objects consisting of the following properties: |Property|Description| |--------|-----------| |`$name`|The name of the field| |`$value`|The value of the field| -|`$type`|An `Ibexa\Contracts\Core\Search\FieldType` instance, describing the type information of the Field.| +|`$type`|An `Ibexa\Contracts\Core\Search\FieldType` instance, describing the type information of the field.| -## Search Field Types +## Search field types -There are many available search Field Types which are handled by search backend configuration. When using them, there is no need to adapt, for example, the Solr configuration in any way. You can always use custom Field Types, but these might require re-configuration of the search backend. For Solr this would mean adapting the `schema.xml` file. +There are many available search field types which are handled by search backend configuration. +When using them, there is no need to adapt, for example, the Solr configuration in any way. +You can always use custom field types, but these might require re-configuration of the search backend. For Solr this would mean adapting the `schema.xml` file. -The default available search Field Types that can be found in the `Ibexa\Contracts\Core\Search\FieldType` namespace are: +The default available search field types that can be found in the `Ibexa\Contracts\Core\Search\FieldType` namespace are: -|Field Type|Description| +|Field type|Description| |--------|-----------| |`BooleanField`|Boolean values.| -|`CustomField`|Custom Field, for custom search data types. Will probably require additional configuration in the search backend.| +|`CustomField`|Custom field, for custom search data types. Probably requires additional configuration in the search backend.| |`DateField`|Date field. Can be used for date range queries.| |`DocumentField`|Document field| |`FloatField`|Field for floating point numbers.| -|`FullTextField`|Represents full text searchable value of the Field which can be indexed by the legacy search engine. Some full text Fields are stored as an array of strings.| -|`GeoLocationField`|Field used for Geo Location.| -|`IdentifierField`|Field used for IDs. Basically acts like the string Field, but will not be queried by fulltext searches| +|`FullTextField`|Represents full text searchable value of the field which can be indexed by the legacy search engine. Some full text fields are stored as an array of strings.| +|`GeoLocationField`|Field used for Geo location.| +|`IdentifierField`|Field used for IDs. Basically acts like the string field, but it's not queried by fulltext searches| |`IntegerField`|Field for integer numbers.| |`MultipleBooleanField`|Multiple boolean values.| |`MultipleIdentifierField`|Multiple IDs values.| |`MultipleIntegerField`|Multiple integer numbers.| |`MultipleStringField`|Multiple string values.| |`PriceField`|Field for price values. Currency conversion might be applied by the search backends. Might require careful configuration.| -|`StringField`|Standard string values. Will also be queries by full text searches.| -|`TextField`|Standard text values. Will be queried by full text searches. Configured text normalizations in the search backend apply.| +|`StringField`|Standard string values. It's also queried by full text searches.| +|`TextField`|Standard text values. It's queried by full text searches. Configured text normalizations in the search backend apply.| ## Configuring Solr As mentioned before, if you use the standard type definitions, there is no need to configure the search backend in any way. -The Field definitions are handled using `dynamicField` definitions in Solr, for example. +The field definitions are handled using `dynamicField` definitions in Solr, for example. -If you want to configure the handling of your Field, you can always add a special Field definition to the Solr `schema.xml`. For Fields, the Field Type names used by the Solr search backend look like this: `//_`. +If you want to configure the handling of your field, you can always add a special field definition to the Solr `schema.xml`. +For fields, the field type names used by the Solr search backend look like this: `//_`. You can define custom `dynamicField` definitions to match, for example, on your custom `_` definition. -You could also define a custom Field definition for certain Fields, like for the name Field in an article: +You could also define a custom field definition for certain fields, like for the name field in an article: ``` diff --git a/docs/content_management/field_types/field_type_storage.md b/docs/content_management/field_types/field_type_storage.md index 4ae1510ce1..2e2aa0f5a8 100644 --- a/docs/content_management/field_types/field_type_storage.md +++ b/docs/content_management/field_types/field_type_storage.md @@ -1,38 +1,38 @@ --- -description: To be able to store the data saved to a Field, you must configure storage conversion for the Field Type. +description: To be able to store the data saved to a field, you must configure storage conversion for the field type. --- -# Field Type storage +# Field type storage ## Storage conversion -If you want to store Field values in regular [[= product_name =]] database tables, +If you want to store field values in regular [[= product_name =]] database tables, the `FieldValue` must be converted to the storage-specific format used by the Persistence SPI: `Ibexa\Contracts\Core\Persistence\Content\FieldValue`. -After restoring a Field of the Field Type, you must reverse the conversion. +After restoring a field of the field type, you must reverse the conversion. -The following methods of the Field Type are responsible for that: +The following methods of the field type are responsible for that: |Method|Description| |------|-----------| -|`toPersistenceValue()`|This method receives the value of a Field of the Field Type and returns an SPI `FieldValue`, which can be stored.| -|`fromPersistenceValue()`|This method receives an SPI `FieldValue` and reconstructs the original value of the Field from it.| +|`toPersistenceValue()`|This method receives the value of a field of the field type and returns an SPI `FieldValue`, which can be stored.| +|`fromPersistenceValue()`|This method receives an SPI `FieldValue` and reconstructs the original value of the field from it.| -The SPI `FieldValue` struct has properties which the Field Type can use: +The SPI `FieldValue` struct has properties which the field type can use: |Property|Description| |--------|-----------| |`$data`|The data to be stored in the database. This may be a scalar value, an associative array or a simple, serializable object.| -|`$externalData`|The arbitrary data stored in this field will not be touched by any of the [[= product_name =]] components directly, but will be available for [Storing data externally](#storing-data-externally).| -|`$sortKey`|A value which can be used to sort content by this Field.| +|`$externalData`|The arbitrary data stored in this field isn't touched by any of the [[= product_name =]] components directly, but is available for [Storing data externally](#storing-data-externally).| +|`$sortKey`|A value which can be used to sort content by this field.| ### Legacy storage engine -The Legacy storage engine uses the `ezcontentobject_attribute` table to store Field values, -and `ezcontentclass_attribute` to store Field definition values. -They are both based on the same principle. +The Legacy storage engine uses the `ezcontentobject_attribute` table to store field values, +and `ezcontentclass_attribute` to store field definition values. +They're both based on the same principle. -Each row represents a Field or a Field definition, and offers several free fields of different types, where the type can store its data e.g. +Each row represents a field or a field definition, and offers several free fields of different types, where the type can store its data. - `ezcontentobject_attribute` offers: - `data_int` @@ -45,12 +45,13 @@ Each row represents a Field or a Field definition, and offers several free field Each type is free to use those fields in any way it requires. -The default Legacy storage engine cannot store arbitrary value information as provided by a Field Type. +The default Legacy storage engine cannot store arbitrary value information as provided by a field type. This means that using this storage engine requires a conversion. -Converters will map a Field's semantic values to the fields described above, for both settings (validation and configuration) and value. +Converters map a field's semantic values to the fields described above, for both settings (validation and configuration) and value. The conversion takes place through the `Ibexa\Core\Persistence\Legacy\Content\FieldValue\Converter` interface, -which you must implement in your Field Type. The interface contains the following methods: +which you must implement in your field type. +The interface contains the following methods: |Method|Description| |------|-----------| @@ -79,50 +80,47 @@ The tag has the following attribute: | Attribute name | Usage | |----------------|-------| -| `alias` | Represents the `fieldTypeIdentifier` (just like for the [Field Type service](type_and_value.md#registration)). | +| `alias` | Represents the `fieldTypeIdentifier` (like for the [field type service](type_and_value.md#registration)). | !!! tip - Converter configuration for built-in Field Types is located in [`ibexa/core/src/lib/Resources/settings/fieldtype_external_storages.yml`](https://github.com/ibexa/core/blob/main/src/lib/Resources/settings/fieldtype_external_storages.yml). + Converter configuration for built-in field types is located in [`ibexa/core/src/lib/Resources/settings/fieldtype_external_storages.yml`](https://github.com/ibexa/core/blob/main/src/lib/Resources/settings/fieldtype_external_storages.yml). ## Storing data externally -A Field Type may store arbitrary data in external data sources. -External storage can be e.g. a web service, a file in the file system, another database -or even the [[= product_name =]] database itself (in form of a non-standard table). +A field type may store arbitrary data in external data sources. +External storage can be, for example, a web service, a file in the file system, another database or even the [[= product_name =]] database itself (in form of a non-standard table). -In order to store data in external storage, the Field Type will interact with the Persistence SPI -through the `Ibexa\Contracts\Core\FieldType\FieldStorage` interface. +To store data in external storage, the field type interacts with the Persistence SPI through the `Ibexa\Contracts\Core\FieldType\FieldStorage` interface. -Accessing the internal storage of a content item that includes a Field of the Field Type -calls one of the following methods to also access the external data: +Accessing the internal storage of a content item that includes a field of the field type calls one of the following methods to also access the external data: |Method|Description| |------|-----------| -|`hasFieldData()`|Returns whether the Field Type stores external data at all.| -|`storeFieldData()`|Called right before a Field of the Field Type is stored. The method stores `$externalData`. It returns `true` if the call manipulated internal data of the given Field, so that it is updated in the internal database.| -|`getFieldData()`|Called after a Field has been restored from the database in order to restore `$externalData`.| -|`deleteFieldData()`|Must delete external data for the given Field, if exists.| +|`hasFieldData()`|Returns whether the field type stores external data at all.| +|`storeFieldData()`|Called right before a field of the field type is stored. The method stores `$externalData`. It returns `true` if the call manipulated internal data of the given field, so that it's updated in the internal database.| +|`getFieldData()`|Called after a field has been restored from the database to restore `$externalData`.| +|`deleteFieldData()`|Must delete external data for the given field, if exists.| |`getIndexData()`|Returns the actual index data for the provided `Ibexa\Contracts\Core\Persistence\Content\Field`. For more information, see [search service](field_type_search.md#search-field-values).| Each of the above methods (except `hasFieldData`) receives a `$context` array with information on the underlying storage and the environment. -To retrieve and store data in the [[= product_name =]] data storage, -but outside of the normal structures (e.g. a custom table in an SQL database), -use [Gateway-based storage](#gateway-based-storage) with properly injected Doctrine Connection. +To retrieve and store data in the [[= product_name =]] data storage, but outside of the normal structures (for example, a custom table in an SQL database), use [Gateway-based storage](#gateway-based-storage) with properly injected Doctrine Connection. -Note that the Field Type must take care on its own for being compliant with different data sources and that third parties can extend the data source support easily. +The field type must take care on its own for being compliant with different data sources and that third parties can extend the data source support. ### Gateway-based storage -In order to allow the usage of a Field Type that uses external data with different data storages, it is recommended to implement a gateway infrastructure and a registry for the gateways. To make this easier, the Core implementation of Field Types provides corresponding interfaces and base classes. They can also be used for custom Field Types. +To allow the usage of a field type that uses external data with different data storages, it's recommended to implement a gateway infrastructure and a registry for the gateways. +To make this easier, the Core implementation of field types provides corresponding interfaces and base classes. +They can also be used for custom field types. -The interface `Ibexa\Contracts\Core\FieldType\StorageGateway` is implemented by gateways, in order to be handled correctly by the registry. It has one method: +The interface `Ibexa\Contracts\Core\FieldType\StorageGateway` is implemented by gateways, to be handled correctly by the registry. It has one method: |Method|Description| |------|-----------| -|`setConnection()`|The registry mechanism uses this method to set the SPI storage connection (e.g. the database connection to the Legacy Storage database) into the gateway, which might be used to store external data. The connection is retrieved from the `$context` array automatically by the registry.| +|`setConnection()`|The registry mechanism uses this method to set the SPI storage connection (for example, the database connection to the Legacy Storage database) into the gateway, which might be used to store external data. The connection is retrieved from the `$context` array automatically by the registry.| -Note that the Gateway implementation itself must take care of validating that it received a usable connection. If it does not, it should throw a `RuntimeException`. +The Gateway implementation itself must take care of validating that it received a usable connection. If it doesn't, it should throw a `RuntimeException`. The registry mechanism is realized as a base class for `FieldStorage` implementations: `Ibexa\Core\FieldType\GatewayBasedStorage`. For managing `StorageGateway`s, the following methods are already implemented in the base class: @@ -133,14 +131,14 @@ The registry mechanism is realized as a base class for `FieldStorage` implementa !!! tip - Refer to the built-in Keyword, URL and User Field Types for usages of such infrastructure. + Refer to the built-in Keyword, URL and User field types for usages of such infrastructure. ### Registering external storage To use external storage, you need to define a service implementing the `Ibexa\Contracts\Core\FieldType\FieldStorage` interface -and tag it as `ibexa.field_type.storage.external.handler` to be recognized by the Repository. +and tag it as `ibexa.field_type.storage.external.handler` to be recognized by the repository. -Here is an example for the `myfield` Field Type: +Here is an example for the `myfield` field type: ``` yaml services: @@ -156,7 +154,7 @@ services: The configuration requires providing the `ibexa.field_type.storage.external.handler` tag, with the `alias` attribute being the *fieldTypeIdentifier*. You also have to inject the gateway in `arguments`, [see Gateway-based storage](#gateway-based-storage). -External storage configuration for basic Field Types is located in [`ibexa/core/src/lib/Resources/settings/fieldtype_external_storages.yml`](https://github.com/ibexa/core/blob/main/src/lib/Resources/settings/fieldtype_external_storages.yml). +External storage configuration for basic field types is located in [`ibexa/core/src/lib/Resources/settings/fieldtype_external_storages.yml`](https://github.com/ibexa/core/blob/main/src/lib/Resources/settings/fieldtype_external_storages.yml). Using gateway-based storage requires another service implementing `Ibexa\Core\FieldType\StorageGateway` to be injected into the [external storage handler](#storing-data-externally)). @@ -170,41 +168,35 @@ services: App\FieldType\MyField\Storage\Gateway\DoctrineStorage: ~ ``` -Note that `ibexa.api.storage_engine.legacy.connection` is of type `Doctrine\DBAL\Connection`. If your gateway still uses an implementation of `eZ\Publish\Core\Persistence\Database\DatabaseHandler` (`eZ\Publish\Core\Persistence\Doctrine\ConnectionHandler`), instead of the `ibexa.api.storage_engine.legacy.connection`, you can pass the `ibexa.api.storage_engine.legacy.dbhandler` service. +The `ibexa.api.storage_engine.legacy.connection` is of type `Doctrine\DBAL\Connection`. If your gateway still uses an implementation of `eZ\Publish\Core\Persistence\Database\DatabaseHandler` (`eZ\Publish\Core\Persistence\Doctrine\ConnectionHandler`), instead of the `ibexa.api.storage_engine.legacy.connection`, you can pass the `ibexa.api.storage_engine.legacy.dbhandler` service. -Also note that there can be several gateways per Field Type (one per storage engine). In this case it's recommended to either create base implementation which each gateway can inherit or create interface which each gateway must implement and reference it instead of specific implementation when type-hinting method arguments. +Also there can be several gateways per field type (one per storage engine). +In this case it's recommended to either create base implementation which each gateway can inherit or create interface which each gateway must implement and reference it instead of specific implementation when type-hinting method arguments. !!! tip - Gateway configuration for built-in Field Types is located in [`core/src/lib/Resources/settings/storage_engines/`](https://github.com/ibexa/core/tree/main/src/lib/Resources/settings/storage_engines). + Gateway configuration for built-in field types is located in [`core/src/lib/Resources/settings/storage_engines/`](https://github.com/ibexa/core/tree/main/src/lib/Resources/settings/storage_engines). -## Storing Field Type settings externally +## Storing field type settings externally -Just like in the case of data, storing [Field Type settings](type_and_value.md#field-type-settings) -in content item tables may prove insufficient. -It is not a problem if your setting specifies, for example, just the allowed number of characters -in a text field. -However, the Field Type may represent a more complex object, for example, it may -consist of two or more other fields, such as the name, SKU and price, and there -can be a set of default values instead of just one. +Just like in the case of data, storing [field type settings](type_and_value.md#field-type-settings) in content item tables may prove insufficient. +It's not a problem if your setting specifies, for example, the allowed number of characters in a text field. +However, the field type may represent a more complex object, for example, it may consist of two or more other fields, such as the name, SKU, and price, and there can be a set of default values instead of just one. Once you add validation rules for these field values, then it becomes an issue. - -You can overcome this obstacle: -When you create a new Field Type, you can move Field Type settings -to external storage. - + +You can overcome this obstacle: +When you create a new field type, you can move field type settings to external storage. + !!! note - - Another benefit of an external storage is that there can be database relations to - other objects/entities, and the database itself can maintain the integrity of data. - -First, create a class that implements the -`Ibexa\Contracts\Core\FieldType\FieldConstraintsStorage` interface. - -Then, register the External Storage as a service and tag it with `ibexa.field_type.external_constraints_storage`. -Make sure that the alias you use matches the identifier of the new Field Type: - + + Another benefit of an external storage is that there can be database relations to other objects/entities, and the database itself can maintain the integrity of data. + +First, create a class that implements the `Ibexa\Contracts\Core\FieldType\FieldConstraintsStorage` interface. + +Then, register the External Storage as a service and tag it with `ibexa.field_type.external_constraints_storage`. +Make sure that the alias you use matches the identifier of the new field type: + ``` yaml services: App\FieldType\Example\ExternalStorage: diff --git a/docs/content_management/field_types/field_type_validation.md b/docs/content_management/field_types/field_type_validation.md index dd4f777b46..8faab59a9c 100644 --- a/docs/content_management/field_types/field_type_validation.md +++ b/docs/content_management/field_types/field_type_validation.md @@ -1,8 +1,8 @@ --- -description: Field Type validation allows you to validate if data entered stored in the Field conforms to the schema. +description: Field type validation allows you to validate if data entered stored in the field conforms to the schema. --- -# Field Type validation +# Field type validation ## Validator schema @@ -12,7 +12,7 @@ except it has an additional level, to group settings for a certain validation me - The key on the 1st level is a string, identifying a validator - Assigned to that is an associative array (2nd level) of settings - This associative array has a string key for each setting of the validator -- It is assigned to a 3rd level associative array, the setting description +- It's assigned to a 3rd level associative array, the setting description - This associative array should have the same format as for normal settings For example, for the `ezstring` type, the validator schema could be: diff --git a/docs/content_management/field_types/field_types.md b/docs/content_management/field_types/field_types.md index c7f5d8b17f..08706cfa90 100644 --- a/docs/content_management/field_types/field_types.md +++ b/docs/content_management/field_types/field_types.md @@ -1,52 +1,50 @@ --- -description: Field Types define the Fields that a content item is built of. +description: Field types define the fields that a content item is built of. --- -# Field Types +# Field types -Field Types are the smallest building blocks of content. -[[= product_name =]] comes with many [built-in Field Types](field_type_reference.md#available-field-types) that cover most common needs e.g. Text line, Email address, Author list, Content relation, Map location, Float, etc. +Field types are the smallest building blocks of content. +[[= product_name =]] comes with many [built-in field types](field_type_reference.md#available-field-types) that cover most common needs, for example, Text line, Email address, Author list, Content relation, Map location, or Float. -Field Types are responsible for: +Field types are responsible for: - Storing data, either using the native storage engine mechanisms or specific means - Validating input data - Making the data searchable (if applicable) -- Displaying Fields of this type +- Displaying fields of this type ## Custom data -[[= product_name =]] can support custom data to be stored in the Fields of a content item. -To do so, you need to create a custom Field Type. +[[= product_name =]] can support custom data to be stored in the fields of a content item. +To do so, you need to create a custom field type. -A custom Field Type must implement the **FieldType Service Provider Interfaces** +A custom field type must implement the **FieldType Service Provider Interfaces** available in the [`Ibexa\Core\FieldType`](https://github.com/ibexa/core/tree/main/src/lib/FieldType) namespace. !!! note "Registration" - Remember that all your custom Field Types must be registered in `config/services.yml`. - For more information see [Registration](type_and_value.md#registration). + Remember that all your custom field types must be registered in `config/services.yml`. + For more information, see [Registration](type_and_value.md#registration). -In order to provide custom functionality for a Field Type, the SPI interacts with multiple layers of the [[= product_name =]] architecture: +To provide custom functionality for a field type, the SPI interacts with multiple layers of the [[= product_name =]] architecture: -![Field Type Overview](field_type_overview.png) +![Field type Overview](field_type_overview.png) -On the top layer, the Field Type needs to provide conversion from and to a simple PHP hash value to support the **REST API**. The generated hash value may only consist of scalar values and hashes. It must not contain objects or arrays with numerical indexes that aren't sequential and/or don't start with zero. +On the top layer, the field type needs to provide conversion from and to a simple PHP hash value to support the **REST API**. The generated hash value may only consist of scalar values and hashes. It must not contain objects or arrays with numerical indexes that aren't sequential and/or don't start with zero. [[= include_file('docs/snippets/simple_hash_value_caution.md') =]] -Below that, the Field Type must support the **public PHP API** implementation regarding: +Below that, the field type must support the **public PHP API** implementation regarding: - Settings definition for `FieldDefinition` - Value creation and validation - Communication with the Persistence SPI -On the bottom level, a Field Type can additionally hook into the **Persistence SPI** -in order to store data from a `FieldValue` in an external service. -Note that all non-standard [[= product_name =]] database tables (e.g. `ezurl`) -are treated as [external storage](field_type_storage.md#storing-data-externally). +On the bottom level, a field type can additionally hook into the **Persistence SPI** to store data from a `FieldValue` in an external service. +All non-standard [[= product_name =]] database tables (for example, `ezurl`) are treated as [external storage](field_type_storage.md#storing-data-externally). -The following sequence diagrams visualize the process of creating and publishing new content across all layers, especially focused on the interaction with a Field Type. +The following sequence diagrams visualize the process of creating and publishing new content across all layers, especially focused on the interaction with a field type. ## Creating content @@ -56,8 +54,8 @@ The following sequence diagrams visualize the process of creating and publishing !!! note "indexLocation()" - For **Solr** Locations are indexed during Content indexing. - For **Legacy/SQL** indexing is not required as Location data already exists in a database. + For **Solr** locations are indexed during Content indexing. + For **Legacy/SQL** indexing isn't required as location data already exists in a database. ![Publish content sequence](publish_content_sequence.png) diff --git a/docs/content_management/field_types/form_and_template.md b/docs/content_management/field_types/form_and_template.md index 2e0e8576af..3adf4d98d2 100644 --- a/docs/content_management/field_types/form_and_template.md +++ b/docs/content_management/field_types/form_and_template.md @@ -1,24 +1,24 @@ --- -description: Field Type FormMappers allow Field editing, while custom templates ensure the Field can be rendered both in the Back office and on site front. +description: Field type FormMappers allow field editing, while custom templates ensure the field can be rendered both in the back office and on site front. --- # Form and template ## FormMapper -The FormMapper maps Field definitions into Symfony forms, allowing Field editing. +The FormMapper maps field definitions into Symfony forms, allowing field editing. It can implement two interfaces: - `Ibexa\Contracts\ContentForms\FieldType\FieldValueFormMapperInterface` to provide editing support -- `Ibexa\AdminUi\FieldType\FieldDefinitionFormMapperInterface` to provide Field Type definition editing support, +- `Ibexa\AdminUi\FieldType\FieldDefinitionFormMapperInterface` to provide field type definition editing support, when you require non-standard settings ### FieldValueFormMapperInterface The `FieldValueFormMapperInterface::mapFieldValueForm` method accepts two arguments: -- `FormInterface` — form for the current Field +- `FormInterface` — form for the current field - `FieldData` — underlying data for current field form You have to add your form type to the content editing form. The example shows how `ezboolean` injects the form: @@ -55,9 +55,9 @@ public function mapFieldValueForm(FormInterface $fieldForm, FieldData $data) Your type has to be called `value`. In the example above, `CheckboxFieldType::class` is used, but you can use standard Symfony form type instead. -It's good practice to encapsulate Fields with custom types as it allows easier templating. -Type has to be compatible with your Field Type's `Ibexa\Core\FieldType` implementation. -You can use a [`DataTransformer`]([[= symfony_doc =]]/form/data_transformers.html) to achieve that or just assure correct property and form field names. +It's good practice to encapsulate fields with custom types as it allows easier templating. +Type has to be compatible with your field type's `Ibexa\Core\FieldType` implementation. +You can use a [`DataTransformer`]([[= symfony_doc =]]/form/data_transformers.html) to achieve that or assure correct property and form field names. ### FieldDefinitionFormMapperInterface @@ -98,7 +98,7 @@ public function mapFieldDefinitionForm(FormInterface $fieldDefinitionForm, Field } ``` -Use names corresponding to the keys used in Field Type's `Ibexa\Core\FieldType\FieldType::$settingsSchema` implementation. +Use names corresponding to the keys used in field type's `Ibexa\Core\FieldType\FieldType::$settingsSchema` implementation. The special `defaultValue` key allows you to specify a field for setting the default value assigned during content editing. ### Registering the service @@ -115,13 +115,13 @@ App\FieldType\Mapper\CustomFieldTypeMapper: Tag the mapper according to the support you need to provide: - Add the `ibexa.admin_ui.field_type.form.mapper.value` tag when providing content editing support (`FieldValueFormMapperInterface` interface). -- Add the `ibexa.admin_ui.field_type.form.mapper.definition` tag when providing Field Type definition editing support (`FieldDefinitionFormMapperInterface` interface). -The `fieldType` key has to correspond to the name of your Field Type. +- Add the `ibexa.admin_ui.field_type.form.mapper.definition` tag when providing field type definition editing support (`FieldDefinitionFormMapperInterface` interface). +The `fieldType` key has to correspond to the name of your field type. ## Content view templates -To render the Field in content view by using the [`ibexa_render_field()` Twig helper](field_twig_functions.md#ibexa_render_field), -you need to define a template containing a block for the Field. +To render the field in content view by using the [`ibexa_render_field()` Twig helper](field_twig_functions.md#ibexa_render_field), +you need to define a template containing a block for the field. ``` html+twig {% block customfieldtype_field %} @@ -134,12 +134,10 @@ By convention, your block must be named `_field`. !!! tip - Template blocks for built-in Field Types are available in - [`Core/Resources/views/content_fields.html.twig`](https://github.com/ibexa/core/blob/main/src/bundle/Core/Resources/views/content_fields.html.twig). + Template blocks for built-in field types are available in [`Core/Resources/views/content_fields.html.twig`](https://github.com/ibexa/core/blob/main/src/bundle/Core/Resources/views/content_fields.html.twig). This template is also exposed as a part of Standard Design, so you can override it with the [design engine](design_engine.md). - To do so, place the template `themes/standard/content_fields.html.twig` in your `Resources/views` - (assuming `ibexa_standard_design.override_kernel_templates` is set to true). + To do so, place the template `themes/standard/content_fields.html.twig` in your `Resources/views` (assuming `ibexa_standard_design.override_kernel_templates` is set to true). ### Template variables @@ -148,15 +146,15 @@ The block can receive the following variables: | Name | Type | Description | |------|------|-------------| | `field` | `Ibexa\Contracts\Core\Repository\Values\Content\Field` | The field to display | -| `contentInfo` | `Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo` | The ContentInfo of the content item the Field belongs to | -| `versionInfo` | `Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo` | The VersionInfo of the content item the Field belongs to | -| `fieldSettings` | array | Settings of the Field (depends on the Field Type) | +| `contentInfo` | `Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo` | The ContentInfo of the content item the field belongs to | +| `versionInfo` | `Ibexa\Contracts\Core\Repository\Values\Content\VersionInfo` | The VersionInfo of the content item the field belongs to | +| `fieldSettings` | array | Settings of the field (depends on the field type) | | `parameters` | hash | Options passed to `ibexa_render_field()` under the `'parameters'` key | | `attr` | hash | The attributes to add the generate the HTML markup, passed to ibexa_render_field()` under the `'attr'` key.
Contains at least a class entry, containing -field | ### Reusing blocks -For easier Field Type template development you can take advantage of all defined blocks by using the [`block()` function](https://twig.symfony.com/doc/3.x/functions/block.html). +For easier field type template development you can take advantage of all defined blocks by using the [`block()` function](https://twig.symfony.com/doc/3.x/functions/block.html). You can for example use `simple_block_field`, `simple_inline_field` or `field_attributes` blocks provided in [`content_fields.html.twig`](https://github.com/ibexa/core/blob/main/src/bundle/Core/Resources/views/content_fields.html.twig#L486). @@ -166,7 +164,7 @@ You can for example use `simple_block_field`, `simple_inline_field` or `field_at ### Registering a template -If you don't use the [design engine](design_engine.md) or you want to have separate templates per Field Type and/or SiteAccess, +If you don't use the [design engine](design_engine.md) or you want to have separate templates per field type and/or SiteAccess, you can register a template under the `ibexa.system..field_templates` [configuration key](configuration.md#configuration-files): ``` yaml @@ -180,15 +178,15 @@ ibexa: priority: 10 ``` -## Back Office templates +## Back office templates -### Back Office view template +### Back office view template -For templates for previewing the Field in the Back Office, +For templates for previewing the field in the back office, using the design engine is recommended with `ibexa_standard_design.override_kernel_templates` set to `true`. -With the design engine you can apply a template (e.g. `Resources/views/themes/admin/content_fields.html.twig`) without any extra configuration. +With the design engine you can apply a template (for example, `Resources/views/themes/admin/content_fields.html.twig`) without any extra configuration. -If you do not use the design engine, apply the following configuration: +If you don't use the design engine, apply the following configuration: ``` yaml ibexa: @@ -200,7 +198,7 @@ ibexa: ### Field edit template -To use a template for the Field edit form in the Back Office, you need to specify it in configuration +To use a template for the field edit form in the back office, you need to specify it in configuration under the `twig.form_themes` [configuration key](configuration.md#configuration-files): ``` yaml @@ -210,7 +208,7 @@ twig: ``` We encourage using custom form types for encapsulation as this makes templating easier by providing Twig block name. -All built-in Field Types are implemented with this approach. In that case overriding form theme can be done with: +All built-in field types are implemented with this approach. In that case overriding form theme can be done with: ``` html+twig {% block custom_fieldtype_widget %} @@ -219,6 +217,4 @@ All built-in Field Types are implemented with this approach. In that case overri {% endblock %} ``` -!!! tip - - For more information on creating and overriding form type templates, see [Symfony documentation]([[= symfony_doc =]]/form/create_custom_field_type.html#creating-the-form-type-template). +For more information on creating and overriding form type templates, see [Symfony documentation]([[= symfony_doc =]]/form/create_custom_field_type.html#creating-the-form-type-template). diff --git a/docs/content_management/field_types/type_and_value.md b/docs/content_management/field_types/type_and_value.md index 539b7d19c5..9b71d0dd08 100644 --- a/docs/content_management/field_types/type_and_value.md +++ b/docs/content_management/field_types/type_and_value.md @@ -1,84 +1,99 @@ --- -description: The basis of all Field Types are their Type and Value classes, containing, respectively, the logic and the data for the Fields. +description: The basis of all field types are their Type and Value classes, containing, respectively, the logic and the data for the fields. --- # Type and Value -A Field Type must contain a Type class which contains the logic of the Field Type: validating data, transforming from various formats, describing the validators, etc. -A Type class must implement `Ibexa\Core\FieldType\FieldType` ("Field Type interface"). -All native Field Types also extend the `Ibexa\Core\FieldType\FieldType` abstract class that implements this interface and provides implementation facilities through a set of abstract methods of its own. +A field type must contain a Type class which contains the logic of the field type, for example, validating data, transforming from various formats, or describing the validators. +A Type class must implement `Ibexa\Core\FieldType\FieldType` ("field type interface"). +All native field types also extend the `Ibexa\Core\FieldType\FieldType` abstract class that implements this interface and provides implementation facilities through a set of abstract methods of its own. -You should also provide a value object class for storing the custom Field value provided by the Field Type. -The Value is used to represent an instance of the Field Type within a content item. -Each Field presents its data using an instance of the Type's Value class. +You should also provide a value object class for storing the custom field value provided by the field type. +The Value is used to represent an instance of the field type within a content item. +Each field presents its data using an instance of the Type's Value class. A Value class must implement the `Ibexa\Contracts\Core\FieldType` interface. It may also extend the `Ibexa\Core\FieldType\Value` abstract class. -It is meant to be stateless and as lightweight as possible. +It's meant to be stateless and as lightweight as possible. This class must contain as little logic as possible, because the logic is handled by the Type class. ## Type class -The Type class of a Field Type provides an implementation of the [`Ibexa\Contracts\Core\FieldType\FieldType`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-FieldType-FieldType.html) interface. +The Type class of a field type provides an implementation of the [`Ibexa\Contracts\Core\FieldType\FieldType`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-FieldType-FieldType.html) interface. ### Field Definition handling -A custom Field Type is used in a Field definition of a custom content type. -You can additionally provide [settings for the Field Type](#field-type-settings) and a [validator configuration](field_type_validation.md). -Since the public PHP API cannot know anything about these, their handling is delegated to the Field Type itself through the following methods: +A custom field type is used in a field definition of a custom content type. +You can additionally provide [settings for the field type](#field-type-settings) and a [validator configuration](field_type_validation.md). +Since the public PHP API cannot know anything about these, their handling is delegated to the field type itself through the following methods: #### `getFieldTypeIdentifier()` -Returns a unique identifier for the custom Field Type which is used to assign the type to a Field definition. -By convention it should be prefixed by a unique vendor shortcut (e.g. `ibexa` for [[= product_name =]]). +Returns a unique identifier for the custom field type which is used to assign the type to a field definition. +By convention it should be prefixed by a unique vendor shortcut (for example, `ibexa` for [[= product_name =]]). #### `getSettingsSchema()` -This method retrieves via public PHP API a schema for the Field Type settings. A typical setting would be e.g. default value. The settings structure defined by this schema is stored in the `FieldDefinition`. Since it is not possible to define a generic format for such a schema, the Field Type is free to return any serializable data structure from this method. +This method retrieves via public PHP API a schema for the field type settings. +A typical setting would be, for example, default value. +The settings structure defined by this schema is stored in the `FieldDefinition`. +Since it's not possible to define a generic format for such a schema, the field type is free to return any serializable data structure from this method. #### `getValidatorConfigurationSchema()` -In addition to normal settings, the Field Type should provide schema settings for its validation process. The schema describes what kind of validation can be performed by the Field Type and which settings the user can specify to these validation methods. For example, the `ezstring` type can validate minimum and maximum length of the string. It therefore provides a schema to indicate to the user that they might specify the corresponding restrictions, when creating a `FieldDefinition` with this type. The schema does not underlie any regulations, except for that it must be serializable. +In addition to normal settings, the field type should provide schema settings for its validation process. +The schema describes what kind of validation can be performed by the field type and which settings the user can specify to these validation methods. +For example, the `ezstring` type can validate minimum and maximum length of the string. +It therefore provides a schema to indicate to the user that they might specify the corresponding restrictions, when creating a `FieldDefinition` with this type. +The schema doesn't underlie any regulations, except for that it must be serializable. #### `validateFieldSettings()` -The type is asked to validate the settings (provided by the user) before the public PHP API stores those settings for the Field Type in a `FieldDefinition`. As a result, the Field Type must return if the given settings comply to the schema defined by `getSettingsSchema()`. +The type is asked to validate the settings (provided by the user) before the public PHP API stores those settings for the field type in a `FieldDefinition`. +As a result, the field type must return if the given settings comply to the schema defined by `getSettingsSchema()`. #### `validateValidatorConfiguration()` As in `validateFieldSettings()`, this method verifies that the given validator configuration complies to the schema provided by `getValidatorConfigurationSchema()`. -It is important to note that the schema definitions of the Field Type can be both of arbitrary and serializable format. It is highly recommended to use a simple hash structure. +It's important to know that the schema definitions of the field type can be both of arbitrary and serializable format. +It's highly recommended to use a simple hash structure. !!! note - Since it is not possible to enforce a schema format, the code using a specific Field Type must basically know all Field Types it deals with. + Since it's not possible to enforce a schema format, the code using a specific field type must basically know all field types it deals with. -This also applies to all user interfaces and the REST API, which therefore must provide extension points to register handling code for custom Field Type. These extensions are not defined yet. +This also applies to all user interfaces and the REST API, which therefore must provide extension points to register handling code for custom field type. +These extensions aren't defined yet. -### Field Type name +### Field type name The content item name is retrieved by the `Ibexa\Core\FieldType\FieldType::getName` method which must be implemented. -To generate content item name or URL alias the Field Type name must be a part of a name schema or a URL schema. +To generate content item name or URL alias the field type name must be a part of a name schema or a URL schema. ## Value handling -A Field Type needs to deal with the custom value format provided by it. In order for the public PHP API to work properly, it delegates working with such custom Field values to the corresponding Field Type. The `Ibexa\Core\FieldType\FieldType` interface therefore provides the following methods: +A field type needs to deal with the custom value format provided by it. +In order for the public PHP API to work properly, it delegates working with such custom field values to the corresponding field type. +The `Ibexa\Core\FieldType\FieldType` interface therefore provides the following methods: #### `acceptValue()` -This method is responsible for accepting and converting user input for the Field. It checks the input structure by accepting, building, and returning a different structure holding the data. +This method is responsible for accepting and converting user input for the field. +It checks the input structure by accepting, building, and returning a different structure holding the data. -For example: a user provides an HTTP link as a string, `acceptValue()` converts the link to a URL Field Type value object. Unlike the `FieldType\Value` constructor, it is possible to make this method aware of multiple input types (object or primitive). +For example: a user provides an HTTP link as a string, `acceptValue()` converts the link to a URL field type value object. +Unlike the `FieldType\Value` constructor, it's possible to make this method aware of multiple input types (object or primitive). !!! note - `acceptValue()` asserts structural consistency of the value, but does not validate plausibility of the value. + `acceptValue()` asserts structural consistency of the value, but doesn't validate plausibility of the value. #### `getEmptyValue()` -The Field Type can specify that the user may define a default value for the `Field` of the type through settings. If no default value is provided, the Field Type is asked for an "empty value" as the final fallback. +The field type can specify that the user may define a default value for the `Field` of the type through settings. +If no default value is provided, the field type is asked for an "empty value" as the final fallback. -The value chain for filling a specific Field of the Field Type is as follows: +The value chain for filling a specific field of the field type is as follows: 1. Is a value provided by the filling user? 2. If not, is a default value provided by the`FieldDefinition`? @@ -87,27 +102,29 @@ The value chain for filling a specific Field of the Field Type is as follows: #### `validate()` In contrast to `acceptValue()` this method validates the plausibility of the given value. -It is based on the Field Type settings and validator configuration and stored in the corresponding `FieldDefinition`. +It's based on the field type settings and validator configuration and stored in the corresponding `FieldDefinition`. ### Serialization -When [REST API](rest_api_usage.md) is used, conversion needs to be done for Field Type values, settings and validator configurations. These are converted to and from a simple hash format that can be encoded in REST payload. As conversion needs to be done both when transmitting and receiving data through REST, Field Type implements the following pairs of methods: +When [REST API](rest_api_usage.md) is used, conversion needs to be done for field type values, settings, and validator configurations. +These are converted to and from a simple hash format that can be encoded in REST payload. +As conversion needs to be done both when transmitting and receiving data through REST, field type implements the following pairs of methods: |Method|Description| |------|-----------| -|`toHash()`|Converts Field Type Value into a simple hash format.| +|`toHash()`|Converts field type Value into a simple hash format.| |`fromHash()`|Converts the other way around.| -|`fieldSettingsToHash()`|Converts Field Type settings to a simple hash format.| +|`fieldSettingsToHash()`|Converts field type settings to a simple hash format.| |`fieldSettingsFromHash()`|Converts the other way around.| -|`validatorConfigurationToHash()`|Converts Field Type validator configuration to a simple hash format.| +|`validatorConfigurationToHash()`|Converts field type validator configuration to a simple hash format.| |`validatorConfigurationFromHash()`|Converts the other way around.| [[= include_file('docs/snippets/simple_hash_value_caution.md') =]] ## Registration -The Field Type must be registered in `config/services.yml`: - +The field type must be registered in `config/services.yml`: + ``` yaml services: Ibexa\FieldTypeMatrix\FieldType\Type: @@ -118,35 +135,35 @@ services: #### `parent` -As described in the [Symfony service container documentation]([[= symfony_doc =]]/components/dependency_injection/parentservices.html), the `parent` config key indicates that you want your service to inherit from the parent's dependencies, including constructor arguments and method calls. This helps avoiding repetition in your Field Type configuration and keeps consistency between all Field Types. +As described in the [Symfony service container documentation]([[= symfony_doc =]]/components/dependency_injection/parentservices.html), the `parent` config key indicates that you want your service to inherit from the parent's dependencies, including constructor arguments and method calls. +This helps avoiding repetition in your field type configuration and keeps consistency between all field types. If you need to inject other services into your Type class, skip using the `parent` config key. #### `tags` -Like most API components, Field Types use the [Symfony service tag mechanism]([[= symfony_doc =]]/service_container/tags.html). +Like most API components, field types use the [Symfony service tag mechanism]([[= symfony_doc =]]/service_container/tags.html). A service can be assigned one or several tags, with specific parameters. -When the [service container](php_api.md#service-container) is compiled into a PHP file, -tags are read by `CompilerPass` implementations that add extra handling for tagged services. -Each service tagged as `ibexa.field_type` is added to a [registry](https://martinfowler.com/eaaCatalog/registry.html) using the `alias` key as its unique `fieldTypeIdentifier` e.g. `ezstring`. -Each Field Type must also inherit from the abstract `ibexa.field_type` service. -This ensures that the initialization steps shared by all Field Types are executed. +When the [service container](php_api.md#service-container) is compiled into a PHP file, tags are read by `CompilerPass` implementations that add extra handling for tagged services. +Each service tagged as `ibexa.field_type` is added to a [registry](https://martinfowler.com/eaaCatalog/registry.html) using the `alias` key as its unique `fieldTypeIdentifier`, for example, `ezstring`. +Each field type must also inherit from the abstract `ibexa.field_type` service. +This ensures that the initialization steps shared by all field types are executed. !!! tip - The configuration of built-in Field Types is located in [`core/src/lib/Resources/settings/fieldtypes.yml`](https://github.com/ibexa/core/blob/main/src/lib/Resources/settings/fieldtypes.yml). + The configuration of built-in field types is located in [`core/src/lib/Resources/settings/fieldtypes.yml`](https://github.com/ibexa/core/blob/main/src/lib/Resources/settings/fieldtypes.yml). ### Indexing -To make the search engine aware of the data stored in a Field Type, register it as [indexable](field_type_search.md) +To make the search engine aware of the data stored in a field type, register it as [indexable](field_type_search.md) -## Field Type settings +## Field type settings -It is recommended to use a simple associative array format for the settings schema returned by `Ibexa\Contracts\Core\FieldType\FieldType::getSettingsSchema()`, which follows these rules: +It's recommended to use a simple associative array format for the settings schema returned by `Ibexa\Contracts\Core\FieldType\FieldType::getSettingsSchema()`, which follows these rules: -- The key of the associative array identifies a setting (e.g. `default`) +- The key of the associative array identifies a setting (for example, `default`) - Its value is an associative array describing the setting using: - - `type` to identify the setting type (e.g. `int` or `string`) + - `type` to identify the setting type (for example, `int` or `string`) - `default` containing the default setting value An example schema could look like this: @@ -168,12 +185,12 @@ The settings are mapped into Symfony forms via the [FormMapper](form_and_templat !!! note - You can store Field Type settings internally, or, when the schema becomes - too complex, move them to [external storage](field_type_storage.md#storing-field-type-settings-externally). + You can store field type settings internally, or, when the schema becomes too complex, move them to [external storage](field_type_storage.md#storing-field-type-settings-externally). ## Extensibility points -Some Field Types require additional processing, for example a Field Type storing a binary file, or one having more complex settings or validator configuration. For this purpose specific implementations of an abstract class `Ibexa\Contracts\Rest\FieldTypeProcessor` are used. +Some field types require additional processing, for example a field type storing a binary file, or one having more complex settings, or validator configuration. +For this purpose specific implementations of an abstract class `Ibexa\Contracts\Rest\FieldTypeProcessor` are used. This class provides the following methods: @@ -186,4 +203,5 @@ This class provides the following methods: |`preProcessValidatorConfigurationHash()`|Performs manipulations on a received validator configuration hash, so that it conforms to the format expected by the `validatorConfigurationFromHash()` method described above.| |`postProcessValidatorConfigurationHash()`|Performs manipulations on a outgoing validator configuration hash, previously generated by the `validatorConfigurationToHash()` method described above.| -Base implementations of these methods simply return the given hash, so you can implement only the methods your Field Type requires. Some built-in Field Types already implement processors and you are encouraged to take a look at them. +Base implementations of these methods return the given hash, so you can implement only the methods your field type requires. +Some built-in field types already implement processors and you're encouraged to take a look at them. diff --git a/docs/content_management/file_management/binary_and_media_download.md b/docs/content_management/file_management/binary_and_media_download.md index c74c9b6b94..b36349f773 100644 --- a/docs/content_management/file_management/binary_and_media_download.md +++ b/docs/content_management/file_management/binary_and_media_download.md @@ -4,9 +4,9 @@ description: Create route to to enable binary and media files download. # Binary and Media download -You can restrict files stored in BinaryFile or Media Fields to certain user Roles. -These files are not publicly downloadable from disk, and are instead served by Symfony, using a custom route that runs the necessary checks. -This route is automatically generated as the `url` property for those Field values. +You can restrict files stored in BinaryFile or Media fields to certain user roles. +These files aren't publicly downloadable from disk, and are instead served by Symfony, using a custom route that runs the necessary checks. +This route is automatically generated as the `url` property for those field values. ## `content/download` route @@ -21,8 +21,8 @@ The [`ibexa_render_field`](field_twig_functions.md#ibexa_render_field) Twig hel ## Download link generation -To generate a direct download link for a File Field you have to create -a [RouteReference](urls_and_routes.md#routereference) with the `ibexa_route` helper, passing `content` and File Field identifier as parameters. +To generate a direct download link for a File field you have to create +a [RouteReference](urls_and_routes.md#routereference) with the `ibexa_route` helper, passing `content` and File field identifier as parameters. Optional parameter `inLanguage` may be used to specify File content translation. ```html+twig @@ -32,6 +32,6 @@ Optional parameter `inLanguage` may be used to specify File content translation. ## REST API: `uri` property -The `uri` property of Binary Fields in REST contains a valid download URL, of the same format as the public PHP API, prefixed with the same host as the REST Request. +The `uri` property of Binary fields in REST contains a valid download URL, of the same format as the public PHP API, prefixed with the same host as the REST Request. For [more information about REST API see the documentation](rest_api_usage.md). diff --git a/docs/content_management/file_management/file_management.md b/docs/content_management/file_management/file_management.md index cf5f878a59..bedce65245 100644 --- a/docs/content_management/file_management/file_management.md +++ b/docs/content_management/file_management/file_management.md @@ -15,7 +15,7 @@ $fileContent = $this->ioService->getFileContents($file); ## Handling binary files -[[= product_name =]] supports multiple binary file handling mechanisms by means of an `IOHandler` interface. This feature is used by the [BinaryFile](imagefield.md) Field Types. +[[= product_name =]] supports multiple binary file handling mechanisms by means of an `IOHandler` interface. This feature is used by the [BinaryFile](imagefield.md) field types. ### Native IO handler @@ -36,7 +36,7 @@ ibexa: binarydata_handler: nfs ``` -The adapter is the *driver* used by Flysystem v2 to read/write files. Adapters are declared using `oneup_flysystem`. +The adapter is the *driver* used by Flysystem v2 to read/write files. Adapters are declared using `oneup_flysystem`. Metadata and binary data handlers are configured under `ibexa_io`. See below the configuration for the default handlers. It declares a metadata handler and a binary data handler, both labeled `default`. Both handlers are of type `flysystem`, and use the same Flysystem v2 adapter, labeled `default` as well. ``` yaml @@ -81,8 +81,7 @@ Default values: !!! note - As SiteAccess configuration Flysystem's v2 native Local NFS adapter is not supported, the following - configuration should be used: + As SiteAccess configuration Flysystem's v2 native Local NFS adapter isn't supported, the following configuration should be used: ``` yaml oneup_flysystem: @@ -95,14 +94,16 @@ Default values: ### Native Flysystem v2 handler -[[= product_name =]] uses it as the default way to read and write content in form of binary files. Flysystem v2 can use the `local` filesystem, but is also able to read/write to `sftp`, `zip` or cloud filesystems (`azure`, `rackspace`, `S3`). +[[= product_name =]] uses it as the default way to read and write content in form of binary files. +Flysystem v2 can use the `local` filesystem, but is also able to read/write to `sftp`, `zip` or cloud filesystems (`azure`, `rackspace`, `S3`). [league/flysystem](https://flysystem.thephpleague.com/docs/) (along with [FlysystemBundle](https://github.com/1up-lab/OneupFlysystemBundle/)) is an abstract file handling library. #### Handler options ##### Adapter -To be able to rely on dynamic SiteAccess-aware paths, you need to use Ibexa custom `nfs_adapter`. A basic configuration might look like the following: +To be able to rely on dynamic SiteAccess-aware paths, you need to use [[= product_name_base =]] custom `nfs_adapter`. +A basic configuration might look like the following: ``` yaml oneup_flysystem: @@ -112,7 +113,7 @@ oneup_flysystem: service: ibexa.io.nfs.adapter.site_access_aware ``` -To learn how to configure other adapters, see the [bundle's online documentation](https://github.com/1up-lab/OneupFlysystemBundle/blob/main/doc/index.md#step3-configure-your-filesystems). +To learn how to configure other adapters, see the [bundle's online documentation](https://github.com/1up-lab/OneupFlysystemBundle/blob/main/doc/index.md#step3-configure-your-filesystems). !!! note @@ -121,4 +122,6 @@ To learn how to configure other adapters, see the [bundle's online documentation ### DFS Cluster handler For clustering, the platform provides a custom metadata handler that stores metadata about your assets in the database. -This is faster than accessing the remote NFS or S3 instance to read metadata. For further reading on setting this up, see [Clustering](clustering.md). +This is faster than accessing the remote NFS or S3 instance to read metadata. + +For more information, see [Clustering](clustering.md). diff --git a/docs/content_management/file_management/file_url_handling.md b/docs/content_management/file_management/file_url_handling.md index 6de13f9765..6683fd9052 100644 --- a/docs/content_management/file_management/file_url_handling.md +++ b/docs/content_management/file_management/file_url_handling.md @@ -36,7 +36,7 @@ ibexa: !!! caution - For security reasons, do not map `/path/to/ibexa/public/` as + For security reasons, don't map `/path/to/ibexa/public/` as Document Root of the static server. Map the `/var/` directory directly to `/path/to/ibexa/public/var` instead. @@ -49,7 +49,7 @@ Any BinaryFile returned by the public PHP API is prefixed with the value of thi Default value: `$var_dir$/$storage_dir$` Example: `/var/site/storage` -You can use `io.url_prefix` to configure the default URL decorator service (`ibexa.core.io.default_url_decorator`), used by all binary data handlers to generate the URI of loaded files. It is always interpreted as an absolute URI, meaning that unless it contains a scheme (`http://`, `ftp://`), is prepended with a `/`. +You can use `io.url_prefix` to configure the default URL decorator service (`ibexa.core.io.default_url_decorator`), used by all binary data handlers to generate the URI of loaded files. It's always interpreted as an absolute URI, meaning that unless it contains a scheme (`http://`, `ftp://`), is prepended with a `/`. This setting is SiteAccess-aware. @@ -64,6 +64,6 @@ Two implementations are provided: `Prefix`, and `AbsolutePrefix`. They both add Three URL decorator services are introduced: - `Ibexa\Core\IO\UrlDecorator\AbsolutePrefix` used by the binary data handlers to decorate all URIs sent out by the API. Uses `AbsolutePrefix`. -- `Ibexa\Core\IO\UrlDecorator\Prefix` used through the `UrlRedecorator` by various legacy elements (converter, storage gateway, etc.) to generate its internal storage format for URIs. Uses a `Prefix`, not an `AbsolutePrefix`, meaning that no leading `/` is added. +- `Ibexa\Core\IO\UrlDecorator\Prefix` used through the `UrlRedecorator` by various legacy elements (for example, converter or storage gateway) to generate its internal storage format for URIs. Uses a `Prefix`, not an `AbsolutePrefix`, meaning that no leading `/` is added. In addition, a URL redecorator service, `Ibexa\Core\IO\UrlDecorator\Prefix`, uses both previously mentioned decorators to convert URIs between what is used on the new stack, and what format legacy expects (relative URLs from the project root). diff --git a/docs/content_management/forms/create_custom_form_field.md b/docs/content_management/forms/create_custom_form_field.md index eea7376899..3f7d7129a9 100644 --- a/docs/content_management/forms/create_custom_form_field.md +++ b/docs/content_management/forms/create_custom_form_field.md @@ -10,8 +10,7 @@ Define new form fields in configuration. ## Configure Form field -For example, to create a Country Form field in the "Custom form fields" category, -provide the following configuration under the `ibexa_form_builder.fields` [configuration key](configuration.md#configuration-files): +For example, to create a Country Form field in the "Custom form fields" category, provide the following configuration under the `ibexa_form_builder.fields` [configuration key](configuration.md#configuration-files): ``` yaml [[= include_file('code_samples/forms/custom_form_field/config/packages/form_builder.yaml') =]] @@ -28,7 +27,7 @@ Available attribute types are: |`multiple`|Multiple choice| |`select`|Dropdown| |`checkbox`|Checkbox| -|`location`|Content Location| +|`location`|Content location| |`radio`|Radio button| |`action`|Button| |`choices`|List of available options| @@ -62,7 +61,7 @@ Then, register the mapper as a service: [[= include_file('code_samples/forms/custom_form_field/config/custom_services.yaml', 0, 7) =]] ``` -Now you can go to Back Office and build a new form. +Now you can go to back office and build a new form. You should be able to see the new section in the list of available fields: ![Custom form fields](extending_form_builder_custom_form_fields.png) diff --git a/docs/content_management/forms/create_form_attribute.md b/docs/content_management/forms/create_form_attribute.md index e3144cb7bd..c4d7bc506b 100644 --- a/docs/content_management/forms/create_form_attribute.md +++ b/docs/content_management/forms/create_form_attribute.md @@ -1,14 +1,14 @@ --- -description: Create Form Builder Form attribute. +description: Create Form Builder Form attribute. edition: experience --- -# Create Form Builder Form attribute +# Create Form Builder Form attribute You can create a Form attribute for new Form fields or existing ones. To do it, you have to define a new Form attribute in the configuration. -In the following example you will learn how to create the new Form with `richtext_description` attribute that allows you to add formatted +In the following example you can learn how to create the new Form with `richtext_description` attribute that allows you to add formatted description to the Form. ## Configure Form attribute @@ -63,7 +63,8 @@ twig: ## Add scripts -Now you need to enable the Rich Text editor. Provide the required script in a new `assets/js/formbuilder-richtext-checkbox.js` file: +Now you need to enable the Rich Text editor. +Provide the required script in a new `assets/js/formbuilder-richtext-checkbox.js` file: ``` js [[= include_file('code_samples/forms/custom_form_attribute/assets/js/formbuilder-richtext-checkbox.js') =]] @@ -83,9 +84,9 @@ php bin/console assets:install yarn encore dev ``` -## Implement Field +## Implement field -Now you have to implement the Field, and make sure the value from the Rich Text attribute is passed on to the field form. +Now you have to implement the field, and make sure the value from the Rich Text attribute is passed on to the field form. Create a `src/FormBuilder/Form/Type/CheckboxWithRichtextDescriptionType.php` file. @@ -105,7 +106,7 @@ Now, the attribute value can be stored in the new Form. ## Create submission converter -The new Field is based on a checkbox, so to display the submissions of this field, you can use the `BooleanFieldSubmissionConverter`. +The new field is based on a checkbox, so to display the submissions of this field, you can use the `BooleanFieldSubmissionConverter`. Create a `src/FormBuilder/FormSubmission/Converter/RichtextDescriptionFieldSubmissionConverter.php` file. @@ -113,7 +114,7 @@ Create a `src/FormBuilder/FormSubmission/Converter/RichtextDescriptionFieldSubmi [[= include_file('code_samples/forms/custom_form_attribute/src/FormBuilder/FormSubmission/Converter/RichtextDescriptionFieldSubmissionConverter.php') =]] ``` -Now you can go to Back Office and build a new form. +Now you can go to back office and build a new form. In the main menu, click **Content** -> **Forms** -> **Create content**, and select **Form**. You should be able to see the new section in the list of available fields: diff --git a/docs/content_management/forms/customize_email_notifications.md b/docs/content_management/forms/customize_email_notifications.md index acdab4990a..1ad41532f5 100644 --- a/docs/content_management/forms/customize_email_notifications.md +++ b/docs/content_management/forms/customize_email_notifications.md @@ -20,12 +20,12 @@ Each of them is rendered independently and consists of three sets of parameters. |---------|----|-----------| |`content`|`Ibexa\Contracts\Core\Repository\Values\Content\Content`|Name of the form, its content type| |`form`|`Ibexa\Contracts\FormBuilder\FieldType\Model\Form`|Definition of the form| -|`data`|`Ibexa\Contracts\FormBuilder\FieldType\Model\FormSubmission`|Sent data| +|`data`|`Ibexa\Contracts\FormBuilder\FieldType\Model\FormSubmission`|Sent data| ## Configure sender details Some email providers require a sender address to be set, so to avoid unsent emails when using Form Builder, -it is recommended to configure `sender_address` in `config/packages/swiftmailer.yaml`. +it's recommended to configure `sender_address` in `config/packages/swiftmailer.yaml`. This email acts as a sender and return address for all bounced messages. !!! note diff --git a/docs/content_management/forms/form_api.md b/docs/content_management/forms/form_api.md index c5c0c5e3c7..c0c9930445 100644 --- a/docs/content_management/forms/form_api.md +++ b/docs/content_management/forms/form_api.md @@ -11,15 +11,13 @@ To manage form submissions created in the [Form Builder](form_builder_guide.md), ### Getting form submissions -To get existing form submissions, use `FormSubmissionServiceInterface::loadByContent()` -(which takes a `ContentInfo` object as parameter), or `FormSubmissionServiceInterface::loadById()`. +To get existing form submissions, use `FormSubmissionServiceInterface::loadByContent()` (which takes a `ContentInfo` object as parameter), or `FormSubmissionServiceInterface::loadById()`. ``` php [[= include_file('code_samples/api/public_php_api/src/Command/FormSubmissionCommand.php', 54, 55) =]] ``` -Through this object, you can get information about submissions, such as their total number, -and submission contents. +Through this object, you can get information about submissions, such as their total number, and submission contents. ``` php [[= include_file('code_samples/api/public_php_api/src/Command/FormSubmissionCommand.php', 55, 66) =]] @@ -33,7 +31,7 @@ This method takes: - the `ContentInfo` object of the content item containing the form - the language code -- the value of the Field containing the form +- the value of the field containing the form - the array of form field values ``` php diff --git a/docs/content_management/forms/form_builder_guide.md b/docs/content_management/forms/form_builder_guide.md index 00b22a4138..14cf27838f 100644 --- a/docs/content_management/forms/form_builder_guide.md +++ b/docs/content_management/forms/form_builder_guide.md @@ -9,8 +9,8 @@ edition: experience Form Builder is a tool that lets you build forms consisting of different fields. -By adding forms on the website, you can increase its functionality and improve user experience. Use Form Builder to create various forms, such as survey, -questionnaire, sign-up form, using basic form fields available in the Form Builder. +By adding forms on the website, you can increase its functionality and improve user experience. +Use Form Builder to create various forms, such as survey, questionnaire, sign-up form, using basic form fields available in the Form Builder. You can also manage your forms and review the results gathered from the website users. ## Availability @@ -60,21 +60,21 @@ The available basic form fields are: ### Create a form -Editors can use the created form anywhere on the website. -Forms can be used in page blocks, embedded in the online editor or even used as a field relation. +Editors can use the created form anywhere on the website. +Forms can be used in page blocks, embedded in the online editor or even used as a field relation. The same form can be placed at multiple locations on the website. To learn more, see [Work with forms]([[= user_doc =]]/content_management/work_with_forms/). ### Forms management -[Form](work_with_forms.md) is one of available [content items]([[= user_doc =]]/content_management/content_items/) that you can find in the platform. -You can work with it as with other regular items: create new one, edit existing one, move, etc. +[Form](work_with_forms.md) is one of available [content items]([[= user_doc =]]/content_management/content_items/) that you can find in the platform. +You can work with it as with other regular items, for example, create new one, edit existing one, or move. You can manage all the existing forms. To do it, in a selected place of the content tree find your form and click on it. -In this window you can see all the information about your form, view submissions, create versions, etc. +In this window you can see all the information about your form, view submissions, create versions, and more -Using the buttons in the right corner, you can also edit, move, copy, hide or send your form to the trash. +Using the buttons in the right corner, you can also edit, move, copy, hide, or send your form to the trash. ![Forms management](img/forms_management.png) @@ -82,17 +82,17 @@ Using the buttons in the right corner, you can also edit, move, copy, hide or se To manage form submissions created in the Form Builder, use `FormSubmissionServiceInterface`. You can get existing form submission and create or delete one. -Detailed instruction of getting, creating and deleting form submissions, you can find in Ibexa Developer Documentation in [Form API page](form_api.md). +Detailed instruction of getting, creating and deleting form submissions, you can find in [[= product_name_base =]] Developer Documentation in [Form API page](form_api.md). ### Extend Form Builder -You can extend the Form Builder by adding new Form fields or modifying existing ones. -To create new form fields, you need to [define them in configuration](create_custom_form_field.md). +You can extend the Form Builder by adding new Form fields or modifying existing ones. +To create new form fields, you need to [define them in configuration](create_custom_form_field.md). Fields or fields attributes [can be modified](create_custom_form_field.md#modify-existing-form-fields) by subscribing `ibexa.form_builder.field.` or `ibexa.form_builder.field..` events. ### Create new Form attribute -Each Form has available attributes, for example, string, text, location, etc. +Each Form has available attributes, for example, string, text, or location. You can also [create a Form attribute](create_form_attribute.md) for new Form fields or existing ones. To do it, you have to: @@ -102,7 +102,7 @@ To do it, you have to: 1. add Symfony form type, 1. customize Form templates, 1. add scripts, -1. implement Field, +1. implement field, 1. implement field mapper, 1. create submission converter. @@ -121,21 +121,21 @@ The **Download submissions** button enables you to download all the submissions ### General overview -With Form Builder you are allowed to build an unlimited number of forms. -These forms can be used anywhere on the website and are ready to start collecting information. -Form Builder interface is simple, which makes the creation of forms fast and intuitive. +With Form Builder you're allowed to build an unlimited number of forms. +These forms can be used anywhere on the website and are ready to start collecting information. +Form Builder interface is plain, which makes the creation of forms fast and intuitive. ### Forms management -Forms can be managed simply and effectively: you can copy them, move, organize into folders, create versions and delete if necessary. +Forms can be managed simply and effectively: you can copy them, move, organize into folders, create versions, and delete if necessary. Each field can be configured so that the form collects the exact details that you need. ### Custom Form fields -With Form Builder you can use existing Form fields, but also you can extend it by adding new or modifying existing ones. +With Form Builder you can use existing Form fields, but also you can extend it by adding new or modifying existing ones. This allows you to create forms that fit your needs. ### Analytic tool -All the submissions can are visible in Submissions tab. +All the submissions can are visible in **Submissions** tab. You can download them as a .CSV file for additional analysis. \ No newline at end of file diff --git a/docs/content_management/forms/forms.md b/docs/content_management/forms/forms.md index 7bd327a345..663c1dbc27 100644 --- a/docs/content_management/forms/forms.md +++ b/docs/content_management/forms/forms.md @@ -14,5 +14,5 @@ Forms are a type of content item that you can use to improve the functionality o "content_management/forms/form_api", "content_management/forms/create_form_attribute", "content_management/forms/create_custom_form_field", - "content_management/forms/customize_email_notifications" + "content_management/forms/customize_email_notifications", ], columns=3) =]] diff --git a/docs/content_management/forms/work_with_forms.md b/docs/content_management/forms/work_with_forms.md index db65fe60b3..245b1bdea7 100644 --- a/docs/content_management/forms/work_with_forms.md +++ b/docs/content_management/forms/work_with_forms.md @@ -9,8 +9,7 @@ You can build forms consisting of different fields in the Form Builder. !!! tip - To learn how to get, create, and delete form submissions by using the PHP API, - see [Form API](form_api.md). + To learn how to get, create, and delete form submissions by using the PHP API, see [Form API](form_api.md). [[% include 'snippets/forms_caution.md' %]] @@ -32,8 +31,7 @@ gregwar_captcha: reload: true ``` -The example configuration above resizes the Captcha image (line 3), changes the error message (line 4), -and enables the user to reload the code (line 5). +The example configuration above resizes the Captcha image (line 3), changes the error message (line 4), and enables the user to reload the code (line 5). ![Custom captcha field](extending_form_builder_captcha_result.png) @@ -41,31 +39,31 @@ For information about available options, see [Gregwar/CaptchaBundle's documentat !!! note - If your installation uses Varnish to manage content cache, you must modify the configuration to avoid issues with the Captcha field. For more information, see [Ensure proper captcha behavior](reverse_proxy.md#ensure-proper-captcha-behavior). + If your installation uses Varnish to manage content cache, you must modify the configuration to avoid issues with the Captcha field. + For more information, see [Ensure proper captcha behavior](reverse_proxy.md#ensure-proper-captcha-behavior). ## Form submission purging You can purge all submissions of a given form. -To do this, run the following command, where `form-id` stands for Content ID -of the form for which you want to purge data: +To do this, run the following command, where `form-id` stands for Content ID of the form for which you want to purge data: ```bash php bin/console ibexa:form-builder:purge-form-submissions [options] [--] ``` -The following table lists some of the available options and their meaning: +The following table lists some of the available options and their meaning: | Switch | Option | Description | |--------------|------------|------------| | `-l` | `--language-code=LANGUAGE-CODE` | Passes a language code, for example, "eng-GB". | -| `-u` | `--user[=USER]` | Passes a repository username. By default it is "admin". | -| `-c` | `--batch-size[=BATCH-SIZE]` | Passes a number of URLs to check in a single iteration. Set it to avoid using too much memory. By default it is set to 50. | +| `-u` | `--user[=USER]` | Passes a repository username. By default it's "admin". | +| `-c` | `--batch-size[=BATCH-SIZE]` | Passes a number of URLs to check in a single iteration. Set it to avoid using too much memory. By default it's set to 50. | | | `--siteaccess[=SITEACCESS]` | Passes a SiteAccess to use for operations. If not provided, the default SiteAccess is used. | ## Form-uploaded files You can use Forms to enable the user to upload files. -The default Location for files uploaded in this way is `/Media/Files/Form Uploads`. +The default location for files uploaded in this way is `/Media/Files/Form Uploads`. You can change it with the following configuration: ``` yaml @@ -76,4 +74,4 @@ ibexa: upload_location_id: 54 ``` -This applies only if no specific Location is defined in the Form itself. +This applies only if no specific location is defined in the Form itself. diff --git a/docs/content_management/images/add_image_asset_from_dam.md b/docs/content_management/images/add_image_asset_from_dam.md index 4e80a266ce..fe5d114ee5 100644 --- a/docs/content_management/images/add_image_asset_from_dam.md +++ b/docs/content_management/images/add_image_asset_from_dam.md @@ -26,7 +26,7 @@ To add the Unsplash connector to your system add the `ibexa/connector-unsplash` ## Add Image Asset in Page Builder [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] -To add Image Assets directly in the Page Builder, you can do it by using the Embed block. +To add Image Assets directly in the Page Builder, you can do it by using the Embed block. The example below shows how to add images from [Unsplash](https://unsplash.com/). First, in `templates/themes/standard/embed/`, create a custom template `dam.html.twig`: @@ -41,9 +41,10 @@ First, in `templates/themes/standard/embed/`, create a custom template `dam.html {% endif %} ``` -The `770px` parameter in the template above is used to render the DAM image. It is the `unsplash` specific image variation and must be defined separately. +The `770px` parameter in the template above is used to render the DAM image. It's the `unsplash` specific image variation and must be defined separately. + +Next, in `config/packages/ibexa.yaml`, set the `dam.html.twig` template for the `embed` view type that is matched for the content type, which you created for DAM images. -Next, in `config/packages/ibexa.yaml`, set the `dam.html.twig` template for the `embed` view type that is matched for the content type, which you created for DAM images. For more information about displaying content, see [Content rendering](render_content.md). ``` yaml @@ -63,7 +64,7 @@ In your [configuration file](configuration.md#configuration-files) add the follo ``` yaml dam_unsplash: application_id: - utm_source: + utm_source: variations: 770px: fm: jpg @@ -72,11 +73,12 @@ dam_unsplash: fit: max ``` -You can customize the parameters according to your needs. +You can customize the parameters according to your needs. + For more information about supported parameters, see the [Unsplash documentation](https://unsplash.com/documentation#dynamically-resizable-images). -In the Back Office, go to **Admin** > **Content types**. -In the **Content** group, create a content type for DAM images, which includes the ImageAsset Field. +In the back office, go to **Admin** > **Content types**. +In the **Content** group, create a content type for DAM images, which includes the ImageAsset field. Now, when you use the Embed block in the Page Builder, you should see a DAM Image. diff --git a/docs/content_management/images/configure_image_editor.md b/docs/content_management/images/configure_image_editor.md index 4456ac7dc5..a7386fbd7c 100644 --- a/docs/content_management/images/configure_image_editor.md +++ b/docs/content_management/images/configure_image_editor.md @@ -4,32 +4,30 @@ description: Configure image editor to crop, flip, and modify images. # Configure Image Editor -When a content item contains Fields of the [ezimage](imageassetfield.md) type, users can perform basic image editing functions with the Image Editor. -For more information, see the [user documentation]([[= user_doc =]]/editing_images/). +When a content item contains fields of the [ezimage](imageassetfield.md) type, users can perform basic image editing functions with the Image Editor. + +For more information, see [User Documentation]([[= user_doc =]]/editing_images/). !!! note - The Image Editor does not support images that come from a Digital Asset Management (DAM) system. + The Image Editor doesn't support images that come from a Digital Asset Management (DAM) system. !!! note - If you intend to modify images in formats other than JPEG in image editor, - consider [adding a library to optimize them](images.md#image-optimization). + If you intend to modify images in formats other than JPEG in image editor, consider [adding a library to optimize them](images.md#image-optimization). ## Configuration You can modify the default settings to change the appearance or behavior of the Image Editor. -You can also expand the default set of parameters to create buttons that may be required by custom features -that you add by extending the Image Editor, for example, to enable changes to the color palette of an image. +You can also expand the default set of parameters to create buttons that may be required by custom features that you add by extending the Image Editor, for example, to enable changes to the color palette of an image. -To do this, under the `ibexa.system..image_editor` [configuration key](configuration.md#configuration-files) -add a settings tree similar to the following example. +To do this, under the `ibexa.system..image_editor` [configuration key](configuration.md#configuration-files) add a settings tree similar to the following example. The settings tree can contain one or more action groups. You can control the order of actions within a group by setting the `priority` parameter. You can also toggle the visibility of actions within the user interface. Image Editor settings are [SiteAccess-aware](dynamic_configuration.md). -The following example sets the aspect ratio values and label names for buttons used by the Crop feature. +The following example sets the aspect ratio values and label names for buttons used by the Crop feature. ``` yaml [[= include_file('code_samples/back_office/image_editor/config/packages/image_editor.yaml', 0, 36) =]] @@ -48,10 +46,8 @@ The default quality is 0.92: ### Additional information -Each image can be accompanied by additional information that is not visible to the user. -By default, additional information stores the coordinates of the [focal point]([[= user_doc =]]/editing_images/#focal-point), -but you can use this extension point to pass various parameters of custom features -that you add by extending the Image Editor. +Each image can be accompanied by additional information that isn't visible to the user. +By default, additional information stores the coordinates of the [focal point]([[= user_doc =]]/editing_images/#focal-point), but you can use this extension point to pass various parameters of custom features that you add by extending the Image Editor. To modify the value of additional information programmatically, you can set a value of the `Image` field by using the PHP API, for example: diff --git a/docs/content_management/images/extend_image_editor.md b/docs/content_management/images/extend_image_editor.md index 5b39e59f9e..3c780f3dd9 100644 --- a/docs/content_management/images/extend_image_editor.md +++ b/docs/content_management/images/extend_image_editor.md @@ -19,7 +19,7 @@ In `assets/random_dot/`, create the `random-dot.js` file with the following code [[= include_file('code_samples/back_office/image_editor/assets/random_dot/random-dot-stem.js') =]] ``` -The code does not perform any action yet, you add the action in the following steps. +The code doesn't perform any action yet, you add the action in the following steps. ## Add configuration @@ -46,7 +46,7 @@ At this point you should be able to see a new button in the Image Editor's UI. ## Expand the React component -The button that you created above does not initiate any action yet. +The button that you created above doesn't initiate any action yet. You must modify the JavaScript component to add a function to the button. ### Contexts diff --git a/docs/content_management/images/fastly_io.md b/docs/content_management/images/fastly_io.md index 19e571df66..62d71add11 100644 --- a/docs/content_management/images/fastly_io.md +++ b/docs/content_management/images/fastly_io.md @@ -13,8 +13,8 @@ To be able to configure this feature, you need [Fastly IO subscription](https:// To use Fastly Image Optimizer, you first need a [working setup of Ibexa DXP and Fastly](reverse_proxy.md#using-varnish-or-fastly) with shielding enabled. -To enable shielding, follow the steps in [Fastly developer documentation](https://developer.fastly.com/learning/concepts/shielding/#enabling-and-disabling-shielding). -Remember to choose a shield location from the **Shielding** menu, as described in [Fastly user documentation](https://docs.fastly.com/en/guides/shielding#enabling-shielding). +To enable shielding, follow the steps in [Fastly Developer Documentation](https://developer.fastly.com/learning/concepts/shielding/#enabling-and-disabling-shielding). +Remember to choose a shield location from the **Shielding** menu, as described in [Fastly User Documentation](https://docs.fastly.com/en/guides/shielding#enabling-shielding). ## VCL configuration @@ -52,7 +52,7 @@ For more information about Fastly configuration and CLI usage examples, see [Con Fastly IO configuration is SiteAccess aware. You can define what handler should be used for a specific SiteAccess under `variation_handler_identifier` [configuration key](configuration.md#configuration-files). You need to set it up as `fastly`, so Fastly IO can generate all image links. -By default, it is set as `alias`, and it points to a built-in image optimizer. +By default, it's set as `alias`, and it points to a built-in image optimizer. You can also set up a custom handler if your setup requires it. ```yaml @@ -76,9 +76,9 @@ that they should reflect variations in your original setup. The built-in image optimizer serves as backup to Fastly IO in case of misconfiguration, so it needs to be able to serve the same image variations. -Fastly IO image filters are not compatible with our built-in filters, -so you will not be able to reflect your original filters accurately with Fastly. -The script below will help you find replacement filters within Fastly configuration for the basic filters. +Fastly IO image filters aren't compatible with [[= product_name_base =]] built-in filters, +so you aren't able to reflect your original filters accurately with Fastly. +The script below helps you find replacement filters within Fastly configuration for the basic filters. For more optimization options on Fastly side, see [Fastly IO reference](https://developer.fastly.com/reference/io/). To generate your original image configuration run: @@ -139,5 +139,5 @@ ibexa: You can select defined image variations during content item creation in the image options. Variations can include different sizing options and other filters that are applied to the image. -![Fastly Image Variations](img/fastly_variations.png) +![Fastly image variations](img/fastly_variations.png) diff --git a/docs/content_management/images/images.md b/docs/content_management/images/images.md index 33cfe2c1c7..4410f6de5d 100644 --- a/docs/content_management/images/images.md +++ b/docs/content_management/images/images.md @@ -7,41 +7,33 @@ description: Manage image assets by using DAM systems, configuring image variati Images are an integral part of any website. They can serve as decoration and convey information. -In [[= product_name =]], you can reuse them, normalize their file names, generate -different size variations, resize images programmatically, or even define -placeholders for missing ones. +In [[= product_name =]], you can reuse them, normalize their file names, generate different size variations, resize images programmatically, or even define placeholders for missing ones. ## Images from DAM systems -If your installation is connected to a DAM system, you can use images directly -from a DAM system in your content. +If your installation is connected to a DAM system, you can use images directly from a DAM system in your content. -Specific [DAM configuration](add_image_asset_from_dam.md#dam-configuration) depends on -the system that the installation uses. +Specific [DAM configuration](add_image_asset_from_dam.md#dam-configuration) depends on the system that the installation uses. ## Reuse images -You can store images in the media library as independent content items of -a generic Image [content type](content_types.md) to reuse them across the system. -You do this by uploading images to an [ImageAsset](imageassetfield.md) Field Type. +You can store images in the media library as independent content items of a generic Image [content type](content_types.md) to reuse them across the system. +You do this by uploading images to an [ImageAsset](imageassetfield.md) field type. -For an ImageAsset field to be reused, you must publish it. -Only then is notification triggered, which states that an image has been published -under the Location and can now be reused. -After you establish a media library, you can create [Relations](content_relations.md) between the -image content item and the main content item that uses it. +For an ImageAsset field to be reused, you must publish it. +Only then is notification triggered, which states that an image has been published under the location and can now be reused. +After you establish a media library, you can create [Relations](content_relations.md) between the image content item and the main content item that uses it. ## Normalizing image file names -If you use image files with unprintable UTF-8 characters in file names, you may -come across a problem with images not displaying. +If you use image files with unprintable UTF-8 characters in file names, you may come across a problem with images not displaying. Run the following command to normalize image file names: ``` bash php bin/console ibexa:images:normalize-paths ``` -Next, clear the cache: +Next, clear the cache: ```bash php bin/console cache:clear @@ -55,44 +47,34 @@ php bin/console liip:imagine:cache:remove ## Configuring image variations -With [image variations](image_variations.md) (image aliases) you can define and use different versions -of the same image. -You generate variations based on [filters](image_variations.md#available-variation-filters) that modify aspects such as size -and proportions, quality or effects. +With [image variations](image_variations.md) (image aliases) you can define and use different versions of the same image. +You generate variations based on [filters](image_variations.md#available-variation-filters) that modify aspects such as size and proportions, quality or effects. -Image variations are generated with [LiipImagineBundle](https://github.com/liip/LiipImagineBundle), by using the underlying -[Imagine library](https://imagine.readthedocs.io/en/latest/).  -The LiipImagineBundle bundle supports GD (default), Imagick or Gmagick PHP -extensions, and enables you to define flexible filters in PHP.  -Image files are stored by using the `IOService,` and are completely independent -from the Image Field Type. -They are generated only once and cleared on demand, for example, on content removal). +Image variations are generated with [LiipImagineBundle](https://github.com/liip/LiipImagineBundle), by using the underlying [Imagine library](https://imagine.readthedocs.io/en/latest/).  +The LiipImagineBundle bundle supports GD (default), Imagick or Gmagick PHP extensions, and enables you to define flexible filters in PHP.  +Image files are stored by using the `IOService,` and are completely independent from the Image field type. +They're generated only once and cleared on demand, for example, on content removal). + +LiipImagineBundle only works on image blobs, so no command line tool is needed. -LiipImagineBundle only works on image blobs, so no command line tool is needed. For more information, see the [bundle's documentation](https://symfony.com/bundles/LiipImagineBundle/current/configuration.html). !!! caution "Code injection in image EXIF" - EXIF metadata of an image may contain for example, HTML, JavaScript, - or PHP code.  - [[= product_name =]] is itself does not parse EXIF metadata, but third-party - bundles must be secured against this eventuality. - Images must be treated like any other user-submitted data - make sure that - metadata is properly escaped before use. + EXIF metadata of an image may contain for example, HTML, JavaScript, or PHP code.  + [[= product_name =]] is itself doesn't parse EXIF metadata, but third-party bundles must be secured against this eventuality. + Images must be treated like any other user-submitted data - make sure that metadata is properly escaped before use. ### Image URL resolution -You can use LiipImagine's `liip:imagine:cache:resolve` command to resolve the path -to image variations that are generated from the original image, with one or more -paths as arguments. -Paths to repository images must be relative to the `var//storage/images` -directory, for example: `7/4/2/0/247-1-eng-GB/test.jpg`. +You can use LiipImagine's `liip:imagine:cache:resolve` command to resolve the path to image variations that are generated from the original image, with one or more paths as arguments. +Paths to repository images must be relative to the `var//storage/images` directory, for example: `7/4/2/0/247-1-eng-GB/test.jpg`. + For more information, see [LiipImagineBundle documentation](https://symfony.com/bundles/LiipImagineBundle/current/basic-usage.html#resolve-with-the-console). ## Resizing images -You can resize all original images of a chosen content type with the following -command. +You can resize all original images of a chosen content type with the following command. ``` bash php bin/console ibexa:images:resize-original -f @@ -101,7 +83,7 @@ php bin/console ibexa:images:resize-original (see [example 2](#configuration-examples)) - live version of a site (see [example 3](#configuration-examples)) @@ -174,14 +147,13 @@ placeholders from: |Option|Default value|Description| |------|-------------|-----------| -|url_pattern|''|URL pattern. %width%, %height%, %id% in it will be replaced with width, height and ID of the original image.| +|url_pattern|''|URL pattern. %width%, %height%, %id% in it's replaced with width, height and ID of the original image.| |timeout|5|Period of time before timeout, measured in seconds.| ### Semantic configuration -Placeholder generation can be configured for each [`binary_handler`](file_management.md#handling-binary-files) under the -`ibexa.image_placeholder` [configuration key](configuration.md#configuration-files): - +Placeholder generation can be configured for each [`binary_handler`](file_management.md#handling-binary-files) under the `ibexa.image_placeholder` [configuration key](configuration.md#configuration-files): + ```yaml ibexa: # ... @@ -191,8 +163,7 @@ ibexa: options: ``` -If there is no configuration assigned to the `binary_handler`, the placeholder -generation is disabled. +If there is no configuration assigned to the `binary_handler`, the placeholder generation is disabled. ##### Configuration examples: @@ -216,20 +187,15 @@ generation is disabled. ## Support for SVG images -You cannot store SVG images in [[= product_name =]] by using the Image or -ImageAsset Field Type. -However, you can work things around by relying on the File Field Type and implementing -a custom extension that lets you display and download files in your templates. +You cannot store SVG images in [[= product_name =]] by using the Image or ImageAsset field type. +However, you can work things around by relying on the File field type and implementing a custom extension that lets you display and download files in your templates. !!! caution - SVG images may contain JavaScript, so they may introduce XSS or other security - vulnerabilities. - Make sure end users are not allowed to upload SVG images, and be restrictive - about which editors are allowed to do so. + SVG images may contain JavaScript, so they may introduce XSS or other security vulnerabilities. + Make sure end users aren't allowed to upload SVG images, and be restrictive about which editors are allowed to do so. -First, enable adding SVG files to content by removing them from the blacklist -of allowed MIME types. +First, enable adding SVG files to content by removing them from the blacklist of allowed MIME types. To do it, overwrite `ibexa.site_access.config.default.io.file_storage.file_type_blacklist` defined in `Core/Resources/config/default_settings.yml` so that `svg` is removed from the blacklist. You can do it per SiteAccess or SiteAccess group by using [SiteAccess-aware configuration](siteaccess_aware_configuration.md). @@ -267,9 +233,7 @@ Now you can load SVG files in your templates by using generated links and a newl JPEG images are optimized using the ImageMagic library, which is available out of the box. -If you use other formats, such a PNG, SVG, GIF or WEBP, and you use the Image Editor, -to prevent images increasing in size when you modify them in the editor, -you need to install additional image handling libraries. +If you use other formats, such a PNG, SVG, GIF, or WEBP, and you use the Image Editor, to prevent images increasing in size when you modify them in the editor, you need to install additional image handling libraries. |Image format|Library| |---|---| @@ -287,13 +251,11 @@ sudo apt-get install optipng ## Embedding images in Rich Text -The [RichText](richtextfield.md) field allows you to embed other -content items within the field. +The [RichText](richtextfield.md) field allows you to embed other content items within the field. -Content items that are identified as images are rendered in the Rich Text Field -by using a dedicated template. +Content items that are identified as images are rendered in the Rich Text field by using a dedicated template. -You can determine content types that will be treated as images and rendered. +You can determine content types that are treated as images and rendered. You do this by overriding the `ibexa.content_view.image_embed_content_types_identifiers` parameter, for example: ``` yaml diff --git a/docs/content_management/locations.md b/docs/content_management/locations.md index abf2839fc3..6b598b7bc2 100644 --- a/docs/content_management/locations.md +++ b/docs/content_management/locations.md @@ -4,84 +4,84 @@ description: Locations hold published content items and can be used to control v # Locations -When a new content item is published, it is automatically placed in a new Location. +When a new content item is published, it's automatically placed in a new location. -All Locations form a tree which is the basic way of organizing content in the system. -Every published content item has a Location and, as a consequence, also a place in this tree. +All locations form a tree which is the basic way of organizing content in the system. +Every published content item has a location and, as a consequence, also a place in this tree. -![Content Tree - locations](content_management_tree_locations.png "Content Tree - locations") +![Content tree - locations](content_management_tree_locations.png "Content tree - locations") -A content item receives a Location only once it has been published. -This means that a new unpublished draft does not have a Location yet. +A content item receives a location only once it has been published. +This means that a new unpublished draft doesn't have a location yet. You can find drats in the **Drafts** tab in the **Content** menu. ![Drafts](content_management_drafts.png "Drafts") -A content item can have more than one Location. It is then present in two or more places in the tree. +A content item can have more than one location. It's then present in two or more places in the tree. For example, an article can be at the same time under "Local news" and "Sports news". -Even in such a case, one of these places is always the main Location. +Even in such a case, one of these places is always the main location. -You can change the main Location in the Back Office in the **Locations** tab, +You can change the main location in the back office in the **Locations** tab, or [through the API](managing_content.md#changing-the-main-location). ![Locations](content_management_locations.png "Locations") -## Top level Locations +## Top level locations -The content tree is hierarchical. It has an empty root Location at the top and a structure of dependent Locations below it. -Every Location (aside from the root) has one parent Location and can have any number of children. +The content tree is hierarchical. It has an empty root location at the top and a structure of dependent locations below it. +Every location (aside from the root) has one parent location and can have any number of children. -Top level Locations are direct children of the root of the tree. -The root has Location ID 1, is not related to any content items and should not be used directly. +Top level locations are direct children of the root of the tree. +The root has location ID 1, isn't related to any content items and should not be used directly. -Under this root there are preset top level Locations in each installation which cannot be deleted. +Under this root there are preset top level locations in each installation which cannot be deleted. ### Content -The top level Location for the actual contents of a site +The top level location for the actual contents of a site can be viewed by selecting the **Content structure** tab in the Content mode interface. ![Content structure](content_management_tree.png "Content structure") -This part of the tree is typically used for organizing folders, articles, information pages, etc. -The default ID number of this Location is 2, but it can be [modified via configuration](repository_configuration.md#top-level-locations). +This part of the tree is typically used, for example, for organizing folders, articles, or information pages. +The default ID number of this location is 2, but it can be [modified via configuration](repository_configuration.md#top-level-locations). It contains a Folder content item. ### Media -**Media** is the top level Location which stores and organizes information +**Media** is the top level location which stores and organizes information that is frequently used by content items located below the **Content** node. ![Media](content_management_media.png "Media") It usually contains images, animations, documents and other files. -The default ID number of the **Media** Location is 43, but it can be [modified via configuration](repository_configuration.md#top-level-locations). +The default ID number of the **Media** location is 43, but it can be [modified via configuration](repository_configuration.md#top-level-locations). It contains a Folder content item. ### Users -**Users** is the top level Location that contains the built-in system for managing User accounts. +**Users** is the top level location that contains the built-in system for managing user accounts. -![Users in admin panel](admin_panel_users.png "Users in admin panel") +![Users in Admin panel](admin_panel_users.png "Users in Admin panel") -A User is simply a content item of the User account content type. -The Users are organized within User Group content items below this Location. +A user is simply a content item of the user account content type. +The users are organized within user group content items below this location. -In other words, the **Users** Location contains the actual Users and User Groups, -which can be viewed by selecting the **Users** tab in the Admin Panel. +In other words, the **Users** location contains the actual users and user groups, +which can be viewed by selecting the **Users** tab in the **Admin** Panel. -The default ID number of the **Users** Location is 5. -It contains User Group content items. +The default ID number of the **Users** location is 5. +It contains user group content items. ### Forms [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] -**Forms** is the top level Location that is intended for Forms created using the [Form Builder](https://doc.ibexa.co/projects/userguide/en/latest/content_management/work_with_forms/#create-forms). +**Forms** is the top level location that is intended for Forms created using the [Form Builder](https://doc.ibexa.co/projects/userguide/en/latest/content_management/work_with_forms/#create-forms). ![Forms](content_management_forms.png "Forms") -### Other top level Locations +### Other top level locations -You should not add any more content directly below Location 1, but instead store any content under one of those top-level Locations. +You should not add any more content directly below location 1, but instead store any content under one of those top-level locations. ## Location visibility @@ -90,7 +90,7 @@ Location visibility allows you to control which parts of the content tree are av ![Location visibility](content_management_visibility.png "Location visibility") Once a content item is published, it cannot be un-published. -When the Location of a content item is hidden, the system will not display it on the website. +When the location of a content item is hidden, the system doesn't display it on the website. !!! caution "Visibility and permissions" @@ -99,72 +99,70 @@ When the Location of a content item is hidden, the system will not display it on It isn't permission-based, and **doesn't restrict access to content**. Hidden content can be read through other means, like the REST API. If you need to restrict access to a given content item, you could create a role that grants read access for a given [**Section**](sections.md) or - [**Object State**](object_states.md), and set a different Section or Object State for the given Content. + [**Object State**](object_states.md), and set a different section or object state for the given content. Or use other permission-based [**Limitations**](limitations.md). -If a content item is hidden, it is invisible in all its Locations. -If a Location is hidden, all of its descendants in the tree will be hidden as well. +If a content item is hidden, it's invisible in all its locations. +If a location is hidden, all of its descendants in the tree are hidden as well. This means that there are three different visibility statuses: - Visible - Hidden - Hidden by superior -All Locations and content items are visible by default. -If a Location is made invisible manually, its status is set to Hidden. -All Locations under it will change status to Hidden by superior. -A content item is Hidden by superior only in Locations in which it has a parent Location with the Hidden status. +All locations and content items are visible by default. +If a location is made invisible manually, its status is set to Hidden. +All locations under it change status to Hidden by superior. +A content item is Hidden by superior only in locations in which it has a parent location with the Hidden status. In the following example, the **Content item 1** is Hidden by superior in the **Location A** while still visible in the **Location B**. ![Visibility in two locations](locations_visibility.png) -From the visitor's perspective a Location behaves the same whether its status is Hidden or Hidden by superior – -it will be unavailable on the front page. +From the visitor's perspective a location behaves the same whether its status is Hidden or Hidden by superior – it's unavailable on the front page. -The difference is that a Location Hidden by superior cannot be revealed separately from their parent(s). -It will only become visible once all of its parent Locations are made visible again. +The difference is that a location Hidden by superior cannot be revealed separately from their parent(s). +It only becomes visible once all of its parent locations are made visible again. -A Hidden by superior status does not override a Hidden status. -This means that if a Location is Hidden manually and later one of its ancestors is hidden as well, -the first Location's status does not change – it remains Hidden (not Hidden by superior). -If the ancestor Location is made visible again, the first Location still remains hidden. +A Hidden by superior status doesn't override a Hidden status. +This means that if a location is Hidden manually and later one of its ancestors is hidden as well, the first location's status doesn't change – it remains Hidden (not Hidden by superior). +If the ancestor location is made visible again, the first location still remains hidden. The way visibility works can be illustrated using the following scenarios: -#### Hiding a visible Location +#### Hiding a visible location -![Hiding a visible Location](node_visibility_hide.png) +![Hiding a visible location](node_visibility_hide.png) -When you hide a Location that was visible before, it will get the status Hidden. -Its child Locations will be Hidden by superior. -The visibility status of child Locations that were already Hidden or Hidden by superior will not change. +When you hide a location that was visible before, it gets the status Hidden. +Its child locations are Hidden by superior. +The visibility status of child locations that were already Hidden or Hidden by superior doesn't change. -#### Hiding a Location which is Hidden by superior +#### Hiding a location which is Hidden by superior -![Hiding a Location which is Hidden by superior](node_visibility_hide_invisible.png) +![Hiding a location which is Hidden by superior](node_visibility_hide_invisible.png) -When you explicitly hide a Location which was Hidden by superior, it will get the status Hidden. -Since the underlying Locations are already either Hidden or Hidden by superior, their visibility status will not be changed. +When you explicitly hide a location which was Hidden by superior, it gets the status Hidden. +Since the underlying locations are already either Hidden or Hidden by superior, their visibility status doesn't changed. -#### Revealing a Location with a visible ancestor +#### Revealing a location with a visible ancestor -![Revealing a Location with a visible ancestor](node_visibility_unhide1.png) +![Revealing a location with a visible ancestor](node_visibility_unhide1.png) -When you reveal a Location which has a visible ancestor, this Location and its children will become visible. -However, child Locations that were explicitly hidden by a user will keep their Hidden status -(and their children will remain Hidden by superior). +When you reveal a location which has a visible ancestor, this location and its children become visible. +However, child locations that were explicitly hidden by a user keep their Hidden status +(and their children remain Hidden by superior). -#### Revealing a Location with a Hidden ancestor +#### Revealing a location with a Hidden ancestor -![Revealing a Location with a Hidden ancestor](node_visibility_unhide2.png) +![Revealing a location with a Hidden ancestor](node_visibility_unhide2.png) -When you reveal a Location that has a Hidden ancestor, it will **not** become Visible itself. -Because it still has invisible ancestors, its status will change to Hidden by superior. +When you reveal a location that has a Hidden ancestor, it **doesn't** become Visible itself. +Because it still has invisible ancestors, its status changes to Hidden by superior. !!! tip "In short" - A Location can only be Visible when all of its ancestors are Visible as well. + A location can only be Visible when all of its ancestors are Visible as well. ### Visibility mechanics @@ -175,10 +173,10 @@ Together, the flags represent the three visibility statuses: |Hidden flag|Invisible flag|Status| |------|------|------| -|-|-|The Location is visible.| -|1|1|The Location is invisible and it was hidden by a user (Hidden).| -|-|1|The Location is invisible and it was hidden by the system because its ancestor is hidden/invisible (Hidden by superior).| +|-|-|The location is visible.| +|1|1|The location is invisible and it was hidden by a user (Hidden).| +|-|1|The location is invisible and it was hidden by the system because its ancestor is hidden/invisible (Hidden by superior).| !!! note - Displaying visible or hidden Locations in governed by the [`Visibility` Search Criterion](visibility_criterion.md) + Displaying visible or hidden locations in governed by the [`Visibility` Search Criterion](visibility_criterion.md) diff --git a/docs/content_management/pages/create_custom_page_block.md b/docs/content_management/pages/create_custom_page_block.md index bdc3d08acd..31998acecd 100644 --- a/docs/content_management/pages/create_custom_page_block.md +++ b/docs/content_management/pages/create_custom_page_block.md @@ -22,14 +22,12 @@ First, add the following [YAML configuration](configuration.md#configuration-fil ``` `event` is the internal name for the block, and `name` indicates the name under which the block is available in the interface. -You also set up the category in the Elements panel that the block appears in. +You also set up the category in the **Page blocks** toolbox that the block appears in. In this case, it doesn't show with the rest of the built-in blocks, but in a separate "Custom" category. -The thumbnail for the block can be one of the pre-existing icons, like in the example above, -or you can use a custom SVG file. +The thumbnail for the block can be one of the pre-existing icons, like in the example above, or you can use a custom SVG file. -A block can have multiple attributes that you edit when adding it to a Page. -In this example, you configure three attributes: name of the event, category it belongs to, -and an event content item that you select and embed. +A block can have multiple attributes that you edit when adding it to a page. +In this example, you configure three attributes: name of the event, category it belongs to, and an event content item that you select and embed. For a list of all available attribute types, see [Page block attributes](page_block_attributes.md). @@ -40,7 +38,7 @@ The `regexp` validator ensure that the final value looks like a content ID. ## Add block templates -A block can have different templates that you select when adding it to a Page. +A block can have different templates that you select when adding it to a page. To configure block templates, add them to block configuration: @@ -63,7 +61,7 @@ The template with the greatest priority is used as the default one. ## Add block JavaScript -If your block is animated with JavaScript, you may have to take precaution to keep it working when previewed in Back Office's Page Builder. +If your block is animated with JavaScript, you may have to take precaution to keep it working when previewed in back office's Page Builder. If you use an event related to the page being loaded to trigger the initialisation of your custom block, a freshly added block doesn't work in the Page Builder preview. For example, the [`DOMContentLoaded`](https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event) event isn't fired when a block is dragged into the page as the DOM is already loaded. @@ -91,7 +89,7 @@ document.getElementsByTagName('body')[0].addEventListener('ibexa-render-block-pr !!! note For the addition of your custom block's JS and CSS files, see [Assets](assets.md). - + If you consider using React JavaScript library, see [React App block](react_app_block.md). ## Add pre-render event listener @@ -133,6 +131,12 @@ The following UDW configuration is used so only an `event` typed content item ca For more information, see [UDW configuration](browser.md#udw-configuration). +Your custom page block is now ready. + +!!! caution + + Before you can use it in Page Builder, you must [enable it in Page field settings]([[= user_doc =]]/content_management/configure_ct_field_settings/#block-display). + Your custom page block is now registered in the system. !!! caution diff --git a/docs/content_management/pages/ibexa_connect_scenario_block.md b/docs/content_management/pages/ibexa_connect_scenario_block.md index 7097265c9c..999e3c9588 100644 --- a/docs/content_management/pages/ibexa_connect_scenario_block.md +++ b/docs/content_management/pages/ibexa_connect_scenario_block.md @@ -1,14 +1,14 @@ --- -description: Work with Ibexa Connect scenario block that retrieves and displays data from an Ibexa Connect webhook. +description: Work with Ibexa Connect scenario block that retrieves and displays data from an Ibexa Connect webhook. --- -# Ibexa Connect scenario block +# [[= product_name_connect =]] scenario block -[[= product_name_connect =]] scenario block retrieves and displays data from an [[= product_name_connect =]] webhook. +[[= product_name_connect =]] scenario block retrieves and displays data from an [[= product_name_connect =]] webhook. Scenario block is a regular [Page block](page_blocks.md) and can be configured on field definition level as any other block. !!! caution - + When setting up your instance, ensure you have profiler enabled. To set up Page Builder in [[= product_name =]], follow the [Page and Form tutorial](page_and_form_tutorial.md). @@ -24,11 +24,11 @@ First, in `config/packages/ibexa_connect.yaml` add the following configuration: [[= include_file('code_samples/page/ibexa_connect_scenario_block/config/packages/ibexa_connect.yaml') =]] ``` -For each block template you can set up additional settings, for example, label, type or parameters. +For each block template you can set up additional settings, for example, label, type or parameters. ### Define page layouts -To preview your block in the frontend, define page layouts in `config/packages/views.yaml` directory. This file defines, which layouts are used to render Page Builder. +To preview your block in the frontend, define page layouts in `config/packages/views.yaml` directory. This file defines, which layouts are used to render Page Builder. ```yaml [[= include_file('code_samples/page/ibexa_connect_scenario_block/config/packages/views.yaml') =]] @@ -49,22 +49,21 @@ Then, in `templates/blocks` directory under `default.html.twig`, provide your bl In the following example, the configuration of the block is non-complex - block is only used to display the content transferred from an [[= product_name_connect =]] webhook. At this point the [[= product_name_connect =]] scenario block is ready to be used in Page Builder. -### Configure Ibexa Connect scenario block in Page Builder +### Configure [[= product_name_connect =]] scenario block in Page Builder Now, you can configure [[= product_name_connect =]] scenario block in Page Builder. -To do it, in your Page add [[= product_name_connect =]] block by dragging it from the menu to a drop zone and enter block settings. +To do it, in your Page add [[= product_name_connect =]] block by dragging it from the menu to a drop zone and enter block settings. -- In the **Basic** tab in **Webhook link** field, provide a link to an [[= product_name_connect =]] webhook, -for example, `https://connect.ibexa.co/3/scenarios/688/edit`: +- In the **Basic** tab in **Webhook link** field, provide a link to an [[= product_name_connect =]] webhook, for example, `https://connect.ibexa.co/3/scenarios/688/edit`: ![Ibexa Connect Basic tab](ibexa_connect_basic_tab.png) -- In the **Design** tab, choose one of declared templates, in the following example, `company_customers` or `External clients`. +- In the **Design** tab, choose one of declared templates, in the following example, `company_customers` or `External clients`. To do it, extend drop-down list in the **View** field and choose one of the available options. ![Ibexa Connect Design tab](ibexa_connect_design_tab.png) Click **Submit** button to confirm. -After submitting the block, Page refreshes and [[= product_name_connect =]] block displays data from provided [[= product_name_connect =]] webhook. +After submitting the block, page refreshes and [[= product_name_connect =]] block displays data from provided [[= product_name_connect =]] webhook. ![Ibexa Connect webhook preview](ibexa_connect_webhook_preview.png) \ No newline at end of file diff --git a/docs/content_management/pages/page_block_attributes.md b/docs/content_management/pages/page_block_attributes.md index d2a3e9dac0..bc2ef3eef3 100644 --- a/docs/content_management/pages/page_block_attributes.md +++ b/docs/content_management/pages/page_block_attributes.md @@ -51,6 +51,7 @@ attributes: `embed` and `locationlist` use the Universal Discovery Widget (UDW). When creating a block with these two types you can configure the UDW behavior. + For more information, see [Create custom page block / Add edit template](create_custom_page_block.md#add-edit-template) ## Custom attribute types @@ -73,7 +74,7 @@ To define the type, create a `src/Block/Attribute/MyStringAttributeType.php` fil [[= include_file('code_samples/page/custom_attribute/src/Block/Attribute/MyStringAttributeType.php') =]] ``` -Note that the attribute uses `AbstractType` (line 5) and `TextType` (line 6). +The attribute uses `AbstractType` (line 5) and `TextType` (line 6). Adding `getBlockPrefix` (line 15) returns a unique prefix key for a custom template of the attribute. ### Mapper @@ -130,7 +131,7 @@ Now, you can create a block containing your custom attribute: The `nested_attribute` attribute is used when you want to create a group of attributes. -First, make sure you have configured the attributes you want to use in the group. +First, make sure you have configured the attributes you want to use in the group. Next, provide the configuration. See the example: diff --git a/docs/content_management/pages/page_block_validators.md b/docs/content_management/pages/page_block_validators.md index 1064200e00..2622fa1e37 100644 --- a/docs/content_management/pages/page_block_validators.md +++ b/docs/content_management/pages/page_block_validators.md @@ -16,11 +16,10 @@ The following block validators are available: !!! note - Do not use the `required` and `not_blank` validators for `richtext` attributes. + Don't use the `required` and `not_blank` validators for `richtext` attributes. Instead, use `not_blank_richtext`. -For each validator you can provide a message that displays in the Page Builder -when an attribute field doesn't fulfil the criteria. +For each validator you can provide a message that displays in the Page Builder when an attribute field doesn't fulfill the criteria. Additionally, for some validators you can provide settings under the `ibexa_fieldtype_page.blocks..validators.regexp.options` [configuration key](configuration.md#configuration-files), for example: diff --git a/docs/content_management/pages/page_blocks.md b/docs/content_management/pages/page_blocks.md index 24739adf4b..ab94e0d3dc 100644 --- a/docs/content_management/pages/page_blocks.md +++ b/docs/content_management/pages/page_blocks.md @@ -8,11 +8,9 @@ Page blocks are configured in YAML files, under the `ibexa_fieldtype_page` key. Keep in mind that Page block configuration isn't SiteAccess-aware. [[= product_name =]] ships with a number of page blocks. -For a list of all page blocks that are available out-of-the-box, -see [Page block reference]([[= user_doc =]]/content_management/block_reference/). +For a list of all page blocks that are available out-of-the-box, see [Page block reference]([[= user_doc =]]/content_management/block_reference/). -For information on how to create and configure new layouts for the Page, -see [Page layouts](render_page.md#render-a-layout). +For information on how to create and configure new layouts for the Page, see [Page layouts](render_page.md#render-a-layout). [[% include 'snippets/page_block_cache_clear.md' %]] @@ -23,10 +21,10 @@ Each configured block has an identifier and the following settings: | Setting | Description | |--------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| | `name` | Name of the block used in the Page Builder interface. | -| `category` | Category in the Page Builder elements menu that the block is shown in. | -| `thumbnail` | Thumbnail used in the Page Builder elements menu. | +| `category` | Category in the Page Builder **Page blocks** toolbox that the block is shown in. | +| `thumbnail` | Thumbnail used in the Page Builder **Page blocks** toolbox. | | `views` | Available [templates for the block](#block-templates). | -| `visible` | (Optional) Toggles the block's visibility in the Page Builder elements menu. Remove the block from the layout before you publish another version of the page. | +| `visible` | (Optional) Toggles the block's visibility in the Page Builder **Page blocks** toolbox. Remove the block from the layout before you publish another version of the page. | | `configuration_template` | (Optional) Template for the block settings modal. | | `attributes` | (Optional) List of [block attributes](page_block_attributes.md). | @@ -64,7 +62,7 @@ The highest number shows first on the list. !!! tip Default views have a `priority` of -255. - It is good practice to keep the value between -255 and 255. + It's good practice to keep the value between -255 and 255. ### Block modal template @@ -88,8 +86,7 @@ The following example wraps all form fields for block attributes in an ordered l ## Block events -To add functionalities to your block that go beyond the available attributes, -you can use an event listener. +To add functionalities to your block that go beyond the available attributes, you can use an event listener. You can listen to events related to block definition and block rendering. @@ -116,7 +113,7 @@ You can use this parameter, for example, in block template: #### Exposing content relations from blocks Page blocks, for example Embed block or Collection block, can embed other content items. -Publishing a Page with such blocks creates Relations to those content items. +Publishing a page with such blocks creates Relations to those content items. When creating a custom block with embeds, you can ensure such Relations are created using the block Relation collection event. diff --git a/docs/content_management/pages/page_builder_guide.md b/docs/content_management/pages/page_builder_guide.md index 26e84f9cc6..4ff642db95 100644 --- a/docs/content_management/pages/page_builder_guide.md +++ b/docs/content_management/pages/page_builder_guide.md @@ -7,7 +7,8 @@ edition: experience ## What is page -[Page](pages.md) is a block-based type of content. You can create and modify it with a visual drag-and-drop editor - Page Builder. +[Page](pages.md) is a block-based type of content. +You can create and modify it with a visual drag-and-drop editor - Page Builder. Page is divided into zones into which you can drop various dynamic blocks. By editing pages you can customize the layout and content of your website. @@ -29,15 +30,16 @@ To create a new page: ### Edit page -You can edit any existing page by using Page Builder. To do it, in the Back Office go to **Content** and select **Content structure**. -Then, from the Content Tree choose the page and click **Edit**. +You can edit any existing page with the Page Builder. +To do it, in the back office go to **Content** and select **Content structure**. +Then, from the content tree choose the page and click **Edit**. ## What is Page Builder Page Builder is a visual tool that allows you to create and edit any page in [[= product_name =]]. -It is more than managing: it is about building pages, creating customized content and fully-targeted landing pages. -Creating pages in Page Builder involves composing content using ready-to-use elements - blocks, properly configured and customized. -It is also important to choose a layout - it determines the arrangement of drop zones that contain content elements. +It's more than managing: it's about building pages, creating customized content and fully-targeted landing pages. +Creating pages in Page Builder involves composing content from ready-to-use elements - blocks, properly configured and customized. +It's also important to choose a layout - it determines the arrangement of drop zones that contain content elements. ![Page Builder - diagram](page_builder_diagram.png) @@ -67,11 +69,11 @@ E. Buttons: |Button|Description| |------|-----------| -|![Edit and preview switch](page_builder_toolbar_editpreview.png)|Access main properties of the Page, like title and description.| -|![Preview segments](page_builder_toolbar_preview_segment.png)|Access preview of the Page for a given Segment.| -|![Timeline button](page_builder_toolbartimelinetoggler.png)|Access the timeline to preview how the Page changes with time. You can also view the list of all upcoming scheduled events.| -|![View toggler](page_builder_toolbar_devicestoggler.png)|Toggle through to see how the Page is rendered on different devices.| -|![Elements menu](page_builder_toolbarelements.png)|Move Page blocks / Structure view to the other side of the screen.| +|![Edit and preview switch](page_builder_toolbar_editpreview.png)|Access main properties of the page, like title and description.| +|![Preview segments](page_builder_toolbar_preview_segment.png)|Access preview of the page for a given segment.| +|![Timeline button](page_builder_toolbartimelinetoggler.png)|Access the timeline to preview how the page changes with time. You can also view the list of all upcoming scheduled events.| +|![View toggler](page_builder_toolbar_devicestoggler.png)|Toggle through to see how the page is rendered on different devices.| +|![Page blocks menu](page_builder_toolbarelements.png)|Move Page blocks / Structure view to the other side of the screen.| |![Undo](page_builder_undo.png)|Undo latest change.| |![Redo](page_builder_redo.png)|Redo latest change.| @@ -85,7 +87,9 @@ F. Saving options |Save draft|Save the page draft*.| |Delete draft|Delete the page draft.| -*To help you preserve your work, system saves drafts of content items automatically. For more information, see [Autosave]([[= user_doc =]]/content_management/content_versions/#autosave). +*To help you preserve your work, system saves drafts of content items automatically. + +For more information, see [Autosave]([[= user_doc =]]/content_management/content_versions/#autosave). Page Builder has two main views that you can use while creating a page: @@ -93,7 +97,9 @@ Page Builder has two main views that you can use while creating a page: ![Page blocks](page_blocks_toolbar.png) -- Structure view - shows a structure of the page, including its division into zones and the blocks that it contains. It follows the behavior of the Content Tree. Structure view has ability to reorder blocks using drag and drop. +- Structure view - shows a structure of the page, including its division into zones and the blocks that it contains. +It follows the behavior of the content tree. +Structure view has ability to reorder blocks using drag and drop. ![Structure view](structure_view.png) @@ -104,7 +110,7 @@ For newly created Page you can choose a [layout]([[= user_doc =]]/content_manage Applying a layout divides the Page into the defined zones. The zones are placeholders for content items. On the Page creation modal, select the layout and click **Create draft**. -Now you are ready to add blocks of content to the Page. +Now you're ready to add blocks of content to the Page. The page layouts that an editor has access to are up to you to choose. In the `Select layouts` section, you can select layouts that you want to be available for the Page. @@ -112,6 +118,7 @@ In the `Select layouts` section, you can select layouts that you want to be avai ![Switch layout](switch_layout_window.png) The default, built-in Page layout has only one zone, but developers can create other layouts in configuration. + For more information, see [Configure layout](render_page.md#configure-layout). #### Add blocks @@ -201,9 +208,9 @@ Additionaly, Page Builder offers you a selection of ready-to-use page blocks tha A. **Default** blocks: -- Dynamic targeting - embeds recommended items based on the Segment the user belongs to. +- Dynamic targeting - embeds recommended items based on the segment the user belongs to. - Personalized - displays a list of content items/products that are recommended to end users when specific scenarios are triggered. -- Targeting - embeds a content item based on the Segment the user belongs to. +- Targeting - embeds a content item based on the segment the user belongs to. B. **PIM** blocks: diff --git a/docs/content_management/pages/react_app_block.md b/docs/content_management/pages/react_app_block.md index 493009d200..d3f869a851 100644 --- a/docs/content_management/pages/react_app_block.md +++ b/docs/content_management/pages/react_app_block.md @@ -8,8 +8,7 @@ React App block allows an editor to embed a preconfigured React application into It's configured in YAML files, under the `ibexa_fieldtype_page` key. Page block configuration isn't SiteAccess-aware. -Another element of React App Block is `\Ibexa\FieldTypePage\FieldType\Page\Block\Event\Listener\ReactBlock` Listener -which adds component and props variables. +Another element of React App Block is `\Ibexa\FieldTypePage\FieldType\Page\Block\Event\Listener\ReactBlock` Listener which adds component and props variables. It's common to all the blocks. @@ -28,10 +27,10 @@ Each configured React app block has an identifier and the following settings: | Setting | Description | |--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| | `name` | Name of the block used in the Page Builder interface. | -| `category` | Category in the Page Builder elements menu that the block is shown in. | -| `thumbnail` | Thumbnail used in the Page Builder elements menu. | +| `category` | Category in the Page Builder **Page blocks** toolbox that the block is shown in. | +| `thumbnail` | Thumbnail used in the Page Builder **Page blocks** toolbox. | | `component` | React App Component name used in `assets/page-builder/react/blocks` directory. | -| `visible` | (Optional) Toggles the block's visibility in the Page Builder elements menu. Remove the block from the layout before you publish another version of the page. | +| `visible` | (Optional) Toggles the block's visibility in the Page Builder **Page blocks** toolbox. Remove the block from the layout before you publish another version of the page. | | `attributes` | (Optional) List of [block attributes](page_block_attributes.md). | For example: @@ -61,8 +60,7 @@ attributes: ... ``` -Apps that are registered this way must be configured and referenced in the -semantic configuration to be registered as blocks. +Apps that are registered this way must be configured and referenced in the semantic configuration to be registered as blocks. Parameters passed as props must be converted so that they can be used as the configured type in the app. @@ -87,7 +85,7 @@ In the following example, create `Calculator.jsx` file in `assets/page-builder/c Then, create a `Calculator.js` file in `assets/page-builder/react/blocks` directory. Files in this directory create a map of Components which then are imported to `react.blocks.js` file. -As a result, the components are rendered on the page. +As a result, the components are rendered on the page. ``` js [[= include_file('code_samples/page/react_app_block/assets/page-builder/react/blocks/Calculator.js') =]] diff --git a/docs/content_management/rich_text/create_custom_richtext_block.md b/docs/content_management/rich_text/create_custom_richtext_block.md index 672c6d4a6c..e97dc74759 100644 --- a/docs/content_management/rich_text/create_custom_richtext_block.md +++ b/docs/content_management/rich_text/create_custom_richtext_block.md @@ -5,16 +5,13 @@ edition: experience # Create custom RichText block -A RichText block is a specific example of a [custom block](create_custom_page_block.md) that you can use when -you create a Page. -To create a custom block, you must define the block's layout, provide templates, add a subscriber -and register the subscriber as a service. +A RichText block is a specific example of a [custom block](create_custom_page_block.md) that you can use when you create a page. +To create a custom block, you must define the block's layout, provide templates, add a subscriber, and register the subscriber as a service. -Follow the procedure below to create a RichText Page block. +Follow the procedure below to create a RichText page block. First, provide the block configuration under the `ibexa_page_fieldtype.blocks` [configuration key](configuration.md#configuration-files). -The following code defines a new block, its view and configuration -templates. +The following code defines a new block, its view and configuration templates. It also sets the attribute type to `richtext` (line 15): ``` yaml hl_lines="3 15" @@ -37,8 +34,7 @@ Lines 41-51 handle the conversion of content into an XML string: [[= include_file('code_samples/back_office/online_editor/src/event/subscriber/RichTextBlockSubscriber.php') =]] ``` -Now you can create [templates](templates.md) that are used -for displaying and configuring your block. +Now you can create [templates](templates.md) that are used for displaying and configuring your block. Create the view template in `templates/themes//blocks/my_block/richtext.html.twig`. Line 2 is responsible for rendering the content from XML to HTML5: @@ -70,10 +66,9 @@ services: ``` -You have successfully created a custom RichText block. -You can now add your block in the Site tab. +You have successfully created a custom RichText block. +You can now add your block in the **Site** tab. ![RichText block](extending_richtext_block.png) -For more information about customizing additional options of the block or creating -custom blocks with other attribute types, see [Create custom Page block](create_custom_page_block.md). +For more information about customizing additional options of the block or creating custom blocks with other attribute types, see [Create custom Page block](create_custom_page_block.md). diff --git a/docs/content_management/rich_text/extend_online_editor.md b/docs/content_management/rich_text/extend_online_editor.md index a910df5ef9..d82fca3d06 100644 --- a/docs/content_management/rich_text/extend_online_editor.md +++ b/docs/content_management/rich_text/extend_online_editor.md @@ -4,17 +4,15 @@ description: Add custom tags, styles and data attributes to enrich the functiona # Extend Online Editor -[[= product_name =]] users edit the contents of RichText Fields, for example, -in the Content box of a Page, by using the Online Editor. +[[= product_name =]] users edit the contents of RichText fields, for example, in the Content box of a Page, by using the Online Editor. -You can extend the Online Editor by adding custom tags and styles, defining custom -data attributes, re-arranging existing buttons, grouping buttons into custom toolbar, +You can extend the Online Editor by adding custom tags and styles, defining custom data attributes, re-arranging existing buttons, grouping buttons into custom toolbar, and creating [custom buttons](https://ckeditor.com/docs/ckeditor4/latest/guide/widget_sdk_tutorial_1.html#widget-toolbar-button) and [custom plugins](https://ckeditor.com/docs/ckeditor4/latest/guide/dev_plugins.html). Online Editor is based on the CKEditor5. -Refer to [CKEditor5 documentation](https://ckeditor.com/docs/ckeditor5/latest/index.html) to learn -how you can extend the Online Editor with even more elements. -For more information about extending the Back Office, see [Extend Back Office](back_office.md). +Refer to [CKEditor5 documentation](https://ckeditor.com/docs/ckeditor5/latest/index.html) to learn how you can extend the Online Editor with even more elements. + +For more information about extending the back office, see [Extend back office](back_office.md). ## Configure custom tags @@ -42,7 +40,7 @@ Place the `factbox.html.twig` template in the !!! tip - If an attribute is not required, check if it is defined by adding a check + If an attribute isn't required, check if it's defined by adding a check in the template, for example: ```html+twig @@ -58,7 +56,7 @@ Add labels for the new tag by providing translations in `translations/custom_tag ``` Now you can use the tag. -In the Back Office, create or edit a content item that has a RichText Field Type. +In the back office, create or edit a content item that has a RichText field type. In the Online Editor, click **Add**, and from the list of available tags select the FactBox tag icon. ![FactBox Tag](custom_tag_factbox.png "FactBox Tag in the Online Editor") @@ -72,7 +70,7 @@ You can also place custom tags inline with the following configuration: ``` `is_inline` is an optional key. -The default value is `false`, therefore, if it is not set, the custom tag is +The default value is `false`, therefore, if it's not set, the custom tag is treated as a block tag. ### Use cases @@ -80,7 +78,7 @@ treated as a block tag. #### Link tag You can configure a custom tag with a `link` attribute that offers a basic UI with text input. -It is useful when migrating from eZ Publish to [[= product_name =]]. +It's useful when migrating from eZ Publish to [[= product_name =]]. The configuration is: @@ -105,7 +103,7 @@ Add labels for the tag by providing translations in `translations/custom_tags.en ``` Now you can use the tag. -In the Back Office, create or edit a content item that has a RichText Field Type. +In the back office, create or edit a content item that has a RichText field type. In the Online Editor's toolbar, click **Show more items**, and from the list of available tags select the Link tag icon. ![Link Tag](custom_tag_link.png "Link Tag in the Online Editor") @@ -118,7 +116,7 @@ You can create an inline custom tag that displays a hovering tooltip with an exp [[= include_file('code_samples/back_office/online_editor/custom_tags/acronym/config/packages/custom_tags.yaml') =]] ``` -The `explanation` attribute contains the meaning of the acronym that will be provided +The `explanation` attribute contains the meaning of the acronym that is provided while editing in the Online Editor. Add labels for the tag by providing translations in `translations/custom_tags.en.yaml`: @@ -129,8 +127,7 @@ Add labels for the tag by providing translations in `translations/custom_tags.en ![Adding an explanation to an Acronym custom tag](oe_custom_tag_add_acronym.png) -In the template file `acronym.html.twig` provide the explanation as attribute value -to the title of the `abbr` tag: +In the template file `acronym.html.twig` provide the explanation as attribute value to the title of the `abbr` tag: ``` html+twig {{ content }} @@ -170,7 +167,7 @@ Add labels for the new styles by providing translations in `translations/custom_ ### Rendering The `template` key points to the template that is used to render the custom style. -It is recommended that you use the [design engine](design_engine.md). +It's recommended that you use the [design engine](design_engine.md). The template files for the front end could look as follows: @@ -186,7 +183,7 @@ The template files for the front end could look as follows:
{% apply spaceless %}{{ content|raw }}{% endapply %}
``` -Templates for Content View in the Back Office would be `templates/themes/admin/field_type/ezrichtext/custom_styles/highlighted_word.html.twig` and `templates/themes/admin/field_type/ezrichtext/custom_styles/highlighted_block.html.twig` respectively (assuming that the Back Office SiteAccess uses the default `admin` theme). +Templates for Content View in the back office would be `templates/themes/admin/field_type/ezrichtext/custom_styles/highlighted_word.html.twig` and `templates/themes/admin/field_type/ezrichtext/custom_styles/highlighted_block.html.twig` (assuming that the back office SiteAccess uses the default `admin` theme). ### Use cases @@ -265,8 +262,7 @@ ezrichtext.custom_styles.highlight.label: 'Highlight' ## Configure custom data attributes and classes -You can add custom data attributes and CSS classes to the following elements -in the Online Editor: +You can add custom data attributes and CSS classes to the following elements in the Online Editor: - `embedInline` - `embed` @@ -294,7 +290,7 @@ in the Online Editor: If you override the default templates for `embedInline`, `embed` or `embedImage` elements, for example, `@IbexaCore/default/content/embed.html.twig`, - the data attributes and classes will not be rendered automatically. + the data attributes and classes aren't rendered automatically. Instead, you can make use of the `data_attributes` and `class` properties in your templates. @@ -306,25 +302,21 @@ in the Online Editor: You configure custom data attributes under the `fieldtypes.ibexa_fieldtype_richtext.attributes` key. The configuration is SiteAccess-aware. -A custom data attribute can belong to one of the following types: `choice`, -`boolean`, `string`, or `number`. +A custom data attribute can belong to one of the following types: `choice`, `boolean`, `string`, or `number`. You can also set each attribute to be `required` and set its `default_value`. For the `choice` type, you must provide an array of available `choices`. By adding `multiple`, you can decide whether more than one option can be selected. -It is set to `false` by default. +It's set to `false` by default. -Use the example below to add two data attributes, `custom_attribute` and -`another_attribute` to the Heading element in the `admin_group` SiteAccess: +Use the example below to add two data attributes, `custom_attribute` and `another_attribute` to the Heading element in the `admin_group` SiteAccess: ``` yaml [[= include_file('code_samples/back_office/online_editor/config/packages/custom_data_attributes.yaml') =]] ``` -The configuration outputs `data-ezattribute-=""` in the -corresponding HTML element. -Here, the resulting values are `data-ezattribute-custom-attribute="false"` and -`data-ezattribute-another-attribute="attr1,attr2"`. +The configuration outputs `data-ezattribute-=""` in the corresponding HTML element. +Here, the resulting values are `data-ezattribute-custom-attribute="false"` and `data-ezattribute-another-attribute="attr1,attr2"`. ### Custom CSS classes @@ -343,9 +335,7 @@ Use the example below to add a class choice to the Paragraph element in the `adm !!! note "Label translations" - If there are many custom attributes, to provide label translations for these - attributes, you can use the `ez_online_editor_attributes` translation extractor - to get a full list of all custom attributes for all elements in all scopes. + If there are many custom attributes, to provide label translations for these attributes, you can use the `ez_online_editor_attributes` translation extractor to get a full list of all custom attributes for all elements in all scopes. For example: @@ -358,8 +348,7 @@ Use the example below to add a class choice to the Paragraph element in the `adm #### Note box -You can create a custom class that enables you to place a paragraph element in -a note box: +You can create a custom class that enables you to place a paragraph element in a note box: ![Example of a note box custom style](oe_custom_style_note_box.png) @@ -368,8 +357,7 @@ a note box: ``` -With this class you can choose one of the following classes for each paragraph -element: `regular`, `tip_box`, or `warning_box`. +With this class you can choose one of the following classes for each paragraph element: `regular`, `tip_box`, or `warning_box`. You can then style the class by using CSS. ![Selecting a custom style for a paragraph](oe_custom_class_note_box_select.png) @@ -380,23 +368,23 @@ You can then style the class by using CSS. ## Rearrange buttons -You can modify the order and visibility of buttons that are available in the -Online Editor toolbar through configuration: +You can modify the order and visibility of buttons that are available in the Online Editor toolbar through configuration: ``` yaml [[= include_file('code_samples/back_office/online_editor/config/packages/custom_buttons.yaml') =]] ``` -For each button you can set `priority`, which defines the order of buttons in -the toolbar. +For each button you can set `priority`, which defines the order of buttons in the toolbar. For a full list of standard buttons, see the RichText module's [configuration file](https://github.com/ibexa/fieldtype-richtext/blob/main/src/bundle/Resources/config/prepend/ezpublish.yaml) ## Add CKEditor plugins -Regular CKEditor plugins can be added to the Online Editor. This procedure is illustrated with the addition of the [Special characters plugin](https://ckeditor.com/docs/ckeditor5/latest/features/special-characters.html). +Regular CKEditor plugins can be added to the Online Editor. +This procedure is illustrated with the addition of the [Special characters plugin](https://ckeditor.com/docs/ckeditor5/latest/features/special-characters.html). -A CKEditor plugin is installed locally by using `yarn add ` or `npm install`, and is deployed by committing the `yarn.lock` file. A local installation looks like: +A CKEditor plugin is installed locally by using `yarn add ` or `npm install`, and is deployed by committing the `yarn.lock` file. +A local installation looks like: ```bash yarn add @ckeditor/ckeditor5-special-characters diff --git a/docs/content_management/rich_text/online_editor_guide.md b/docs/content_management/rich_text/online_editor_guide.md index be46e8ed3e..828a6d8439 100644 --- a/docs/content_management/rich_text/online_editor_guide.md +++ b/docs/content_management/rich_text/online_editor_guide.md @@ -6,8 +6,8 @@ description: Learn how to use the Online Editor, a tool that allows you to edit ## What is Online Editor -Online Editor is the interface for editing RichText Fields in any content item in [[= product_name =]]. -It offers standard editing capabilities as well as extensibility points to customize the editing experience and the available elements. +Online Editor is the interface for editing RichText fields in any content item in [[= product_name =]]. +It offers standard editing capabilities and extensibility points to customize the editing experience and the available elements. Online Editor is based on [CKEditor 5](https://ckeditor.com/ckeditor-5/). @@ -17,26 +17,23 @@ Online Editor is available in all supported [[= product_name =]] versions and ed ## How to get started -Online Editor is the default editing interface for all RichText Fields. -To start using it, create any content item with a RichText Field -(for example, using the built-in Article content type) and edit this Field. +Online Editor is the default editing interface for all RichText fields. +To start using it, create any content item with a RichText field (for example, based on the built-in Article content type) and edit this field. ## Capabilities ### Rich Text editor -Online Editor covers all fundamental formatting options for rich text, -such as headings, lists, tables, inline text formatting, anchors and links. -It also allows embedding other content from the Repository, as well as from Facebook, Twitter or YouTube. +Online Editor covers all fundamental formatting options for rich text, such as headings, lists, tables, inline text formatting, anchors, and links. +It also allows embedding other content from the repository, but also from Facebook, Twitter, or YouTube. #### Links -All links added to a RichText Field by using the link element are listed -and can be managed in the [Link manager](url_management.md). +All links added to a RichText field by using the link element are listed and can be managed in the [Link manager](url_management.md). #### Distraction free mode -While editing Rich Text Fields, you can switch to distraction free mode that expands the workspace to full screen. +While editing Rich Text fields, you can switch to distraction free mode that expands the workspace to full screen. ![Distraction free mode](distraction_free_mode.png) @@ -44,12 +41,14 @@ For more information, see [Distraction free mode]([[= user_doc =]]/content_manag ### Custom tags -Custom tags are customizable RichText elements for which you can specify attributes -and render them with custom templates. +Custom tags are customizable RichText elements for which you can specify attributes and render them with custom templates. -Custom tags can be created by means of specifying two things only: -YAML configuration and relevant Twig templates. -The YAML configuration defines a custom tag’s attributes and the template used to render it, as well as where in the toolbar the tag is available. +Custom tags can be created by means of specifying two things only: + +- YAML configuration +- relevant Twig templates + +The YAML configuration defines a custom tag’s attributes, the template used to render it, and where in the toolbar the tag is available. See [Extend Online Editor](extend_online_editor.md#configure-custom-tags) for a full example. @@ -57,7 +56,8 @@ See [Extend Online Editor](extend_online_editor.md#configure-custom-tags) for a Custom styles allow specifying custom predefined templates for specific RichText elements. -Custom styles differ from custom tags in that they do not have attributes configured. A custom style requires YAML configuration that points to a template used to render an elements with this style. +Custom styles differ from custom tags in that they don't have attributes configured. +A custom style requires YAML configuration that points to a template used to render an elements with this style. See [Extend Online Editor](extend_online_editor.md#configure-custom-styles) for a full example. @@ -67,11 +67,11 @@ For each RichText element type, you can configure custom data attributes or CSS Custom data attributes allow adding new attributes to existing Rich Text elements, such as headings or lists, which are added in the form of `data-ezattribute-=""`. -See [Extend Online Editor](extend_online_editor.md#custom-data-attributes) for more information +For more information, see [Extend Online Editor](extend_online_editor.md#custom-data-attributes). Custom CSS classes work in a similar way, giving editor a choice of classes to add to any type of element. -See [Extend Online Editor](extend_online_editor.md#custom-css-classes) for more information +For more information, see [Extend Online Editor](extend_online_editor.md#custom-css-classes). ### Plugins @@ -81,8 +81,7 @@ Because Online Editor is based on CKEditor 5, you can use CKEditor's capabilitie ### Familiar editing tools -Online editor offers rich text editing tools familiar to most editors and contributors, -which allows quick adoption to the editorial flow. +Online editor offers rich text editing tools familiar to most editors and contributors, which allows quick adoption to the editorial flow. ![Familiar editing tools](img/familiar_editing_tools.png) @@ -92,19 +91,19 @@ The editor's toolbars can be customized and reorganized to for the specific proj The range of available text elements can be extended by offering custom elements and custom formatting options. -Custom formatting options can be offered either as custom CSS classes that editors can add to specific elements, -or as custom styles which can have their own templates. +Custom formatting options can be offered either as custom CSS classes that editors can add to specific elements, or as custom styles which can have their own templates. + +More extensive customization is available via custom tags: -More extensive customization is available via custom tags: -completely custom RichText elements that you can fully configure, -as well as custom CKEditor 5 plugins. +- completely custom RichText elements that you can fully configure +- custom CKEditor 5 plugins ## Use cases ### Customizable Call to action buttons -Online Editor extensibility offers a simple way to create custom elements such as Call to action (CTA) buttons. -Creating a CTA custom tag lets you use a template to construct a button element. +Online Editor extensibility offers a simple way to create custom elements such as Call to action (CTA) buttons. +Creating a CTA custom tag lets you use a template to construct a button element. Then, you can add a link attribute to provide target for the button, and a style attribute with different presets to style its look. ![Call to action buttons](img/call_to_action_buttons.png) @@ -113,6 +112,6 @@ Refer to [Extend Online Editor](extend_online_editor.md#link-tag) for a similar ### Embed external resources -Custom tags allow embedding content from external resources inside RichText Fields. -The built-in elements offer embedding of Twitter or Facebook posts, but you can extend the capability by embedding other resources. -These can be, for example, 3D product or real estate viewers. \ No newline at end of file +Custom tags allow embedding content from external resources inside RichText fields. +The built-in elements offer embedding of Twitter or Facebook posts, but you can extend the capability by embedding other resources. +These can be, for example, 3D product, or real estate viewers. \ No newline at end of file diff --git a/docs/content_management/rich_text/rich_text.md b/docs/content_management/rich_text/rich_text.md index 3024c2e56d..fe5e1d4ce0 100644 --- a/docs/content_management/rich_text/rich_text.md +++ b/docs/content_management/rich_text/rich_text.md @@ -5,10 +5,10 @@ page_type: landing_page # RichText -RichText is a type of field that you add in any content item in Ibexa DXP and edit in Online Editor. +RichText is a type of field that you add in any content item in [[= product_name =]] and edit in Online Editor. [[= cards([ "content_management/rich_text/online_editor_guide", "content_management/rich_text/extend_online_editor", - "content_management/rich_text/create_custom_richtext_block" + "content_management/rich_text/create_custom_richtext_block", ], columns=3) =]] \ No newline at end of file diff --git a/docs/content_management/taxonomy/taxonomy.md b/docs/content_management/taxonomy/taxonomy.md index 800af018e2..1f97a36ac0 100644 --- a/docs/content_management/taxonomy/taxonomy.md +++ b/docs/content_management/taxonomy/taxonomy.md @@ -4,7 +4,7 @@ description: A taxonomy uses tags to categorize and organize content # Taxonomy -Taxonomies (**Tags**) allow you to organize content to make it easy for your site users to browse and to deliver content appropriate for them. +Taxonomies (**Tags**) allow you to organize content to make it easy for your site users to browse and to deliver content appropriate for them. Taxonomies are classifications of logical relationships between content. In [[= product_name =]] you can create many taxonomies, each with many tags. The platform mechanism enables creating any entities with a tree structure and assign them to a content item. @@ -18,12 +18,12 @@ The associated content type is `tag`. ## Configuration keys * `ibexa_taxonomies` - section responsible for taxonomy structure where you can [configure other taxonomies](#customize-taxonomy-structure) -* `ibexa_taxonomies.tags.parent_location_remote_id` - Remote ID for Location where new content items representing tags are created +* `ibexa_taxonomies.tags.parent_location_remote_id` - Remote ID for location where new content items representing tags are created * `ibexa_taxonomies.tags.content_type` - Content type identifier which stands for the tags -* `ibexa_taxonomies.tags.field_mappings` - Field Types map of a content type which taxonomy receives information about the tag from. +* `ibexa_taxonomies.tags.field_mappings` - field types map of a content type which taxonomy receives information about the tag from. Three fields are available: `identifier`, `parent` and `name`. -The identifiers correspond to Field names defined in the content type. The `name` Field is used to automatically generate an identifier. +The identifiers correspond to field names defined in the content type. The `name` field is used to automatically generate an identifier. ## Customize taxonomy structure @@ -38,22 +38,22 @@ Next, under the `ibexa_taxonomy.taxonomies` [key](configuration.md#configuration [[= include_file('code_samples/taxonomy/config/packages/ibexa_taxonomy.yaml', 9, 17) =]] ``` -Replace `` with the new container's Location remote ID. +Replace `` with the new container's location remote ID. Translate the configuration identifier in the `ibexa_taxonomy` domain by, for example, creating a `translations/ibexa_taxonomy.en.yaml` file containing the following: ```yaml taxonomy.content_categories: 'Content categories' ``` -Then, create a content type with `content_category` identifier and include the following Field definitions: +Then, create a content type with `content_category` identifier and include the following field definitions: -* `name` of `ezstring` type and required. Use this Field, as ``, for content name pattern. +* `name` of `ezstring` type and required. Use this field, as ``, for content name pattern. * `category_identifier` of `ezstring` type and required. * `parent_category` of `ibexa_taxonomy_entry` type and not required. In its Taxonomy drop-down menu, select Content categories (or `taxonomy.content_categories` if no translation has been provided). Finish taxonomy setup by creating a new Content category named Root with identifier `content_categories_root` under the previously created container folder named Content categories. -To use this new taxonomy, add an `ibexa_taxonomy_entry_assignement` Field to a content type and select Content categories (or `taxonomy.content_categories`) in its Taxonomy drop-down setting. +To use this new taxonomy, add an `ibexa_taxonomy_entry_assignement` field to a content type and select Content categories (or `taxonomy.content_categories`) in its Taxonomy drop-down setting. ### Hide Content tab @@ -99,7 +99,7 @@ ibexa: ## Remove orphaned content items -In some rare case, especially in [[= product_name =]] v4.2 and older, when deleting parent of huge subtrees, some Taxonomy entries are not properly deleted, leaving content items that point to a non-existing parent. +In some rare case, especially in [[= product_name =]] v4.2 and older, when deleting parent of huge subtrees, some Taxonomy entries aren't properly deleted, leaving content items that point to a non-existing parent. The command `ibexa:taxonomy:remove-orphaned-content` deletes those orphaned content item. It works on a taxonomy passed as an argument, and has two options that act as a protective measure against deleting data by mistake: diff --git a/docs/content_management/url_management/url_api.md b/docs/content_management/url_management/url_api.md index 988061f48d..e956740e91 100644 --- a/docs/content_management/url_management/url_api.md +++ b/docs/content_management/url_management/url_api.md @@ -1,21 +1,21 @@ --- -description: The PHP API URLService enables searching for external URLs used in tech text and URL Fields. +description: The PHP API URLService enables searching for external URLs used in tech text and URL fields. --- # URL API [`URLService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-URLService.html) -enables you to find, load and update external URLs used in RichText and URL Fields. +enables you to find, load and update external URLs used in RichText and URL fields. To view a list of all URLs, use [`URLService::findUrls`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-URLService.html#method_findUrls) `URLService::findUrls` takes as argument a [`URLQuery`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-URLQuery.html), in which you need to specify: -- query filter e.g. Section +- query filter, for example, Section - Sort Clauses for URL queries - offset for search hits, used for paging the results -- query limit. If value is `0`, search query will not return any search hits +- query limit. If value is `0`, search query doesn't return any search hits ```php // ... diff --git a/docs/content_management/url_management/url_management.md b/docs/content_management/url_management/url_management.md index 5105291f39..a41052cfb8 100644 --- a/docs/content_management/url_management/url_management.md +++ b/docs/content_management/url_management/url_management.md @@ -4,7 +4,7 @@ description: Manage URL aliases and wildcards, and validate external URLs. # URL management -You can manage external URL addresses and URL wildcards in the Back Office, **Admin** tab, the **URL Management** node. +You can manage external URL addresses and URL wildcards in the back office, **Admin** tab, the **URL Management** node. Configure URL aliases to have human-readable URL addresses throughout your system. ## Link manager @@ -12,7 +12,7 @@ Configure URL aliases to have human-readable URL addresses throughout your syste When developing a site, users can enter links to external websites in either RichText or URL fields. Each such link is then displayed in the URL table. You can view and update all external links that exist within the site, without having to modify and re-publish the individual content items. -The Link manager tab contains all the information about each link, including its status (valid or invalid) and the time the system last attempted to validate the URL address. +The **Link manager** tab contains all the information about each link, including its status (valid or invalid) and the time the system last attempted to validate the URL address. Click an entry in the list to display its details and check which content items use this link. Edit the entry to update the URL address in all the occurrences throughout the website. @@ -71,7 +71,7 @@ ibexa: batch_size: 64 https: enabled: true - ignore_certificate: false + ignore_certificate: false mailto: enabled: false ``` @@ -137,22 +137,19 @@ The `scheme` attribute is mandatory and has to correspond to the name of the pro ## URL aliases You can define URL aliases for individual content items, for example, when you reorganize the content, and want to provide users with continuity. -For each URL alias definition the history of changes is preserved, so that users who have bookmarked the URL addresses of content items can still find he information they desire. +For each URL alias definition the history of changes is preserved, so that users who have bookmarked the URL addresses of content items can still find the information they desire. !!! note - Make sure that you correctly define languages used by the site in the configuration - (under the `ibexa.system..languages` key). - Otherwise, redirections for the renamed Content with translations in multiple - languages may fail to work properly. + Make sure that you correctly define languages used by the site in the configuration (under the `ibexa.system..languages` key). + Otherwise, redirections for the renamed Content with translations in multiple languages may fail to work properly. !!! caution "Legacy storage engine limitation" - The [Legacy storage engine](field_type_storage.md#legacy-storage-engine) does not archive URL aliases, which initially - had the same name in multiple languages. - For more information, see [the Jira ticket](https://issues.ibexa.co/browse/EZP-31818). + The [Legacy storage engine](field_type_storage.md#legacy-storage-engine) doesn't archive URL aliases, which initially had the same name in multiple languages. + For more information, see [the Jira ticket](https://issues.ibexa.co/browse/EZP-31818). -URL aliases are not SiteAccess-aware. When creating an alias, you can select a SiteAccess to base it on. +URL aliases aren't SiteAccess-aware. When creating an alias, you can select a SiteAccess to base it on. If the SiteAccess root path (configured in `content.tree_root.location_id`) is different than the default, the prefix path that results from the configured content root is prepended to the final alias path. @@ -199,11 +196,11 @@ Use it when: - you change URL alias configuration and want to regenerate old aliases - you encounter database corruption -- you have content that does not have a URL alias +- you have content that doesn't have a URL alias !!! caution - Before you apply the command, back up your database and make sure it is not modified while the command is running. + Before you apply the command, back up your database and make sure it's not modified while the command is running. Execute the following command to regenerate aliases: @@ -214,8 +211,8 @@ bin/console ibexa:urls:regenerate-aliases You can also extend the command with the following parameters: -- `--iteration-count` — Defines how many Locations are processed at once to reduce memory usage -- `--location-id` — Regenerates URL addresses for specific Locations only, e.g. `ibexa:urls:regenerate-aliases --location-id=1 --location-id=2` +- `--iteration-count` — Defines how many locations are processed at once to reduce memory usage +- `--location-id` — Regenerates URL addresses for specific locations only, for example, `ibexa:urls:regenerate-aliases --location-id=1 --location-id=2` ## URL wildcards @@ -228,7 +225,7 @@ Also, you can decide whether the user sees the content at the address that uses For example, a URL wildcard called `pictures/*/*` can use `media/images/{1}/{2}` as destination. In this case, accessing `/pictures/home/photo/` loads `/media/images/home/photo/`. -You can configure URL wildcards either in the Back Office, or with the public PHP API. +You can configure URL wildcards either in the back office, or with the public PHP API. Before you configure URL wildcards, you must enable the feature in configuration: @@ -238,13 +235,14 @@ ibexa: enabled: true ``` -### Configuring URL wildcards in the Back Office +### Configuring URL wildcards in the back office -The URL wildcards tab contains all the information about each URL wildcard. You can delete or modify existing entries, or create new ones. +The **URL wildcards** tab contains all the information about each URL wildcard. You can delete or modify existing entries, or create new ones. !!! note - To be able to modify wildcard support settings in the user interface, you must have the `content/urltranslator` Policy. For more information about permissions, see [Permissions](permissions.md). + To be able to modify wildcard support settings in the user interface, you must have the `content/urltranslator` policy. + For more information about permissions, see [Permissions](permissions.md). ### Configuring URL wildcards with the public PHP API @@ -263,4 +261,4 @@ $repository->sudo(function ($repository) use ($urlWildcardService, $source, $des ``` If `$redirect` is set to `true`, the redirection changes the URL address. -If it is `false`, the old URL address is be used, with the new content. +If it's `false`, the old URL address is be used, with the new content. diff --git a/docs/content_management/user_generated_content.md b/docs/content_management/user_generated_content.md index c820ff0832..4a12ecc3bf 100644 --- a/docs/content_management/user_generated_content.md +++ b/docs/content_management/user_generated_content.md @@ -1,11 +1,11 @@ --- -description: You can enable users to create new content in the Repository by using forms available in the front end of the site. +description: You can enable users to create new content in the repository by using forms available in the front end of the site. --- # User-generated content [[= product_name =]] comes with content edition features via the Symfony stack. -They are meant to allow the implementation of user-generated content from the front end, without entering the Back Office. +They're meant to allow the implementation of user-generated content from the front end, without entering the back office. ## Creating a new draft @@ -22,11 +22,11 @@ The `/content/edit/nodraft` route shows a content item creation form for a given |-------------------------|-----------|----------------------------------------------------------------------------| | `contentTypeIdentifier` | `string` | The identifier of the content type to create. Example: `folder`, `article` | | `languageCode` | `string` | Language code the content item must be created in. Example: `eng-GB` | -| `parentLocationId` | `integer` | ID of the Location the content item must be created in. Example: `2` | +| `parentLocationId` | `integer` | ID of the location the content item must be created in. Example: `2` | -This means that `/content/create/nodraft/folder/eng-GB/2` enables you to create a Folder in English as a child of Location with ID 2. +This means that `/content/create/nodraft/folder/eng-GB/2` enables you to create a Folder in English as a child of location with ID 2. -A limited subset of Field Types is supported: +A limited subset of field types is supported: - `TextLine` - `TextBlock` diff --git a/docs/content_management/workflow/add_custom_workflow_action.md b/docs/content_management/workflow/add_custom_workflow_action.md index 97d227c37e..fc8c8fdcf7 100644 --- a/docs/content_management/workflow/add_custom_workflow_action.md +++ b/docs/content_management/workflow/add_custom_workflow_action.md @@ -21,7 +21,7 @@ Configure the first custom action under the `ibexa.system..workflows` [co ``` The configuration indicates the name of the custom action (`legal_transition_action`). -`data` contains additional data that is passed to the action. In this case, it is a message to display. +`data` contains additional data that is passed to the action. In this case, it's a message to display. ## Create event listener diff --git a/docs/content_management/workflow/workflow.md b/docs/content_management/workflow/workflow.md index 89528a84f2..2086789661 100644 --- a/docs/content_management/workflow/workflow.md +++ b/docs/content_management/workflow/workflow.md @@ -6,8 +6,7 @@ description: Workflow controls how content items pass between stages and allows The workflow functionality passes a content item version through a series of stages. -For example, an editorial workflow can pass a content item from draft stage through -design and proofreading. +For example, an editorial workflow can pass a content item from draft stage through design and proofreading. By default, [[= product_name =]] comes pre-configured with a Quick Review workflow. You can disable the default workflow and define different workflows in configuration. @@ -27,15 +26,17 @@ The following example configuration defines a workflow where you can optionally ### Matchers -Matchers define when the workflow is used. Their configuration is optional. +Matchers define when the workflow is used. +Their configuration is optional. `content_type` contains an array of content type identifiers that use this workflow. -`content_status` lists the statuses of content items which fall under this workflow. The available values are: `draft` and `published`. +`content_status` lists the statuses of content items which fall under this workflow. +The available values are: `draft` and `published`. -If set to `draft`, applies for new Content (newly created). +If set to `draft`, applies for new content (newly created). -If set to `published`, applies for Content that has already been published (for example, edit after the Content was published). +If set to `published`, applies for content that has already been published (for example, edit after the content was published). ``` yaml [[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 6, 9) =]] @@ -45,7 +46,7 @@ If set to `published`, applies for Content that has already been published (for Each stage in the workflow has an identifier and can have a label and a color. -The optional `last_stage` key indicates that content in this stage does not appear on the dashboard or in Review Queue. +The optional `last_stage` key indicates that content in this stage doesn't appear on the dashboard or in Review Queue. One stage, listed under `initial_stage`, is the one that the workflow starts with. @@ -57,8 +58,7 @@ One stage, listed under `initial_stage`, is the one that the workflow starts wit Each transition has an identifier and can have a label, a color, and an icon. -A transition must state between which stages it transitions (lines 3-4), -or be `reverse` to a different transition (line 9). +A transition must state between which stages it transitions (lines 3-4), or be `reverse` to a different transition (line 9). ``` yaml hl_lines="3 4 9" [[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 23, 30) =]][[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 38, 43) =]] @@ -68,12 +68,10 @@ or be `reverse` to a different transition (line 9). When moving a content item through a transition, the user can select a reviewer. Assigning a reviewer is mandatory if you set `reviewers.required` to `true` for this transition. -You can restrict who can review the content item by setting `reviewers.user_group` to a Location ID of the user group. +You can restrict who can review the content item by setting `reviewers.user_group` to a location ID of the user group. -To be able to search for users for review, the user must have the content/read Policy without any Limitation, -or with a Limitation that allows reading users. -This means that, in addition to your own settings for this Policy, -you must add the /Users subtree to the Limitation and add Users in the [content type Limitation](limitation_reference.md#content-type-limitation). +To be able to search for users for review, the user must have the `content/read` policy without any limitation, or with a limitation that allows reading users. +This means that, in addition to your own settings for this policy, you must add the /Users subtree to the limitation and add users in the [content type limitation](limitation_reference.md#content-type-limitation). ``` yaml hl_lines="8 9" [[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 23, 32) =]] @@ -93,14 +91,9 @@ The notification is displayed in the user menu: #### Draft locking -You can configure draft assignment in a way that when a user sends a draft to review, -only the first editor of the draft can either edit the draft or unlock it for editing, and no -other user can take it over. +You can configure draft assignment in a way that when a user sends a draft to review, only the first editor of the draft can either edit the draft or unlock it for editing, and no other user can take it over. -Use the [Version Lock Limitation](limitation_reference.md#version-lock-limitation), -set to "Assigned only", together with the `content/edit` and `content/unlock` -Policies to prevent users from editing and unlocking drafts that are locked -by another user. +Use the [Version Lock limitation](limitation_reference.md#version-lock-limitation), set to "Assigned only", together with the `content/edit` and `content/unlock` policies to prevent users from editing and unlocking drafts that are locked by another user. ### Content publishing @@ -113,8 +106,7 @@ To do so, configure the `publish` action for the transition: ### Disable Quick Review -You can disable the default workflow, for example, if your project does not use -workflows, or Quick Review entries clog your database: +You can disable the default workflow, for example, if your project doesn't use workflows, or Quick Review entries clog your database: ``` yaml [[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 0, 4) =]][[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 63, 67) =]] @@ -154,32 +146,25 @@ The template has to provide a block named `ez_workflow_timeline_entry_{ENTRY_IDE You can limit access to workflows at stage and transition level. -The `workflow/change_stage` Policy grants permission to change stages in a specific workflow. +The `workflow/change_stage` policy grants permission to change stages in a specific workflow. -You can limit this Policy with the [Workflow Transition Limitation](limitation_reference.md#workflow-transition-limitation) -to only allow sending content in the selected transition. +You can limit this policy with the [Workflow Transition limitation](limitation_reference.md#workflow-transition-limitation) to only allow sending content in the selected transition. -For example, by using the example above, a `workflow/change_stage` Policy -with `WorkflowTransitionLimitation` set to `Approved by legal` allows a legal team to send content forward -after they are done with their review. +For example, by using the example above, a `workflow/change_stage` policy with `WorkflowTransitionLimitation` set to `Approved by legal` allows a legal team to send content forward after they're done with their review. -You can also use the [Workflow Stage Limitation](limitation_reference.md#workflow-stage-limitation) -together with the `content/edit` and `content/publish` Policies to limit the ability to edit content in specific stages. +You can also use the [Workflow Stage Limitation](limitation_reference.md#workflow-stage-limitation) together with the `content/edit` and `content/publish` Policies to limit the ability to edit content in specific stages. For example, you can use it to only allow a legal team to edit content in the `legal` stage. ## Validation ### Validate form before workflow transition -By default, sending content to the next stage of the workflow does not validate the form in UI, -so with the publish action, the form is not verified for errors in UI. +By default, sending content to the next stage of the workflow doesn't validate the form in UI, so with the publish action, the form isn't verified for errors in UI. However, during the publish action, the sent form is validated in the service. -Therefore, if there are any errors in the form, you return to the edit page but errors aren't triggered, -which can be confusing when you have two or more tabs. +Therefore, if there are any errors in the form, you return to the edit page but errors aren't triggered, which can be confusing when you have two or more tabs. -To enable form validation in UI before sending it to the next stage of the workflow, -add `validate: true` to the transitions of the stage. +To enable form validation in UI before sending it to the next stage of the workflow, add `validate: true` to the transitions of the stage. In the example below the form is validated in two stages:` to_legal` and `done`: ``` yaml hl_lines="15 28" diff --git a/docs/customer_management/cp_applications.md b/docs/customer_management/cp_applications.md index 280857bf8e..8c88e1ad4a 100644 --- a/docs/customer_management/cp_applications.md +++ b/docs/customer_management/cp_applications.md @@ -6,20 +6,19 @@ edition: experience # Customer Portal applications New business customers can apply for a company account. -Applications go through the approval process in the Back Office where they can be accepted, rejected or put on hold. -If they are accepted, the business partner receives an invitation link to the Customer Portal, -where they can set up their team and manage their account. +Applications go through the approval process in the back office where they can be accepted, rejected or put on hold. +If they're accepted, the business partner receives an invitation link to the Customer Portal, where they can set up their team and manage their account. For more information on company self-registration, see [user guide documentation](https://doc.ibexa.co/projects/userguide/en/latest/customer_management/company_self_registration/). If provided options are too limited, you can customize an approval process by yourself. ## Roles and policies -Any user can become application approver, as long as they have the `Company Application/Workflow` Policy assigned to their Role. +Any user can become application approver, as long as they have the `Company Application/Workflow` policy assigned to their role. There, you can define between which states the user may move applications. For example, the assistant can put new applications on hold, or reject them, and only the manager can accept them. -![Company Application Policy](img/cp_company_application_policy.png) +![Company Application policy](img/cp_company_application_policy.png) ## Customer Portal application configuration @@ -27,8 +26,7 @@ Below, you can find possible configurations for Customer Portal applications. ### Reasons for rejecting application -To change or add reasons for not accepting Corporate Portal application go to -`vendor/ibexa/corporate-account/src/bundle/Resources/config/default_settings.yaml`. +To change or add reasons for not accepting Corporate Portal application go to `vendor/ibexa/corporate-account/src/bundle/Resources/config/default_settings.yaml`. ```yaml parameters: @@ -39,8 +37,7 @@ parameters: ### Timeout -Registration form locks for 5 minutes after unsuccessful registration, -if the user, for example, tried to use an email address that already exists in a Customer Portal clients database. +Registration form locks for 5 minutes after unsuccessful registration, if the user, for example, tried to use an email address that already exists in a Customer Portal clients database. To change that duration, go to `config/packages/ibexa.yaml`. ```yaml @@ -59,8 +56,7 @@ In this procedure, you add a new status to the approval process of business acco ### Add new status -First, under the `ibexa.system..corporate_accounts.application.states` -add a `verify` status to the [configuration](configuration.md#configuration-files): +First, under the `ibexa.system..corporate_accounts.application.states` add a `verify` status to the [configuration](configuration.md#configuration-files): ```yaml [[= include_file('code_samples/customer_portal/config/packages/customer_portal.yaml') =]] @@ -69,7 +65,7 @@ add a `verify` status to the [configuration](configuration.md#configuration-file ### Create new Form Type Next, create a new form type in `src/Form/VerifyType.php`. -It will be displayed in the application review stage. +It's displayed in the application review stage. ``` php hl_lines="17-18 25" [[= include_file('code_samples/customer_portal/src/Form/VerifyType.php') =]] @@ -90,8 +86,7 @@ In line 39, you can see the `verify_form` parameter that passes the `verify` for ### Add form template -To be able to see the changes you need to add -a new template `templates/themes/admin/corporate_account/application/details.html.twig`. +To be able to see the changes you need to add a new template `templates/themes/admin/corporate_account/application/details.html.twig`. ``` html+twig [[= include_file('code_samples/customer_portal/templates/themes/admin/corporate_account/application/details.html.twig') =]] @@ -105,10 +100,8 @@ Select one application from the list and inspect application review view for a n ### Create event subscriber to verify state -Now, you need to pass the information that the button has been selected -to the list of applications to change the application status. -Create another event subscriber that passes the information -from the created form to the application list `src/Corporate/EventSubscriber/VerifyStateEventSubscriber.php`. +Now, you need to pass the information that the button has been selected to the list of applications to change the application status. +Create another event subscriber that passes the information from the created form to the application list `src/Corporate/EventSubscriber/VerifyStateEventSubscriber.php`. ``` php hl_lines="42 68" [[= include_file('code_samples/customer_portal/src/Corporate/EventSubscriber/VerifyStateEventSubscriber.php') =]] @@ -117,7 +110,7 @@ from the created form to the application list `src/Corporate/EventSubscriber/Ver In line 46, you can see that it handles changes to verify status. The subscriber only informs that the status has been changed (line 72). -Now, if you click the **Verify** button during application review, the application will get **Verify** status. +Now, if you click the **Verify** button during application review, the application gets **Verify** status. ![Verify status](img/cp_verify_status.png) diff --git a/docs/customer_management/cp_configuration.md b/docs/customer_management/cp_configuration.md index e529199452..1c9d52d532 100644 --- a/docs/customer_management/cp_configuration.md +++ b/docs/customer_management/cp_configuration.md @@ -5,15 +5,12 @@ edition: experience # Customer Portal configuration -You can overwrite the default configuration of the Customer Portal -to fit its capabilities to the unique needs of your business. +You can overwrite the default configuration of the Customer Portal to fit its capabilities to the unique needs of your business. ## `corporate` SiteAccess -The predefined `corporate` SiteAccess in `corporate_group` -(configured in `config/packages/ibexa.yaml`) serves the Customer Portal. -If you need a multisite setup with multiple Customer Portals, -add any additional SiteAccesses to `corporate_group`. +The predefined `corporate` SiteAccess in `corporate_group` (configured in `config/packages/ibexa.yaml`) serves the Customer Portal. +If you need a multisite setup with multiple Customer Portals, add any additional SiteAccesses to `corporate_group`. ## Customer identifier @@ -26,10 +23,9 @@ ibexa: user_content_type_identifier: ['user', 'customer'] ``` -## Roles and Policies +## Roles and policies -You can add custom roles to your installation -by listing them under the `ibexa.site_access.config.default.corporate_accounts.roles` [configuration](configuration.md#configuration-files). +You can add custom roles to your installation by listing them under the `ibexa.site_access.config.default.corporate_accounts.roles` [configuration](configuration.md#configuration-files). This key overwrites the default list set in `vendor/ibexa/corporate-account/src/bundle/Resources/config/default_settings.yaml` (the following example redeclares them for clarity): ```yaml @@ -44,12 +40,10 @@ You can do it per SiteAccess or SiteAccess group by using [SiteAccess-aware conf ## Content type names -You can change names of default content types by assigning what -content types should be used to describe `Company` and `Member` in the Back Office. +You can change names of default content types by assigning what content types should be used to describe `Company` and `Member` in the back office. Proceed only if you already have a `Company` content type in your system, and you don't want to change its identifier. -Configuration for content type names is placed under the `ibexa_corporate_account` key, -like shown in `Ibexa\Bundle\CorporateAccount\DependencyInjection\Configuration`. +Configuration for content type names is placed under the `ibexa_corporate_account` key, like shown in `Ibexa\Bundle\CorporateAccount\DependencyInjection\Configuration`. To change content type names, adjust corporate account configuration in the following way: ```yaml @@ -70,13 +64,12 @@ To do so, [create and configure user registration form](create_user_registration ## Address -With the Address Field Type, you can customize address Fields and configure them per country. -To learn more, see [Address Field Type documentation](addressfield.md). +With the Address field type, you can customize address fields and configure them per country. +To learn more, see [Address field type documentation](addressfield.md). ## Templates -You can also define new templates for, among others: invitation email, -reset password message and the information screens after any of the user's actions. +You can also define new templates for, among others: invitation email, reset password message and the information screens after any of the user's actions. ```yaml ibexa: @@ -92,6 +85,7 @@ ibexa: ## Order management -Reviewing pending and past orders in Customer Portal requires that you configure all currencies that any of the customers may use under the `ibexa.system..product_catalog.currencies` key. +Reviewing pending and past orders in Customer Portal requires that you configure all currencies that any of the customers may use under the `ibexa.system..product_catalog.currencies` key. The first currency from the list is then used for filtering the orders list and calculating the **Average order** and **Total amount** values. + For more information, see [Enable purchasing products](enable_purchasing_products.md). \ No newline at end of file diff --git a/docs/customer_management/cp_page_builder.md b/docs/customer_management/cp_page_builder.md index 80c7c2b08c..f2152934f4 100644 --- a/docs/customer_management/cp_page_builder.md +++ b/docs/customer_management/cp_page_builder.md @@ -5,14 +5,14 @@ edition: experience # Create Customer Portal -On this page, you will learn how to configure the Customer Portal feature to be editable with Page Builder. +On this page, you can learn how to configure the Customer Portal feature to be editable with Page Builder. If you already configured Customer Portal, you can learn how to build it with a Page Builder in [User Documentation]([[= user_doc =]]/customer_management/build_customer_portal/). First, you need to decide if you want to create and configure [one portal](#create-and-configure-one-portal) or [multiple portals](#create-and-configure-multiple-portals) setup. ## Create and configure one portal -This setup is recommended for simple use cases with one Customer Portal for all markets. +This setup is recommended for use cases with one Customer Portal for all markets. If you plan to expand your portal portfolio in the future, see [multiple portal configuration](#create-and-configure-multiple-portals). ### Configure Page Builder access to Customer Portal @@ -20,14 +20,13 @@ If you plan to expand your portal portfolio in the future, see [multiple portal First, create a Customer Portal page, its location ID needs to be later specified in the configuration. To do it, go to **Content** -> **Content structure**, and select **Customer Portal Page**. -For now, you only need to add a name and a description in the Field view, you can find it in the upper toolbar on the left side. +For now, you only need to add a name and a description in the field view, you can find it in the upper toolbar on the left side. Next, click **Publish** to see the page in the content tree. ![Add name and description to Customer Portal](img/cp_name_description.png) To be able to see the Customer Portal site template in the Page Builder you need to add `custom_portal` SiteAccess to the configuration. -First, under the `ibexa.siteaccess` [configuration key](configuration.md#configuration-files) add `custom_portal` to -the SiteAccess `list` and to `corporate_group`. +First, under the `ibexa.siteaccess` [configuration key](configuration.md#configuration-files) add `custom_portal` to the SiteAccess `list` and to `corporate_group`. Next, add configuration for `corporate_group` and `custom_portal` under `ibexa.system`. Remember to specify `location_id` of your Customer Portal, you can find it under the **Technical details** tab of your new page. @@ -40,7 +39,7 @@ ibexa: - site - admin - corporate - - custom_portal + - custom_portal groups: site_group: [import, site] storefront_group: [site] @@ -69,7 +68,7 @@ ibexa: - custom_portal ``` -Now, you can go to your Customer Portal Landing Page and edit it in Page Builder. +Now, you can go to your Customer Portal landing page and edit it in Page Builder. ![Edit Customer Portal in Page Builder](img/cp_edit_in_page_builder.png) @@ -82,11 +81,12 @@ You need to grant the following permissions to company members, so they can view ![Single Customer Portal permissions](img/single_cp_permissions.png) -If members of the company don't have sufficient permissions for any Customer Portal, they are redirected to the default Customer Portal view. +If members of the company don't have sufficient permissions for any Customer Portal, they're redirected to the default Customer Portal view. !!! note - Customer Portal is only available to users that are members of the company. Even if a user has all the sufficient permissions but is not a member of a company, they can't see the Customer Portal. + Customer Portal is only available to users that are members of the company. + Even if a user has all the sufficient permissions but isn't a member of a company, this user cannot see the Customer Portal. ## Create and configure multiple portals @@ -94,16 +94,15 @@ This setup is recommended for global markets or company specific portals, where ### Customer Portal container -First, you need to create a root folder for Customer Portals, -its location ID needs to be later specified in the configuration as [a tree root](multisite_configuration.md#location-tree). +First, you need to create a root folder for Customer Portals, its location ID needs to be later specified in the configuration as [a tree root](multisite_configuration.md#location-tree). To do it, go to **Content** -> **Content structure**, and select **Create content**. -There you will see two possibilities **Customer Portal** and **Customer Portal Page**. +There you can see two possibilities **Customer Portal** and **Customer Portal Page**. ![Create content tab](img/cp_portal_vs_page.png) The first one is a separate content type used as a container for your Customer Portal pages. Customer Portals containers should be used to sort Customer Portal pages and any other content types used by them, such as articles, inside the root folder. -It is recommended that you use them instead of folders to divide and store your portals. +It's recommended that you use them instead of folders to divide and store your portals. Select **Customer Portal**, define its name and publish. ![Customer Portals folder](img/cp_folder_for_portals.png) @@ -111,8 +110,7 @@ Select **Customer Portal**, define its name and publish. ### Configure Page Builder access to Customer Portal To be able to see Customer Portal site template in the Page Builder you need to add `custom_portal` SiteAccess to the configuration. -First, under the `ibexa.siteaccess` [configuration key](configuration.md#configuration-files), add `custom_portal` to -the SiteAccess `list` and to `corporate_group`. +First, under the `ibexa.siteaccess` [configuration key](configuration.md#configuration-files), add `custom_portal` to the SiteAccess `list` and to `corporate_group`. Next, add configuration for `corporate_group` and `custom_portal` under `ibexa.system`. Remember to specify `location_id` of the root folder for Customer Portals, you can find it under the **Technical details** tab. @@ -125,7 +123,7 @@ ibexa: - site - admin - corporate - - custom_portal + - custom_portal groups: site_group: [import, site] storefront_group: [site] @@ -155,27 +153,28 @@ ibexa: ``` Now, you can go back to your Customer Portal's container. -All Landing Pages that you create in it use Customer Portal template. +All landing pages that you create in it use Customer Portal template. -### Assign portal to Customer Group +### Assign portal to Customer group -You can assign multiple Customer Portal containers or Pages to a specific Customer Group. -First, you need to grant the following permissions to company members from the Customer Group: +You can assign multiple Customer Portal containers or Pages to a specific Customer group. +First, you need to grant the following permissions to company members from the Customer group: - `user/login` to `custom_portal` SiteAccess - `content/read` to selected Customer Portals ![Customer Portal permissions](img/cp_permissions.png) -If members of the Customer Group don't have sufficient permissions for any Customer Portal assigned to them, they will be redirected to the default Customer Portal view. +If members of the Customer group don't have sufficient permissions for any Customer Portal assigned to them, they're redirected to the default Customer Portal view. !!! note - Customer Portal is only available to users that are members of the company. Even if user has all the sufficient permissions but is not a member of a company, they won't see the Customer Portal. + Customer Portal is only available to users that are members of the company. + Even if user has all the sufficient permissions but isn't a member of a company, this user cannot see the Customer Portal. #### Build-in portal mapping -Now, you need to assign your custom portals to Customer Groups. +Now, you need to assign your custom portals to Customer groups. Add portal mapping configuration in `config/services.yaml`: ```yaml hl_lines="3 4" @@ -188,12 +187,12 @@ parameters: - 6ce85480aeaeed59f7431a12b46bc869 ``` -There, you can specify which Customer Portals should be available to which Customer Group by adding: +There, you can specify which Customer Portals should be available to which Customer group by adding: -- Customer Group identifier. You can find it in the **Summary** section of the Company. +- Customer group identifier. You can find it in the **Summary** section of the Company. - Location remote ID of Customer Portal container or Customer Portal page. You can find it in the **Details** section. -Portals will be displayed to the Customer Group in order specified in the configuration based on company member's permissions. +Portals are displayed to the Customer group in order specified in the configuration based on company member's permissions. #### Custom portal mapping diff --git a/docs/customer_management/create_user_registration_form.md b/docs/customer_management/create_user_registration_form.md index f5b92ba007..7f82c75417 100644 --- a/docs/customer_management/create_user_registration_form.md +++ b/docs/customer_management/create_user_registration_form.md @@ -11,10 +11,9 @@ First, make sure you [enabled user registration](permission_use_cases.md#registe ## Configure existing form -In your configuration, under `allowed_field_definitions_identifiers` [configuration key](configuration.md#configuration-files), -specify the fields that should be part of your registration form. -You can also define what kind of user you want to create under `user_type_identifier` e.g. frontend user. -To learn more about available users, see [user types documentation](user_registration.md#user-types). +In your configuration, under `allowed_field_definitions_identifiers` [configuration key](configuration.md#configuration-files), specify the fields that should be part of your registration form. +You can also define what kind of user you want to create under `user_type_identifier`, for example, frontend user. +To learn more about available users, see [user types documentation](user_registration.md#user-types). ``` yaml ibexa: @@ -42,7 +41,7 @@ ibexa: form: '@ibexadesign/user/registration_form.html.twig' confirmation: '@ibexadesign/user/registration_confirmation.html.twig' ``` -This defines which templates will be used for rendering the registration form and confirmation page. +This defines which templates are used for rendering the registration form and confirmation page. In the `templates/themes//user/registration_form.html.twig` create the template for registration form. diff --git a/docs/customer_management/customer_portal.md b/docs/customer_management/customer_portal.md index 5baa756ae1..555e487b1d 100644 --- a/docs/customer_management/customer_portal.md +++ b/docs/customer_management/customer_portal.md @@ -6,13 +6,11 @@ page_type: landing_page # Customer Portal -A Customer Portal serves as a central entry point to your services and products. +A Customer Portal serves as a central entry point to your services and products. It helps you provide a unique user experience with a single point of access to any relevant self-service options for your products and services. -[[= product_name =]] Customer Portal and customer management that ships with it let you create and handle business accounts -and communicate with your partners in a personalized space. -With this feature, your customers can self-register, edit their organization information, -invite and view members, check their order history and more. +[[= product_name =]] Customer Portal and customer management that ships with it let you create and handle business accounts and communicate with your partners in a personalized space. +With this feature, your customers can self-register, edit their organization information, invite and view members, check their order history, and more. [[= cards([ "customer_management/customer_portal_guide", @@ -20,5 +18,5 @@ invite and view members, check their order history and more. "customer_management/cp_applications", "users/invitations", "customer_management/cp_page_builder", - "customer_management/create_user_registration_form" + "customer_management/create_user_registration_form", ], columns=3) =]] \ No newline at end of file diff --git a/docs/customer_management/customer_portal_guide.md b/docs/customer_management/customer_portal_guide.md index 388d6d4a26..b899158516 100644 --- a/docs/customer_management/customer_portal_guide.md +++ b/docs/customer_management/customer_portal_guide.md @@ -7,21 +7,19 @@ edition: experience ## What is Customer Portal -A Customer Portal serves as a central entry point to your services and products. +A Customer Portal serves as a central entry point to your services and products. It helps you provide a unique user experience with a single point of access to any relevant self-service options for your products and services. -[[= product_name =]] Customer Portal and customer management that ships with it let you create and handle business accounts -and communicate with your partners in a personalized space. -With this feature, your customers can self-register, edit their organization information, -invite and view members, check their order history and more. +[[= product_name =]] Customer Portal and customer management that ships with it let you create and handle business accounts and communicate with your partners in a personalized space. +With this feature, your customers can self-register, edit their organization information, invite and view members, check their order history, and more. ## Availability -Customer Portal is available in [[= product_name_exp =]]. It is also compatible with PIM, Commerce and [[= product_name_connect =]]. +Customer Portal is available in [[= product_name_exp =]]. It's also compatible with PIM, Commerce and [[= product_name_connect =]]. ## How does Customer Portal work? -Customer Portal is a component based on content types. +Customer Portal is a component based on content types. This means that [[= product_name =]] provides containers, user management, content management, so you can focus on business logic and general outlook of the portal for your B2B clients. ### Customer Portal @@ -35,11 +33,10 @@ With user differentiation, company buyers can only purchase products while compa Custom Customer Portal can be created and edited in Page Builder to meet the needs of each business type, company, or market they operate on. -To create a new Customer Portal, go to Content and, from the menu, select Content structure. -There, navigate to the root container for your Customer Portals and select Customer Portal Page. -In the Page Builder creation box, you see the Customer Portal layout where you can add a dedicated Customer Portal block, -Sales Representative, or choose from a selection of blocks available to your [[= product_name =]] version. -If the built-in page blocks are not sufficient to fulfill your needs, you can add your own. +To create a new Customer Portal, go to **Content** and, from the menu, select **Content structure**. +There, navigate to the root container for your Customer Portals and select **Customer Portal Page**. +In the Page Builder creation box, you see the Customer Portal layout where you can add a dedicated Customer Portal block, Sales Representative, or choose from a selection of blocks available to your [[= product_name =]] version. +If the built-in page blocks aren't sufficient to fulfill your needs, you can add your own. ![Editable in Page Builder](img/cp_edit_in_page_builder.png) @@ -50,24 +47,24 @@ This setup is recommended for global markets or company-specific portals, where ### Company management -The main company management takes place in the Back Office where each company has its own profile where sales representative can find: +The main company management takes place in the back office where each company has its own profile where sales representative can find: - summary with basic information and order history - company profile with billing information and contact person - list of members and pending invitations - address book with multiple shipping addresses -![Companies section in Back Office](img/cp_back_office.png) +![Companies section in back office](img/cp_back_office.png) -From there, they can activate and deactivate the company, edit its information, invite members, manage their roles and edit their basic information. +From there, they can activate and deactivate the company, edit its information, invite members, manage their roles, and edit their basic information. -In the Roles section, you can define Policies for each user group, for example, a Company buyer. -You can also set up Policies for every user who has a business account by editing a Corporate Access role. +In the roles section, you can define policies for each user group, for example, a Company buyer. +You can also set up policies for every user who has a business account by editing a Corporate Access role. ### Members -Company members are not standard users. They belong to a separate category called Corporate Accounts. -This category is located in **Admin** -> **Corporate** -> **Corporate Accounts**. +Company members aren't standard users. They belong to a separate category called Corporate Accounts. +This category is located in **Admin** -> **Corporate** -> **Corporate Accounts**. There, you can find a list of companies and their members. This feature comes with a set of new roles: @@ -83,40 +80,41 @@ All roles and policies associated with them can be fully customized to fit your Members can be invited to the organization from: -- the Back Office: go to **Customers** -> **Companies** -> **Select your company** -> **Invitations** -> **Invite member** +- the back office: go to **Customers** -> **Companies** -> **Select your company** -> **Invitations** -> **Invite member** - the Customer Portal: go to your company admin profile, select **Members** -> **Invite members** -Then, in a pop-up fill out email addresses one by one, or use drag and drop to upload a file with a list of emails. -You also have to assign a role to each new member from a drop-down list. +Then, in a pop-up fill out email addresses one by one, or use drag and drop to upload a file with a list of emails. +You also have to assign a role to each new member from a drop-down list. Click **Send** to send out invitations. ![Invitations](img/cp_invitations.png) -Invited users receive an email message with a registration link. +Invited users receive an email message with a registration link. With it, they can register and create their account in the Customer Portal. ![Create account](img/cp_create_account.png) ### Company self-registration -Self-registration allows business customers to take charge and apply for a business account by themselves. -Applications go through the approval process in the Back Office where they can be accepted, rejected or put on hold. -If they are accepted, the business partner receives an invitation link to the Customer Portal, where they can set up their team and manage their account. +Self-registration allows business customers to take charge and apply for a business account by themselves. +Applications go through the approval process in the back office where they can be accepted, rejected or put on hold. +If they're accepted, the business partner receives an invitation link to the Customer Portal, where they can set up their team and manage their account. -To apply for a business account, a company needs to provide their basic information, -contact information and billing address in an application. +To apply for a business account, a company needs to provide their basic information, contact information and billing address in an application. ![Company self-registration](img/cp_registration.png) -The approval process is customizable. You can decide which user has approval rights by granting them Company Application/Workflow Policy, -you can also decide between which states the user may move applications: +The approval process is customizable. +You can decide which user has approval rights by granting them `Company Application/Workflow` policy, you can also decide between which states the user may move applications: - on hold - accept - reject -If built-in statuses are not sufficient, you can add custom ones. You can also edit or add reasons for not accepting the company application. Finally, you can customize the registration site itself. +If built-in statuses aren't sufficient, you can add custom ones. +You can also edit or add reasons for not accepting the company application. +Finally, you can customize the registration site itself. ### REST API @@ -126,15 +124,15 @@ Customer Portal comes with [REST API](https://doc.ibexa.co/en/latest/api/rest_ap ### Company management -Sales representatives can manage details for companies they are associated with, such as contact persons, billing addresses, and more by accessing Back Office. +Sales representatives can manage details for companies they're associated with, such as contact persons, billing addresses, and more by accessing back office. Company admins are also able to manage the company's details in the Customer Portal interface. By giving users power to manage their own accounts, you reduce the need for administrative interventions. ### Self registration Self-registration allows your customers to take control of their business accounts. -This not only improves customer satisfaction but also reduces the administrative burden on your team. -With the ability to integrate with [[= product_name_connect =]], you are able to fully automate the process. +This not only improves customer satisfaction but also reduces the administrative burden on your team. +With the ability to integrate with [[= product_name_connect =]], you're able to fully automate the process. ### Address book @@ -154,35 +152,33 @@ It allows you to make use of customer targeting of the segments and create perso ### General overview The overall benefit of customer portals is the help they provide to retain customers and increase loyalty, while freeing up customer service employees time for higher-level work. -They can achieve that by providing customers with up-to-date information about their orders and deliveries, personalize shopping experience, offer special deals available only to B2B partners and do that in one, easily accessible space. -Currently, customer portals are a standard in global sites such as Amazon. They are the level of quality that customers just expect, and all businesses strive for. +They can achieve that by providing customers with up-to-date information about their orders and deliveries, personalize shopping experience, offer special deals available only to B2B partners, and do that in one, accessible space. +Currently, Customer Portals are a standard in global sites such as Amazon. +They're the level of quality that customers expect, and all businesses strive for. ### Simplified shopping process -Business account helps streamline the B2B shopping process with all the paperwork, payment, -and other administrative tasks converted into a few simple steps with prefilled forms, billing addresses, shipping addresses and more. +Business account helps streamline the B2B shopping process with all the paperwork, payment, and other administrative tasks converted into a few steps with prefilled forms, billing addresses, shipping addresses, and more. Making your site a go-to place for company orders. ### Better customer experience -In the era of internet, customers expect quick, accessible and excellent quality service and user experience from every business they associate with. +In the era of internet, customers expect quick, accessible and excellent quality service, and user experience from every business they associate with. Customer portals offer a seamless self-service experience by providing complete 24/7 access to relevant, up-to-date information and customer support. ### Client encouragement -Price strategies are a great way to build and maintain strong relationships with your trading partners. -With special prices available to B2B clients, you can offer the best deals in highly competitive markets. -Those discounts may be a great encouragement to convince big buyers to choose your business over other options. -Competitive prices impact not only the size of the customer base, -they affect every customer’s purchasing strategy, including the diversity, frequency, and volume of their orders. +Price strategies are a great way to build and maintain strong relationships with your trading partners. +With special prices available to B2B clients, you can offer the best deals in highly competitive markets. +Those discounts may be a great encouragement to convince big buyers to choose your business over other options. +Competitive prices impact not only the size of the customer base, they affect every customer’s purchasing strategy, including the diversity, frequency, and volume of their orders. ### Cost benefits -Customer portals help you to automate tasks that otherwise would be done by your employees manually, such as customer services, checking shipment status. -An additional benefit of customer portals is their availability 24/7. +Customer portals help you to automate tasks that otherwise would be done by your employees manually, such as customer services, checking shipment status. +An additional benefit of customer portals is their availability 24/7. Thus, reducing the need to allocate resources to extend working hours or hire more employees. ### Localization and personalization -The use of Page Builder in the Customer Portal creation process enables you to -create unique experiences for each business customer based on their location, business type, company, or market they operate on. \ No newline at end of file +The use of Page Builder in the Customer Portal creation process enables you to create unique experiences for each business customer based on their location, business type, company, or market they operate on. \ No newline at end of file diff --git a/docs/getting_started/first_steps.md b/docs/getting_started/first_steps.md index d3eea3ec7b..6b72a0dae3 100644 --- a/docs/getting_started/first_steps.md +++ b/docs/getting_started/first_steps.md @@ -5,19 +5,17 @@ description: Start off working with Ibexa DXP by doing initial configuration and # First steps This page lists first steps you can take after installing [[= product_name =]]. -These are most common actions you may need to take in a new installation. +These steps are the most common actions you may need to take in a new installation. !!! tip "Beginner tutorial" - To go through a full tutorial that leads from a clean installation to creating a full site, - see [Beginner tutorial](beginner_tutorial.md). + To go through a full tutorial that leads from a clean installation to creating a full site, see [Beginner tutorial](beginner_tutorial.md). ## Remove welcome page ![Welcome page](welcome_page.png) -To remove the welcome page and get a completely clean installation to start your project with, -remove the following files and folders from your installation: +To remove the welcome page and get a completely clean installation to start your project with, remove the following files and folders from your installation: - Delete the file `config/packages/ibexa_welcome_page.yaml` - Delete the `templates/themes/standard/full/welcome_page.html.twig` file @@ -35,43 +33,39 @@ module.exports = [ eZConfig, ibexaConfig, ...customConfigs ]; ## Add a content type -1\. In your browser, go to the Back Office: `/admin`, and use the default credentials to log in: `admin/publish`. +1\. In your browser, go to the back office: `/admin`, and use the default credentials to log in: `admin/publish`. !!! caution "Password change" - Make sure that you change the default password before you switch your installation - from development to production. + Make sure that you change the default password before you switch your installation from development to production. For more information about passwords, see [Passwords](passwords.md). For more information about production security, see [Security checklist](security_checklist.md). 2\. In the upper-right corner, click the avatar icon and in the drop-down menu disable the [Focus mode]([[= user_doc =]]/getting_started/discover_ui/#focus-mode). -3\. Select Content and go to content types. +3\. Select content and go to content types. -4\. Enter the Content group and create a new content type. +4\. Enter the content group and create a new content type. ![Creating a content type](first-steps-create-ct.png) 5\. Input the content type's name, for example "Blog Post", and identifier: `blog_post`. -6\. Below, add a Field definition of the type Text Line. Name it "Title" and give it identifier `title`. +6\. Below, add a field definition of the type Text Line. Name it "Title" and give it identifier `title`. -7\. Add another Field definition: Text (type Rich text) with identifier `text`. +7\. Add another field definition: Text (type Rich text) with identifier `text`. 8\. Save the content type. -!!! tip "More information" - - - [Content model](content_model.md) +For more information, see [Content model](content_model.md). ## Create Twig templates and match then with view config -To display Content in the front page you need to define content views and templates. +To display content in the front page you need to define content views and templates. Content views decide which templates and controllers are used to display content. -1\. In `config/packages/ibexa.yaml`, under `ibexa.system` -add the following block (pay attention to indentation: `site_group` should be one level below `system`): +1\. In `config/packages/ibexa.yaml`, under `ibexa.system` add the following block (pay attention to indentation: `site_group` should be one level below `system`): ``` yaml site_group: @@ -92,21 +86,19 @@ Content view templates use the [Twig templating engine](https://twig.symfony.com
{{ ibexa_render_field(content, 'text') }}
``` -!!! tip "More information" - - - [Templates](templates.md) - - [Twig documentation](https://twig.symfony.com/doc/3.x/) +For more information, see [Templates](templates.md) and [Twig documentation](https://twig.symfony.com/doc/3.x/). ## Create content and test view templates -1\. Go to the Back Office, activate Content/Content structure and create a new content item by clicking **Create content**. +1\. Go to the back office, select **Content** -> **Content structure**, and create a new content item by clicking **Create content**. ![Creating a Blog Post](first-steps-create-content.png) -2\. Select a Blog Post content type. Fill in the content item and publish it. +2\. Select a Blog Post content type. +Fill in the content item and publish it. 3\. To preview the new content item on the front page, go to `/`. -For example, if the title of the Blog post is "First blog post", the address will be `/first-blog-post`. +For example, if the title of the Blog post is "First blog post", the address is `/first-blog-post`. ![Previewing Content](first-steps-preview-content.png) @@ -114,7 +106,8 @@ For example, if the title of the Blog post is "First blog post", the address wil You can use SiteAccesses to serve different versions of the website. -SiteAccesses are used depending on matching rules. They are set up in YAML configuration under the `ibexa.siteaccess.list` key. +SiteAccesses are used depending on matching rules. +They're set up in YAML configuration under the `ibexa.siteaccess.list` key. 1\. In `config/packages/ibexa.yaml` add a new SiteAccess called `de` for the German version of the website: @@ -127,29 +120,24 @@ ibexa: site_group: [site, de] ``` -The SiteAccess will automatically be matched using the last part of the URI. +The SiteAccess is automatically matched based on the last part of the URI. 2\. You can now access the front page through the new SiteAccess: `/de`. !!! note "Log in" - At this point you need to log in to preview the new SiteAccess, - because an anonymous visitor does not have permissions to view it. + At this point you need to log in to preview the new SiteAccess, because an anonymous visitor doesn't have permissions to view it. See [section about permissions below](#set-up-permissions). -For now the new SiteAccess does not differ from the main site. - -!!! tip "More information" +For now the new SiteAccess doesn't differ from the main site. - - [Multisite](multisite.md) - - [SiteAccess matchers](siteaccess_matching.md#available-siteaccess-matchers) +For more information, see [Multisite](multisite.md) and [SiteAccess matchers](siteaccess_matching.md#available-siteaccess-matchers). ## Add a language and translate Content One of the most common use cases for SiteAccesses is having different language versions of a site. -1\. To set up the `de` SiteAccess to use a different language, add its configuration under `ibexa.system`, -below `site.languages`: +1\. To set up the `de` SiteAccess to use a different language, add its configuration under `ibexa.system`, below `site.languages`: ``` yaml site: @@ -160,29 +148,28 @@ de: - eng-GB ``` -This means that German will be used as the main language for this SiteAccess, and English as a fallback. +This means that German is used as the main language for this SiteAccess, and English as a fallback. -2\. Go to the Back Office and select **Admin** > **Languages**. Add a new language called "German", with the language code `ger-DE`. -Make sure it is enabled. +2\. Go to the back office and select **Admin** > **Languages**. Add a new language called "German", with the language code `ger-DE`. +Make sure it's enabled. ![Creating a language](first-steps-create-language.png) -3\. Next, go to the Content structure and open the blog post you had created earlier. +3\. Next, go to the **Content structure** and open the blog post you had created earlier. Switch to the **Translations** tab and add a new translation. ![Adding a translation](first-steps-add-translation.png) -4\. Select German and base the new translation on the English version. Edit the content item and publish it. +4\. Select German and base the new translation on the English version. +Edit the content item and publish it. -5\. Go to the front page. The blog post will now display different content, depending on which SiteAccess you enter it from: +5\. Go to the front page. +The blog post now displays different content, depending on which SiteAccess you enter it from: `/` or `/de/`. ![Previewing translated Content](first-steps-translated-content.png) -!!! tip "More information" - - - [Languages](languages.md) - - [Set up translation SiteAccess](set_up_translation_siteaccess.md) +For more information, see [Languages](languages.md) and [Set up translation SiteAccess](set_up_translation_siteaccess.md). ## Add a design @@ -204,16 +191,17 @@ ibexa_design_engine: 3\. Under `site`, add `design: site_design` -4\. Go back to the `content_view` configuration for the blog post. Change the path to the template so that it points to the folder for the correct design: -`template: '@ibexadesign\full\blog_post.html.twig'` +4\. Go back to the `content_view` configuration for the blog post. +Change the path to the template so that it points to the folder for the correct design: `template: '@ibexadesign\full\blog_post.html.twig'` -This means that the app will look for the `blog_post.html.twig` file in a folder relevant for the SiteAccess: `de_design` for the `de` SiteAccess, or `site_design` for other SiteAccesses in `site_group`. +This means that the app looks for the `blog_post.html.twig` file in a folder relevant for the SiteAccess: `de_design` for the `de` SiteAccess, or `site_design` for other SiteAccesses in `site_group`. 5\. Create a `themes` folder under `templates`, and two folders under it: `de_design` and `site_design`. 6\. Move the existing `full\blog_post.html.twig` file under `site_design`. -7\. Copy it also under `de_design`. Modify the second one in any way (for example, add some html), so you can preview the effect. +7\. Copy it also under `de_design`. +Modify the second one in any way (for example, add some html), so you can preview the effect. 8\. To see the difference between the different themes, compare what is displayed at `/` and `/de/` @@ -221,19 +209,24 @@ This means that the app will look for the `blog_post.html.twig` file in a folder To allow a group of users to edit only a specific content type (in this example, blog posts), you need to set up permissions for them. -Users and User Groups are assigned Roles. A Role can contain a number of Policies, which are rules that permit the user to perform a specific function. -Policies can be additionally restricted by Limitations. +Users and user groups are assigned roles. +A role can contain a number of policies, which are rules that permit the user to perform a specific function. +Policies can be additionally restricted by limitations. -1\. Go to Admin > Users. Create a new User Group (the same way you create regular Content). +1\. Go to **Admin** -> **Users**. +Create a new user group (the same way you create regular content). Call the group "Bloggers". -2\. In the new group create a User. Remember their username and password. Mark the user as "Enabled". +2\. In the new group create a user. +Remember their username and password. +Mark the user as "Enabled". ![Creating a User](first-steps-create-user.png) -3\. Go to Admin > Roles. Create a new Role called "Blogger". +3\. Go to **Admin** -> **Roles**. +Create a new role called "Blogger". -4\. Add Policies that will allow the User to log in: +4\. Add policies that allow the user to log in: - `User/Login` - `Content/Read` @@ -241,21 +234,19 @@ Call the group "Bloggers". - `Section/View` - `Content/Reverserelatedlist` -5\. Now add Policies that will allow the User to create and publish content, limited to Blog Posts: - -- `Content/Create` with Limitation for content type Blog Post -- `Content/Edit` with Limitation for content type Blog Post -- `Content/Publish` with Limitation for content type Blog Post +5\. Now add policies that allow the user to create and publish content, limited to Blog Posts: -![Adding Limitations to a Policy](first-steps-policy-limitations.png) +- `Content/Create` with limitation for content type Blog Post +- `Content/Edit` with limitation for content type Blog Post +- `Content/Publish` with limitation for content type Blog Post -6\. In the Assignments tab assign the "Blogger" Role to the "Bloggers" group. +![Adding limitations to a policy](first-steps-policy-limitations.png) -![Assigning a Role](first-steps-assign-roles.png) +6\. In the **Assignments** tab assign the "Blogger" role to the "Bloggers" group. -You can now log out and log in again as the new User. -You will be able to create Blog Posts only. +![Assigning a role](first-steps-assign-roles.png) -!!! tip "More information" +You can now log out and log in again as the new user. +You're able to create Blog Posts only. - - [Permissions](permissions.md) +For more information, see [Permissions](permissions.md). diff --git a/docs/getting_started/install_ibexa_dxp.md b/docs/getting_started/install_ibexa_dxp.md index 73a77100e5..4edf449bd2 100644 --- a/docs/getting_started/install_ibexa_dxp.md +++ b/docs/getting_started/install_ibexa_dxp.md @@ -2,20 +2,18 @@ description: Install Ibexa DXP on a Linux system and prepare your installation for production. --- -# Install Ibexa DXP +# Install [[= product_name =]] !!! note Installation for production is only supported on Linux. - To install [[= product_name =]] for development on macOS or Windows, - see the [installation guide for macOS and Windows](install_on_mac_os_and_windows.md). + To install [[= product_name =]] for development on macOS or Windows, see the [installation guide for macOS and Windows](install_on_mac_os_and_windows.md). !!! note "Installing [[= product_name_oss =]]" This installation guide shows in details how to install [[= product_name =]] for users who have a subscription agreement with [[= product_name_base =]]. - If you want to install [[= product_name_oss =]], you do not need authentication tokens or an account on updates.ibexa.co, - but must adapt the steps shown here to the product edition and the `ibexa/oss-skeleton` repository. + If you want to install [[= product_name_oss =]], you don't need authentication tokens or an account on updates.ibexa.co, but must adapt the steps shown here to the product edition and the `ibexa/oss-skeleton` repository. ## Prepare work environment @@ -25,12 +23,12 @@ You can install it by following your favorite tutorial, for example: [Install LA Additional requirements: -- [Node.js](https://nodejs.org/en) and [Yarn](https://classic.yarnpkg.com/en/docs/install/#debian-stable) for asset management. -- `git` for version control. +- [Node.js](https://nodejs.org/en) and [Yarn](https://classic.yarnpkg.com/en/docs/install/#debian-stable) for asset management +- `git` for version control [For production](#prepare-installation-for-production) you also need Apache or nginx as the HTTP server (Apache is used as an example below). -Before getting started, make sure you review other [requirements](requirements.md) to see the systems we support and use for testing. +Before getting started, make sure you review other [requirements](requirements.md) to see the systems that is supported and used for testing. ### Get Composer @@ -59,7 +57,7 @@ composer -V ### Set up authentication tokens [[= product_name =]] subscribers have access to commercial packages at [updates.ibexa.co](https://updates.ibexa.co/). -The site is password-protected. +The site is password-protected. You must set up authentication tokens to access the site. Log in to your service portal on [support.ibexa.co](https://support.ibexa.co/), go to your **Service Portal**, and look for the following on the **Maintenance and Support agreement details** screen: @@ -67,14 +65,14 @@ Log in to your service portal on [support.ibexa.co](https://support.ibexa.co/), ![Authentication token](using_composer_auth_token.png) 1. Select **Create token** (this requires the **Portal administrator** access level). -2. Fill in a label describing the use of the token. This will allow you to revoke access later. -3. Save the password, **you will not get access to it again**! +2. Fill in a label describing the use of the token. +This allows you to revoke access later. +3. Save the password, **you aren't able to access it again**. !!! tip "Save the authentication token in `auth.json` to avoid re-typing it" - Composer will ask whether you want to save the token every time you perform an update. - If you prefer, you can decline and create an `auth.json` file globally - in [`COMPOSER_HOME`](https://getcomposer.org/doc/03-cli.md#composer-home) directory for machine-wide use: + Composer asks whether you want to save the token every time you perform an update. + If you prefer, you can decline and create an `auth.json` file globally in [`COMPOSER_HOME`](https://getcomposer.org/doc/03-cli.md#composer-home) directory for machine-wide use: ``` bash composer config --global http-basic.updates.ibexa.co @@ -85,22 +83,23 @@ Log in to your service portal on [support.ibexa.co](https://support.ibexa.co/), ``` bash export COMPOSER_AUTH='{"http-basic":{"updates.ibexa.co": {"username": "", "password": ""}}}' ``` - + You then need to [add the contents of this variable to `auth.json`](#authentication-token). !!! tip "Different tokens for different projects on a single host" - If you configure several projects on one machine, make sure that - you set different tokens for each of the projects in their respective `auth.json` files. + If you configure several projects on one machine, make sure that you set different tokens for each of the projects in their respective `auth.json` files. -After this, when running Composer to get updates, you will be asked for a username and password. Use: +After this, when running Composer to get updates, you're asked for a username and password. +Use: - as username - your Installation key found on the **Maintenance and Support agreement details** page in the service portal -- as password - the token password you retrieved in step 3 above. +- as password - the token password you retrieved in step 3 above !!! note "Authentication token validation delay" - You can encounter some delay between creating the token and being able to use it in Composer. It might take up to 15 minutes. + You can encounter some delay between creating the token and being able to use it in Composer. + It might take up to 15 minutes. !!! caution "Support agreement expiry" @@ -110,8 +109,7 @@ After this, when running Composer to get updates, you will be asked for a userna ### Create project -To use Composer to instantly create a project in the current folder with all the dependencies, -run the following command: +To use Composer to instantly create a project in the current folder with all the dependencies, run the following command: !!! note "Using PHP 8.3 (recommended)" @@ -135,7 +133,7 @@ run the following command: ??? note "Using PHP 8.2 or older" - If you are using PHP 8.2 or any older version, use a different set of commands: + If you're using PHP 8.2 or any older version, use a different set of commands: === "[[= product_name_headless =]]" @@ -160,13 +158,11 @@ run the following command: !!! tip "Authentication token" - If you added credentials to the `COMPOSER_AUTH` variable, - at this point add this variable to `auth.json` (for example, by running `echo $COMPOSER_AUTH > auth.json`). + If you added credentials to the `COMPOSER_AUTH` variable, at this point add this variable to `auth.json` (for example, by running `echo $COMPOSER_AUTH > auth.json`). !!! tip - You can set [different version constraints](https://getcomposer.org/doc/articles/versions.md): - specific tag (`3.3.2`), version range (`~3.3.2`), stability (`^3.3@rc`), etc.: + You can set [different version constraints](https://getcomposer.org/doc/articles/versions.md), for example, specific tag (`3.3.2`), version range (`~3.3.2`), or stability (`^3.3@rc`): ``` bash composer create-project ibexa/experience-skeleton:3.3.2 . @@ -174,18 +170,17 @@ run the following command: !!! note "Platform.sh" - If you are deploying your installation on [Platform.sh](https://docs.platform.sh/guides/ibexa/deploy.html), - run the following command: - + If you're deploying your installation on [Platform.sh](https://docs.platform.sh/guides/ibexa/deploy.html), run the following command: + ``` bash composer ibexa:setup --platformsh ``` - + This command provides the necessary configuration for using Platform.sh. #### Add project to version control -It is recommended to add your project to version control. +It's recommended to add your project to version control. Initiate your project repository: ``` bash @@ -194,8 +189,7 @@ git init; git add . > /dev/null; git commit -m "init" > /dev/null ### Change installation parameters -At this point configure your database via the `DATABASE_URL` in the `.env` file, -depending of the database you are using: +At this point configure your database via the `DATABASE_URL` in the `.env` file, depending of the database you're using: `DATABASE_URL=mysql://user:password@host:port/database_name`. @@ -211,30 +205,29 @@ or ### Add entropy to improve cryptographic randomness -Choose a [secret]([[= symfony_doc =]]/reference/configuration/framework.html#secret) -and provide it in the `APP_SECRET` parameter in `.env`. +Choose a [secret]([[= symfony_doc =]]/reference/configuration/framework.html#secret) and provide it in the `APP_SECRET` parameter in `.env`. It should be a random string, made up of at least 32 characters, numbers, and symbols. -This is used by Symfony when generating [CSRF tokens]([[= symfony_doc =]]/security/csrf.html), -[encrypting cookies]([[= symfony_doc =]]/cookbook/security/remember_me.html), -and for creating signed URIs when using [ESI (Edge Side Includes)]([[= symfony_doc =]]/http_cache/esi.html). +It's used by Symfony when generating [CSRF tokens]([[= symfony_doc =]]/security/csrf.html), [encrypting cookies]([[= symfony_doc =]]/cookbook/security/remember_me.html), and for creating signed URIs when using [ESI (Edge Side Includes)]([[= symfony_doc =]]/http_cache/esi.html). !!! caution - The app secret is crucial to the security of your installation. Be careful about how you generate it, and how you store it. + The app secret is crucial to the security of your installation. + Be careful about how you generate it, and how you store it. Here's one way to generate a 64 characters long, secure random string as your secret, from command line: - + ``` bash php -r "print bin2hex(random_bytes(32));" ``` - Do not commit the secret to version control systems, or share it with anyone who does not strictly need it. + Don't commit the secret to version control systems, or share it with anyone who doesn't strictly need it. If you have any suspicion that the secret may have been exposed, replace it with a new one. - The same goes for other secrets, like database password, Varnish invalidate token, JWT passphrase, etc. - + The same goes for other secrets, like database password, Varnish invalidate token, JWT passphrase, and more. + After changing the app secret, make sure that you clear the application cache and log out all the users. - For more information, see [Symfony documentation]([[= symfony_doc =]]/reference/configuration/framework.html#secret). - It is recommended to store the database credentials in your `.env.local` file and not commit it to the Version Control System. + For more information, see [Symfony documentation]([[= symfony_doc =]]/reference/configuration/framework.html#secret). + + It's recommended to store the database credentials in your `.env.local` file and not commit it to the Version Control System. In `DATABASE_VERSION` you can also configure the database server version (for a MariaDB database, prefix the value with `mariadb-`). @@ -277,8 +270,7 @@ php bin/console ibexa:graphql:generate-schema Before executing the command make sure that the database user has sufficient permissions. -If Composer asks for your token, you must log in to your GitHub account and generate a new token -(edit your profile and go to **Developer settings** > **Personal access tokens** > **Generate new token** with default settings). +If Composer asks for your token, you must log in to your GitHub account and generate a new token (edit your profile and go to **Developer settings** > **Personal access tokens** > **Generate new token** with default settings). This operation is performed only once, when you install [[= product_name =]] for the first time. ### Run post-installation script @@ -297,7 +289,7 @@ For development you can use the built-in PHP server. php -S 127.0.0.1:8000 -t public ``` -Your PHP web server will be accessible at `http://127.0.0.1:8000` +Your PHP web server is accessible at `http://127.0.0.1:8000` You can also use [Symfony CLI](https://symfony.com/download): @@ -339,19 +331,18 @@ chown -R www-data:www-data ``` Directories `var` and `public/var` must be writable by CLI and the web server user. -Future files and directories created by these two users will need to inherit those permissions. +Future files and directories created by these two users need to inherit those permissions. !!! caution - For security reasons, in production, the web server cannot have write access to other directories than `var`. + For security reasons, in production, the web server cannot have write access to other directories than `var`. Skip the step above and follow the link below for production needs instead. You must also make sure that the web server cannot interpret the files in the `var` directory through PHP. To do so, follow the instructions on [setting up a virtual host below](#set-up-virtual-host). -To set up permissions for production, it is recommended to use an ACL (Access Control List). -See [Setting up or Fixing File Permissions]([[= symfony_doc =]]/setup/file_permissions.html) in Symfony documentation -for information on how to do it on different systems. +To set up permissions for production, it's recommended to use an ACL (Access Control List). +See [Setting up or Fixing File Permissions]([[= symfony_doc =]]/setup/file_permissions.html) in Symfony documentation for information on how to do it on different systems. ### Set up virtual host @@ -363,8 +354,7 @@ Prepare a [virtual host configuration](https://en.wikipedia.org/wiki/Virtual_hos to `/etc/apache2/sites-available` as a `.conf` file and modify it to fit your project. Specify `//public` as the `DocumentRoot` and `Directory`, or ensure `BASEDIR` is set in the environment. - Uncomment the line that starts with `#if [APP_ENV]` and set the value to `prod` or `dev`, depending on the environment that you are configuring, - or ensure `APP_ENV` is set in the environment. + Uncomment the line that starts with `#if [APP_ENV]` and set the value to `prod` or `dev`, depending on the environment that you're configuring, or ensure `APP_ENV` is set in the environment. ``` SetEnvIf Request_URI ".*" APP_ENV=prod @@ -387,13 +377,11 @@ Prepare a [virtual host configuration](https://en.wikipedia.org/wiki/Virtual_hos === "nginx" - You can use [this example vhost file](https://raw.githubusercontent.com/ibexa/post-install/main/resources/templates/nginx/vhost.template) - and modify it to fit your project. You will also need the `ibexa_params.d` files that should reside in a subdirectory below where the main file is, - [as is shown here](https://github.com/ibexa/post-install/tree/main/resources/templates/nginx). + You can use [this example vhost file](https://raw.githubusercontent.com/ibexa/post-install/main/resources/templates/nginx/vhost.template) and modify it to fit your project. You also need the `ibexa_params.d` files that should reside in a subdirectory below where the main file is, [as is shown here](https://github.com/ibexa/post-install/tree/main/resources/templates/nginx). Specify `//public` as the `root`, or ensure `BASEDIR` is set in the environment. - Ensure `APP_ENV` is set to `prod` or `dev` in the environment, depending on the environment that you are configuring, and uncomment the line that starts with `#if[APP_ENV`. + Ensure `APP_ENV` is set to `prod` or `dev` in the environment, depending on the environment that you're configuring, and uncomment the line that starts with `#if[APP_ENV`. When the virtual host file is ready, enable the virtual host and disable the default. Finally, restart the nginx server. @@ -406,8 +394,7 @@ You should see the welcome page. !!! note "Security checklist" - See the [Security checklist](security_checklist.md) for a list of security-related issues - you should take care of before going live with a project. + See the [Security checklist](security_checklist.md) for a list of security-related issues you should take care of before going live with a project. ### Enable Date-based Publisher @@ -434,6 +421,6 @@ Finally, remove the temporary file: To make use of the [Link Manager](url_management.md#enabling-automatic-url-validation). -## Ibexa Cloud +## [[= product_name_cloud =]] -If you want to host your application on [[= product_name_cloud =]], follow the [Install on Ibexa Cloud](install_on_ibexa_cloud.md) procedure. +If you want to host your application on [[= product_name_cloud =]], follow the [Ibexa Cloud](install_on_ibexa_cloud.md) procedure. diff --git a/docs/getting_started/install_on_mac_os_and_windows.md b/docs/getting_started/install_on_mac_os_and_windows.md index c8489301ed..6349b8a423 100644 --- a/docs/getting_started/install_on_mac_os_and_windows.md +++ b/docs/getting_started/install_on_mac_os_and_windows.md @@ -11,7 +11,7 @@ This page explains how to install [[= product_name =]] on macOS or Windows. This procedure is **for development purposes only**. Installing [[= product_name =]] for production purposes is supported only on Linux. - For information about installing the product on Linux, see [Install [[= product_name =]]](install_ibexa_dxp.md). + For information about installing the product on Linux, see [Install [[= product_name =]]](install_ibexa_dxp.md). ### Prepare work environment @@ -22,7 +22,7 @@ If you want to use a web server, you need to install it as well: - For Windows: Apache - For macOS: Apache/nginx -The instructions below assume that you are using Apache. +The instructions below assume that you're using Apache. ??? note "Windows" @@ -39,7 +39,7 @@ The instructions below assume that you are using Apache. ``` bash zend_extension=opcache.so ``` - + You can install Apache as a Windows service by running the following command in CMD as administrator: ``` bash @@ -69,7 +69,7 @@ The instructions below assume that you are using Apache. === "Windows" - Download and run [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe) - it will install the latest Composer version. + Download and run [Composer-Setup.exe](https://getcomposer.org/Composer-Setup.exe) - it installs the latest Composer version. ## Install [[= product_name =]] @@ -88,7 +88,7 @@ Then restart the Apache server. ## Set up permissions Directories `var` and `web/var` need to be writable by CLI and web server user. -Future files and directories created by these two users will need to inherit those permissions. +Future files and directories created by these two users need to inherit those permissions. For more information, see [Setting up or Fixing File Permissions]([[= symfony_doc =]]/setup/file_permissions.html). diff --git a/docs/getting_started/install_with_ddev.md b/docs/getting_started/install_with_ddev.md index 4d39312782..ddfcf1c42a 100644 --- a/docs/getting_started/install_with_ddev.md +++ b/docs/getting_started/install_with_ddev.md @@ -52,12 +52,13 @@ To use MySQL instead, run the following command: ddev config --database=mysql:8.0 ``` -You can also use other versions of MariaDB, Mysql or PostgreSQL. +You can also use other versions of MariaDB, Mysql or PostgreSQL. See [DDEV database types documentation](https://ddev.readthedocs.io/en/latest/users/extend/database-types/) for available version ranges. #### Configure database connection -Now, configure the database connection for your [[= product_name =]] project. Depending on your database of choice (MySQL or PostgreSQL), use the appropriate command below. +Now, configure the database connection for your [[= product_name =]] project. +Depending on your database of choice (MySQL or PostgreSQL), use the appropriate command below. !!! note @@ -89,7 +90,8 @@ Now, configure the database connection for your [[= product_name =]] project. De #### Enable Mutagen (optional) -If you're using macOS or Windows, you might want to enable [Mutagen](https://ddev.readthedocs.io/en/latest/users/install/performance/#mutagen) to improve performance. You can do this by running the following command: +If you're using macOS or Windows, you might want to enable [Mutagen](https://ddev.readthedocs.io/en/latest/users/install/performance/#mutagen) to improve performance. +You can do this by running the following command: ```bash ddev config --performance-mode=mutagen @@ -122,13 +124,14 @@ ddev start Next, you need to [set up authentication tokens](install_ibexa_dxp.md#set-up-authentication-tokens) by modifying the Composer configuration. You must run the following command **after** executing `ddev start`, because the command runs inside the container. -Replace `` and `` with your actual installation key and token password, respectively. +Replace `` and `` with your actual installation key and token password. ```bash ddev composer config --global http-basic.updates.ibexa.co ``` -This authentication won't persist if the project is restarted (by `ddev restart` or `ddev composer create`). You can back up the authentication file (`auth.json`) by using the following command: +This authentication doesn't persist if the project is restarted (by `ddev restart` or `ddev composer create`). +You can back up the authentication file (`auth.json`) by using the following command: ```bash ddev exec "mkdir -p .ddev/homeadditions/.composer; cp ~/.composer/auth.json .ddev/homeadditions/.composer" @@ -138,8 +141,8 @@ If you want to reuse an existing `auth.json` file, see [Using `auth.json`](#usin ### 5. Create project -Once DDEV is running, use Composer to create a new [[= product_name =]] project. -Remember to replace `` and `` with your desired edition and version respectively. +Once DDEV is running, use Composer to create a new [[= product_name =]] project. +Remember to replace `` and `` with your desired edition and version. ```bash ddev composer create ibexa/-skeleton: @@ -185,10 +188,10 @@ DDEV offers several ways to get the same result, offering different levels of fl !!! tip Learn more about the [DDEV commands](https://ddev.readthedocs.io/en/latest/users/usage/commands/): - + - run [`ddev --help`](https://ddev.readthedocs.io/en/latest/users/usage/cli/#using-the-ddev-command) to list all commands - run [`ddev help `](https://ddev.readthedocs.io/en/latest/users/usage/commands/#help) to get usage details about a specific command - + Learn more about DDEV configuration from [`ddev config` command documentation](https://ddev.readthedocs.io/en/latest/users/usage/commands/#config) and [advanced configuration files documentation](https://ddev.readthedocs.io/en/latest/users/configuration/config/). @@ -196,11 +199,9 @@ DDEV offers several ways to get the same result, offering different levels of fl An `auth.json` file can be used for one project, or globally for all projects, with the [DDEV `homeaddition` feature](https://ddev.readthedocs.io/en/latest/users/extend/in-container-configuration/). -For example, you can copy an `auth.json` file to a DDEV project: -`cp /auth.json .ddev/homeadditions/.composer` +For example, you can copy an `auth.json` file to a DDEV project: `cp /auth.json .ddev/homeadditions/.composer` -Alternatively, the Composer global `auth.json` can be the DDEV global `auth.json` with the help of a symbolic link: -`mkdir -p ~/.ddev/homeadditions/.composer && ln -s ~/.composer/auth.json ~/.ddev/homeadditions/.composer/auth.json` +Alternatively, the Composer global `auth.json` can be the DDEV global `auth.json` with the help of a symbolic link: `mkdir -p ~/.ddev/homeadditions/.composer && ln -s ~/.composer/auth.json ~/.ddev/homeadditions/.composer/auth.json` If the DDEV project has already been started, you need to run `ddev restart`. @@ -274,7 +275,7 @@ For example, you can append it to [[= product_name_base =]]'s FastCGI config: echo 'fastcgi_param HTTPS $fcgi_https;' >> .ddev/nginx_full/ibexa_params.d/ibexa_fastcgi_params ``` -### Switch to Apache and its Virtual Host +### Switch to Apache and its virtual host To use Apache instead of the default Nginx, run the following command: @@ -282,14 +283,14 @@ To use Apache instead of the default Nginx, run the following command: ddev config --webserver-type=apache-fpm ``` -[[= product_name =]] can't run on Apache without a dedicated Virtual Host. +[[= product_name =]] can't run on Apache without a dedicated virtual host. -To set the Apache Virtual Host, override `.ddev/apache/apache-site.conf` with [[= product_name =]]'s config. +To set the Apache virtual host, override `.ddev/apache/apache-site.conf` with [[= product_name =]]'s config. You can do it manually or by using a script. #### Manual procedure -Copy the Virtual Host template as the new Apache configuration: +Copy the virtual host template as the new Apache configuration: ```bash cp vendor/ibexa/post-install/resources/templates/apache2/vhost.template .ddev/apache/apache-site.conf @@ -335,7 +336,7 @@ ddev restart #### Scripted procedure -Generate the Virtual Host with [`vhost.sh`](https://github.com/ibexa/docker/blob/main/scripts/vhost.sh): +Generate the virtual host with [`vhost.sh`](https://github.com/ibexa/docker/blob/main/scripts/vhost.sh): ```bash curl -O https://raw.githubusercontent.com/ibexa/docker/main/scripts/vhost.sh @@ -412,16 +413,17 @@ If the local project needs to answer to real production domains (for example, to As this feature modifies domain resolution, the real website may be unreachable until the `hosts` file is manually cleaned. -### Cluster or Ibexa Cloud +### Cluster or [[= product_name_cloud =]] -DDEV can be useful to locally simulate a production cluster. +You can use DDEV to locally simulate a production cluster. -- See [clustering with DDEV](clustering_with_ddev.md) to add Elasticsearch, Solr, Redis or Memcached to your DDEV installation. +- See [Clustering with DDEV](clustering_with_ddev.md) to add Elasticsearch, Solr, Redis, or Memcached to your DDEV installation. - See [DDEV and Ibexa Cloud](ddev_and_ibexa_cloud.md) to locally run an [[= product_name =]] project by using DDEV. ## Stop or remove the project -If you need to stop the project to start it again later, use `ddev stop`. Then, use `ddev start` to run the project in the same state. +If you need to stop the project to start it again later, use `ddev stop`. +Then, use `ddev start` to run the project in the same state. If you want to fully remove the project: diff --git a/docs/getting_started/requirements.md b/docs/getting_started/requirements.md index 8ac4ad6719..94377fff48 100644 --- a/docs/getting_started/requirements.md +++ b/docs/getting_started/requirements.md @@ -7,26 +7,29 @@ description: System, component and package requirements for running Ibexa DXP. # Requirements This document covers all supported versions of the product. -To review the requirements, select the specific version of Ibexa DXP you are interested in. +To review the requirements, select the specific version of [[= product_name =]] you're interested in. The following server requirements cover both running the software on-premise and on third-party PaaS providers. -!!! note "Ibexa Cloud" +!!! note "[[= product_name_cloud =]]" - For running on [Ibexa Cloud](https://www.ibexa.co/products/ibexa-cloud), where recommended configuration and support is provided out of the box, see separate [Ibexa Cloud section](#ibexa-cloud-requirements-and-setup) for further reading on its requirements. + For running on [[[= product_name_cloud =]]](https://www.ibexa.co/products/ibexa-cloud), where recommended configuration and support is provided out of the box, see separate [[[= product_name_cloud =]] section](#ibexa-cloud-requirements-and-setup) for further reading on its requirements. The minimal setup requires PHP, MySQL/MariaDB, Apache/Nginx, Node.js and `yarn`. Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, NFS/EFS/S3 and Solr/Elasticsearch in a [clustered setup](clustering.md). !!! caution "Recommended versions" - Review all the recommended versions carefully. If you see a "+" next to the product version, it means that we recommend this version or higher within the same major release. For example, "1.18+" means any 1.x version higher or equal to 1.18, but not 2.x. + Review all the recommended versions carefully. + If you see a "+" next to the product version, it means that we recommend this version or higher within the same major release. + For example, "1.18+" means any 1.x version higher or equal to 1.18, but not 2.x. - Using the latest listed version of each product or component is recommended. Always use a version that receives security updates, either by the vendor themselves or by a trusted third party, such as the distribution vendor. + Using the latest listed version of each product or component is recommended. + Always use a version that receives security updates, either by the vendor themselves or by a trusted third party, such as the distribution vendor. ## Operating system -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" |Name|Version| |---|---| @@ -36,9 +39,10 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, |Ubuntu "Jammy Jellyfish"| 22.04 | |RHEL / CentOS | 8.1-8.5+ | - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" |Name|Version| |---|---| @@ -48,7 +52,8 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, |Ubuntu "Jammy Jellyfish"| 22.04 | |RHEL / CentOS | 8.1-8.5+ | - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. === "eZ Platform v2.5" @@ -58,19 +63,21 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, |Ubuntu "Bionic" | 18.04 LTS | |RHEL / CentOS | 8.0-8.5+ | - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. ## Web server -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - Nginx 1.18-1.25+ - Apache 2.4 (with required modules `mod_rewrite`, `mod_env` and recommended: `mod_setenvif`, `mod_expires`; event MPM is recommended, if you need to use prefork you also need the `mod_php` module) - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - Nginx 1.18 - Apache 2.4 (with required modules `mod_rewrite`, `mod_env` and recommended: `mod_setenvif`, `mod_expires`; @@ -84,33 +91,37 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, ## DBMS -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - MariaDB 10.3-10.11+ - MySQL 8.0 - PostgreSQL 14 - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - MariaDB 10.3, 10.4 (optionally 10.2 - deprecated) - MySQL 8.0 (optionally 5.7 - deprecated) - PostgreSQL 10+ (PostgreSQL 10 has reached its End of Life. We highly recommend using PostgreSQL 14 for optimal performance and security) - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. === "eZ Platform v2.5" - MariaDB 10.3, 10.4 (optionally 10.2 - deprecated) - MySQL 8.0 (optionally 5.7 - deprecated) - - PostgreSQL 10+ (PostgreSQL 10 has reached its End of Life. We highly recommend using PostgreSQL 14 for optimal performance and security) + - PostgreSQL 10+ (PostgreSQL 10 has reached its End of Life. + We highly recommend using PostgreSQL 14 for optimal performance and security) - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. ## PHP -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - 8.3 - 8.2 @@ -118,7 +129,7 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, - 8.0 (PHP 8.0 has reached its End of Life. Unless you have extended support from vendors like Debian or Zend, you should use PHP 8.1) - 7.4 (PHP 7.4 has reached its End of Life. Unless you have extended support from vendors like Debian or Zend, you should use PHP 8.1) -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - 8.3 - 8.2 @@ -129,14 +140,17 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, === "eZ Platform v2.5" - - 7.1 (PHP 7.1 has reached its End of Life. Unless you have extended support from vendors like Debian or Zend, you should upgrade to Ibexa DXP v3.3 or v4.x) - - 7.2 (PHP 7.2 has reached its End of Life. Unless you have extended support from vendors like Debian or Zend, you should upgrade to Ibexa DXP v3.3 or v4.x) - - 7.3 (PHP 7.3 has reached its End of Life. Unless you have extended support from vendors like Debian or Zend, you should upgrade to Ibexa DXP v3.3 or v4.x) - - 7.4 (PHP 7.4 has reached its End of Life. Unless you have extended support from vendors like Debian or Zend, you should upgrade to Ibexa DXP v3.3 or v4.x) + - 7.1 (PHP 7.1 has reached its End of Life. + Unless you have extended support from vendors like Debian or Zend, you should upgrade to [[= product_name =]] v3.3 or v4.x) + - 7.2 (PHP 7.2 has reached its End of Life. Unless you have extended support from vendors like Debian or Zend, you should upgrade to [[= product_name =]]P v3.3 or v4.x) + - 7.3 (PHP 7.3 has reached its End of Life. + Unless you have extended support from vendors like Debian or Zend, you should upgrade to [[= product_name =]] v3.3 or v4.x) + - 7.4 (PHP 7.4 has reached its End of Life. + Unless you have extended support from vendors like Debian or Zend, you should upgrade to [[= product_name =]] v3.3 or v4.x) ### PHP extensions -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - `php-cli` - `php-fpm` @@ -152,7 +166,7 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, - `php-sodium` - `php-bcmath` -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - `php-cli` - `php-fpm` @@ -183,11 +197,11 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, ### Cluster PHP extensions -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - `php-redis` or `php-memcached` -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - `php-redis` or `php-memcached` @@ -195,30 +209,36 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, - `php-redis` 3.1.3+ or `php-memcached` 3.x+* - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. ## Search -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - - For content search, Solr 7.7 LTS or Solr 8, recommended 8.11.1 or higher. Alternatively, Elasticsearch 7.16.2 or higher 7.x version. - - The above solutions require Oracle Java/Open JDK. The minimum requirement is 8 LTS, recommended 11 LTS. Newer versions are not supported. + - For content search, Solr 7.7 LTS or Solr 8, recommended 8.11.1 or higher. + Alternatively, Elasticsearch 7.16.2 or higher 7.x version. + - The above solutions require Oracle Java/Open JDK. The minimum requirement is 8 LTS, recommended 11 LTS. + Newer versions aren't supported. -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - - For content search, Solr 7.7 LTS or Solr 8, recommended 8.11.1 or higher. Alternatively, Elasticsearch 7.16.2 or higher 7.x version. - - For BinaryFile Field indexing, Apache Tika 1.20 or higher 1.x version, recommended 1.28.1 or higher. - - The above solutions require Oracle Java/Open JDK. The minimum requirement is 8 LTS, recommended 11 LTS. Newer versions are not supported. + - For content search, Solr 7.7 LTS or Solr 8, recommended 8.11.1 or higher. + Alternatively, Elasticsearch 7.16.2 or higher 7.x version. + - For BinaryFile field indexing, Apache Tika 1.20 or higher 1.x version, recommended 1.28.1 or higher. + - The above solutions require Oracle Java/Open JDK. The minimum requirement is 8 LTS, recommended 11 LTS. Newer versions aren't supported. === "eZ Platform v2.5" - - For content search, Solr 7.7 LTS or Solr 8, recommended 8.11.1 or higher. Alternatively, Elasticsearch 7.16.2 or higher 7.x version. - - For BinaryFile Field indexing, Apache Tika 1.20 or higher 1.x version, recommended 1.28.1 or higher. - - The above solutions require Oracle Java/Open JDK. The minimum requirement is 8 LTS, recommended 11 LTS. Newer versions are not supported. + - For content search, Solr 7.7 LTS or Solr 8, recommended 8.11.1 or higher. + Alternatively, Elasticsearch 7.16.2 or higher 7.x version. + - For BinaryFile field indexing, Apache Tika 1.20 or higher 1.x version, recommended 1.28.1 or higher. + - The above solutions require Oracle Java/Open JDK. + The minimum requirement is 8 LTS, recommended 11 LTS. Newer versions aren't supported. ## Graphic Handler -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - GraphicsMagick - ImageMagick @@ -233,7 +253,7 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, - Gifsicle - cwebp -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - GraphicsMagick - ImageMagick @@ -256,21 +276,23 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, ## [Clustering](clustering.md) -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - Linux NFS or S3/EFS (for IO, aka binary files stored in content repository, not supported with legacy) - Redis 4.0+, 5.0 or higher (separate instances for session and cache, both using a `volatile-*` [eviction policy](https://redis.io/docs/reference/eviction/), session instance configured for persistence) or [Memcached](https://memcached.org/) 1.5 or higher - [Varnish](http://varnish-cache.org/) 6.0LTS or 7.1 with [varnish-modules](https://github.com/varnish/varnish-modules/blob/master/README.md) or [Fastly](https://www.fastly.com/) using [the provided bundle](http_cache.md) (for HTTP Cache) - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - Linux NFS or S3/EFS (for IO, aka binary files stored in content repository, not supported with legacy) - Redis 4.0+, 5.0 or higher (separate instances for session and cache, both using a `volatile-*` [eviction policy](https://redis.io/docs/reference/eviction/), session instance configured for persistence) or [Memcached](https://memcached.org/) 1.5 or higher - [Varnish](http://varnish-cache.org/) 6.0LTS with [varnish-modules](https://github.com/varnish/varnish-modules/blob/master/README.md) or [Fastly](https://www.fastly.com/) using [the provided bundle](https://doc.ibexa.co/en/3.3/guide/cache/http_cache/#serving-varnish-through-fastly) (for HTTP Cache) - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. === "eZ Platform v2.5" @@ -278,15 +300,16 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, - Redis 3.2+ (separate instances for session and cache, both using a `volatile-*` [eviction policy](https://redis.io/docs/reference/eviction/), session instance configured for persistence) or [Memcached](https://memcached.org/) 1.5 or higher - [Varnish](http://varnish-cache.org/) 5.1 or 6.0LTS with [varnish-modules](https://github.com/varnish/varnish-modules/blob/master/README.md) or [Fastly](https://www.fastly.com/) using [the provided bundle](https://doc.ibexa.co/en/2.5/guide/cache/http_cache/#serving-varnish-through-fastly) (for HTTP Cache) - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. ## Filesystem -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - Linux ext4 / XFS -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - Linux ext4 / XFS @@ -296,11 +319,11 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, ## Package manager -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - Composer: recent 2.7 version -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - Composer: recent 2.1 version @@ -310,41 +333,47 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, ## Asset manager -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - `Node.js` 18+ - `yarn` 1.15.2+ - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - - `Node.js` 14+, 16+, 18+ (`Node.js` 14+ has reached its End of Life. We strongly recommend using a newer version to ensure you receive security updates.) + - `Node.js` 14+, 16+, 18+ (`Node.js` 14+ has reached its End of Life. + We strongly recommend using a newer version to ensure you receive security updates.) - `yarn` 1.15.2+ - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. === "eZ Platform v2.5" - `Node.js` 10, 12 or 14 - `yarn` 1.15.2+ - If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. ## Browser -=== "Ibexa DXP v4.6" +=== "[[= product_name =]] v4.6" - Ibexa DXP is developed to work with *any* web browser that supports modern standards, on *any* screen resolution suitable for web, running on *any* device. However for the Editorial and Administration User Interfaces you'll need; a minimum of 1366-by-768 screen resolution, a desktop or tablet device, and a recommended/supported browser among the ones found below. + [[= product_name =]] is developed to work with *any* web browser that supports modern standards, on *any* screen resolution suitable for web, running on *any* device. + However for the Editorial and Administration User Interfaces you need: a minimum of 1366-by-768 screen resolution, a desktop or tablet device, and a recommended/supported browser among the ones found below. - Mozilla® Firefox® most recent stable version (recommended) - Google Chrome™ most recent stable version (recommended) - Chromium™ based browsers such as Microsoft® Edge® and Opera®, most recent stable version, desktop *and* tablet - Apple® Safari® most recent stable version, desktop *and* tablet -=== "Ibexa DXP v3.3" +=== "[[= product_name =]] v3.3" - Ibexa DXP is developed to work with *any* web browser that supports modern standards, on *any* screen resolution suitable for web, running on *any* device. However for the Editorial and Administration User Interfaces you'll need; a minimum of 1366-by-768 screen resolution, a desktop or tablet device, and a recommended/supported browser among the ones found below. + [[= product_name =]] is developed to work with *any* web browser that supports modern standards, on *any* screen resolution suitable for web, running on *any* device. + However for the Editorial and Administration User Interfaces you need: a minimum of 1366-by-768 screen resolution, a desktop or tablet device, and a recommended/supported browser among the ones found below. - Mozilla® Firefox® most recent stable version (recommended) - Google Chrome™ most recent stable version (recommended) @@ -353,108 +382,109 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, === "eZ Platform v2.5" - eZ Platform is developed to work with *any* web browser that supports modern standards, on *any* screen resolution suitable for web, running on *any* device. However for the Editorial and Administration User Interfaces you'll need; a minimum of 1366-by-768 screen resolution, a desktop or tablet device, and a recommended/supported browser among the ones found below. + eZ Platform is developed to work with *any* web browser that supports modern standards, on *any* screen resolution suitable for web, running on *any* device. + However for the Editorial and Administration User Interfaces you need: a minimum of 1366-by-768 screen resolution, a desktop or tablet device, and a recommended/supported browser among the ones found below. - Mozilla® Firefox® most recent stable version (recommended) - Google Chrome™ most recent stable version (recommended) - Chromium™ based browsers such as Microsoft® Edge® and Opera®, most recent stable version, desktop *and* tablet - Apple® Safari® most recent stable version, desktop *and* tablet -## Ibexa Cloud requirements and setup +## [[= product_name_cloud =]] requirements and setup -=== "Ibexa Cloud v4.6" +=== "[[= product_name_cloud =]] v4.6" - ### Cloud hosting with Ibexa Cloud and Platform.sh + ### Cloud hosting with [[= product_name_cloud =]] and Platform.sh - In general, Ibexa Cloud supports all features and services of [Platform.sh](https://platform.sh/marketplace/ibexa/) that are compatible and supported by the Ibexa DXP version you use. + In general, [[= product_name_cloud =]] supports all features and services of [Platform.sh](https://platform.sh/marketplace/ibexa/) that are compatible and supported by the [[= product_name =]] version you use. For example: - - Platform.sh provides Redis support for versions 3.2, 4.0 and 5.0. Ibexa DXP supports Redis version 4.0 or higher, and recommends 5.0. As a result, Redis is supported on Ibexa Cloud in versions 4.0 and 5.0, but 5.0 is recommended. + - Platform.sh provides Redis support for versions 3.2, 4.0 and 5.0. [[= product_name =]] supports Redis version 4.0 or higher, and recommends 5.0. + As a result, Redis is supported on [[= product_name_cloud =]] in versions 4.0 and 5.0, but 5.0 is recommended. - Features or services supported by Ibexa DXP but not covered by Platform.sh may be possible by means of a [custom integration](#custom-integrations). + Features or services supported by [[= product_name =]] but not covered by Platform.sh may be possible by means of a [custom integration](#custom-integrations). - ### Ibexa Cloud Setup support matrix + ### [[= product_name_cloud =]] Setup support matrix - All Ibexa DXP features are supported in accordance with the example above. For example: As Legacy Bridge is not supported with v3, it is not supported on Ibexa Cloud either. + All [[= product_name =]] features are supported in accordance with the example above. + For example: As Legacy Bridge isn't supported with v3, it's not supported on [[= product_name_cloud =]] either. !!! note - As Platform.sh does not support a configuration with multiple PostgreSQL databases, - for Ibexa Cloud / Platform.sh it is impossible to have a DFS table in a separate database. + As Platform.sh doesn't support a configuration with multiple PostgreSQL databases, for [[= product_name_cloud =]] / Platform.sh it's impossible to have a DFS table in a separate database. - ### Recommended Ibexa Cloud setup + ### Recommended [[= product_name_cloud =]] setup For more details on recommended setup configuration see bundled `.platform.app.yaml` and `.platform/` configuration files. These files are kept up-to-date with latest recommendations and can be improved through contributions. - ### Supported Ibexa Cloud setup + ### Supported [[= product_name_cloud =]] setup - Because of the large range of possible configurations of Ibexa DXP, there are many possibilities beyond what is provided in the default recommended configuration. + Because of the large range of possible configurations of [[= product_name =]], there are many possibilities beyond what is provided in the default recommended configuration. Make sure to set aside time and budget for: - - Verifying your requirements and ensuring they are supported by Platform.sh + - Verifying your requirements and ensuring they're supported by Platform.sh - Additional time for adaptation and configuration work, and testing by your development team - - Additional consulting/onboarding time with Platform.sh, Ibexa technical services, and/or one of the many partners with prior experience using Platform.sh with Ibexa DXP + - Additional consulting/onboarding time with Platform.sh, Ibexa technical services, and/or one of the many partners with prior experience in using Platform.sh with [[= product_name =]] - The cost and effort of this is not included in Ibexa Cloud subscription and will vary depending on the project. + The cost and effort of this isn't included in [[= product_name_cloud =]] subscription and is vary depending on the project. ### Custom integrations - Features supported by Ibexa DXP, but not natively by Platform.sh, can in many cases be used by means of custom integrations with external services. + Features supported by [[= product_name =]], but not natively by Platform.sh, can in many cases be used by means of custom integrations with external services. - For example, you can create an integration with S3 by means of setting up your own S3 bucket and configuring the relevant parts of Ibexa DXP. - We recommend giving the development team working on the project access to the bucket - to ensure work is done in a DevOps way without depending on external teams when changes are needed. + For example, you can create an integration with S3 by means of setting up your own S3 bucket and configuring the relevant parts of [[= product_name =]]. + We recommend giving the development team working on the project access to the bucket to ensure work is done in a DevOps way without depending on external teams when changes are needed. -=== "Ibexa Cloud v3.3" +=== "[[= product_name_cloud =]] v3.3" - ### Cloud hosting with Ibexa Cloud and Platform.sh + ### Cloud hosting with [[= product_name_cloud =]] and Platform.sh - In general, Ibexa Cloud supports all features and services of [Platform.sh](https://platform.sh/marketplace/ibexa/) that are compatible and supported by the Ibexa DXP version you use. + In general, [[= product_name_cloud =]] supports all features and services of [Platform.sh](https://platform.sh/marketplace/ibexa/) that are compatible and supported by the [[= product_name =]] version you use. For example: - - Platform.sh provides Redis support for versions 3.2, 4.0 and 5.0. Ibexa DXP supports Redis version 4.0 or higher, and recommends 5.0. As a result, Redis is supported on Ibexa Cloud in versions 4.0 and 5.0, but 5.0 is recommended. + - Platform.sh provides Redis support for versions 3.2, 4.0 and 5.0. [[= product_name =]] supports Redis version 4.0 or higher, and recommends 5.0. + As a result, Redis is supported on [[= product_name_cloud =]] in versions 4.0 and 5.0, but 5.0 is recommended. - Features or services supported by Ibexa DXP but not covered by Platform.sh may be possible by means of a [custom integration](#custom-integrations). + Features or services supported by [[= product_name =]] but not covered by Platform.sh may be possible by means of a [custom integration](#custom-integrations). - ### Ibexa Cloud Setup support matrix + ### [[= product_name_cloud =]] Setup support matrix - All Ibexa DXP features are supported in accordance with the example above. For example: As Legacy Bridge is not supported with v3, it is not supported on Ibexa Cloud either. + All [[= product_name =]] features are supported in accordance with the example above. + For example: As Legacy Bridge isn't supported with v3, it's not supported on [[= product_name_cloud =]] either. !!! note - As Platform.sh does not support a configuration with multiple PostgreSQL databases, - for Ibexa Cloud / Platform.sh it is impossible to have a DFS table in a separate database. + As Platform.sh doesn't support a configuration with multiple PostgreSQL databases, for [[= product_name_cloud =]] / Platform.sh it's impossible to have a DFS table in a separate database. - ### Recommended Ibexa Cloud setup + ### Recommended [[= product_name_cloud =]] setup For more details on recommended setup configuration see bundled `.platform.app.yaml` and `.platform/` configuration files. These files are kept up-to-date with latest recommendations and can be improved through contributions. - ### Supported Ibexa Cloud setup + ### Supported [[= product_name_cloud =]] setup - Because of the large range of possible configurations of Ibexa DXP, there are many possibilities beyond what is provided in the default recommended configuration. + Because of the large range of possible configurations of [[= product_name =]], there are many possibilities beyond what is provided in the default recommended configuration. Make sure to set aside time and budget for: - - Verifying your requirements and ensuring they are supported by Platform.sh + - Verifying your requirements and ensuring they're supported by Platform.sh - Additional time for adaptation and configuration work, and testing by your development team - - Additional consulting/onboarding time with Platform.sh, Ibexa technical services, and/or one of the many partners with prior experience using Platform.sh with Ibexa DXP + - Additional consulting/onboarding time with Platform.sh, Ibexa technical services, and/or one of the many partners with prior experience in using Platform.sh with [[= product_name =]] - The cost and effort of this is not included in Ibexa Cloud subscription and will vary depending on the project. + The cost and effort of this isn't included in [[= product_name_cloud =]] subscription and is vary depending on the project. ### Custom integrations - Features supported by Ibexa DXP, but not natively by Platform.sh, can in many cases be used by means of custom integrations with external services. + Features supported by [[= product_name =]], but not natively by Platform.sh, can in many cases be used by means of custom integrations with external services. - For example, you can create an integration with S3 by means of setting up your own S3 bucket and configuring the relevant parts of Ibexa DXP. - We recommend giving the development team working on the project access to the bucket - to ensure work is done in a DevOps way without depending on external teams when changes are needed. + For example, you can create an integration with S3 by means of setting up your own S3 bucket and configuring the relevant parts of [[= product_name =]]. + We recommend giving the development team working on the project access to the bucket to ensure work is done in a DevOps way without depending on external teams when changes are needed. === "eZ Platform Cloud v2.5" @@ -464,8 +494,10 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, For example: - - Platform.sh provides Redis support for versions 2.8, 3.0 and 3.2. eZ Platform supports Redis version 3.2 or higher. As a result, Redis is supported by eZ Platform Cloud versions 3.2. - - Platform.sh provides Elastic Search service (different versions supported). Elastic Search is not supported for use as search engine for eZ Platform. + - Platform.sh provides Redis support for versions 2.8, 3.0 and 3.2. eZ Platform supports Redis version 3.2 or higher. + As a result, Redis is supported by eZ Platform Cloud versions 3.2. + - Platform.sh provides Elasticsearch service (different versions supported). + Elasticsearch isn't supported for use as search engine for eZ Platform. Features or services supported by eZ Platform but not covered by Platform.sh may be possible by means of a [custom integration](#custom-integrations). @@ -480,31 +512,27 @@ Recommendation for production setups is to use Varnish/Fastly, Redis/Memcached, Because of the large range of possible configurations of eZ Publish legacy, there is no ready-made recommended setup. Make sure to set aside time and budget for: - - Verifying your legacy configuration and ensuring it is supported by Platform.sh + - Verifying your legacy configuration and ensuring it's supported by Platform.sh - Additional time for adaptation and configuration work, and testing by your own team - - Additional consulting/onboarding time with Platform.sh, Ibexa technical services, and/or one of the many partners with prior experience using Platform.sh with eZ Publish legacy + - Additional consulting/onboarding time with Platform.sh, Ibexa technical services, and/or one of the many partners with prior experience in using Platform.sh with eZ Publish legacy - The cost and effort of this is not included in eZ Platform Cloud subscription and will vary depending on the project. + The cost and effort of this isn't included in eZ Platform Cloud subscription and is vary depending on the project. ### Experimental/custom Platform.sh setups - Any use of experimental versions or setups is not eligible for use with eZ Platform Cloud. - However, it is possible to use an eZ Enterprise subscription in combination with a Platform.sh contract, - where you or a partner take ownership of the configuration to set up the project. + Any use of experimental versions or setups isn't eligible for use with eZ Platform Cloud. + However, it's possible to use an eZ Enterprise subscription in combination with a Platform.sh contract, where you or a partner take ownership of the configuration to set up the project. - Such projects are possible by means of custom integrations/configuration, - but they may generate issues that won't be covered by eZ Enterprise subscription bug fix guarantee. + Such projects are possible by means of custom integrations/configuration, but they may generate issues that aren't covered by eZ Enterprise subscription bug fix guarantee. !!! tip "Use a partner with prior experience on legacy and Platform.sh" - If you are in need of setting up your legacy project on Platform.sh for a transitional period, - eZ can put you in contact with a partner experienced in setting up older projects on Platform.sh. - This will save you a lot of time and effort. + If you're in need of setting up your legacy project on Platform.sh for a transitional period, eZ can put you in contact with a partner experienced in setting up older projects on Platform.sh. + This saves you a lot of time and effort. !!! note - As Platform.sh does not support a configuration with multiple PostgreSQL databases, - for eZ Platform Cloud / Platform.sh it is impossible to have a DFS table in a separate database. + As Platform.sh doesn't support a configuration with multiple PostgreSQL databases, for eZ Platform Cloud / Platform.sh it's impossible to have a DFS table in a separate database. ### Custom integrations diff --git a/docs/getting_started/troubleshooting.md b/docs/getting_started/troubleshooting.md index 8a9cff5a00..35810d8dd7 100644 --- a/docs/getting_started/troubleshooting.md +++ b/docs/getting_started/troubleshooting.md @@ -8,12 +8,12 @@ This page lists potential problems that you may encounter while installing, conf ## Encoding database password -The password entered in `DATABASE_URL` during installation must either be URL encoded, -or not contain any special characters that would require URL encoding. +The password entered in `DATABASE_URL` during installation must either be URL encoded, or not contain any special characters that would require URL encoding. ### URL encoding -Using URL encoding involves two steps. First, the password must be URL encoded. This can for instance be done with PHP's `urlencode()` function. +Using URL encoding involves two steps. +First, the password must be URL encoded. This can for instance be done with PHP's `urlencode()` function. For example, this function converts a password like `(/!=#Ƥ*;%?[` to `%28%2F%21%3D%23%C3%86%C2%A4%2A%3B%25%3F%5B`. Second, you must remove `resolve:` from `doctrine.dbal.url` in `config/packages/doctrine.yaml`. @@ -22,27 +22,27 @@ That means changing `%env(resolve:DATABASE_URL)%` to `%env(DATABASE_URL)%`. ### Avoid special characters If your password only contains letters a-z, A-Z, and numbers 0-9, you don't need to do any encoding. -You can either create your password that way, in which case it is a good idea to make it longer to maintain entropy, -keeping the password hard to guess for an attacker. -Or, you can for instance convert your password with `bin2hex()`, so that e.g. `(/!=#Ƥ*;%?[` becomes `282f213d23c386c2a42a3b253f5b`. -The output from `bin2hex` is limited to 0-9 and a-f. This more than doubles the length of the password, keeping entropy similar. +You can either create your password that way, in which case it's a good idea to make it longer to maintain entropy, keeping the password hard to guess for an attacker. +Or, you can for instance convert your password with `bin2hex()`, so that, for example, `(/!=#Ƥ*;%?[` becomes `282f213d23c386c2a42a3b253f5b`. +The output from `bin2hex` is limited to 0-9 and a-f. +This more than doubles the length of the password, keeping entropy similar. ## Enabling swap with limited RAM If you have problems installing [[= product_name =]] on a system with limited RAM (for example 1GB or 2GB), enable swap. It allows your operating system to use the hard disk to supplement RAM when it runs out. -With swap enables you will be able to successfully run `php -d memory_limit=-1 bin/console ibexa:install --env prod ezplatform-clean`. +With swap enabled you're able to successfully run `php -d memory_limit=-1 bin/console ibexa:install --env prod ezplatform-clean`. -When a system runs out of RAM, you may see `Killed` when trying to clear the cache (e.g. `php bin/console --env=prod cache:clear` from your project's root directory). +When a system runs out of RAM, you may see `Killed` when trying to clear the cache (for example, `php bin/console --env=prod cache:clear` from your project's root directory). ## Upload size limit -To make use of the Back Office, the defined maximum upload size must be consistent with the maximum file size defined in the content type using a File, Media or Image Field. +To make use of the back office, the defined maximum upload size must be consistent with the maximum file size defined in the content type by using a File, Media, or Image field. -This is done by setting `LimitRequestBody` for Apache or `client_max_body_size` for nginx. +It's done by setting `LimitRequestBody` for Apache or `client_max_body_size` for nginx. -For instance, if one of those Fields is configured to accept files up to 10MB, then `client_max_body_size` (in case of nginx) should be set above 10MB, with a safe margin, for example to 15MB. +For instance, if one of those fields is configured to accept files up to 10MB, then `client_max_body_size` (in case of nginx) should be set above 10MB, with a safe margin, for example to 15MB. You also need to define settings for uploading files in `php.ini`: `upload_max_filesize` and `post_max_size`. @@ -58,16 +58,13 @@ To avoid the error, check the stability of packages and avoid using `--prefer-s ### Inconsistent cache/session data -If cache or session data inconsistent across web servers in Redis, -see [Redis clustering](persistence_cache.md#redis-clustering), and make sure you only read/write to -one active master instance at a time. +If cache or session data inconsistent across web servers in Redis, see [Redis clustering](persistence_cache.md#redis-clustering), and make sure you only read/write to one active master instance at a time. ### Removed or refused sessions If Redis sessions are removed or new sessions are refused. -see info on [Cluster setup](sessions.md#cluster-setup). -Ideally, use a separated instance of Redis for sessions, -that either never runs out of memory or uses an eviction policy that suits your needs. +For more information, see [Cluster setup](sessions.md#cluster-setup). +It's recommended to use a separated instance of Redis for sessions, that either never runs out of memory or uses an eviction policy that suits your needs. ## Conflict with roave/security-advisories @@ -84,15 +81,13 @@ This means there is a known security bug in the specific version of the package, In most cases this means that a fix is available in a newer version. If you increase your requirement to that version, the conflict is resolved. -In the rare case when there is no fixed version, you can revert your requirement to an older version which does not have the bug. +In the rare case when there is no fixed version, you can revert your requirement to an older version which doesn't have the bug. If you have to use the version with the bug (not recommended) you can use `composer remove roave/security-advisories`. In such case, require it again when the bug is fixed and the package is updated: `composer require roave/security-advisories:dev-master`  ## Platform.sh HTTP access credentials with Varnish -If you are using Platform.sh with Varnish for HTTP cache -and you have [HTTP access control by login/password](https://docs.platform.sh/administration/web/configure-environment.html#http-access-control) enabled, -configure the following variables in your Platform.sh environment: +If you're using Platform.sh with Varnish for HTTP cache and you have [HTTP access control by login/password](https://docs.platform.sh/administration/web/configure-environment.html#http-access-control) enabled, configure the following variables in your Platform.sh environment: - `HTTPCACHE_USERNAME` - `HTTPCACHE_PASSWORD` diff --git a/docs/ibexa_cloud/ddev_and_ibexa_cloud.md b/docs/ibexa_cloud/ddev_and_ibexa_cloud.md index edd6c73e41..c1fc1e1a3d 100644 --- a/docs/ibexa_cloud/ddev_and_ibexa_cloud.md +++ b/docs/ibexa_cloud/ddev_and_ibexa_cloud.md @@ -2,7 +2,7 @@ description: Use DDEV to run an Ibexa Cloud project locally. --- -# DDEV and Ibexa Cloud +# DDEV and [[= product_name_cloud =]] Two ways are available to run an [[= product_name_cloud =]] project locally with DDEV: @@ -11,28 +11,35 @@ Two ways are available to run an [[= product_name_cloud =]] project locally with !!! note - The following examples use [Ibexa Cloud CLI (`ibexa_cloud`)](https://cli.ibexa.co/). + The following examples use [[[= product_name_cloud =]] CLI (`ibexa_cloud`)](https://cli.ibexa.co/). ## With the `ddev-platformsh` add-on To configure the [`ddev/ddev-platformsh` add-on](https://github.com/ddev/ddev-platformsh), you need a [Platform.sh API Token](https://docs.platform.sh/administration/cli/api-tokens.html). -The `ddev/ddev-platformsh` add-on configures the document root, the PHP version, the database, and the cache pool according to the [[= product_name_cloud =]] configuration. About the search engine, the add-on can configure Elasticsearch but can't configure Solr. If you use Solr on [[= product_name_cloud =]] and want to add it to your DDEV stack, see [clustering with DDEV and `ibexa/ddev-solr` add-on](clustering_with_ddev.md#solr). +The `ddev/ddev-platformsh` add-on configures the document root, the PHP version, the database, and the cache pool according to the [[= product_name_cloud =]] configuration. +About the search engine, the add-on can configure Elasticsearch but can't configure Solr. +If you use Solr on [[= product_name_cloud =]] and want to add it to your DDEV stack, see [Clustering with DDEV and `ibexa/ddev-solr` add-on](clustering_with_ddev.md#solr). `COMPOSER_AUTH` from Platform.sh can't be used, because JSON commas are incorrectly interpreted by `--web-environment-add`, which sees them as multiple variable separators. -But the variable must exist for Platform.sh `hooks` scripts to work. To use an `auth.json` file for this purpose, see [Using `auth.json`](install_with_ddev.md#using-authjson). +But the variable must exist for Platform.sh `hooks` scripts to work. +To use an `auth.json` file for this purpose, see [Using `auth.json`](install_with_ddev.md#using-authjson). You must remove Node.js and NVM installations as they're already included in DDEV. The following sequence of commands: -1. Downloads the [[= product_name_cloud =]] Platform.sh project from the default environment "production" into a new directory using [Platform.sh CLI alias `ibexa_cloud` defined in introduction](#ibexa-cloud-and-ddev). (Replace `` with the hash of your own project. See [`ibexa_cloud help get`](https://docs.platform.sh/administration/cli.html#3-use) for options like selecting another environment). +1. Downloads the [[= product_name_cloud =]] Platform.sh project from the default environment "production" into a new directory, based on the [Platform.sh CLI alias `ibexa_cloud` defined in introduction](#ibexa-cloud-and-ddev). +(Replace `` with the hash of your own project. +See [`ibexa_cloud help get`](https://docs.platform.sh/administration/cli.html#3-use) for options like selecting another environment). 1. Configures a new DDEV project. -1. Ignores `.ddev/` directory from Git. (Some DDEV config could be committed like in [this documentation](https://ddev.readthedocs.io/en/latest/users/extend/customization-extendibility/#extending-configyaml-with-custom-configyaml-files).) +1. Ignores `.ddev/` directory from Git. +(Some DDEV config could be committed like in [this documentation](https://ddev.readthedocs.io/en/latest/users/extend/customization-extendibility/#extending-configyaml-with-custom-configyaml-files).) 1. Sets Composer authentication by using an already existing `auth.json` file. 1. Creates a `public/var` directory if it doesn't exist, to allow the creation of `public/var/.platform.installed` by Platform.sh hook script. 1. Installs the `ddev/ddev-platformsh` add-on which prompts for the Platform.sh API token, project ID and environment name. -1. Comments out the Node.js and NVM installations from the hooks copied in `.ddev/config.platformsh.yaml`. (In this file, you may have to discard other specific features like New Relic.) +1. Comments out the Node.js and NVM installations from the hooks copied in `.ddev/config.platformsh.yaml`. +(In this file, you may have to discard other specific features like New Relic.) 1. Changes `maxmemory-policy` from default `allkeys-lfu` to a [value accepted by the `RedisTagAwareAdapter`](https://github.com/symfony/cache/blob/5.4/Adapter/RedisTagAwareAdapter.php#L95). 1. Starts the project. 1. Gets the content from Platform.sh, both database and binary files by using `ddev pull platform` feature from the add-on. @@ -58,7 +65,7 @@ ddev launch !!! note - The Platform.sh API token is set at user profile level, therefore it is stored globally under current user root as `PLATFORMSH_CLI_TOKEN` in `~/.ddev/global_config.yaml`. + The Platform.sh API token is set at user profile level, therefore it's stored globally under current user root as `PLATFORMSH_CLI_TOKEN` in `~/.ddev/global_config.yaml`. ## Without the Platform.sh add-on @@ -66,9 +73,11 @@ The following example adapts the [manual method to run an already existing proje The following sequence of commands: -1. Downloads the [[= product_name_cloud =]] Platform.sh project from the default environment "production" into a new directory using [Platform.sh CLI alias `ibexa_cloud` defined in introduction](#ibexa-cloud-and-ddev). (Replace `` with the hash of your own project. See [`ibexa_cloud help get`](https://docs.platform.sh/administration/cli.html#3-use) for options like selecting another environment). +1. Downloads the [[= product_name_cloud =]] Platform.sh project from the default environment "production" into a new directory, based on the [Platform.sh CLI alias `ibexa_cloud` defined in introduction](#ibexa-cloud-and-ddev). +(Replace `` with the hash of your own project. See [`ibexa_cloud help get`](https://docs.platform.sh/administration/cli.html#3-use) for options like selecting another environment). 1. Configures a new DDEV project. -1. Ignores `.ddev/` directory from Git. (Some DDEV config could be committed like in [this documentation](https://ddev.readthedocs.io/en/latest/users/extend/customization-extendibility/#extending-configyaml-with-custom-configyaml-files).) +1. Ignores `.ddev/` directory from Git. +(Some DDEV config could be committed like in [this documentation](https://ddev.readthedocs.io/en/latest/users/extend/customization-extendibility/#extending-configyaml-with-custom-configyaml-files).) 1. Starts the DDEV project. 1. Sets Composer authentication. 1. [Gets the database content from Platform.sh](https://docs.platform.sh/add-services/mysql.html#exporting-data). @@ -94,4 +103,4 @@ ddev launch From there, services can be added to get closer to [[= product_name_cloud =]] Platform.sh architecture. `.platform/services.yaml` indicates the services used. -Refer to [clustering with DDEV](clustering_with_ddev.md) for those additions. +For more information, see [Clustering with DDEV](clustering_with_ddev.md). diff --git a/docs/ibexa_cloud/ibexa_cloud.md b/docs/ibexa_cloud/ibexa_cloud.md index 749f96ac26..2635127a5d 100644 --- a/docs/ibexa_cloud/ibexa_cloud.md +++ b/docs/ibexa_cloud/ibexa_cloud.md @@ -6,10 +6,10 @@ month_change: false # [[= product_name_cloud =]] -[[= product_name_cloud =]] is a cloud hosting platform that enables you to host your application in the cloud using the Platform.sh service. +[[= product_name_cloud =]] is a cloud hosting platform that enables you to host your application in the cloud by using the Platform.sh service. [[= cards([ -"ibexa_cloud/ibexa_cloud_guide", -"ibexa_cloud/install_on_ibexa_cloud", -"ibexa_cloud/ddev_and_ibexa_cloud", + "ibexa_cloud/ibexa_cloud_guide", + "ibexa_cloud/install_on_ibexa_cloud", + "ibexa_cloud/ddev_and_ibexa_cloud", ], columns=3) =]] diff --git a/docs/ibexa_cloud/ibexa_cloud_guide.md b/docs/ibexa_cloud/ibexa_cloud_guide.md index 709d40eb1f..67876c3ced 100644 --- a/docs/ibexa_cloud/ibexa_cloud_guide.md +++ b/docs/ibexa_cloud/ibexa_cloud_guide.md @@ -41,16 +41,18 @@ When you have an account, you can log in to https://console.ibexa.cloud. ### Platform as a Service -[[= product_name_cloud =]] is a PaaS provider. It's a cloud-based subscription service that you can use for developing, managing, and running applications without infrastructure concerns. +[[= product_name_cloud =]] is a PaaS provider. +It's a cloud-based subscription service that you can use for developing, managing, and running applications without infrastructure concerns. This cloud computing approach gives users access to a full cloud platform, including hardware, software, and infrastructure. -PaaS eliminates the requirement to buy and install the necessary hardware and software. All you have to do is access it and you can start deploying resources and developing right away. +PaaS eliminates the requirement to buy and install the necessary hardware and software. +All you have to do is access it and you can start deploying resources and developing right away. ![How PaaS works](how_paas_works.png) ### Performance management Make your applications more effective, scalable, and effective by using the [Observability Suite](https://platform.sh/features/observability-suite/). -This package gives you the the ability to test, profile, and monitor your application before putting it into production. +This package gives you the ability to test, profile, and monitor your application before putting it into production. Observability Suite comes with each [[= product_name_cloud =]] subscription. ### Automation @@ -74,7 +76,8 @@ What's more, [[= product_name_cloud =]] as an end-to-end cloud hosting platform, Comprehensive data security procedures guarantee that you maintain complete ownership of your client's data, defining where it's stored. You can be sure that the safety protocols are compliant with all applicable legislation. -What's more, all updates to your code and infrastructure are fully auditable. Global CDN (Content Delivery Network) is included and fully managed. +What's more, all updates to your code and infrastructure are fully auditable. +Global CDN (Content Delivery Network) is included and fully managed. [[= product_name_cloud =]], thanks to extensive [[= product_name_base =]] support, enables effortless deployment. You can create a clone not only of the code, but also data and the infrastructure. As the infrastructure is exactly the same as what's currently in production, you can be sure that everything works well when you conduct your release and push it live. @@ -82,7 +85,8 @@ As the infrastructure is exactly the same as what's currently in production, you ### High availability and compatibility [[= product_name_cloud =]] is compatible with your choice of public cloud server and supports a variety of hosting platforms. -It's a Git-native development - compatible with Git Flow. [[= product_name_cloud =]] deployment integrates naturally at the end of your existing production chain, including staging, and work in progress branch preview. +It's a Git-native development - compatible with Git Flow. +[[= product_name_cloud =]] deployment integrates naturally at the end of your existing production chain, including staging, and work in progress branch preview. You can also integrate with, for example, Bitbucket, GitHub, Gitlab. You can instantly clone every branch of both your code and infrastructure configuration. Platform.sh (and [[= product_name_cloud =]], by extension) uses the [Infrastracture as Code approach](https://docs.platform.sh/learn/overview.html#infrastructure-as-code). diff --git a/docs/ibexa_cloud/install_on_ibexa_cloud.md b/docs/ibexa_cloud/install_on_ibexa_cloud.md index 164cffb10a..21fa0b9bfc 100644 --- a/docs/ibexa_cloud/install_on_ibexa_cloud.md +++ b/docs/ibexa_cloud/install_on_ibexa_cloud.md @@ -2,7 +2,7 @@ description: Install and configure Ibexa DXP to run in cloud using Ibexa Cloud. --- -# Install on Ibexa Cloud +# Install on [[= product_name_cloud =]] [[= product_name_cloud =]] enables you to host your application in the cloud by using the [Platform.sh](https://platform.sh/) service. @@ -22,15 +22,13 @@ You can adapt the configuration in the following places: - `.platform/services.yml` - additional services such as search engines or cache - `.platform/routes.yml` - routes to additional services, for example Fastly -For details about available configuration settings, -refer to [Platform.sh documentation](https://docs.platform.sh/create-apps.html). +For details about available configuration settings, refer to [Platform.sh documentation](https://docs.platform.sh/create-apps.html). ### Disk space The total disk space depends on your [[= product_name_cloud =]] subscription level. You can assign disk space to the main app container under the `disk` key. -You can distribute the remaining space between other containers (for example, the database) or search engine -in `.platform/services.yaml`, under the individual service definitions. +You can distribute the remaining space between other containers (for example, the database) or search engine in `.platform/services.yaml`, under the individual service definitions. ### Build and deploy process @@ -44,14 +42,11 @@ Configuration under `hooks` defines the process of building and deploying your p ### Additional services -`.platform/services.yaml` contains preconfigured setting blocks that you can uncomment -to enable services such as Solr or Elasticsearch, or persistent Redis session storage. +`.platform/services.yaml` contains preconfigured setting blocks that you can uncomment to enable services such as Solr or Elasticsearch, or persistent Redis session storage. -For information about available services, -see [Platform.sh documentation](https://docs.platform.sh/add-services.html#available-services). +For information about available services, see [Platform.sh documentation](https://docs.platform.sh/add-services.html#available-services). -If you enable any of the services, you must uncomment the relevant relationship -under the `relationship` key in `.platform.app.yaml` as well. +If you enable any of the services, you must uncomment the relevant relationship under the `relationship` key in `.platform.app.yaml` as well. ## 2. Create an account @@ -79,13 +74,13 @@ This ensures that the token isn't exposed. ## 4. Push the project -When you are done with configuration, push your project to the Platform.sh remote: +When you're done with configuration, push your project to the Platform.sh remote: ``` bash git push -u master ``` -You can also use the [Ibexa Cloud CLI](https://cli.ibexa.cloud/) to push your code. +You can also use the [[[= product_name_cloud =]] CLI](https://cli.ibexa.cloud/) to push your code. ``` bash ibexa_cloud push master @@ -97,11 +92,11 @@ ibexa_cloud push master !!! caution - Do not use Platform.sh CLI (`platform`), instead, use the [Ibexa Cloud CLI (`ibexa_cloud`)](https://cli.ibexa.cloud/). + Don't use Platform.sh CLI (`platform`), instead, use the [[[= product_name_cloud =]] CLI (`ibexa_cloud`)](https://cli.ibexa.cloud/). - To install Ibexa Cloud CLI, follow https://cli.ibexa.cloud/ "Installation instructions". + To install [[= product_name_cloud =]] CLI, follow https://cli.ibexa.cloud/ "Installation instructions". - Ibexa Cloud CLI and Platform.sh CLI share the same commands and the [same documentation](https://docs.platform.sh/administration/cli.html#3-use), but you have to replace `platform` with `ibexa_cloud`. + [[= product_name_cloud =]] CLI and Platform.sh CLI share the same commands and the [same documentation](https://docs.platform.sh/administration/cli.html#3-use), but you have to replace `platform` with `ibexa_cloud`. - If you have previously set up an alias to use Platform.sh CLI with Ibexa Cloud, it is outdated. - Remove the alias and install Ibexa Cloud CLI instead. + If you have previously set up an alias to use Platform.sh CLI with [[= product_name_cloud =]], it's outdated. + Remove the alias and install [[= product_name_cloud =]] CLI instead. diff --git a/docs/ibexa_engage/create_campaign.md b/docs/ibexa_engage/create_campaign.md index 5fac820998..5cf16b067c 100644 --- a/docs/ibexa_engage/create_campaign.md +++ b/docs/ibexa_engage/create_campaign.md @@ -6,29 +6,32 @@ edition: experience # Create campaign [Campaign]([[= user_doc =]]/ibexa_engage/ibexa_engage/#campaign) is a set of concepts, divided into steps, that the user can configure. -It can contain a welcome screen, an interaction element, a form step, an exit screen, and so on. +It can contain, for example, a welcome screen, an interaction element, a form step, and an exit screen. To create new campaign, you need to use Qualifio Manager. You can use Qualifio's existing templates and interactive elements, such as quizzes, pools, and forms, to create visually appealing, customized campaigns. Users can configure the backgrounds, themes, or designs, and set up a specific time frame for each campaign. -Technically, each campaign has a unique campaign ID, that is automatically defined by the Qualifio platform when it is created. +Technically, each campaign has a unique campaign ID, that is automatically defined by the Qualifio platform when it's created. For more information about creating and managing campaigns, see [Qualifio documentation](https://support.qualifio.com/hc/en-us/categories/202280638-Campaigns). ## Publication channels Each campaign includes a minimum of one publication channel that you can choose from the three options the platform provides for publishing a campaign. -For more information about publication channels, see [Publication channel]([[= user_doc =]]/ibexa_engage/ibexa_engage/#publication-channel) in the User Documentation. +For more information about publication channels, see [Publication channel]([[= user_doc =]]/ibexa_engage/ibexa_engage/#publication-channel) in User Documentation. ## Use Campaign block in Page Builder -You can add [Campaign block]([[= user_doc =]]/content_management/block_reference/#campaign-block) in Page Builder to display campaign on the Landing Page. +You can add [Campaign block]([[= user_doc =]]/content_management/block_reference/#campaign-block) in Page Builder to display campaign on the landing page. -To select campaign, go to **Properties** tab. From the **Campaign** drop-down, choose campaign. +To select campaign, go to **Properties** tab. +From the **Campaign** drop-down, choose campaign. This list includes all campaigns available on user's Qualifio account which are active or scheduled to launch in the future. -You can set the dimensions of the field in which the campaign is displayed. To do it, insert width and height values in the proper fields. -If size fields are blank, the system sets default template values. It's recommended to adjust them for better results. +You can set the dimensions of the field in which the campaign is displayed. +To do it, insert width and height values in the proper fields. +If size fields are blank, the system sets default template values. +It's recommended to adjust them for better results. ![Campaign block](campaign_block.png "Campaign block") @@ -38,7 +41,9 @@ You can embed campaign in the Rich text field with Campaign custom tag. To do it, insert **Campaign** content item in the Rich Text Field and choose campaign from the drop-down list. This list includes all campaigns available on user's Qualifio account which are active or scheduled to launch in the future. -You can set the dimensions of the field in which the campaign is displayed. To do it, select units, and provide width and height values in the proper fields. -If size fields are blank, the system sets default template values. It's recommended to adjust them for better results. +You can set the dimensions of the field in which the campaign is displayed. +To do it, select units, and provide width and height values in the proper fields. +If size fields are blank, the system sets default template values. +It's recommended to adjust them for better results. ![Campaign custom tag](campaign_custom_tag.png "Campaign custom tag") \ No newline at end of file diff --git a/docs/ibexa_engage/ibexa_engage.md b/docs/ibexa_engage/ibexa_engage.md index 7b14a7704a..5fc2515d68 100644 --- a/docs/ibexa_engage/ibexa_engage.md +++ b/docs/ibexa_engage/ibexa_engage.md @@ -7,7 +7,8 @@ month_change: false # [[= product_name_engage =]] [[= product_name_engage =]] is a data collection tool. -It gives you the ability to use the [Qualifio](https://qualifio.com/) tools to engage your audiences. You can use interactive content to build relationships and collect important data, for example, a list of recent orders, or personal information about customers. +It gives you the ability to use the [Qualifio](https://qualifio.com/) tools to engage your audiences. +You can use interactive content to build relationships and collect important data, for example, a list of recent orders, or personal information about customers. You can also integrate [[= product_name_engage =]] with [[= product_name_connect =]] to create workflows. [[= cards([ diff --git a/docs/ibexa_engage/install_ibexa_engage.md b/docs/ibexa_engage/install_ibexa_engage.md index 33627eb8e9..3fd434419e 100644 --- a/docs/ibexa_engage/install_ibexa_engage.md +++ b/docs/ibexa_engage/install_ibexa_engage.md @@ -13,9 +13,10 @@ For more information, see [Qualifio Developers documentation](https://developers ## Enable [[= product_name_engage =]] account To use [[= product_name_engage =]], you must make arrangements with [[= product_name =]] to define the initial configuration. -[[= product_name_base =]] team creates and provides user account. An invitation link is sent during the setup process. +[[= product_name_base =]] team creates and provides user account. +An invitation link is sent during the setup process. -For more information, see [Ibexa Engage in User documentation]([[= user_doc =]]/ibexa_engage/ibexa_engage/#request-access). +For more information, see [[[= product_name_engage =]] in User Documentation]([[= user_doc =]]/ibexa_engage/ibexa_engage/#request-access). ## Install [[= product_name_engage =]] @@ -50,4 +51,5 @@ In `config/packages` directory add the following `ibexa_connector_qualifio.yaml` [[= product_name_base =]] configures the `channel` and `client_id` values so that the selections can be filled up automatically on [[= product_name =]] side. - The `feed_url` and `variable_map` values don't need to be set at the installation process. They are preconfigured and can be overwritten. \ No newline at end of file + The `feed_url` and `variable_map` values don't need to be set at the installation process. + They're preconfigured and can be overwritten. \ No newline at end of file diff --git a/docs/ibexa_engage/integrate_ibexa_connect.md b/docs/ibexa_engage/integrate_ibexa_connect.md index 8f1c00f6b8..3b8974bbb9 100644 --- a/docs/ibexa_engage/integrate_ibexa_connect.md +++ b/docs/ibexa_engage/integrate_ibexa_connect.md @@ -5,11 +5,11 @@ edition: experience # Use Ibexa Connect -You can create workflows using [Ibexa Connect](https://doc.ibexa.co/projects/connect/en/latest/general/ibexa_connect/). +You can use [[[= product_name_connect =]]](https://doc.ibexa.co/projects/connect/en/latest/general/ibexa_connect/) to create workflows. [[= product_name_engage =]] collects user data and passes it directly to [[= product_name_connect =]]. With this data, you can create scenarios, for example, to add a user to newsletter, or to specific user segment group. -For more information, see [Ibexa Connect documentation](https://doc.ibexa.co/projects/connect/en/latest/). +For more information, see [[[= product_name_connect =]] documentation](https://doc.ibexa.co/projects/connect/en/latest/). ## Integrate [[= product_name_engage =]] with [[= product_name_connect =]] @@ -54,4 +54,5 @@ To do it, perform the following actions:: ![Configure Ibexa Engage](configure_ibexa_engage.png "Configure Ibexa Engage") -4\. Then, go to **Engage** -> **Integrations** -> **Push rules** to define the default or specific rules for new campaign or website. Select the created webhook. \ No newline at end of file +4\. Then, go to **Engage** -> **Integrations** -> **Push rules** to define the default or specific rules for new campaign or website. +Select the created webhook. \ No newline at end of file diff --git a/docs/ibexa_products/editions.md b/docs/ibexa_products/editions.md index 8fe28003a8..d4d62332ae 100644 --- a/docs/ibexa_products/editions.md +++ b/docs/ibexa_products/editions.md @@ -3,14 +3,14 @@ description: Learn more about various Ibexa DXP editions' features to help yours page_type: landing_page --- -# Ibexa DXP editions +# [[= product_name =]] editions Three [[= product_name =]] product editions are available to help you accelerate your digital transformation at the speed and cost that work best for you. [[= cards([ -"ibexa_products/ibexa_headless", -"ibexa_products/ibexa_experience", -"ibexa_products/ibexa_commerce" + "ibexa_products/ibexa_headless", + "ibexa_products/ibexa_experience", + "ibexa_products/ibexa_commerce", ], columns=3) =]] ## Feature comparison @@ -45,7 +45,7 @@ Compare all features available in [[= product_name_headless =]], [[= product_nam | [Customer Portal](customer_portal_guide.md) | | ✔ | ✔ | | [Segments](segments_admin_panel.md) | | ✔ | ✔ | | [Recent activity](recent_activity.md) | | ✔ | ✔ | -| [Ibexa Engage add-on]([[= user_doc =]]/ibexa_engage/ibexa_engage/) | | ✔ | ✔ | +| [[[= product_name_engage =]] add-on]([[= user_doc =]]/ibexa_engage/ibexa_engage/) | | ✔ | ✔ | | [Customer Data Platform (CDP) add-on](cdp_guide.md) | | ✔ | ✔ | | [Order management](order_management.md) | | | ✔ | | [Payment management](payment.md) | | | ✔ | diff --git a/docs/ibexa_products/ibexa_commerce.md b/docs/ibexa_products/ibexa_commerce.md index 8928994275..9789f1d59b 100644 --- a/docs/ibexa_products/ibexa_commerce.md +++ b/docs/ibexa_products/ibexa_commerce.md @@ -4,7 +4,7 @@ description: Explore all of the key features, functionalities, and advantages of month_change: false --- -# Ibexa DXP Commerce edition product guide +# [[= product_name_com =]] edition product guide ## What is [[= product_name_com =]] @@ -20,7 +20,8 @@ You can completely revamp your online stores and give your consumers exceptional ## Availability To start using [[= product_name_com =]], you need to purchase a product license. -For more information, see [[[= product_name_com =]] license pricing](https://www.ibexa.co/products/pricing?tab=3). + +For more information, see [Ibexa Commerce license pricing](https://www.ibexa.co/products/pricing?tab=3). You can also [contact us](https://www.ibexa.co/about-ibexa/contact-us) or [one of our partners](https://www.ibexa.co/partners). ## How it works @@ -34,7 +35,7 @@ With a help of documentation and trainings, any developer familiar with Symfony Version control systems and environment variables allow you to deploy your extensions and settings on several environments, such as [Ibexa Cloud](ibexa_cloud_guide.md). -[[= product_name_com =]] is built on [[[= product_name_exp =]]](ibexa_experience.md) and includes all bundles, APIs, and features that come with both [Headless](ibexa_headless.md#core-features) and [Experience](ibexa_experience.md#core-features) editions. +[[= product_name_com =]] is built on [[[= product_name_exp =]]](ibexa_experience.md) and includes all bundles, APIs, and features that come with both [[[= product_name_product_name_headless =]]](ibexa_headless.md#core-features) and [[[= product_name_exp =]]](ibexa_experience.md#core-features) editions. ## Capabilities and benefits @@ -71,7 +72,7 @@ Depending on their role, users can also enable or disable shipping methods, chan #### Storefront The [Storefront](storefront.md) package includes a starter kit for developers. -It is a foundational set of components that developers can customize and extend to create their own web store implementations. +It's a foundational set of components that developers can customize and extend to create their own web store implementations. It contains default UI components and widgets that can be modified to [create a customized web store](customize_storefront_layout.md). #### Relevant faceted search @@ -103,7 +104,7 @@ Recommendations can be used to propose related, alternative, or complimentary pr #### Use effective merchandising -Merchandising assists in keeping the consistency of the brand and providing customized product recommendations with captivating visuals and powerful search features. +Merchandising assists in keeping the consistency of the brand and providing customized product recommendations with captivating visuals and powerful search features. You can engage your customers with eye-catching graphics and information. The search engine makes it easy to find what they're looking for by providing quick and easy access to the product catalogs. @@ -123,7 +124,7 @@ You can create online store that really fits your needs. #### Automate business processes -With [[= product_name_com =]], the automation process becomes easier, which is essential if your company wants to do more with less effort. -It comes with all capabilities, including order and inventory management, customer data and custom pricing, which are needed to achieve it. -You can integrate with over 1,300 standard apps, including your CRM, ERP, PIM and DAM systems, and build custom connectors. +With [[= product_name_com =]], the automation process becomes easier, which is essential if your company wants to do more with less effort. +It comes with all capabilities, including order and inventory management, customer data, and custom pricing, which are needed to achieve it. +You can integrate with over 1,300 standard apps, including your CRM, ERP, PIM, and DAM systems, and build custom connectors. Also, you can use the ready-to-use pre-designed templates. \ No newline at end of file diff --git a/docs/ibexa_products/ibexa_experience.md b/docs/ibexa_products/ibexa_experience.md index c10500d944..bafb9f2356 100644 --- a/docs/ibexa_products/ibexa_experience.md +++ b/docs/ibexa_products/ibexa_experience.md @@ -4,7 +4,7 @@ description: Learn about all the main attributes, features, and benefits of the month_change: false --- -# Ibexa DXP Experience edition product guide +# [[= product_name_exp =]] edition product guide ## What is [[= product_name_exp =]] @@ -18,6 +18,7 @@ It also provides tools for using segmentation and targeting, and it can be widel ## Availability To start using [[= product_name_exp =]], you need to purchase a product license. + For more information, see [[[= product_name_exp =]] license pricing](https://www.ibexa.co/products/pricing?tab=2). You can also [contact us](https://www.ibexa.co/about-ibexa/contact-us) or [one of our partners](https://www.ibexa.co/partners). @@ -32,7 +33,7 @@ With a help of documentation and trainings, any developer familiar with Symfony [[= product_name_exp =]] is built on top of [[[= product_name_headless =]]](ibexa_headless.md), therefore it includes all bundles, APIs, and [features that come with Headless edition](ibexa_headless.md#core-features), but also more advanced features for digital experience management. -Version control systems and environment variables allow you to deploy your projects and settings on several environments, such as Ibexa Cloud. +Version control systems and environment variables allow you to deploy your projects and settings on several environments, such as [[= product_name_cloud =]]. ## Capabilities and benefits @@ -63,7 +64,7 @@ Additionaly, you can monitor and manage the information obtained from website vi #### Site Factory -[Site Factory ](site_factory.md) is a site management interface, integrated with the Back Office. +[Site Factory ](site_factory.md) is a site management interface, integrated with the back office. It enables you to configure new sites without leaving the administration interface and editing SiteAccess configuration. With this feature you can create and deploy multiple websites at lightning speed and at scale. It allows you to manage expenses and resources while industrializing your web presence. @@ -112,11 +113,11 @@ This central data storage supports business growth with a scalable infrastructur ![CDP](cdp.png) -#### Ibexa Engage +#### [[= product_name_engage =]] Another add-on available for Experience and [Commerce](ibexa_commerce.md) edition is [Ibexa Engage](ibexa_engage.md). To use it, you must make arrangements with [[= product_name_base =]] to define the initial configuration, and then get and set up a user account. -Ibexa Engage is a data collection tool. +[[= product_name_engage =]] is a data collection tool. It gives you the ability to use the [Qualifio](https://qualifio.com/) tools to engage your audiences. You can use Qualifio's existing templates and interactive elements, such as quizzes, pools, and forms, to create visually appealing, customized campaigns and collect important data. To promote your campaign, you can add a Campaign block to a page in Page Builder or embed a campaign within the Rich Text field by using a Campaign custom tag. @@ -125,7 +126,7 @@ To promote your campaign, you can add a Campaign block to a page in Page Builder ### Use cases With [[= product_name_exp =]], your customers are the main focus of all that you do. -It makes it simpler than ever to create the different touchpoints that your customers have with your brand, giving you the ability to guide them through your significant business procedures. +It makes it simpler than ever to create the different touchpoints that your customers have with your brand, giving you the ability to guide them through your significant business procedures. #### Build new pages and integrated forms diff --git a/docs/ibexa_products/ibexa_headless.md b/docs/ibexa_products/ibexa_headless.md index 850da65191..465ca06747 100644 --- a/docs/ibexa_products/ibexa_headless.md +++ b/docs/ibexa_products/ibexa_headless.md @@ -3,21 +3,22 @@ title: Ibexa Headless description: Get to know Ibexa Headless - an edition that focuses on content management. --- -# Ibexa DXP Headless edition product guide +# [[= product_name_headless =]] edition product guide ## What is [[= product_name_headless =]] The Headless edition of [[= product_name =]] focuses on content management. It provides tools to collaboratively create content, and interfaces (API) to distribute this content. -Multilingual, multichannel, extensible, [[= product_name_headless =]] is an advanced Content Management Framework (CMF), a Product Information Management (PIM) platform, as well as a Digital Asset Management (DAM) repository. -It's provided without a default front office, but with a complete Back Office and several APIs to manage and access content. +Multilingual, multichannel, extensible, [[= product_name_headless =]] is an advanced Content Management Framework (CMF), a Product Information Management (PIM) platform, and a Digital Asset Management (DAM) repository. +It's provided without a default front office, but with a complete back office and several APIs to manage and access content. ![Ibexa Headless](ibexa_headless.png) ## Availability To start using [[= product_name_headless =]] you must purchase a product license. + For more information, see [[[= product_name_headless =]] license pricing](https://www.ibexa.co/products/pricing?tab=1). You can [contact us](https://www.ibexa.co/about-ibexa/contact-us) or [contact one of our partners](https://www.ibexa.co/partners). @@ -25,9 +26,9 @@ You can [contact us](https://www.ibexa.co/about-ibexa/contact-us) or [contact on ### Editorial stage -You access with any web browser from any platform to a rich Back Office, the main place to +You access with any web browser from any platform to a rich back office, the main place to -- define users and their rights (customers, subscribers, editors, etc.), +- define users and their rights (for example, customers, subscribers, or editors), - organize content (content types, fields, tree, tags, languages, and more), - edit content in a collaborative workplace with versions and workflows. @@ -35,15 +36,14 @@ Then, content is available to end users through REST, GraphQL, or every output y ### Technical backstage -When you have a license, you install [[= product_name_headless =]] through Composer -on an architecture including at least a web server with PHP and a relational database server. +When you have a license, you install [[= product_name_headless =]] through Composer on an architecture including at least a web server with PHP and a relational database server. For performance, several bricks can be added to your stack such as a reverse proxy or a search engine. [[= product_name_headless =]] is based on Symfony. Any Symfony developer, or even PHP developer, can quickly learn how to extend it with the help of an online documentation. By using a version control system and environment variables, you can deploy your configuration and extensions on several environments including [[= product_name_cloud =]]. -Standard web APIs and [[[= product_name_connect =]]]([[= connect_doc =]]/general/ibexa_connect/) help establish interoperability, even if you aren't an advanced developer. +Standard web APIs and [[[= product_name_connect =]]]([[= connect_doc =]]/general/ibexa_connect/) help establish interoperability, even if you'ren't an advanced developer. ![Ibexa Headless data inputs and outputs](img/headless.png) @@ -53,17 +53,15 @@ APIs summary: - The OAuth 2 [Client](oauth_client.md) and [Server](oauth_server.md) allow to connect to an SSO or be the SSO. - The design engine and its theme templates mechanism allows to serve the content in several shapes. - The PHP API opens [[= product_name_headless =]] to extendability to fit your needs. - For example, content can be computed, edited or served in specific ways such as - scheduled/live imports/exports, automated edition tasks, or specific controllers to communicate with other applications. + For example, content can be computed, edited, or served in specific ways such as scheduled/live imports/exports, automated edition tasks, or specific controllers to communicate with other applications. ## Capabilities and benefits -[[= product_name_headless =]] is a tool box with a Back Office. +[[= product_name_headless =]] is a tool box with a back office. It comes without a default front office. -You don't lose time to develop a theme for a provided front office before discovering it won't fit your needs. +You don't lose time to develop a theme for a provided front office before discovering it doesn't fit your needs. No distraction. -[[= product_name_headless =]] helps you focus on the content, create and organize with its straightforward user interface (UI), -imagine its inputs/outputs, and implement them with its various layers' APIs. +[[= product_name_headless =]] helps you focus on the content, create and organize with its straightforward user interface (UI), imagine its inputs/outputs, and implement them with its various layers' APIs. ### Core features @@ -77,7 +75,7 @@ Content modeling and management are the foundation of [[= product_name =]] with - An item can have multiple locations in this tree. - Content items are typed. - Content types are sets of typed data fields, with optional conditions on the possible values. -- Rich Text Field Type comes with an [online editor](online_editor_guide.md). +- Rich Text field type comes with an [online editor](online_editor_guide.md). - Multilingual, it can store a content in several languages, the content model defines which field must be translated, and which don't vary. For more information, see [Content management product guide](content_management_guide.md). @@ -97,15 +95,15 @@ There are many paths to access the content in many shapes: - [[= product_name_headless =]] offers a complete PHP API to extend the ways to access content. - A design engine and a view controller offer to create plain text content views (such as HTML, JSON, XML, CSS, JS, CSV, or Markdown), and to factorize those views by using theme cascades. - This design engine is used in the Back Office which is equally extendable. + This design engine is used in the back office which is equally extendable. - Multichannel, content can be accessed through several channel configurations, such as the domain name it replies to, the sub-part of the content tree it starts from, the users rights, or the design theme. - The Back Office itself is such a channel. + The back office itself is such a channel. - Multi-repository, the same platform can use separate databases if data isolation is needed between channel groups. ### Advanced features -On top of this strong core, [[= product_name_headless =]] brings tools to increase user experience, from final front users to Back Office contributors. +On top of this strong core, [[= product_name_headless =]] brings tools to increase user experience, from final front users to back office contributors. #### Complete DXP @@ -116,7 +114,7 @@ On top of this strong core, [[= product_name_headless =]] brings tools to increa - Content scheduler, which allows you to establish the future of the content and use events to have a living front application, even when the editorial team is absent or reduced. This way, visitors can discover new content at midnight, during weekends or vacations. A calendar summarises those scheduled content events. -Like everything in the Back Office, the calendar is extendable: you can add an event source to coordinate content events with other company events. +Like everything in the back office, the calendar is extendable: you can add an event source to coordinate content events with other company events. #### Many ways to structure and organize content @@ -127,7 +125,7 @@ Like everything in the Back Office, the calendar is extendable: you can add an e - Product variants can rapidly be created by the automatic declination of attributes that have a defined set of values. - With taxonomy, you can tag content items to organize them by topics in a much intuitive way for the editor than a content tree with multiple locations would. Tags themselves are organized in a tree, and synonyms are linked to favorite terms. -Tag organization can be handled by a supervisor who won't need to move content items around a corporate content tree. +Tag organization can be handled by a supervisor who doesn't need to move content items around a corporate content tree. At search time, tags can be keywords with a high value in relevance score to help the end user having results closer to the searched topic. #### Collaboration @@ -172,22 +170,14 @@ Several features help end users collaborate on the content, such as: ## Use cases -As a content repository with an omnipotent Back Office, -many APIs to absorb, compute and distribute content, -even a recommendation engine to deliver the right content to various readers, -[[= product_name_headless =]] can be used in several cases. +As a content repository with an omnipotent back office, many APIs to absorb, compute and distribute content, even a recommendation engine to deliver the right content to various readers, [[= product_name_headless =]] can be used in several cases. Here are few examples. ### Brick and mortar, but with an online showcase -If you prefer the human warmth of a retail store, -if your products' numerous complex options should be discussed, -or if you're simply not ready yet to sell online, -[[= product_name_headless =]] helps to build an exposition of your product catalog and your philosophy, -an online presence to keep earlier customers interested and gather new ones. -It can be a structuring first step to test customer's adoption of your website, -before increasing user experience with [[= product_name_exp =]], -and finally becoming an online store with [[= product_name_com =]]. +If you prefer the human warmth of a retail store, if your products' numerous complex options should be discussed, +or if you're not ready yet to sell online, [[= product_name_headless =]] helps to build an exposition of your product catalog and your philosophy, an online presence to keep earlier customers interested and gather new ones. +It can be a structuring first step to test customer's adoption of your website, before increasing user experience with [[= product_name_exp =]], and finally becoming an online store with [[= product_name_com =]]. ### Large network with multiple inputs and outputs @@ -196,4 +186,4 @@ Thanks to migration feature and PHP API, existing content has been imported from Fine-tuned user rights and workflows ensure that each collaborator can focus on their own tasks without the risk to disturb the content model or content organization. Content is distributed on several websites and applications, some running on the [[= product_name_base =]] platform itself, some on third parties' servers, some as native mobile apps. Part of the content has multiple locations or is translated, and reused from place to place. -While the Back Office offers to search into the whole repository, the front end apps have correctly circumscribed search capabilities. +While the back office offers to search into the whole repository, the front end apps have correctly circumscribed search capabilities. diff --git a/docs/infrastructure_and_maintenance/backup.md b/docs/infrastructure_and_maintenance/backup.md index 79e0f16e5a..d28854d9b9 100644 --- a/docs/infrastructure_and_maintenance/backup.md +++ b/docs/infrastructure_and_maintenance/backup.md @@ -2,20 +2,22 @@ description: Periodically back up your Repository information by making a database backup. --- -# Backup +# Backup -You should always make sure that your solution is properly backed up. The following example shows you how to do this on a Linux-UNIX-based system. You should shut down the DXP if it's running before making a backup. +You should always make sure that your solution is properly backed up. +The following example shows you how to do this on a Linux-UNIX-based system. +You should shut down the DXP if it's running before making a backup. !!! note "Externally stored assets" If you store assets in any external service or localization, you should back them up before proceeding. 1\. Navigate into the [[= product_name =]] directory: - + ``` cd /path/to/ibexa ``` - + 2\. Clear all caches: ``` @@ -24,7 +26,7 @@ var/logs/* ``` 3\. Create a dump of the database: - + ``` # MySQL mysqldump -u --add-drop-table > db_backup.sql diff --git a/docs/infrastructure_and_maintenance/cache/http_cache/content_aware_cache.md b/docs/infrastructure_and_maintenance/cache/http_cache/content_aware_cache.md index 9bdfd73838..6b480745cb 100644 --- a/docs/infrastructure_and_maintenance/cache/http_cache/content_aware_cache.md +++ b/docs/infrastructure_and_maintenance/cache/http_cache/content_aware_cache.md @@ -1,16 +1,16 @@ --- -description: Content-aware HTTP cache takes into account the content it is connected to. +description: Content-aware HTTP cache takes into account the content it's connected to. --- # Content-aware HTTP cache -HTTP cache in [[= product_name =]] is aware of which content or entity it is connected to. -This awareness is accomplished by means of cache tagging. All supported reverse proxies are content-aware. +HTTP cache in [[= product_name =]] is aware of which content or entity it's connected to. +This awareness is accomplished by means of cache tagging. +All supported reverse proxies are content-aware. !!! note "Tag header is stripped in production for security reasons" - For security reasons this header, and other internal cache headers, - are stripped from output in production by the reverse proxy (in VCL for Varnish and Fastly). + For security reasons this header, and other internal cache headers, are stripped from output in production by the reverse proxy (in VCL for Varnish and Fastly). ## Cache tags @@ -20,33 +20,30 @@ Tags form a secondary set of keys assigned to every cache item, on top of the "p Like an index in a database, a tag is typically used for anything relevant that represents the given cache item. Tags are used for cache invalidation. -For example, the system tags every article response, and when the article content type is updated, -it tells Varnish that all articles should be considered stale -and updated in the background when someone requests them. +For example, the system tags every article response, and when the article content type is updated, it tells Varnish that all articles should be considered stale and updated in the background when someone requests them. Current content tags (and when the system purges on them): -- Content: `c` - Purged on all smaller or larger changes to content (including its metadata, Fields and Locations). -- Content Version: `cv` - Purged when any version of Content is changed (for example, a draft is created or removed). +- Content: `c` - Purged on all smaller or larger changes to content (including its metadata, fields and locations). +- Content version: `cv` - Purged when any version of Content is changed (for example, a draft is created or removed). - Content type: `ct` - Used when the content type changes, affecting content of its type. -- Location: `l` - Used for clearing all cache relevant for a given Location. -- Parent Location: `pl<[parent-]location-id>` - Used for clearing all children of a Location (`pl`), or all siblings (`pl`). -- Path: `p` - For operations that change the tree itself, like move, remove, etc. +- Location: `l` - Used for clearing all cache relevant for a given location. +- Parent Location: `pl<[parent-]location-id>` - Used for clearing all children of a location (`pl`), or all siblings (`pl`). +- Path: `p` - For operations that change the tree itself, for example, move or remove. - Relation: `r` - Only purged on when content updates are severe enough to also affect reverse relations. -- Relation location: `rl` - Same as relation, but by Location ID. +- Relation location: `rl` - Same as relation, but by location ID. !!! note "Automatic repository prefixing of cache tags" - As [[= product_name =]] supports multi-repository (multi-database) setups that can have overlapping IDs, - the shared HTTP cache systems need to distinguish tags relevant to the different content repositories. + As [[= product_name =]] supports multi-repository (multi-database) setups that can have overlapping IDs, the shared HTTP cache systems need to distinguish tags relevant to the different content repositories. This is why in multi-repository setup you can see cache tags such as `1p2`. In this example `1` represents the index among configured repositories, meaning the second repository in the system. - Tags are not prefixed for default repository (index "0"). + Tags aren't prefixed for default repository (index "0"). -The content tags are returned in a header in the responses from [[= product_name =]]. The header name is dependent on -which HTTP Cache [[= product_name =]] is configured with: +The content tags are returned in a header in the responses from [[= product_name =]]. +The header name is dependent on which HTTP Cache [[= product_name =]] is configured with: - Symfony reverse proxy: `X-Cache-Tags` - Varnish: `xkey` @@ -60,9 +57,8 @@ Examples: ### Troubleshooting - Cache header too long errors -In case of complex content, for example, Pages with many blocks, or RichText with a lot of embeds/links, -you can encounter problems with too long cache header on responses. -It happens because necessary cache entries may not be tagged properly. +In case of complex content, for example, Pages with many blocks, or RichText with a lot of embeds/links, you can encounter problems with too long cache header on responses. +It happens because necessary cache entries may not be tagged properly. You may also see `502 Headers too long` errors, and webserver refusing to serve the page. You can solve this issue in one of the following ways: @@ -89,15 +85,14 @@ Apache has a [hard](https://github.com/apache/httpd/blob/5f32ea94af5f1e7ea68d6fc #### B. Limit tags header output by system -1\. For inline rendering just displaying the content name, image attribute, and/or link, it would be enough to: +1\. For inline rendering displaying the content name, image attribute, and/or link, it would be enough to: -- Look into how many inline (non ESI) render calls for content rendering you are doing, and see if you can organize it differently. +- Look into how many inline (non ESI) render calls for content rendering you're doing, and see if you can organize it differently. - Consider inlining the views not used elsewhere in the given template and [tagging the response in Twig](#response-tagging-in-templates) with "relation" tags. - (Optional) You can set reduced cache TTL for the given view, to reduce the risk of stale cache on subtree operations affecting the inlined content. -2\. You can opt in to set a max length parameter (in bytes) and corresponding ttl (in seconds) -for cases when the limit is reached. The system will log a warning where the limit is reached, and when needed, you can optimize -these cases as described above. +2\. You can opt in to set a max length parameter (in bytes) and corresponding ttl (in seconds) for cases when the limit is reached. +The system logs a warning where the limit is reached, and when needed, you can optimize these cases as described above. ```yaml parameters: @@ -117,31 +112,32 @@ Cache-Control: public, max-age=86400 xkey: ez-all c1 ct1 l2 pl1 p1 p2 ``` -If the given content has several Locations, you can see several `l` and `p` tags in the response. +If the given content has several locations, you can see several `l` and `p` tags in the response. !!! note "How response tagging for ContentView is done internally" In `ibexa/http-cache` there is a dedicated response listener `HttpCacheResponseSubscriber` that checks if: - + - the response has attribute `view` - the view implements `Ibexa\Core\MVC\Symfony\View\CachableView` - - cache is not disabled on the individual view + - cache isn't disabled on the individual view If that checks out, the response is adapted with the following: - + - `ResponseCacheConfigurator` applies SiteAccess settings for enabled/disabled cache and default TTL. - `DispatcherTagger` dispatches the built-in ResponseTaggers which generate the tags as described above. ### ResponseConfigurator -A `ReponseCacheConfigurator` configures an HTTP Response object, makes the response public, adds tags and sets the shared max age. -It is provided to `ReponseTaggers` that use it to add the tags to the response. +A `ReponseCacheConfigurator` configures an HTTP Response object, makes the response public, adds tags, and sets the shared max age. +It's provided to `ReponseTaggers` that use it to add the tags to the response. -The `ConfigurableResponseCacheConfigurator` (`Ibexa\HttpCache\ResponseConfigurator\ConfigurableResponseCacheConfigurator`) follows the `view_cache` configuration and only enables cache if it is enabled in the configuration. +The `ConfigurableResponseCacheConfigurator` (`Ibexa\HttpCache\ResponseConfigurator\ConfigurableResponseCacheConfigurator`) follows the `view_cache` configuration and only enables cache if it's enabled in the configuration. ### Delegator and Value taggers -- Delegator taggers - extract another value or several from the given value and pass it on to another tagger. For example, a `ContentView` is covered both by the `ContentValueViewTagger` and `LocationValueViewTagger`, where the first extracts the Content from the `ContentView` and passes it to the `ContentInfoTagger`. +- Delegator taggers - extract another value or several from the given value and pass it on to another tagger. +For example, a `ContentView` is covered both by the `ContentValueViewTagger` and `LocationValueViewTagger`, where the first extracts the content from the `ContentView` and passes it to the `ContentInfoTagger`. - Value taggers - extract the `Location` and pass it on to the `LocationViewTagger`. ## DispatcherTagger @@ -189,8 +185,7 @@ $tagHandler->addRelationTags([33, 44]); In PHP, FOSHttpCache exposes the `fos_http_cache.http.symfony_response_tagger` service which enables you to add tags to a response. -The following example adds minimal tags when ID 33 and 34 are rendered in ESI, -but parent response needs these tags to get refreshed if they are deleted: +The following example adds minimal tags when ID 33 and 34 are rendered in ESI, but parent response needs these tags to get refreshed if they're deleted: ``` php /** @var \FOS\HttpCacheBundle\Http\SymfonyResponseTagger $responseTagger */ @@ -201,8 +196,8 @@ See [Tagging from code](https://foshttpcachebundle.readthedocs.io/en/latest/feat 4\. Use deprecated `X-Location-Id` header. -For custom or built-in controllers (e.g. REST) still using `X-Location-Id`, `XLocationIdResponseSubscriber` handles translating -this header to tags. It supports singular and comma-separated Location ID value(s): +For custom or built-in controllers (for example, REST) that still use `X-Location-Id`, `XLocationIdResponseSubscriber` handles translating this header to tags. +It supports singular and comma-separated location ID value(s): ```php /** @var \Symfony\Component\HttpFoundation\Response $response */ @@ -214,9 +209,8 @@ $response->headers->set('X-Location-Id', '123,212,42'); !!! caution "X-Location-Id use is deprecated" - `X-Location-Id` is deprecated and will be removed in future. - For rendering content it is advised to refactor to use Content View, - if not applicable `ContentTagInterface` or lastly manually output tags. + `X-Location-Id` is deprecated and removed in future. + For rendering content it's advised to refactor to use content view, if not applicable `ContentTagInterface` or lastly manually output tags. ## Response tagging in templates @@ -256,14 +250,13 @@ See [Tagging from Twig Templates](https://foshttpcachebundle.readthedocs.io/en/l ### Default tag purging -`ibexa/http-cache` uses Repository API event subscribers to listen to events emitted on Repository operations, -and depending on the operation triggers expiry on a specific tag or set of tags. +`ibexa/http-cache` uses repository API event subscribers to listen to events emitted on repository operations, and depending on the operation triggers expiry on a specific tag or set of tags. All event subscribers can be found in `http-cache/src/lib/EventSubscriber/CachePurge`. ### Tags purged on publish event -Below is an example of a Content structure. The tags which the content view controller adds to each location are -also listed +Below is an example of a content structure. +The tags which the content view controller adds to each location are also listed: ``` - [Home] (content-id=52, location-id=2) @@ -282,23 +275,22 @@ In the event when a new version of `Child` is published, the following keys are - `c55`, because Content `[Child]` was changed - `r55`, because cache for any object that has a relation to Content `[Child]` should be purged -- `l22`, because Location `[Child]` has changed ( that would be location holding content-id=55) +- `l22`, because location `[Child]` has changed ( that would be location holding content-id=55) - `pl22`, because cache for children of `[Child]` should be purged - `rl22`, because cache for any object that has a relation to Location `[Child]` should be purged - `l20`, because cache for parent of `[Child]` should be purged - `pl20`, because cache for siblings of `[Child]` should be purged -In summary, HTTP Cache for any location representing `[Child]`, any Content that relates to the Content `[Child]`, the -location for `[Child]`, any children of `[Child]`, any Location that relates to the Location `[Child]`, location for -`[Parent1]`, any children on `[Parent1]`. -Effectively, in this example HTTP cache for `[Parent1]` and `[Child]` will be cleared. +In summary, HTTP Cache for any location representing `[Child]`, any Content that relates to the Content `[Child]`, the location for `[Child]`, any children of `[Child]`, any location that relates to the location `[Child]`, location for `[Parent1]`, any children on `[Parent1]`. +Effectively, in this example HTTP cache for `[Parent1]` and `[Child]` is cleared. ### Tags purged on move event -With the same Content structure as above, the `[Child]` location is moved below `[Parent2]`. +With the same content structure as above, the `[Child]` location is moved below `[Parent2]`. + +The new structure is then: -The new structure will then be: ``` - [Home] (content-id=52, location-id=2) ez-all c52 ct42 l2 pl1 p1 p2 @@ -312,7 +304,7 @@ The new structure will then be: ez-all c55 ct1 l22 pl21 p1 p2 p21 p22 ``` -The following keys will be purged during the move: +The following keys are purged during the move: - `l20`, because cache for previous parent of `[Child]` should be purged (`[Parent1]`) - `pl20`, because cache for children of `[Parent1]` should be purged @@ -320,8 +312,7 @@ The following keys will be purged during the move: - `pl21`, because cache for all children of new parent (`[Parent2]`) should be purged - `p22`, because cache for any element below `[Child]` should be purged (because path has changed) -In other words, HTTP Cache for `[Parent1]`, children of `[Parent1]` ( if any ), `[Parent2]`, children of `[Parent2]` ( if any ), -`[Child]` and any subtree below `[Child]`. +In other words, HTTP Cache for `[Parent1]`, children of `[Parent1]` ( if any ), `[Parent2]`, children of `[Parent2]` ( if any ), `[Child]` and any subtree below `[Child]`. ### Custom purging from code @@ -340,7 +331,7 @@ $purgeClient->purgeAll(); ### Purging from command line -Example for purging by Location and by Content ID: +Example for purging by location and by content ID: ```bash bin/console fos:httpcache:invalidate:tag l44 c33 @@ -352,33 +343,31 @@ Example for purging by all cache: bin/console fos:httpcache:invalidate:tag ez-all ``` -!!! tip "Purge is done on the current Repository" +!!! tip "Purge is done on the current repository" - Similarly to purging from code, the tags you purge on, are prefixed to match the currently configured SiteAccess. + Similarly to purging from code, the tags you purge on, are prefixed to match the currently configured SiteAccess. When you use this command in combination with multi-repository setup, make sure to specify SiteAccess argument. ## Testing and debugging HTTP cache -It is important to test your code in an environment which is as similar as your production environment as possible. That -means that if only are testing locally using the default Symfony Reverse proxy when your are going to use Varnish or -Fastly in production, you are likely ending up some (bad) surprises. Due to the symfony reverse proxy's lack of support for ESIs, it behaves -quite different from Varnish and Fastly in some aspects. -If you are going to use Varnish in production, make sure you also test your code with Varnish. -If you are going to use Fastly in production, testing with Fastly in your developer install is likely not feasible -(you're local development environment must then be accessible for Fastly). Testing with Varnish instead will in most -cases do the job. But if you need to change the varnish configuration to make your site work, be aware that Varnish and Fastly uses different dialects, and -that .vcl code for Varnish V6.x will likely not work as-is on Fastly. - -This section describes to how to debug problems related to HTTP cache. - In order to that, you must be able to look both at - responses and headers [[= product_name =]] sends to HTTP cache, and not so much at responses and headers +It's important to test your code in an environment which is as similar as your production environment as possible. +That means that if only are testing locally using the default Symfony Reverse proxy when your are going to use Varnish or Fastly in production, you're likely ending up some (bad) surprises. +Due to the symfony reverse proxy's lack of support for ESIs, it behaves quite different from Varnish and Fastly in some aspects. +If you're going to use Varnish in production, make sure you also test your code with Varnish. +If you're going to use Fastly in production, testing with Fastly in your developer install is likely not feasible (you're local development environment must then be accessible for Fastly). +Testing with Varnish instead in most cases does the job. +But if you need to change the varnish configuration to make your site work, be aware that Varnish and Fastly uses different dialects, and that .vcl code for Varnish V6.x doesn't likely work as-is on Fastly. + +This section describes to how to debug problems related to HTTP cache. + + You must be able to look both at responses and headers [[= product_name =]] sends to HTTP cache, and not so much at responses and headers the HTTP cache sends to the client (web browser). - It means you must be able to send requests to your origin (web server) that do not go through Varnish or Fastly. - If you run Nginx and Varnish on premise, you should know what host and port number both Varnish and Nginx runs on. If you - perform tests on Fastly enabled environment on [[= product_name_cloud =]] provided by Platform.sh, you need to use the Platform.sh - Dashboard to obtain the endpoint for Nginx. + It means you must be able to send requests to your origin (web server) that don't go through Varnish or Fastly. + If you run Nginx and Varnish on premise, you should know what host and port number both Varnish and Nginx runs on. + If you perform tests on Fastly enabled environment on [[= product_name_cloud =]] provided by Platform.sh, you need to use the Platform.sh + dashboard to obtain the endpoint for Nginx. -The following example shows how to debug and check why Fastly does not cache the front page properly. +The following example shows how to debug and check why Fastly doesn't cache the front page properly. If you run the command multiple times: `curl -IXGET https://www.staging.foobar.com.us-2.platformsh.site` @@ -395,12 +384,13 @@ x-cache: MISS #### Finding Nginx endpoint for environments located on the grid -To find the Nginx point, first, you need to know in which region your project is located. To do that, go to the Platform.sh dashboard. +To find the Nginx point, first, you need to know in which region your project is located. +To do that, go to the Platform.sh dashboard. To find a valid route, click an element in the **URLs** drop-down for the specified environment and select the route. A route may look like this: `https://www.staging.foobar.com.us-2.platformsh.site/` -In this case the region is `us-2` and you can find the public IP list on [Platform.sh documentation page](https://docs.platform.sh/development/regions.html#public-ip-addresses) +In this case the region is `us-2` and you can find the public IP list on [Platform.sh documentation page](https://docs.platform.sh/development/regions.html#public-ip-addresses). Typically, you can add a `gw` to the hostname and use nslookup to find it. ```bash @@ -410,7 +400,7 @@ Typically, you can add a `gw` to the hostname and use nslookup to find it. Address: 1.2.3.4 ``` -You can also use the [Ibexa Cloud CLI](https://cli.ibexa.co/) (which has the same command as the Platform.sh CLI) to find [the endpoint](https://docs.platform.sh/domains/steps/dns.html): +You can also use the [[[= product_name_cloud =]] CLI](https://cli.ibexa.co/) (which has the same command as the Platform.sh CLI) to find [the endpoint](https://docs.platform.sh/domains/steps/dns.html): ```bash ibexa_cloud environment:info edge_hostname @@ -418,12 +408,10 @@ You can also use the [Ibexa Cloud CLI](https://cli.ibexa.co/) (which has the sam #### Finding Nginx endpoint on dedicated cloud -If you have a dedicated 3-node cluster on Platform.sh, the procedure for getting the endpoint to environments that are -located on that cluster (`production` and sometimes also `staging`) is slightly different. -In the **URLs** drop-down in the Platform.sh dashboard, find the route that has the format -`somecontent.[clusterid].ent.platform.sh/`, for example, `myenvironment.abcdfg2323.ent.platform.sh/` +If you have a dedicated 3-node cluster on Platform.sh, the procedure for getting the endpoint to environments that are located on that cluster (`production` and sometimes also `staging`) is slightly different. +In the **URLs** drop-down in the Platform.sh dashboard, find the route that has the format `somecontent.[clusterid].ent.platform.sh/`, for example, `myenvironment.abcdfg2323.ent.platform.sh/` -The endpoint in case has the format `c.[clusterid].ent.platform.sh`, for example, `c.asddfs2323.ent.platform.sh/` +The endpoint in case has the format `c.[clusterid].ent.platform.sh`, for example, `c.asddfs2323.ent.platform.sh/`. Next, use nslookup to find the IP: ```bash @@ -435,11 +423,10 @@ Next, use nslookup to find the IP: ### Fetching user context hash -As explained in [User Context Hash caching](context_aware_cache.md#user-context-hash-caching), the HTTP cache indexes the cache based on the -user-context-hash. Users with the same user-context-hash here the same cache (as long as [[= product_name =]] -responds with `Vary: X-Context-User-Hash`). +As explained in [User Context Hash caching](context_aware_cache.md#user-context-hash-caching), the HTTP cache indexes the cache based on the user-context-hash. +Users with the same user-context-hash here the same cache (as long as [[= product_name =]] responds with `Vary: X-Context-User-Hash`). -In order to simulate the requests the HTTP cache sends to [[= product_name =]], you need this user-context-hash. +To simulate the requests the HTTP cache sends to [[= product_name =]], you need this user-context-hash. To obtain it, use `curl`. ```bash @@ -450,21 +437,19 @@ Some notes about each of these parameters: - `-IXGET`, one of many ways to tell curl that we want to send a GET request, but we are only interested in outputting the headers - `--resolve www.staging.foobar.com.us-2.platformsh.site:443:1.2.3.4` - - We tell curl not to do a DNS lookup for `www.staging.foobar.com.us-2.platformsh.site`. We do that because in our case - that will resolve to the Fastly endpoint, not our origin (nginx) + - We tell curl not to do a DNS lookup for `www.staging.foobar.com.us-2.platformsh.site`. + We do that because in our case that resolves to the Fastly endpoint, not our origin (nginx) - We specify `443` because we are using `https` - We provide the IP of the nginx endpoint at platform.sh (`1.2.3.4` in this example) - `--header "Surrogate-Capability: abc=ESI/1.0"`, strictly speaking not needed when fetching the user-context-hash, but this tells [[= product_name =]] that client understands ESI tags. - It is good practice to always include this header when imitating the HTTP Cache. + It's good practice to always include this header when imitating the HTTP Cache. - `--header "accept: application/vnd.fos.user-context-hash"` tells [[= product_name =]] that the client wants to receive the user-context-hash -- `--header "x-fos-original-url: /"` is required by the fos-http-cache bundle in order to deliver the user-context-hash -- `https://www.staging.foobar.com.us-2.platformsh.site/_fos_user_context_hash` : here we use the hostname we earlier told - curl how to resolve using `---resolve`. `/_fos_user_context_hash` is the route to the controller that are able to - deliver the user-context-hash. -- You may also provide the session cookie (`--cookie ".....=....") for a logged-in-user if you are interested in - the x-user-context-hash for a different user but anonymous +- `--header "x-fos-original-url: /"` is required by the fos-http-cache bundle to deliver the user-context-hash +- `https://www.staging.foobar.com.us-2.platformsh.site/_fos_user_context_hash` : here we use the hostname we earlier told curl how to resolve using `---resolve`. `/_fos_user_context_hash` is the route to the controller that are able to deliver the user-context-hash. +- You may also provide the session cookie (`--cookie ".....=....") for a logged-in-user if you're interested in the x-user-context-hash for a different user but anonymous The output for this command should look similar to this: + ``` HTTP/1.1 200 OK Server: nginx/1.20.0 @@ -481,18 +466,18 @@ The output for this command should look similar to this: Surrogate-Key: ez-user-context-hash ez-all fos_http_cache_hashlookup- ``` -The header `X-User-Context-Hash` is the one of the interest here, but you may also note the `Surrogate-Key` which -holds the [cache tags](#cache-tags). +The header `X-User-Context-Hash` is the one of the interest here, but you may also note the `Surrogate-Key` which holds the [cache tags](#cache-tags). ### Fetching HTML response -Now you have the user-context-hash, and you can ask origin for the actual resource you are after: +Now you have the user-context-hash, and you can ask origin for the actual resource you're after: ```bash $ curl -IXGET --resolve www.staging.foobar.com.us-2.platformsh.site:443:1.2.3.4 --header "Surrogate-Capability: abc=ESI/1.0" --header "x-user-context-hash: daea248406c0043e62997b37292bf93a8c91434e8661484983408897acd93814" https://www.staging.foobar.com.us-2.platformsh.site/ ``` The output : + ``` HTTP/1.1 200 OK Server: nginx/1.20.0 @@ -509,16 +494,17 @@ Surrogate-Key: ez-all c52 ct42 l2 pl1 p1 p2 r56 r57 ``` The `Cache-Control` header tells the HTTP cache to store the result in the cache for 1 day (86400 seconds) -The `Vary: X-User-Content-Hash` header tells the HTTP cache that this cache element may be used for all users which has -the given `x-user-hash` (`daea248406c0043e62997b37292bf93a8c91434e8661484983408897acd93814`). +The `Vary: X-User-Content-Hash` header tells the HTTP cache that this cache element may be used for all users which has the given `x-user-hash` (`daea248406c0043e62997b37292bf93a8c91434e8661484983408897acd93814`). The document might also be removed from the cache by purging any of the keys provided in the `Surrogate-Key` header. -So back to the original problem here. This resource is for some reason not cached by Fastly ( remember the -`x-cache: MISS` we started with). But origin says this page can be cached for 1 day. How can that be? -The likely reason is that this page also contains some ESI fragments and that one or more of these are not cachable. +So back to the original problem here. +This resource is for some reason not cached by Fastly (remember the `x-cache: MISS` we started with). +But origin says this page can be cached for 1 day. +How can that be? +The likely reason is that this page also contains some ESI fragments and that one or more of these aren't cachable. -So, first let's see if there are any ESIs here. We remove the `-IXGET` options (in order to see content of the response, -not only headers) to curl and search for esi: +So, first let's see if there are any ESIs here. +We remove the `-IXGET` options (to see content of the response, not only headers) to curl and search for esi: ```bash $ curl --resolve www.staging.foobar.com.us-2.platformsh.site:443:1.2.3.4 --header "Surrogate-Capability: abc=ESI/1.0" --header "x-user-context-hash: daea248406c0043e62997b37292bf93a8c91434e8661484983408897acd93814" https://www.staging.foobar.com.us-2.platformsh.site/ | grep esi @@ -532,9 +518,8 @@ The output is: ``` -Now, investigate the response of each of these ESI fragments to understand what is going on. It is important to -put that URL in single quotes as the URLS to the ESIs include special characters that can be interpreted by the -shell. +Now, investigate the response of each of these ESI fragments to understand what is going on. +It's important to put that URL in single quotes as the URLS to the ESIs include special characters that can be interpreted by the shell. #### 1st ESI @@ -542,7 +527,7 @@ shell. $ curl -IXGET --resolve www.staging.foobar.com.us-2.platformsh.site:443:1.2.3.4 --header "Surrogate-Capability: abc=ESI/1.0" --header "x-user-context-hash: daea248406c0043e62997b37292bf93a8c91434e8661484983408897acd93814" 'https://www.staging.foobar.com.us-2.platformsh.site/_fragment?_hash=B%2BLUWB2kxTCc6nc5aEEn0eEqBSFar%2Br6jNm8fvSKdWU%3D&_path=locationId%3D2%26contentId%3D52%26blockId%3D11%26versionNo%3D3%26languageCode%3Deng-GB%26serialized_siteaccess%3D%257B%2522name%2522%253A%2522site%2522%252C%2522matchingType%2522%253A%2522default%2522%252C%2522matcher%2522%253Anull%252C%2522provider%2522%253Anull%257D%26serialized_siteaccess_matcher%3Dnull%26_format%3Dhtml%26_locale%3Den_GB%26_controller%3DEzSystems%255CEzPlatformPageFieldTypeBundle%255CController%255CBlockController%253A%253ArenderAction' ``` -You can also note that this ESI is handled by a controller in the `FieldTypePage` bundle provided by [[= product_name =]]. +This ESI is handled by a controller in the `FieldTypePage` bundle provided by [[= product_name =]]. The output is: @@ -561,7 +546,7 @@ X-Cache-Debug: 1 Surrogate-Key: ez-all c52 l2 ``` -The headers here look correct and do not indicate that this ESI will not be cached by the HTTP cache +The headers here look correct and don't indicate that this ESI isn't cached by the HTTP cache. The second ESI has a similar response. #### 3rd ESI @@ -590,23 +575,28 @@ X-Cache-Debug: 1 Surrogate-Key: ez-all ``` -The `Cache-Control` and `Vary` headers look correct. The request is handled by a custom controller and the `Surrogate-Key` only contains the default `ez-all` value. -This is not a problem as long as the controller -does not return values from any Content in the [[= product_name =]] Repository. If it does, the controller should also add -the corresponding IDs to such objects in that header. +The `Cache-Control` and `Vary` headers look correct. +The request is handled by a custom controller and the `Surrogate-Key` only contains the default `ez-all` value. +This isn't a problem as long as the controller doesn't return values from any content in the [[= product_name =]] repository. +If it does, the controller should also add the corresponding IDs to such objects in that header. + +The `Set-Cookie` here may cause the problem. +A ESI fragment should never set a cookie because: + +- Clients only receive the headers set in the "mother" document (the headers in the "/" response in this case). + +- Only the content of ESIs responses is returned to the client. +**No headers set in the ESI response ever reach the client**. +ESI headers are only seen by the HTTP cache. + +- Symfony reverse proxy doesn't support ESIs at all, and any ESI calls (`render_esi()`) are implicitly replaced by sub-requests (`render()`). +So any `Set-Cookie` **is** sent to the client when using Symfony reverse proxy. -The `Set-Cookie` here may cause the problem. A ESI fragment should never set a cookie because: -- Clients will only receive the headers set in the "mother" document (the headers in the "/" response in this case). +- Fastly flags it resource as "not cachable" because it set a cookie at least once. +Even though that endpoint stops setting cookies, Fastly still doesn't cache that fragment. +Any document referring to that ESI is a `MISS`. +Fastly cache needs to be purged (`Purge-all` request) to remove this flag. -- Only the content of ESIs responses will be returned to the client. **No headers set in the ESI response will ever reach the client**. ESI headers are only seen by the HTTP cache. - -- Symfony reverse proxy does not support ESIs at all, and any ESI calls (`render_esi()`) will implicitly be replaced by - sub-requests (`render()`). So any `Set-Cookie` **will** be sent to the client when using Symfony reverse proxy. - -- Fastly will flag it resource as "not cachable" because it set a cookie at least once. Even though that endpoint. - stops setting cookies, Fastly will still not cache that fragment. Any document referring to that ESI will be a `MISS`. - Fastly cache needs to be purged (`Purge-all` request) in order to remove this flag. - -- It means that it is not recommended to always initiate a session when loading the front page. +- It means that it's not recommended to always initiate a session when loading the front page. -You must ensure that you do not unintendedly start a session in a controller used by ESIs, for example, when trying to access as session variable before a session has been initiated yet. +You must ensure that you don't unintendedly start a session in a controller used by ESIs, for example, when trying to access as session variable before a session has been initiated yet. diff --git a/docs/infrastructure_and_maintenance/cache/http_cache/context_aware_cache.md b/docs/infrastructure_and_maintenance/cache/http_cache/context_aware_cache.md index 81e7faf16c..d39204d565 100644 --- a/docs/infrastructure_and_maintenance/cache/http_cache/context_aware_cache.md +++ b/docs/infrastructure_and_maintenance/cache/http_cache/context_aware_cache.md @@ -7,10 +7,8 @@ description: Context-aware HTTP cache caches requests depending on the logged-in [[= product_name =]] allows caching requests made by logged-in users. This is called (user) context-aware cache. -It means that HTTP cache is unique per set of user permissions (Roles and Limitations), -and there are variations of cache shared only among users that have the exact same permissions. -So if a user browses a list of children Locations, they will only see children Locations -they have access to, even if their rendering is served from HTTP cache. +It means that HTTP cache is unique per set of user permissions (roles and limitations), and there are variations of cache shared only among users that have the exact same permissions. +So if a user browses a list of children locations, they only see children locations they have access to, even if their rendering is served from HTTP cache. This is accomplished by varying on a header called `X-Context-User-Hash`, which the system populates on the request. The [logic for this](#request-lifecycle) is accomplished in the provided VCL for Varnish and Fastly. @@ -25,10 +23,9 @@ This expands steps covered in [FOSHttpCacheBundle documentation on user context 1. The application receives the hash request. An event subscriber (`UserContextSubscriber`) aborts the request immediately after the Symfony firewall is applied. The application calculates the hash (`HashGenerator`) and then sends a response with the hash in a custom header (`X-Context-User-Hash`). 1. The caching proxy receives the hash response, copies the hash header to the client's original request for `/foo` and restarts the modified original request. -1. If the response to `/foo` should differ per user context, the application sets a `Vary: X-Context-User-Hash` header, which will make Proxy store the variations of this cache varying on the hash value. +1. If the response to `/foo` should differ per user context, the application sets a `Vary: X-Context-User-Hash` header, which makes Proxy store the variations of this cache varying on the hash value. -The next time a request comes in from the same user, application lookup for the hash (step 3) does not take place, -as the hash lookup itself is cached by the cache proxy as described below. +The next time a request comes in from the same user, application lookup for the hash (step 3) doesn't take place, as the hash lookup itself is cached by the cache proxy as described below. ### User context hash caching @@ -43,34 +40,27 @@ Vary: Cookie, Authorization ``` In the example above the response is set to be cached for 10 minutes. -It varies on the `Cookie` header in order to be able to cache it for the given user. +It varies on the `Cookie` header to be able to cache it for the given user. To optimize it, the default VCL strips any cookie other than session cookies to make this work. It also varies on `Authorization` to cover any possible basic authorization headers in case that is used over sessions for some requests. !!! note "Problems with stale user hash" - If you notice issues with stale hash usage, before you disable this cache, make sure login or logout always - generates new session IDs and performs a full redirect to make sure no requests are being made using stale - user context hashes. + If you notice issues with stale hash usage, before you disable this cache, make sure login or logout always generates new session IDs and performs a full redirect to make sure no requests are being made with stale user context hashes. !!! caution "Limitations of the user context hash" - If you use URI-based SiteAccess matching on a multi-repository installation (multiple databases), - the default SiteAccess on the domain needs to point to the same repository (database), - because `/_fos_user_context_hash` is not SiteAccess-aware by default (see - `ibexa.rest.default_router.non_siteaccess_aware_routes` parameter). - This occurs because reverse proxy does not have knowledge about SiteAccesses - and it does not pass the whole URL to be able to cache the user context hash response. + If you use URI-based SiteAccess matching on a multi-repository installation (multiple databases), the default SiteAccess on the domain needs to point to the same repository (database), because `/_fos_user_context_hash` isn't SiteAccess-aware by default (see `ibexa.rest.default_router.non_siteaccess_aware_routes` parameter). + This occurs because reverse proxy doesn't have knowledge about SiteAccesses and it doesn't pass the whole URL to be able to cache the user context hash response. - The only known workaround is to make it SiteAccess aware, and have custom VCL logic tied to your SiteAccess - matching with Varnish/Fastly, to send the SiteAccess prefix as URI. + The only known workaround is to make it SiteAccess aware, and have custom VCL logic tied to your SiteAccess matching with Varnish/Fastly, to send the SiteAccess prefix as URI. !!! caution "Default options for FOSHttpCacheBundle" The following configuration is defined by default for FOSHttpCacheBundle. - You should not override these settings unless you know what you are doing. + You should not override these settings unless you know what you're doing. ``` yaml fos_http_cache: @@ -95,10 +85,9 @@ Here are some generic recommendations on how to approach personalized content wi 1\. ESI with vary by cookie: Default VCL strips everything except session cookie, so this is effectively "per user". -If you are on single-server setup without Varnish or Fastly, you can use the same cookie logic on the web server instead. +If you're on single-server setup without Varnish or Fastly, you can use the same cookie logic on the web server instead. -This a low effort solution, and can be enough for one fragment that is reused across the whole site, -for example, in header to show user name: +This a low effort solution, and can be enough for one fragment that is reused across the whole site, for example, in header to show user name: Example: @@ -109,11 +98,11 @@ Example: 2\. Ajax/JS lookup to "uncached" custom Symfony controllers: -This method does not consume memory in Varnish. -It can optionally be cached with custom logic: Symfony Cache on server side and/or with client side caching techniques. -This should be done as Ajax/JS lookup to avoid the uncached request that slows down the whole delivery of Vanish if it is done as ESI. +This method doesn't consume memory in Varnish. +It can optionally be cached with custom logic: Symfony Cache on server side and/or with client side caching techniques. +This should be done as Ajax/JS lookup to avoid the uncached request that slows down the whole delivery of Vanish if it's done as ESI. -This solution requires more effort depending on project requirements (traffic load, etc.). +This solution requires more effort depending on project requirements (for example, traffic load). 3\. Custom vary by logic, for example, `X-User-Preference-Hash` inspired by `X-Context-User-Hash`: @@ -123,8 +112,7 @@ This solution requires more effort (controller, VCL logic and adapting your own !!! tip "Dealing with paywall use cases" - If you need to handle a paywall on a per-item basis, or example, do a - lookup to backend for each URL where this is relevant. + If you need to handle a paywall on a per-item basis, or example, do a lookup to backend for each URL where this is relevant. You can find an example for paywall authorization in [FOSHTTPCache documentation](https://foshttpcache.readthedocs.io/en/latest/user-context.html#alternative-for-paywalls-authorization-request). @@ -132,23 +120,20 @@ This solution requires more effort (controller, VCL logic and adapting your own For information on how user context hashes are generated, see [FOSHttpCacheBundle documentation](https://foshttpcachebundle.readthedocs.io/en/latest/features/user-context.html#generating-hashes). -[[= product_name =]] implements a custom context provider in order to make user context hash reflect the current User's Roles and Limitations. +[[= product_name =]] implements a custom context provider to make user context hash reflect the current user's roles and limitations. This is needed given [[= product_name =]]'s more complex permission model compared to Symfony's. You can technically extend the user context hash by [implementing your own custom context provider(s)](https://foshttpcachebundle.readthedocs.io/en/latest/reference/configuration/user-context.html#custom-context-providers). -However, **this is strongly discouraged** as it means increasing the amount of cache variations -stored in proxy for every single cache item, lowering cache hit ratio and increasing memory use. +However, **this is strongly discouraged** as it means increasing the amount of cache variations stored in proxy for every single cache item, lowering cache hit ratio and increasing memory use. -Instead, you can create your own hash header for use cases where you need it. -This way only controllers and views that really vary by your custom logic will vary on it. +Instead, you can create your own hash header for use cases where you need it. +This way only controllers and views that really vary by your custom logic varies on it. -You can do it using several methods, ranging from completely custom VCL logic and dedicated controller to respond with hash -to trusted proxy lookups, but this means additional lookups. +You can use several methods to do it, ranging from completely custom VCL logic and dedicated controller to respond with hash to trusted proxy lookups, but this means additional lookups. ### Example for custom vary by logic -You can extend `/_fos_user_context_hash` lookup to add another HTTP header with custom hash for your -needs, and adapt the user context hash VCL logic to use the additional header. +You can extend `/_fos_user_context_hash` lookup to add another HTTP header with custom hash for your needs, and adapt the user context hash VCL logic to use the additional header. To avoid overloading any application code, take advantage of Symfony's event system: diff --git a/docs/infrastructure_and_maintenance/cache/http_cache/fastly.md b/docs/infrastructure_and_maintenance/cache/http_cache/fastly.md index 4e9ff0e105..bd7ee11a78 100644 --- a/docs/infrastructure_and_maintenance/cache/http_cache/fastly.md +++ b/docs/infrastructure_and_maintenance/cache/http_cache/fastly.md @@ -4,26 +4,25 @@ description: Configure Fastly for use with Ibexa DXP. # Configure and customize Fastly -You can configure Fastly by using API calls or through the Fastly Web Interface. +You can configure Fastly by using API calls or through the Fastly Web Interface. Fastly provides a [Fastly CLI](https://developer.fastly.com/reference/cli/) for configuring Fastly through its API. -Ibexa Cloud is delivered with Fastly preconfigured. -It means that you don't have to do any changes to the Fastly configuration to make your site work. -The information provided here is only applicable if you want to change the default Fastly configuration on Ibexa Cloud, -or if you are not using Ibexa Cloud and want to configure Fastly to work with [[= product_name =]] on premise. +[[= product_name_cloud =]] is delivered with Fastly preconfigured. +It means that you don't have to do any changes to the Fastly configuration to make your site work. +The information provided here is only applicable if you want to change the default Fastly configuration on [[= product_name_cloud =]], or if you're not using [[= product_name_cloud =]] and want to configure Fastly to work with [[= product_name =]] on premise. -!!! note "The Fastly Web Interface is not available for Ibexa Cloud" - It's recommend for Ibexa Cloud customers to use the Fastly CLI instead of using the Fastly API directly with `curl`, and so on. +!!! note "The Fastly Web Interface isn't available for [[= product_name_cloud =]]" + It's recommend for [[= product_name_cloud =]] customers to use the Fastly CLI instead of using the Fastly API directly with `curl`, or other alternatives. !!! note "Disable Varnish when you use Fastly" - Varnish is automatically provisioned on Ibexa Cloud. Varnish needs to be disabled on all environments that use + Varnish is automatically provisioned on [[= product_name_cloud =]]. Varnish needs to be disabled on all environments that use Fastly. See [documentation on how to do that](https://docs.platform.sh/guides/ibexa/fastly.html). ## Prepare for using Fastly locally -These steps are not needed when you use Ibexa Cloud, because Fastly is preconfigured in it. +These steps aren't needed when you use [[= product_name_cloud =]], because Fastly is preconfigured in it. -### Get Fastly credentials from Ibexa Cloud installation +### Get Fastly credentials from [[= product_name_cloud =]] installation To use Fastly CLI or Fastly API directly, you need to obtain the credentials for your site. To obtain the credentials, connect to your Fastly-enabled environment (for example, production or staging) through SSH and run the following command: @@ -34,7 +33,7 @@ FASTLY_KEY=... FASTLY_SERVICE_ID=... ``` -These credentials are different for your production and staging environments. +These credentials are different for your production and staging environments. When you configure the Fastly CLI, use the credentials for the environment that you want to change. !!! note "Different environment variable names between products" @@ -56,7 +55,7 @@ fastly service-version activate --version=latest ## Quick introduction to Fastly CLI Fastly configuration is versioned, which means that when you alter the configuration, you create a new version -and activate it. +and activate it. If needed, you can revert the configuration to one of previous versions at any point. ### List configuration versions @@ -99,10 +98,10 @@ fastly service-version clone --version=latest ``` !!! note "Command parameters" - Most Fastly CLI commands have the `--version` parameter. + Most Fastly CLI commands have the `--version` parameter. In addition to a specific version number, the `--version` parameter always supports aliases like `active` and `latest`. - Most Fastly CLI commands that alter the config also support the `--autoclone` parameter. + Most Fastly CLI commands that alter the config also support the `--autoclone` parameter. With such commands, when you use the `--autoclone` parameter, calling `fastly service-version clone` is no longer needed. ### Activate version @@ -115,7 +114,7 @@ fastly service-version activate --version=latest ## View and modify VCL configuration -Fastly configuration is stored in Varnish Configuration Language (VCL) files. +Fastly configuration is stored in Varnish Configuration Language (VCL) files. You can change the behaviour of Fastly by [uploading custom VCL files](https://docs.fastly.com/en/guides/uploading-custom-vcl). [[= product_name =]] ships with two VCL files that need to be enabled for Fastly to work correctly with the platform; `ez_main.vcl` and `ez_user_hash.vcl` (located in `vendor/ibexa/fastly/fastly/`) @@ -193,7 +192,7 @@ Versions: 8 ### Modify Fastly configuration -You can modify the existing Fastly configuration, for example, by uploading a modified `.vcl` file. +You can modify the existing Fastly configuration, for example, by uploading a modified `.vcl` file. Create a new version based on the one that is currently active, and upload the file: @@ -215,12 +214,12 @@ fastly service-version activate --version=latest ## Snippets -You can also add VCL code to the Fastly configuration without modifying the custom `.vcl` files directly. +You can also add VCL code to the Fastly configuration without modifying the custom `.vcl` files directly. You do it by creating [snippets](https://docs.fastly.com/en/guides/about-vcl-snippets). -It is recommended that you use snippets instead of changing the VCL files provided by [[= product_name =]] as much as possible, which makes it easier to upgrade the [[= product_name =]] VCL configuration later. +it's recommended that you use snippets instead of changing the VCL files provided by [[= product_name =]] as much as possible, which makes it easier to upgrade the [[= product_name =]] VCL configuration later. When you use snippets, the snippet code is injected into the VCL where the `#FASTLY ...` macros are placed. -For example, if you create a snippet for the `recv` subroutine, it is injected into the `ez_main.vcl` file, the +For example, if you create a snippet for the `recv` subroutine, it's injected into the `ez_main.vcl` file, the line where `#FASTLY recv` is found. ### List available snippets for specific version @@ -236,7 +235,7 @@ KlUh0J1fnw1JY1aEQ0up 8 Re-Enable shielding on restart false 1iJWIf ### Get details of installed snippets -Use the `vcl snippet list` command with the `--verbose` option to get information such as: priority, which subroutine it is attached to (`vcl_recv`, `vcl_fetch` etc.) and the code itself. +Use the `vcl snippet list` command with the `--verbose` option to get information such as: priority, which subroutine it's attached to (for example, `vcl_recv` or `vcl_fetch`) and the code itself. ``` bash fastly vcl snippet list --version=active -v @@ -303,8 +302,8 @@ fastly service-version activate --version=latest ### Get diff between two versions -You can easily view the diff between two different versions by using the Fastly web interface. -Unfortunately, Fastly CLI does not support this functionality. +You can view the diff between two different versions by using the Fastly web interface. +Unfortunately, Fastly CLI doesn't support this functionality. However, Fastly API and GNU diff can help you get an identical result. Use the Fastly API to download the generated `.vcl` file. It includes the VCL configuration that Fastly generates @@ -346,7 +345,7 @@ Usernames and passwords can be stored inside the VCL file, but in this case cred ### Create and activate dictionary -Fastly configuration includes a dictionary named `basicauth`. +Fastly configuration includes a dictionary named `basicauth`. Using a dictionary instead of storing usernames directly in a `.vcl` file is beneficial, because you can add or remove records without having to create and activate new configuration versions. ``` bash @@ -390,8 +389,8 @@ fastly dictionary-entry list --dictionary-id=ltC6Rg4pqw4qaNKF5tEW33 ``` Now your dictionary stores new username and password. The next thing to do is to alter the Fastly VCL configuration -and add the basic-auth support. -This example uses [snippets](https://docs.fastly.com/en/guides/about-vcl-snippets), so that no changes are needed in the `.vcl` files that are shipped with [[= product_name =]]. +and add the basic-auth support. +This example uses [snippets](https://docs.fastly.com/en/guides/about-vcl-snippets), so that no changes are needed in the `.vcl` files that are shipped with [[= product_name =]]. You need two snippets, store these as files in your system: In `snippet_basic_auth_error.vcl`: @@ -443,7 +442,7 @@ declare local var.username STRING; declare local var.password STRING; declare local var.result STRING; -# Basic auth is checked on edge nodes only. The logic below makes sure that it is only run at the edge. +# Basic auth is checked on edge nodes only. The logic below makes sure that it's only run at the edge. if (fastly.ff.visits_this_service == 0 && req.restarts == 0) { if (req.http.Authorization ~ "(?i)^Basic ([a-z0-9_=]+)$") { set var.credential = digest.base64_decode(re.group.1); @@ -480,4 +479,3 @@ fastly vcl snippet create --name="BasicAuth error" --version=latest --priority 1 fastly service-version activate --version=latest ``` - diff --git a/docs/infrastructure_and_maintenance/cache/http_cache/http_cache.md b/docs/infrastructure_and_maintenance/cache/http_cache/http_cache.md index 10661012d0..3ef834ec29 100644 --- a/docs/infrastructure_and_maintenance/cache/http_cache/http_cache.md +++ b/docs/infrastructure_and_maintenance/cache/http_cache/http_cache.md @@ -4,13 +4,10 @@ description: Ibexa DXP's HTTP cache functionalities enable using reverse proxies # HTTP cache -[[= product_name =]] provides advanced caching features needed for its own content views, -to make Varnish and Fastly act as the view cache for the system. +[[= product_name =]] provides advanced caching features needed for its own content views, to make Varnish and Fastly act as the view cache for the system. This and other features allow [[= product_name =]] to be scaled up to serve high traffic websites and applications. -HTTP cache is handled by the [ibexa/http-cache](https://github.com/ibexa/http-cache) bundle, -which extends [friendsofsymfony/http-cache-bundle](https://foshttpcachebundle.readthedocs.io/en/latest/), -a Symfony community bundle that in turn extends [Symfony HTTP cache]([[= symfony_doc =]]/http_cache.html). +HTTP cache is handled by the [ibexa/http-cache](https://github.com/ibexa/http-cache) bundle, which extends [friendsofsymfony/http-cache-bundle](https://foshttpcachebundle.readthedocs.io/en/latest/), a Symfony community bundle that in turn extends [Symfony HTTP cache]([[= symfony_doc =]]/http_cache.html). For content view responses coming from [[= product_name =]] itself, this means that: diff --git a/docs/infrastructure_and_maintenance/cache/http_cache/http_cache_configuration.md b/docs/infrastructure_and_maintenance/cache/http_cache/http_cache_configuration.md index 7a07ffb8eb..e087d374b9 100644 --- a/docs/infrastructure_and_maintenance/cache/http_cache/http_cache_configuration.md +++ b/docs/infrastructure_and_maintenance/cache/http_cache/http_cache_configuration.md @@ -26,7 +26,8 @@ As the system takes care of purges, the cache should not become stale with the e ## Cache header rules -A few redirect and error pages are served through the content view system. If you set a high `default_ttl`, they can also be served from cache. +A few redirect and error pages are served through the content view system. +If you set a high `default_ttl`, they can also be served from cache. To avoid this, the installation ships with configuration to match these specific situations and set a much lower TTL. [FOSHttpCacheBundle matching rules](https://foshttpcachebundle.readthedocs.io/en/latest/reference/configuration/headers.html) enables you to specify a different TTL: @@ -68,11 +69,9 @@ fos_http_cache: ## Time-to-live value for Page blocks For the Page Builder, block cache by default respects `$content.ttl_cache$` and `$content.default_ttl$` settings. -However, if the given block value has a since or till date, -it is taken into account for the TTL calculation for both the block and the whole page. +However, if the given block value has a since or till date, it's taken into account for the TTL calculation for both the block and the whole page. -To overload this behavior, listen to [`BlockResponseEvents::BLOCK_RESPONSE`](page_events.md), -and set priority to `-200` to adapt what Page Field Type does by default. +To overload this behavior, listen to [`BlockResponseEvents::BLOCK_RESPONSE`](page_events.md), and set priority to `-200` to adapt what Page field type does by default. For example, to disable cache for the block, use `$event->getResponse()->setPrivate()`. @@ -80,19 +79,17 @@ For example, to disable cache for the block, use `$event->getResponse()->setPriv [Edge Side Includes](https://symfony.com/doc/current/http_cache/esi.html) (ESI) can be used to split out the different parts of a web page into separate fragments that can be freely reused as pieces by reverse proxy. -In practice, with ESI, every sub-request is regenerated from application perspective. And while you can tune your system to reduce this, it always causes additional overhead in the following situations: +In practice, with ESI, every sub-request is regenerated from application perspective. +And while you can tune your system to reduce this, it always causes additional overhead in the following situations: - When cache is cold on all or some of the sub-requests - With Symfony Proxy (AppCache) there is always some overhead, even on warm cache (hits) - In development environment -This may differ depending on your system, however, it is recommended to stay below 5 ESI -requests per page and only using them for parts that are the same across the whole site or larger parts of it. +This may differ depending on your system, however, it's recommended to stay below 5 ESI requests per page and only using them for parts that are the same across the whole site or larger parts of it. -You should not use ESI for parts that are effectively uncached, -because your reverse proxy has to wait for the back end and cannot deliver cached pages directly. +You should not use ESI for parts that are effectively uncached, because your reverse proxy has to wait for the back end and cannot deliver cached pages directly. !!! note "ESI limitations with the URIElement SiteAccess matcher" - Is is not possible to share ESIs across the SiteAccesses when using URI matching - as URI contains the SiteAccess name encoded in its path information. + Is isn't possible to share ESIs across the SiteAccesses when using URI matching as URI contains the SiteAccess name encoded in its path information. diff --git a/docs/infrastructure_and_maintenance/cache/http_cache/reverse_proxy.md b/docs/infrastructure_and_maintenance/cache/http_cache/reverse_proxy.md index b4949cd261..3367b6e64d 100644 --- a/docs/infrastructure_and_maintenance/cache/http_cache/reverse_proxy.md +++ b/docs/infrastructure_and_maintenance/cache/http_cache/reverse_proxy.md @@ -41,12 +41,11 @@ Using a different proxy is highly recommended as they provide better performance !!! note - Use of Varnish or Fastly is a requirement for a [Clustering](clustering.md) setup, as Symfony Proxy does not support sharing cache between several application servers. + Use of Varnish or Fastly is a requirement for a [clustering](clustering.md) setup, as Symfony Proxy doesn't support sharing cache between several application servers. ## VCL base files -For reverse proxies to work properly with your installation, you need to add the corresponding VCL files for your -HTTP Cache. +For reverse proxies to work properly with your installation, you need to add the corresponding VCL files for your HTTP Cache. - [Varnish VCL xkey example](https://github.com/ibexa/http-cache/blob/main/docs/varnish/vcl/varnish5.vcl) - Fastly can be found in `vendor/ibexa/fastly/fastly`. You must install the following to use Fastly: @@ -58,12 +57,9 @@ The provided `.vcl` files work both with [Fastly Shielding](https://docs.fastly. If you decide to use Fastly VCL, consider using [Fastly CLI](https://developer.fastly.com/learning/tools/cli/#installing) with it to manage VCL files from the command line. To learn more, see [Prepare to use Fastly locally](fastly.md#prepare-for-using-fastly-locally) and [Introduction to Fastly CLI](fastly.md#quick-introduction-to-fastly-cli). -!!! tip - Support for Fastly Shielding was added in Ibexa DXP v3.3.24 and v4.1.6 +!!! tip "Support for Fastly Shielding was added in [[= product_name =]] v3.3.24 and v4.1.6" - When you extend [FOSHttpCacheBundle](https://foshttpcachebundle.readthedocs.io/en/latest/), - you can also adapt your VCL further with [FOSHttpCache documentation](https://foshttpcache.readthedocs.io/en/latest/varnish-configuration.html) - to use additional features. + When you extend [FOSHttpCacheBundle](https://foshttpcachebundle.readthedocs.io/en/latest/), you can also adapt your VCL further with [FOSHttpCache documentation](https://foshttpcache.readthedocs.io/en/latest/varnish-configuration.html) to use additional features. ## Configure Varnish and Fastly @@ -73,49 +69,45 @@ Failing to configure reverse proxies correctly may introduce several problems, i - [[= product_name =]] generating links with a wrong protocol schema (HTTP instead of HTTPS) if HTTPS termination is done before the web server due to the `X-Forward-Proto` headers being ignored - [[= product_name =]] generating links with wrong port numbers due to the `X-Forward-Port` headers being ignored -- Back Office showing the login screen because JWT tokens are not accepted due to the `X-Forward-For` headers being ignored +- back office showing the login screen because JWT tokens aren't accepted due to the `X-Forward-For` headers being ignored ### Configure Symfony front controller You need to consider your `TrustedProxy` configuration when you use Symfony [behind a load balancer or a reverse proxy](https://symfony.com/doc/5.1/deployment/proxies.html). -To configure trusted proxies, use [Symfony semantic configuration]([[= symfony_doc =]]/deployment/proxies.html#solution-settrustedproxies) under -the `framework.trusted_proxies` [configuration key](configuration.md#configuration-files), for example: +To configure trusted proxies, use [Symfony semantic configuration]([[= symfony_doc =]]/deployment/proxies.html#solution-settrustedproxies) under the `framework.trusted_proxies` [configuration key](configuration.md#configuration-files), for example: ``` yaml framework: trusted_proxies: '192.0.0.1,10.0.0.0/8' ``` -!!! caution "Careful when trusting dynamic IP using `REMOTE_ADDR` value or similar" +!!! caution "Careful when trusting dynamic IP that uses `REMOTE_ADDR` value or similar" - On Platform.sh, Varnish does not have a static IP, like with [AWS LB](https://symfony.com/doc/5.1/deployment/proxies.html#but-what-if-the-ip-of-my-reverse-proxy-changes-constantly). + On Platform.sh, Varnish doesn't have a static IP, like with [AWS LB](https://symfony.com/doc/5.1/deployment/proxies.html#but-what-if-the-ip-of-my-reverse-proxy-changes-constantly). For this reason, the `TRUSTED_PROXIES` env variable supports being set to value `REMOTE_ADDR`, which is equal to: - + ```php Request::setTrustedProxies([$request->server->get('REMOTE_ADDR')], Request::HEADER_X_FORWARDED_ALL); ``` - When trusting remote IP like this, make sure your application is only accessible through Varnish. - If it is accessible in other ways, this may result in trusting, for example, the IP of client browser instead, which would be a serious security issue. + When trusting remote IP like this, make sure your application is only accessible through Varnish. + If it's accessible in other ways, this may result in trusting, for example, the IP of client browser instead, which would be a serious security issue. - Make sure that **all** traffic always comes from the trusted proxy/load balancer, - and that there is no other way to configure it. + Make sure that **all** traffic always comes from the trusted proxy/load balancer, and that there is no other way to configure it. When using Fastly, you need to set `trusted_proxies` according to the [IP ranges used by Fastly](https://api.fastly.com/public-ip-list). !!! tip You don't have to set `trusted_proxies` when using Fastly on Platform.sh. - The Platform.sh router automatically changes the source IP of requests coming from Fastly, - replacing the source IP with the actual client IP and removing any `X-FORWARD-...` header in the request before it reaches Ibexa DXP. + The Platform.sh router automatically changes the source IP of requests coming from Fastly, replacing the source IP with the actual client IP and removing any `X-FORWARD-...` header in the request before it reaches [[= product_name =]]. For more information about setting these variables, see [Configuration examples](#configuration-examples). ### Update YML configuration -Next, you need to tell [[= product_name =]] to use an HTTP-based purge client (specifically the FosHttpCache Varnish purge client), -and specify the URL that Varnish can be reached on: +Next, you need to tell [[= product_name =]] to use an HTTP-based purge client (specifically the FosHttpCache Varnish purge client), and specify the URL that Varnish can be reached on: | Configuration | Parameter| Environment variable| Possible values| |---------|--------|--------|----------| @@ -125,8 +117,7 @@ and specify the URL that Varnish can be reached on: | `ibexa.system..http_cache.fastly.service_id` | `fastly_service_id` | `FASTLY_SERVICE_ID` | Service ID to authenticate with Fastly. | | `ibexa.system..http_cache.fastly.key` | `fastly_key` | `FASTLY_KEY` | Service key/token to authenticate with Fastly. | -If you need to set multiple purge servers, configure them in the YAML configuration, -instead of parameter or environment variable, as they only take single string value. +If you need to set multiple purge servers, configure them in the YAML configuration, instead of parameter or environment variable, as they only take single string value. Example configuration for Varnish as reverse proxy, providing that [front controller has been configured](#configure-symfony-front-controller): @@ -162,18 +153,16 @@ env:HTTPCACHE_PASSWORD=mypasswd If you want to use Basic Auth with Fastly on [[= product_name_cloud =]], please see [Enable basic-auth on Fastly](fastly.md#enable-basic-auth-on-fastly). -!!! note "Invalidating Varnish cache using tokens" +!!! note "Invalidating Varnish cache by using tokens" + + In setups where the Varnish server IP can change (for example, on [[= product_name_cloud =]]), you can use token-based cache invalidation through [`ez_purge_acl`](https://github.com/ibexa/http-cache/blob/main/docs/varnish/vcl/varnish5.vcl#L174). - In setups where the Varnish server IP can change (for example, on [[= product_name_cloud =]]), - you can use token-based cache invalidation through [`ez_purge_acl`](https://github.com/ibexa/http-cache/blob/main/docs/varnish/vcl/varnish5.vcl#L174). - In such situation, use strong, secure hash and make sure to keep the token secret. ### Ensure proper Captcha behavior [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] -If your installation uses Varnish and you want users to be able to configure and use Captcha in their forms, -you must enable sending Captcha data as a response to an Ajax request. -Otherwise, Varnish does not allow for the transfer of Captcha data to the form, and as a result, users see an empty image. +If your installation uses Varnish and you want users to be able to configure and use Captcha in their forms, you must enable sending Captcha data as a response to an Ajax request. +Otherwise, Varnish doesn't allow for the transfer of Captcha data to the form, and as a result, users see an empty image. To enable sending Captcha over Ajax, add the following configuration: @@ -188,8 +177,7 @@ ibexa: ### Update custom Captcha block [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] -If you created a custom Captcha block for your site by overriding the default file (`vendor/gregwar/captcha-bundle/Resources/views/captcha.html.twig`), -you must make the following changes to the custom block template file: +If you created a custom Captcha block for your site by overriding the default file (`vendor/gregwar/captcha-bundle/Resources/views/captcha.html.twig`), you must make the following changes to the custom block template file: - change the name of the block to `ajax_captcha_widget` - include the JavaScript file: @@ -247,13 +235,13 @@ FASTLY_KEY="token" #### Configure Fastly on Platform.sh -If you use Platform.sh, it is recommended to configure all environment variables through [Platform.sh variables](https://docs.platform.sh/guides/ibexa/fastly.html). -In [[= product_name =]], Varnish is enabled by default. To use Fastly, first you must -[disable Varnish](https://docs.platform.sh/guides/ibexa/fastly.html#remove-varnish-configuration) +If you use Platform.sh, it's recommended to configure all environment variables through [Platform.sh variables](https://docs.platform.sh/guides/ibexa/fastly.html). +In [[= product_name =]], Varnish is enabled by default. To use Fastly, first you must [disable Varnish](https://docs.platform.sh/guides/ibexa/fastly.html#remove-varnish-configuration). #### Get Fastly service ID and API token -To get the service ID, log in to https://www.fastly.com/. In the upper menu, click the **CONFIGURE** tab. +To get the service ID, log in to https://www.fastly.com/. +In the upper menu, click the **CONFIGURE** tab. The service ID is displayed next to the name of your service on any page. For instructions on how to generate a Fastly API token, see [the Fastly guide](https://docs.fastly.com/en/guides/using-api-tokens). @@ -290,8 +278,7 @@ You can configure environment variables through [Platform.sh variables](https:// !!! tip - For HTTP cache, you will most likely only use this for configuring Fastly for production and optionally staging, - allowing `variables:env:` in `.platform.app.yaml` to, for example, specify Varnish or Symfony proxy as default for dev environment. + For HTTP cache, you most likely only use this for configuring Fastly for production and optionally staging, allowing `variables:env:` in `.platform.app.yaml` to, for example, specify Varnish or Symfony proxy as default for dev environment. #### Apache with Varnish @@ -326,31 +313,27 @@ fastcgi_param FASTLY_KEY "token" Stale cache, or grace mode in Varnish, occurs when: - Cache is served some time after the TTL expired. -- When the back-end server does not respond. +- When the back-end server doesn't respond. -This has several benefits for high traffic installations to reduce load to the back end. -Instead of creating several concurrent requests for the same page to the back end, -the following happens when a page has been soft purged: +This has several benefits for high traffic installations to reduce load to the back end. +Instead of creating several concurrent requests for the same page to the back end, the following happens when a page has been soft purged: - Next request hitting the cache triggers an asynchronous lookup to the back end. -- If cache is still within grace period, first and subsequent requests for the content are served from cache, -and do not wait for the asynchronous lookup to finish. +- If cache is still within grace period, first and subsequent requests for the content are served from cache, and don't wait for the asynchronous lookup to finish. - The back-end lookup finishes and refreshes the cache so any subsequent requests get a fresh cache. -By default, [[= product_name =]] always soft purges content on reverse proxies that support it (Varnish and Fastly), -with the following logic in the out-of-the-box VCL: +By default, [[= product_name =]] always soft purges content on reverse proxies that support it (Varnish and Fastly), with the following logic in the out-of-the-box VCL: - Cache is within grace period. -- Either the server is not responding, or the request comes without a session cookie (anonymous user). +- Either the server isn't responding, or the request comes without a session cookie (anonymous user). -Serving grace is not always allowed by default because: +Serving grace isn't always allowed by default because: -- It is a safe default. Even if just for anonymous users, stale cache can easily be confusing during acceptance testing. -- It means REST API, which is used by the Back Office, would serve stale data, breaking the UI. +- It's a safe default. Even if for anonymous users, stale cache can be confusing during acceptance testing. +- It means REST API, which is used by the back office, would serve stale data, breaking the UI. !!! tip "Customizing stale cache handling" - If you want to use grace handling for logged-in users as well, you can adapt the provided VCL to add a condition - for opting out if the request has a cookie and the path contains REST API prefix to make sure the Back Office is not negatively affected. + If you want to use grace handling for logged-in users as well, you can adapt the provided VCL to add a condition for opting out if the request has a cookie and the path contains REST API prefix to make sure the back office isn't negatively affected. If you want to disable grace mode, you can adapt the VCL to do hard instead of soft purges, or set grace/stale time to `0s`. diff --git a/docs/infrastructure_and_maintenance/cache/persistence_cache.md b/docs/infrastructure_and_maintenance/cache/persistence_cache.md index dc06e9396a..2e6a2ad02c 100644 --- a/docs/infrastructure_and_maintenance/cache/persistence_cache.md +++ b/docs/infrastructure_and_maintenance/cache/persistence_cache.md @@ -10,18 +10,17 @@ description: Persistence cache caches SPI\Persistence calls used in common page Persistence cache can best be described as an implementation of `SPI\Persistence` that decorates the main backend implementation, aka Storage Engine *(currently: "Legacy Storage Engine")*. -As shown in the illustration, this is done in the exact same way as the Event layer is a custom implementation of `API\Repository` decorating the main Repository. -In the case of Persistence Cache, instead of sending events on calls passed on to the decorated implementation, most of the load calls are cached, and calls that perform changes purge the affected caches. -Cache handlers *(Memcached, Redis, Filesystem, etc.)* can be configured using Symfony configuration. +As shown in the illustration, this is done in the exact same way as the event layer is a custom implementation of `API\Repository` decorating the main repository. +In the case of persistence cache, instead of sending events on calls passed on to the decorated implementation, most of the load calls are cached, and calls that perform changes purge the affected caches. +Cache handlers *(for example, Memcached, Redis, or Filesystem)* can be configured using Symfony configuration. For details on how to reuse this Cache service in your own custom code, see below. ## Transparent cache -With the persistence cache, just like with the HTTP cache, [[= product_name =]] tries to follow principles of transparent caching. -This can shortly be described as a cache which is invisible to the end user (admin/editors) of [[= product_name =]] where content -is always returned *fresh*. In other words, there should be no need to manually clear the cache like it was frequently -the case with eZ Publish 4.x. This is possible thanks to an interface that follows CRUD (Create Read Update Delete) -operations per domain. +With the persistence cache, like with the HTTP cache, [[= product_name =]] tries to follow principles of transparent caching. +This can shortly be described as a cache which is invisible to the end user (admin/editors) of [[= product_name =]] where content is always returned *fresh*. +In other words, there should be no need to manually clear the cache like it was frequently the case with eZ Publish 4.x. +This is possible thanks to an interface that follows CRUD (Create Read Update Delete) operations per domain. ## What is cached? @@ -33,14 +32,13 @@ Notes: order to allow clearing cache by alternative indexes. For instance tree operations or changes to content types are examples of operations that also need to invalidate content cache by tags. -- Search is not defined as persistence and the queries themselves are not planned to be cached as they are too complex by design (for example, full text). +- Search isn't defined as persistence and the queries themselves aren't planned to be cached as they're too complex by design (for example, full text). Use [Solr](solr_overview.md) which caches this for you to improve scale/performance, and to offload your database. -For further details on which calls are cached or not, see details in the [Symfony Web Debug Toolbar](devops.md#web-debug-toolbar) -which has info on cache use in two places: +For further details on which calls are cached or not, see details in the [Symfony Web Debug Toolbar](devops.md#web-debug-toolbar) which has info on cache use in two places: - Symfony Cache tab: for Symfony Cache itself, the tab shows cache lookups to cache backends -- [[= product_name_base =]] tab: shows calls made to database back end, and if they are cached or not +- [[= product_name_base =]] tab: shows calls made to database back end, and if they're cached or not To see where and how to contribute additional caches, refer to the [source code](https://github.com/ibexa/core/blob/main/src/lib/Persistence/Cache/Readme.md). @@ -48,8 +46,8 @@ To see where and how to contribute additional caches, refer to the [source code] !!! note - Current implementation uses Symfony cache. It technically supports the following cache backends: - [APCu, Array, Chain, Doctrine, Filesystem, Memcached, PDO & Doctrine DBAL, Php Array, Proxy, Redis]([[= symfony_doc =]]/components/cache/cache_pools.html#creating-cache-pools). + Current implementation uses Symfony cache. + It technically supports the following cache backends: [APCu, Array, Chain, Doctrine, Filesystem, Memcached, PDO & Doctrine DBAL, Php Array, Proxy, Redis]([[= symfony_doc =]]/components/cache/cache_pools.html#creating-cache-pools). [[= product_name =]] officially supports only using Filesystem for single server and Redis or Memcached for clustered setups. Use of Memcached or Redis as shared cache back end is a requirement for use in clustering setup. @@ -61,12 +59,11 @@ Filesystem adapters, for example, are **not** intended to be used over a shared The underlying cache system is exposed as an `ibexa.cache_pool` service, and can be reused by any other service as described in the [Using Cache service](#using-cache-service) section. By default, configuration uses the `cache.tagaware.filesystem` service to store cache files. -The service is defined in `config/packages/cache_pool/cache.tagaware.filesystem.yaml` -to use [FilesystemTagAwareAdapter](https://github.com/ibexa/recipes/blob/master/ibexa/oss/4.0/config/packages/cache_pool/cache.tagaware.filesystem.yaml#L8). +The service is defined in `config/packages/cache_pool/cache.tagaware.filesystem.yaml` to use [FilesystemTagAwareAdapter](https://github.com/ibexa/recipes/blob/master/ibexa/oss/4.0/config/packages/cache_pool/cache.tagaware.filesystem.yaml#L8). You can select a different cache backend and configure its parameters in the relevant file in the `cache_pool` folder. -### Multi Repository setup +### Multi repository setup You can [configure multisite to work with multiple Repositories](repository_configuration.md#defining-custom-connection). Then, in configuration you can specify which cache pool you want to use on a SiteAccess or SiteAccess group level. @@ -83,20 +80,20 @@ ibexa: cache_service_name: '%cache_pool%' ``` -!!! note "One cache pool for each Repository" +!!! note "One cache pool for each repository" - If your installation has several Repositories *(databases)*, make sure every group of sites using different Repositories also uses a different cache pool. + If your installation has several repositories *(databases)*, make sure every group of sites that uses different repositories also uses a different cache pool. ### In-Memory cache configuration Persistence cache layer caches selected objects in-memory for a short time. -It avoids loading repeatedly the same data from e.g. a remote Redis instance, which can take up to 4-5ms per call due to the network latency and Redis instance load. -The cache is organized in 2 pools, one for metadata which is not updated frequently, and one for content related objects that is only meant as a short-lived burst cache. +It avoids loading repeatedly the same data from, for example, a remote Redis instance, which can take up to 4-5ms per call due to the network latency and Redis instance load. +The cache is organized in 2 pools, one for metadata which isn't updated frequently, and one for content related objects that is only meant as a short-lived burst cache. Limit is organized using a [least frequently used (LFU)](https://en.wikipedia.org/wiki/Least_frequently_used) approach. -It makes sure repeatedly used objects will stay in-memory until expired, and those seldom used will be bulk evicted from cache every time the maximum number of cache items is reached. +It makes sure repeatedly used objects stay in-memory until expired, and those seldom used are bulk evicted from cache every time the maximum number of cache items is reached. -This in-memory cache will be purged *(for the current PHP process)* when clearing it using any of the mentioned methods below. -For other processes, the object will be refreshed when it expires or evicted when it reaches the cache limits. +This in-memory cache is purged *(for the current PHP process)* when clearing it using any of the mentioned methods below. +For other processes, the object is refreshed when it expires or evicted when it reaches the cache limits. In-Memory cache is configured globally, and has the following default settings: @@ -119,9 +116,9 @@ parameters: !!! caution "In-Memory cache is per-process" - **TTL and Limit need to have a low value.** Setting limit high will increase memory use. - High TTL value also increases exponentially risk for system acting on stale metadata (e.g. content type definitions). - The only case where it is safe to increase these values is for dev environment with single concurrency on writes. + **TTL and Limit need to have a low value.** Setting limit high increases memory use. + High TTL value also increases exponentially risk for system acting on stale metadata (for example, content type definitions). + The only case where it's safe to increase these values is for dev environment with single concurrency on writes. In prod environment you should only consider reducing them if you have heavy concurrency writes. ### Redis @@ -129,8 +126,7 @@ parameters: [Redis](https://redis.io/), an in-memory data structure store, is one of the supported cache solutions for clustering. Redis is used via [Redis pecl extension](https://pecl.php.net/package/redis). -See [Redis Cache Adapter in Symfony documentation]([[= symfony_doc =]]/components/cache/adapters/redis_adapter.html#configure-the-connection) -for information on how to connect to Redis. +See [Redis Cache Adapter in Symfony documentation]([[= symfony_doc =]]/components/cache/adapters/redis_adapter.html#configure-the-connection for information on how to connect to Redis. #### Supported Adapters @@ -140,30 +136,30 @@ There are two Redis adapters available out of the box that fit different needs. **Requirement**: Redis server configured with eviction [`maxmemory-policy`](https://redis.io/docs/reference/eviction/#eviction-policies): `volatile-ttl`, `volatile-lru` or `volatile-lfu` (Redis 4.0+). -Use of LRU or LFU is recommended. It is also possible to use `noeviction`, but it is usually not practical. +Use of LRU or LFU is recommended. it's also possible to use `noeviction`, but it's usually not practical. -**Pros**: It is typically faster than `RedisAdapter`, because fewer lookups needed to cache backend. +**Pros**: It's typically faster than `RedisAdapter`, because fewer lookups needed to cache backend. **Cons**: Consumes much more memory. To avoid situations where Redis stops accepting new cache (warnings about `Failed to save key`), set aside enough memory for the Redis server. ##### `Symfony\Component\Cache\Adapter\RedisAdapter` -**Pros**: Uses a bit less memory than `RedisTagAwareAdapter`, so it eliminated the risk of stopping saving cache when there is not enough memory. +**Pros**: Uses a bit less memory than `RedisTagAwareAdapter`, so it eliminated the risk of stopping saving cache when there isn't enough memory. **Cons**: 1.5-2x more lookups to the back-end cache server then `RedisTagAwareAdapter`. Depending on the number of lookups and latency to cache server this might affect page load time. #### Adjusting configuration -Out of the box in `config/packages/cache_pool/cache.redis.yaml` you'll find a default example that can be used. +Out of the box in `config/packages/cache_pool/cache.redis.yaml` you can find a default example that can be used. -!!! note "Ibexa Cloud" +!!! note "[[= product_name_cloud =]]" - For Ibexa Cloud/Platform.sh: This is automatically configured in `vendor/ibexa/core/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php` if you have enabled Redis as `rediscache` Platform.sh service. + For [[= product_name_cloud =]]/Platform.sh: This is automatically configured in `vendor/ibexa/core/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php` if you have enabled Redis as `rediscache` Platform.sh service. For anything else, you can enable it with environment variables. -For instance, if you set the following environment variables `export CACHE_POOL="cache.redis" CACHE_DSN="secret@example.com:1234/13"`, it will result in config like this: +For instance, if you set the following environment variables `export CACHE_POOL="cache.redis" CACHE_DSN="secret@example.com:1234/13"`, it results in config like this: ``` yaml services: @@ -183,23 +179,23 @@ See `.env`, `config/packages/ibexa.yaml` and `config/packages/cache_pool/cache.r !!! caution "Clearing Redis cache" - The regular `php bin/console cache:clear` command does not clear Redis persistence cache. + The regular `php bin/console cache:clear` command doesn't clear Redis persistence cache. Use a dedicated Symfony command to clear the pool you have configured: `php bin/console cache:pool:clear cache.redis`. -##### Redis Clustering +##### Redis clustering Persistence cache depends on all involved web servers, each of them seeing the same view of the cache because it's shared among them. With that in mind, the following configurations of Redis are possible: - [Redis Cluster](https://redis.io/docs/management/scaling/) - - Shards cache across several instances in order to be able to cache more than memory of one server allows + - Shards cache across several instances to be able to cache more than memory of one server allows - Shard slaves can improve availability, however [they use asynchronous replication](https://redis.io/docs/management/scaling/#redis-cluster-consistency-guarantees) so they can't be used for reads - Unsupported Redis features that can affect performance: [pipelining](https://github.com/phpredis/phpredis/blob/develop/cluster.md#pipelining) and [most multiple key commands](https://github.com/phpredis/phpredis/blob/develop/cluster.md#multiple-key-commands) - [Redis Sentinel](https://redis.io/docs/management/sentinel/) - - Provides high availability by providing one or several slaves (ideally 2 slaves or more, e.g. minimum 3 servers), and handle failover + - Provides high availability by providing one or several slaves (ideally 2 slaves or more, for example, minimum 3 servers), and handle failover - [Slaves are asynchronously replicated](https://redis.io/docs/management/sentinel/#fundamental-things-to-know-about-sentinel-before-deploying), so they can't be used for reads - - Typically used with a load balancer (e.g. HAproxy with occasional calls to Redis Sentinel API) in the front in order to only speak to elected master - - As of v3 you can also configure this [directly on the connection string]([[= symfony_doc =]]/components/cache/adapters/redis_adapter.html#configure-the-connection), **if** you use `Predis` instead of `php-redis` + - Typically used with a load balancer (for example, HAproxy with occasional calls to Redis Sentinel API) in the front to only speak to elected master + - As of v3 you can also configure this [directly on the connection string]([[= symfony_doc =]]/components/cache/adapters/redis_adapter.html#configure-the-connection), **if** you use `Predis` instead of `php-redis` Several cloud providers have managed services that are easier to set up, handle replication and scalability for you, and might perform better. Notable services include: @@ -207,9 +203,9 @@ Several cloud providers have managed services that are easier to set up, handle - [Azure Redis Cache](https://azure.microsoft.com/en-us/products/cache/) - [Google Cloud Memorystore](https://cloud.google.com/memorystore/) -###### Ibexa Cloud / Platform.sh usage +###### [[= product_name_cloud =]] / Platform.sh usage -!!! note "Ibexa Cloud" +!!! note "[[= product_name_cloud =]]" If you use Platform.sh Enterprise you can benefit from the Redis Sentinel across three nodes for great fault tolerance. Platform.sh Professional and lower versions offer Redis in single instance mode only. @@ -218,8 +214,7 @@ Several cloud providers have managed services that are easier to set up, handle [Memcached, a distributed caching solution](http://memcached.org/) is a cache solution that is supported for clustering use, as an alternative to Redis. -See [Memcached Cache Adapter in Symfony documentation]([[= symfony_doc =]]/components/cache/adapters/memcached_adapter.html#configure-the-connection) -for information on how to configure Memcached. +See [Memcached Cache Adapter in Symfony documentation]([[= symfony_doc =]]/components/cache/adapters/memcached_adapter.html#configure-the-connection) for information on how to configure Memcached. #### Supported Adapters @@ -230,18 +225,19 @@ There is one Memcached adapter available out of the box. **Pros**: Memcached is able to handle much more concurrent load by design (multi threaded), and typically uses far less memory than Redis in general due to a simpler data structure. -**Cons**: 1.5-2x more lookups to the back-end cache server then `RedisTagAwareAdapter`. Depending on the number of lookups and latency to cache server this might affect page load time. +**Cons**: 1.5-2x more lookups to the back-end cache server then `RedisTagAwareAdapter`. +Depending on the number of lookups and latency to cache server this might affect page load time. #### Adjusting configuration -Out of the box in `config/packages/cache_pool/cache.memcached.yaml` you'll find a default example that can be used. +Out of the box in `config/packages/cache_pool/cache.memcached.yaml` you can find a default example that can be used. -!!! note "Ibexa Cloud" +!!! note "[[= product_name_cloud =]]" - For Ibexa Cloud/Platform.sh: This is automatically configured in `vendor/ibexa/core/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php` if you have enabled Memcached as `cache` Platform.sh service. + For [[= product_name_cloud =]]/Platform.sh: This is automatically configured in `vendor/ibexa/core/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php` if you have enabled Memcached as `cache` Platform.sh service. For anything else, you can enable it with environment variables detected automatically by `vendor/ibexa/core/src/bundle/Core/DependencyInjection/IbexaCoreExtension.php`. -For instance, if you set the following environment variables `export CACHE_POOL="cache.memcached" CACHE_DSN="user:pass@localhost?weight=33"`, it will result in config like this: +For instance, if you set the following environment variables `export CACHE_POOL="cache.memcached" CACHE_DSN="user:pass@localhost?weight=33"`, it results in config like this: ``` yaml services: @@ -259,7 +255,7 @@ See `config/default_parameters.yaml` and `config/cache_pool/cache.memcached.yaml !!! caution "Clearing Memcached cache" - The regular `php bin/console cache:clear` command does not clear Memcached persistence cache. + The regular `php bin/console cache:clear` command doesn't clear Memcached persistence cache. Use a dedicated Symfony command to clear the pool you have configured: `php bin/console cache:pool:clear cache.memcached`. @@ -269,7 +265,7 @@ See `config/default_parameters.yaml` and `config/cache_pool/cache.memcached.yaml !!! note - Memcached must not be bound to the local address if clusters are in use, or user logins will fail. + Memcached must not be bound to the local address if clusters are in use, or user logins fail. To avoid this, in `/etc/memcached.conf` take a look under `# Specify which IP address to listen on. The default is to listen on all IP addresses` For development environments, change the address below this comment in `/etc/memcached.conf` to `-l 0.0.0.0` @@ -278,12 +274,16 @@ See `config/default_parameters.yaml` and `config/cache_pool/cache.memcached.yaml > -l <addr> - > Listen on <addr>; default to INADDR\_ANY. <addr> may be specified as host:port. If you don't specify a port number, the value you specified with -p or -U is used. You may specify multiple addresses separated by comma or by using -l multiple times. This is an important option to consider as there is no other way to secure the installation. Binding to an internal or firewalled network interface is suggested. + > Listen on <addr>; default to INADDR\_ANY. <addr> may be specified as host:port. + If you don't specify a port number, the value you specified with -p or -U is used. + You may specify multiple addresses separated by comma or by using -l multiple times. + This is an important option to consider as there is no other way to secure the installation. + Binding to an internal or firewalled network interface is suggested. ## Using cache service Using the internal cache service allows you to use an interface and without caring whether the system is configured to place the cache in Memcached or on File system. -And as [[= product_name =]] requires that instances use a cluster-aware cache in Cluster setup, you can safely assume your cache is shared *(and invalidated)* across all web servers. +And as [[= product_name =]] requires that instances use a cluster-aware cache in cluster setup, you can safely assume your cache is shared *(and invalidated)* across all web servers. !!! note @@ -292,7 +292,7 @@ And as [[= product_name =]] requires that instances use a cluster-aware cache in !!! caution "Use unique vendor prefix for Cache key" - When reusing the cache service within your own code, it is very important to not conflict with the cache keys used by others. + When reusing the cache service within your own code, it's very important to not conflict with the cache keys used by others. That is why the example of usage below starts with a unique `myApp` key. For the namespace of your own cache, you must do the same. @@ -300,7 +300,7 @@ And as [[= product_name =]] requires that instances use a cluster-aware cache in ##### With dependency injection -In your Symfony services configuration you can simply define that you require the cache service in your configuration like so: +In your Symfony services configuration you can define that you require the cache service in your configuration like so: ``` yaml # yml configuration diff --git a/docs/infrastructure_and_maintenance/clustering/clustering.md b/docs/infrastructure_and_maintenance/clustering/clustering.md index 521080723e..cd5f799d81 100644 --- a/docs/infrastructure_and_maintenance/clustering/clustering.md +++ b/docs/infrastructure_and_maintenance/clustering/clustering.md @@ -13,9 +13,7 @@ The parts illustrate the different roles needed for a successful cluster setup. ![Server setup for clustering](server_setup.png) -The number of web servers, Memcached/Redis, Solr, Varnish, Database and NFS servers, -as well as whether some servers play several of these roles (typically running Memcached/Redis across the web server) -is up to you and your performance needs. +The number of web servers, Memcached/Redis, Solr, Varnish, Database, and NFS servers, but also whether some servers play several of these roles (typically running Memcached/Redis across the web server), is up to you and your performance needs. The minimal requirements are: @@ -24,9 +22,9 @@ The minimal requirements are: - Shared database (using MySQL/MariaDB) - [Shared binary files](#shared-binary-files) (using NFS, or S3) -For further details on requirements, see [Requirements page](requirements.md). +For more information on requirements, see [Requirements page](requirements.md). -It is also recommended to use: +It's also recommended to use: - [Solr](solr_overview.md) or [Elasticsearch](elastic_search_overview.md) for better search and performance - a CDN for improved performance and faster ping time worldwide @@ -36,7 +34,8 @@ It is also recommended to use: ### Shared persistence cache -Redis is the recommended cache solution for clustering. An alternative solution is using Memcached. +Redis is the recommended cache solution for clustering. +An alternative solution is using Memcached. See [persistence cache documentation](persistence_cache.md#persistence-cache-configuration) on information on how to configure them. @@ -62,29 +61,27 @@ They make sure that files are correctly synchronized among the multiple clients ## DFS IO handler The DFS IO handler (`legacy_dfs_cluster`) can be used to store binary files on an NFS server. -It will use a database to manipulate metadata, making up for the potential inconsistency of network-based filesystems. +It uses a database to manipulate metadata, making up for the potential inconsistency of network-based filesystems. ### Configuring the DFS IO handler You need to configure both metadata and binarydata handlers. -[[= product_name =]] ships with a custom local adapter (`ibexa.io.nfs.adapter.site_access_aware`), -which decorates the Flysystem v2 local adapter to enable support for SiteAccess-aware settings. -If an NFS path relies on SiteAccess-aware dynamic parameters, you must use the custom local adapter -instead of the Flysystem v2 local adapter. +[[= product_name =]] ships with a custom local adapter (`ibexa.io.nfs.adapter.site_access_aware`), which decorates the Flysystem v2 local adapter to enable support for SiteAccess-aware settings. +If an NFS path relies on SiteAccess-aware dynamic parameters, you must use the custom local adapter instead of the Flysystem v2 local adapter. Configure the custom local adapter to read/write to the NFS mount point on each local server. As metadata handler, create a DFS one, configured with a Doctrine connection. !!! tip - The default database install will now include the dfs table *in the same database* + The default database install now includes the dfs table *in the same database* First, define DFS folder path as a variable in `.env` file: `DFS_NFS_PATH=/tmp/ibx_1439_nfs` -Next, if you are using a separate DFS database, configure it via the `DATABASE_URL` variable in the `.env` file. -Depending on which database you are using: +Next, if you're using a separate DFS database, configure it via the `DATABASE_URL` variable in the `.env` file. +Depending on which database you're using: `DFS_DATABASE_URL=mysql://root:rootpassword@127.0.0.1:3306/ibexa_dfs?serverVersion=8.0` @@ -92,10 +89,9 @@ or `DATABASE_URL=postgresql://root:rootpassword@127.0.0.1:3306/ibexa_dfs?serverVersion=8.0` -For production, it is recommended to create the DFS table in its own database, -manually importing its schema definition: +For production, it's recommended to create the DFS table in its own database, manually importing its schema definition: -??? note "dfs_schema.sql (MySQL)" +!!! note "dfs_schema.sql (MySQL)" ``` sql CREATE TABLE ezdfsfile ( @@ -116,7 +112,7 @@ manually importing its schema definition: ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` -??? note "dfs_schema.sql (PostgreSQL)" +!!! note "dfs_schema.sql (PostgreSQL)" ``` sql CREATE TABLE ezdfsfile ( @@ -200,13 +196,13 @@ ibexa: !!! tip - If you are looking to [set up S3](clustering_with_aws_s3.md) or other [Flysystem](https://flysystem.thephpleague.com/docs/)/third-party adapters like Google Cloud Storage, this needs to be configured as binary handler. The rest here will still stay the same, the DFS metadata handler will take care of caching the lookups to avoid slow IO lookups. + If you're looking to [set up S3](clustering_with_aws_s3.md) or other [Flysystem](https://flysystem.thephpleague.com/docs/)/third-party adapters like Google Cloud Storage, this needs to be configured as binary handler. + The rest here still stays the same, the DFS metadata handler takes care of caching the lookups to avoid slow IO lookups. #### Customizing the storage directory Earlier versions required the NFS adapter directory to be set to `$var_dir$/$storage_dir$` part for the NFS path. -This is no longer required, -but the default prefix used to serve binary files still matches this expectation. +It's no longer required, but the default prefix used to serve binary files still matches this expectation. If you decide to change this setting, make sure you also set `io.url_prefix` to a matching value. If you set the NFS adapter's directory to `/path/to/nfs/storage`, use this configuration so that the files can be served by Symfony: @@ -219,9 +215,8 @@ ibexa: url_prefix: storage ``` -As an alternative, you may serve images from NFS using a dedicated web server. -If in the example above, this server listens on `http://static.example.com/` -and uses `/path/to/nfs/storage` as the document root, configure `io.url_prefix` as follows: +As an alternative, you may serve images from NFS by using a dedicated web server. +If in the example above, this server listens on `http://static.example.com/` and uses `/path/to/nfs/storage` as the document root, configure `io.url_prefix` as follows: ``` yaml ibexa: @@ -235,10 +230,10 @@ You can read more about that on [Binary files URL handling](file_url_handling.md ### Web server rewrite rules -The default [[= product_name =]] rewrite rules will let image requests be served directly from disk. +The default [[= product_name =]] rewrite rules let image requests be served directly from disk. In a cluster setup, files matching `^/var/([^/]+/)?storage/images(-versioned)?/.*` have to be passed through `/public/index.php` instead. -In any case, this specific rewrite rule must be placed before the ones that "ignore" image files and just let the web server serve the files directly. +In any case, this specific rewrite rule must be placed before the ones that "ignore" image files and let the web server serve the files directly. #### Apache @@ -258,9 +253,9 @@ Place this before the include of `ez_params.d`/`ez_rewrite_params` in your vhost ## Migrating to a cluster setup -If you are migrating an existing single-server site to a cluster setup, and not setting up clustering from scratch, you need to migrate your files. +If you're migrating an existing single-server site to a cluster setup, and not setting up clustering from scratch, you need to migrate your files. Once you have configured your binarydata and metadata handlers, you can run the `ibexa:io:migrate-files` command. -You can also use it when you are migrating from one data handler to another, e.g. from NFS to Amazon S3. +You can also use it when you're migrating from one data handler to another, for example, from NFS to Amazon S3. This command shows which handlers are configured: @@ -277,8 +272,8 @@ You can do the actual migration like this: ``` The `--from` and `--to` values must be specified as `,`. -If `--from` is omitted, the default IO configuration will be used. -If `--to` is omitted, the first non-default IO configuration will be used. +If `--from` is omitted, the default IO configuration is used. +If `--to` is omitted, the first non-default IO configuration is used. !!! tip @@ -287,4 +282,4 @@ If `--to` is omitted, the first non-default IO configuration will be used. While the command is running, the files should not be modified. To avoid surprises you should create a [backup](backup.md) and/or execute a dry run before doing the actual update, using the `--dry-run` switch. -Since this command can run for a very long time, to avoid memory exhaustion run it in the production environment using the `--env=prod` switch. +Since this command can run for a long time, to avoid memory exhaustion, use the `--env=prod` switch when you run it in the production environment. diff --git a/docs/infrastructure_and_maintenance/clustering/clustering_with_aws_s3.md b/docs/infrastructure_and_maintenance/clustering/clustering_with_aws_s3.md index d173f14c3c..ba78c00cf7 100644 --- a/docs/infrastructure_and_maintenance/clustering/clustering_with_aws_s3.md +++ b/docs/infrastructure_and_maintenance/clustering/clustering_with_aws_s3.md @@ -1,11 +1,10 @@ --- -description: When you are using a clustering configuration, you can store binary files on Amazon AWS S3. +description: When you're using a clustering configuration, you can store binary files on Amazon AWS S3. --- # Clustering with Amazon AWS S3 -When setting up clustering, you can use Amazon AWS S3 as a binary handler, -meaning AWS S3 will be used to store binary files. +When setting up clustering, you can use Amazon AWS S3 as a binary handler, meaning AWS S3 is used to store binary files. !!! tip @@ -23,7 +22,7 @@ The example below uses EU (Ireland): `eu-west-1` See . 1. Then create a group and assign the user to the group. 1. Assign policies to the group. The `AmazonS3FullAccess` policy gives read/write access to your bucket. -1. Still in the IAM console, view the user you created. Click the "Security credentials" tab. +1. Still in the IAM console, view the user you created. Click the **Security credentials** tab. 1. Click "Create access key" and make note of the "Access key ID" and the "Secret access key". The secret key cannot be retrieved again after the key has been created, so don't lose it. (However, you can create new keys if needed.) @@ -31,7 +30,7 @@ The secret key cannot be retrieved again after the key has been created, so don' !!! note Make sure that your bucket is [configured as Public](https://docs.aws.amazon.com/AmazonS3/latest/userguide/configuring-block-public-access-bucket.html) to avoid facing 403 errors, as the current S3 handler is meant to store files publicly so they can be served directly from S3. - + ## Set up [[= product_name =]] for AWS S3 In your [[= product_name =]] root directory, run `php composer require league/flysystem-aws-s3-v3:^2.0`. @@ -76,8 +75,7 @@ ibexa_io: `aws_s3` is an arbitrary handler identifier that is used in the config block below. You can configure multiple handlers. - For example, you could configure one called `gcloud_storage` for a - [Google Cloud Storage adapter](https://github.com/thephpleague/flysystem#officially-supported-adapters). + For example, you could configure one called `gcloud_storage` for a [Google Cloud Storage adapter](https://github.com/thephpleague/flysystem#officially-supported-adapters). Under the `ibexa.system..io` [configuration key](configuration.md#configuration-files), enable the binary data handler: @@ -95,5 +93,4 @@ Clear all caches and reload, and that's it. ## Migrate your existing binary data to S3 -You can [migrate existing binary data](clustering.md#migrating-to-a-cluster-setup) to S3 using the `php bin/console ibexa:io:migrate-files` command -which was added in [EZP-25946](https://issues.ibexa.co/browse/EZP-25946). +You can [migrate existing binary data](clustering.md#migrating-to-a-cluster-setup) to S3 with the `php bin/console ibexa:io:migrate-files` command that was added in [EZP-25946](https://issues.ibexa.co/browse/EZP-25946). \ No newline at end of file diff --git a/docs/infrastructure_and_maintenance/clustering/clustering_with_ddev.md b/docs/infrastructure_and_maintenance/clustering/clustering_with_ddev.md index 6d5e2c8f0d..0f7ca0bf45 100644 --- a/docs/infrastructure_and_maintenance/clustering/clustering_with_ddev.md +++ b/docs/infrastructure_and_maintenance/clustering/clustering_with_ddev.md @@ -6,7 +6,7 @@ description: Use DDEV to run a cluster infrastructure locally. !!! caution - Do not use this procedure in production. + Don't use this procedure in production. A staging environment for validation before production should exactly replicate the production environment. This is meant for development environment only. @@ -18,7 +18,7 @@ But the data sharing needed by a cluster of several servers can still be emulate The `ddev config --php-version` option should set the same PHP version as the production servers. !!! tip - + - [`ddev describe`](https://ddev.readthedocs.io/en/latest/users/usage/commands/#describe) displays a cluster summary that include accesses from inside and outside DDEV services - [`ddev ssh`](https://ddev.readthedocs.io/en/latest/users/usage/commands/#ssh) opens a terminal inside a service - [`ddev exec`](https://ddev.readthedocs.io/en/latest/users/usage/commands/#exec) executes a command inside a service @@ -54,7 +54,7 @@ You can now check whether Elasticsearch works. For example, the `ddev exec curl -s "http://elasticsearch:9200/_count"` command checks whether the `web` server can access the `elasticsearch` server and displays the number of indexed documents. -See [ddev/ddev-elasticsearch README](https://github.com/ddev/ddev-elasticsearch) for more information on topics such as memory management. +For more information on topics such as memory management, see [ddev/ddev-elasticsearch README](https://github.com/ddev/ddev-elasticsearch). See [Elasticsearch REST API reference](https://www.elastic.co/guide/en/elasticsearch/reference/current/rest-apis.html) for more request options, like, for example: @@ -79,7 +79,7 @@ You can now check whether Solr works. For example, the `ddev exec curl -s http://solr:8983/api/cores/` command: - - checks whether the `web` server can access the `solr` server, + - checks whether the `web` server can access the `solr` server - checks whether `collection1` exists and its status - displays `collection1`'s `numDocs` that shouldn't be zero if indexing worked correctly @@ -117,7 +117,7 @@ ddev php bin/console cache:clear You can now check whether Redis works. -For example, the `ddev redis-cli MONITOR` command returns outputs such as `"SETEX" "ezp:`, `"MGET" "ezp:`, `"SETEX" "PHPREDIS_SESSION:`, `"GET" "PHPREDIS_SESSION:`, etc. while navigating into the website, in particular the Back Office. +For example, the `ddev redis-cli MONITOR` command returns outputs, for example, `"SETEX" "ezp:`, `"MGET" "ezp:`, `"SETEX" "PHPREDIS_SESSION:`, or `"GET" "PHPREDIS_SESSION:`, while navigating into the website, in particular the back office. See [Redis commands](https://redis.io/commands/) for more details such as information about the [`MONITOR`](https://redis.io/commands/monitor/) command used in the previous example. diff --git a/docs/infrastructure_and_maintenance/databases.md b/docs/infrastructure_and_maintenance/databases.md index f5dd568264..0ad31fe788 100644 --- a/docs/infrastructure_and_maintenance/databases.md +++ b/docs/infrastructure_and_maintenance/databases.md @@ -14,11 +14,11 @@ To use PostgreSQL, you need to have the `pdo_pgsql` PHP extension installed. ### Provide parameters -When you run `composer install`, you will be asked to [provide installation parameters](install_ibexa_dxp.md#change-installation-parameters). +When you run `composer install`, you're asked to [provide installation parameters](install_ibexa_dxp.md#change-installation-parameters). !!! tip - It is recommended to store the database credentials in your `.env.local` file and not commit it to the Version Control System. + It's recommended to store the database credentials in your `.env.local` file and not commit it to the Version Control System. If you use PostgreSQL, the following parameters need to be set differently in the `.env.local` file than when using MySQL: diff --git a/docs/infrastructure_and_maintenance/devops.md b/docs/infrastructure_and_maintenance/devops.md index 8f7027cf77..ef851697dc 100644 --- a/docs/infrastructure_and_maintenance/devops.md +++ b/docs/infrastructure_and_maintenance/devops.md @@ -8,7 +8,11 @@ description: See various tools that can help you debug your Ibexa DXP installati ### Clearing file cache using the Symfony cache:clear command -Symfony provides a command for clearing cache. It will delete all file-based caches, which mainly consist of a Twig template, a [service container](php_api.md#service-container), and the Symfony route cache, but also everything else stored in the cache folder. Out of the box on a single-server setup this includes Content cache. For further information on the command's use, see its help text: +Symfony provides a command for clearing cache. +It deletes all file-based caches, which mainly consist of a Twig template, a [service container](php_api.md#service-container), and the Symfony route cache, but also everything else stored in the cache folder. +Out of the box on a single-server setup this includes Content cache.  + +For further information on the command's use, see its help text: ``` bash php bin/console --env=prod cache:clear -h @@ -16,7 +20,8 @@ php bin/console --env=prod cache:clear -h !!! note - If you do not specify an environment, by default `cache:clear` will clear the cache for the `dev` environment. If you want to clear it for `prod` you need to use the `--env=prod` option. + If you don't specify an environment, by default `cache:clear` clears the cache for the `dev` environment. + If you want to clear it for `prod` you need to use the `--env=prod` option. !!! caution "Clustering" @@ -24,7 +29,8 @@ php bin/console --env=prod cache:clear -h ### Clearing content cache on a cluster setup -For a [cluster](clustering.md) setup, the content cache ([HTTP cache](http_cache.md) and [Persistence cache](persistence_cache.md)) must be set up to be shared among the servers. And while all relevant cache is cleared for you on Repository changes when using the APIs, there might be times where you'll need to clear cache manually:  +For a [cluster](clustering.md) setup, the content cache ([HTTP cache](http_cache.md) and [Persistence cache](persistence_cache.md)) must be set up to be shared among the servers. +While all relevant cache is cleared for you on repository changes when using the APIs, there might be times where you need to clear cache manually:  - Varnish: [Cache purge](reverse_proxy.md#using-varnish-or-fastly) - Persistence Cache: [Using Cache service](persistence_cache.md#using-cache-service) @@ -38,17 +44,20 @@ To install it, run the following command: composer require symfony/debug-pack ``` -After you have installed Symfony Web Debug Toolbar, it will be available when running [[= product_name =]] in the `dev` environment. It is extended with some [[= product_name =]]-specific information: +After you have installed Symfony Web Debug Toolbar, it's available when running [[= product_name =]] in the `dev` environment. +It's extended with some [[= product_name =]]-specific information: ![Ibexa DXP info in Web Debug Toolbar](web_debug_toolbar.png "Ibexa DXP info in Web Debug Toolbar") #### SPI (persistence) -This section provides the number of non-cached SPI calls and handlers. You can see details of these calls in the [Symfony Profiler]([[= symfony_doc =]]/profiler.html) page. +This section provides the number of non-cached SPI calls and handlers. +You can see details of these calls in the [Symfony Profiler]([[= symfony_doc =]]/profiler.html) page. #### SiteAccess -Here you can see the name of the current SiteAccess and how it was matched. For reference see the [list of possible SiteAccess matchers](siteaccess_matching.md#available-siteaccess-matchers). +Here you can see the name of the current SiteAccess and how it was matched. +For reference see the [list of possible SiteAccess matchers](siteaccess_matching.md#available-siteaccess-matchers). ## Logging and debug configuration @@ -58,8 +67,8 @@ The other is the standard [PSR-3](https://github.com/php-fig/fig-standards/blob ### Debugging in dev environment -When using the Symfony `dev` [environment](environments.md), the system tracks additional metrics for you to be able to debug issues. They -include Symfony cache use, and a [persistence cache](persistence_cache.md#persistence-cache-configuration) use. +When using the Symfony `dev` [environment](environments.md), the system tracks additional metrics for you to be able to debug issues. +They include Symfony cache use, and a [persistence cache](persistence_cache.md#persistence-cache-configuration) use. #### Reducing memory use @@ -67,7 +76,7 @@ include Symfony cache use, and a [persistence cache](persistence_cache.md#persis For long-running scripts, see [Long-running console commands](performance.md#long-running-console-commands). -If you are running out of memory and don't need to keep track of cache hits and misses, you can disable persistence cache logging, represented by the setting `parameters.ibexa.spi.persistence.cache.persistenceLogger.enableCallLogging`. In `config_dev.yaml`: +If you're running out of memory and don't need to keep track of cache hits and misses, you can disable persistence cache logging, represented by the setting `parameters.ibexa.spi.persistence.cache.persistenceLogger.enableCallLogging`. In `config_dev.yaml`: ``` yaml parameters: @@ -78,7 +87,7 @@ parameters: [[= product_name =]] uses the [Monolog](https://github.com/Seldaek/monolog) component to log errors, and it has a `RotatingFileHandler` that allows for file rotation. -According to [their documentation](https://seldaek.github.io/monolog/doc/02-handlers-formatters-processors.html#log-to-files-and-syslog), it "logs records to a file and creates one logfile per day. It will also delete files older than `$maxFiles`". +According to [their documentation](https://seldaek.github.io/monolog/doc/02-handlers-formatters-processors.html#log-to-files-and-syslog), it "logs records to a file and creates one logfile per day. It also deletes files older than `$maxFiles`". Monolog's handler can be configured in `config/packages//monolog.yaml`: diff --git a/docs/infrastructure_and_maintenance/environments.md b/docs/infrastructure_and_maintenance/environments.md index 16ef74f22e..0d88ec1fe0 100644 --- a/docs/infrastructure_and_maintenance/environments.md +++ b/docs/infrastructure_and_maintenance/environments.md @@ -1,19 +1,22 @@ --- -description: In Ibexa DXP you can use environment provided by Symfony in virtual host configuration, as well as to create custom environments. +description: In Ibexa DXP you can use environment provided by Symfony in virtual host configuration, and to create custom environments. --- # Environments -Environment configuration is provided by Symfony. [[= product_name =]] additionally enables you to specify environments in virtual host configuration. -You can configure several environments, such as production, development or staging. You can have different configuration sets for each of them. +Environment configuration is provided by Symfony. +[[= product_name =]] additionally enables you to specify environments in virtual host configuration. +You can configure several environments, such as production, development, or staging. +You can have different configuration sets for each of them. !!! tip See also [Environments in Symfony doc]([[= symfony_doc =]]/configuration.html#configuration-environments). - + ## Web server configuration -For example, using Apache, in the [`VirtualHost` example](https://raw.githubusercontent.com/ibexa/post-install/main/resources/templates/apache2/vhost.template) in your installation, the required `VirtualHost` configurations have been already included. You can switch to the desired environment by setting the `ENVIRONMENT` variable to `prod`, `dev` or another custom value, like in the following example: +For example, when you use Apache, in the [`VirtualHost` example](https://raw.githubusercontent.com/ibexa/post-install/main/resources/templates/apache2/vhost.template) in your installation, the required `VirtualHost` configurations have been already included. +You can switch to the desired environment by setting the `ENVIRONMENT` variable to `prod`, `dev` or another custom value, like in the following example: ``` # Environment. diff --git a/docs/infrastructure_and_maintenance/logging.md b/docs/infrastructure_and_maintenance/logging.md index 78623f065d..d028c27a5c 100644 --- a/docs/infrastructure_and_maintenance/logging.md +++ b/docs/infrastructure_and_maintenance/logging.md @@ -8,7 +8,7 @@ description: Ensure that your logs are secure and GDPR compliant by clearing the Some logs can contain personal information such as User ID or password. -By default, [[= product_name =]] does not log User IDs. +By default, [[= product_name =]] doesn't log User IDs. You can change this behavior by modifying the following setting: ``` yaml diff --git a/docs/infrastructure_and_maintenance/performance.md b/docs/infrastructure_and_maintenance/performance.md index 185a9289c2..a9f29c21cd 100644 --- a/docs/infrastructure_and_maintenance/performance.md +++ b/docs/infrastructure_and_maintenance/performance.md @@ -5,23 +5,23 @@ description: Ensure that your Ibexa DXP installation performs well by following # Performance [[= product_name =]] can be set up to run efficiently on almost any modern configuration. -What follows is a list of recommendation that will make your installation perform better. +What follows is a list of recommendation that make your installation perform better. !!! note All the following recommendations are valid for both development and production setups, unless otherwise noted. -If you are in a hurry, the most important recommendations on this page are: +If you're in a hurry, the most important recommendations on this page are: - Dump optimized Composer autoload classmap - Use a full web (Nginx/Apache) server with vhost -- Avoid shared filesystems for code (Docker for Mac/Win, VirtualBox/*, Vagrant, etc.), or find ways to optimize or work around the issues. +- Avoid shared filesystems for code (Docker for Mac/Win, VirtualBox/*, Vagrant, and more), or find ways to optimize or work around the issues. - For clustering (mainly relevant for production/staging), reduce latency to Redis/Memcached, use Varnish and [Solr](solr_overview.md). ## Client - Always use an up-to-date browser and an up-to-date operating system so you have access to latest browser versions -- If possible, use a fast, stable internet connection, because an unreliable connection will slow down UI +- If possible, use a fast, stable internet connection, because an unreliable connection slows down UI ## Server @@ -39,12 +39,12 @@ In production setups: ### VM -- Avoid shared filesystems for code (Docker for Mac/Win, VirtualBox/*, Vagrant, etc.), because they typically slow down the application 10x or more, compared to native Linux filesystem. -- VM in itself also adds 10-30% of overhead. However when it comes to production, e.g. AWS vs barebones, it also comes down to cost and convenience factors. +- Avoid shared filesystems for code (for example, Docker for Mac/Win, VirtualBox/*, or Vagrant), because they typically slow down the application 10x or more, compared to native Linux filesystem. +- VM in itself also adds 10-30% of overhead. However when it comes to production, for example, AWS vs barebones, it also comes down to cost and convenience factors. ### Web server -- Use Nginx/Apache even for development, as PHP's built-in web server (as exposed via Symfony's `server:*` commands) is only able to handle one request at a time (including JS/CSS/* asset loading, etc.). +- Use Nginx/Apache even for development, as PHP's built-in web server (as exposed via Symfony's `server:*` commands) is only able to handle one request at a time (including JS/CSS/* asset loading, and more). - Use a recent version of nginx, set up https, and enable http/2 to reduce connection latency on parallel requests. ### PHP @@ -69,16 +69,17 @@ In production setups: [Symfony v3.4.15](https://github.com/symfony/symfony/pull/28249) may have resolved this. - Memcached/Redis can in some cases perform better than filesystem cache even with a single server, as it offers better general performance for operations invalidating cache. - - However, pure read performance is slower, especially if the next points are not optimized. + - However, pure read performance is slower, especially if the next points aren't optimized. - With cache being on different node(s) than web server, make sure to try to tune latency between the two. !!! tip Check if your cloud provider has native service for Memcached/Redis, as those might be better tuned. -- If you use Redis, make sure to tune it for in-memory cache usage. Its persistence feature is not needed with cache and will severely slow down execution time. +- If you use Redis, make sure to tune it for in-memory cache usage. Its persistence feature isn't needed with cache and severely slows down execution time. - [For use with sessions](sessions.md#cluster-setup) however, persistence can be a good fit if you want sessions to survive service interruptions. - - Further tips for Redis with cache can be found in doc regarding [Redis Clustering](persistence_cache.md#redis-clustering). + +For more information, see [Redis clustering](persistence_cache.md#redis-clustering). ### Search @@ -110,14 +111,14 @@ To avoid quickly running out of memory while executing such commands you should buffer_size: 200 ``` -1. Run PHP without memory limits using: `php -d memory_limit=-1 bin/console ` -1. Disable `xdebug` *(PHP extension to debug/profile php use)* when running the command, this will cause php to use much more memory. +1. Run PHP without memory limits: `php -d memory_limit=-1 bin/console ` +1. Disable `xdebug` *(PHP extension to debug/profile php use)* when running the command, this causes php to use much more memory. -!!! note "Memory will still grow" +!!! note "Memory still grows" - Even when everything is configured like described above, memory will grow for each iteration - of indexing/inserting a content item with at least *1kb* per iteration after the initial first 100 rounds. - This is expected behavior; to be able to handle more iterations you will have to do one or several of the following: + Even when everything is configured like described above, memory grows for each iteration of indexing/inserting a content item with at least *1kb* per iteration after the initial first 100 rounds. + This is expected behavior. + To be able to handle more iterations you have to do one or several of the following: - Change the import/index script in question to [use process forking](#process-forking-with-symfony) to avoid the issue. - Upgrade PHP: *newer versions of PHP are typically more memory-efficient.* @@ -126,14 +127,13 @@ To avoid quickly running out of memory while executing such commands you should ### Process forking with Symfony The recommended way to completely avoid "memory leaks" in PHP in the first place is to use processes. -For console scripts this is typically done using process forking which is quite easily achievable with Symfony. +For console scripts this is typically done using process forking which is achievable with Symfony. -The things you will need to do: +The things you need to do: 1. Change your command so it supports taking slice parameters, like for instance a batch size and a child-offset parameter. - 1. *If defined, child-offset parameter denotes if a process is a child, - this can be accomplished using two commands as well.* - 2. *If not defined, it is the master process which will execute the processes until nothing is left to process.* + 1. *If defined, child-offset parameter denotes if a process is a child, this can be accomplished using two commands as well.* + 2. *If not defined, it's the master process which executes the processes until nothing is left to process.* 2. Change the command so that the master process takes care of forking child processes in slices. 1. For execution in-order, [you may look to our platform installer code](https://github.com/ibexa/core/blob/main/src/bundle/RepositoryInstaller/Command/InstallPlatformCommand.php#L220) diff --git a/docs/infrastructure_and_maintenance/request_lifecycle.md b/docs/infrastructure_and_maintenance/request_lifecycle.md index 0cd5ee7eb6..19f2d7d15e 100644 --- a/docs/infrastructure_and_maintenance/request_lifecycle.md +++ b/docs/infrastructure_and_maintenance/request_lifecycle.md @@ -11,7 +11,8 @@ When entering the server infrastructure, the HTTP request can be handled by seve For an overview of what happens on a reverse proxy like Varnish or Fastly, see [Context-aware HTTP cache / Request lifecycle](context_aware_cache.md#request-lifecycle). -When arriving at a web server, the request is filtered by Apache Virtual Host, Nginx Server Blocks or equivalent. There, requests of static resources are separated from requests to PHP interpreter. +When arriving at a web server, the request is filtered by Apache virtual host, Nginx Server Blocks, or equivalent. +There, requests of static resources are separated from requests to PHP interpreter. As [[= product_name =]] is a Symfony application, the handling of requests starts like in Symfony (see [Symfony and HTTP Fundamentals](https://symfony.com/doc/current/introduction/http_fundamentals.html)). @@ -19,7 +20,8 @@ If the HTTP request is to be treated by [[= product_name =]], it goes to the `pu The front controller transforms the HTTP request into a PHP [`Request` object](https://symfony.com/doc/current/introduction/http_fundamentals.html#symfony-request-object) and passes it to Symfony's Kernel to get a [`Response` object](https://symfony.com/doc/current/introduction/http_fundamentals.html#symfony-response-object) that is transformed and sent back as an HTTP response. -The schemas start with a regular `Request` object from a browser that enters Symfony and [[= product_name =]]. There is no ESI, no REST, and no GraphQL request performed. +The schemas start with a regular `Request` object from a browser that enters Symfony and [[= product_name =]]. +There is no ESI, no REST, and no GraphQL request performed. ## Lifecycle flowcharts @@ -41,19 +43,19 @@ This schema is described below event by event. !!! tip To list all listeners that listen to an event, run `php bin/console debug:event-dispatcher `, for example: - + ```bash php bin/console debug:event-dispatcher kernel.request ``` - + To view details of a service (including class, arguments and tags), run `php bin/console debug:container --show-arguments `, for example: - + ```bash php bin/console debug:container --show-arguments ibexa.siteaccess_match_listener` ``` - + To list all services with a specific tag, run `php bin/console debug:container --tag=`, for example: - + ```bash php bin/console debug:container --tag=router ``` @@ -79,13 +81,11 @@ The `ibexa.siteaccess_match_listener` service: - then dispatches the `Ibexa\Core\MVC\Symfony\SiteAccess` event (`MVCEvents::SITEACCESS`). The `SiteAccessListener` (`Ibexa\Bundle\Core\EventListener\SiteAccessListener`) subscribes to this `Ibexa\Core\MVC\Symfony\SiteAccess` event with top priority (priority 255). -The `SiteAccessListener` adds the **`semanticPathinfo`** attribute, the path without SiteAccess indications ([`URIElement`](siteaccess_matching.md#urielement), [`URIText`](siteaccess_matching.md#uritext), -or [`Map\URI`](siteaccess_matching.md#mapuri) implementing the `URILexer` interface) to the request. +The `SiteAccessListener` adds the **`semanticPathinfo`** attribute, the path without SiteAccess indications ([`URIElement`](siteaccess_matching.md#urielement), [`URIText`](siteaccess_matching.md#uritext), or [`Map\URI`](siteaccess_matching.md#mapuri) implementing the `URILexer` interface) to the request. ### Routing -Finally, the `Symfony\Component\HttpKernel\EventListener\RouterListener` (`router_listener`) (priority 32), which also listens to the `kernel.request` event, -calls `Ibexa\Core\MVC\Symfony\Routing\ChainRouter::matchRequest` and adds its returned parameters to the request. +Finally, the `Symfony\Component\HttpKernel\EventListener\RouterListener` (`router_listener`) (priority 32), which also listens to the `kernel.request` event, calls `Ibexa\Core\MVC\Symfony\Routing\ChainRouter::matchRequest` and adds its returned parameters to the request. #### `ChainRouter` @@ -109,8 +109,8 @@ If a wildcard matches, the request's `semanticPathinfo` is updated and the route ### `UrlAliasRouter` `UrlAliasRouter` (`Ibexa\Bundle\Core\Routing\UrlAliasRouter`): -This router uses the `UrlAliasService` to associate the `semanticPathinfo` to a Location. -If it finds a Location, the request receives the attributes **`locationId`** and **`contentId`**, **`viewType`** is set to `full`, and the **`_controller`** is set to `ibexa_content:viewAction` for now. +This router uses the `UrlAliasService` to associate the `semanticPathinfo` to a location. +If it finds a location, the request receives the attributes **`locationId`** and **`contentId`**, **`viewType`** is set to `full`, and the **`_controller`** is set to `ibexa_content:viewAction` for now. The `locale_listener` (priority 16) sets the request's **`_locale`** attribute. @@ -118,7 +118,7 @@ The `locale_listener` (priority 16) sets the request's **`_locale`** attribute. Another `kernel.request` event listener is the `Ibexa\AdminUi\EventListener\RequestListener` (priority 13). When a route gets a `siteaccess_group_whitelist` parameter, this listener checks that the current SiteAccess is in one of the listed groups. - For example, the Back Office sets an early protection of its routes by passing them a `siteaccess_group_whitelist` containing only the `admin_group`. + For example, the back office sets an early protection of its routes by passing them a `siteaccess_group_whitelist` containing only the `admin_group`. Now, when the `Request` knows its controller, the `HttpKernel` dispatches the `kernel.controller` event. @@ -153,7 +153,8 @@ The `HttpKernel` then dispatches a `kernel.controller_arguments` (`KernelEvents: ## Controller execution -The `HttpKernel` extracts from the request the controller and the arguments to pass to the controller. [Argument resolvers](https://symfony.com/doc/5.4/controller/argument_value_resolver.html) work in a way similar to autowiring. +The `HttpKernel` extracts from the request the controller and the arguments to pass to the controller. +[Argument resolvers](https://symfony.com/doc/5.4/controller/argument_value_resolver.html) work in a way similar to autowiring. The `HttpKernel` executes the controller with those arguments. As a reminder, the controller and its argument can be: @@ -233,4 +234,6 @@ The `HttpKernel` retrieves the response attached to the event and continues. ## End of HTTP response -The web server outputs the HTTP response. Depending on the architecture, few things may still occur. For example, Varnish or Fastly can take specific headers into account when setting the cache or serving it. +The web server outputs the HTTP response. +Depending on the architecture, few things may still occur. +For example, Varnish or Fastly can take specific headers into account when setting the cache or serving it. diff --git a/docs/infrastructure_and_maintenance/security/development_security.md b/docs/infrastructure_and_maintenance/security/development_security.md index 27e04a7243..298aa5e465 100644 --- a/docs/infrastructure_and_maintenance/security/development_security.md +++ b/docs/infrastructure_and_maintenance/security/development_security.md @@ -10,8 +10,7 @@ description: Ensure the security of your Ibexa DXP installation by using one of !!! note "Security checklist" - See the [Security checklist](security_checklist.md) for a list of security-related issues - you should take care of before going live with a project. + See the [Security checklist](security_checklist.md) for a list of security-related issues you should take care of before going live with a project. ## Symfony authentication @@ -50,13 +49,15 @@ logout: ### Authentication using Symfony Security component -Authentication is provided using the Symfony Security component. +Authentication is provided by the Symfony Security component. -[Native and universal `form_login`]([[= symfony_doc =]]/security/form_login_setup.html) is used, in conjunction with an extended `DaoAuthenticationProvider` (DAO stands for *Data Access Object*), the `RepositoryAuthenticationProvider`. Native behavior of `DaoAuthenticationProvider` has been preserved, making it possible to still use it for pure Symfony applications. +[Native and universal `form_login`]([[= symfony_doc =]]/security/form_login_setup.html) is used, in conjunction with an extended `DaoAuthenticationProvider` (DAO stands for *Data Access Object*), the `RepositoryAuthenticationProvider`. +Native behavior of `DaoAuthenticationProvider` has been preserved, making it possible to still use it for pure Symfony applications. #### Security controller -A `SecurityController` is used to manage all security-related actions and is thus used to display the login form. It follows all standards explained in [Symfony security documentation]([[= symfony_doc =]]/security/form_login_setup.html). +A `SecurityController` is used to manage all security-related actions and is thus used to display the login form. +It follows all standards explained in [Symfony security documentation]([[= symfony_doc =]]/security/form_login_setup.html). The base template used is [`Security/login.html.twig`](https://github.com/ibexa/core/blob/main/src/bundle/Core/Resources/views/Security/login.html.twig). @@ -77,10 +78,10 @@ By default, Symfony redirects to the [URI configured in `security.yaml` as `defa #### Remember me -It is possible to use the "Remember me" functionality. +It's possible to use the "Remember me" functionality. Refer to the [Symfony cookbook on this topic]([[= symfony_doc =]]/security/remember_me.html). -If you want to use this feature, you must at least extend the login template in order to add the required checkbox: +If you want to use this feature, you must at least extend the login template to add the required checkbox: ``` html+twig {% extends "@IbexaCore/Security/login.html.twig" %} @@ -94,14 +95,14 @@ If you want to use this feature, you must at least extend the login template in #### Login handlers / SSO -Symfony provides native support for [multiple user providers]([[= symfony_doc =]]/security/multiple_user_providers.html). This makes it easy to integrate any kind of login handlers, including SSO and existing third-party bundles (e.g. [FR3DLdapBundle](https://github.com/Maks3w/FR3DLdapBundle), [HWIOauthBundle](https://github.com/hwi/HWIOAuthBundle), [FOSUserBundle](https://github.com/FriendsOfSymfony/FOSUserBundle), [BeSimpleSsoAuthBundle](https://github.com/BeSimple/BeSimpleSsoAuthBundle), etc.). +Symfony provides native support for [multiple user providers]([[= symfony_doc =]]/security/multiple_user_providers.html). +This makes it easy to integrate any kind of login handlers, including SSO and existing third-party bundles (for example, [FR3DLdapBundle](https://github.com/Maks3w/FR3DLdapBundle), [HWIOauthBundle](https://github.com/hwi/HWIOAuthBundle), [FOSUserBundle](https://github.com/FriendsOfSymfony/FOSUserBundle), [BeSimpleSsoAuthBundle](https://github.com/BeSimple/BeSimpleSsoAuthBundle), and more). See [Authenticating a user with multiple user provider](user_authentication.md#authenticate-user-with-multiple-user-providers) for more information. ## JWT authentication -To use [JWT authentication](https://jwt.io/) with [[= product_name =]], in the provided `config/packages/lexik_jwt_authentication.yaml` file, -modify the existing configuration by setting `authorization_header` to `enabled`: +To use [JWT authentication](https://jwt.io/) with [[= product_name =]], in the provided `config/packages/lexik_jwt_authentication.yaml` file, modify the existing configuration by setting `authorization_header` to `enabled`: ``` yaml hl_lines="8" lexik_jwt_authentication: @@ -119,7 +120,7 @@ lexik_jwt_authentication: ``` You also need a new Symfony firewall configuration for REST and/or GraphQL APIs. -It is already provided in `config/packages/security.yaml`, you only need to uncomment it: +It's already provided in `config/packages/security.yaml`, you only need to uncomment it: ``` yaml security: diff --git a/docs/infrastructure_and_maintenance/security/reporting_issues.md b/docs/infrastructure_and_maintenance/security/reporting_issues.md index 3c7190217d..b41279981e 100644 --- a/docs/infrastructure_and_maintenance/security/reporting_issues.md +++ b/docs/infrastructure_and_maintenance/security/reporting_issues.md @@ -1,19 +1,20 @@ --- -description: How to report security issues in Ibexa DXP? +description: Learn how to report security issues in Ibexa DXP. --- # Reporting security issues in Ibexa products -The security of our software is a primary concern and we take it seriously. -For more information on security in our products, see [Ibexa Security Policy](https://www.ibexa.co/software-information/security). +The security of [[= product_name_base =]] software is a primary concern and is taken seriously. + +For more information on security in [[= product_name_base =]] products, see [Ibexa Security Policy](https://www.ibexa.co/software-information/security). No engineering team is perfect though, and if you do discover a security issue in one of our products we are very grateful for your help in reporting it to us privately, and refraining from public disclosure until we have found the solution and distributed it. Thank you! ## Channels -- If you're a customer or partner, please log in to your Service Portal at , click "New Ticket", and report the issue as you would report a normal support request. Ibexa Product Support will respond, take care of the report, and keep you informed of the developments. -- If you're not a customer or partner, please log in to the Ibexa JIRA issue tracker: . Create an account if you don't have one, it's free. Click the "Create" button in the top menu to create your report. For "Project", select "Ibexa IBX", or "eZ Publish / Platform", or "eZ Platform Enterprise Edition", depending on which product is affected by the bug. **Important: Select "Security Level": "Security"!** The engineering team will take care of your report. -- It is also possible to report security issues by email to - this requires no account. +- If you're a customer or partner, please log in to your Service Portal at , click "New Ticket", and report the issue as you would report a normal support request. [[= product_name_base =]] Product Support will respond, take care of the report, and keep you informed of the developments. +- If you're not a customer or partner, please log in to the [[= product_name_base =]] JIRA issue tracker: . Create an account if you don't have one, it's free. Click the "Create" button in the top menu to create your report. For "Project", select "[[= product_name_base =]] IBX", or "eZ Publish / Platform", or "eZ Platform Enterprise Edition", depending on which product is affected by the bug. **Important: Select "Security Level": "Security"!** The engineering team will take care of your report. +- It's also possible to report security issues by email to - this requires no account. ## Verbosity @@ -21,11 +22,12 @@ Please be verbose when reporting issues. The issue will be solved faster if you - A **title** describing the gist of the issue in one sentence - A **description** which includes the steps you take to produce the problem, what you expect the result to be, and what actually happens. -- Make it clear **why you consider it a security issue**. If you know, also include what type of security issue it is (example: SQL injection, CSRF, Role/Policy failure), what the nature of it is (example: slowing/stopping a web site, leaking sensitive information, destroying data, privilege escalation) and how easy it is to exploit (example: Does it require editor login?). +- Make it clear **why you consider it a security issue**. If you know, also include its type of security issue (example: SQL injection, CSRF, Role/Policy failure), its nature (example: slowing/stopping a web site, leaking sensitive information, destroying data, privilege escalation), and how easy it is to exploit (example: Does it require editor login?). ## Dialogue -The engineering team may need your help to clarify certain specifics, so please respond to such inquiries. We will keep you updated about the progress on our end. +The engineering team may need your help to clarify certain specifics, so please respond to such inquiries. +We keep you updated about the progress on our end. ## Responsible disclosure @@ -33,4 +35,5 @@ Please give the engineering team time to produce and distribute a solution befor ## Attribution -We will, if you want, include your name and/or the name of your organisation, a link, and short description about you in the security notification we send out with the fix. Thank you! +If you want, we can include your name and/or the name of your organisation, a link, and short description about you in the security notification we send out with the fix. +Thank you! diff --git a/docs/infrastructure_and_maintenance/security/security_checklist.md b/docs/infrastructure_and_maintenance/security/security_checklist.md index a6fd5deba8..558c5316b9 100644 --- a/docs/infrastructure_and_maintenance/security/security_checklist.md +++ b/docs/infrastructure_and_maintenance/security/security_checklist.md @@ -4,47 +4,39 @@ description: Ensure that your Ibexa DXP installation is secure by following our # Security checklist -When getting ready to go live with your project for the first time, or when re-launching it, -make sure that your setup is secure. +When getting ready to go live with your project for the first time, or when re-launching it, make sure that your setup is secure. !!! caution - Security is an ongoing process. After going live, you should pay attention to security advisories - released via [your service portal](https://support.ibexa.co/), - or via [Security advisories](https://developers.ibexa.co/security-advisories) if you're not a subscriber. - + Security is an ongoing process. After going live, you should pay attention to security advisories released via [your service portal](https://support.ibexa.co/), or via [Security advisories](https://developers.ibexa.co/security-advisories) if you're not a subscriber. + ## Symfony ### `APP_SECRET` `APP_SECRET` needs to be a strong, random, securely stored value. -- Do not use a default value like `ff6dc61a329dc96652bb092ec58981f7` or `ThisTokenIsNotSoSecretChangeIt`. -- The secret must be secured against unwanted access. Do not commit the value to a version control system. +- Don't use a default value like `ff6dc61a329dc96652bb092ec58981f7` or `ThisTokenIsNotSoSecretChangeIt`. +- The secret must be secured against unwanted access. Don't commit the value to a version control system. - The secret must be long enough. 32 characters is minimum, longer is better. !!! tip - - The following command will generate a 64-character-long secure random value: - + + The following command generates a 64-character-long secure random value: + `php -r "print bin2hex(random_bytes(32));"` - + !!! note - On [[= product_name_cloud =]], if `APP_SECRET` is not set, the system sets it to [`PLATFORM_PROJECT_ENTROPY`](https://docs.platform.sh/guides/symfony/environment-variables.html#symfony-environment-variables) + On [[= product_name_cloud =]], if `APP_SECRET` isn't set, the system sets it to [`PLATFORM_PROJECT_ENTROPY`](https://docs.platform.sh/guides/symfony/environment-variables.html#symfony-environment-variables) ### Symfony production mode Only expose Symfony production mode openly on the internet. -Do not expose the dev mode on the internet, otherwise you may disclose things like `phpinfo` and environment variables. -Exposing the dev mode exposes things like `phpinfo`, environment variables and so on. - -!!! tip "More information about Symfony security" +Don't expose the dev mode on the internet, otherwise you may disclose things like `phpinfo` and environment variables. +Exposing the dev mode exposes things like `phpinfo`, environment variables, and more. - For more information about securing Symfony-based systems, see: - - - [Authentication and authorisation]([[= symfony_doc =]]/security.html), and [more on this subject]([[= symfony_doc =]]/security.html#learn-more) - - Symfony's [secrets management system]([[= symfony_doc =]]/configuration/secrets.html) +For more information about securing Symfony-based systems, see [Authentication and authorisation]([[= symfony_doc =]]/security.html), [more on this subject]([[= symfony_doc =]]/security.html#learn-more), and Symfony's [secrets management system]([[= symfony_doc =]]/configuration/secrets.html). ## PHP @@ -52,10 +44,9 @@ Exposing the dev mode exposes things like `phpinfo`, environment variables and s PHP 7.4 introduced the `zend.exception_ignore_args` setting in `php.ini`. The default value is 0 (disabled) for backwards compatibility. -On production sites this should be set to 1 (enabled), to ensure stack traces do not include arguments passed to functions. +On production sites this should be set to 1 (enabled), to ensure stack traces don't include arguments passed to functions. Such arguments could include passwords or other sensitive information. -You should also make sure no stack trace is ever visible to end users of production sites, -though visible arguments are unsafe even if the stack traces only show up in log files. +You should also make sure no stack trace is ever visible to end users of production sites, though visible arguments are unsafe even if the stack traces only show up in log files. ### Disable error output from PHP @@ -73,28 +64,26 @@ display_startup_errors = Off ### Other PHP settings Consider what other security related settings are relevant for your needs. -The [OWASP PHP Configuration Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/PHP_Configuration_Cheat_Sheet.html) -contains several recommendations, but be aware that they may be out of date as they don't mention PHP 8. -See also [PHP's own security manual](https://www.php.net/manual/en/security.php). +The [OWASP PHP Configuration Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/PHP_Configuration_Cheat_Sheet.html) contains several recommendations, but be aware that they may be out of date as they don't mention PHP 8. + +For more information, see [PHP's own security manual](https://www.php.net/manual/en/security.php). ## [[= product_name =]] ### Fully-vetted admin users -Make sure Admin users and other privileged users who have access to System Information and setup in the back end -are vetted and fully trustworthy. +Make sure Admin users and other privileged users who have access to System Information and setup in the back end are vetted and fully trustworthy. -As administrator you have access to full information about the system through the `setup/system_info` Policy, -and also to user data, Role editing, and many other critical aspects. +As administrator you have access to full information about the system through the `setup/system_info` policy, and also to user data, role editing, and many other critical aspects. ### Strong passwords -Enforce strong passwords for all users. +Enforce strong passwords for all users. This is specially important for admin accounts and other privileged users. - Never go online with admin password set to `publish` or any other default value. - Introduce password quality checks. Make sure the checks are strict enough (length/complexity). -- 16 characters is a quite secure minimum length. Do not go below 10. +- 16 characters is a quite secure minimum length. Don't go below 10. - If using [[= product_name =]] v4.5 or newer, enable the password rule that rejects any password which has been exposed in a public breach. !!! tip "Password rules" @@ -103,25 +92,28 @@ This is specially important for admin accounts and other privileged users. ### Secure secrets -Ensure all other secrets are similarly secured: Varnish invalidate token, JWT passphrase (if in use), -and any other application-specific secrets. +Ensure all other secrets are similarly secured: Varnish invalidate token, JWT passphrase (if in use), and any other application-specific secrets. ### Protect against brute force attacks -Consider introducing a measure against brute force login attacks, like CAPTCHA. Adjust timeout limits to your needs: - -When using the "forgot password" feature, a token is created which expires if the user doesn't click the password reset -link that gets mailed to them in time. The time before it expires is set in the parameter -`ibexa.site_access.config.default.security.token_interval_spec`. By nature this feature must be available to users -before they have logged in, including would-be attackers. If an attacker uses this feature with someone else's email -address, the attacker does not receive the email. But they could still try to guess the password reset link. That's why -this interval should be as short as possible. 5 minutes is often enough. - -[[= product_name =]] allows you to create and send invitations to create an account in the frontend as a customer, the Back Office -as an employee, or the Corporate Portal as a business partner. You can send invitations to individual users or in -bulk. These invitations time out according to the parameter -`ibexa.site_access.config.default.user_invitation.hash_expiration_time`. This can safely be longer than the "forgot password" time, -since attackers cannot generate invitations. Don't leave it longer than it needs to be, though. +Consider introducing a measure against brute force login attacks, like CAPTCHA. +Adjust timeout limits to your needs: + +When using the "forgot password" feature, a token is created which expires if the user doesn't click the password reset link that gets mailed to them in time. +The time before it expires is set in the parameter `ibexa.site_access.config.default.security.token_interval_spec`. +By nature this feature must be available to users before they have logged in, including would-be attackers. +If an attacker uses this feature with someone else's email address, the attacker doesn't receive the email. +But they could still try to guess the password reset link. +That's why this interval should be as short as possible. +5 minutes is often enough. + +[[= product_name =]] allows you to create and send invitations to create an account in the frontend as a customer, the back office +as an employee, or the Corporate Portal as a business partner. +You can send invitations to individual users or in bulk. +These invitations time out according to the parameter +`ibexa.site_access.config.default.user_invitation.hash_expiration_time`. +This can safely be longer than the "forgot password" time, since attackers cannot generate invitations. +Don't leave it longer than it needs to be, though. These timeouts are both entered as [PHP DateInterval duration strings](https://www.php.net/manual/en/dateinterval.construct.php). The forgot password feature defaults to "PT1H" (one hour). @@ -129,17 +121,19 @@ The account invitation feature defaults to "P7D" (seven days). ### Disable Varnish when using Fastly -If you are using Fastly, disable Varnish. +If you're using Fastly, disable Varnish. See [Security advisory: EZSA-2020-002](https://developers.ibexa.co/security-advisories/ezsa-2020-002-unauthorised-cache-purge-with-misconfigured-fastly). ### Block upload of unwanted file types The `ibexa.site_access.config.default.io.file_storage.file_type_blacklist` setting is defined in the config file `src/bundle/Core/Resources/config/default_settings.yml` in the Core bundle. -It prevents uploading files that might be executed on the server, a Remote Code Execution (RCE) vulnerability. The setting lists filename extensions for files that shouldn't be uploaded. +It prevents uploading files that might be executed on the server, a Remote Code Execution (RCE) vulnerability. +The setting lists filename extensions for files that shouldn't be uploaded. Attempting to upload files from the list results in an error message. There are also other safety measures in place, like using the web server configuration to block execution of uploaded scripts, see the next point. -You should adapt this list to your needs. Note that `svg` images are blocked because they may contain JavaScript code. +You should adapt this list to your needs. +`svg` images are blocked because they may contain JavaScript code. If you opt to allow them, make sure you take steps to mitigate the risk. The default list of blocked file types contains: `hta htm html jar js jse pgif phar php php3 php4 php5 phps phpt pht phtml svg swf xhtm xhtml`. @@ -151,53 +145,57 @@ See the line below `# Disable .php(3) and other executable extensions in the var ### Use secure password hashing -Use the most secure supported password hashing method. This is currently `bcrypt`, and it is enabled by default. +Use the most secure supported password hashing method. +This is currently `bcrypt`, and it's enabled by default. ### Use UTF8MB4 with MySQL/MariaDB -If you are using MySQL/MariaDB, use the UTF8MB4 database character set and related collation. +If you're using MySQL/MariaDB, use the UTF8MB4 database character set and related collation. The older UTF8 can lead to truncation with 4-byte characters, like some emoji, which may have unpredictable side effects. See [Change from UTF8 to UTF8MB4](update_db_to_2.5.md#change-from-utf8-to-utf8mb4). -### Use secure Roles and Policies +### Use secure roles and policies -Use the following checklist to ensure the Roles and Policies are secure: +Use the following checklist to ensure the roles and policies are secure: -- Do Roles restrict read/write access to content as they should? Is read/write access to personal data, like User content items, properly restricted? -- Are the Roles and their use properly differentiated and restricted? Is an editor Role used for everyday editorial work? -- Is the admin Role used only for high-level administrative work? Is the number of people with admin access properly restricted and vetted? +- Do roles restrict read/write access to content as they should? Is read/write access to personal data, like User content items, properly restricted? +- Are the roles and their use properly differentiated and restricted? Is an editor role used for everyday editorial work? +- Is the admin role used only for high-level administrative work? Is the number of people with admin access properly restricted and vetted? - Should people be allowed to create new user accounts themselves? Should such accounts be enabled by default, or require vetting by admins? -- Is the Role of self-created new users restricted as intended? -- Is there a clear Role separation between the organisation's internal and external users? +- Is the role of self-created new users restricted as intended? +- Is there a clear role separation between the organisation's internal and external users? - Is access to user data properly restricted, in accordance with GDPR? - Is access to Form Builder uploads managed properly? Files uploaded with the Form Builder are accessible to any user by default. If this doesn't suit you, restrict access to the Form Uploads folder. -### Do not use "hide" for read access restriction +### Don't use "hide" for read access restriction The [visibility switcher](https://doc.ibexa.co/en/latest/content_management/locations/#location-visibility) is a convenient feature for withdrawing content from the frontend. -It acts as a filter in the frontend by default. You can choose to respect it or ignore it in your code. -It isn't permission-based, and doesn't restrict read access to content. Hidden content can be read through other means, like the REST API or GraphQL. +It acts as a filter in the frontend by default. +You can choose to respect it or ignore it in your code. +It isn't permission-based, and doesn't restrict read access to content. +Hidden content can be read through other means, like the REST API or GraphQL. -If you need to restrict read access to a given content item, you could create a role that grants read access for a given -[**Section**](https://doc.ibexa.co/en/latest/administration/content_organization/sections/) -or [**Object State**](https://doc.ibexa.co/en/latest/administration/content_organization/object_states/), -and set a different Section or Object State for the given Content. +If you need to restrict read access to a given content item, you could create a role that grants read access for a given [**Section**](https://doc.ibexa.co/en/latest/administration/content_organization/sections/) or [**Object State**](https://doc.ibexa.co/en/latest/administration/content_organization/object_states/), and set a different section or object State for the given content. Or use other permission-based [**Limitations**](https://doc.ibexa.co/en/latest/permissions/limitations/). ### Minimize exposure -Security should be a multi-layered exercise. It is wise to minimize what features you make available to the world, even if there are no known or suspected vulnerabilities in those features, and even if your content is properly protected by roles and policies. Reduce your attack surface by exposing only what you must. +Security should be a multi-layered exercise. +It's wise to minimize what features you make available to the world, even if there are no known or suspected vulnerabilities in those features, and even if your content is properly protected by roles and policies. +Reduce your attack surface by exposing only what you must. -- If possible, make the Back Office unavailable on the open internet. -- [Symfony FOSJsRoutingBundle](https://github.com/FriendsOfSymfony/FOSJsRoutingBundle) is required in those releases where it is included, to expose routes to JavaScript. It exposes only the required routes, nothing more. It is only required in the Back Office site access though, so you can consider blocking it in other site accesses. You should also go through your own custom routes, and decide for each if you need to expose them or not. See the documentation on [YAML route definitions for exposure](https://github.com/FriendsOfSymfony/FOSJsRoutingBundle/blob/master/Resources/doc/usage.rst#generating-uris). -- By default, a [Powered-By header](https://doc.ibexa.co/en/latest/update_and_migration/from_1.x_2.x/update_db_to_2.5/#powered-by-header) is set. It specifies what version of the DXP is running. For example, `x-powered-by: Ibexa Experience v4`. This doesn't expose anything that couldn't be detected through other means. But if you wish to obscure this, you can either omit the version number, or disable the header entirely. +- If possible, make the back office unavailable on the open internet. +- [Symfony FOSJsRoutingBundle](https://github.com/FriendsOfSymfony/FOSJsRoutingBundle) is required in those releases where it's included, to expose routes to JavaScript. It exposes only the required routes, nothing more. It's only required in the back office SiteAccess though, so you can consider blocking it in other SiteAccesses. You should also go through your own custom routes, and decide for each if you need to expose them or not. See the documentation on [YAML route definitions for exposure](https://github.com/FriendsOfSymfony/FOSJsRoutingBundle/blob/master/Resources/doc/usage.rst#generating-uris). +- By default, a [Powered-By header](https://doc.ibexa.co/en/latest/update_and_migration/from_1.x_2.x/update_db_to_2.5/#powered-by-header) is set. It specifies what version of the DXP is running. For example, `x-powered-by: [[= product_name_exp =]] v4`. This doesn't expose anything that couldn't be detected through other means. But if you wish to obscure this, you can either omit the version number, or disable the header entirely. - Consider whether certain interfaces must be left available on the open internet. For example: - The `/search` and `/graphql` endpoints - The REST API endpoints !!! tip "Access control" - One way to lock down an endpoint that should not be openly available is to restrict access to logged-in users, by using the [`access_control`]([[= symfony_doc =]]/security/access_control.html) feature. In your YAML configuration, under the `security` key, add an entry similar to the following one, which redirects requests to a login page: + + One way to lock down an endpoint that should not be openly available is to restrict access to logged-in users, by using the [`access_control`]([[= symfony_doc =]]/security/access_control.html) feature. + In your YAML configuration, under the `security` key, add an entry similar to the following one, which redirects requests to a login page: ```yaml security: @@ -212,7 +210,7 @@ Once you have properly configured secure user roles and permissions, to avoid ex - Avoid exposing servers on the open internet when not strictly required. - Ensure any servers, services, ports and virtual hosts that were opened for testing purposes are shut down before going live. - Ensure file system permissions are set up in such a way that the web server or PHP user can't access files they shouldn't be able to read. -- Secure the database with a good password, keys, firewall, etc. +- Secure the database with a good password, keys, firewall. Optionally, ensure that the database user used by the web app only has permissions to do the operations needed by [[= product_name =]]. The Data Definition Language (DDL) commands (create, alter, drop, truncate, comment) are only needed for installing and upgrading [[= product_name =]], and not for running it. Not granting these rights to web app users reduces the damage that can result from a security breach. @@ -221,34 +219,34 @@ Those steps aren't needed when using [[= product_name_cloud =]], where the provi ### Security headers -There are a number of security related HTTP response headers that you can use to improve your security. -Headers must be adapted to the site in question, and in most cases it is site owner's responsibility. -The headers can be set either by the web server, or by a proxy like Varnish. +There are a number of security related HTTP response headers that you can use to improve your security. +Headers must be adapted to the site in question, and in most cases it's site owner's responsibility. +The headers can be set either by the web server, or by a proxy like Varnish. You can also set headers in PHP code by making a Symfony `RequestListener` for the `kernel.response` event and adding the header to the response object headers list. -You will likely need to vary the security headers based on the SiteAccess in question and site implementation details, such as frontend code and libraries used. - -- `Strict-Transport-Security` - ensures that all requests are sent over HTTPS, with no fallback to HTTP. -All production sites should use HTTPS and this header unless they have very particular needs. -This header is less important during development provided that the site is on an internal, protected network. -- `X-Frame-Options` - ensures that the site is not be embedded in a frame by a compliant browser. -Set the header to `SAMEORIGIN` to allow embedding by your own site, or `DENY` to block framing completely. -- `X-Content-Type-Options` - prevents the browser from second-guessing the mime-type of delivered content. -This header is less important if users cannot upload content and/or you trust your editors. However, it is safer to use it at all times. -Make sure that the `Content-Type` header is also correctly set, including for the top-level document, to avoid issues with HTML documents being downloaded while they should be rendered. -- `Content-Security-Policy` - blocks cross site scripting (XSS) attacks by setting an allowlist (whitelist) of resources to be loaded for a given page. -You can set separate lists for scripts, images, fonts, and so on. -For experimentation and testing, you can use `Content-Security-Policy-Report-Only` before activating the actual policy. -- `Referrer-Policy` - limits what information is sent from the previous page or site when navigating to a new page or site. -This header has several directives for fine-tuning the referrer information. -- `Permissions-Policy` - limits what features the browser can use, such as fullscreen, notifications, location, camera, or microphone. -For example, if someone succeeds in injecting their JavaScript into your site, this header prevents them from using those features to attack your users. +You most likely need to vary the security headers based on the SiteAccess in question and site implementation details, such as frontend code and libraries used. + +- `Strict-Transport-Security` - ensures that all requests are sent over HTTPS, with no fallback to HTTP. +All production sites should use HTTPS and this header unless they have particular needs. +This header is less important during development provided that the site is on an internal, protected network. +- `X-Frame-Options` - ensures that the site isn't embedded in a frame by a compliant browser. +Set the header to `SAMEORIGIN` to allow embedding by your own site, or `DENY` to block framing completely. +- `X-Content-Type-Options` - prevents the browser from second-guessing the mime-type of delivered content. +This header is less important if users cannot upload content and/or you trust your editors. However, it's safer to use it at all times. +Make sure that the `Content-Type` header is also correctly set, including for the top-level document, to avoid issues with HTML documents being downloaded while they should be rendered. +- `Content-Security-Policy` - blocks cross site scripting (XSS) attacks by setting an allowlist (whitelist) of resources to be loaded for a given page. +You can set separate lists for scripts, images, fonts, and more. +For experimentation and testing, you can use `Content-Security-Policy-Report-Only` before activating the actual policy. +- `Referrer-Policy` - limits what information is sent from the previous page or site when navigating to a new page or site. +This header has several directives for fine-tuning the referrer information. +- `Permissions-Policy` - limits what features the browser can use, such as fullscreen, notifications, location, camera, or microphone. +For example, if someone succeeds in injecting their JavaScript into your site, this header prevents them from using those features to attack your users. ### Track dependencies - Run servers on a recent operating system and install security patches for dependencies. - Configure servers to alert you about security updates from vendors. Pay special attention to dependencies used by your project directly, or by PHP. The provider of the operating system usually has a service for this. - Enable [GitHub Dependabot](https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates) -to receive notifications when a security fix is released in a Github-hosted dependency. -- If you're not using Github for your project, you can create a dummy project on Github with the same dependencies as your real project, and enable Dependabot notifications for that. +to receive notifications when a security fix is released in a GitHub-hosted dependency. +- If you're not using GitHub for your project, you can create a dummy project on GitHub with the same dependencies as your real project, and enable Dependabot notifications for that. - Ensure you get notifications about security fixes in JavaScript dependencies. diff --git a/docs/infrastructure_and_maintenance/sessions.md b/docs/infrastructure_and_maintenance/sessions.md index ef0b80ded6..948b7807ce 100644 --- a/docs/infrastructure_and_maintenance/sessions.md +++ b/docs/infrastructure_and_maintenance/sessions.md @@ -5,17 +5,15 @@ description: Ibexa DXP uses Symfony to handle user sessions, with support for Si # Sessions Sessions are handled by the Symfony framework, specifically API and underlying session handlers provided by the HttpFoundation component. -It is further enhanced in [[= product_name =]] with support for SiteAccess-aware session cookie configuration. +It's further enhanced in [[= product_name =]] with support for SiteAccess-aware session cookie configuration. !!! note - Use of Memcached, Redis (or experimentally PDO) as session handler is a requirement in a cluster setup, - for details [see below](#cluster-setup). For an overview of the clustering feature see [Clustering](clustering.md). + Use of Memcached, Redis (or experimentally PDO) as session handler is a requirement in a cluster setup, for details [see below](#cluster-setup). For an overview of the clustering feature see [Clustering](clustering.md). ## Configuration -Symfony offers the possibility to change many session options at application level -(for example, in Symfony [`framework` configuration]([[= symfony_doc =]]/reference/configuration/framework.html#session)). +Symfony offers the possibility to change many session options at application level (for example, in Symfony [`framework` configuration]([[= symfony_doc =]]/reference/configuration/framework.html#session)). These options include: - `cookie_domain` @@ -24,13 +22,11 @@ These options include: - `cookie_secure` - `cookie_httponly` -However, in [[= product_name =]] you can set up several sites within one Symfony application, -so you can also define session configuration per SiteAccess and SiteAccess group level. +However, in [[= product_name =]] you can set up several sites within one Symfony application, so you can also define session configuration per SiteAccess and SiteAccess group level. ### Session options per SiteAccess -All site-related session configuration can be defined per SiteAccess and SiteAccess group -under the `ibexa.system..session` [configuration key](configuration.md#configuration-files): +All site-related session configuration can be defined per SiteAccess and SiteAccess group under the `ibexa.system..session` [configuration key](configuration.md#configuration-files): ``` yaml ibexa: @@ -52,8 +48,8 @@ ibexa: ## Session handlers -In Symfony, a session handler is configured using `framework.session.handler_id`. -Symfony can be configured to use custom handlers, or just fall back to what is configured in PHP by setting it to null (`~`). +In Symfony, a session handler is configured with `framework.session.handler_id`. +Symfony can be configured to use custom handlers, or fall back to what is configured in PHP by setting it to null (`~`). ### Default configuration @@ -102,8 +98,7 @@ Alternatively if you need to configure Memcached servers dynamically: - Set `%ibexa.session.handler_id%` (or `SESSION_HANDLER_ID` env var) to `app.session.handler.native_memcached` - Set `%ibexa.session.save_path%` (or `SESSION_SAVE_PATH` env var) to [`save_path` config for Memcached](https://www.php.net/manual/en/memcached.sessions.php) -Optionally tweak [`php-memcached` session settings](https://www.php.net/manual/en/memcached.configuration.php) for things like -session locking. +Optionally tweak [`php-memcached` session settings](https://www.php.net/manual/en/memcached.configuration.php) for things like session locking. ##### Handling sessions with Redis @@ -117,24 +112,23 @@ Alternatively if you have needs to configure Redis servers dynamically: - Set `%ibexa.session.handler_id%` (or `SESSION_HANDLER_ID` env var) to `Ibexa\Bundle\Core\Session\Handler\NativeSessionHandler` - Set `%ibexa.session.save_path%` (or `SESSION_SAVE_PATH` env var) to [save_path config for Redis](https://github.com/phpredis/phpredis/#php-session-handler) -!!! note "Ibexa Cloud" +!!! note "[[= product_name_cloud =]]" For [[= product_name_cloud =]] (and Platform.sh), this is already configured in `config/env/platformsh.php` based on `.platform.yaml` config. -If you are on `php-redis` v4.2.0 and higher, you can optionally tweak [`php-redis` settings](https://github.com/phpredis/phpredis#session-locking) for session locking. +If you're on `php-redis` v4.2.0 and higher, you can optionally tweak [`php-redis` settings](https://github.com/phpredis/phpredis#session-locking) for session locking. Ideally keep [persistence cache](persistence_cache.md) and session data separated: - Sessions can't risk getting [randomly evicted](https://redis.io/docs/reference/eviction/#eviction-policies) when you run out of memory for cache. -- You can't completely disable eviction either, as Redis will then start to refuse new entries once full, including new sessions. +- You can't completely disable eviction either, as Redis then starts to refuse new entries once full, including new sessions. - Either way, you should monitor your Redis instances and make sure you have enough memory set aside for active sessions/cache items. If you want to make sure sessions survive Redis or server restarts, consider using a [persistent Redis](https://redis.io/docs/management/persistence/) instance for sessions. -##### Alternative storing sessions in database using PDO +##### Alternative storing sessions in database by using PDO -For setups where database is preferred for storing sessions, you may use Symfony's PdoSessionHandler, -although it is not currently recommended from performance perspective. +For setups where database is preferred for storing sessions, you may use Symfony's PdoSessionHandler, although it's not currently recommended from performance perspective. Below is a configuration example for [[= product_name =]]. Refer to the [Symfony Cookbook]([[= symfony_doc =]]/doctrine/pdo_session_storage.html) for full documentation. diff --git a/docs/infrastructure_and_maintenance/support_and_maintenance_faq.md b/docs/infrastructure_and_maintenance/support_and_maintenance_faq.md index 7a18b7c63c..c64b158e55 100644 --- a/docs/infrastructure_and_maintenance/support_and_maintenance_faq.md +++ b/docs/infrastructure_and_maintenance/support_and_maintenance_faq.md @@ -4,13 +4,12 @@ description: See how you can resolve common issues and report a Customer Support # Support and maintenance FAQ -This page contains answers to most common questions and tips around support and maintenance, -as well as references to important parts of the documentation and tools useful for developers in their daily work. +This page contains answers to most common questions and tips around support and maintenance, references to important parts of the documentation, and tools for developers in their daily work. #### What information should I specify when creating a Customer Support ticket? When reporting a problem to Customer Support the most important information is the version of [[= product_name =]] which is used in the project. -The best way to specify it is to provide the list of currently installed packages by running: +The best way to specify it's to provide the list of currently installed packages by running: ``` bash composer show ibexa/* @@ -18,29 +17,27 @@ composer show ibexa/* Besides that, all the configuration from the `config` directory may be helpful. -You should also list the steps to reproduce the issue, -or at least provide a clear description of the circumstances under which the problem occurred. +You should also list the steps to reproduce the issue, or at least provide a clear description of the circumstances under which the problem occurred. If you stumble upon a database-related problem, providing corresponding logs is also an important step. -Additionally, mention recent changes, performed migrations or external scripts/code customizations -related to the code which generates the problem. +Additionally, mention recent changes, performed migrations or external scripts/code customizations related to the code which generates the problem. #### What are the recommended ways to increase my project's performance? The most important clues around increasing overall performance of your [[= product_name =]]-based project can be found in [the Performance documentation page](performance.md). -#### How can I translate my Back Office? +#### How can I translate my back office? -The language of the Back Office is based on the browser language. -In order to change it you should install the proper package for your language (see [language packages list](https://github.com/ezplatform-i18n)). -Once you have language packages installed, you can switch the language of the Back Office in the User Settings menu. +The language of the back office is based on the browser language. +To change it you should install the proper package for your language (see [language packages list](https://github.com/ezplatform-i18n)). +Once you have language packages installed, you can switch the language of the back office in the **User Settings** menu. -If you do not have a language defined in the browser, it will be selected based on the `parameters.locale_fallback` parameter located in `config/packages/ibexa.yaml`. +If you don't have a language defined in the browser, it's selected based on the `parameters.locale_fallback` parameter located in `config/packages/ibexa.yaml`. To read more about language managing in [[= product_name =]], see the following doc pages: -- [Back Office languages](back_office_translations.md) +- [Back office languages](back_office_translations.md) - [Multi-language SiteAccesses and corresponding translations](set_up_translation_siteaccess.md) #### How can I apply patches to the installation? @@ -50,14 +47,11 @@ Remember to clear the cache afterwards. As an alternative to manually applying the patch, you can use [composer-patches](https://github.com/cweagans/composer-patches). You can apply patches received from the Support, community or the others by using your `composer.json` file. -For checking the versions you are on, refer to your `composer.lock`. -All you need is to specify which package will receive patches and give the path/URL to the actual file. -This should be done inside the `extra` section. Packages which should receive patches -will be removed during `composer update` or `composer require` so they can be re-installed and re-patched. - -When updating to the release that already contains specified patches, -Composer will throw an error alongside a message that they cannot be applied and will be skipped -([this is configurable with 1.x](https://github.com/cweagans/composer-patches/tree/1.x#error-handling)). +For checking the versions you're on, refer to your `composer.lock`. +All you need is to specify which package receives patches and give the path/URL to the actual file. +This should be done inside the `extra` section. Packages which should receive patches are removed during `composer update` or `composer require` so they can be re-installed and re-patched. + +When updating to the release that already contains specified patches, Composer throws an error alongside a message that they cannot be applied and are skipped ([this is configurable with 1.x](https://github.com/cweagans/composer-patches/tree/1.x#error-handling)). They can be manually removed from `composer.json` now. #### How to clear the cache properly? @@ -99,8 +93,7 @@ rm -rf var/cache/* #### Where should I place my configuration files? -In order to avoid merge conflicts on important configuration settings during upgrades, -moving as much as possible of your configuration to your own files can be a good idea. +To avoid merge conflicts on important configuration settings during upgrades, moving as much as possible of your configuration to your own files can be a good idea. All project-specific parameters should be kept in separate files. For example, configuration for Page Blocks could be placed in `config/packages/landing_page_blocks.yaml`. diff --git a/docs/multisite/languages/back_office_translations.md b/docs/multisite/languages/back_office_translations.md index 238bcf4c67..8b1597f874 100644 --- a/docs/multisite/languages/back_office_translations.md +++ b/docs/multisite/languages/back_office_translations.md @@ -1,12 +1,13 @@ --- -description: The language of the Back Office is selected automatically based on browser language, or you can choose it manually in user settings. +description: The language of the back office is selected automatically based on browser language, or you can choose it manually in user settings. --- -# Back Office translations +# Back office translations -## Enabling Back Office languages +## Enabling back office languages -All translations are available as a part of [[= product_name =]]. To enable Back Office translations, use the following configuration: +All translations are available as a part of [[= product_name =]]. +To enable back office translations, use the following configuration: ``` yaml ibexa: @@ -15,44 +16,40 @@ ibexa: enabled: true ``` -Then clear the cache. Now you can reload your [[= product_name =]] Back Office. -If your browser language is set to French, the Back Office will be displayed in French. +Then clear the cache. Now you can reload your [[= product_name =]] back office. +If your browser language is set to French, the back office is displayed in French. !!! tip "Checking browser language" - To make sure that a language is set in your browser, check if it is sent as an accepted language in the `Accept-Language` header. + To make sure that a language is set in your browser, check if it's sent as an accepted language in the `Accept-Language` header. !!! tip You can also manually add the necessary .xliff files to an existing project. - + Add the language to an array under `ibexa.system..user_preferences.additional_translations`, for example: `ibexa.system..user_preferences.additional_translations: ['pl_PL', 'fr_FR']` Then, run `composer run post-update-cmd` and clear the cache. -### Contributing Back Office translations +### Contributing back office translations To learn how to contribute to a translation, see [Contributing translations](contribute_translations.md). -### Selecting Back Office language +### Selecting back office language -Once you have language packages enabled, you can switch the language of the Back Office -in the User Settings menu. +Once you have language packages enabled, you can switch the language of the back office in the **User Settings** menu. -Otherwise, the language will be selected based on the browser language. -If you do not have a language defined in the browser, the language will be selected -based on `parameters.locale_fallback` in `config/packages/ibexa.yaml`. +Otherwise, the language is selected based on the browser language. +If you don't have a language defined in the browser, the language is selected based on `parameters.locale_fallback` in `config/packages/ibexa.yaml`. ## Custom string translations -When you extend the Back Office you often need to provide labels for new elements. -It is good practice to provide your labels in translations files, instead of literally, -so they can be reused and translated into other languages. +When you extend the back office you often need to provide labels for new elements. +It's good practice to provide your labels in translations files, instead of literally, so they can be reused and translated into other languages. -To provide label strings, make use of the `Symfony\Component\Translation\TranslatorInterface` -and its `trans()` method. +To provide label strings, make use of the `Symfony\Component\Translation\TranslatorInterface` and its `trans()` method. The method takes as arguments: @@ -84,7 +81,7 @@ private function getTranslatedDescription(): string The strings are provided in .xliff files. The file should be stored in your project's or your bundle's `Resources/translations` folder. -File name corresponds to the selected domain and the language, e.g. `custom_extension.en.xliff`. +File name corresponds to the selected domain and the language, for example, `custom_extension.en.xliff`. ``` xml @@ -116,8 +113,8 @@ For example, in `custom_extension.de.xliff`: ``` -The language to display will then be selected automatically based on [user preferences or browser setup](#selecting-back-office-language). +The language to display is then selected automatically based on [user preferences or browser setup](#selecting-back-office-language). !!! note - You may need to clear the cache after adding new translations, before they are available in the Back Office. + You may need to clear the cache after adding new translations, before they're available in the back office. diff --git a/docs/multisite/languages/language_api.md b/docs/multisite/languages/language_api.md index 2e3d783b2d..bd596cacfd 100644 --- a/docs/multisite/languages/language_api.md +++ b/docs/multisite/languages/language_api.md @@ -16,8 +16,7 @@ To get a list of all languages in the system use [`LanguageService::loadLanguage ## Creating a language -To create a new language, you need to create a [`LanguageCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-LanguageCreateStruct.html) -and provide it with the language code and language name. +To create a new language, you need to create a [`LanguageCreateStruct`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-LanguageCreateStruct.html) and provide it with the language code and language name. Then, use [`LanguageService::createLanguage`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-LanguageService.html#method_createLanguage) and pass the `LanguageCreateStruct` to it: ``` php diff --git a/docs/multisite/languages/languages.md b/docs/multisite/languages/languages.md index 1867872fa7..c6f53cb3d5 100644 --- a/docs/multisite/languages/languages.md +++ b/docs/multisite/languages/languages.md @@ -9,53 +9,70 @@ description: You can create multiple language versions (translations) of content [[= product_name =]] offers the ability to create multiple language versions (translations) of a content item. Translations are created per version of the item, so each version of the content can have a different set of translations. -A version always has at least one translation which by default is the *initial/main* translation. Further versions can be added, but only for languages that have previously been [added to the global translation list](#adding-available-languages), that is a list of all languages available in the system. The maximum number of languages in the system is 62. +A version always has at least one translation which by default is the *initial/main* translation. +Further versions can be added, but only for languages that have previously been [added to the global translation list](#adding-available-languages), that is a list of all languages available in the system. +The maximum number of languages in the system is 62. -Different translations of the same content item can be edited separately. This means that different users can work on translations into different languages at the same time. +Different translations of the same content item can be edited separately. +This means that different users can work on translations into different languages at the same time. Each version, including a draft, contains all the existing translations. -However, even if work on a draft takes time and other translations are updated in the meantime, -publishing the draft will not overwrite later modifications. +However, even if work on a draft takes time and other translations are updated in the meantime, publishing the draft doesn't overwrite later modifications. ### Adding available languages -The multilanguage system operates based on a global translation list that contains all languages available in the installation. Languages can be [added to this list from the Admin Panel](https://doc.ibexa.co/projects/userguide/en/latest/content_management/translate_content/) in the Back Office. After adding a language be sure to dump all assets to the file system: +The multilanguage system operates based on a global translation list that contains all languages available in the installation. +Languages can be [added to this list from the **Admin** panel](https://doc.ibexa.co/projects/userguide/en/latest/content_management/translate_content/) in the back office. +After adding a language be sure to dump all assets to the file system: ``` yarn encore # OR php bin/console ibexa:encore:compile ``` -**The new language must then be added to the [SiteAccess](multisite.md) configuration**. Once this is done, any user with proper permissions can create content item versions in these languages in the user interface. +**The new language must then be added to the [SiteAccess](multisite.md) configuration**. +Once this is done, any user with proper permissions can create content item versions in these languages in the user interface. -### Translatable and untranslatable Fields +### Translatable and untranslatable fields -Language versions consist of translated values of the content item's Fields. In the content type definition every Field is set to be Translatable or not. +Language versions consist of translated values of the content item's fields. +In the content type definition every field is set to be Translatable or not. -[[= product_name =]] does not decide by itself which Fields can be translated and which cannot. For some Field values the need for a translation can be obvious, for example for the body of an article. In other cases, for instance images without text, integer numbers or e-mail addresses, translation is usually unnecessary. Despite that, [[= product_name =]] gives you the possibility to mark any Field as translatable regardless of its Field Type. It is only your decision to exclude the translation possibility for those Fields where it makes no sense. +[[= product_name =]] doesn't decide by itself which fields can be translated and which cannot. +For some field values the need for a translation can be obvious, for example for the body of an article. +In other cases, for instance images without text, integer numbers, or email addresses, translation is usually unnecessary. +Despite that, [[= product_name =]] gives you the possibility to mark any field as translatable regardless of its field type. +It's only your decision to exclude the translation possibility for those fields where it makes no sense. -When a Field is not flagged as Translatable, its value will be copied from the initial/main translation when a new language version is created. This copied value cannot be modified. When a Field is Translatable, you will have to enter its value in a new language version manually. +When a field isn't flagged as Translatable, its value is copied from the initial/main translation when a new language version is created. This copied value cannot be modified. When a field is Translatable, you have to enter its value in a new language version manually. -For example, let's say that you need to store information about marathon contestants and their results. You build a "contestant" content type using the following Fields: name, photo, age, nationality, finish time. Allowing the translation of anything other than nationality would be pointless, since the values stored by the other Fields are the same regardless of the language used to describe the contestant. In other words, the name, photo, age and finish time would be the same in, for example, both English and Norwegian. +For example, let's say that you need to store information about marathon contestants and their results. +You build a "contestant" content type that includes the following fields: name, photo, age, nationality, finish time. +Allowing the translation of anything other than nationality would be pointless, since the values stored by the other fields are the same regardless of the language used to describe the contestant. +In other words, the name, photo, age and finish time would be the same in, for example, both English and Norwegian. ### Access control -You can control whether a User or User Group is able to translate content or not. You do this by adding a [Language Limitation](limitation_reference.md#language-limitation) to Policies that allow creating or editing content. This Limitation enables you to define which Role can work with which languages in the system. (For more information of the permissions system, see [Permissions](permissions.md).) +You can control whether a user or user group is able to translate content or not. +You do this by adding a [Language limitation](limitation_reference.md#language-limitation) to policies that allow creating or editing content. +This limitation enables you to define which role can work with which languages in the system. -In addition, you can also control the access to the global translation list by using the Content/Translations Policy. This Policy allows users to add and remove languages from the global translation list. +For more information of the permissions system, see [Permissions](permissions.md). + +In addition, you can also control the access to the global translation list by using the `Content/Translations` policy. +This policy allows users to add and remove languages from the global translation list. ## Using SiteAccesses for handling translations -If you want to have completely separate versions of the website, each with content in its own language, -you can [use SiteAccesses](#using-siteaccesses-for-handling-translations). -Depending on the URI used to access the website, a different site will open, with a language set in configuration settings. -All content items will then be displayed in this language. +If you want to have completely separate versions of the website, each with content in its own language, you can [use SiteAccesses](#using-siteaccesses-for-handling-translations). +Depending on the URI used to access the website, a different site opens, with a language set in configuration settings. +All content items are then displayed in this language. For details, see [Multi-language SiteAccesses](set_up_translation_siteaccess.md). ### Explicit translation SiteAccesses -Configuration is not mandatory, but can help to distinguish which SiteAccesses can be considered translation SiteAccesses. +Configuration isn't mandatory, but can help to distinguish which SiteAccesses can be considered translation SiteAccesses. ``` yaml ibexa: @@ -89,7 +106,7 @@ ibexa: !!! note - The top prioritized language is always used the SiteAccess language reference (e.g. `fre-FR` for `fre` SiteAccess in the example above). + The top prioritized language is always used the SiteAccess language reference (for example, `fre-FR` for `fre` SiteAccess in the example above). If several translation SiteAccesses share the same language reference, **the first declared SiteAccess always applies**. @@ -109,7 +126,8 @@ A locale *conversion map* example [can be found in `ibexa/core`, in `locale.yaml ### More complex translation setup -There are some cases where your SiteAccesses share settings (Repository, content settings, etc.), but you don't want all of them to share the same `translation_siteaccesses` setting. This can be for example the case when you use separate SiteAccesses for mobile versions of a website. +There are some cases where your SiteAccesses share settings (for example, repository or content settings), but you don't want all of them to share the same `translation_siteaccesses` setting. +This can be for example the case when you use separate SiteAccesses for mobile versions of a website. The solution is defining new groups: @@ -169,15 +187,20 @@ ibexa: ### Using implicit *related SiteAccesses* -If the `translation_siteaccesses` setting is not provided, implicit *related SiteAccesses* will be used instead. SiteAccesses are considered *related* if they share: +If the `translation_siteaccesses` setting isn't provided, implicit *related SiteAccesses* is used instead. +SiteAccesses are considered *related* if they share: -- The same Repository +- The same repository - The same root `location_id` (see [Multisite](multisite.md)) ### Fallback languages and missing translations -When setting up SiteAccesses with different language versions, you can specify a list of preset languages for each SiteAccess. When this SiteAccess is used, the system will go through this list. If a content item is unavailable in the first (prioritized) language, it will attempt to use the next language in the list, and so on. Thanks to this you can have a fallback in case of a lacking translation. +When setting up SiteAccesses with different language versions, you can specify a list of preset languages for each SiteAccess. +When this SiteAccess is used, the system goes through this list. +If a content item is unavailable in the first (prioritized) language, it attempts to use the next language in the list, and more. +Thanks to this you can have a fallback in case of a lacking translation. -You can also assign a Default content availability flag to content types (available in the Admin Panel). When this flag is assigned, content items of this type will be available even when they do not have a language version in any of the languages configured for the current SiteAccess. +You can also assign a Default content availability flag to content types (available in the **Admin** panel). +When this flag is assigned, content items of this type are available even when they don't have a language version in any of the languages configured for the current SiteAccess. -Note that if a language is not provided in the list of prioritized languages and it is not the content item's first language, the URL alias for this content in this language will not be generated. +If a language isn't provided in the list of prioritized languages and it's not the content item's first language, the URL alias for this content in this language isn't generated. diff --git a/docs/multisite/multisite.md b/docs/multisite/multisite.md index e454df2dda..7c310dda7f 100644 --- a/docs/multisite/multisite.md +++ b/docs/multisite/multisite.md @@ -1,5 +1,5 @@ --- -description: Multisite enables hosting multiple websites with different content, templates and configuration using one Repository. +description: Multisite enables hosting multiple websites with different content, templates and configuration by using one repository. page_type: landing_page --- diff --git a/docs/multisite/multisite_configuration.md b/docs/multisite/multisite_configuration.md index a1d62c0127..8a35200057 100644 --- a/docs/multisite/multisite_configuration.md +++ b/docs/multisite/multisite_configuration.md @@ -32,19 +32,17 @@ ibexa: event_group: [event] ``` -Groups are useful when you want to use common settings for several SiteAccesses and avoid duplicating configuration. +You can use groups when you want to use common settings for several SiteAccesses and avoid duplicating configuration. SiteAccess groups act like regular SiteAccesses as far as configuration is concerned. A SiteAccess can be part of several groups. SiteAccess configuration has always precedence over group configuration. #### `admin` SiteAccess -The predefined `admin` SiteAccess in `admin_group` (configured in `config/packages/ibexa_admin_ui.yaml`) serves the Back Office. -Do not remove this group. -If you need a multisite setup with multiple Back Offices, add any additional administration SiteAccesses to `admin_group`. +The predefined `admin` SiteAccess in `admin_group` (configured in `config/packages/ibexa_admin_ui.yaml`) serves the back office. +Don't remove this group. +If you need a multisite setup with multiple back offices, add any additional administration SiteAccesses to `admin_group`. -In cases where the sites are on separate databases, each needs its own [repository](repository_configuration.md) -(including their own storage and search connection), var dir, [cache pool](persistence_cache.md#persistence-cache-configuration), -and ideally also separate Varnish/Fastly configuration. +In cases where the sites are on separate databases, each needs its own [repository](repository_configuration.md) (including their own storage and search connection), var dir, [cache pool](persistence_cache.md#persistence-cache-configuration), and ideally also separate Varnish/Fastly configuration. !!! caution @@ -64,7 +62,8 @@ ibexa: ### SiteAccess matching The `match` setting defines the rule or set of rules by which SiteAccesses are matched. -See [SiteAccess matching](siteaccess_matching.md) for more information. + +For more information, see [SiteAccess matching](siteaccess_matching.md). ``` yaml ibexa: @@ -75,13 +74,11 @@ ibexa: ### SiteAccess name -To create a better editorial experience, you can replace the SiteAccess code in the Back Office -with a human-readable name of the website, for example `Company site` or `Summer Sale`. +To create a better editorial experience, you can replace the SiteAccess code in the back office with a human-readable name of the website, for example `Company site` or `Summer Sale`. -You can also translate SiteAccess names. Displayed names depend on the current Back Office language. +You can also translate SiteAccess names. Displayed names depend on the current back office language. -To define translations or SiteAccess names, place them in YAML file with correct language code, -for example `translations/ibexa_siteaccess.en.yaml`: +To define translations or SiteAccess names, place them in YAML file with correct language code, for example `translations/ibexa_siteaccess.en.yaml`: ``` yaml en: Company site @@ -100,7 +97,7 @@ The available scopes are: 4. `default` `global` overrides all other scopes. -If `global` is not defined, the configuration then tries to match a SiteAccess, and then a SiteAccess group. +If `global` isn't defined, the configuration then tries to match a SiteAccess, and then a SiteAccess group. Finally, if no other scope is matched, `default` is applied. In short: if you want a match that always applies, regardless of SiteAccesses, use `global`. @@ -119,9 +116,8 @@ ibexa: # This value is only used if there is no setting for global scope, SiteAccess or SiteAccess group ``` -`global` and `default` scopes include the `admin` SiteAccess, which is responsible for the Back Office. -For example, the following configuration defines both the front template for articles -and the template used in the Back Office, unless you configure other templates for a specific SiteAccess or SiteAccess group: +`global` and `default` scopes include the `admin` SiteAccess, which is responsible for the back office. +For example, the following configuration defines both the front template for articles and the template used in the back office, unless you configure other templates for a specific SiteAccess or SiteAccess group: ``` yaml ibexa: @@ -150,7 +146,7 @@ ibexa: siteaccess_list: [site, de] ``` -If you are using multiple domains, list all domains for an admin SiteAccess under `siteaccess_hosts`: +If you're using multiple domains, list all domains for an admin SiteAccess under `siteaccess_hosts`: ``` yaml ibexa: @@ -165,19 +161,19 @@ ibexa: !!! caution "SiteAccess with separate admin domain" - If an admin SiteAccess in your installation uses a different domain than the front SiteAccesses, - be sure to use SSL (https protocol). - Otherwise, you cannot preview content in Page Builder from the Back Office. + If an admin SiteAccess in your installation uses a different domain than the front SiteAccesses, be sure to use SSL (https protocol). + Otherwise, you cannot preview content in Page Builder from the back office. #### SiteAccess switching in Page Builder -If you need to change between SiteAccesses in Site mode, do not use any functions in the page itself (for example, a language switcher). -This may cause unexpected errors. Instead, switch between SiteAccesses using the SiteAccess bar above the page. +If you need to change between SiteAccesses in Site mode, don't use any functions in the page itself (for example, a language switcher). +This may cause unexpected errors. +Instead, switch between SiteAccesses with the SiteAccess bar above the page. ## Location tree You can restrict SiteAccesses to different parts of the content tree. -When you do it, only the selected Location and its descendants are reachable from this SiteAccess. +When you do it, only the selected location and its descendants are reachable from this SiteAccess. Configure this under the `ibexa.systems..content.tree_root` [configuration key](configuration.md#configuration-files), for example: @@ -192,15 +188,14 @@ ibexa: index_page: /EventFrontPage ``` -- `location_id` defines the Location ID of the content root for the SiteAccess. -- `excluded_uri_prefixes` defines which URIs ignore the root limit set using `location_id`. -In the example above, the Media and Images folders are accessible using their own URI, -even though they are outside the Location provided in `content.tree_root.location_id`. +- `location_id` defines the location ID of the content root for the SiteAccess. +- `excluded_uri_prefixes` defines which URIs ignore the root limit set by using `location_id`. +In the example above, to access the Media and Images folders, you can use their own URI, even though they're outside the location provided in `content.tree_root.location_id`. - `index_page` is the page shown when you access the root index `/`. !!! note - - Prefixes are not case sensitive. + + Prefixes aren't case sensitive. Leading slashes (`/`) are automatically trimmed internally, so they can be ignored. !!! tip diff --git a/docs/multisite/set_up_campaign_siteaccess.md b/docs/multisite/set_up_campaign_siteaccess.md index e6fb687e21..83030c9056 100644 --- a/docs/multisite/set_up_campaign_siteaccess.md +++ b/docs/multisite/set_up_campaign_siteaccess.md @@ -11,8 +11,7 @@ The `campaign` site uses a different part of the content tree than the main site ## Configure SiteAccesses -First, in SiteAccess configuration, add the `campaign` SiteAccess -to the list under the `ibexa.siteaccess` [configuration key](configuration.md#configuration-files): +First, in SiteAccess configuration, add the `campaign` SiteAccess to the list under the `ibexa.siteaccess` [configuration key](configuration.md#configuration-files): ``` yaml ibexa: @@ -27,8 +26,7 @@ ibexa: site: site ``` -The `match` setting ensures that when a visitor accesses the `/summer-sale` URI, -they see the `campaign` SiteAccess. +The `match` setting ensures that when a visitor accesses the `/summer-sale` URI, they see the `campaign` SiteAccess. ## Set root folder @@ -48,13 +46,12 @@ ibexa: location_id: 57 ``` -Thanks to this configuration, you can access `/campaign/Articles/Article2`, -but not `/campaign/General/Articles/Article1`. +Thanks to this configuration, you can access `/campaign/Articles/Article2`, but not `/campaign/General/Articles/Article1`. ## Reuse content Finally, reuse some content between sites, for example "Logos" from "Images/Media". -You can allow the `campaign` site to access them, even though they are in a different part of the tree, via `excluded_uri_prefixes`: +You can allow the `campaign` site to access them, even though they're in a different part of the tree, via `excluded_uri_prefixes`: ``` yaml ibexa: @@ -66,8 +63,6 @@ ibexa: excluded_uri_prefixes: [ /media/images/logos ] ``` -Now, when you use the `campaign` SiteAccess, you can reach `/campaign/Media/Images/Logos`, -despite the fact that it is not a sub-item of the "Campaign" Location. +Now, when you use the `campaign` SiteAccess, you can reach `/campaign/Media/Images/Logos`, despite the fact that it's not a sub-item of the "Campaign" location. -As a next step, you can configure different [designs](design_engine.md) -for the two SiteAccesses. +As a next step, you can configure different [designs](design_engine.md) for the two SiteAccesses. diff --git a/docs/multisite/set_up_translation_siteaccess.md b/docs/multisite/set_up_translation_siteaccess.md index 04f8756ccf..ef471c792c 100644 --- a/docs/multisite/set_up_translation_siteaccess.md +++ b/docs/multisite/set_up_translation_siteaccess.md @@ -16,7 +16,7 @@ First, add a new language for the whole installation. For more details, see [Languages](languages.md). -1. In the Back Office, go to **Admin** -> **Languages**. +1. In the back office, go to **Admin** -> **Languages**. 1. Click **Create a new language** and provide the language name and code (examples below use French with `fre-FR`). 1. After creating the new language, refresh the assets by running: @@ -28,8 +28,7 @@ yarn encore Next, configure a new SiteAccess to match the newly-configured language. -The most typical setup for a site with translated content is to map the base of the domain to one language -and use the first segment of the URI to match to translations. +The most typical setup for a site with translated content is to map the base of the domain to one language and use the first segment of the URI to match to translations. For example: @@ -38,7 +37,7 @@ For example: To achieve this you need to create a new SiteAccess in configuration under the `ibexa.siteaccesses` [configuration key](configuration.md#configuration-files). Add the `fr` SiteAccess to list of all SiteAccesses and it to the common `site_group`. -This group is used for sharing settings such as API keys, cache locations and so on. +This group is used for sharing settings such as API keys, cache locations, and more. ``` yaml ibexa: @@ -49,7 +48,7 @@ ibexa: ``` Under the `ibexa.system` key, add the new SiteAccess. -Indicate that they are meant for translations under `site_group.translation_siteaccesses`: +Indicate that they're meant for translations under `site_group.translation_siteaccesses`: ``` yaml ibexa: @@ -64,20 +63,19 @@ ibexa: ``` With this configuration, the main English site displays content in English and ignores French content. -The French site displays content in French, but also in English, if it does not exist in French. +The French site displays content in French, but also in English, if it doesn't exist in French. Clear the cache by running: `php bin/console cache:clear`. ## Set permissions -By default, the Anonymous user Role does not have permissions for new SiteAccesses. +By default, the Anonymous user role doesn't have permissions for new SiteAccesses. As a next step, allow Anonymous users to read content on the new SiteAccesses: -1. In the Back Office, go to **Admin** -> **Roles**. +1. In the back office, go to **Admin** -> **Roles**. 1. Click the **Anonymous** role. 1. Edit the **Limitations** of the module `user`, select both SiteAccesses and click **Update**. 1. Clear the cache by running: `php bin/console cache:clear`. You can now start translating content. -When you reload the site, access a translated content item through both SiteAccesses to see the difference, -for example: `/` and `/fr/`. +When you reload the site, access a translated content item through both SiteAccesses to see the difference, for example: `/` and `/fr/`. diff --git a/docs/multisite/site_factory/site_factory.md b/docs/multisite/site_factory/site_factory.md index 4863d9897a..84fe97184b 100644 --- a/docs/multisite/site_factory/site_factory.md +++ b/docs/multisite/site_factory/site_factory.md @@ -1,24 +1,22 @@ --- -description: Site Factory allows creating multiple sites (SiteAccesses) from the Back Office. +description: Site Factory allows creating multiple sites (SiteAccesses) from the back office. edition: experience --- # Site Factory -Site Factory is a site management interface, integrated with the Back Office. +Site Factory is a site management interface, integrated with the back office. It enables you to configure new sites without editing [YAML-based SiteAccess configuration](multisite_configuration.md). !!! note - A SiteAccess that you define for a site by following the [configuration](multisite_configuration.md) - is always treated with higher priority than a SiteAccess created by using the Site Factory. - For example, if you define a French site within a YAML file, - and then create a site that uses the `fr` path in Site Factory, matchers ignore the second site. + A SiteAccess that you define for a site by following the [configuration](multisite_configuration.md) is always treated with higher priority than a SiteAccess created by using the Site Factory. + For example, if you define a French site within a YAML file, and then create a site that uses the `fr` path in Site Factory, matchers ignore the second site. Site Factory is disabled by default after installation. If you plan to use Site Factory, you need to enable and configure it. -To enable or disable Site Factory, follow respectively: +To enable or disable Site Factory, follow: - [Enable Site Factory section](#enable-site-factory) - [Disable Site Factory section](#disable-site-factory) @@ -29,11 +27,11 @@ To enable Site Factory, set the `ibexa_site_factory.enabled` [configuration key] ### Configure designs -Next, configure Site Factory by adding empty SiteAccess groups. At least one empty group is required. +Next, configure Site Factory by adding empty SiteAccess groups. +At least one empty group is required. The number of empty SiteAccess groups must be equal to the number of templates that you want to have when you create the new site. -In this example, you add two SiteAccess groups (`example_site_factory_group_1` and `example_site_factory_group_2`) -that correspond to the two templates (`site1` and `site2`) that you add in the next step. +In this example, you add two SiteAccess groups (`example_site_factory_group_1` and `example_site_factory_group_2`) that correspond to the two templates (`site1` and `site2`) that you add in the next step. Add the groups under the `ibexa.siteaccess` [configuration key](configuration.md#configuration-files): @@ -100,7 +98,7 @@ ibexa_site_factory: thumbnail: /path/to/image/example-thumbnail_2.png ``` -You can check the results of your work in the Back Office by going to **Site management** and selecting **Sites**. +You can check the results of your work in the back office by going to **Site management** and selecting **Sites**. There, you should be able to add a new site and choose a design for it. @@ -111,7 +109,7 @@ To be able to see your site online, you need to define a domain for it. !!! caution "Define domain for production environment" These steps are for `dev` environment only. - If you want to define domains in production environment, you will need to configure Apache or Nginx by yourself. + If you want to define domains in production environment, you need to configure Apache or Nginx by yourself. In the `.env` file change line 2 to: `COMPOSE_FILE=doc/docker/base-dev.yml:doc/docker/multihost.yml` @@ -144,7 +142,7 @@ Then, run `docker-compose up`: ```bash export COMPOSE_FILE="doc/docker/base-dev.yml:doc/docker/multihost.yml" docker-compose up -``` +``` Your sites should be now visible under: @@ -157,7 +155,7 @@ Your sites should be now visible under: ### Define site directory -You can adjust the place where the directory of the new site is created (Location with ID 2 by default). +You can adjust the place where the directory of the new site is created (location with ID 2 by default). To do it, go to configuration files and under the `ibexa.system..site_factory` [configuration key](configuration.md#configuration-files) add the following parameter: ``` yaml @@ -168,13 +166,13 @@ ibexa: sites_location_id: 42 ``` -Now, all new directories are created under "Ibexa DXP". +Now, all new directories are created under "[[= product_name =]]". ### Provide access -The Site Factory is set up, now you can provide sufficient permissions to the Users. +The Site Factory is set up, now you can provide sufficient permissions to the users. -Set the below Policies to allow Users to: +Set the below policies to allow users to: - `site/view` - enter the Site Factory interface - `site/create` - create sites @@ -182,9 +180,9 @@ Set the below Policies to allow Users to: - `site/change_status` - change status of the public accesses to `Live` or `Offline` - `site/delete` - delete sites -For full documentation on how Permissions work and how to set them up, see [the Permissions section](permissions.md). +For full documentation on how permissions work and how to set them up, see [the permissions section](permissions.md). -To learn how to use Site Factory, see [User documentation]([[= user_doc =]]/site_organization/site_factory/). +To learn how to use Site Factory, see [User Documentation]([[= user_doc =]]/site_organization/site_factory/). ## Disable Site Factory @@ -194,11 +192,11 @@ Enabled Site Factory may cause following performance issues: - Site Factory matchers are connected to the database in search for new SiteAccesses You can disable Site Factory to boost ConfigResolver performance. -Keep in mind that with disabled Site Factory you are unable to add new sites or use existing ones. +Keep in mind that with disabled Site Factory you're unable to add new sites or use existing ones. 1\. In `config/packages/ibexa_site_factory.yaml` change `enabled` to `false`. -2\. In `config/packages/ibexa.yaml` comment the `ibexa.siteaccess.match: '@Ibexa\SiteFactory\SiteAccessMatcher': ~` if it is uncommented. +2\. In `config/packages/ibexa.yaml` comment the `ibexa.siteaccess.match: '@Ibexa\SiteFactory\SiteAccessMatcher': ~` if it's uncommented. 3\. Remove separate connection to database in `config/packages/doctrine.yaml`. diff --git a/docs/multisite/site_factory/site_factory_configuration.md b/docs/multisite/site_factory/site_factory_configuration.md index 0c1861600c..63dc004337 100644 --- a/docs/multisite/site_factory/site_factory_configuration.md +++ b/docs/multisite/site_factory/site_factory_configuration.md @@ -5,15 +5,14 @@ edition: experience # Site Factory configuration -## Parent Location +## Parent location -When working with the [Site Factory](site_factory.md), you can define the parent -Location for a new site in the configuration. -Each new site is created in the designated Location. +When working with the [Site Factory](site_factory.md), you can define the parent location for a new site in the configuration. +Each new site is created in the designated location. -To define a parent Location, add a new configuration key to the site template definition. -Each template is assigned to its own Location. -This can be either a Location ID (for example, `62`), or a recommended remote Location ID (for example, `1548b8cd8dd4c6b5082e566615d45e91`). +To define a parent location, add a new configuration key to the site template definition. +Each template is assigned to its own location. +This can be either a location ID (for example, `62`), or a recommended remote location ID (for example, `1548b8cd8dd4c6b5082e566615d45e91`). Add the configuration key to your template under the `ibexa_site_factory` [configuration key](configuration.md#configuration-files): @@ -32,13 +31,13 @@ ibexa_site_factory: parent_location_remote_id: 1548b8cd8dd4c6b5082e566615d45e91 ``` -Now, you can see the path to the new site's parent Location under design selection. -If you have sufficient permissions, you can change the defined Location during site creation. -If the parent Location is not defined, you have to choose it from Universal Discovery Widget. +Now, you can see the path to the new site's parent location under design selection. +If you have sufficient permissions, you can change the defined location during site creation. +If the parent location isn't defined, you have to choose it from Universal Discovery Widget. ## Site skeletons -The Site skeleton enables you to copy an entire content structure of the site design to the defined Location. +The Site skeleton enables you to copy an entire content structure of the site design to the defined location. Site skeleton copying is a one-off operation, it only happens during the site creation process. After that, you cannot copy the Site skeleton again, for example in the edit view. @@ -46,10 +45,10 @@ After that, you cannot copy the Site skeleton again, for example in the edit vie You can create as many skeletons as you need and assign them to templates. Remember that one template can only have one Site skeleton. -If the design does not have a defined Site skeleton, a directory of the new site is created in a standard Site Factory process. +If the design doesn't have a defined Site skeleton, a directory of the new site is created in a standard Site Factory process. To define a Site skeleton, add the `site_skeleton_id` or `site_skeleton_remote_id` key to the site template definition. -This can be either a Location ID (e.g. `5966`), or a remote Location ID (e.g. `3bed95afb1f8126f06a3c464e461e1ae66`). +This can be either a location ID (for example, `5966`), or a remote location ID (for example, `3bed95afb1f8126f06a3c464e461e1ae66`). ``` yaml hl_lines="7 12" ibexa_site_factory: @@ -68,16 +67,15 @@ ibexa_site_factory: Now, you can choose a design with a defined Site skeleton, and decide if you want to use its skeleton by toggling **Generate site using site skeleton**. -## User Group skeletons +## User group skeletons -With User Group skeletons you can define Policies and Limitations that apply to selected groups of users who can access the site. +With user group skeletons you can define policies and limitations that apply to selected groups of users who can access the site. -You can create many User Group skeletons and associate them with many templates. -One template can have many User Group skeletons assigned. +You can create many user group skeletons and associate them with many templates. +One template can have many user group skeletons assigned. -To create a User Group skeleton, first go to **Admin** -> **Site skeletons** and add a User Group to the list of available skeletons. -Then, review the detailed information of the newly created User Group skeleton, -copy the Location ID or the Location remote ID, and add a configuration key to the site template definition: +To create a user group skeleton, first go to **Admin** -> **Site skeletons** and add a user group to the list of available skeletons. +Then, review the detailed information of the newly created user group skeleton, copy the location ID or the Location remote ID, and add a configuration key to the site template definition: ``` yaml ibexa_site_factory: @@ -88,20 +86,19 @@ ibexa_site_factory: user_group_skeleton_remote_ids: [ , , ... ] ``` -Manage the permissions associated to the User Group skeleton by [assigning Roles](https://doc.ibexa.co/projects/userguide/en/latest/site_organization/organizing_the_site/#managing-permissions). -Make sure that the Roles that you assign to the User Group skeleton do not contain Location-based Limitations. -User Group skeletons cannot contain individual User content items either. +Manage the permissions associated to the user group skeleton by [assigning roles](https://doc.ibexa.co/projects/userguide/en/latest/site_organization/organizing_the_site/#managing-permissions). +Make sure that the roles that you assign to the user group skeleton don't contain location-based limitations. +User group skeletons cannot contain individual user content items either. -User Group skeletons are retained after deleting the site. +User group skeletons are retained after deleting the site. -## Automatic update of Roles +## Automatic update of roles -Role definitions can contain user/login Policies with Limitations that limit user access to certain sites. -To avoid the need to add the new SiteAccess to Limitations for all Roles, -you can decide that the Roles you select are automatically updated when the site is created, updated or deleted. +Role definitions can contain user/login policies with limitations that limit user access to certain sites. +To avoid the need to add the new SiteAccess to limitations for all roles, +you can decide that the roles you select are automatically updated when the site is created, updated, or deleted. -Under the `ibexa_site_factory` [configuration key](configuration.md#configuration-files), add a list of Roles which should have access to the frontend -when a site is created in Site Factory, for example: +Under the `ibexa_site_factory` [configuration key](configuration.md#configuration-files), add a list of roles which should have access to the frontend when a site is created in Site Factory, for example: ``` yaml ibexa_site_factory: @@ -110,4 +107,4 @@ ibexa_site_factory: update_roles: [Anonymous, Administrator] ``` -For more information about Roles and Policies, see [Permissions](permissions.md). +For more information about roles and policies, see [Permissions](permissions.md). diff --git a/docs/multisite/siteaccess/siteaccess_aware_configuration.md b/docs/multisite/siteaccess/siteaccess_aware_configuration.md index 32a0f38933..b2e73ac072 100644 --- a/docs/multisite/siteaccess/siteaccess_aware_configuration.md +++ b/docs/multisite/siteaccess/siteaccess_aware_configuration.md @@ -5,14 +5,13 @@ description: Make sure your custom development's configuration can be used with # SiteAccess-aware configuration The [Symfony Config component]([[= symfony_doc =]]/components/config.html) makes it possible to define semantic configuration, exposed to the end developer. -This configuration is validated by rules you define, e.g. validating type (string, array, integer, boolean and so on). -Usually, after it is validated and processed, this semantic configuration is then mapped to internal *key/value* parameters stored in the service container. +This configuration is validated by rules you define, for example, validating type (string, array, integer, boolean, and more). +Usually, after it's validated and processed, this semantic configuration is then mapped to internal *key/value* parameters stored in the service container. [[= product_name =]] uses this for its core configuration, but adds another configuration level, the SiteAccess. For each defined SiteAccess, you need to be able to use the same configuration tree to define SiteAccess-specific config. -These settings then need to be mapped to SiteAccess-aware internal parameters -that you can retrieve with the [ConfigResolver](dynamic_configuration.md#configresolver). +These settings then need to be mapped to SiteAccess-aware internal parameters that you can retrieve with the [ConfigResolver](dynamic_configuration.md#configresolver). For this, internal keys need to follow the format `..`. where: - `namespace` is specific to your app or bundle @@ -23,10 +22,9 @@ For more information about the ConfigResolver, namespaces and scopes, see [confi !!! tip "Repository-aware configuration" - If you need to use different settings per Repository, not per SiteAccess, - see [Repository-aware configuration](repository_configuration.md#repository-aware-configuration). + If you need to use different settings per repository, not per SiteAccess, see [Repository-aware configuration](repository_configuration.md#repository-aware-configuration). -The example below assumes you are using an `Acme\ExampleBundle`. +The example below assumes you're using an `Acme\ExampleBundle`. Remember to register the bundle by adding it to `config/bundles.php`: ``` php @@ -35,9 +33,7 @@ Acme\ExampleBundle\AcmeExampleBundle::class => ['all' => true], ### Parsing semantic configuration -To parse semantic configuration, create a `Configuration` class which extends -`Ibexa\Bundle\Core\DependencyInjection\Configuration\SiteAccessAware\Configuration` -and then extend its `generateScopeBaseNode()` method: +To parse semantic configuration, create a `Configuration` class which extends `Ibexa\Bundle\Core\DependencyInjection\Configuration\SiteAccessAware\Configuration` and then extend its `generateScopeBaseNode()` method: ``` php hl_lines="17" mapConfigArray('custom_setting', $config); } } @@ -170,9 +166,9 @@ parameters: #### Merging hash values between scopes -When you define a hash as semantic config, you sometimes do not want the SiteAccess settings to replace the default or group values, -but enrich them by appending new entries. This is possible by using `$processor->mapConfigArray()`, -which you must call outside the closure (before or after), so that it is called only once. +When you define a hash as semantic config, you sometimes don't want the SiteAccess settings to replace the default or group values, +but enrich them by appending new entries. +This is possible by using `$processor->mapConfigArray()`, which you must call outside the closure (before or after), so that it's called only once. ``` php $processor->mapConfigArray('custom_setting', $config); @@ -209,8 +205,7 @@ acme_example: language: javascript ``` -By calling `mapConfigArray()` you can get the following end configuration, -where keys defined for `custom_setting` in default/group/SiteAccess scopes are merged: +By calling `mapConfigArray()` you can get the following end configuration, where keys defined for `custom_setting` in default/group/SiteAccess scopes are merged: ``` yaml parameters: @@ -225,11 +220,9 @@ parameters: ##### Merging from second level In the example above, entries were merged in respect to the scope order of precedence. -However, because you defined the `os_types` key for `siteaccess1`, it completely overrode the default value, -because the merge process is done only at the first level. +However, because you defined the `os_types` key for `siteaccess1`, it completely overrode the default value, because the merge process is done only at the first level. -You can add another level by passing `ContextualizerInterface::MERGE_FROM_SECOND_LEVEL` -as the third argument to `$contextualizer->mapConfigArray()`: +You can add another level by passing `ContextualizerInterface::MERGE_FROM_SECOND_LEVEL` as the third argument to `$contextualizer->mapConfigArray()`: ``` php $contextualizer->mapConfigArray('custom_setting', $config, ContextualizerInterface::MERGE_FROM_SECOND_LEVEL); @@ -247,24 +240,22 @@ parameters: language: javascript ``` -There is also another option, `ContextualizerInterface::UNIQUE`, -that ensures the array setting has unique values. It only works on normal arrays, not hashes. +There is also another option, `ContextualizerInterface::UNIQUE`, that ensures the array setting has unique values. +It only works on normal arrays, not hashes. !!! note - Merge is not recursive. Only second level merge is possible by using `ContextualizerInterface::MERGE_FROM_SECOND_LEVEL` option. + Merge isn't recursive. Only second level merge is possible by using `ContextualizerInterface::MERGE_FROM_SECOND_LEVEL` option. ### Dedicated mapper object Instead of passing a callable to `$processor->mapConfig()`, you can pass an instance of `Ibexa\Bundle\Core\DependencyInjection\Configuration\SiteAccessAware\ConfigurationMapperInterface`. -This can be useful if you have a lot of configuration to map and do not want to pollute -your service container extension class (it is better for maintenance). +This can be useful if you have a lot of configuration to map and don't want to pollute your service container extension class (it's better for maintenance). #### Merging hash values between scopes You should not use `$contextualizer->mapConfigArray()` within the scope loop, like for simple values. When using a closure/callable, you usually call it before or after `$processor->mapConfig()`. -For mapper objects, you can use a dedicated interface: `HookableConfigurationMapperInterface`, -which defines two methods: `preMap()` and `postMap()`. +For mapper objects, you can use a dedicated interface: `HookableConfigurationMapperInterface`, which defines two methods: `preMap()` and `postMap()`. diff --git a/docs/multisite/siteaccess/siteaccess_matching.md b/docs/multisite/siteaccess/siteaccess_matching.md index 708d77700f..a6c32c2f2c 100644 --- a/docs/multisite/siteaccess/siteaccess_matching.md +++ b/docs/multisite/siteaccess/siteaccess_matching.md @@ -25,7 +25,8 @@ ibexa: `ibexa.siteaccess.match` can contain multiple matchers. -The first matcher succeeding always wins, so be careful when using catch-all matchers like `URIElement`. In the following example, `Compound\LogicalAnd` is placed before the `Map\Host` for `my.site/corporate` to be reachable: +The first matcher succeeding always wins, so be careful when using catch-all matchers like `URIElement`. +In the following example, `Compound\LogicalAnd` is placed before the `Map\Host` for `my.site/corporate` to be reachable: ```yaml ibexa: @@ -43,11 +44,9 @@ ibexa: my.site: mysite ``` -If the matcher class does not start with a backslash (`\`), it is relative to `Ibexa\Core\MVC\Symfony\SiteAccess\Matcher` -(for example, `Map\URI` refers to `Ibexa\Core\MVC\Symfony\SiteAccess\Matcher\Map\URI`) +If the matcher class doesn't start with a backslash (`\`), it's relative to `Ibexa\Core\MVC\Symfony\SiteAccess\Matcher` (for example, `Map\URI` refers to `Ibexa\Core\MVC\Symfony\SiteAccess\Matcher\Map\URI`) -You can specify [custom matchers](#custom-matchers) by using a fully qualified class name (e.g. `\My\SiteAccess\Matcher`) -or a service identifier (e.g. `@my_matcher_service`). +You can specify [custom matchers](#custom-matchers) by using a fully qualified class name (for example, `\My\SiteAccess\Matcher`) or a service identifier (for example, `@my_matcher_service`). In the case of a fully qualified class name, the matching configuration is passed in the constructor. In the case of a service, it must implement `Ibexa\Bundle\Core\SiteAccess\Matcher`. The matching configuration is passed to `setMatchingConfiguration()`. @@ -150,8 +149,7 @@ Example host name `www.page.com` matches SiteAccess `event`. !!! note - If you encounter problems with the `Map\Host` matcher, make sure that your installation is - [properly configured to use token-based authentication](ez_platform_v2.4.md#update-ez-enterprise-v24-to-v242). + If you encounter problems with the `Map\Host` matcher, make sure that your installation is [properly configured to use token-based authentication](ez_platform_v2.4.md#update-ez-enterprise-v24-to-v242). ### `Map\URI` @@ -190,7 +188,7 @@ Example URL `http://my_site.com:8080/content` matches SiteAccess `site`. ### `Ibexa\SiteFactory\SiteAccessMatcher` [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] Enables the use of [Site Factory](site_factory.md). -Does not take any parameters in configuration: +Doesn't take any parameters in configuration: ``` yaml ibexa: @@ -214,9 +212,7 @@ ibexa: '@App\Matcher\MySiteaccessMatcher': ~ ``` -The service must be tagged with `ibexa.site_access.matcher` -and must implement `Ibexa\Bundle\Core\SiteAccess\Matcher` -(and `Ibexa\Core\MVC\Symfony\SiteAccess\VersatileMatcher` if you want to use compound logical matchers). +The service must be tagged with `ibexa.site_access.matcher` and must implement `Ibexa\Bundle\Core\SiteAccess\Matcher` (and `Ibexa\Core\MVC\Symfony\SiteAccess\VersatileMatcher` if you want to use compound logical matchers). ## Combining SiteAccess matchers @@ -294,7 +290,7 @@ You can define this environment variable directly in web server configuration: !!! tip You can configure the variable by using the PHP-FPM configuration file. - See [PHP-FPM documentation](https://www.php.net/manual/en/install.fpm.configuration.php#example-25) for more information. + For more information, see [PHP-FPM documentation](https://www.php.net/manual/en/install.fpm.configuration.php#example-25). !!! note "Precedence" diff --git a/docs/permissions/custom_policies.md b/docs/permissions/custom_policies.md index 9a3b368d83..25481d977b 100644 --- a/docs/permissions/custom_policies.md +++ b/docs/permissions/custom_policies.md @@ -1,24 +1,24 @@ --- -description: Create a custom Policy to cover non-standard permission needs. +description: Create a custom policy to cover non-standard permission needs. --- -# Custom Policies +# Custom policies -The content Repository uses [Roles and Policies](permissions.md) to give Users access to different functions of the system. +The content repository uses [roles and policies](permissions.md) to give users access to different functions of the system. -Any bundle can expose available Policies via a `PolicyProvider` which can be added to IbexaCoreBundle's [service container](php_api.md#service-container) extension. +Any bundle can expose available policies via a `PolicyProvider` which can be added to IbexaCoreBundle's [service container](php_api.md#service-container) extension. ## PolicyProvider -A `PolicyProvider` object provides a hash containing declared modules, functions and Limitations. +A `PolicyProvider` object provides a hash containing declared modules, functions and limitations. -- Each Policy provider provides a collection of permission *modules*. +- Each policy provider provides a collection of permission *modules*. - Each module can provide *functions* (for example, in `content/read`, "content" is the module, and "read" is the function) -- Each function can provide a collection of Limitations. +- Each function can provide a collection of limitations. -First level key is the module name which is limited to characters within the set `A-Za-z0-9_`, value is a hash of -available functions, with function name as key. Function value is an array of available Limitations, identified -by the alias declared in `LimitationType` service tag. If no Limitation is provided, value can be `null` or an empty array. +First level key is the module name which is limited to characters within the set `A-Za-z0-9_`, value is a hash of available functions, with function name as key. +Function value is an array of available limitations, identified by the alias declared in `LimitationType` service tag. +If no limitation is provided, value can be `null` or an empty array. ``` php [ @@ -34,7 +34,7 @@ by the alias declared in `LimitationType` service tag. If no Limitation is provi ``` Limitations need to be implemented as *Limitation types* and declared as services identified with `ibexa.permissions.limitation_type` tag. -Name provided in the hash for each Limitation is the same value set in the `alias` attribute in the service tag. +Name provided in the hash for each limitation is the same value set in the `alias` attribute in the service tag. For example: @@ -60,13 +60,11 @@ class MyPolicyProvider implements PolicyProviderInterface } ``` -!!! note "Extend existing Policies" +!!! note "Extend existing policies" - While a `PolicyProvider` may provide new functions to an existing Policy module, - or additional Limitations to an existing function, - it's however strongly recommended to create your own modules. + While a `PolicyProvider` may provide new functions to an existing policy module, or additional limitations to an existing function, it's however strongly recommended to create your own modules. - It's impossible to remove an existing module, function or limitation from a Policy. + It's impossible to remove an existing module, function or limitation from a policy. ### YamlPolicyProvider @@ -143,7 +141,7 @@ For a `PolicyProvider` to be active, you have to register it in the `src/Kernel. [[= include_file('code_samples/back_office/limitation/src/Kernel.php') =]] ``` -## Custom Limitation type +## Custom limitation type For a custom module function, you can use existing limitation types or create custom ones. @@ -172,11 +170,11 @@ services: [[= include_file('code_samples/back_office/limitation/config/append_to_services.yaml', 1, 4) =]] ``` -### Custom Limitation type form +### Custom limitation type form #### Form mapper -To provide support for editing custom policies in the Back Office, you need to implement [`Ibexa\AdminUi\Limitation\LimitationFormMapperInterface`](https://github.com/ibexa/admin-ui/blob/4.5/src/lib/Limitation/LimitationFormMapperInterface.php). +To provide support for editing custom policies in the back office, you need to implement [`Ibexa\AdminUi\Limitation\LimitationFormMapperInterface`](https://github.com/ibexa/admin-ui/blob/4.5/src/lib/Limitation/LimitationFormMapperInterface.php). - `mapLimitationForm` adds the limitation field as a child to a provided Symfony form. - `getFormTemplate` returns the path to the template to use for rendering the limitation form. Here it use [`form_label`]([[= symfony_doc =]]/form/form_customization.html#reference-forms-twig-label) and [`form_widget`]([[= symfony_doc =]]/form/form_customization.html#reference-forms-twig-widget) to do so. @@ -192,7 +190,7 @@ Provide a template corresponding to `getFormTemplate`. [[= include_file('code_samples/back_office/limitation/templates/themes/admin/limitation/custom_limitation_form.html.twig') =]] ``` -Next, register the service with the `ibexa.admin_ui.limitation.mapper.form` tag and set the `limitationType` attribute to the Limitation type's identifier: +Next, register the service with the `ibexa.admin_ui.limitation.mapper.form` tag and set the `limitationType` attribute to the limitation type's identifier: ``` yaml [[= include_file('code_samples/back_office/limitation/config/append_to_services.yaml', 5, 8) =]] @@ -200,32 +198,32 @@ Next, register the service with the `ibexa.admin_ui.limitation.mapper.form` tag #### Notable form mappers to extend -Some abstract Limitation type form mapper classes are provided to help implementing common complex Limitations. +Some abstract limitation type form mapper classes are provided to help implementing common complex limitations. -- `MultipleSelectionBasedMapper` is a mapper used to build forms for Limitations based on a checkbox list, where multiple items can be chosen. For example, it's used to build forms for [Content Type Limitation](limitation_reference.md#content-type-limitation), [Language Limitation](limitation_reference.md#language-limitation) or [Section Limitation](limitation_reference.md#section-limitation). -- `UDWBasedMapper` is used to build a Limitation form where a Content/Location must be selected. For example, it's used by the [Subtree Limitation](limitation_reference.md#subtree-limitation) form. +- `MultipleSelectionBasedMapper` is a mapper used to build forms for limitations based on a checkbox list, where multiple items can be chosen. For example, it's used to build forms for [Content Type Limitation](limitation_reference.md#content-type-limitation), [Language Limitation](limitation_reference.md#language-limitation) or [Section Limitation](limitation_reference.md#section-limitation). +- `UDWBasedMapper` is used to build a limitation form where a content/location must be selected. For example, it's used by the [Subtree Limitation](limitation_reference.md#subtree-limitation) form. #### Value mapper -By default, without a value mapper, the Limitation value is rendered by using the block `ez_limitation_value_fallback` of the template [`vendor/ibexa/admin-ui/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig`](https://github.com/ibexa/admin-ui/blob/4.5/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig#L1-L6). +By default, without a value mapper, the limitation value is rendered by using the block `ez_limitation_value_fallback` of the template [`vendor/ibexa/admin-ui/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig`](https://github.com/ibexa/admin-ui/blob/4.5/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig#L1-L6). -To customize the rendering, a value mapper eventually transforms the Limitation value and sends it to a custom template. +To customize the rendering, a value mapper eventually transforms the limitation value and sends it to a custom template. The value mapper implements [`Ibexa\AdminUi\Limitation\LimitationValueMapperInterface`](https://github.com/ibexa/admin-ui/blob/4.5/src/lib/Limitation/LimitationValueMapperInterface.php). -Its `mapLimitationValue` function returns the Limitation value transformed for the needs of the template. +Its `mapLimitationValue` function returns the limitation value transformed for the needs of the template. ``` php [[= include_file('code_samples/back_office/limitation/src/Security/Limitation/Mapper/CustomLimitationValueMapper.php') =]] ``` -Then register the service with the `ibexa.admin_ui.limitation.mapper.value` tag and set the `limitationType` attribute to Limitation type's identifier: +Then register the service with the `ibexa.admin_ui.limitation.mapper.value` tag and set the `limitationType` attribute to limitation type's identifier: ``` yaml [[= include_file('code_samples/back_office/limitation/config/append_to_services.yaml', 9, 12) =]] ``` -When a value mapper exists for a Limitation, the rendering uses a Twig block named `ez_limitation__value` where `` is the Limitation identifier in lower case. +When a value mapper exists for a limitation, the rendering uses a Twig block named `ez_limitation__value` where `` is the limitation identifier in lower case. In this example, block name is `ez_limitation_customlimitation_value` as the identifier is `CustomLimitation`. This template receives a `values` variable which is the return of the `mapLimitationValue` function from the corresponding value mapper. @@ -248,7 +246,7 @@ For example, `translations/ibexa_content_forms_policies.en.yaml`: [[= include_file('code_samples/back_office/limitation/translations/ibexa_content_forms_policies.en.yaml') =]] ``` -### Custom Limitation check +### Custom limitation check Check if current user has this custom limitation set to true from a custom controller: diff --git a/docs/permissions/limitation_reference.md b/docs/permissions/limitation_reference.md index f8c871c3ed..40bcc538fa 100644 --- a/docs/permissions/limitation_reference.md +++ b/docs/permissions/limitation_reference.md @@ -1,33 +1,31 @@ --- -description: Limitations let you fine-tune the permission system by specifying limits to Roles granted to users. +description: Limitations let you fine-tune the permission system by specifying limits to roles granted to users. page_type: reference --- # Limitation reference -## Blocking Limitation +## Blocking limitation -A generic Limitation type to use when no other Limitation has been implemented. -Without any Limitation assigned, a `LimitationNotFoundException` is thrown. +A generic limitation type to use when no other limitation has been implemented. +Without any limitation assigned, a `LimitationNotFoundException` is thrown. -It is called "blocking" because it always informs the permissions system that -the User does not have access to any Policy the Limitation is assigned to, making -the permissions system move on to the next Policy. +It's called "blocking" because it always informs the permissions system that the user doesn't have access to any policy the limitation is assigned to, making the permissions system move on to the next policy. ### Possible values |Value|UI value|Description| |------|------|------| -|``|``|This is a generic Limitation which does not validate the values provided to it. Make sure that you validate the values passed to this Limitation in your own logic.| +|``|``|This is a generic limitation which doesn't validate the values provided to it. Make sure that you validate the values passed to this limitation in your own logic.| ### Configuration -As this is a generic Limitation, you can configure your custom Limitations to use it. +As this is a generic limitation, you can configure your custom limitations to use it. Out of the box FunctionList uses it in the following way: ``` yaml # FunctionList is an ezjscore limitation, it only applies to ezjscore policies not used by - # API/platform stack, so configure to use Blocking Limitation to avoid LimitationNotFoundException + # API/platform stack, so configure to use Blocking limitation to avoid LimitationNotFoundException ibexa.api.role.limitation_type.function_list: class: Ibexa\Core\Limitation\BlockingLimitationType arguments: ['FunctionList'] @@ -35,28 +33,28 @@ Out of the box FunctionList uses it in the following way: - {name: ibexa.permissions.limitation_type, alias: FunctionList} ``` -## ActivityLogOwner Limitation +## ActivityLogOwner limitation -The `ActivityLogOwner` Limitation specifies if a user can see only their own [recent activity](recent_activity.md) log entries, and not entries from other users. +The `ActivityLogOwner` limitation specifies if a user can see only their own [recent activity](recent_activity.md) log entries, and not entries from other users. | Value | UI value | Description | |-------|-----------------|--------------------------------------------------------------| | `1` | "Only own logs" | Current user can only access their own activity log entries. | -## CartOwner Limitation +## CartOwner limitation -The `CartOwner` Limitation specifies whether the user can modify a cart. +The `CartOwner` limitation specifies whether the user can modify a cart. ### Possible values |Value|UI value|Description| |------|------|------| -|"self"|"self"|Only the User who is the owner of the cart gets access.| +|"self"|"self"|Only the user who is the owner of the cart gets access.| |`null`| none |User can access all carts.| -## Change Owner Limitation +## Change Owner limitation -The Change Owner (`ChangeOwner`) Limitation specifies whether the user can change the owner of a content item. +The Change Owner (`ChangeOwner`) limitation specifies whether the user can change the owner of a content item. ### Possible values @@ -64,33 +62,29 @@ The Change Owner (`ChangeOwner`) Limitation specifies whether the user can chang |------|------|------| |`1`|"Forbid"|The user cannot change owner of a content item| -## Content type Group Limitation +## Content type Group limitation -The content type Group (`UserGroup`) Limitation specifies that only Users with at least one common *direct* User -Group with the owner of content get the selected access right. +The Content Type Group (`UserGroup`) limitation specifies that only users with at least one common *direct* user group with the owner of content get the selected access right. ### Possible values |Value|UI value|Description| |------|------|------| -|`1`|"self"|Only a User who has at least one common *direct* User Group with the owner gets access| +|`1`|"self"|Only a user who has at least one common *direct* user group with the owner gets access| -## Content type Group of Parent Limitation +## Content type Group of Parent limitation -The content type Group of Parent (`ParentUserGroupLimitation`) Limitation specifies that only Users with at least one common *direct* User Group -with the owner of the parent Location of a content item get a certain access right, -used by `content/create` permission. +The Content Type Group of Parent (`ParentUserGroupLimitation`) limitation specifies that only Users with at least one common *direct* user group with the owner of the parent location of a content item get a certain access right, used by `content/create` permission. ### Possible values |Value|UI value|Description| |------|------|------| -|`1`|"self"|Only a User who has at least one common *direct* User Group with owner of the parent Location gets access| +|`1`|"self"|Only a user who has at least one common *direct* user group with owner of the parent location gets access| -## Content type Limitation +## Content type limitation -The Content Typ (`ContentType`) Limitation specifies whether the User has access to content with a specific -content type. +The Content Type (`ContentType`) limitation specifies whether the user has access to content with a specific content type. ### Possible values @@ -98,15 +92,12 @@ content type. |------|------|------| |``|``|All valid content type IDs can be set as value(s)| -## Content type of Parent Limitation +## Content type of Parent limitation -The content type of Parent (`ParentContentType`) Limitation specifies whether the User has access to content whose parent Location -contains a specific content type, used by `content/create`. +The Content Type of Parent (`ParentContentType`) limitation specifies whether the user has access to content whose parent location contains a specific content type, used by `content/create`. -This Limitation combined with `ContentType` Limitation allows you to define business -rules like allowing Users to create "Blog Post" within a "Blog." -If you also combine it with `Owner of Parent` Limitation, you effectively limit -access to create Blog Posts in the Users' own Blogs. +This limitation combined with `ContentType` limitation allows you to define business rules like allowing users to create "Blog Post" within a "Blog." +If you also combine it with `Owner of Parent` limitation, you effectively limit access to create Blog Posts in the users' own Blogs. ### Possible values @@ -114,27 +105,25 @@ access to create Blog Posts in the Users' own Blogs. |------|------|------| |``|``|All valid content type IDs can be set as value(s)| -## Field Group Limitation [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] +## Field Group limitation [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] -A Field Group (`FieldGroup`) Limitation specifies whether the User can work with content Fields belonging -to a specific group. -A user with this Limitation is allowed to edit Fields belonging to the indicated group. -Otherwise, the Fields are inactive and filled with the default value (if set). +A Field Group (`FieldGroup`) limitation specifies whether the user can work with content fields belonging to a specific group. +A user with this limitation is allowed to edit fields belonging to the indicated group. +Otherwise, the fields are inactive and filled with the default value (if set). ### Possible values |Value|UI value|Description| |------|------|------| -|``|``|All valid Field group identifiers can be set as value(s)| +|``|``|All valid field group identifiers can be set as value(s)| -## Language Limitation +## Language limitation -A Language (`Language`) Limitation specifies whether the User has access to work on the specified translation. +A Language (`Language`) limitation specifies whether the user has access to work on the specified translation. -A user with this Limitation is allowed to: +A user with this limitation is allowed to: - - Create new content with the given translation(s) only. -This only applies to creating the first version of a content item. +- Create new content with the given translation(s) only. This only applies to creating the first version of a content item. - Edit content by adding a new translation or modifying an existing translation. - Publish content only when it results in adding or modifying an allowed translation. - Delete content only when it contains a translation into the specified language. @@ -145,23 +134,21 @@ This only applies to creating the first version of a content item. |------|------|------| |``|``|All valid language codes can be set as value(s)| -## Location Limitation +## Location limitation -A Location (`Location`) Limitation specifies whether the User has access to content with a specific -Location, in case of `content/create` the parent Location is evaluated. +A location (`Location`) limitation specifies whether the user has access to content with a specific location, in case of `content/create` the parent location is evaluated. ### Possible values |Value|UI value|Description| |------|------|------| -|``|``|All valid Location IDs can be set as value(s)| +|``|``|All valid location IDs can be set as value(s)| -## New Section Limitation +## New Section limitation -A New Section (`NewSection`) Limitation specifies whether the User has access to assigning content to a given Section. +A New Section (`NewSection`) limitation specifies whether the user has access to assigning content to a given section. -In the `section/assign` Policy you can combine this with Section Limitation to -limit both from and to values. +In the `section/assign` policy you can combine this with section limitation to limit both from and to values. ### Possible values @@ -169,13 +156,11 @@ limit both from and to values. |------|------|------| |``|``|All valid session IDs can be set as value(s)| -## New State Limitation +## New State limitation -A New State (`NewObjectState`) Limitation specifies whether the User has access to (assigning) a given Object -state to content. +A New State (`NewObjectState`) limitation specifies whether the user has access to (assigning) a given object state to content. -In the `state/assign` Policy you can combine this with State Limitation to limit -both from and to values. +In the `state/assign` policy you can combine this with State limitation to limit both from and to values. ### Possible values @@ -183,10 +168,9 @@ both from and to values. |------|------|------| |``|``|All valid state IDs can be set as value(s)| -## Object State Limitation +## Object State limitation -The Object State (`ObjectState`) Limitation specifies whether the User has access to content with a specific -Object state. +The Object State (`ObjectState`) limitation specifies whether the user has access to content with a specific object state. ### Possible values @@ -194,9 +178,9 @@ Object state. |------|------|------| |``|``|All valid Object state IDs can be set as value(s)| -## Order Owner Limitation +## Order Owner limitation -The Order Owner (`OrderOwner`) Limitation specifies whether the user can modify an order. +The Order Owner (`OrderOwner`) limitation specifies whether the user can modify an order. ### Possible values @@ -204,35 +188,31 @@ The Order Owner (`OrderOwner`) Limitation specifies whether the user can modify |------|------|------| |"self"|"self"|Users can access only their own orders. | -## Owner Limitation +## Owner limitation -The Owner (`Owner`) Limitation specifies that only the owner of the content item gets the selected -access right. +The Owner (`Owner`) limitation specifies that only the owner of the content item gets the selected access right. ### Possible values |Value|UI value|Description| |------|------|------| -|`1`|"self"|Only the User who is the owner gets access| +|`1`|"self"|Only the user who is the owner gets access| |`2`|"session"|Deprecated and works exactly like "self" in public PHP API since it has no knowledge of user Sessions| -## Owner of Parent Limitation +## Owner of Parent limitation -The Owner of Parent (`ParentOwner`) Limitation specifies that only the Users who own all parent Locations of -a content item get a certain access right, used for `content/create` permission. +The Owner of Parent (`ParentOwner`) limitation specifies that only the users who own all parent locations of a content item get a certain access right, used for `content/create` permission. ### Possible values |Value|UI value|Description| |------|------|------| -|`1`|"self"|Only the User who is the owner of all parent Locations gets access| +|`1`|"self"|Only the user who is the owner of all parent locations gets access| |`2`|"session"|Deprecated and works exactly like "self" in public PHP API since it has no knowledge of user Sessions| -## Parent Depth Limitation +## Parent Depth limitation -The Parent Depth (`ParentDepth`) Limitation specifies whether the User has access to creating content under -a parent Location within a specific depth of the tree, used for `content/create` -permission. +The Parent Depth (`ParentDepth`) limitation specifies whether the user has access to creating content under a parent location within a specific depth of the tree, used for `content/create` permission. ### Possible values @@ -240,9 +220,9 @@ permission. |------|------|------| |``|``|All valid integers can be set as value(s)| -## PaymentOwner Limitation +## PaymentOwner limitation -The Payment Owner (`PaymentOwner`) Limitation specifies whether the user can modify a payment. +The Payment Owner (`PaymentOwner`) limitation specifies whether the user can modify a payment. ### Possible values @@ -251,14 +231,13 @@ The Payment Owner (`PaymentOwner`) Limitation specifies whether the user can mod |"self"|"self"|Users can access only their own payments. | |"all"| none |Users can access all payments.| -## Personalization access Limitation +## Personalization access limitation -The Personalization Limitation specifies the SiteAccesses for which the User can view or modify -the scenario configuration. +The Personalization limitation specifies the SiteAccesses for which the user can view or modify the scenario configuration. -## Product Type Limitation +## Product Type limitation -The Product Type (`ProductType`) Limitation specifies whether the User has access to products belonging to a specific Product Type. +The Product Type (`ProductType`) limitation specifies whether the user has access to products belonging to a specific product type. ### Possible values @@ -266,12 +245,11 @@ The Product Type (`ProductType`) Limitation specifies whether the User has acces |------|------|------| |``|``|All valid content type IDs can be set as value(s)| -## Section Limitation +## Section limitation -The Section (`Section`) Limitation specifies whether the User has access to content within a specific -Section. +The Section (`Section`) limitation specifies whether the user has access to content within a specific section. -This Limitation can be used as a Role Limitation. +This limitation can be used as a role limitation. ### Possible values @@ -279,23 +257,21 @@ This Limitation can be used as a Role Limitation. |------|------|------| |``|``|All valid session IDs can be set as value(s)| -## Segment Group Limitation [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] +## Segment group limitation [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] -The Segment Group (`SegmentGroup`) Limitation specifies whether the User has access Segments within a specific -Segment Group. +The segment group (`SegmentGroup`) limitation specifies whether the user has access segments within a specific segment group. -This Limitation can be used as a Role Limitation. +This limitation can be used as a role limitation. ### Possible values |Value|UI value|Description| |------|------|------| -|``|``|All valid Segment Group IDs can be set as value(s).| +|``|``|All valid segment group IDs can be set as value(s).| -## SiteAccess Limitation +## SiteAccess limitation -The SiteAccess (`SiteAccess`) Limitation specifies to which SiteAccesses a certain permission applies, used -by `user/login`. +The SiteAccess (`SiteAccess`) limitation specifies to which SiteAccesses a certain permission applies, used by `user/login`. ### Possible values @@ -305,12 +281,11 @@ by `user/login`. ### Legacy compatibility notes -`SiteAccess` Limitation is deprecated and is not used actively in public PHP API, -but is allowed for being able to read / create Limitations for legacy. +`SiteAccess` limitation is deprecated and isn't used actively in public PHP API, but is allowed for being able to read / create limitations for legacy. -## Shipment Owner Limitation +## Shipment Owner limitation -The Shipment Owner (`ShipmentOwner`) Limitation specifies whether the user can modify a shipment. +The Shipment Owner (`ShipmentOwner`) limitation specifies whether the user can modify a shipment. ### Possible values @@ -318,13 +293,11 @@ The Shipment Owner (`ShipmentOwner`) Limitation specifies whether the user can m |------|------|------| |"self"|"self"|Users can access only their own shipments. | -## Subtree Limitation +## Subtree limitation -The Subtree (`Subtree`) Limitation specifies whether the User has access to content within a specific -Subtree of Location, in case of `content/create` the parent Subtree of Location  -is evaluated. +The subtree (`Subtree`) limitation specifies whether the user has access to content within a specific subtree of location, in case of `content/create` the parent subtree of location is evaluated. -This Limitation can be used as a Role Limitation. +This limitation can be used as a role limitation. ### Possible values @@ -334,15 +307,13 @@ This Limitation can be used as a Role Limitation. ### Usage notes -For more information on how to restrict User's access to part of the Subtree -follow [the example in the Admin management section](permission_use_cases.md#restrict-editing-to-part-of-the-tree). +For more information on how to restrict user's access to part of the subtree, see [the example in the Admin management section](permission_use_cases.md#restrict-editing-to-part-of-the-tree). -## Version Lock Limitation +## Version Lock limitation -The Version Lock (`VersionLock`) Limitation specifies whether the User can perform actions, for example, edit -or unlock, on content items that are in a workflow. +The Version Lock (`VersionLock`) limitation specifies whether the user can perform actions, for example, edit or unlock, on content items that are in a workflow. -This Limitation can be used as a Role Limitation. +This limitation can be used as a role limitation. ### Possible values @@ -351,20 +322,18 @@ This Limitation can be used as a Role Limitation. | `userId` | "Assigned only" | Users can perform actions only on content items that are assigned to them or not assigned to anybody. | | `null` | none | Users can perform actions on all drafts, regardless of the assignments or whether drafts are locked or not. | -## Workflow Stage Limitation +## Workflow Stage limitation -The Workflow Stage (`WorkflowStage`) Limitation specifies whether the User can edit content in a specific workflow -stage. +The Workflow Stage (`WorkflowStage`) limitation specifies whether the user can edit content in a specific workflow stage. ### Possible values -The Limitation takes as values stages configured for the workflow. +The limitation takes as values stages configured for the workflow. -## Workflow Transition Limitation +## Workflow Transition limitation -The Workflow Transition (`WorkflowTransition`) Limitation specifies whether the User can move the content in a workflow through -a specific transition. +The Workflow Transition (`WorkflowTransition`) limitation specifies whether the user can move the content in a workflow through a specific transition. ### Possible values -The Limitation takes as values transitions between stages configured for the workflow. +The limitation takes as values transitions between stages configured for the workflow. diff --git a/docs/permissions/limitations.md b/docs/permissions/limitations.md index a961883cc1..66663cc618 100644 --- a/docs/permissions/limitations.md +++ b/docs/permissions/limitations.md @@ -6,25 +6,25 @@ page_type: reference # Limitations Limitations are part of the permissions system. -They limit the access granted to users by [Policies](permission_overview.md). -While a Policy grants the user access to a function, Limitations narrow it down by different criteria. +They limit the access granted to users by [policies](permission_overview.md). +While a policy grants the user access to a function, Limitations narrow it down by different criteria. Limitations consist of two parts: - `Limitation` (Value) - `LimitationType` -Certain Limitations also serve as Role Limitations, which means they can be used to limit the rights of a Role assignment. -Currently, this covers [Subtree of Location](limitation_reference.md#subtree-limitation), [Section](limitation_reference.md#section-limitation) and [Personalization access](limitation_reference.md#personalization-access-limitation) Limitations. +Certain limitations also serve as role limitations, which means they can be used to limit the rights of a role assignment. +Currently, this covers [subtree of location](limitation_reference.md#subtree-limitation), [Section](limitation_reference.md#section-limitation) and [Personalization access](limitation_reference.md#personalization-access-limitation) limitations. `Limitation` represents the value, while `LimitationType` deals with the business logic surrounding how it actually works and is enforced. `LimitationTypes` have two modes of operation in regard to permission logic (see [`Ibexa\Contracts\Core\Limitation`](../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Limitation-Type.html) interface for more info): | Method | Use | |--------|-----| -| `evaluate` | Evaluates if the User has access to a given object in a certain context (for instance the context can be Locations when the object is `Content`), under the condition of the `Limitation` value(s). | -| `getCriterion` | Generates a `Criterion` using `Limitation` value and current User which `SearchService` by default applies to search criteria for filtering search based on permissions. | +| `evaluate` | Evaluates if the User has access to a given object in a certain context (for instance the context can be locations when the object is `Content`), under the condition of the `Limitation` value(s). | +| `getCriterion` | Generates a `Criterion` based on `Limitation` value and current user which `SearchService` by default applies to Search Criteria for filtering search based on permissions. | ## Limitation reference -See [Limitation reference](limitation_reference.md) for detailed information about individual Limitations. +See [Limitation reference](limitation_reference.md) for detailed information about individual limitations. diff --git a/docs/permissions/permission_overview.md b/docs/permissions/permission_overview.md index 6b5d513ef6..6a8b2f1dbe 100644 --- a/docs/permissions/permission_overview.md +++ b/docs/permissions/permission_overview.md @@ -1,40 +1,42 @@ --- -description: The permission system is based on Policies that you assign to users or user groups in the form of Roles. +description: The permission system is based on policies that you assign to users or user groups in the form of roles. --- # Permission overview -A new User does not have permissions for any part of the system, unless they are explicitly given access. -To get access they need to inherit Roles, typically assigned to the User Group they belong to. +A new user doesn't have permissions for any part of the system, unless they're explicitly given access. +To get access they need to inherit roles, typically assigned to the user group they belong to. -Each Role can contain one or more **Policies**. A Policy is a rule that gives access to a single **function** in a **module**. -For example, a `section/assign` Policy allows the User to assign content to Sections. +Each role can contain one or more **Policies**. +A policy is a rule that gives access to a single **function** in a **module**. +For example, a `section/assign` policy allows the user to assign content to sections. -When you add a Policy to a Role, you can also restrict it using one or more **Limitations**. -A Policy with a Limitation will only apply when the condition in the Limitation is fulfilled. -For example, a `content/publish` Policy with a `ContentType` Limitation on the "Blog Post" content type will allow the User to publish only Blog Posts, and not other content. +When you add a policy to a role, you can also restrict it using one or more **Limitations**. +A policy with a limitation only applies when the condition in the limitation is fulfilled. +For example, a `content/publish` policy with a `ContentType` limitation on the "Blog Post" content type allows the user to publish only Blog Posts, and not other content. -A Limitation, like a Policy, specifies what a User *can* do, not what they *can't do*. -A `Section` Limitation, for example, *gives* the User access to the selected Section, not *prohibits* it. +A limitation, like a policy, specifies what a user *can* do, not what they *can't do*. +A `Section` limitation, for example, *gives* the user access to the selected section, not *prohibits* it. -See [Limitation reference](limitation_reference.md) for further information -and [Permission use cases](permission_use_cases.md) for example permission setups. +For more information, see [Limitation reference](limitation_reference.md) and [Permission use cases](permission_use_cases.md). -## Assigning Roles to Users +## Assigning roles to users -Every User or User Group can have many roles. A User can also belong to many groups, for example, Administrators, Editors, Subscribers. +Every user or user group can have many roles. +A user can also belong to many groups, for example, Administrators, Editors, Subscribers. -It is best practice to avoid assigning Roles to users directly. -Instead, try to organize your content so that it can be covered with general Roles assigned to User Groups. +It's best practice to avoid assigning roles to users directly. +Instead, try to organize your content so that it can be covered with general roles assigned to user groups. -Using Groups is easier to manage and more secure. It also improves system performance. -The more Role assignments and complex Policies you add for a given User, the more complex the search/load queries will be, because they always take permissions into account. +Using groups is easier to manage and more secure. +It also improves system performance. +The more role assignments and complex policies you add for a given user, the more complex the search/load queries are, because they always take permissions into account. ## Permissions for custom controllers You can control access to a custom controller by implementing the `performAccessCheck()` method. -In the following example the user does not have access to the controller unless they have the `section/view` Policy: +In the following example the user doesn't have access to the controller unless they have the `section/view` policy: ``` php use Ibexa\Core\MVC\Symfony\Security\Authorization\Attribute; @@ -48,13 +50,13 @@ public function performAccessCheck(): void `Attribute` accepts three arguments: -- `module` is the Policy module (e.g. `content`) -- `function` is the function inside the module (e.g. `read`) -- `limitations` are optional Limitations to check against. Here you can provide two keys: +- `module` is the policy module (for example,`content`) +- `function` is the function inside the module (for example, `read`) +- `limitations` are optional limitations to check against. Here you can provide two keys: - `valueObject` is the object you want to check for, for example `ContentInfo`. - `targets` are a table of value objects that are the target of the operation. For example, to check if content can be assigned to a Section, provide the Section as `targets`. - `targets` accept Location, Object state and Section objects. + `targets` accept location, object state and section objects. ### Checking user access @@ -71,7 +73,7 @@ You can also use the permission resolver (`Ibexa\Core\Repository\Permission\Perm The `canUser()` method checks if the user can perform a given action with the selected object. For example: `canUser('content', 'edit', $content, [$location] );` -checks the `content/edit` permission for the provided content item at the provided Location. +checks the `content/edit` permission for the provided content item at the provided location. ### Blocking access to controller action diff --git a/docs/permissions/permission_use_cases.md b/docs/permissions/permission_use_cases.md index 28c07b0b6f..cd043357de 100644 --- a/docs/permissions/permission_use_cases.md +++ b/docs/permissions/permission_use_cases.md @@ -4,11 +4,11 @@ description: Set up permission sets for common use cases. # Permission use cases -Here are a few examples of sets of Policies that you can use to get some common permission configurations. +Here are a few examples of sets of policies that you can use to get some common permission configurations. -## Enter Back Office +## Enter back office -To allow the User to enter the Back Office interface and view all content, set the following Policies: +To allow the user to enter the back office interface and view all content, set the following policies: - `user/login` - `content/read` @@ -16,129 +16,119 @@ To allow the User to enter the Back Office interface and view all content, set t - `section/view` - `content/reverserelatedlist` -These Policies are necessary for all other cases below that require access to the content structure. +These policies are necessary for all other cases below that require access to the content structure. ## Create content without publishing [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] You can use this option together with [[= product_name_exp =]]'s content review options. -Users assigned with these Policies can create content, but cannot publish it. -To publish, they must send the content for review to another User with proper permissions -(for example, senior editor, proofreader, etc.). +Users assigned with these policies can create content, but cannot publish it. +To publish, they must send the content for review to another User with proper permissions (for example, senior editor or proofreader). - `content/create` - `content/edit` -Use this setup with [[= product_name_exp =]] or [[= product_name_com =]] only, -as [[= product_name_headless =]] does not allow the User to continue working with their content. +Use this setup with [[= product_name_exp =]] or [[= product_name_com =]] only, as [[= product_name_headless =]] doesn't allow the User to continue working with their content. ## Create and publish content -To create and publish content, users must additionally have the following Policies: +To create and publish content, users must additionally have the following policies: - `content/create` - `content/edit` - `content/publish` -This also lets the user copy and move content, as well as add new Locations to a content item (but not remove them). +This also lets the user copy and move content, and add new locations to a content item (but not remove them). ## Move content -To move a content item or a Subtree to another Location, the user must have the following Policies: +To move a content item or a subtree to another location, the user must have the following policies: -- `content/read` - on the source Location -- `content/create` - on the target Location +- `content/read` - on the source location +- `content/create` - on the target location ## Remove content -To send content to Trash, the User needs to have the `content/remove` Policy. -If content has more than one language, the User must have access to all the languages. -That is, the `content/remove` Policy must have either no Limitation, or a Limitation for all languages of the content item. +To send content to Trash, the user needs to have the `content/remove` policy. +If content has more than one language, the user must have access to all the languages. +That is, the `content/remove` policy must have either no limitation, or a limitation for all languages of the content item. -To remove an archived version of content, the User must have the `content/versionremove` Policy. +To remove an archived version of content, the user must have the `content/versionremove` policy. -Further manipulation of Trash requires the `content/restore` Policy to restore items from Trash, and `content/cleantrash` to completely delete all content from the Trash. +Further manipulation of Trash requires the `content/restore` policy to restore items from Trash, and `content/cleantrash` to completely delete all content from the Trash. !!! caution - With the `content/cleantrash` Policy, the User can empty the Trash even if they do not have access to the trashed content, - for example, because it belonged to a Section that the User does not have permissions for. + With the `content/cleantrash` policy, the user can empty the Trash even if they don't have access to the trashed content, for example, because it belonged to a Section that the user doesn't have permissions for. ## Restrict editing to part of the tree -If you want to let the User create or edit content, but only in one part of the content tree, use Limitations. -Three Limitations that you could use here are `Section` Limitation, `Location` Limitation and `Subtree of Location` Limitation. +If you want to let the User create or edit content, but only in one part of the content tree, use limitations. +Three limitations that you could use here are `Section` limitation, `Location` limitation and `Subtree of Location` limitation. -### Section Limitation +### Section limitation Let's assume you have two Folders under your Home: Blog and Articles. -You can let a User create content for the blogs, but not in Articles, by adding a `Section` Limitation to -the Blog content item. -This allows the User to publish content anywhere under this Location in the structure. -Section does not have to belong to the same Subtree of Location in the content structure, any Locations can be assigned to it. +You can let a user create content for the blogs, but not in Articles, by adding a `Section` limitation to the Blog content item. +This allows the User to publish content anywhere under this location in the structure. +Section doesn't have to belong to the same subtree of location in the content structure, any locations can be assigned to it. -### Location Limitation +### Location limitation -If you add a `Location` Limitation and point to the same Location, the User is able to publish content directly -under the selected Location, but not anywhere deeper in its Subtree of Location. +If you add a `Location` limitation and point to the same location, the user is able to publish content directly under the selected location, but not anywhere deeper in its subtree of location. -### Subtree of Location Limitation +### Subtree of location limitation -To limit the User's access to a subtree, use the `Subtree of Location` Limitation. -You do it by creating two new Roles for a User Group: - - 1. Role with a `Subtree` Limitation for the User - 1. Role with a `Location` Limitation for the Subtree +To limit the user's access to a subtree, use the `Subtree of Location` limitation. +You do it by creating two new roles for a user group: + + 1. Role with a `Subtree` limitation for the User + 1. Role with a `Location` limitation for the subtree Follow the example below to learn how to do that. -**Cookbook**, **Dinner recipes** and **Dessert recipes** containers are not accessible in the frontend. -Edit access to them in the **Admin Panel**. +**Cookbook**, **Dinner recipes** and **Dessert recipes** containers aren't accessible in the frontend. +Edit access to them in the **Admin** panel. ![Subtree file structure](subtree_usability_notes_1.png) -To give the vegetarian editors access only to the **Vegetarian** dinner recipes section, - create a new Role, for example, *EditorVeg*. -Next, add to it a `content/read` Policy with the `Subtree` Limitation for `Cookbook/Dinner recipes/Vegetarian`. -Assign the Role to the vegetarian editors User Group. +To give the vegetarian editors access only to the **Vegetarian** dinner recipes section, create a new role, for example, *EditorVeg*. +Next, add to it a `content/read` policy with the `Subtree` limitation for `Cookbook/Dinner recipes/Vegetarian`. +Assign the role to the vegetarian editors user group. It allows users from that group to access the **Vegetarian** container but not **Cookbook** and **Dinner recipes**. -To give users access to **Cookbook** and **Dinner recipes** containers, -create a new Role, for example, *EditorVegAccess*. -Next, add to it a `content/read` Policy with the `Location` Limitations **Cookbook** and **Dinner recipes**. -Assign the new Role to the vegetarian editors User Group as well. +To give users access to **Cookbook** and **Dinner recipes** containers, create a new role, for example, *EditorVegAccess*. +Next, add to it a `content/read` policy with the `Location` limitations **Cookbook** and **Dinner recipes**. +Assign the new role to the vegetarian editors user group as well. Only then the limitations are combined with `AND`, resulting in an empty set. -The vegetarian editors should now see the following Content Tree: +The vegetarian editors should now see the following content tree: ![Limited subtree file structure](subtree_usability_notes_2.png) -When a Policy has more than one Limitation, all of them have to apply, or the Policy does not work. -For example, a `Location` Limitation on Location `1/2` and `Subtree of Location` Limitation on `1/2/55` cannot work together, -because no Location can satisfy both those requirements at the same time. -To combine more than one Limitation with the *or* relation, not *and*, -you can split your Policy in two, each with one of these Limitations. +When a policy has more than one limitation, all of them have to apply, or the policy doesn't work. +For example, a `Location` limitation on location `1/2` and `Subtree of Location` limitation on `1/2/55` cannot work together, because no location can satisfy both those requirements at the same time. +To combine more than one limitation with the *or* relation, not *and*, you can split your policy in two, each with one of these limitations. -## Manage Locations +## Manage locations -To add a new Location to a content item, the Policies required for publishing content are enough. -To allow the User to remove a Location, grant them the following Policies: +To add a new location to a content item, the policies required for publishing content are enough. +To allow the user to remove a location, grant them the following policies: - `content/remove` - `content/manage_locations` -Hiding and revealing Location requires one more Policy: `content/hide`. +Hiding and revealing location requires one more policy: `content/hide`. ## Editorial workflows You can control which stages in an editorial workflow the user can work with. -Do this by adding the `WorkflowStageLimitation` to `content` Policies such as `content/edit` or `content/publish`. +Do this by adding the `WorkflowStageLimitation` to `content` policies such as `content/edit` or `content/publish`. You can also control which transitions the user can pass content through. -Do this by using the `workflow/change_stage` Policy together with the `WorkflowTransitionLimitation`. +Do this by using the `workflow/change_stage` policy together with the `WorkflowTransitionLimitation`. -For example, to enable the user to edit only content in the "Design" stage -and to pass it after creating design to the "Proofread stage", use following permissions: +For example, to enable the user to edit only content in the "Design" stage and to pass it after creating design to the "Proofread stage", use following permissions: - `content/edit` with `WorkflowStageLimitation` set to "Design". - `workflow/change_stage` with `WorkflowTransitionLimitation` set to `to_proofreading` @@ -152,37 +142,34 @@ To enable upload, you need you set the following permissions: - `content/read` - `content/publish` -You can control what content items can be uploaded and where by using Limitations -on the `content/create` and `content/publish` Policies. +You can control what content items can be uploaded and where by using imitations on the `content/create` and `content/publish` policies. -A Location Limitation limits the uploading to a specific Location in the tree. -A content type Limitation controls the content types that are allowed. -For example, you can set the Location Limitation on a **Pictures** Folder, and add a content type Limitation -that only allows content items of type **Image**. -This ensures that only files of type `image` can be uploaded, -and only to the **Pictures** Folder. +A location limitation limits the uploading to a specific location in the tree. +A content type limitation controls the content types that are allowed. +For example, you can set the location limitation on a **Pictures** Folder, and add a content type limitation that only allows content items of type **Image**. +This ensures that only files of type `image` can be uploaded, and only to the **Pictures** Folder. ## Taxonomies -You can control which users or user groups can work with taxonomies. +You can control which users or user groups can work with taxonomies. To let users create and assign taxonomy entries, set the following permissions: - `taxonomy/assign` to allow user to tag and untag content - `taxonomy/read` to see the Taxonomy interface - `taxonomy/manage` to create, edit and delete tags -With Limitations, you can configure whether permissions apply to Tags, Product categories or both. +With limitations, you can configure whether permissions apply to Tags, product categories, or both. -## Register Users +## Register users -To allow anonymous users to register through the `/register` route, grant the `user/register` Policy to the Anonymous User Group. +To allow anonymous users to register through the `/register` route, grant the `user/register` policy to the Anonymous user group. ## Admin -To access the [administration panel](admin_panel.md) in the Back Office, the User must have the `setup/administrate` Policy. +To access the [administration panel](admin_panel.md) in the back office, the User must have the `setup/administrate` policy. This allows the User to view the languages and content types. -Additional Policies are needed for each section of the Admin. +Additional policies are needed for each section of the Admin. ### System Information @@ -190,9 +177,9 @@ Additional Policies are needed for each section of the Admin. ### Sections -- `section/view` to see and access the Section list -- `section/edit` to add and edit Sections -- `section/assign` to assign Sections to content +- `section/view` to see and access the section list +- `section/edit` to add and edit sections +- `section/assign` to assign sections to content ### Languages @@ -204,27 +191,27 @@ Additional Policies are needed for each section of the Admin. ### Object states -- `state/administrate` to view a list of Object states, add and edit them -- `state/assign` to assign Objects states to Content +- `state/administrate` to view a list of object states, add and edit them +- `state/assign` to assign Objects states to content ### Roles -- `role/read` to view the list of Roles in Admin -- `role/create`, `role/update`, `role/assign` and `role/delete` to manage Roles +- `role/read` to view the list of roles in Admin +- `role/create`, `role/update`, `role/assign` and `role/delete` to manage roles ### Users -- `content/view` to view the list of Users +- `content/view` to view the list of users -Users are treated like other content, so to create and modify them, the User needs to have the same permissions as for managing other content items. +Users are treated like other content, so to create and modify them, the user needs to have the same permissions as for managing other content items. ## Product catalog -You can control to what extend users can access the Product catalog and all its related parts. +You can control to what extend users can access the product catalog and all its related parts. ### Product type -To create or edit product types, a user needs to have access to attributes and attribute groups. +To create or edit product types, a user needs to have access to attributes and attribute groups. Set the following permissions to allow such access: - `product_type/create` @@ -233,9 +220,8 @@ Set the following permissions to allow such access: ### Product item -When a product is created, a product item and a content item are also generated. -Permissions for the product catalog override permissions for content, therefore, -users without permissions for content can still manage products. +When a product is created, a product item and a content item are also generated. +Permissions for the product catalog override permissions for content, therefore, users without permissions for content can still manage products. - `product/create` - `product/view` @@ -243,48 +229,40 @@ users without permissions for content can still manage products. ## Commerce [[% include 'snippets/commerce_badge.md' %]] -To control which commerce functionalities are available to store users, you can grant -or prevent them access to individual components. +To control which commerce functionalities are available to store users, you can grant or prevent them access to individual components. -Out of the box, [[= product_name_com =]] comes with the *Storefront User* Role that is assigned to anonymous users and grants them the following permissions: +Out of the box, [[= product_name_com =]] comes with the *Storefront User* role that is assigned to anonymous users and grants them the following permissions: -- `product/view`, `product_type/view` and `catalog/view`, to allow them to view a product -list and product details -- `cart/view`, `cart/create` and `cart/edit` with the `CartOwner` Limitation set to `self`, to allow them to add items to their own shopping cart, modify their cart, and delete it -- `checkout/view`, `checkout/create`, `checkout/update` and `checkout/delete`, to allow -them to proceed to checkout and interact with the checkout process +- `product/view`, `product_type/view` and `catalog/view`, to allow them to view a product list and product details +- `cart/view`, `cart/create` and `cart/edit` with the `CartOwner` limitation set to `self`, to allow them to add items to their own shopping cart, modify their cart, and delete it +- `checkout/view`, `checkout/create`, `checkout/update` and `checkout/delete`, to allow them to proceed to checkout and interact with the checkout process -You can modify the default Roles by preventing anonymous users from being able to proceed with the checkout process, -and creating the *Registered Buyer* Role that enables logged-in users to purchase products. +You can modify the default roles by preventing anonymous users from being able to proceed with the checkout process, and creating the *Registered Buyer* role that enables logged-in users to purchase products. -You could do this by moving permissions that relate to checkout from the *Storefront User* Role to the *Registered Buyer* Role, -and granting *Registered Buyer* with the `user/register` and `user/login` permissions which control access to registration and login. +You could do this by moving permissions that relate to checkout from the *Storefront User* role to the *Registered Buyer* role, and granting *Registered Buyer* with the `user/register` and `user/login` permissions which control access to registration and login. See below for a detailed listing of permissions that apply to Commerce, together with their meaning. !!! note "Owner limitation" - For anonymous users, orders, shipments, and/or payments are saved with a 'null' user reference. - Therefore, when you apply the 'Owner/self' Limitation to any of the permissions below, anonymous users are not allowed to interact with any of these entities. + For anonymous users, orders, shipments, and/or payments are saved with a 'null' user reference. + Therefore, when you apply the `Owner/self` limitation to any of the permissions below, anonymous users aren't allowed to interact with any of these entities. -### Cart +### Cart -Set the following permissions to decide what actions are available when users -interact with carts: +Set the following permissions to decide what actions are available when users interact with carts: -- `cart/view` - to allow user to view their cart +- `cart/view` - to allow user to view their cart - `cart/delete` - to delete cart, for example, after successful checkout - `cart/create` - to create a new cart - `cart/edit` - to allow user to add products to their cart -To further control access to a cart, you can use the `CartOwner` Limitation -and set its value to `self`. +To further control access to a cart, you can use the `CartOwner` limitation and set its value to `self` This way users can only interact with their own carts. -### Checkout +### Checkout -Set the following permissions to decide what actions are available when users -interact with checkout: +Set the following permissions to decide what actions are available when users interact with checkout: - `checkout/view` - to control user access to checkout - `checkout/create` - to allow starting the checkout process, by proceeding from cart @@ -293,60 +271,54 @@ interact with checkout: ### Order management -Set the following permissions to decide what actions are available when users -interact with orders: +Set the following permissions to decide what actions are available when users interact with orders: - `order/create` - to allow the user to create a new order - `order/view` - to allow the user to view orders -- `order/update` - to allow the user to change status of an existing order -- `order/cancel` - to allow the user to cancel an existing order +- `order/update` - to allow the user to change status of an existing order +- `order/cancel` - to allow the user to cancel an existing order -To further control access to an order, you can use the `OrderOwner` Limitation -and set its value to `self`. +To further control access to an order, you can use the `OrderOwner` limitation and set its value to `self`. This way users can only interact with their own orders. ### Shipping management -Set the following permissions to decide what actions are available when users -interact with shipping methods and shipments. +Set the following permissions to decide what actions are available when users interact with shipping methods and shipments. #### Shipping methods - `shipping_method/create` - to allow the user to create a new shipping method - `shipping_method/view` - to allow the user to view shipping methods -- `shipping_method/edit` - to allow the user to modify an existing shipping method -- `shipping_method/delete` - to allow the user to delete an existing shipping method +- `shipping_method/edit` - to allow the user to modify an existing shipping method +- `shipping_method/delete` - to allow the user to delete an existing shipping method #### Shipments - `shipment/create` - to allow the user to create a new shipment - `shipment/view` - to allow the user to view shipments -- `shipment/update` - to allow the user to change status of an existing shipment -- `shipment/delete` - to allow the user to cancel an existing shipment +- `shipment/update` - to allow the user to change status of an existing shipment +- `shipment/delete` - to allow the user to cancel an existing shipment -To further control access to a shipment, you can use the `ShipmentOwner` Limitation -and set its value to `self`. +To further control access to a shipment, you can use the `ShipmentOwner` limitation and set its value to `self`. This way users can only interact with their own shipments. ### Payment management -Set the following permissions to decide what actions are available when users -interact with payment methods and payments. +Set the following permissions to decide what actions are available when users interact with payment methods and payments. #### Payment methods - `payment_method/create` - to allow the user to create a new payment method - `payment_method/view` - to allow the user to view payment methods -- `payment_method/edit` - to allow the user to modify an existing payment method -- `payment_method/delete` - to allow the user to delete an existing payment method +- `payment_method/edit` - to allow the user to modify an existing payment method +- `payment_method/delete` - to allow the user to delete an existing payment method #### Payments - `payment/create` - to allow the user to create a new payment - `payment/view` - to allow the user to view payments -- `payment/edit` - to allow the user to modify an existing payment -- `payment/delete` - to allow the user to delete an existing payment +- `payment/edit` - to allow the user to modify an existing payment +- `payment/delete` - to allow the user to delete an existing payment -To further control access to a payment, you can use the `PaymentOwner` Limitation -and set its value to `self`. +To further control access to a payment, you can use the `PaymentOwner` limitation and set its value to `self`. This way users can only interact with their own payments. diff --git a/docs/permissions/permissions.md b/docs/permissions/permissions.md index 937ebd71a0..139ec8ed18 100644 --- a/docs/permissions/permissions.md +++ b/docs/permissions/permissions.md @@ -1,11 +1,11 @@ --- -description: Use granular permission system to grant access to various parts of the system using Roles, Policies, and Limitations. +description: Use granular permission system to grant access to various parts of the system by using roles, policies, and limitations. page_type: landing_page --- # Permissions -The permission system of [[= product_name =]] enables you to control in detail which users have access to which parts of the system, both the Back Office's administrative and editorial features, and the content of the website front. +The permission system of [[= product_name =]] enables you to control in detail which users have access to which parts of the system, both the back office's administrative and editorial features, and the content of the website front. [[= cards([ "permissions/permission_overview", diff --git a/docs/permissions/policies.md b/docs/permissions/policies.md index 4bd60ebae8..2bc83d88cd 100644 --- a/docs/permissions/policies.md +++ b/docs/permissions/policies.md @@ -1,19 +1,18 @@ --- -description: Policies are the main building block of the permissions system which lets you define the accesses for specific user Roles. +description: Policies are the main building block of the permissions system which lets you define the accesses for specific user roles. page_type: reference --- # Policies Policies are the main building block of the permissions system. -Each Role you assign to user or user group consists of Policies -which define, which parts of the application or website the user has access to. +Each role you assign to user or user group consists of policies which define, which parts of the application or website the user has access to. -## Available Policies +## Available policies ### Access to all functions -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |--------|----------|-------------------------------------------------------------|----------------------| | `*` | `*` | all modules, all functions: grant all available permissions | | @@ -32,7 +31,7 @@ which define, which parts of the application or website the user has access to. #### Customer groups -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |-------------------------------|-----------------------|-------------------------|----------------------| | `customer_group` | `create` | create a customer group | | | `delete` | delete a customer group | @@ -41,33 +40,33 @@ which define, which parts of the application or website the user has access to. #### Personalization -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |--------------------------------|---------------------|-------------------------------------------------------------------|-------------------------------------------------------------------------------------| | `personalization` | `edit` | modify scenario configuration for selected SiteAccesses | [Personalization access](limitation_reference.md#personalization-access-limitation) | | | `view` | view scenario configuration and results for selected SiteAccesses | [Personalization access](limitation_reference.md#personalization-access-limitation) | #### Roles -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |---------------------|-----------------------|----------------------------------------------------------------------------|----------------------| -| `role` | `assign` | assign Roles to Users and User Groups | -| | `create` | create new Roles | -| | `delete` | delete Roles | -| | `read` | view the Roles list in Admin. Required for all other role-related Policies | -| | `update` | modify existing Roles | +| `role` | `assign` | assign roles to users and user groups | +| | `create` | create new roles | +| | `delete` | delete roles | +| | `read` | view the roles list in Admin. Required for all other role-related policies | +| | `update` | modify existing roles | #### Setup -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |----------------------|-----------------------------|------------------------------------------|----------------------| | `setup` | `administrate` | access Admin | | | `install` | unused | | | `setup` | unused | -| | `system_info` | view the System Information tab in Admin | +| | `system_info` | view the **System Information** tab in Admin | #### Sites [[% include 'snippets/experience_badge.md' %]] [[% include 'snippets/commerce_badge.md' %]] -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |---------------------|------------------------------|-------------------------------------------------------------------------------------------------------|----------------------| | `site` | `change_status` | change status of the public accesses of sites to `Live` or `Offline` in the Site Factory | | | `create` | create sites in the Site Factory | @@ -78,7 +77,7 @@ which define, which parts of the application or website the user has access to. #### Users -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |---------------------|----------------------------|---------------------------------------------------|----------------------| | `user` | `activation` | unused | | | `invite` | create and send invitations to create an account | @@ -92,7 +91,7 @@ which define, which parts of the application or website the user has access to. #### Cart [[% include 'snippets/commerce_badge.md' %]] -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |---------------------|-----------------------|---------------------------------------------------------------------|-----------------------------------------------------------| | `cart` | `create` | create a cart | [CartOwner](limitation_reference.md#cartowner-limitation) | | | `delete` | delete cart, for example, after successful checkout | [CartOwner](limitation_reference.md#cartowner-limitation) | @@ -101,7 +100,7 @@ which define, which parts of the application or website the user has access to. #### Checkout [[% include 'snippets/commerce_badge.md' %]] -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |-------------------------|-----------------------|---------------------------------------------------------------------|----------------------| | `checkout` | `create` | create new checkout, for example, after workflow fails to complete | | | `delete` | delete checkout, for example, after workflow completes successfully | @@ -110,14 +109,14 @@ which define, which parts of the application or website the user has access to. #### Currencies and regions -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |-------------------------|-------------------------|-------------------|----------------------| | `commerce` | `currency` | manage currencies | | | `region` | manage regions | #### Orders [[% include 'snippets/commerce_badge.md' %]] -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |----------------------|-----------------------|---------------------------|--------------------------------------------------------------| | `order` | `cancel` | cancel an order | [OrderOwner](limitation_reference.md#order-owner-limitation) | | | `create` | create an order | [OrderOwner](limitation_reference.md#order-owner-limitation) | @@ -126,7 +125,7 @@ which define, which parts of the application or website the user has access to. #### Payments [[% include 'snippets/commerce_badge.md' %]] -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |------------------------|-----------------------|------------------|-----------------------------------------------------------------| | `payment` | `create` | create a payment | [PaymentOwner](limitation_reference.md#paymentowner-limitation) | | | `delete` | delete a payment | [PaymentOwner](limitation_reference.md#paymentowner-limitation) | @@ -135,7 +134,7 @@ which define, which parts of the application or website the user has access to. #### Payment methods [[% include 'snippets/commerce_badge.md' %]] -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |-------------------------------|-----------------------|-------------------------|----------------------| | `payment_method` | `create` | create a payment method | | | `delete` | delete a payment method | @@ -144,26 +143,26 @@ which define, which parts of the application or website the user has access to. #### Segments [[% include 'snippets/commerce_badge.md' %]] -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |------------------------|-------------------------------|--------------------------|-------------------------------------------------------------------| -| `segment` | `assign_to_user` | assign Segments to Users | [Segment Group](limitation_reference.md#segment-group-limitation) | -| | `create` | create Segments | [Segment Group](limitation_reference.md#segment-group-limitation) | -| | `read` | load Segment information | [Segment Group](limitation_reference.md#segment-group-limitation) | -| | `remove` | remove Segments | [Segment Group](limitation_reference.md#segment-group-limitation) | -| | `update` | update Segments | [Segment Group](limitation_reference.md#segment-group-limitation) | +| `segment` | `assign_to_user` | assign segments to users | [Segment Group](limitation_reference.md#segment-group-limitation) | +| | `create` | create segments | [Segment Group](limitation_reference.md#segment-group-limitation) | +| | `read` | load segment information | [Segment Group](limitation_reference.md#segment-group-limitation) | +| | `remove` | remove segments | [Segment Group](limitation_reference.md#segment-group-limitation) | +| | `update` | update segments | [Segment Group](limitation_reference.md#segment-group-limitation) | #### Segment groups [[% include 'snippets/commerce_badge.md' %]] -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |------------------------------|-----------------------|--------------------------------|----------------------| -| `segment_group` | `create` | create Segment Groups | -| | `read` | load Segment Group information | -| | `remove` | remove Segment Groups | -| | `update` | update Segment Groups | +| `segment_group` | `create` | create segment groups | +| | `read` | load segment group information | +| | `remove` | remove segment groups | +| | `update` | update segment groups | #### Shipments [[% include 'snippets/commerce_badge.md' %]] -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |-------------------------|-----------------------|-----------------------------|--------------------------------------------------------------------| | `shipment` | `create` | create a shipment | [ShipmentOwner](limitation_reference.md#shipment-owner-limitation) | | | `delete` | delete a shipment | [ShipmentOwner](limitation_reference.md#shipment-owner-limitation) | @@ -172,7 +171,7 @@ which define, which parts of the application or website the user has access to. #### Shipping methods [[% include 'snippets/commerce_badge.md' %]] -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |--------------------------------|-----------------------|--------------------------|----------------------| | `shipping_method` | `create` | create a shipping method | | | `delete` | delete a shipping method | @@ -183,31 +182,31 @@ which define, which parts of the application or website the user has access to. #### Content -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |------------------------|-----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `content` | `cleantrash` | empty the Trash (even when the User does not have access to individual content items) | -| | `create` | create new content. Note: even without this Policy the User is able to enter edit mode, but cannot finalize work with the content item. | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Language](limitation_reference.md#language-limitation)
[Owner of Parent](limitation_reference.md#owner-of-parent-limitation)
[Content type Group of Parent](limitation_reference.md#content-type-group-of-parent-limitation)
[Content type of Parent](limitation_reference.md#content-type-of-parent-limitation)
[Parent Depth](limitation_reference.md#parent-depth-limitation)
[Field Group](limitation_reference.md#field-group-limitation)
[Change Owner](limitation_reference.md#change-owner-limitation) | +| `content` | `cleantrash` | empty the Trash (even when the User doesn't have access to individual content items) | +| | `create` | create new content. Note: even without this policy the user is able to enter edit mode, but cannot finalize work with the content item. | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Language](limitation_reference.md#language-limitation)
[Owner of Parent](limitation_reference.md#owner-of-parent-limitation)
[Content type Group of Parent](limitation_reference.md#content-type-group-of-parent-limitation)
[Content type of Parent](limitation_reference.md#content-type-of-parent-limitation)
[Parent Depth](limitation_reference.md#parent-depth-limitation)
[Field Group](limitation_reference.md#field-group-limitation)
[Change Owner](limitation_reference.md#change-owner-limitation) | | | `diff` | unused | | | `edit` | edit existing content | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Content type Group](limitation_reference.md#content-type-group-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Language](limitation_reference.md#language-limitation)
[Object State](limitation_reference.md#object-state-limitation)
[Workflow Stage](limitation_reference.md#workflow-stage-limitation)
[Field Group](limitation_reference.md#field-group-limitation)
[Version Lock](limitation_reference.md#version-lock-limitation)
[Change Owner](limitation_reference.md#change-owner-limitation) | -| | `hide` | hide and reveal content Locations | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Content type Group](limitation_reference.md#content-type-group-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Language](limitation_reference.md#language-limitation) | -| | `manage_locations` | remove Locations and send content to Trash | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Object State](limitation_reference.md#object-state-limitation) | +| | `hide` | hide and reveal content locations | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Content type Group](limitation_reference.md#content-type-group-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Language](limitation_reference.md#language-limitation) | +| | `manage_locations` | remove locations and send content to Trash | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Object State](limitation_reference.md#object-state-limitation) | | | `pendinglist` | unused | | | `publish` | publish content. Without this Policy, the User can only save drafts or send them for review (in [[= product_name_exp =]]) | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Content type Group](limitation_reference.md#content-type-group-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Language](limitation_reference.md#language-limitation)
[Object State](limitation_reference.md#object-state-limitation)
[Workflow Stage](limitation_reference.md#workflow-stage-limitation) | | | `read` | view the content both in front and back end | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Content type Group](limitation_reference.md#content-type-group-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Object State](limitation_reference.md#object-state-limitation) | -| | `remove` | remove Locations and send content to Trash | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Object State](limitation_reference.md#object-state-limitation)
[Language](limitation_reference.md#language-limitation) | +| | `remove` | remove locations and send content to Trash | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Object State](limitation_reference.md#object-state-limitation)
[Language](limitation_reference.md#language-limitation) | | | `restore` | restore content from Trash | -| | `reverserelatedlist` | see all content that a content item relates to (even when the User is not allowed to view it as an individual content items) | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
| +| | `reverserelatedlist` | see all content that a content item relates to (even when the User isn't allowed to view it as an individual content items) | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
| | | `translate` | unused | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Language](limitation_reference.md#language-limitation) | | | `translations` | manage the language list in Admin | | | `unlock` | unlock drafts locked to a user for performing actions | [Owner](limitation_reference.md#owner-limitation)
[Content type Group](limitation_reference.md#content-type-group-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Language](limitation_reference.md#language-limitation)
[Version Lock](limitation_reference.md#version-lock-limitation) | | | `urltranslator` | manage URL aliases of a content item | | | `versionread` | view content after publishing, and to preview any content in the Site mode | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
Status
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Object State](limitation_reference.md#object-state-limitation) | | | `versionremove` | remove archived content versions | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
Status
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Object State](limitation_reference.md#object-state-limitation) | -| | `view_embed` | view content embedded in another content item (even when the User is not allowed to view it as an individual content item) | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation) | +| | `view_embed` | view content embedded in another content item (even when the User isn't allowed to view it as an individual content item) | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation) | #### Content types -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |----------------------|-----------------------|--------------------------------------------------------------------------|----------------------| | `class` | `create` | create new content types. Also required to edit exiting content types | | | `delete` | delete content types | @@ -215,22 +214,22 @@ which define, which parts of the application or website the user has access to. #### Sections -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |------------------------|-----------------------|----------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `section` | `assign` | assign Sections to content | [content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[New Section](limitation_reference.md#new-section-limitation) | | | `edit` | edit existing Sections and create new ones | -| | `view` | view the Sections list in Admin. Required for all other section-related Policies | +| | `view` | view the Sections list in Admin. Required for all other section-related policies | #### Object States -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |----------------------|-----------------------------|---------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `state` | `assign` | assign Object states to content items | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Content type Group](limitation_reference.md#content-type-group-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Object State](limitation_reference.md#object-state-limitation)
[New State](limitation_reference.md#new-state-limitation) | -| | `administrate` | view, add and edit Object states | +| `state` | `assign` | assign object states to content items | [Content type](limitation_reference.md#content-type-limitation)
[Section](limitation_reference.md#section-limitation)
[Owner](limitation_reference.md#owner-limitation)
[Content type Group](limitation_reference.md#content-type-group-limitation)
[Location](limitation_reference.md#location-limitation)
[Subtree](limitation_reference.md#subtree-limitation)
[Object State](limitation_reference.md#object-state-limitation)
[New State](limitation_reference.md#new-state-limitation) | +| | `administrate` | view, add and edit object states | #### Taxonomy -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |-------------------------|-----------------------|-------------------------------|----------------------| | `taxonomy` | `assign` | tag or untag content | | | `manage` | create, edit, and delete tags | @@ -238,7 +237,7 @@ which define, which parts of the application or website the user has access to. #### Workflow and version comparison -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |---------------------------|-----------------------------|----------------------------------------|-------------------------------------------------------------------------------| | `comparison` | `view` | view version comparison | | `workflow` | `change_stage` | change stage in the specified workflow | [Workflow Transition](limitation_reference.md#workflow-transition-limitation) | @@ -247,7 +246,7 @@ which define, which parts of the application or website the user has access to. #### Catalogs -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |------------------------|-----------------------|------------------|----------------------| | `catalog` | `create` | create a catalog | | | `delete` | delete a catalog | @@ -256,7 +255,7 @@ which define, which parts of the application or website the user has access to. #### Products -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |------------------------|-----------------------|---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------| | `product` | `create` | create a product | [Product Type](limitation_reference.md#product-type-limitation)
[Language](limitation_reference.md#language-limitation) | | | `delete` | delete a product | [Product Type](limitation_reference.md#product-type-limitation) | @@ -265,17 +264,15 @@ which define, which parts of the application or website the user has access to. #### Product types -| Module | Function | Effect | Possible Limitations | +| Module | Function | Effect | Possible limitations | |-----------------------------|-----------------------|-----------------------------------------------------------------------------------------------------------------|----------------------| -| `product_type` | `create` | create a product type, a new attribute, a new attribute group and add translation to product type and attribute | +| `product_type` | `create` | create a product type, a new attribute, a new attribute group, and add translation to product type and attribute | | | `delete` | delete a product type, attribute, attribute group | | | `edit` | edit a product type, attribute, attribute group | | | `view` | view product types, attributes and attribute groups | -## Combining Policies +## Combining policies -Policies on one Role are connected with the *and* relation, not *or*, -so when Policy has more than one Limitation, all of them have to apply. +Policies on one role are connected with the *and* relation, not *or*, so when policy has more than one limitation, all of them have to apply. -If you want to combine more than one Limitation with the *or* relation, not *and*, -you can split your Policy in two, each with one of these Limitations. +If you want to combine more than one limitation with the *or* relation, not *and*, you can split your policy in two, each with one of these limitations. diff --git a/docs/personalization/api_reference/content_api.md b/docs/personalization/api_reference/content_api.md index 992e68f498..22d0aa5f85 100644 --- a/docs/personalization/api_reference/content_api.md +++ b/docs/personalization/api_reference/content_api.md @@ -4,10 +4,8 @@ description: Personalization server can use external information about the items # Content API -Apart from the [events]([[= user_doc =]]/personalization/event_types) collected by the Personalization client, -the Personalization server can use external information about the products. -This information must be uploaded to the Personalization server by the administrator -of the website. +Apart from the [events]([[= user_doc =]]/personalization/event_types) collected by the Personalization client, the Personalization server can use external information about the products. +This information must be uploaded to the Personalization server by the administrator of the website. The following information can be loaded to the recommendation solution: @@ -18,22 +16,19 @@ The following information can be loaded to the recommendation solution: For more information about personalization, see [Introduction](personalization.md) and [Best practices](recommendation_integration.md). The Personalization client provides a REST interface that accepts items in XML format. -You can use the interface to post item information within the request's body into the store,  -and to display or update the items directly. +You can use the interface to post item information within the request's body into the store, and to display or update the items directly. You can use HTTP methods to create, update or retrieve items that are in the data store. !!! note "Authentication" For getting or posting content data, basic authentication is enabled by default. - Use your customer ID and license key as username and password. - If authentication is enabled for recommendation requests and you want to change - this, contact support@ibexa.co. + Use your customer ID and license key as username and password. + If authentication is enabled for recommendation requests and you want to change this, contact support@ibexa.co. ## GET requests -Use the GET method to retrieve all information that is stored in the database -for the given item ID: +Use the GET method to retrieve all information that is stored in the database for the given item ID: `GET: https://admin.perso.ibexa.co/api/[customerid]/item/[itemtypeid]/[itemid]` @@ -44,12 +39,11 @@ Use the POST request to create or update items with the given ID in the database `POST: https://admin.perso.ibexa.co/api/[customerid]/item` A body of the request must contain a valid XML document. -Once uploaded, the item is scheduled to be inserted in the database, and it -is not directly available. +Once uploaded, the item is scheduled to be inserted in the database, and isn't directly available. ## DELETE requests -Use the DELETE method to delete all information that is related to the given item ID. +Use the DELETE method to delete all information that is related to the given item ID. `DELETE: https://admin.perso.ibexa.co/api/[customerid]/item/[itemtypeid]/[itemid]?lang=` @@ -68,7 +62,7 @@ The following call attributes are available: ### Request object format -An XML representation of the data object used for item import can look like this: +An XML representation of the data object used for item import can look like this: ``` xml @@ -104,8 +98,7 @@ An XML representation of the data object used for item import can look like this !!! note "XML schema definition" - The current schema that is used for interpreting the XML objects - can be seen [here](https://admin.perso.ibexa.co/api/00000/item/schema.xsd). + The current schema that is used for interpreting the XML objects can be seen [here](https://admin.perso.ibexa.co/api/00000/item/schema.xsd). The following keys and attributes used in the XML object are available: @@ -138,62 +131,53 @@ To check how many digits the fractional unit of a currency has, see the [ISO 421 ##### Validity -Items with defined validity are recommended only in the specified timeframe. -Values in the `validto` and `validfrom` attributes must follow the [XSD format](https://www.w3.org/TR/xmlschema-2/#dateTime) -and do not include the time zone. +Items with defined validity are recommended only in the specified timeframe. +Values in the `validto` and `validfrom` attributes must follow the [XSD format](https://www.w3.org/TR/xmlschema-2/#dateTime) and don't include the time zone. Time zone is always your time zone. ##### Category path -With the data import interface, you can upload information about the paths -to categories in which the product is located. +With the data import interface, you can upload information about the paths to categories in which the product is located. However, the category path can be also updated as a result of the "Click" events. -If you regularly upload product data, the "Click" event cannot contain the category -path information. +If you regularly upload product data, the "Click" event cannot contain the category path information. Otherwise, the following negative side effects occur: - Every new category path attached to the "Click" event is appended to a list of the categories of the product - Imported product data overwrites the collected category paths -For example, when a product that is originally located under `Garden` is clicked -in the "Hot Sellers" section, the category path `TopSeller` is sent. +For example, when a product that is originally located under `Garden` is clicked in the "Hot Sellers" section, the category path `TopSeller` is sent. #### Content items/products with no attributes All the elements and attributes except the `type` and `id` are optional. You can therefore upload a product without any additional information. -You do it, for example, when a random recommendation model is used -or you want to want to apply ad-hoc boosting and filtering of recommendations. +You do it, for example, when a random recommendation model is used or you want to want to apply ad-hoc boosting and filtering of recommendations. As a result, the Personalization server randomly recommends the imported items/products. -This can prove useful for a news agency, where new items are published very often. +This can prove useful for a news agency, where new items are published often. #### Custom attributes You can also define custom attributes under the `` key. This section can only contain values that are distinct and used to build pre-filtered models. -By default, it is assumed that every attribute is of type "NOMINAL", which means that -there is a limited set of values, and values of an attribute are treated as distinct -when calculating the results of a content-based model. +By default, it's assumed that every attribute is of type "NOMINAL", which means that there is a limited set of values, and values of an attribute are treated as distinct when calculating the results of a content-based model. -If you have an attribute that is of type "NUMERIC", and you add another attribute -of the same type, the Personalization server treats the two values as a range. +If you have an attribute that is of type "NUMERIC", and you add another attribute of the same type, the Personalization server treats the two values as a range. ``` xml ``` -However, if the other attribute is of type "NOMINAL", they are both treated -as different and have no "distance-based similarity". +However, if the other attribute is of type "NOMINAL", they're both treated as different and have no "distance-based similarity". -Another typical example of a custom attribute is the color of an item. +Another typical example of a custom attribute is the color of an item. To upload the value to the data store, add the following line under the `` key. ``` xml ``` -You can have multiple attributes with the same name and different type. +You can have multiple attributes with the same name and different type. For example, `size` can be expressed as a number (40.5) or as a code ("L"). ## Responses @@ -211,11 +195,8 @@ The following HTTP response codes are used by the recommendation controller: ## Transferring item identifiers -You could use the data import interface to help migrate the database, -when it involves changing item IDs of items that are supported by the -Personalization server. -If you transfer items from one ID to another, you can use the events recorded -for "old" item IDs to calculate model results that present "new" IDs. +You could use the data import interface to help migrate the database, when it involves changing item IDs of items that are supported by the Personalization server. +If you transfer items from one ID to another, you can use the events recorded for "old" item IDs to calculate model results that present "new" IDs. Use the following method to pass the XML object: @@ -236,6 +217,4 @@ The old item is wiped, including all attributes. !!! note - The attributes of the "old" item ID are not moved or merged, and if you - rely on attributes, for example, for filtering based on prices, - you must reimport the new item. + The attributes of the "old" item ID aren't moved or merged, and if you rely on attributes, for example, for filtering based on prices, you must reimport the new item. diff --git a/docs/personalization/api_reference/recommendation_api.md b/docs/personalization/api_reference/recommendation_api.md index a465d5c3b7..22b98d15ff 100644 --- a/docs/personalization/api_reference/recommendation_api.md +++ b/docs/personalization/api_reference/recommendation_api.md @@ -5,20 +5,15 @@ month_change: true # Recommendation API -Recommendations are retrieved from the Personalization server with RESTful requests -that rely on the HTTP GET method. -The result can a list of item IDs that can then be used to call the underlying -CMS or shop system and postload the necessary information for the rendering process. +Recommendations are retrieved from the Personalization server with RESTful requests that rely on the HTTP GET method. +The result can a list of item IDs that can then be used to call the underlying CMS or shop system and postload the necessary information for the rendering process. -For more information about Personalization, see [Introduction](personalization.md), -[Basic integration](recommendation_integration.md). +For more information about Personalization, see [Introduction](personalization.md) and [Basic integration](recommendation_integration.md). !!! note "Authentication" - For fetching recommendations, authentication is disabled by default, and - it must be disabled when you use [JSONP](https://en.wikipedia.org/wiki/JSONP) for response handling. - If authentication is enabled for recommendation requests and you want to change - this, contact support@ibexa.co. + For fetching recommendations, authentication is disabled by default, and it must be disabled when you use [JSONP](https://en.wikipedia.org/wiki/JSONP) for response handling. + If authentication is enabled for recommendation requests and you want to change this, contact support@ibexa.co. ## GET requests @@ -33,33 +28,30 @@ For the request to return recommendations, you must provide the following parame |Parameter|Description|Value| |---|---|---| |`customerid`|A customer ID (for example "00000"), as defined when [enabling Personalization](enable_personalization.md#set-up-customer-credentials). Can be used to identify a website in installations that [hosts multiple SiteAccesses]([[= user_doc =]]/personalization/use_cases/#multiple-website-hosting).|alphanumeric| -|`userid`|An ID of the tracked user in the website (for example, an internal customer code, a session code or a cookie for anonymous users.|alphanumeric| -|`scenarioid`|An ID of the scenario used for providing recommendations, as defined in the Back Office.|alphanumeric| +|`userid`|An ID of the tracked user in the website (for example, an internal customer code, a session code, or a cookie for anonymous users.|alphanumeric| +|`scenarioid`|An ID of the scenario used for providing recommendations, as defined in the back office.|alphanumeric| |`extension`|A format of the response (either JSON or JSONP).|`json` or `jsonp`| !!! caution "Parameter encoding limitations" - All parameters must be URL-encoded (see RFC 3986) and cannot contain a backslash - (`%5C`) character. + All parameters must be URL-encoded (see RFC 3986) and cannot contain a backslash (`%5C`) character. ### Customizing the recommendation request -You can customize the recommendation request by using additional query string parameters. +You can customize the recommendation request by using additional query string parameters. For example, you can send the following request to the Personalization server:  `GET https://reco.perso.ibexa.co/api/v2/00000/john.doe/landing_page.json ?contextitems=123&categorypath=%2FCamera%2FCompact&attribute=title&attribute=deeplink,description&numrecs=8` -The request fetches 8 recommendations for user ID `john.doe`, who is viewing item 123 -and the category `/Camera/Compact`, based on the scenario with the identifier `landing_page`. -The recommendation response uses the JSON format and should include values of -`title`, `deeplink` and `description` attributes. +The request fetches 8 recommendations for user ID `john.doe`, who is viewing item 123 and the category `/Camera/Compact`, based on the scenario with the identifier `landing_page`. +The recommendation response uses the JSON format and should include values of `title`, `deeplink` and `description` attributes. You can use the following parameters to customize a request: |Parameter|Example|Description|Value| |---|---|---|---| |`numrecs`|20|Defines a number of recommendations to be delivered. The lower this value, the shorter the response time. The default value is 10. |1 to 50| -|`contextitems`|10,13,14 or "CLICKED"|A comma-separated list of items that the user is viewing on the web page. The list is required by [context-based recommendations]([[= user_doc =]]/personalization/recommendation_models). All items must be of the same type. The type is defined in the scenario configuration. If history code is used ("CLICKED","CONSUMED", "OWNS", "RATED" or "BASKET"), context items are pulled from the user profile (for example, the most recent clicks or purchases). This parameter is optional. |1 to 2147483647 (or alphanumeric if enabled)| +|`contextitems`|10,13,14, or "CLICKED"|A comma-separated list of items that the user is viewing on the web page. The list is required by [context-based recommendations]([[= user_doc =]]/personalization/recommendation_models). All items must be of the same type. The type is defined in the scenario configuration. If history code is used ("CLICKED","CONSUMED", "OWNS", "RATED" or "BASKET"), context items are pulled from the user profile (for example, the most recent clicks or purchases). This parameter is optional. |1 to 2147483647 (or alphanumeric if enabled)| |`outputtypeid`|1|Required for scenarios that are defined with multiple output item types, otherwise optional. By default it's the first/lowest output type enabled in the scenario config.|numeric| |`crosscontenttype`| |Used instead of `outputtypeid`, if set to true, displays recommendations for all output types defined in the scenario. | boolean| |`jsonpCallback`|"myCallback"|Function or method name (used for JSONP request only). It can be a function ("callme"), or a method ("obj.callme"). The default value is "jsonpCallback".|legal JavaScript function call| @@ -71,9 +63,8 @@ You can use the following parameters to customize a request: ##### Submodel parameters -If your recommendation model uses submodels to group content items/products based -on an attribute, you can pass the following parameters to request recommendations -for a specific group. +If your recommendation model uses submodels to group content items/products based on an attribute, you can pass the following parameters to request recommendations for a specific group. + For more information, see [Submodels]([[= user_doc =]]/personalization/recommendation_models/#submodels). |Parameter|Example|Description|Value| @@ -84,9 +75,9 @@ For more information, see [Submodels]([[= user_doc =]]/personalization/recommend !!! note "Multiple submodels in recommendations" If you send a request with two attribute keys, the response contains an intersection of two recommendation sets that originate from submodels calculated for these attributes. - + For example, to get recommendations for items of certain type that are limited by submodels based on both a nominal and numeric attribute, you can send the following request: - + `GET https://reco.perso.ibexa.co/api/v2/00000/john.doe/landing_page.json?numrecs=50&outputtypeid=1&width-range=10:30&color=green` !!! note "Dynamic attribute submodels" @@ -102,8 +93,7 @@ For more information, see [Submodels]([[= user_doc =]]/personalization/recommend ##### Segment parameters -If you have configured segments, you can use them in the recommendation model. Pass the following parameter -to request recommendations for a specific segment or segment group. +If you have configured segments, you can use them in the recommendation model. Pass the following parameter to request recommendations for a specific segment or segment group. Parameter|Example|Description|Value| |---|---|---|---| @@ -113,21 +103,18 @@ For more information, see [Segments]([[= user_doc =]]/personalization/segment_ma ## Responses -The recommendation request returns information about the currently used context -items and an array of recommendation objects in JSON or JSONP format. -The result can be integrated into any webpage on the client side by using script code. -To track user actions like "clickrecommended" and "rendered", use the links -delivered in the response. +The recommendation request returns information about the currently used context items and an array of recommendation objects in JSON or JSONP format. +The result can be integrated into any webpage on the client side by using script code. +To track user actions like "clickrecommended" and "rendered", use the links delivered in the response. + For more information, see inline comments below. !!! note "Previewing recommendations" - You can preview the actual responses that come from the Personalization server - and how they are rendered in the user interface. + You can preview the actual responses that come from the Personalization server and how they're rendered in the user interface. For more information, see [Previewing scenario results]([[= user_doc =]]/personalization/previewing_scenario). - -For more information about integrating recommendations in the web page, -see [Best practices](recommendation_integration.md). + +For more information about integrating recommendations in the web page, see [Best practices](recommendation_integration.md). ### Response object format @@ -266,18 +253,13 @@ Error messages can change, don't use them for automated processing. !!! note "Rendering data" - If data import with the [Content API](content_api.md) was successful, you - can also fetch data used for rendering (for example "title", "description" - or "deeplink") from the recommendation response. + If data import with the [Content API](content_api.md) was successful, you can also fetch data used for rendering (for example "title", "description" or "deeplink") from the recommendation response. ## Cache recommendations -The Personalization server's response can be cached. -Depending on the recommendation model and context, it can drastically reduce -the number of recommendation requests. -The recommendation service supports the following HTTP headers to enable cache -control on the client side (all date values must follow the "HTTP-date" format -as defined by [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616)): +The Personalization server's response can be cached. +Depending on the recommendation model and context, it can drastically reduce the number of recommendation requests. +The recommendation service supports the following HTTP headers to enable cache control on the client side (all date values must follow the "HTTP-date" format as defined by [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616)): |Scope|Header|Description|Example| |---|---|---|---| @@ -285,22 +267,16 @@ as defined by [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616)): |Response|`Last-Modified`|The last modification date of the recommendations.|`Last-Modified: Tue, 15 Nov 2013 12:45:26 GMT`| |Response|`Expires`|Gives the date/time after which the response is outdated|`Expires: Thu, 01 Dec 2013 16:00:00 GMT`| -The last modification timestamp indicates a change that could influence the -recommendation response. -It depends on an updated recommendation calculation, an update of an item or -certain scenario configuration changes.  +The last modification timestamp indicates a change that could influence the recommendation response. +It depends on an updated recommendation calculation, an update of an item or certain scenario configuration changes.  -The expiration timestamp is a best-effort prediction based on the model configuration -and provided context. -The shortest expiration period is 5 minutes from the request time, the longest -is 24 hours. +The expiration timestamp is a best-effort prediction based on the model configuration and provided context. +The shortest expiration period is 5 minutes from the request time, the longest is 24 hours. -You don't usually have to calculate the expiration time manually. -Instead, make sure that the `Expires` header is used in the configuration -of your caching system and not a static value out of your configuration. +You don't usually have to calculate the expiration time manually. +Instead, make sure that the `Expires` header is used in the configuration of your caching system and not a static value out of your configuration. -To learn how Personalization server calculates the `Expires` header that's provided -to your caching system, see the following table with caching strategy examples: +To learn how Personalization server calculates the `Expires` header that's provided to your caching system, see the following table with caching strategy examples: | Model | Context | Expiration time | Description | |------|------|-----|-----| diff --git a/docs/personalization/api_reference/tracking_api.md b/docs/personalization/api_reference/tracking_api.md index c6755c46f4..3c62742e24 100644 --- a/docs/personalization/api_reference/tracking_api.md +++ b/docs/personalization/api_reference/tracking_api.md @@ -1,11 +1,10 @@ --- -description: Allows to track items using it ID. It covers many content types with the same ID configured for tracking. +description: Allows to track items based on an ID. It covers many content types with the same ID configured for tracking. --- # Tracking API -To provide recommendations, a tracking process needs to collect user behavior -on the customer's site. +To provide recommendations, a tracking process needs to collect user behavior on the customer's site. The most popular user events are: - Click - When a user opens a detail page. @@ -14,34 +13,30 @@ The most popular user events are: - Login - When a user logs in on a website - Clickrecommended - When a user clicks a recommendation -For a complete list of events, see [Event types]([[= user_doc =]]/personalization/event_types) in the user documentation.  -Depending on the event type, some additional parameters, such as item price -or user rating, must be provided. +For a complete list of events, see [Event types]([[= user_doc =]]/personalization/event_types) in User Documentation.  +Depending on the event type, some additional parameters, such as item price or user rating, must be provided. + +Importing historical user data can help you reduce the delay in delivery of high quality recommendations. -Importing historical user data can help you reduce the delay in delivery of high -quality recommendations. For more information, see [Importing historical user tracking data](importing_historical_user_tracking_data.md). -Apart from the tracking API, you can add tracking to the website by integrating -a JavaScript library. +Apart from the tracking API, you can add tracking to the website by integrating a JavaScript library. + For more information, see [Tracking with ibexa-tracker.js](tracking_with_ibexa-tracker.md). ## Definitions You can use the tracking API both in eCommerce and content publishing scenarios. -eCommerce mostly uses the term "product", whereas the Publisher domain widely -uses the terms "content", "article", "images" or "videos". +eCommerce mostly uses the term "product", whereas the Publisher domain widely uses the terms "content", "article", "images" or "videos". Therefore, a generic term "item" is used instead to cover all the mentioned types. -For further segmentation the term "item type" is used, which, in combination -with the item ID itself, defines a domain specific object. +For further segmentation the term "item type" is used, which, in combination with the item ID itself, defines a domain specific object. For example, an electronic product can be defined by item type "1" and item id "3298", while a textile product can be defined by item type "2" and item id "3298". !!! note - Usually only one item type is sufficient in the eCommerce business as each - product available in an eCommerce shop has a unique identifier. + Usually only one item type is sufficient in the eCommerce business as each product available in an eCommerce shop has a unique identifier. |Domain|Item ID|Item Type| |---|---|---| @@ -49,12 +44,9 @@ while a textile product can be defined by item type "2" and item id "3298". |Content publishing|Video|ID of a video| |Content publishing|Photo Gallery|ID of a photo gallery| -Assuming the numbering of content is independent and the same item ID is used -for two items of different item types, it is impossible to tell the difference -if there is no segmentation by item types. +Assuming the numbering of content is independent and the same item ID is used for two items of different item types, it's impossible to tell the difference if there is no segmentation by item types. -If an article, a video and a photo gallery have the same item ID, use different -item types to separate the items that are tracked. +If an article, a video and a photo gallery have the same item ID, use different item types to separate the items that are tracked. For example: - item type "1" and itemid "29712" -> article @@ -63,88 +55,64 @@ For example: !!! note - Even if item IDs cannot overlap in a customer's system, [[= product_name_base =]] recommends using - different item types to provide independent tracking and cross-item type recommendations, - such as, for example, "Users who read this article also watched these videos" - or "Users who liked this gallery also read these articles". + Even if item IDs cannot overlap in a customer's system, [[= product_name_base =]] recommends using different item types to provide independent tracking and cross-item type recommendations, such as, for example, "Users who read this article also watched these videos" or "Users who liked this gallery also read these articles". ## Identifiers ### User identifier -High quality recommendations can only be delivered if the underlying data -is correct and consistent.  -For consistent tracking it is crucial to choose and use a consistent identifier for a user. +High quality recommendations can only be delivered if the underlying data is correct and consistent.  +For consistent tracking it's crucial to choose and use a consistent identifier for a user. A user usually visits a website anonymously. -Therefore, their identifier is either a first-party cookie or a session ID -provided by the website.  -If there is no existing user ID handling that can be re-used, it is recommended that -you use your own cookie and set the expiry date to at least 90 days from the last usage. -If there is a login mechanism, the user is usually tracked with a temporary -identifier before the login. +Therefore, their identifier is either a first-party cookie or a session ID provided by the website.  +If there is no existing user ID handling that can be re-used, it's recommended that you use your own cookie and set the expiry date to at least 90 days from the last usage. +If there is a login mechanism, the user is usually tracked with a temporary identifier before the login. Immediately after a successful login process a Login event must be sent. -At this point a [pseudonymous](https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32016R0679&from=EN#d1e1489-1-1) user ID, -for example, a system's internal registration id, must be used.  +At this point a [pseudonymous](https://eur-lex.europa.eu/legal-content/EN/TXT/HTML/?uri=CELEX:32016R0679&from=EN#d1e1489-1-1) user ID, for example, a system's internal registration id, must be used.  After logout, the anonymous user ID can be used again. !!! note - The user identifier is required in tracking requests, otherwise it is discarded - from the tracking servers. + The user identifier is required in tracking requests, otherwise it's discarded from the tracking servers. - If a browser has JavaScript or cookies disabled, make sure that you put some - "dummy" value as identifier in the tracking request to avoid losing tracking - information. - Even if the event is not user-specific, it is still useful for [popularity models]([[= user_doc =]]/personalization/recommendation_models/). + If a browser has JavaScript or cookies disabled, make sure that you put some "dummy" value as identifier in the tracking request to avoid losing tracking information. + Even if the event isn't user-specific, it's still useful for [popularity models]([[= user_doc =]]/personalization/recommendation_models/). The Personalization server internally creates a hash of every user ID. -The original ID is not saved. -It is still possible that the original ID appears in the log files for the debugging -purposes but log files are purged regularly. +The original ID isn't saved. +it's still possible that the original ID appears in the log files for the debugging purposes but log files are purged regularly. The user ID is case sensitive. ### Item identifiers -Persons responsible for the sales policy in place in your organization must decide -what should be presented as recommendations on the website. +Persons responsible for the sales policy in place in your organization must decide what should be presented as recommendations on the website. In the eCommerce business you mostly have the possibility to track items based on: - Stock Keeping Unit (SKU) or - Universal Product Code (UPC) The exact identifiers that are tracked are also recommended ("what-you-track-is-what-you-get"). -By default, it is not possible to track SKUs but recommend UPCs. +By default, it's not possible to track SKUs but recommend UPCs. The following use case is typical for eCommerce business: -Customer A implements the Personalization server and decides to use the SKU -as item identifiers and recommendable items. -End users who browse through the shop probably get recommendations of -the same item that is currently displayed but in a different size and/or color, -a so-called "variant". -The Personalization server does not recognize relations between items, therefore, -every single SKU is used to calculate similarities between them. -In the case of bestsellers, this could lead to the appearance of a shirt -in size L on position 2 and the same shirt in size M on position 4. +Customer A implements the Personalization server and decides to use the SKU as item identifiers and recommendable items. +End users who browse through the shop probably get recommendations of the same item that is currently displayed but in a different size and/or color, a so-called "variant". +The Personalization server doesn't recognize relations between items, therefore, every single SKU is used to calculate similarities between them. +In the case of bestsellers, this could lead to the appearance of a shirt in size L on position 2 and the same shirt in size M on position 4. Customer B decides to use the UPC as item identifiers. -This results in recommendations that do not contain variations of the currently shown item. -Therefore, the detail page of shirt X does not contain a recommendation -for the same shirt in a different size. -And the same shirt does not show up twice on a list of bestseller recommendations. +This results in recommendations that don't contain variations of the currently shown item. +Therefore, the detail page of shirt X doesn't contain a recommendation for the same shirt in a different size. +And the same shirt doesn't show up twice on a list of bestseller recommendations. -If the size of an item or the color is selectable on a detail page of an item, -you may prefer to use the UPC. -If recommendations of the same item in different sizes or colors are desired, -you should use the SKU as item identifiers. +If the size of an item or the color is selectable on a detail page of an item, you may prefer to use the UPC. +If recommendations of the same item in different sizes or colors are desired, you should use the SKU as item identifiers. -Remember to use the same identifier in all interactions between your website -and the Personalization server, for example, when a user buys an item, -clicks a recommendation or displays a product page. +Remember to use the same identifier in all interactions between your website and the Personalization server, for example, when a user buys an item, clicks a recommendation, or displays a product page. ## Request parameter categorypath -Category paths are logical tree structures that lead to items and are used for -recommendation filtering. +Category paths are logical tree structures that lead to items and are used for recommendation filtering. For example, "recommend only items from the same category". During recommendation requests, the category path must always be provided. @@ -152,30 +120,23 @@ The category path is a forward slash-separated list of categories from the root, The initial slash (if present) is ignored. Like all other parameters, the category path must be URL-encoded and cannot contain backslashes. -The "categorypath" parameter offers the possibility to provide category-based -recommendations without an explicit export of the structure of a customer's website. -If enabled by [[= product_name_base =]], it is used for on-the-fly updating of item categories. -If an item is moved to another category, it is handled as present in both -categories until the old category ages out or is forcibly deleted. +The "categorypath" parameter offers the possibility to provide category-based recommendations without an explicit export of the structure of a customer's website. +If enabled by [[= product_name_base =]], it's used for on-the-fly updating of item categories. +If an item is moved to another category, it's handled as present in both categories until the old category ages out or is forcibly deleted. Multiple category locations of an item (multi-homing) are therefore possible. !!! note "Category paths" - When you import your own item metadata by using the Personalization server - import interface, you might choose to not provide the category path - in the Click event. - Category path is required by default, contact [[= product_name_base =]] to change the default - configuration. + When you import your own item metadata by using the Personalization server import interface, you might choose to not provide the category path in the Click event. + Category path is required by default, contact [[= product_name_base =]] to change the default configuration. ## Track events !!! note - Events are forwarded to the Personalization server with HTTP or HTTPS requests - (or [RESTful-Requests](https://en.wikipedia.org/wiki/Representational_state_transfer)). + Events are forwarded to the Personalization server with HTTP or HTTPS requests (or [RESTful-Requests](https://en.wikipedia.org/wiki/Representational_state_transfer)). Both GET and POST methods are allowed for the event tracking. - Make sure that all embedded and query string parameters are URL encoded and - do not use a backslash, encoded as %5C\. + Make sure that all embedded and query string parameters are URL encoded and don't use a backslash, encoded as %5C\. ### Event parameters @@ -186,23 +147,18 @@ For a list of embedded parameters that each of the events may use, see the follo |`customerid`|A customer ID (for example "00000"). Can be used to identify a website in installations that [hosts multiple SiteAccesses]([[= user_doc =]]/personalization/use_cases/#multiple-website-hosting).|alphanumeric| |userid|A user's ID on the website of the customer. It could be an internal customer code, a session code or a cookie for anonymous users.|URL-encoded alphanumeric| |`itemtypeid`|Item type ID.|1 to 2147483647| -|`itemid`|A unique ID of the item the user has clicked.
String-based identifiers are also supported as item IDs to track content on a website, but it is discouraged due to fraud and security issues. If you are unable to provide numeric identifiers for the tracking process, contact [[= product_name_base =]] for further information and implementation notes.|1 to 2147483647| +|`itemid`|A unique ID of the item the user has clicked.
String-based identifiers are also supported as item IDs to track content on a website, but it's discouraged due to fraud and security issues. If you're unable to provide numeric identifiers for the tracking process, contact [[= product_name_base =]] for further information and implementation notes.|1 to 2147483647| |`sourceuserid`|User identifier valid up to now(usually some anonymous session ID)|URL-encoded alphanumeric| |`targetuserid`|User identifier valid from now on (usually an account ID or login name)|URL-encoded alphanumeric| ### Basket event The Basket event can be used to add products to a user's shopping cart. -This event is especially valuable if anonymized checkout is allowed or no recurring -user identification is possible. -By using the shopping cart products as input for getting recommendations, problems -with an empty profile or no buy history for the user can be solved. -The more valuable Basket events instead of recent user clicks can be used to provide -personalized recommendations. -It also happens quite often that users "store" products on their shopping [wishlist](#wishlist-event) -and plan to buy them later. -With the help of this information, personalized shopping cart-based recommendations -can be provided in the whole shop. +This event is especially valuable if anonymized checkout is allowed or no recurring user identification is possible. +By using the shopping cart products as input for getting recommendations, problems with an empty profile or no buy history for the user can be solved. +The more valuable Basket events instead of recent user clicks can be used to provide personalized recommendations. +It also happens quite often that users "store" products on their shopping [wishlist](#wishlist-event) and plan to buy them later. +With the help of this information, personalized shopping cart-based recommendations can be provided in the whole shop. `GET https://event.perso.ibexa.co/api/[customerid]/basket/[userid]/[itemtypeid]/[itemid]` @@ -211,9 +167,7 @@ This event has no query string parameters. ### Blacklist event -If a website offers a link or button that allows feedback similar to "do not -recommend this product to me anymore", a user could express that they have bought -it already in another shop. +If a website offers a link or button that allows feedback similar to "don't recommend this product to me anymore", a user could express that they have bought it already in another shop. The format of the URL is: @@ -225,58 +179,48 @@ This event has no query string parameters.  ### Buy event As the name suggests, this event is used when an end user buys an item. -It must be sent to the event tracker at the end of a successful check-out process -to ensure that no further action of the user can result in an abort. +It must be sent to the event tracker at the end of a successful check-out process to ensure that no further action of the user can result in an abort. The URL has the following format:  `GET https://event.perso.ibexa.co/api/[customerid]/buy/[userid]/[itemtypeid]/[itemid]?fullprice=2.50EUR&quantity=4` For a detailed description of embedded parameters, see [event parameters](#event-parameters). -In addition to the fact that an item is bought, this event should provide information -about the product price and quantity. +In addition to the fact that an item is bought, this event should provide information about the product price and quantity. |Name|Description|Values| |---|---|---| |`quantity`|The number of products a user has bought. Default value is "1". You can send n events instead of setting this parameter to n. This parameter is optional.|integer (default is "1")| |`fullprice`|A price for a single product. It contains the price in decimal format plus the currency ISO 4217 code. If the price has a decimal part, the point must be used. There can be no space between price and currency. This parameter is optional.|currency, for example "12.45EUR" or "456JPY"| -For example, if a user bought 4 pens for 10 Euros, `fullprice` can be set to "2.50EUR" -and `quantity` can be set to 4. +For example, if a user bought 4 pens for 10 Euros, `fullprice` can be set to "2.50EUR" and `quantity` can be set to 4. The Buy event is only relevant if the user is charged per product, like in a classic shop. -If products are sold on a subscription basis, or the web presence is ad-sponsored, -this event type is not applicable. +If products are sold on a subscription basis, or the web presence is ad-sponsored, this event type isn't applicable. #### Prices in a Buy event Every Buy event can contain a price. -If the price is set, it is stored with the event and used for calculating the -revenue for statistics. +If the price is set, it's stored with the event and used for calculating the revenue for statistics. The price must be a price the user paid for the item, including all taxes and discounts.  -If product price filtering is activated, the information provided over the product -import is used. +If product price filtering is activated, the information provided over the product import is used. + For more information, see [Content API](content_api.md). -The currency is stored with the price and normalized only when statistic information -is requested. -It is often a good choice to select a base currency and convert prices before -sending the buy event. -The price attached to a buy event never overwrites the price which was defined -in an item import. +The currency is stored with the price and normalized only when statistic information is requested. +It's often a good choice to select a base currency and convert prices before sending the buy event. +The price attached to a buy event never overwrites the price which was defined in an item import. ### Click event When the end user opens an item/article detail, a Click events is sent. -The Click event often provides additional information about the category -structure of the website. +The Click event often provides additional information about the category structure of the website. !!! note - User IDs are not stored in the database. - They are irreversibly anonymized before saving to disk or building the - recommendation model. + User IDs aren't stored in the database. + They're irreversibly anonymized before saving to disk or building the recommendation model. The URL to track user clicks has the following format: @@ -290,17 +234,17 @@ Some optional request parameters can be set over query string parameters (GET pa |Name|Description|Values| |---|---|---| -|`categorypath`|The forward slash-separated path of categories of the item. Like all other parameters it must be URL-encoded, for example `%2FCameras%26Foto%2FCompact%20Cameras%2FCanon`.
For use cases, see [Category path filters]([[= user_doc =]]/personalization/filters/#category-path-filters) in the user documentation.|URL-encoded string.
Initial and trailing slashes are ignored: "/Cameras/" is the same as "Cameras".| +|`categorypath`|The forward slash-separated path of categories of the item. Like all other parameters it must be URL-encoded, for example `%2FCameras%26Foto%2FCompact%20Cameras%2FCanon`.
For use cases, see [Category path filters]([[= user_doc =]]/personalization/filters/#category-path-filters) in User Documentation.|URL-encoded string.
Initial and trailing slashes are ignored: "/Cameras/" is the same as "Cameras".| ### Consume event !!! note "eCommerce vs. content publishing" The Consume event is important for content publishing websites. - For eCommerce stores, this event is not required but can be used in custom implementations. + For eCommerce stores, this event isn't required but can be used in custom implementations. The event is sent when the end user stays on the page for a predefined period of time. -It is then assumed that the user consumed the item (read an article or watched a video). +It's then assumed that the user consumed the item (read an article or watched a video). The URL has the following format: @@ -314,24 +258,17 @@ The following table lists the request parameters: |`percentage`|Informs how much of an item was consumed, for example, that an article was read only in 20%, a movie was watched in 90% or someone finished 3/4 of all levels of a game.|0-100| The logic for calculating the percentage is defined by the implementation. -For articles, this could be by scrolling down, for a movie/video based on the -consumption part.  +For articles, this could be by scrolling down, for a movie/video based on the consumption part.  You must decide what 100% consumption means. For example, a movie contains end titles that are almost never consumed. Therefore, they should not be part of the percentage calculation. -The simplest implementation for articles is a JavaScript timer, which sends this -event after a predefined time has elapsed (and the user did not leave the page). -The timespan after that the event is triggered should be dependent on the content, -for example, it could be 30 seconds for a small newspaper article or a timespan -calculated by the amount of words. +The simplest implementation for articles is a JavaScript timer, which sends this event after a predefined time has elapsed (and the user did not leave the page). +The timespan after that the event is triggered should be dependent on the content, for example, it could be 30 seconds for a small newspaper article or a timespan calculated by the amount of words. !!! note "Incremental tracking of consume events" - Consume events for a user can be sent incrementally as the recommender uses - only the highest percentage rate. For example, if a user watches a movie, - the website could send Consume events in 10% steps to avoid losing tracking - information when the browser window is forcibly closed. + Consume events for a user can be sent incrementally as the recommender uses only the highest percentage rate. For example, if a user watches a movie, the website could send Consume events in 10% steps to avoid losing tracking information when the browser window is forcibly closed. ### Deletefrombasket event @@ -357,19 +294,13 @@ This event has no query string parameters.  ### Login event -Recommendations rely on the fact that user actions can be correlated over a longer -period of time. -Moreover, recommendations similar to "users who viewed this product ultimately -bought it" require correlating Click events with subsequent Buy events. -In general, users tend to browse a website anonymously and add products to their -shopping cart. -Up to this point, a user is identified by a visit-scoped variable (for example, -a session ID or a first party cookie). +Recommendations rely on the fact that user actions can be correlated over a longer period of time. +Moreover, recommendations similar to "users who viewed this product ultimately bought it" require correlating Click events with subsequent Buy events. +In general, users tend to browse a website anonymously and add products to their shopping cart. +Up to this point, a user is identified by a visit-scoped variable (for example, a session ID or a first party cookie). During the check-out of the shopping cart, a user probably logs in to an existing account. -As a result, the user identifier changes from an anonymous visit-scoped ID -(sourceuserid) to a pseudonymous, persistent account ID (targetuserid). -You should correlate both IDs to correlate the Buy events (account ID) with -the preceding Click events (visit-scoped ID). +As a result, the user identifier changes from an anonymous visit-scoped ID (sourceuserid) to a pseudonymous, persistent account ID (targetuserid). +You should correlate both IDs to correlate the Buy events (account ID) with the preceding Click events (visit-scoped ID). The Login event serves exactly this purpose. The format of the URL is:  @@ -381,8 +312,7 @@ For a detailed description of embedded parameters, see [event parameters](#event ### Rate event Publishers, media or shops often allow commenting/rating products, articles or movies. -If a user comments on an item, it indicates a special interest in this topic that has -to be treated separately. +If a user comments on an item, it indicates a special interest in this topic that has to be treated separately. The format of the URL is: @@ -400,15 +330,14 @@ A predefined rating can be submitted when the user comments on an item. ### Wishlist event This event is issued when the end user puts a product on their shopping list. -It means that they are interested in the product but plan to buy it later. +It means that they're interested in the product but plan to buy it later. This information can help return better recommendations. It can also be used as a basis for the price drop trigger. `GET https://event.perso.ibexa.co/api/[customerid]/wishlist/[userid]/[itemtypeid]/[itemid]?price=2.50EUR` For a detailed description of embedded parameters, see [event parameters](#event-parameters). -In addition to the fact that an item is placed on the shopping list, this event can provide information -about the product price at the time it was saved. +In addition to the fact that an item is placed on the shopping list, this event can provide information about the product price at the time it was saved. |Name|Description| |---|---| @@ -416,20 +345,15 @@ about the product price at the time it was saved. ## Tracking events based on recommendations -Tracking events based on integrated recommendations are the only way to measure the accuracy -and effectiveness of recommendations. +Tracking events based on integrated recommendations are the only way to measure the accuracy and effectiveness of recommendations. Both recommendation response and trigger message include requests to generate these events. -Events of this type inform the Personalization server about the recommendations that -were shown to the user and which of those recommendations were clicked. -Otherwise, it would be impossible to calculate reliable statistics that could be checked -against the customer's KPIs. +Events of this type inform the Personalization server about the recommendations that were shown to the user and which of those recommendations were clicked. +Otherwise, it would be impossible to calculate reliable statistics that could be checked against the customer's KPIs. A recommendation response includes requests to generate a Rendered and Clickrecommended event. The first one is executed when a recommendation is shown to the user. The second is called when a recommendation is clicked or otherwise accepted. -Sending Rendered events causes as many requests as recommendations to be displayed, -a Clickrecommended event is usually sent only once (when a user clicks on -a specific recommendation item). +Sending Rendered events causes as many requests as recommendations to be displayed, a Clickrecommended event is usually sent only once (when a user clicks on a specific recommendation item). Example of a recommendation response: @@ -491,11 +415,8 @@ For more information, see [Send messages with recommendations](../integrate_reco ### Rendered event -This event is sent when the website uses the recommendation provided by the recommendation -engine and renders it on the webpage. -In combination with a predefined threshold, it allows the recommender engine to -exclude this item from future results and avoid recommending the same item to the -same user multiple times during a session. +This event is sent when the website uses the recommendation provided by the recommendation engine and renders it on the webpage. +In combination with a predefined threshold, it allows the recommender engine to exclude this item from future results and avoid recommending the same item to the same user multiple times during a session. The URL for a Rendered event has the following format: @@ -503,14 +424,13 @@ The URL for a Rendered event has the following format: For a detailed description of embedded parameters, see [event parameters](#event-parameters). -It is common that recommendations are rendered as a block with multiple items. +It's common that recommendations are rendered as a block with multiple items. To save traffic and speed up the process, you can bundle multiple recommendations in one request. Several item IDs must be comma-separated. ### Clickrecommended event -When the end users clicks a recommendation, the following event is sent -to gather statistics related to the acceptance of recommendations. +When the end users clicks a recommendation, the following event is sent to gather statistics related to the acceptance of recommendations. The URL has the following format: @@ -523,12 +443,10 @@ The request parameters are: |---|---|---| |`scenario`|Name of the scenario, where recommendations originated from. This parameter is required.|URL-encoded alphanumeric| -The scenario parameter identifies the originating scenario to gain detailed statistics -about the scenario that motivated the user to click on a recommendation. +The scenario parameter identifies the originating scenario to gain detailed statistics about the scenario that motivated the user to click on a recommendation. This information comes with the recommendation from the recommendation controller.  -The event is used for providing statistics about how often users accepted the recommendations of -the configured recommendation scenario or considered them as valuable. +The event is used for providing statistics about how often users accepted the recommendations of the configured recommendation scenario or considered them as valuable. ### Triggeropened event @@ -595,13 +513,11 @@ User "Js79009234YU7" puts products 128 and 129 into the cart. `GET https://event.perso.ibexa.co/api/00000/basket/Js79009234YU7/1/129` -To buy selected products, user "Js79009234YU7" logs in and obtains an internal -identifier (for example, the registration ID) "johndoe" from the site. +To buy selected products, user "Js79009234YU7" logs in and obtains an internal identifier (for example, the registration ID) "johndoe" from the site. `GET https://event.perso.ibexa.co/api/00000/login/Js79009234YU7/johndoe` -The user buys two products from the cart: product 128 (one piece for the price - of EUR 19.99) and product 129 (2 pieces for the price of EUR 4.44 each). +The user buys two products from the cart: product 128 (one piece for the price of EUR 19.99) and product 129 (2 pieces for the price of EUR 4.44 each). `GET https://event.perso.ibexa.co/api/00000/buy/johndoe/1/128?quantity=1&fullprice=19.99EUR` `GET https://event.perso.ibexa.co/api/00000/buy/johndoe/1/129?quantity=2&fullprice=4.44EUR` diff --git a/docs/personalization/api_reference/user_api.md b/docs/personalization/api_reference/user_api.md index 417403e4e8..710baa385a 100644 --- a/docs/personalization/api_reference/user_api.md +++ b/docs/personalization/api_reference/user_api.md @@ -4,19 +4,18 @@ description: Use HTTP methods to correlate metadata with user data and combine u # User API -When generating recommendations, it is useful to have the ability to correlate metadata -with user data and combine users into clusters of certain type. -Such metadata can be gender, ZIP code, discount rate, etc.  -You can use the following user metadata import format to enrich the tracked data with information that cannot be calculated and must be provided by the end-user. +When generating recommendations, it's useful to have the ability to correlate metadata with user data and combine users into clusters of certain type. +Such metadata can be gender, ZIP code, discount rate, and more.  +You can use the following user metadata import format to enrich the tracked data with information that cannot be calculated and must be provided by the end-user. -If you plan to import user metadata, contact support@ibexa.co to ensure that you are compliant with privacy regulations. +If you plan to import user metadata, contact support@ibexa.co to ensure that you're compliant with privacy regulations. !!! note "Authentication" For importing metadata, basic authentication is enabled by default. - Use your customer ID and license key as username and password. + Use your customer ID and license key as username and password. If authentication is enabled for recommendation requests and you want change this, contact support@ibexa.co. - + ## GET requests Use the following request to fetch user attributes for the specified users: @@ -40,21 +39,16 @@ For the requests to function, you must provide the following parameters: |---|---|---| |`customerid`|A customer ID (for example "00000"), as defined when [enabling Personalization](enable_personalization.md#set-up-customer-credentials). Can be used to identify a website in installations that [hosts multiple SiteAccesses]([[= user_doc =]]/personalization/use_cases/#multiple-website-hosting).|alphanumeric| |`source`|An ID of the source of the specified user's metadata.|alphanumeric| -|`userid`|An ID of the tracked user in the website (for example, an internal customer code, a session code or a cookie for anonymous users.|alphanumeric| - +|`userid`|An ID of the tracked user in the website (for example, an internal customer code, a session code, or a cookie for anonymous users.|alphanumeric| + !!! caution "Parameter encoding limitations" - All parameters must be URL-encoded (see RFC 3986) and cannot contain slash, backslash or space - characters. - + All parameters must be URL-encoded (see RFC 3986) and cannot contain slash, backslash or space characters. + ##### Source -The `source` parameter defines the system that stores the specified user's metadata. -If you have multiple source systems for updating user attributes, -for example, a registration service, where users define their gender and age, -or an application that integrates with Facebook to source the brands the user "liked" in your shop, -every new upload of attributes will replace the attribute set that already exists -for the same user/source pair. +The `source` parameter defines the system that stores the specified user's metadata. +If you have multiple source systems for updating user attributes, for example, a registration service, where users define their gender and age, or an application that integrates with Facebook to source the brands the user "liked" in your shop, every new upload of attributes replaces the attribute set that already exists for the same user/source pair. If you need to get all the available attributes for all sources, apply the `allSources` query string parameter, for example: @@ -78,14 +72,14 @@ For example: ## DELETE request Use the following request to run an opt-out option to delete the user and all data related to this user. After this request, the user is deleted from the database. - + `DELETE: https://admin.perso.ibexa.co/api/[customerid]/user/[userid[,userid[...]]]` ## Responses ### Response object format -For an example of user metadata, see the following XML code. +For an example of user metadata, see the following XML code. The attribute keys and values are chosen at random. ``` xml @@ -111,6 +105,6 @@ The following attribute types are supported: - DATE - An XSD-formatted date, for example, "2014-08-07" - DATETIME - An XSD-formatted time without a time zone, for example, "2014-08-07T14:43:12" -- NOMINAL - A value from a fixed length list, for example "gender" or "favorite film genre". If you do not set the attribute type, this is the default value +- NOMINAL - A value from a fixed length list, for example "gender" or "favorite film genre". If you don't set the attribute type, this is the default value - NUMERIC - A decimal value, for example, "1.23" or "-2345" - TEXT - A longer text, usually free form diff --git a/docs/personalization/attribute_search_in_elasticsearch.md b/docs/personalization/attribute_search_in_elasticsearch.md index 8d08e24607..01c2b6a710 100644 --- a/docs/personalization/attribute_search_in_elasticsearch.md +++ b/docs/personalization/attribute_search_in_elasticsearch.md @@ -4,7 +4,8 @@ description: Attribute search uses Elasticsearch database to display dynamically # Attribute search in Elasticsearch database -If you use external data source for personalization data, it is not possible to display external content in the Universal Discovery Widget as it is deprecated. Attribute search is used in scenario preview and editorials models instead. +If you use external data source for personalization data, it's not possible to display external content in the Universal Discovery Widget as it's deprecated. +Attribute search is used in scenario preview and editorials models instead. Attribute search works like an autocomplete feature, but values are dynamically taken from the Elasticsearch database. ## Configure attribute search @@ -18,7 +19,7 @@ ibexa: personalization: output_type_attributes: : - title: + title: ``` @@ -41,7 +42,7 @@ ibexa: title: short_name description: body image: image - + ``` ![Attributes search](perso_attributes_search.png) diff --git a/docs/personalization/enable_personalization.md b/docs/personalization/enable_personalization.md index 0ad0487e29..b9b512deaa 100644 --- a/docs/personalization/enable_personalization.md +++ b/docs/personalization/enable_personalization.md @@ -10,14 +10,13 @@ To enable it, you must set up authentication parameters that you receive from [[ ## Get authentication parameters -First, either you or another [[= product_name_base =]] user responsible for managing the [[= product_name =]] -instance must [request access to the service]([[= user_doc =]]/personalization/enabling_personalization/#request-access-to-the-server). +First, either you or another [[= product_name_base =]] user responsible for managing the [[= product_name =]] instance must [request access to the service]([[= user_doc =]]/personalization/enabling_personalization/#request-access-to-the-server). ## Set up customer credentials When you receive the credentials, add them to your configuration. -In the root folder of your project, edit the `.env.local` file -by adding the following lines with your customer ID and license key: + +In the root folder of your project, edit the `.env.local` file by adding the following lines with your customer ID and license key: ``` PERSONALIZATION_CUSTOMER_ID=12345 @@ -27,17 +26,15 @@ PERSONALIZATION_HOST_URI=https://server_uri !!! note "Configuring user credentials for multisite setup and different personalization customers" - If your installation [hosts multiple sites]([[= user_doc =]]/personalization/use_cases/#multiple-website-hosting) with different - customer IDs, for example, to provide separate recommendations for different - language versions of the store, you can store all credentials in the same file: - + If your installation [hosts multiple sites]([[= user_doc =]]/personalization/use_cases/#multiple-website-hosting) with different customer IDs, for example, to provide separate recommendations for different language versions of the store, you can store all credentials in the same file: + ``` # Main credentials - ENU store PERSONALIZATION_CUSTOMER_ID=12345 PERSONALIZATION_LICENSE_KEY=67890-1234-5678-90123-4567 PERSONALIZATION_HOST_URI=https://server_uri - # Additional credentials - FRA store + # Additional credentials - FRA store FRA_CUSTOMER_ID=54321 FRA_LICENSE_KEY=09876-5432-1098-7654-3210 FRA_HOST_URI=https://FRA_server_uri @@ -47,30 +44,22 @@ PERSONALIZATION_HOST_URI=https://server_uri ## Configure Personalization -The [Personalization package](https://github.com/ibexa/personalization-client) -adds a personalization solution to [[= product_name =]] and communicates with -the Personalization server. +The [Personalization package](https://github.com/ibexa/personalization-client) adds a personalization solution to [[= product_name =]] and communicates with the Personalization server. -Its job is to track the way visitors use the website and recommend content -based on their behavior. +Its job is to track the way visitors use the website and recommend content based on their behavior. -For more information about integrating the Personalization service, -see [Developer guide](tracking_api.md) and [Best practices](tracking_integration.md). +For more information about integrating the Personalization service, see [Developer guide](tracking_api.md) and [Best practices](tracking_integration.md). ### Set up item type tracking -For the recommendations to be calculated, apart from visitor events (CLICK, BUY, etc.), -the Personalization server must receive a list of item types that are tracked. +For the recommendations to be calculated, apart from visitor events (for example, CLICK or BUY), the Personalization server must receive a list of item types that are tracked. You define item types to be tracked in [configuration files](configuration.md#configuration-files). The content is then initially exported by a script. -After this, it is synchronized with the Personalization service every time a change -occurs (using any method that triggers the event). +After this, it's synchronized with the Personalization service every time a change occurs (using any method that triggers the event). The Personalization configuration is SiteAccess-aware. -If your installation hosts multiple sites with different customer IDs, -for example, to provide separate recommendations for different language versions -of the site, provide the credentials that correspond to each of the sites. +If your installation hosts multiple sites with different customer IDs, for example, to provide separate recommendations for different language versions of the site, provide the credentials that correspond to each of the sites. The configuration can resemble the following example: @@ -90,7 +79,7 @@ ibexa: title: 'title' image: 'image_legend' description: 'sub_title' - 456: + 456: title: 'short_title' image: 'primary_image' description: 'sub_title' @@ -108,7 +97,7 @@ ibexa: title: 'title' image: 'image_legend' description: 'sub_title' - 456: + 456: title: 'short_title' image: 'primary_image' description: 'sub_title' @@ -116,10 +105,9 @@ ibexa: !!! note "Authentication" - For data exchange purposes, basic authentication is enabled by default. + For data exchange purposes, basic authentication is enabled by default. To change this, contact support@ibexa.co. - For security reasons, [store the authentication credentials in the ENV file](#set-up-customer-credentials), - and do not commit them to the Version Control System. + For security reasons, [store the authentication credentials in the ENV file](#set-up-customer-credentials), and don't commit them to the Version Control System. Then, use environment variables to pull them into the YAML file. | Parameter | Description | @@ -148,8 +136,7 @@ ibexa: #### Enable tracking -The Personalization client bundle delivers a Twig extension -which helps integrate the user tracking functionality into your site. +The Personalization client bundle delivers a Twig extension which helps integrate the user tracking functionality into your site. Place the following code snippet in the `` section of your header template: ``` html+twig @@ -169,8 +156,7 @@ As the API uses token based authorization you first need a valid bearer token. When you publish a content item a bearer token is created and saved to the `ibexa_token` db table. -Additionally a POST request is send to the Personalization Engine, containing the token -and the Rest URL where the Personalization Engine can fetch the changed Content. +Additionally a POST request is send to the Personalization Engine, containing the token and the Rest URL where the Personalization Engine can fetch the changed Content. The `BEARER_TOKEN` is the newest one in `ibexa_token` table having `type=1` and `identifier=update`. The token has a default lifetime of one day. @@ -237,8 +223,7 @@ The `content` endpoint returns one item and the `contentlist` endpoint returns m To get recommendations you must first export the item information to the Personalization server. -After you [define item types to be tracked and recommended](#set-up-item-type-tracking), -start the full export. +After you [define item types to be tracked and recommended](#set-up-item-type-tracking), start the full export. You need to run the `ibexa:personalization:run-export command per SiteAccesses that you want to use together with Personalization. You need different customer IDs for different SiteAccesses. @@ -251,12 +236,9 @@ php bin/console ibexa:personalization:run-export --languages=, ``` -The bundle exporter collects all content related to the ``/`` -pair and stores it in files to the folder `public/var/export/yyyy/mm/dd/hh/mm` of your project. -After finishing, the system sends a POST request to the endpoint and informs the -Personalization server to fetch new content. -An internal workflow is then triggered, so that the generated files are downloaded -and imported in the Personalization server's content store. +The bundle exporter collects all content related to the ``/`` pair and stores it in files to the folder `public/var/export/yyyy/mm/dd/hh/mm` of your project. +After finishing, the system sends a POST request to the endpoint and informs the Personalization server to fetch new content. +An internal workflow is then triggered, so that the generated files are downloaded and imported in the Personalization server's content store. The export process can take several minutes. @@ -264,8 +246,7 @@ The export process can take several minutes. !!! caution "Re-exporting modified item types" - If the item types to be recommended change, you must perform a new full export - by running the `php bin/console ibexa:personalization:run-export` command again. + If the item types to be recommended change, you must perform a new full export by running the `php bin/console ibexa:personalization:run-export` command again. #### Check export results @@ -283,7 +264,7 @@ To get the data of an imported item you can request the following REST resource: `GET https://admin.perso.ibexa.co/api//item//` -This way uses basic authentication. +This way uses basic authentication. The username is the customer ID and the password is the license key. ??? note "Example response" @@ -329,7 +310,7 @@ The username is the customer ID and the password is the license key. ##### Personalization backend -In the Back Office, go to **Personalization** > **Import** and review the list of historical import operations to see whether a full import was successful. +In the back office, go to **Personalization** > **Import** and review the list of historical import operations to see whether a full import was successful. ![Item Import tab with full import results](reco_full_import.png) @@ -337,10 +318,8 @@ In the Back Office, go to **Personalization** > **Import** and review the list o The Personalization server is automatically kept in sync with the content in [[= product_name =]]. -Every time an editor creates, updates or deletes content in the Back Office, -a notification is sent to https://admin.perso.ibexa.co/. -The personalization service also notifies other components of the Personalization server -and it eventually fetches the affected content and updates it internally. +Every time an editor creates, updates or deletes content in the back office, a notification is sent to https://admin.perso.ibexa.co/. +The personalization service also notifies other components of the Personalization server and it eventually fetches the affected content and updates it internally. ![Subsequent content exports](incremental_content_export.png) @@ -348,16 +327,13 @@ and it eventually fetches the affected content and updates it internally. !!! note "Client-based recommendations" - Recommendations are fetched and rendered asynchronously, so there - is no additional load on the server. - Therefore, it is crucial that you check whether the content export was successful, - because certain references, for example, deeplinks and image references, are - included. - If the export fails, the Personalization server does not have full content information. - As a result, even if the recommendations are displayed, they might miss images, - titles or deeplinks. + Recommendations are fetched and rendered asynchronously, so there is no additional load on the server. + Therefore, it's crucial that you check whether the content export was successful, because certain references, for example, deeplinks and image references, are included. + If the export fails, the Personalization server doesn't have full content information. + As a result, even if the recommendations are displayed, they might miss images, titles or deeplinks. -To display recommendations on your site, you must include the asset in the template using the following code: +To display recommendations on your site, you must include the asset in the template. +To do it, use the following code: ``` html+twig {{ encore_entry_script_tags('ibexa-personalization-client-js', null, 'ibexa') }} @@ -380,8 +356,7 @@ render(controller('ibexa_personalization::showRecommendationsAction', { !!! tip - To check whether tracking is enabled on the front end, use the - `ibexa_recommendation_enabled()` Twig function. + To check whether tracking is enabled on the front end, use the `ibexa_recommendation_enabled()` Twig function. You can wrap the call to the `RecommendationController` with: ``` html+twig @@ -397,32 +372,29 @@ render(controller('ibexa_personalization::showRecommendationsAction', { | Parameter | Type | Description | |------------------|--------|---------------| | `contextItems` | int | ID of the content you want to get recommendations for. | -| `scenario` | string | Scenario used to display recommendations. You can create custom scenarios in the Back Office. | +| `scenario` | string | Scenario used to display recommendations. You can create custom scenarios in the back office. | | `outputTypeId` | string | Item type that you expect in response, for example, `blog_post`. | | `crossContentType`| bool | If set to `true`, returns recommendations for all content types specified in the scenario. | | `limit` | int | Number of recommendations to fetch. | | `template` | string | Template name. | -| `attributes` | array | Fields that are required and are requested from the Personalization server. These Field names are also used inside Handlebars templates. | +| `attributes` | array | Fields that are required and are requested from the Personalization server. These field names are also used inside Handlebars templates. | You can also bypass named arguments with standard value passing as arguments. !!! note "Custom templates" - To use a custom template for displaying recommendations, - ensure that it includes `event_tracking.html.twig`: + To use a custom template for displaying recommendations, ensure that it includes `event_tracking.html.twig`: `{% include '@IbexaPersonalization/event_tracking.html.twig' %}`. -Recommendation responses contain all content data that is requested as attribute -in the recommendation call. +Recommendation responses contain all content data that is requested as attribute in the recommendation call. This response data can be used in templates to render and style recommendations. -For example, the following GET request should deliver the response below -if the content Fields were previously exported by the export script. +For example, the following GET request should deliver the response below if the content fields were previously exported by the export script. `GET https://reco.perso.ibexa.co/api/v2//someuser/popular.json?contextitems=71&numrecs=5&categorypath=/&outputtypeid=&attribute=name,author,uri,image` -??? note "Example response" +!!! note "Example response" ``` json { @@ -513,8 +485,7 @@ if the content Fields were previously exported by the export script. #### Modify recommendation data -You can retrieve data returned from the Personalization server and modify it -before it is shown to the user. +You can retrieve data returned from the Personalization server and modify it before it's shown to the user. To modify recommendation data, subscribe to `RecommendationResponseEvent`. See [`Event/Subscriber/RecommendationEventSubscriber.php`](https://github.com/ibexa/personalization-client/blob/main/src/lib/Event/Subscriber/RecommendationEventSubscriber.php) for an example: @@ -528,18 +499,15 @@ public static function getSubscribedEvents(): array } ``` -The `-10` refers to priority, which must be negative so this action is performed -before the main subscriber is run. +The `-10` refers to priority, which must be negative so this action is performed before the main subscriber is run. ### Image variations -Displaying image variations is not supported out of the box. +Displaying image variations isn't supported out of the box. -You can work around this limitation by creating a template -(based on [recommendations.html.twig](https://github.com/ibexa/personalization-client/blob/main/src/bundle/Resources/views/recommendations.html.twig)). +You can work around this limitation by creating a template (based on [recommendations.html.twig](https://github.com/ibexa/personalization-client/blob/main/src/bundle/Resources/views/recommendations.html.twig)). -To access a specific image variation through API, add the `image` parameter to the -request URL with the name of the variation as its value. +To access a specific image variation through API, add the `image` parameter to the request URL with the name of the variation as its value. For example, to retrieve the `rss` variation of the image, use: `/api/ezp/v2/ibexa_recommendation/v1/contenttypes/16?lang=eng-GB&fields=title,description,image,intro,name&page=1&page_size=20&image=rss` @@ -565,12 +533,8 @@ You can replace `info` with `debug` to increase verbosity. ## Set up user roles and permissions -Depending on your requirements, you may need to set up `edit` and `view` [permissions](permissions.md) -to grant users access to recommendation settings that relate to different SiteAccesses -and results that come from these websites. +Depending on your requirements, you may need to set up `edit` and `view` [permissions](permissions.md) to grant users access to recommendation settings that relate to different SiteAccesses and results that come from these websites. ## Configure recommendation logic -When you enable the Personalization, you can go back to the Back Office, -refresh the Personalization dashboard and proceed with [configuring the logic]([[= user_doc =]]/personalization/perso_configuration) -used to calculate the recommendation results. +When you enable the Personalization, you can go back to the back office, refresh the Personalization dashboard and proceed with [configuring the logic]([[= user_doc =]]/personalization/perso_configuration) used to calculate the recommendation results. diff --git a/docs/personalization/importing_historical_user_tracking_data.md b/docs/personalization/importing_historical_user_tracking_data.md index 8744409c78..2617bdc13a 100644 --- a/docs/personalization/importing_historical_user_tracking_data.md +++ b/docs/personalization/importing_historical_user_tracking_data.md @@ -5,20 +5,15 @@ description: Use historical user tracking data to build user profiles and genera # Importing historical user tracking data The recommendation engine supports replaying historical user events by adding a special parameter *overridetimestamp* on the buy event to simulate the event date. -This is then used as the datetime of an event instead of the current timestamp -of the request. +This is then used as the datetime of an event instead of the current timestamp of the request. -To give an example: It is often requested to import the buy history of users -to avoid the cold start problem and being able to start with good recommendations. -Instead of waiting till the user profile is built by collecting events from the day, -you implemented the tracking. -Usually a curl input file is generated which creates buy requests that are sent -to the tracking endpoint. +To give an example: it's often requested to import the buy history of users to avoid the cold start problem and being able to start with good recommendations. +Instead of waiting till the user profile is built by collecting events from the day, you implemented the tracking. +Usually a curl input file is generated which creates buy requests that are sent to the tracking endpoint. !!! note "User identifiers" - Ensure that user identifiers used in an import file are the same that - are used in the live tracking, for example, the user login identifiers. + Ensure that user identifiers used in an import file are the same that are used in the live tracking, for example, the user login identifiers. There must be some validation to avoid importing buy events by any user. Therefore a signature parameter needs to be added, which is calculated like the following: @@ -28,12 +23,10 @@ Therefore a signature parameter needs to be added, which is calculated like the !!! caution "Parameters without a value" The order of the parameters to be signed is crucial. - They must be sent in alphabetical order based on the parameter names to create - a signature. + They must be sent in alphabetical order based on the parameter names to create a signature. Encodings must always contain capital letters (for example, %3A and not %3a). - If a parameter value is "" or "null" or "undefined" it needs to be excluded from - the signing and must not be sent in the query string. + If a parameter value is "" or "null" or "undefined" it needs to be excluded from the signing and must not be sent in the query string. **valid**: `https://event.perso.ibexa.co/api/00000/buy/johndoe/1/11?fullprice=19.99EUR&overridetimestamp=2012-01-01T11%3A00%3A00&quantity=1&signature=d0026f017ae823f19530d93318c5a2f6` @@ -41,8 +34,7 @@ Therefore a signature parameter needs to be added, which is calculated like the ## Example -With a license key of "8695-1828-92810-5535-4239" and a purchase of certain -products, there can be the following signature values: +With a license key of "8695-1828-92810-5535-4239" and a purchase of certain products, there can be the following signature values: ``` https://event.perso.ibexa.co/api/00000/buy/johndoe/1/11?fullprice=19.99EUR&overridetimestamp=2012-01-01T11%3A00%3A00&quantity=1&signature=d0026f017ae823f19530d93318c5a2f6 diff --git a/docs/personalization/integrate_recommendation_service.md b/docs/personalization/integrate_recommendation_service.md index 377bb3149c..de0ee73945 100644 --- a/docs/personalization/integrate_recommendation_service.md +++ b/docs/personalization/integrate_recommendation_service.md @@ -6,8 +6,7 @@ month_change: true # Integrate recommendation service To return recommendations, you must first [enable the Personalization service](enable_personalization.md). -Next, integrate the service with [[= product_name =]] by activating -event tracking and embedding recommendation results into the website. +Next, integrate the service with [[= product_name =]] by activating event tracking and embedding recommendation results into the website. !!! note @@ -17,18 +16,15 @@ event tracking and embedding recommendation results into the website. ## Track events The service primarily relies on event tracking. -For the events to be registered, every content item or product page must call -a special tracking URL. -The easiest way of embedding the tracking URL is placing a one pixel image on every page, -like in the case of analytical tools or visitor counters. +For the events to be registered, every content item or product page must call a special tracking URL. +The easiest way of embedding the tracking URL is placing a one pixel image on every page, like in the case of analytical tools or visitor counters. A code that includes an image looks like this: `` where: -- `` stands either for the user ID or session ID of the user who is currently -logged into your website (any URL-encoded string is allowed). +- `` stands either for the user ID or session ID of the user who is currently logged into your website (any URL-encoded string is allowed). - `` stands for the [contentTypeId](content_model.md#content-information) of the content item or product that you want to track and recommend. @@ -217,10 +213,8 @@ The object contains links to the recommended items (`triggerOpenedLink`, `clickR ## Advanced integration -You can configure integration at a more advanced level to track more events, -use additional parameters, apply custom scenario configurations, filters, -and enable additional features. +You can configure integration at a more advanced level to track more events, use additional parameters, apply custom scenario configurations, filters, and enable additional features. -For more information about available functionalities, see the [User Documentation]([[= user_doc =]]/personalization/personalization). +For more information about available functionalities, see [User Documentation]([[= user_doc =]]/personalization/personalization). For more information about integrating the Personalization service, see [tracking API](tracking_api.md) and [tracking integration](tracking_integration.md) documentation. diff --git a/docs/personalization/legacy_recommendation_api.md b/docs/personalization/legacy_recommendation_api.md index 89c2b6fb71..55c442b602 100644 --- a/docs/personalization/legacy_recommendation_api.md +++ b/docs/personalization/legacy_recommendation_api.md @@ -6,37 +6,30 @@ description: An old method of fetching recommendations from the system using rec !!! caution - This is a page describing the old version of the recommendation API. - It is available for reference purposes only. + This is a page describing the old version of the recommendation API. + It's available for reference purposes only. Use the new [Recommendation API](recommendation_api.md) instead. -This page describes how to fetch recommendations from the Recommender System through -recommendation requests. -Before recommendation can be fetched from the recommendation controller, a sufficient -number of events must be collected and the model build must finish successfully. +This page describes how to fetch recommendations from the Recommender System through recommendation requests. +Before recommendation can be fetched from the recommendation controller, a sufficient number of events must be collected and the model build must finish successfully. !!! note - **BASIC Authentication** for fetching recommendations is enabled for some - configurations (for example for Gambio Plugin) by default. + **BASIC Authentication** for fetching recommendations is enabled for some configurations (for example for Gambio Plugin) by default. Use the `customerid` as username and the license key as password. - The license key is displayed in the upper right in the [Admin GUI](https://admin.yoochoose.net/)) - after you log in with your registration credentials. + The license key is displayed in the upper right in the [Admin GUI](https://admin.yoochoose.net/)) after you log in with your registration credentials. - If you plan to use [JSONP](https://www.w3schools.com/js/js_json_jsonp.asp), authentication - must be disabled. - If it is enabled in your solution (can be easily tested with a recommendation request in a browser), please contact the eZ Recommender support () for further information and disabling. + If you plan to use [JSONP](https://www.w3schools.com/js/js_json_jsonp.asp), authentication must be disabled. + If it's enabled in your solution (can be easily tested with a recommendation request in a browser), please contact the eZ Recommender support () for further information and disabling. ## Getting recommendations -Recommendations are retrieved from the Personalization server with RESTful requests -by using the GET method. -The result is a list of item IDs that can be used to call the underlying CMS -or shop system, to retrieve the necessary information for the rendering process. +Recommendations are retrieved from the Personalization server with RESTful requests by using the GET method. +The result is a list of item IDs that can be used to call the underlying CMS or shop system, to retrieve the necessary information for the rendering process. -To allow the customer to retrieve different types of recommendations based on different methods (for example, Collaborative Filtering, Content Based, Stereotype, etc.) the Recommendation System uses scenario IDs relating to a predefined set of configurations inside the system. -These configurations are a combination of methods and filters that should be applied including possible fallbacks if the requested methods do not deliver a result. +To allow the customer to retrieve different types of recommendations based on different methods (for example, Collaborative Filtering, Content Based, or Stereotype) the Recommendation System uses scenario IDs relating to a predefined set of configurations inside the system. +These configurations are a combination of methods and filters that should be applied including possible fallbacks if the requested methods don't deliver a result. A recommendation request looks like this: @@ -46,8 +39,8 @@ The embedded parameters `solutionid`, `clientid` and `userid` are the same as us | Parameter Name | Description | Values | |-----|-----|------| -| `scenarioid` | The ID of the scenario used for providing recommendations. It is configured or predefined in the Administration GUI. | alphanumeric | -| `extension` | The format the server generates the response in. There are three formats supported: JSON, XML and JSONP. See the chapter [Response Handling](#response-handling) below for more information | json, xml or jsonp | +| `scenarioid` | The ID of the scenario used for providing recommendations. It's configured or predefined in the Administration GUI. | alphanumeric | +| `extension` | The format the server generates the response in. There are three formats supported: JSON, XML and JSONP. For more information, see [Response Handling](#response-handling). | json, xml or jsonp | ## Basic Request Parameters @@ -58,8 +51,8 @@ Using additional query string parameters one can customize the recommendation re |`numrecs`|Defines the number of recommendations that should be delivered. Keep this amount as low as possible as this increases the response time of the recommendation call.|1 to 50 (default "10")| |`contextitems` (required for context based recommendations)|Comma-separated list of items that the user is currently viewing on the webpage. All items must be from the same type. The type is defined in the scenario configuration.|comma separated list of item IDs (1 to 2147483647)| |`itemid` (deprecated)|A single item to be used as a source for creating recommendations. This parameter is deprecated. Use `contextitems` instead.|1 to 2147483647| -|`outputtypeid` (required, if the scenario defined multiple output item types, otherwise it is optional)|Item type of the requested recommendations. This can differ from the input item type, for example, if you want to get recommendations for pictures based on an article the item type for pictures has to be used here. For a web shop this is probably not needed as only one type of items is tracked. Multiple item types are available only for advanced license.|numeric| -|`categorypath`|Base category path for providing recommendations. The format is the same as the category path for the event tracking. It is possible to add this parameter multiple times. The order of recommendations from the different categories is defined by the calculated relevance.|alphanumeric[/alphanumeric]*| +|`outputtypeid` (required, if the scenario defined multiple output item types, otherwise it's optional)|Item type of the requested recommendations. This can differ from the input item type, for example, if you want to get recommendations for pictures based on an article the item type for pictures has to be used here. For a web shop this is probably not needed as only one type of items is tracked. Multiple item types are available only for advanced license.|numeric| +|`categorypath`|Base category path for providing recommendations. The format is the same as the category path for the event tracking. It's possible to add this parameter multiple times. The order of recommendations from the different categories is defined by the calculated relevance.|alphanumeric[/alphanumeric]*| |`jsonpcallback` (used only for JSONP request)|Function or method name for a JSONP request. It can be a function ("callme"), or a method ("obj.callme").|valid JavaScript function call (by default "jsonpCallback")| An example of the recommendation request:  @@ -77,7 +70,7 @@ It fetches 8 recommendations for user Smith, who is watching the item 123 and th ## Response handling The recommendation request returns a list of item IDs that are JSON, JSONP or XML-formatted. -The result can be easily integrated into any webpage by using some lines of script code.  +The result can be integrated into any webpage by using some lines of script code.  !!! tips @@ -147,7 +140,7 @@ The Following HTTP response codes are used by the recommendation controller. |400 Bad Request
414 Request-URI Too Long|The request is wrongly formatted. See response body for more information.| |401 Unauthorized|Not valid authentication credentials.| |403 Forbidden|Access denied.| -|404 Not Found|The requested element was not found. It can be customer ID (a.k.a. mandator ID), model ID, scenario ID etc.| +|404 Not Found|The requested element was not found. It can be, for example, customer ID (a.k.a. mandator ID), model ID, or scenario ID.| |409 Conflict|The combination of used models and the recommendation request parameters doesn't allow to provide recommendations. This could be, for example, if personalized recommendations are requested for a user who has no history at all.| |500 Internal Server Error|Unspecified error. Please inform support if you get this error repeatedly.| @@ -156,11 +149,11 @@ The format of error messages can be changed and should not be used for automated ## Advanced Request Parameter -There are some additional very special request parameters. +There are some additional special request parameters. ###### any attribute name (used only if submodels are configured) -Item's attribute, for example, color, price, etc. +Item's attribute, for example, color, price, and more. These are customer specific and can only be understood by the recommender system if the item attributes are imported by using the YOOCHOOSE content import APIs. There can be multiple attributename and attributevalue pairs. @@ -170,7 +163,7 @@ Legacy Recommendation API and [Submodel configuration]([[= user_doc =]]/personal ###### `usecontextcategorypath` -If set to true, the category path of the contextitem(s) will be resolved by the recommender engine from the internal store and used as base category path. +If set to true, the category path of the contextitem(s) is resolved by the recommender engine from the internal store and used as base category path. If more than one category is returned, all categories are used for providing recommendations. Avoid setting this parameter to true to minimize the response time. Use the parameter categorypath to provide the category to the recommender engine during the request. @@ -179,7 +172,7 @@ Use the parameter categorypath to provide the category to the recommender engine ###### `recommendCategory` (to be used only in the eZ Recommendation extension) -If passed in combination with a "categorypath" value, the "closest" category the recommended items linked with will be delivered in the response as additional field "category". +If passed in combination with a "categorypath" value, the "closest" category the recommended items linked with is delivered in the response as additional field "category". ``` recommendationResponseList: [ { @@ -191,7 +184,7 @@ This feature helps to find "better" template for articles, which are located in For example there is an article about football in the USA. The article is located in both categories "/Sport/Football" and "/America/USA". -Depending on the category it is shown with a football field or the USA flag in the background. +Depending on the category it's shown with a football field or the USA flag in the background. If this article is recommended and is clicked in the category "/Sport/Cricket" it must open with the "football" template. If the article is clicked in the category "/America/Canada" it must open with the "USA" template. @@ -212,16 +205,22 @@ Recommendation service support following HTTP headers to allow cache control on |Response|`Last-Modified`|The last modification date of the recommendations.|`Last-Modified: Tue, 15 Nov 2013 12:45:26 GMT`|-| ||`Expires`|Gives the date/time after which the response is considered to be outdated|`Expires: Thu, 01 Dec 2013 16:00:00 GMT`|-| -The last modification timestamp indicates a change that could influence the recommendation response. It depends on an updated recommendation calculation, an update of an item or some scenario configuration changes. The expiration timestamp is a best-effort prediction based on the model building configuration and provided context. The shortest expiration period is 5 minutes from the request time. The longest is 24 hours. In the table below several examples are illustrated: +The last modification timestamp indicates a change that could influence the recommendation response. +It depends on an updated recommendation calculation, an update of an item or some scenario configuration changes. +The expiration timestamp is a best-effort prediction based on the model building configuration and provided context. +The shortest expiration period is 5 minutes from the request time. The longest is 24 hours. +In the table below several examples are illustrated: | Model | Context | Expiration time | Description | |------|------|-----|-----| -| Bestselling products last 7 days | no context | 24 hours | The model with the 7 days scope is usually built once a day. It can be easily cached for 24 hours. It has no context and can therefore be cached globally for all the users of a customer. | +| Bestselling products last 7 days | no context | 24 hours | The model with the 7 days scope is usually built once a day. It can be cached for 24 hours. It has no context and can therefore be cached globally for all the users of a customer. | | Also bought products in the last month | current product | 24 hours | The model with the 30 days scope is usually built once a day. The context is always the same. It can be cached for every product. The same result can be used for all users of a customer. | | Also consumed read articles in the last hour | current article | 30 minutes | Models with a short scope are usually built several times a day or even per hour. In this case the expiration time is set to the half of the model build frequency/period. | -| Personalized recommendation based on the user's statistic | customers click history | now | Although the statistic model is not updated within minutes, it is very likely that the context will be changed shortly (customer clicks another product and therefore the click is added to his history). The expiration time should not be much longer than the user activity on the web page. | +| Personalized recommendation based on the user's statistic | customers click history | now | Although the statistic model isn't updated within minutes, it's very likely that the context is changed shortly (customer clicks another product and therefore the click is added to his history). The expiration time should not be much longer than the user activity on the web page. | -In most cases you do not need to calculate the expiration time manually. The table above is provided for the orientation, how the Expires header of the HTTP response is calculated by the recommendation engine and already provided to your caching system. You just need to make sure that the Expires header is used in the configuration of your caching system instead of a static value out of your configuration. +In most cases you don't need to calculate the expiration time manually. +The table above is provided for the orientation, how the Expires header of the HTTP response is calculated by the recommendation engine and already provided to your caching system. +You just need to make sure that the Expires header is used in the configuration of your caching system instead of a static value out of your configuration. ## Integration best Practices @@ -229,32 +228,32 @@ There are several ways to integrate the REST calls to the Recommendation engine #### **Simple Way** -The simplest way to load recommendations is to synchronously request the Recommendation Engine for recommendations as they are needed. +The simplest way to load recommendations is to synchronously request the Recommendation Engine for recommendations as they're needed. This way is sufficient in most cases. The most important drawback is that the request time increases by the time of the recommendation request. -If the network is overloaded or the Recommendation Engine is not available it can lock the request. +If the network is overloaded or the Recommendation Engine isn't available it can lock the request. #### Loading in the bottom You can place the code that loads the data from the eZ Recommender at the bottom of the generated document and flush the output buffer to the client just before requesting recommendations. -The browser will get a whole page to render and can display it even if the very end of the page is still loading. -Then the JavaScript code with the recommendation information loaded at the bottom of the page must fill the gaps on the page with recommendation as soon as it is completely loaded. +The browser gets a whole page to render and can display it even if the very end of the page is still loading. +Then the JavaScript code with the recommendation information loaded at the bottom of the page must fill the gaps on the page with recommendation as soon as it's completely loaded. #### Non-blocking loading in the background -If the website is implemented in a language which supports multithreading or non-blocking I/O, it is possible to start the recommendation request just after the browser request is received. -The page generation and the recommendation requests will be accomplished in parallel. +If the website is implemented in a language which supports multithreading or non-blocking I/O, it's possible to start the recommendation request just after the browser request is received. +The page generation and the recommendation requests are accomplished in parallel. By combining this idea with the previous solution and placing the recommendation results at the bottom of the page you can avoid any interruption in the processing. -#### Loading from JavaScript using JSONP +#### Using JSONP to load from JavaScript -It is not possible to request the recommendation controller server directly from the JavaScript (over AJAX library or directly over XMLHttpRequest) because of the cross-domain restriction in most browsers. +It's not possible to request the recommendation controller server directly from the JavaScript (over AJAX library or directly over XMLHttpRequest) because of the cross-domain restriction in most browsers. One of the possible technique to work around this limitation is [JSONP](https://en.wikipedia.org/wiki/JSONP). #### Loading over proxy -A better solution in comparison with JSONP is to provide the proxy on the server side, which will forward script requests to the Recommender system. +A better solution in comparison with JSONP is to provide the proxy on the server side, which forwards script requests to the Recommender system. It can be implemented as a very simple proxy using the [mod\_proxy module](https://httpd.apache.org/docs/2.2/mod/mod_proxy.html) of Apache Webserver. -It just transfers the data and the JavaScript renders the response into HTML itself. +It transfers the data and the JavaScript renders the response into HTML itself. An alternative approach is creating the HTML code on the server side for every target page in a sense to simplify the script on the client side. @@ -266,9 +265,9 @@ An overview of pros and cons for each of the above techniques: |Problem|Simple Way|Bottom loading|Background loading|JSONP|XMLHttpRequest + Proxy| |---|---|---|---|---|---| -|Is not blocked by ad blockers or no-track plug-ins|Yes|Yes|Yes|-|Yes| -|Works if JavaScript is disabled|Yes|depends|-|-|-| +|Isn't blocked by ad blockers or no-track plug-ins|Yes|Yes|Yes|-|Yes| +|Works if JavaScript is disabled|Yes|depends|-|-|-| |Works for server without multithreading functionality|Yes|Yes|-|Yes|Yes| |Compatible with frontend caching on the server|-|-|-|Yes|Yes| -|Does not delay page rendering|-|depends|depends|Yes|Yes| +|Doesn't delay page rendering|-|depends|depends|Yes|Yes| |Supports authentication for recommendation fetching|Yes|Yes|Yes|-|depends| diff --git a/docs/personalization/personalization.md b/docs/personalization/personalization.md index c491f121c1..68ba2eafda 100644 --- a/docs/personalization/personalization.md +++ b/docs/personalization/personalization.md @@ -5,10 +5,9 @@ page_type: landing_page # Personalization -Ibexa Personalization is a service that allows you to track the visitors of your website and offers personalized recommendations or serves targeted content, based on their preferences and behavior. +[[= product_name_base =]] Personalization is a service that allows you to track the visitors of your website and offers personalized recommendations or serves targeted content, based on their preferences and behavior. -Personalization can be used both by publishers, for example, to track content consumption -and promote content, and in e-commerce, to drive purchases. +Personalization can be used both by publishers, for example, to track content consumption and promote content, and in e-commerce, to drive purchases. To provide online recommendations, the service must at least: diff --git a/docs/personalization/personalization_guide.md b/docs/personalization/personalization_guide.md index 49978e7000..44070c6156 100644 --- a/docs/personalization/personalization_guide.md +++ b/docs/personalization/personalization_guide.md @@ -30,7 +30,7 @@ Now, you can start collecting data and boost your business. Personalization with tracking scripts, monitors individual sessions from user’s behavior and interest data through events (clicks, viewed articles, pages, purchases) and demographic data (location, industry, occupation). -Next, collects data and computes models thanks to complex algorithms. +Next, collects data and computes models thanks to complex algorithms. Personalization is SiteAcces-aware, it means it can serve on multiple sites with different customer IDs and deliver recommendations for each site (for example, if you host multi language site). @@ -42,13 +42,13 @@ Use Twig extension to add a tracking script and implement it into your site conf Models are statistics-based and perform calculations based on data from content, users and events. -They work in the background and update on regular time intervals to ensure best and accurate recommendations. Personalization service includes a few predefined models according to your needs and agreements between your organization and Ibexa. +They work in the background and update on regular time intervals to ensure best and accurate recommendations. Personalization service includes a few predefined models according to your needs and agreements between your organization and [[= product_name_base =]]. If you need more customized models, contact customer support. Personalization service includes the following model types: -- popularity models - based on trends, Top clicked, Top purchased, algorithm recommends trending content +- popularity models - based on trends, Top clicked, Top purchased, algorithm recommends trending content - collaborative models - generate predictions by analyzing user behavior and their interactions with target items, compares to other users behavior with similar browsing behavior @@ -61,11 +61,14 @@ Personalization service includes the following model types: ### Scenarios -Scenarios are sequences of events. You can use scenarios to determine how and when render particular content to your customers. Each scenario can include also subscenarios used for granular personalized rendering of content. +Scenarios are sequences of events. +You can use scenarios to determine how and when render particular content to your customers. +Each scenario can include also subscenarios used for granular personalized rendering of content. ### Segments -Use segments to get content targeted at particular user groups. Segments calculate models based on the segment attribute factor. Assign users to different recommendation groups and create advanced logic with operators to get best segmentation for your audience. +Use segments to get content targeted at particular user groups. +Segments calculate models based on the segment attribute factor. Assign users to different recommendation groups and create advanced logic with operators to get best segmentation for your audience. ![Segments](perso_segment_group_or.png) @@ -76,7 +79,7 @@ Use segments to get content targeted at particular user groups. Segments calcula Personalization includes interface as API that you can use to interact with stored data and to send requests and export data from the service. -For more information see documentation for API operations available for Personalization: +For more information, see documentation for API operations available for Personalization: - [Tracking API](api_reference/tracking_api.md/) - [Content API](api_reference/content_api.md/) @@ -87,36 +90,43 @@ For more information see documentation for API operations available for Personal ### Web design and content development -Create websites with content targeted at your customers. Deliver your visitors relevant content and build trust in your brand. +Create websites with content targeted at your customers. +Deliver your visitors relevant content and build trust in your brand. ### Reduce clutter and improve customer retention -Help users find content of their interest quicker, -use words to appeal to individual customers, as well as segments. +Help users find content of their interest quicker, use words to appeal to individual customers and segments. Enrich customer data by integrating [[= product_name_base =]] Personalization with other systems such as ERP, CRMs. Track user’s scenarios and develop strategies that match your strategies and improve engagement. + ### Satisfy customer expectations Personalization engine shows customers products relevant to their interests, builds a feeling of connection and understanding. ### Increase customer engagement -Targeted and customized content considerably improves engagement by delivering content that fits your visitors interests and anticipates their needs. This creates a bound between your brand and users who spend more time on your website, and are more likely to come back to your services. A kind of loyalty is created. +Targeted and customized content considerably improves engagement by delivering content that fits your visitors interests and anticipates their needs. +This creates a bound between your brand and users who spend more time on your website, and are more likely to come back to your services. +A kind of loyalty is created. ### Improve customer experience -Stand out from other companies by provided well-suited content and make a space for your customers where they feel known and valued and treated exceptional. Build trust and a bond with visitors, who are more likely to come back. +Stand out from other companies by provided well-suited content and make a space for your customers where they feel known and valued and treated exceptional. +Build trust and a bond with visitors, who are more likely to come back. -### Increase average order value +### Increase average order value -Apply collaborative models with predictive analysis and find out what motivates users to put extra items into their carts. Start building predictions of their behaviors and suggest items, products your visitors are willing to buy. +Apply collaborative models with predictive analysis and find out what motivates users to put extra items into their carts. +Start building predictions of their behaviors and suggest items, products your visitors are willing to buy. ![Dashboard](perso_dashboard_revenue.png) -### Measure your return and boost conversion rates +### Measure your return and boost conversion rates -Connect Personalization engine with your eCommerce shop, focus on the revenue generated by recommendations. Track what recommendations are shown to your visitors and analyze conversion rates. Effectively evaluate quality of recommendations and compare with your KPIs. +Connect Personalization engine with your eCommerce shop, focus on the revenue generated by recommendations. +Track what recommendations are shown to your visitors and analyze conversion rates. +Effectively evaluate quality of recommendations and compare with your KPIs. ## Use cases diff --git a/docs/personalization/recommendation_integration.md b/docs/personalization/recommendation_integration.md index fa63552e18..769f3f1671 100644 --- a/docs/personalization/recommendation_integration.md +++ b/docs/personalization/recommendation_integration.md @@ -4,68 +4,46 @@ description: Methods for REST call with Personalization server. # Recommendation integration -There are several ways to integrate the REST calls with the Personalization server -and to avoid blocking webpage rendering, if the communication with the Recommender -is distrusted or interrupted. +There are several ways to integrate the REST calls with the Personalization server and to avoid blocking webpage rendering, if the communication with the Recommender is distrusted or interrupted. ## Use page blocks -[[= product_name =]] ships with a number of page blocks that editors can place on -landing pages and configure to present scenario results. -To work, these blocks require that Personalization and scenarios are properly -configured. -For a list of all page blocks that are available out-of-the-box, -see [Page block reference]([[= user_doc =]]/content_management/block_reference/). +[[= product_name =]] ships with a number of page blocks that editors can place on landing pages and configure to present scenario results. +To work, these blocks require that Personalization and scenarios are properly configured. +For a list of all page blocks that are available out-of-the-box, see [Page block reference]([[= user_doc =]]/content_management/block_reference/). ## Request recommendations synchronously -The simplest way to load recommendations is to synchronously request the Personalization -server for recommendations as they are needed. This way is sufficient in most cases. -The most important drawback is that the request time increases by the time -of the recommendation request. -If the network is overloaded or the Personalization server is not available, -it can lock the request. +The simplest way to load recommendations is to synchronously request the Personalization server for recommendations as they're needed. This way is sufficient in most cases. +The most important drawback is that the request time increases by the time of the recommendation request. +If the network is overloaded or the Personalization server isn't available, it can lock the request. ## Load in the bottom -You can place the code that loads the data from the eZ Recommender at the bottom -of the generated document and flush the output buffer to the client -before requesting recommendations. -The browser gets a whole page to render and can display it even if the very end -of the page is still loading. -Then the JavaScript code with the recommendation information loaded at the bottom -of the page must fill the gaps on the page with recommendations as soon as -it is completely loaded. +You can place the code that loads the data from the eZ Recommender at the bottom of the generated document and flush the output buffer to the client before requesting recommendations. +The browser gets a whole page to render and can display it even if the very end of the page is still loading. +Then the JavaScript code with the recommendation information loaded at the bottom of the page must fill the gaps on the page with recommendations as soon as it's completely loaded. ## Non-blocking load in the background -If the website is implemented in a language that supports multithreading or -non-blocking I/O, the recommendation request can start right after the browser -request is received. -The page generation and the recommendation requests are accomplished in parallel. -By combining this idea with the previous solution and placing the recommendation -results at the bottom of the page you can avoid any interruption in the processing. +If the website is implemented in a language that supports multithreading or non-blocking I/O, the recommendation request can start right after the browser request is received. +The page generation and the recommendation requests are accomplished in parallel. +By combining this idea with the previous solution and placing the recommendation results at the bottom of the page you can avoid any interruption in the processing. ## Load from JavaScript using JSONP -You cannot request the recommendation controller server directly from the JavaScript -(over AJAX library or directly over XMLHttpRequest) because of the cross-domain -restriction in most browsers. +You cannot request the recommendation controller server directly from the JavaScript (over AJAX library or directly over XMLHttpRequest) because of the cross-domain restriction in most browsers. One of the possible ways to work around this limitation is JSONP. ## Load over proxy -A better solution than JSONP is to provide the proxy on the server side, which -forwards script requests to the Personalization service. -It can be implemented as a basic proxy using the `mod_proxy` module of -the Apache Webserver. +A better solution than JSONP is to provide the proxy on the server side, which forwards script requests to the Personalization service. +It can be implemented as a basic proxy by using the `mod_proxy` module of the Apache Webserver. It transfers the data and the JavaScript renders the response into HTML itself. -An alternative approach is to create the HTML code on the server side for every -target page, to simplify the script on the client side. +An alternative approach is to create the HTML code on the server side for every target page, to simplify the script on the client side. -You can use the following tools as an implementation of such a proxy: -the Apache proxy module, an independent daemon like “netcat” or a PHP script. +You can use the following tools as an implementation of such a proxy: the Apache proxy module, an independent daemon like “netcat” or a PHP script. ## Comparison @@ -74,7 +52,7 @@ An overview of pros and cons for each of the presented techniques: |Feature|Synchronous loading|Bottom loading|Background loading|JSONP|XMLHttpRequest + Proxy| |---|---|---|---|---|---| |Isn't blocked by ad blockers or no-track plug-ins|✔|✔|✔|-|✔| -|Works if JavaScript is disabled|Yes|depends|-|-|-| +|Works if JavaScript is disabled|Yes|depends|-|-|-| |Works for server without multithreading functionality|✔|✔|-|✔|✔| |Compatible with frontend caching on the server|-|-|-|✔|✔| |Doesn't delay page rendering|-|depends|depends|✔|✔| diff --git a/docs/personalization/tracking_integration.md b/docs/personalization/tracking_integration.md index 55459a07fc..7627ee47e6 100644 --- a/docs/personalization/tracking_integration.md +++ b/docs/personalization/tracking_integration.md @@ -5,9 +5,8 @@ month_change: true # Tracking integration -There are several ways to integrate event reporting into the webpage. -The simplest way is to generate code of a tiny image and put it on the webpage -where the event must be sent [pixel tracking](integrate_recommendation_service.md#track-events). +There are several ways to integrate event reporting into the webpage. +The simplest way is to generate code of a tiny image and put it on the webpage where the event must be sent [pixel tracking](integrate_recommendation_service.md#track-events). For example, with HTML:  @@ -26,49 +25,38 @@ img.src = "https://event.perso.ibexa.co/api/00000/click/johndoe/1/100?categorypa -The drawback of this option is that such calls can be blocked by ad blockers -or do-not-track plugins on the client side. +The drawback of this option is that such calls can be blocked by ad blockers or do-not-track plugins on the client side. ## Server-side tracking -Another option is to call the tracker from the server. -The most important drawback is that the event request increases the general request time. -If the network is overloaded or the Personalization server is not available, -the number of requests can grow and lead to a stalled and finally crashing HTTP service. +Another option is to call the tracker from the server. +The most important drawback is that the event request increases the general request time. +If the network is overloaded or the Personalization server isn't available, the number of requests can grow and lead to a stalled and finally crashing HTTP service. See below the techniques that help avoid these problems. ### Tracking at the bottom -You can place the code at the very end of the generating script -and flush the output buffer to the client before sending the events. -The connection to the browser can remain open for the time of processing, -but it is transparent for the end user. +You can place the code at the very end of the generating script and flush the output buffer to the client before sending the events. +The connection to the browser can remain open for the time of processing, but it's transparent for the end user. ### Tracking asynchronously -If the website is implemented in a language that supports multithreading, non-blocking -I/O or messaging infrastructure, you can start the event request right after -the browser request is received instead of waiting for this process to finish. +If the website is implemented in a language that supports multithreading, non-blocking I/O or messaging infrastructure, you can start the event request right after the browser request is received instead of waiting for this process to finish. ## Client-side tracking ### Using JSONP -Another solution is to provide a proxy on the server side, which forwards -script requests to the Personalization server. -In this model, the requests are triggered from the client, when the page is already -loaded and rendered. -It is impossible to request the recommendation controller server directly from JavaScript -(either through the AJAX library or directly over XMLHttpRequest) because of the -cross-domain restriction in most browsers. +Another solution is to provide a proxy on the server side, which forwards script requests to the Personalization server. +In this model, the requests are triggered from the client, when the page is already loaded and rendered. +It's impossible to request the recommendation controller server directly from JavaScript (either through the AJAX library or directly over XMLHttpRequest) because of the cross-domain restriction in most browsers. One possible work around this limitation is [JSONP](https://www.w3schools.com/js/js_json_jsonp.asp). ### Using server proxy -Another option is to tunnel the JavaScript request through the proxy on the same server. -The server only forwards requests to the Personalization server. -It can be an implemented Apache proxy module, an independent daemon -(for example, "netcat"), or a PHP script. +Another option is to tunnel the JavaScript request through the proxy on the same server. +The server only forwards requests to the Personalization server. +It can be an implemented Apache proxy module, an independent daemon (for example, "netcat"), or a PHP script. ## Comparison @@ -76,7 +64,7 @@ An overview of pros and cons for every technique: | Feature | Pixel | Server-side | Page bottom | Async. reporting | JSONP | XMLHttpRequest + Proxy | |----|-----|-----|-----|-----|-----|------| -| Is not blocked by ad blockers or do-not-track plug-ins. |-|✔|✔|✔|-|✔| +| Isn't blocked by ad blockers or do-not-track plug-ins. |-|✔|✔|✔|-|✔| | Works if JavaScript is disabled. |✔|✔|✔|✔|-|-| | Is compatible with frontend caching on the server. |-|-|-|-|✔|✔| | Doesn't delay page rendering. |✔|-|✔|✔|✔|✔| @@ -84,14 +72,8 @@ An overview of pros and cons for every technique: !!! tip "The recommended approach" - An Ibexa-recommended solution is to use pixel tracking for non-complex events, - or where every page is generated on the server side without any caching logic. - For hints about preloading image URLs with JavaScript elements - (`var img = new Image(); img.src="uri"`) - or without them (`<img src="uri"... />`), see [How to Preload Images](https://www.mediacollege.com/internet/javascript/image/preload.html). + An Ibexa-recommended solution is to use pixel tracking for non-complex events, or where every page is generated on the server side without any caching logic. + For hints about preloading image URLs with JavaScript elements (`var img = new Image(); img.src="uri"`) or without them (`<img src="uri"... />`), see [How to Preload Images](https://www.mediacollege.com/internet/javascript/image/preload.html). - If you plan to implement caching mechanisms and more complex events like - Consume (depending on the viewing time of the page), Basket (which is usually - an in-page event) or custom in-page events that take place on the client side, - a JavaScript implementation is strongly encouraged. + If you plan to implement caching mechanisms and more complex events like Consume (depending on the viewing time of the page), Basket (which is usually an in-page event) or custom in-page events that take place on the client side, a JavaScript implementation is strongly encouraged. For a sample script and instructions, see [Track with ibexa-tracker.js](tracking_with_ibexa-tracker.md). diff --git a/docs/personalization/tracking_with_ibexa-tracker.md b/docs/personalization/tracking_with_ibexa-tracker.md index 0de5be2868..0866895c37 100644 --- a/docs/personalization/tracking_with_ibexa-tracker.md +++ b/docs/personalization/tracking_with_ibexa-tracker.md @@ -5,35 +5,28 @@ month_change: true # Track events with ibexa-tracker.js -This is another example of how you can integrate the tracking with a Google-style -JavaScript in your site. -The approach is very generic and evaluate it if it meets your -**requirements and security policy**. - -If you want the `userid` to be generated automatically, set user -parameter as empty `''` in the `_ycq.push` calls. -If a predefined cookie already exists, it is used. +This is another example of how you can integrate the tracking with a Google-style JavaScript in your site. +The approach is very generic and evaluate it if it meets your **requirements and security policy**. + +If you want the `userid` to be generated automatically, set user parameter as empty `''` in the `_ycq.push` calls. +If a predefined cookie already exists, it is used. + Otherwise a new one is created. ## Tracking code quickstart -The Personalization JavaScript is a Google-like tracking API (ga.js) that you can paste -into your pages. -It activates the tracking by inserting  or - into the page. +The Personalization JavaScript is a Google-like tracking API (ga.js) that you can paste into your pages. +It activates the tracking by inserting  or into the page. -To use this mechanism on your pages, copy the code snippet below, and replace: +To use this mechanism on your pages, copy the code snippet below, and replace: - `` with the customer ID -- `` with the Content Type ID +- `` with the content type ID - `` with the content item ID -- `` with an empty string for cookie based anonymous user or with the value generated by -your user identifier system for logged-in user. In case user activity should not be tracked, -'not_defined' value should be used to still have an event stored without a link to the user. +- `` with an empty string for cookie based anonymous user or with the value generated by your user identifier system for logged-in user. In case user activity should not be tracked, 'not_defined' value should be used to still have an event stored without a link to the user. -All identifiers can be any form of string. -Paste this snippet into your website template page so that it appears before -the closing `` tag. +All identifiers can be any form of string. +Paste this snippet into your website template page so that it appears before the closing `` tag. ``` js