diff --git a/.github/workflows/api_refs.yaml b/.github/workflows/api_refs.yaml index 0b3c85c28cb..337dfc103cf 100644 --- a/.github/workflows/api_refs.yaml +++ b/.github/workflows/api_refs.yaml @@ -1,10 +1,10 @@ -name: 'Build API Refs' +name: 'Build REST API Reference' on: workflow_dispatch: inputs: version: - # The version to build the API Reference for. + # The version to build the REST API Reference for. # Use a released tag (e.g. v5.0.9) or a plain number (e.g. 5.0.9). description: 'Version (e.g. v5.0.9 or 5.0.9)' required: true @@ -12,7 +12,7 @@ on: use_dev_version: # When checked, Composer installs from the x-dev branch instead of a released tag. # Useful for building a reference before the final release is tagged. - # Example: version=5.0.9 + use_dev_version=true → DXP_VERSION=v5.0.x-dev, BASE_DXP_BRANCH=5.0, VIRTUAL_DXP_VERSION=5.0.9 + # Example: version=5.0.9 + use_dev_version=true → DXP_VERSION=v5.0.x-dev, VIRTUAL_DXP_VERSION=5.0.9 description: 'Use x-dev branch (default: false)' required: false type: boolean @@ -32,8 +32,8 @@ on: default: false jobs: - open_php_api_ref_pr: - name: "PHP & REST API References' PR" + open_rest_api_ref_pr: + name: "REST API Reference's PR" runs-on: ubuntu-26.04 steps: @@ -59,13 +59,12 @@ jobs: if [[ "$INPUT_USE_DEV_VERSION" == "true" ]]; then # Dev build: install from the x-dev branch and label output with the target version - base_dxp_branch="$(echo "$version" | sed 's/\(.*\..*\)\..*/\1/')" - dxp_version="v${base_dxp_branch}.x-dev" + dxp_branch="$(echo "$version" | sed 's/\(.*\..*\)\..*/\1/')" + dxp_version="v${dxp_branch}.x-dev" virtual_dxp_version="${version}" else # Stable build: install from the released tag dxp_version="v${version}" - base_dxp_branch="" virtual_dxp_version="" fi @@ -73,7 +72,6 @@ jobs: echo "base_branch=${base_branch}" >> "$GITHUB_OUTPUT" echo "work_branch=${work_branch}" >> "$GITHUB_OUTPUT" echo "dxp_version=${dxp_version}" >> "$GITHUB_OUTPUT" - echo "base_dxp_branch=${base_dxp_branch}" >> "$GITHUB_OUTPUT" echo "virtual_dxp_version=${virtual_dxp_version}" >> "$GITHUB_OUTPUT" - name: Checkout documentation @@ -109,14 +107,12 @@ jobs: private-key: ${{ secrets.AUTOMATION_CLIENT_SECRET }} owner: ibexa - - name: Build API Refs + - name: Build REST API Reference env: SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} - BASE_BRANCH: ${{ steps.version_and_branches.outputs.base_branch }} DXP_VERSION: ${{ steps.version_and_branches.outputs.dxp_version }} - BASE_DXP_BRANCH: ${{ steps.version_and_branches.outputs.base_dxp_branch }} VIRTUAL_DXP_VERSION: ${{ steps.version_and_branches.outputs.virtual_dxp_version }} run: | if [ -n "$GITHUB_TOKEN" ]; then @@ -124,45 +120,24 @@ jobs: fi composer config --global http-basic.updates.ibexa.co $SATIS_NETWORK_KEY $SATIS_NETWORK_TOKEN - if [[ '4.6' != $BASE_BRANCH ]]; then - tools/api_refs/api_refs.sh - # Fix escape character: - perl -pi -e 's/\e/\\E/g' tools/api_refs/.phpdoc/template/package-edition-map.twig - else - tools/php_api_ref/phpdoc.sh - # Fix escape character: - perl -pi -e 's/\e/\\E/g' tools/php_api_ref/.phpdoc/template/package-edition-map.twig - cd tools/raml2html/; composer install; cd -; - php tools/raml2html/raml2html.php build --non-standard-http-methods=COPY,MOVE,PUBLISH,SWAP -t default -o docs/api/rest_api/rest_api_reference/ docs/api/rest_api/rest_api_reference/input/ibexa.raml - fi + tools/api_refs/api_refs.sh - name: Commit - env: - BASE_BRANCH: ${{ steps.version_and_branches.outputs.base_branch }} run: | git config --global user.name "${GITHUB_ACTOR}" git config --global user.email "${GITHUB_ACTOR}@users.noreply.github.com" - git add docs/api/php_api/php_api_reference/ - if [[ '4.6' != $BASE_BRANCH ]]; then - git add tools/api_refs/.phpdoc/template/package-edition-map.twig - else - git add tools/php_api_ref/.phpdoc/template/package-edition-map.twig - fi - git diff-index --quiet --cached HEAD || git commit -m "PHP API Ref HTML" git add docs/api/rest_api/rest_api_reference/rest_api_reference.html git diff-index --quiet --cached HEAD || git commit -m "REST API Ref HTML" - if [[ '4.6' != $BASE_BRANCH ]]; then - git add docs/api/rest_api/rest_api_reference/openapi.yaml - git add docs/api/rest_api/rest_api_reference/openapi.json - git diff-index --quiet --cached HEAD || git commit -m "REST API OpenAPI spec" - fi + git add docs/api/rest_api/rest_api_reference/openapi.yaml + git add docs/api/rest_api/rest_api_reference/openapi.json + git diff-index --quiet --cached HEAD || git commit -m "REST API OpenAPI spec" - name: Create Pull Request uses: peter-evans/create-pull-request@v8 with: token: ${{ secrets.EZROBOT_PAT }} - title: "API Refs ${{ steps.version_and_branches.outputs.version }}" - body: "PHP API & REST API References update for ${{ steps.version_and_branches.outputs.version }}" + title: "REST API Reference ${{ steps.version_and_branches.outputs.version }}" + body: "REST API Reference update for ${{ steps.version_and_branches.outputs.version }}" branch: "${{ steps.version_and_branches.outputs.work_branch }}" base: "${{ steps.version_and_branches.outputs.base_branch }}" draft: false diff --git a/.github/workflows/preview_comment.yaml b/.github/workflows/preview_comment.yaml index 43f2bd9c0cf..51c122d2675 100644 --- a/.github/workflows/preview_comment.yaml +++ b/.github/workflows/preview_comment.yaml @@ -32,34 +32,16 @@ jobs: build_url="https://ez-systems-developer-documentation--${{ github.event.pull_request.number }}.com.readthedocs.build/${{inputs.project}}en/${{ github.event.pull_request.number }}/" md_change_list=$(git diff --name-only HEAD "origin/$GITHUB_BASE_REF" -- docs/ | grep -E "^docs\/.*\.md$" | sed -E "s|^docs/(.*)\.md$|- [docs/\1.md](${build_url}\1/)|") - par_change_list=''; - for par_file in $(git diff --diff-filter=A --name-only "origin/$GITHUB_BASE_REF" HEAD -- docs/api/php_api/php_api_reference/ | grep -E '^docs\/.*\.html$'); do - fqcn=$(grep -o 'data-copy-value=".*">Copy FQCN' $par_file | sed -E 's|data-copy-value="(.*)">.*|\1|' | sed 's|\\|\\\\|g') - link=$(echo $par_file | sed -E "s|^docs/(.*\.html)$|- [\`${fqcn}\`](${build_url}\1)|") - par_change_list=$(echo -e "$par_change_list\n$link") - done - par_change_list=$(echo "$par_change_list" | sed '1d' | sort -t '`' -k 2,2) - change_count=$(( $(echo "$md_change_list" | wc -l) + $(echo "$par_change_list" | wc -l) )) + change_count=$(echo "$md_change_list" | wc -l) - echo -e "Markdown files:\n$md_change_list\n\nPHP API Ref.:\n$par_change_list" | perl -p -e 's/\e/\\E/g' + echo -e "Markdown files:\n$md_change_list" | perl -p -e 's/\e/\\E/g' - if [[ $change_count -gt $file_limit ]]; then - par_change_list=$(echo "$par_change_list" | grep -v namespaces) - change_count=$(( $(echo "$md_change_list" | wc -l) + $(echo "$par_change_list" | wc -l) )) - fi - - if [[ -z "$md_change_list$par_change_list" ]]; then + if [[ -z "$md_change_list" ]]; then comment="Preview of modified files: no change to preview." elif [[ $change_count -gt $file_limit ]]; then comment="Preview of modified files: Too many files modified in a single PR, preview link list is skipped. ($change_count files > $file_limit)" else - comment="# Preview of modified files" - if [[ -n "$md_change_list" ]]; then - comment="$comment\n\nPreview of modified Markdown:\n\n$md_change_list" - fi - if [[ -n "$par_change_list" ]]; then - comment="$comment\n\nPreview of addition to PHP API Reference:\n\n$par_change_list" - fi + comment="# Preview of modified files\n\nPreview of modified Markdown:\n\n$md_change_list" fi echo -e "$comment" | perl -p -e 's/\e/\\E/g' > comment.md diff --git a/.github/workflows/yaml_samples.yaml b/.github/workflows/yaml_samples.yaml new file mode 100644 index 00000000000..5bfafa96bbe --- /dev/null +++ b/.github/workflows/yaml_samples.yaml @@ -0,0 +1,51 @@ +name: "Validate YAML samples" + +on: + pull_request: ~ + +jobs: + yaml-samples-validation: + name: Validate YAML samples + runs-on: "ubuntu-26.04" + strategy: + fail-fast: false + matrix: + php: + - "8.4" # Upper supported version + - "8.3" # Lower supported version + steps: + - uses: actions/checkout@v7 + + - name: Setup PHP Action + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + extensions: "pdo_sqlite, gd" + tools: cs2pr + + - name: Generate token + id: generate_token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ secrets.AUTOMATION_CLIENT_ID }} + private-key: ${{ secrets.AUTOMATION_CLIENT_SECRET }} + owner: ${{ github.repository_owner }} + + - name: Add composer keys for private packagist + run: | + composer config --global http-basic.updates.ibexa.co $SATIS_NETWORK_KEY $SATIS_NETWORK_TOKEN + composer config --global github-oauth.github.com $GITHUB_TOKEN + env: + SATIS_NETWORK_KEY: ${{ secrets.SATIS_NETWORK_KEY }} + SATIS_NETWORK_TOKEN: ${{ secrets.SATIS_NETWORK_TOKEN }} + GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} + + # The installed ibexa/* bundles are what makes it possible to build the + # full Symfony configuration tree the YAML samples are validated against. + - uses: ramsey/composer-install@v4 + with: + dependency-versions: highest + + - name: Validate YAML configuration samples + run: composer check-yaml --ansi diff --git a/.gitignore b/.gitignore index f48666154a4..2d4ab85f786 100644 --- a/.gitignore +++ b/.gitignore @@ -4,21 +4,17 @@ __pycache__/* **/__pycache__ /site/ **/.idea/ -.php-cs-fixer.cache composer.lock -tools/php-cs-fixer/vendor node_modules/ auth.json .yarn yarn.lock docs/css/*.map -.deptrac.cache .lycheecache lychee.toml /repositories/ lychee-report.md .phpunit.result.cache -code_samples/_inline_php/ /build/ *.egg-info/ /doc/ @@ -27,3 +23,5 @@ code_samples/_inline_php/ /user/ /class_paths.json /user-docs/ +.scratch/ +AGENTS.md diff --git a/README.md b/README.md index 6226a923888..0033fc0e1fb 100644 --- a/README.md +++ b/README.md @@ -42,11 +42,12 @@ mkdocs serve After a short while your documentation should be reachable at http://localhost:8000. If it isn't, check the output of the command. -## Testing the code samples +## Testing the documentation ### YAML configuration -To test the YAML configuration, run the following commands: +The YAML snippets in `code_samples/` and in the Markdown pages are validated against the +Symfony configuration trees of the installed Ibexa bundles. To run the validation, use: ``` bash composer update @@ -78,54 +79,6 @@ Some issues can be fixed automatically: yarn markdownlint --fix ``` -### PHPStan - -This repository uses PHPStan to test the code samples. To run the tests locally execute the commands below: -```bash -composer update -composer phpstan -``` - -Regenerate the baseline by running: - -```bash -composer phpstan-update-baseline -``` - -#### Skipping validation of inline PHP snippets - -PHP code blocks embedded directly in Markdown files are extracted and tested with PHPStan. -To exclude a snippet from validation (for example, for an intentionally incomplete fragment), add the `skip-validation` marker to its opening fence: - -````markdown -``` php {skip-validation} -``` -```` - -If the code block uses other options, such as `hl_lines`, they must be placed **inside the same curly-brace group** as the marker: - -````markdown -``` php {skip-validation hl_lines="6 14"} -``` -```` - -Both `php {skip-validation} hl_lines="6 14"` and `php hl_lines="6 14" {skip-validation}` are rejected by the Markdown parser, and the whole code block is rendered as plain paragraph text. - -### Deptrac - -This repository uses Deptrac to test the code samples. To run the tests locally execute the commands below: - -```bash -composer update -composer deptrac -``` - -Regenerate the baseline by running: - -```bash -composer deptrac-update-baseline -``` - ## Checking links External links in the built documentation are checked using [lychee](https://lychee.cli.rs). diff --git a/composer.json b/composer.json index 6279c11be6f..ad917dbf7ed 100644 --- a/composer.json +++ b/composer.json @@ -1,8 +1,8 @@ { "name": "ibexa/documentation-developer", - "description": "Ibexa DXP developer documentation as Markdown files, for offline reading and AI coding assistants working inside your project.", + "description": "Cohesivo developer documentation as Markdown files, for offline reading and AI coding assistants working inside your project.", "type": "library", - "keywords": ["ibexa", "ibexa-dxp", "documentation", "markdown", "llm", "ai", "agents"], + "keywords": ["ibexa", "cohesivo", "documentation", "markdown", "llm", "ai", "agents"], "license": "GNU General Public License v2.0", "autoload-dev": { "psr-4": { @@ -22,10 +22,6 @@ "phpunit/phpunit": "^11.0", "symfony/yaml": "^7.0", "ibexa/connector-gemini": "6.0.x-dev", - "ibexa/code-style": "~2.0.0", - "friendsofphp/php-cs-fixer": "^3.30", - "phpstan/phpstan": "^2.0", - "phpstan/phpstan-symfony": "^2.0", "ibexa/doctrine-schema": "6.0.x-dev", "ibexa/search": "6.0.x-dev", "ibexa/content-forms": "6.0.x-dev", @@ -35,7 +31,6 @@ "ibexa/notifications": "6.0.x-dev", "ibexa/product-catalog-date-time-attribute": "6.0.x-dev", "ibexa/fieldtype-richtext": "6.0.x-dev", - "ibexa/rector": "6.0.x-dev", "ibexa/rest": "6.0.x-dev", "ibexa/http-cache": "6.0.x-dev", "ibexa/core-persistence": "6.0.x-dev", @@ -78,9 +73,7 @@ "ibexa/messenger": "~6.0.x-dev", "ibexa/collaboration": "~6.0.x-dev", "ibexa/share": "~6.0.x-dev", - "ibexa/phpstan": "~6.0.-dev", "ibexa/connector-quable": "6.0.x-dev", - "deptrac/deptrac": "^3.0", "ibexa/cdp": "~6.0.x-dev", "ibexa/connector-raptor": "~6.0.x-dev", "ibexa/image-editor": "~6.0.x-dev", @@ -97,30 +90,9 @@ "ibexa/design-system-twig": "~6.0.x-dev" }, "scripts": { - "fix-cs": [ - "php tools/extract-inline-php.php", - "php-cs-fixer fix --config=.php-cs-fixer.php -v --show-progress=dots", - "php-cs-fixer fix --config=.php-cs-fixer-inline.php -v --show-progress=dots", - "php tools/sync-inline-php-to-markdown.php" - ], - "check-cs": [ - "php tools/extract-inline-php.php", - "php-cs-fixer fix --config=.php-cs-fixer.php -v --show-progress=dots --dry-run", - "php-cs-fixer fix --config=.php-cs-fixer-inline.php -v --show-progress=dots --dry-run" - ], - "phpstan": "php tools/extract-inline-php.php && phpstan analyse", - "deptrac": "php tools/extract-inline-php.php && deptrac analyse", - "fix-rector": [ - "php tools/extract-inline-php.php", - "rector process --ansi", - "php tools/sync-inline-php-to-markdown.php" - ], - "check-rector": "php tools/extract-inline-php.php && rector process --dry-run --ansi", "check-yaml": "phpunit --group yaml", "phpunit": "phpunit --exclude-group=yaml", "yaml-update-baseline": "php tests/generate-yaml-baseline.php", - "phpstan-update-baseline": "@phpstan --generate-baseline", - "deptrac-update-baseline": "@deptrac --formatter=baseline", "composer-update": "[ -d vendor ] || composer update", "yarn-install": "[ -d node_modules ] || yarn install", "markdownlint": [ @@ -133,39 +105,26 @@ ], "test": [ "@composer-update", - "EXIT=0; FAILED=''; { composer check-cs; } || { EXIT=1; FAILED=\"$FAILED check-cs\"; }; { composer phpstan; } || { EXIT=1; FAILED=\"$FAILED phpstan\"; }; { composer deptrac; } || { EXIT=1; FAILED=\"$FAILED deptrac\"; }; { composer check-rector; } || { EXIT=1; FAILED=\"$FAILED check-rector\"; }; { composer markdownlint; } || { EXIT=1; FAILED=\"$FAILED markdownlint\"; }; { composer check-yaml; } || { EXIT=1; FAILED=\"$FAILED check-yaml\"; }; if [ 1 -eq $EXIT ]; then echo \"Failed:$FAILED\"; fi; exit $EXIT;" + "EXIT=0; FAILED=''; { composer markdownlint; } || { EXIT=1; FAILED=\"$FAILED markdownlint\"; }; { composer check-yaml; } || { EXIT=1; FAILED=\"$FAILED check-yaml\"; }; if [ 1 -eq $EXIT ]; then echo \"Failed:$FAILED\"; fi; exit $EXIT;" ], "fix": [ - "@composer-update", - "@composer fix-rector", - "@composer fix-cs", "@composer fix-markdownlint" ], "baseline": [ "@composer-update", - "@composer phpstan-update-baseline", - "@composer deptrac-update-baseline", "@composer yaml-update-baseline" ] }, "scripts-descriptions": { - "fix-cs": "Automatically fixes code style in all files", - "check-cs": "Run code style checker for all files", - "phpstan": "Run static code analysis", - "deptrac": "Run Deptrac architecture testing", - "fix-rector": "Automatically applies Rector refactoring to code samples and syncs back to Markdown", - "check-rector": "Check for code refactoring opportunities", "check-yaml": "Run PHPUnit tests (YAML validation)", "yaml-update-baseline": "Regenerate tests/yaml-validation-baseline.yaml from current failures", - "phpstan-update-baseline": "Regenerate PHPStan baseline from current failures", - "deptrac-update-baseline": "Regenerate Deptrac baseline from current failures", "composer-update": "Install composer dependencies if not already installed", "yarn-install": "Install yarn dependencies if not already installed", "markdownlint": "Run Markdownlint on all documentation files", "fix-markdownlint": "Automatically fixes Markdownlint issues in all documentation files", - "test": "Run all checks (CS-Fixer, PHPStan, Deptrac, Rector, Markdownlint, YAML checks), continuing past failures and reporting failure overall if any check failed", - "fix": "Run all automatic fixes (Rector, CS-Fixer, Markdownlint)", - "baseline": "Regenerate all baselines (PHPStan, Deptrac, YAML) from current failures" + "test": "Run all checks (Markdownlint, YAML checks), continuing past failures and reporting failure overall if any check failed", + "fix": "Run all automatic fixes (Markdownlint)", + "baseline": "Regenerate the YAML validation baseline from current failures" }, "config": { "allow-plugins": false diff --git a/docs/administration/admin_panel/corporate_admin_panel.md b/docs/administration/admin_panel/corporate_admin_panel.md index d03f8873378..43810c4808b 100644 --- a/docs/administration/admin_panel/corporate_admin_panel.md +++ b/docs/administration/admin_panel/corporate_admin_panel.md @@ -1,6 +1,5 @@ --- description: You can manage companies profiles in the Admin Panel. -edition: experience --- # Corporate diff --git a/docs/administration/admin_panel/segments_admin_panel.md b/docs/administration/admin_panel/segments_admin_panel.md index 1f9e3e144c7..d932c848a7f 100644 --- a/docs/administration/admin_panel/segments_admin_panel.md +++ b/docs/administration/admin_panel/segments_admin_panel.md @@ -1,6 +1,5 @@ --- description: You can use segments to display specific content to specific users. -edition: experience --- # Segments @@ -16,4 +15,4 @@ 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). +You can assign users to segments over the [REST API](rest_api_usage.md). diff --git a/docs/administration/administration.md b/docs/administration/administration.md index b371a4788a6..f7ba88b1338 100644 --- a/docs/administration/administration.md +++ b/docs/administration/administration.md @@ -9,7 +9,6 @@ Administer and configure your [[= product_name =]] installation. [[= cards([ "administration/admin_panel/admin_panel", - "administration/project_organization/project_organization", "administration/configuration/configuration", "administration/back_office/back_office", ], columns=4) =]] diff --git a/docs/administration/back_office/back_office.md b/docs/administration/back_office/back_office.md index 8ab35513551..ae96520db55 100644 --- a/docs/administration/back_office/back_office.md +++ b/docs/administration/back_office/back_office.md @@ -5,25 +5,10 @@ page_type: landing_page # Back office -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`. +The back office is the web interface where editors and administrators work with content. -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. - -!!! 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. [[= cards([ - "administration/back_office/back_office_configuration", - "administration/back_office/back_office_menus/back_office_menus", - "administration/back_office/back_office_tabs/back_office_tabs", - "administration/back_office/back_office_elements/reusable_components", - "administration/back_office/notifications", - "administration/back_office/browser/browser", - "administration/back_office/add_user_setting", - "administration/back_office/customize_calendar", -], columns=4) =]] + "administration/back_office/integrated_help", + "administration/back_office/product_tour", +], columns=3) =]] diff --git a/docs/administration/back_office/back_office_configuration.md b/docs/administration/back_office/back_office_configuration.md deleted file mode 100644 index 352c12a65d7..00000000000 --- a/docs/administration/back_office/back_office_configuration.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -description: Configure default upload locations, pagination limits, and more settings for the back office. ---- - -# Back office configuration - -## Pagination limits - -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/6.0/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): - -``` yaml -ibexa: - system: - : - pagination_user: - user_settings_limit: 6 -``` - -You can configure the following settings to manage the pagination limits for the product catalog: - -``` yaml -ibexa: - system: - : - product_catalog: - pagination: - attribute_definitions_limit: 10 - attribute_groups_limit: 10 - currencies_limit: 10 - customer_groups_limit: 10 - customer_group_users_limit: 10 - products_limit: 10 - product_types_limit: 10 - product_view_custom_prices_limit: 10 - regions_limit: 10 - catalogs_limit: 10 -``` - -## Subtree operations - -### 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 by setting the `ibexa.system..subtree_operations.copy_subtree.limit` [configuration key](configuration.md#configuration-files). - -The limit applies only to the UI of the back office and disables the "Copy subtree" operation. - -The default value is `100`. You can set it to `-1` for no limit, or to `0` to completely disable copying subtrees. - -To copy a subtree regardless of the limit, use the following console command: - -``` bash -php bin/console ibexa:copy-subtree -``` - -### Query subtree limit - -When working with large content trees, counting child items or calculating subtree sizes can cause significant performance degradation due to unbounded database queries. -You can limit these count operations by setting the `ibexa.system..subtree_operations.query_subtree.limit` [configuration key](configuration.md#configuration-files): - -``` yaml -ibexa: - system: - : - subtree_operations: - copy_subtree: - limit: 100 - query_subtree: - limit: 500 -``` - -The default value for `query_subtree.limit` is `500`. -You can set it to `-1` to disable the limit. - -This limit applies in some cases when the back office needs to determine if a location has children or calculate the number of items in a subtree. -The limit does not affect the sub-items list, which still displays all child elements in a paginated way. - -When a limit is set, the query stops after finding the specified number of items instead of performing a full count. -This significantly improves performance on locations with large numbers of children. -The resulting count is displayed with a `+` sign, indicating that the result is not exact. - -![Example of subtree count with exceeded limit](img/query_subtree_limit_locations_tab.png "Example of subtree count with exceeded limit") - -## Default locations - -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: - system: - : - location_ids: - content_structure: 2 - media: 43 - users: 5 -``` diff --git a/docs/administration/back_office/configure_product_tour.md b/docs/administration/back_office/configure_product_tour.md deleted file mode 100644 index 94704e3b6a4..00000000000 --- a/docs/administration/back_office/configure_product_tour.md +++ /dev/null @@ -1,299 +0,0 @@ ---- -description: Configure custom product tour scenarios with steps, blocks, and interaction modes. -edition: lts-update -month_change: false ---- - -# Configure product tour scenarios - -You can configure the product tour scenarios to adapt it to your project needs, covering different onboarding scenarios. - -Product tour scenarios are configured with YAML configuration files. -Configuration is SiteAccess-aware, allowing you to create separate onboarding experiences for different back offices in [multisite setups](multisite.md). - -For more advanced customization cases that require PHP code, see [Customize product tour](customize_product_tour.md). - -Use the default provided configuration, available in `config/packages/ibexa_integrated_help_tours.yaml`, as a starting point that you can adjust to your needs. - -## Configuration structure - -You configure product tour scenarios under the `ibexa.system..product_tour` key. -Each scenario has a unique identifier and contains steps, which in turn contain blocks. - -The basic configuration structure of a scenario is as follows: - -```yaml -ibexa: - system: - >: # For example, admin or admin_group - product_tour: - : - type: - scenario_title_translation_key: # Optional - user_groups_excluded: [, ...] # Optional - steps: - : # Scenario step, unique within a scenario - step_title_translation_key: - background_image: # Only for general type, optional - target: # Only for targetable type, required - interaction_mode: # Only for targetable type, optional - blocks: - - type: - params: - # Block-specific parameters - # ... -``` - -The product tour scenarios are meant to be translatable. -[[= product_name_base =]] recommends using translation keys instead of literal values in the YAML configuration, and providing the translations separately. -Use the `ibexa_integrated_help` translation domain. - -For all the examples below, you can provide the translations by creating a `translations/ibexa_integrated_help.en.yaml` file with the following content: - -``` yaml -tour.my_general_scenario.title: "My general scenario" -title: "Welcome!" -subtitle: "This is the subtitle" -tour.step.description: "This is the description of the step, you can use it to explain what to do in this step." -tour.link.documentation: "Documentation link" -tour.list.title: "This is the list title" -tour.list.item1: "First item" -tour.list.item2: "Second item" -tour.list.item3: "Third item" -``` - -To insert a line break into a translation, HTML encode the `
` entities to `<br/>`. - -## Scenario configuration - -Each scenario must specify its type and can optionally restrict access by user groups. - -### Scenario display order - -The order of scenarios in the configuration file determines the order in which they are evaluated and, if the right conditions are met, displayed. - -There are two [scenario types](product_tour.md#scenario-types): - -- `general` scenarios appear at the earliest opportunity (on any page after logging in), with an exception of the user settings area -- `targetable` scenarios begin if their `target` element is found in the DOM when the page is loaded. -Targetable scenarios don't trigger in the user settings area as well. - -To control where a targetable tour appears, ensure that the first step targets an element unique to that specific page. -You can target elements that appear after a user action, for example, modals like [content browser](browser.md), but the first step's target must be present in the DOM when the page is loaded. - -Once a scenario ends, the system evaluates the next scenario from the configuration and, if applicable, displays it. - -### Scenario title - -Use the optional `scenario_title_translation_key` field to provide a human-readable label for a scenario. -This label is displayed in the user settings page where users can reset their product tour progress. - -```yaml -product_tour: - welcome_tour: - type: general - scenario_title_translation_key: tour.welcome_tour.title -``` - -If the translation key is not set, the raw scenario identifier is used as the label. - -Translations must be provided in the `ibexa_integrated_help` translation domain, for example, in `translations/ibexa_integrated_help.en.yaml`. - -### User group restrictions - -Restrict scenario visibility by excluding specific user groups by using their content remote IDs: - -```yaml -product_tour: - my_scenario: - user_groups_excluded: ['user_group_content_remote_id_1', 'user_group_content_remote_id_2'] # Exclude specific user groups -``` - -When creating new [back office user groups](user_registration.md#user-types), decide whether the existing product tour scenarios should be available for these new user groups. -If not, add the new group to the exclusion list. - -!!! caution - - If a scenario contains information meant only for specific group of users, always use the `user_groups_excluded` setting to exclude other groups. - Don't rely only on UI access restrictions to control the access to scenarios, as a malicious internal user could trigger and preview them outside of the intended place. - -## Step configuration - -Steps define individual instructions within a scenario. -The configuration differs based on scenario type: - -### General scenario steps - -General scenario steps display centered modals and support the `background_image` setting, allowing you to set a shared background image for each step. -For the background, you can use an absolute URL or place your image in the `public` directory and provide the path relative to it. -To resolve the path relative to the site root, [prefix it with `/`](https://developer.mozilla.org/en-US/docs/Web/API/URL_API/Resolving_relative_references#root_relative). - -```yaml hl_lines="6 11" -[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 0, 14) =]] -``` - -### Targetable tour steps - -Targetable tour steps highlight specific UI elements by using CSS selectors. -You can select a specific element by using the `target` setting. - -```yaml hl_lines="6 11" -[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 0, 15) =]] -``` - -If a step's target element doesn't exist on the page, the step isn't displayed and the scenario is stopped. -Ensure your configuration matches the actual DOM structure to avoid broken scenarios. -Use unique selectors to avoid triggering your scenarios on other pages. - -#### Interaction modes - -Select how the scenario step interacts with the target element by using the `interaction_mode` setting. -Targetable steps support [three interaction modes](product_tour.md#targetable-scenarios): - -!!! note - - Clickable and draggable modes are designed for single actions only (buttons, links). - You can't select an entire form. - If the interaction with the highlighted element results in redirection to a new page or opening a modal window where the previous target element can't be found, the "Previous" navigation button won't be displayed. - -**Standard mode**: - -The default value. -A tooltip attached to a specific element on the page is displayed. -Users continue the scenario with **Previous**/**Next** buttons: - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 8, 16) =]] -``` - -![Standard interaction mode](img/product_tour/standard_mode.png "Standard interaction mode") - -**Clickable mode**: - -A tooltip attached to a specific element on the page is displayed. -Users continue the scenario by clicking the highlighted element. - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 16, 24) =]] -``` - -![Clickable interaction mode](img/product_tour/clickable_mode.png "Clickable interaction mode") - -**Draggable mode**: - -A tooltip attached to a specific element on the page is displayed. -Users continue the scenario by [dragging](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API#draggable_items) the highlighted element. - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml', 32, 40) =]] -``` - -You can use this mode only with HTML elements that have the [`draggable` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/draggable) set to `true`. - -![Draggable interaction mode](img/product_tour/draggable_mode.png "Draggable interaction mode") - -## Block types - -Blocks are content elements that make up each step, available both for `general` and `targetable` scenarios. -Seven block types are available for building step content, and a scenario step must contain at least one. -If multiple blocks are defined for a step, they are displayed one after the other. - -### Title block - -Display bold, prominent titles: - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 12, 15) =]] -``` - -### Text block - -Display regular text content: - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 15, 18) =]] -``` - -### Link block - -Add external or internal links: - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 18, 22) =]] -``` - -### List block - -Create bulleted lists with title: - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 30, 37) =]] -``` - -The `title_translation_key` property is optional. - -### Media blocks - -To provide data to the media block, provide absolute URLs or place your image or video files in the `public` directory and provide the path relative to it. -To resolve the path relative to the site root, [prefix it with `/`](https://developer.mozilla.org/en-US/docs/Web/API/URL_API/Resolving_relative_references#root_relative). - -#### Image block - -Embed images inside the step. -You can provide alternative text by using the `alt_translation_key` property. - -Assuming a `public/img/diagram.jpg` image exists, set the configuration value to `/img/diagram.jpg`. - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 22, 26) =]] -``` - -#### Video block - -Embed video content by using the [`video` HTML element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/video): - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 26, 30) =]] -``` - -### Custom Twig template block - -For advanced content, use custom Twig templates that allows you to fully control the styling of the block: - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml', 37, 40) =]] -``` - -Create the dedicated template, for example in `templates/custom_template.html.twig`. - -``` html+twig -{% trans_default_domain 'app' %} - -{{ 'custom_step_description'|trans }} -``` - -and provide the required translations in `translations/app.en.yaml`: - -``` yaml -custom_step_description: "This is a description coming from a custom template." -``` - -## Configuration examples - -### Example 1: General welcome tour - -The following example showcases all the built-in block types for a `general` scenario consisting of a single step. - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/general_scenario.yaml') =]] -``` - -### Example 2: Targetable feature tour with interactive steps - -The following example showcases how the three interaction modes of a `targetable` scenario can be used to build an onboarding tour for the [customizable dashboard](customize_dashboard.md): - -```yaml -[[= include_file('code_samples/back_office/product_tour/config/targetable_scenario.yaml') =]] -``` - -To learn how to customize your scenarios even further with PHP code, see [Customize product tour](customize_product_tour.md). diff --git a/docs/administration/back_office/content_tree.md b/docs/administration/back_office/content_tree.md deleted file mode 100644 index f247a0de0a5..00000000000 --- a/docs/administration/back_office/content_tree.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -description: Configure SiteAccess, displayed content items, depth and root location for the content tree. ---- - -# Content tree - -With this configuration you can: - -- define configuration for a SiteAccess or a SiteAccess group -- 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 - -```yaml -ibexa: - system: - # any SiteAccess or SiteAccess group - admin_group: - content_tree_module: - # 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 - allowed_content_types: '*' - # 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 is changed - contextual_tree_root_location_ids: - - 2 # Home (Content structure) - - 5 # Users - - 43 # Media -``` diff --git a/docs/administration/back_office/content_type_anchor_menu.md b/docs/administration/back_office/content_type_anchor_menu.md deleted file mode 100644 index 4389949d3b1..00000000000 --- a/docs/administration/back_office/content_type_anchor_menu.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -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). - -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): - -```yaml -ibexa: - system: - admin_group: - admin_ui_forms: - content_type_edit: - field_types: - : - meta: true - position: 100 - -``` - -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 - -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. - -![SEO anchor menu](content_type_edit_screen_anchor_menu.png) - -!!! note - - If you add multiple field types as anchor menus, they're automatically displayed as separate sections. diff --git a/docs/administration/back_office/integrated_help.md b/docs/administration/back_office/integrated_help.md index d8bb081fefd..dc9d4613d55 100644 --- a/docs/administration/back_office/integrated_help.md +++ b/docs/administration/back_office/integrated_help.md @@ -1,35 +1,23 @@ --- description: Integrated help provides quick access to documentation, training, and support resources. -edition: lts-update month_change: false --- # Integrated help -Integrated help is an [LTS Update](editions.md#lts-updates) that brings documentation, training resources, and product roadmap-related information into the back office, together with user onboarding capabilities. -With this feature installed, users can click the ![Help icon](about-info.png){.inline-image} icon to access relevant content straight from the UI. +Integrated help brings documentation, training resources, and product roadmap-related information into the back office, together with user onboarding capabilities. +With this feature, users can click the ![Help icon](about-info.png){.inline-image} icon to access relevant content straight from the UI. ![Integrated help menu](5_0_integrated_help_menu.png) -Integrated help is contextual, therefore, apart from user documentation, release notes, and partner guidelines, which are available to editors and store managers, developers can access API references, the GraphQL console, or the support portal. - ## Product tours -Product tours are interactive guided walkthroughs that help back office users discover [[= product_name =]] features, available starting with [[= product_name =]] v4.6.29. +Product tours are interactive guided walkthroughs that help back office users discover [[= product_name =]] features. They provide step-by-step guidance directly within the application interface, accelerating user adoption and reducing training time. Developers can create custom onboarding journeys tailored to specific client implementations, user roles, or business processes. For more information, see [Product tour](product_tour.md). -## Install package - -The Integrated help LTS Update is optional. -To enable it, run the following command: - -```bash -composer require ibexa/integrated-help -``` - -After installation, the help center is enabled by default for all back office users. +The help center is enabled by default for all back office users. If needed, they can [disable it in user settings]([[= user_doc =]]/getting_started/discover_ui/#disable-help-center). diff --git a/docs/administration/back_office/product_tour.md b/docs/administration/back_office/product_tour.md index ec8df708c5c..335bc9dd335 100644 --- a/docs/administration/back_office/product_tour.md +++ b/docs/administration/back_office/product_tour.md @@ -1,6 +1,5 @@ --- description: Product tours provide interactive guided walkthroughs to help users learn Cohesivo features. -edition: lts-update month_change: false --- @@ -12,8 +11,7 @@ Unlike static documentation, product tours provide real-time, contextual guidanc With product tours, you can create customized onboarding journeys tailored to specific client implementations, user roles, or business processes. This accelerates user adoption, reduces training time, and helps users confidently navigate the platform. -Product tour functionality is available from versions 4.6.29 and 5.0.7 as part of the Integrated help package. -To use product tours, you must first [install the Integrated help LTS Update](integrated_help.md#install-package). +To use product tours, you must first enable [Integrated help](integrated_help.md).
@@ -76,5 +74,3 @@ For **Standard** scenario steps, users can move freely between the previous and For **Clickable** and **Draggable** steps, users can't go back to the previous step without restarting the scenario and starting from the beginning. At any time, users can manually restart completed tours from their [user settings]([[= user_doc =]]/getting_started/get_started/#user-settings). - -To start building your custom onboarding scenarios, see [Configure product tour](configure_product_tour.md). diff --git a/docs/administration/back_office/subitems_list.md b/docs/administration/back_office/subitems_list.md deleted file mode 100644 index 9bc275aec73..00000000000 --- a/docs/administration/back_office/subitems_list.md +++ /dev/null @@ -1,161 +0,0 @@ ---- -description: Inject a sub-items list into your back office customizations or customize the view. -month_change: false ---- - -# 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. - -## Create custom sub-items list view - -You can extend the Sub-items List module to replace an existing view or add your own. -The example below adds a new timeline view to highlight the modification date. - -![Sub-items List module using the new Timeline view](img/subitems/timeline_view.png "Sub-items List module using the new Timeline view") - -To recreate it, start by creating the components responsible for rendering the new view. -You can create two files: - -- `assets/js/timeline.view.component.js` responsible for rendering the whole view - -``` js -[[= include_file('code_samples/back_office/subitems/timeline_view/timeline.view.component.js') =]] -``` - -- `assets/js/timeline.view.item.component.js` responsible for rendering a single item - -``` js -[[= include_file('code_samples/back_office/subitems/timeline_view/timeline.view.item.component.js') =]] -``` - -Provide the necessary styling in `assets/scss/timeline.view.scss`. The example below uses [[= product_name =]]'s SCSS variables for consistency with the rest of the back office interface. - -``` scss -[[= include_file('code_samples/back_office/subitems/timeline_view/timeline.view.scss') =]] -``` - -The last step is adding the view module to the list of available views in the system, by using the provided `registerView` function. - -You can create a new view by providing an unique identifier, or replace an existing one by reusing its identifier. -The existing view identifiers are defined as JavaScript constants in the `@ibexa-admin-ui-modules/sub-items/constants` module: - -- Grid view: `VIEW_MODE_GRID` constant -- Table view: `VIEW_MODE_TABLE` constant - -Create a file called `assets/js/registerTimelineView.js`: - -``` js -[[= include_file('code_samples/back_office/subitems/timeline_view/registerTimelineView.js') =]] -``` - -And include it into the back office using Webpack Encore, together with your custom styles. -See [configuring assets from main project files](importing_assets_from_bundle.md#configuration-from-main-project-files) to learn more about this mechanism. - -``` js -const ibexaConfigManager = require('./ibexa.webpack.config.manager.js'); - -//... - -ibexaConfigManager.add({ - ibexaConfig, - entryName: 'ibexa-admin-ui-layout-js', - newItems: [ - path.resolve(__dirname, './assets/js/registerTimelineView.js') - ], -}); - -ibexaConfigManager.add({ - ibexaConfig, - entryName: 'ibexa-admin-ui-layout-css', - newItems: [ - path.resolve(__dirname, './assets/scss/timeline.view.scss'), - ], -}); -``` - -Complete the task by running `composer run post-install-cmd`. - -## Use sub-items list - -!!! caution - - If you want to load the Sub-items module from your custom code, you need to load the JS code for it in your view, as it's not available by default. - -With plain JS: - -``` js -[[= include_file('code_samples/back_office/subitems/render_subitems.js') =]] -``` - -With JSX: - -``` jsx -[[= include_file('code_samples/back_office/subitems/render_subitems.jsx') =]] -``` - -## Properties list - -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 cannot work. - -- **parentLocationId** _{Number}_ - parent location ID -- **restInfo** _{Object}_ - backend config object: - - **token** _{String}_ - CSRF token - - **siteaccess** _{String}_ - SiteAccess identifier -- **handleEditItem** _{Function}_ - callback to handle edit content action -- **generateLink** _{Function}_ - callback to handle view content action - -### Optional properties - -Optionally, Sub-items module can take a following list of props: - -- **loadContentInfo** _{Function}_ - loads content item info. Takes two params: - - **contentIds** _{Array}_ - list of content IDs - - **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: - - **restInfo** _{Object}_ - REST info params: - - **token** _{String}_ - the user token - - **siteaccess** _{String}_ - the current SiteAccess - - **queryConfig** _{Object}_ - query config: - - **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: - - **params** _{Object}_ - parameters hash containing: - - **priority** _{Number}_ - priority value - - **location** _{String}_ - REST location ID - - **token** _{String}_ - CSRF token - - **siteaccess** _{String}_ - SiteAccess identifier - - **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 -- **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/6.0/src/bundle/ui-dev/src/modules/sub-items/sub.items.module.js) for details. Contains definitions for sub components: - - **subItems** _{Object}_ - list of sub-items module labels - - **tableView** _{Object}_ - list of table view component labels - - **tableViewItem** _{Object}_ - list of table item view component labels - - **loadMore** _{Object}_ - list of load more component labels - - **gridViewItem** _{Object}_ - list of grid item view component labels -- **languageContainerSelector** _{String}_ - selector where the language selector should be rendered - -## Reuse Sub-items list - -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`. diff --git a/docs/administration/configuration/configuration.md b/docs/administration/configuration/configuration.md index 064d8ac3e45..b0f17d8109e 100644 --- a/docs/administration/configuration/configuration.md +++ b/docs/administration/configuration/configuration.md @@ -1,93 +1,58 @@ --- description: In Cohesivo you store and manage configuration in project files, typically in YAML format. +saas_review: + - siteaccess + - links_removed +saas_review_note: >- + Describes the configuration system, including SiteAccess-aware settings that take a + different value per SiteAccess, per SiteAccess group, or globally. Confirm how much + of this remains accurate once configuration is delivered through a UI rather than + project files. + + Links to the deleted php_api.md, repository_configuration.md, + template_configuration.md, devops.md, development_security.md, sessions.md and + persistence_cache.md pages were removed; check that the surrounding text still reads + correctly. --- # Configuration -[[= 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. +TODO: Rework this to describe the SiteAccess UI, and siteacces-aware settings. -## Configuration format +Merge the content from docs/multisite/siteaccess/siteaccess_aware_configuration.md -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 +#### `admin` SiteAccess -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`. +The predefined `admin` SiteAccess in `admin_group` serves the back office. -`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, for example, `config/packages/ibexa_admin_ui.yaml`, `config/packages/ibexa_http_cache.yaml`. -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. +## Location tree -!!! note "New configuration files" +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. - 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 - - Read more about [how configuration is handled in Symfony]([[= symfony_doc =]]/best_practices.html#configuration). - -!!! caution "Special characters" - - Avoid using special characters in your configuration files. More specifically, don't use Unicode characters from the ["Other" (`C`) categories](https://en.wikipedia.org/wiki/Unicode#General_Category_property), such as control or format characters. - - Make sure your IDE displays them. - - Be careful when copy-pasting text from a word processing software or a PDF, because it might contain hidden characters like the [soft hyphen](https://en.wikipedia.org/wiki/Soft_hyphen). - -## Configuration handling - -!!! note - - Configuration is tightly related to the [service container](php_api.md#service-container). - To fully understand it, you must be familiar with the service container and [its configuration]([[= symfony_doc =]]/service_container.html#service-container-parameters). - -Basic configuration handling in [[= product_name =]] is similar to what is commonly possible with Symfony. -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. - -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). - -You can also [implement SiteAccess-aware semantic configuration](siteaccess_aware_configuration.md). - -For example: +Configure this under the `ibexa.systems..content.tree_root` configuration key, for example: ``` yaml -parameters: - myapp.parameter.name: someValue - myapp.boolean.param: true - myapp.some.hash: - foo: bar - an_array: [apple, banana, pear] -``` - -``` php -// Usage inside a controller -/** @var \Symfony\Component\DependencyInjection\ContainerInterface $container */ -$myParameter = $container->getParameter('myapp.parameter.name'); +ibexa: + system: + : + content: + tree_root: + location_id: 42 + excluded_uri_prefixes: [/media/, /images/] + index_page: /EventFrontPage ``` -## Configuration settings +- `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`. + It's an array of prefixes. So, for example, `[/media]` would also exclude `/mediation` from root limit. +- `index_page` is the page shown when you access the root index `/`. -For specific configuration settings, see: +!!! note -- [Back office configuration](back_office_configuration.md) -- [Repository configuration](repository_configuration.md) -- [Content views](template_configuration.md) -- [Multisite configuration](multisite_configuration.md) -- [Image variations](images.md#configuring-image-variations) -- [Logging and debug](devops.md#logging-and-debug-configuration) -- [Authentication](development_security.md#symfony-authentication) -- [Sessions](sessions.md#configuration) -- [Persistence cache](persistence_cache.md#persistence-cache-configuration) + Prefixes aren't case sensitive. + Leading slashes (`/`) are automatically trimmed internally, so they can be ignored. diff --git a/docs/administration/configuration/dynamic_configuration.md b/docs/administration/configuration/dynamic_configuration.md deleted file mode 100644 index c5ebd43fe35..00000000000 --- a/docs/administration/configuration/dynamic_configuration.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -description: Use the ConfigResolver to inject dynamic configuration into your services. ---- - -# Dynamic configuration - -## ConfigResolver - -Dynamic configuration is handled by the [`ConfigResolverInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-SiteAccess-ConfigResolverInterface.html). - -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. - -To work with the ConfigResolver, your dynamic settings must have the following name format: `..parameter.name`. - -``` yaml -parameters: - # Internal configuration - ibexa.site_access.config.default.content.default_ttl: 60 - ibexa.site_access.config.site_group.content.default_ttl: 3600 - - # Here "myapp" is the namespace, followed by the SiteAccess name as the parameter scope - # Parameter "my_param" will have a different value in site_group and admin_group - myapp.site_group.my_param: value - myapp.admin_group.my_param: another value - # Defining a default value, for other SiteAccesses - myapp.default.my_param: Default value -``` - -Inside a controller extending the `Ibexa\Core\MVC\Symfony\Controller\Controller` class, in `site_group` SiteAccess, you can use the parameters in the following way (the same applies for `hasParameter()`): - -``` php {skip-validation} -$configResolver = $this->getConfigResolver(); - -// ibexa.site_access.config is the default namespace, so no need to specify it -// The following will resolve ibexa.site_access.config..content.default_ttl -// In the case of site_group, it will return 3600. -// Otherwise it will return the value for ibexa.site_access.config.default.content.default_ttl (60) -$locationViewSetting = $configResolver->getParameter( 'content.default_ttl' ); - -// For you own namespace, you need to specify it, here as "myapp" -$myParamSetting = $configResolver->getParameter( 'my_param', 'myapp' ); -// $myParamSetting's value will be 'value' -  -// You can also force the scope by naming it explicitly (here as "admin_group") -$myParamSettingAdmin = $configResolver->getParameter( 'my_param', 'myapp', 'admin_group' ); -// $myParamSetting's value will be 'another value' -``` - -!!! tip - - To learn more about scopes, see [SiteAccess documentation](multisite_configuration.md#scope). - -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 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 - -You can use the ConfigResolver in your own services whenever needed. -To do this, inject the `ibexa.config.resolver` service: - -``` yaml -services: - App\Service: - arguments: ['@ibexa.config.resolver'] -``` - -You can also use the [autowire feature]([[= symfony_doc =]]/service_container/autowiring.html), by type hinting against [`ConfigResolverInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-SiteAccess-ConfigResolverInterface.html). - -For more information about dependency injection, see [Service container](php_api.md#service-container). - -!!! note - - 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 -namespace App; - -use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface; - -class Service -{ - public function __construct(private readonly ConfigResolverInterface $configResolver) - { - } - - public function someMethodThatNeedConfig(): void - { - $configValue = $this->configResolver->getParameter('my_param', 'myapp'); - } -} -``` diff --git a/docs/administration/content_organization/content_types.md b/docs/administration/content_organization/content_types.md index 3ce24a50b51..a4d5d9f2c2d 100644 --- a/docs/administration/content_organization/content_types.md +++ b/docs/administration/content_organization/content_types.md @@ -86,17 +86,10 @@ They determine what fields of what field types are included in all content items !!! 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). !!! caution 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. - 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. If you're experincing too many issues, consider rearranging your project to avoid them. @@ -111,43 +104,4 @@ If a field definition is deleted from the content type, all the corresponding fi 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 need to change the configuration, so it reflects the available content types. - -Example configuration: - -```yaml -parameters: - ibexa.multifile_upload.location.default_mappings: - # Image - - mime_types: - - image/jpeg - - image/jpg - - image/pjpeg - - image/pjpg - - image/png - - image/bmp - - image/gif - - image/tiff - - image/x-icon - - image/webp - content_type_identifier: custom_image_contenttype - content_field_identifier: image - name_field_identifier: name - # File - - mime_types: - - image/svg+xml - - application/msword - - application/vnd.openxmlformats-officedocument.wordprocessingml.document - - application/vnd.ms-excel - - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet - - application/vnd.ms-powerpoint - - application/vnd.openxmlformats-officedocument.presentationml.presentation - - application/pdf - content_type_identifier: custom_file_contenttype - content_field_identifier: file - name_field_identifier: name - ibexa.multifile_upload.fallback_content_type: - content_type_identifier: custom_file_contenttype - content_field_identifier: file - name_field_identifier: name -``` +Don't remove the `file` or `image` content types, or change their identifiers. diff --git a/docs/administration/dashboard/configure_default_dashboard.md b/docs/administration/dashboard/configure_default_dashboard.md deleted file mode 100644 index c05e6839d26..00000000000 --- a/docs/administration/dashboard/configure_default_dashboard.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -description: Configure default dashboard. -edition: experience ---- - -# Configure default dashboard - -You can configure default dashboard under the `ibexa.system..admin_group` [configuration key](configuration.md#configuration-files). - -Create `ibexa_dashboard.yaml` file in the `config/packages/` directory. -The following example configuration defines default dashboard: - -``` yaml -ibexa: - system: - admin_group: - dashboard: - container_remote_id: dashboard_container - default_dashboard_remote_id: default_dashboard - users_container_remote_id: user_dashboards - predefined_container_remote_id: predefined_dashboards - section_identifier: dashboard - content_type_identifier: dashboard_landing_page - container_content_type_identifier: folder -``` - -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. - -## Container remote ID - -Defines starting location container for all the dashboards, including customized and predefined 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**. - -![Container remote ID](dashboard_container_remote_id.png) - -## Default dashboard 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'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's defined as **Location remote ID**. - -## Section identifier - -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 Type** section, **View/Global properties** tab. - -![Content type identifier](dashboard_content_type_identifier.png) - -## Container content type identifier - -Determines the content type identifier of the container for dashboards and lets you create additional structure for the predefined dashboards. -By default all the dashboards containers are set as a folders. - -![Container content type](dashboard_container_type.png) - -If the `folder` content type doesn't exist or is modified, you can use another one, for example: - -```yaml -ibexa: - system: - default: - dashboard: - container_content_type_identifier: user_dashboard_container -``` - -The custom content type should be a container and needs to have a field type with `name` identifier. diff --git a/docs/administration/recent_activity/recent_activity.md b/docs/administration/recent_activity/recent_activity.md index 3d4d1ce07a1..a512554cd92 100644 --- a/docs/administration/recent_activity/recent_activity.md +++ b/docs/administration/recent_activity/recent_activity.md @@ -1,78 +1,22 @@ --- description: Log and monitor activity through UI, PHP API and REST API. -edition: experience month_change: false --- # Recent activity -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). ![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 User Documentation]([[= user_doc =]]/recent_activity/recent_activity/). -## Configuration - -With some configuration, you can customize the log length in the database or on screen, or disable the logging completely. -A command maintains the log size in database, it should be scheduled through CRON. - -### Log retention - -The `ibexa.repositories..activity_log.truncate_after_days` setting 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). - -For example, the following configuration sets 15 days of life to the log entries on the `default` repository: - -```yaml -ibexa: - repositories: - default: - activity_log: - truncate_after_days: 15 -``` - -To automate a regular truncation, you must schedule the command `ibexa:activity-log:truncate`. -To minimize the number of entries to delete, it's recommended that you execute the command more than one time a day. - -### Display limit - -The `ibexa.system..activity_log.pagination.activity_logs_limit` setting sets the number of log items shown per page in the back office (default value: 25). - -For example, the following configuration sets 20 context groups per page for the `admin_group` SiteAccess group: - -```yaml -ibexa: - system: - admin_group: - activity_log: - pagination: - activity_logs_limit: 20 -``` - -A log item is a group of entries, or an entry without group. - -### Disable activity log - -The `ibexa.repositories..activity_log.enabled` setting can disable activity log entirely for a given [repository](repository_configuration.md). - -For example, to disable the activity log for the `default` repository: - -```yaml -ibexa: - repositories: - default: - activity_log: - enabled: false -``` - -You can also disable activity log for a single action by using the [PHP API](#disable-logging-activities). - ## Permission and security 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#activity-log-owner-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 dashboard. This policy is required to view [activity log in user profile]([[= user_doc =]]/getting_started/get_started/#view-and-edit-user-profile), if the user profile is enabled. !!! caution @@ -90,218 +34,6 @@ This policy is required to view [activity log in user profile]([[= user_doc =]]/ 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 - -The `ActivityLogService` PHP API can be used to browse activity logs and write new entries. - -### Searching in the Activity Log groups - -You can search among the activity log entry groups with the `ActivityLogService::findGroups` method, by passing an `Ibexa\Contracts\ActivityLog\Values\ActivityLog\Query` object. -This `Query`'s constructor has four arguments: - -- `$criteria` - an array of criteria from `Ibexa\Contracts\ActivityLog\Values\ActivityLog\Criterion` combined as a logical AND. -- `$sortClauses` - an array of `Ibexa\Contracts\ActivityLog\Values\ActivityLog\SortClause`. -- `$offset` - a zero-based index integer indicating at which group to start, its default value is `0` (zero, nothing skipped). -- `$limit` - an integer as the maximum returned group count, default is 25. - -See [Activity Log Search Criteria reference](activity_log_criteria.md) and [Activity Log Search Sort Clauses reference](activity_log_sort_clauses.md) to discover query possibilities. - -In the following example, log groups that contain at least one creation of a Content item are displayed in terminal, with a maximum of 10 groups within the last hour. -It uses the default `admin` user that has a [permission](#permission-and-security) to list everyone's entries. - -``` php hl_lines="34-38" -[[= include_code('code_samples/recent_activity/src/Command/MonitorRecentContentCreationCommand.php') =]] -``` - -```console -% php bin/console app:monitor-content-creation - -web ---- - - --------------------------- --------- --------------------------- -------- ---------- ------------ - Logged at Obj. ID Object Name Action User IP - --------------------------- --------- --------------------------- -------- ---------- ------------ - 2024-01-29T15:01:57+00:00 323 “Bar” (formerly “Folder”) create jane_doe 172.20.0.5 - --------------------------- --------- --------------------------- -------- ---------- ------------ - -migration ---------- - - Migrating file: create_foo_company - --------------------------- --------- -------------------- -------------- ------- ---- - Logged at Obj. ID Object Name Action User IP - --------------------------- --------- -------------------- -------------- ------- ---- - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ create admin - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ publish admin - 2024-01-29T14:58:53+00:00 318 “Members“ create admin - 2024-01-29T14:58:53+00:00 318 “Members“ publish admin - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ create_draft admin - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ update admin - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ publish admin - 2024-01-29T14:58:53+00:00 319 “Address Book“ create admin - 2024-01-29T14:58:53+00:00 319 “Address Book“ publish admin - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ create_draft admin - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ update admin - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ publish admin - 2024-01-29T14:58:53+00:00 320 “HQ“ create admin - 2024-01-29T14:58:53+00:00 320 “HQ“ publish admin - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ create_draft admin - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ update admin - 2024-01-29T14:58:53+00:00 317 “Foo Company Ltd.“ publish admin - --------------------------- --------- -------------------- -------------- ------- ---- -``` - -### Add custom Activity Log entries - -!!! caution - - Keep activity logging as light as possible. - Don't make database requests or heavy computation at logging time. - Keep them for activity log list display time. - If needed, you can [disable logging for specific operations](#disable-logging-activities) using the PHP API. - -#### Create an entry - -Your custom features can write into the activity log. - -First, inject `Ibexa\Contracts\ActivityLog\ActivityLogServiceInterface` into your PHP class from where you want to log an activity (such as a custom event subscriber, event listener, service, or controller). - -In the following example, an event subscriber is subscribing to an event dispatched by a custom feature. -This event has the information needed by a log entry (see details after the example). - -``` php -[[= include_code('code_samples/recent_activity/src/EventSubscriber/MyFeatureEventSubscriber.php') =]] -``` - -`ActivityLogService::build()` function returns an `Ibexa\Contracts\ActivityLog\Values\CreateActivityLogStruct` which can then be passed to `ActivityLogService::save`. - -`ActivityLogService::build` has three arguments: - -- `$className` is a FQCN of the object actually manipulated by the feature, for example `Ibexa\Contracts\Core\Repository\Values\Content\Content::class` -- `$id` is an ID or identifier of the manipulated object, for example, the Content ID cast to string -- `$action` is an identifier of the performed object manipulation, or example, `create`, `update` or `delete` - -The returned `CreateActivityLogStruct` is always related to the currently logged-in user. - -You can still display activity log of an object which was deleted or renamed. -To store the name of the log, you need to use `CreateActivityLogStruct::setName` before saving the log entry. -This stored name can be used at the time of displaying information whether the associated object isn't available anymore, or to check if it has been renamed. - -#### 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. -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 -- `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` -- `$description` - an optional, more specific contextualisation. -For example, `migration` context source is associated with the migration file name in its context description. - -To close a context group, use `ActivityLogService::dismissContext`. - -In the following example, several actions are logged into one context group, even those triggered by a cascade outside the piece of code: - -- `my_feature` - - `init` - - `create` - - `publish` - - `simulate` - - `complete` - -``` php -[[= include_code('code_samples/recent_activity/src/Command/ActivityLogContextTestCommand.php', 47, 66, remove_indent=True) =]] -``` - -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. -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. - -![The example context group displayed on the Recent Activity page](activity_log_group.png "`my_feature` context from the example") - -#### Display log entries - -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, -- create a template to display this class log entries. - -You can have a template that is: - -- specific to a class identifier and placed in `templates/themes//activity_log/ui/.html.twig` -- specific to an action on an identifier and placed in `templates/themes//activity_log/ui//.html.twig` - -Template existence is tested in reverse order: if there is no action that specifies the template, the identifier's default is used. -For the same identifier, you could have specific templates for few actions, and a default one for the remaining actions. - -A default template is used if no template is found for the identifier. -The built-in default template `@ibexadesign/activity_log/ui/default.html.twig` has an empty `activity_log_description_widget` block and doesn't display anything for unknown objects. -Your template can extend `@ibexadesign/activity_log/ui/default.html.twig`, and only redefine the `activity_log_description_widget` block for your objects. - -First, follow an example of a default template overriding the one from the bundle. -It can be used during development as a fallback for classes that aren't mapped yet. - -``` twig -[[= include_code('code_samples/recent_activity/templates/themes/admin/activity_log/ui/default.html.twig') =]] -``` - -Here is an example of a `ClassNameMapperInterface` associating the class `App\MyFeature\MyFeature` with the identifier `my_feature`: - -``` php -[[= include_code('code_samples/recent_activity/src/ActivityLog/ClassNameMapper/MyFeatureNameMapper.php') =]] -``` - -This mapper also provides a translation for the class name in the **Filters** menu. -This translation can be extracted with `php bin/console jms:translation:extract en --domain=ibexa_activity_log --dir=src --output-dir=translations`. - -To be taken into account, this mapper must be registered as a service: - -``` yaml -[[= include_code('code_samples/recent_activity/config/append_to_services.yaml') =]] -``` - -Here is an example of a `PostActivityListLoadEvent` subscriber which loads the related object when it's an `App\MyFeature\MyFeature`, and attaches it to the log entry: - -``` php -[[= include_code('code_samples/recent_activity/src/EventSubscriber/MyFeaturePostActivityListLoadEventSubscriber.php') =]] -``` - -The following template is made to display the object of `App\MyFeature\MyFeature` (now identified as `my_feature`) when the action is `simulate`, -so, it's named in `templates/themes/admin/activity_log/ui/my_feature/simulate.html.twig`. -Thanks to the previous subscriber, the related object is available at display time: - -``` twig -[[= include_code('code_samples/recent_activity/templates/themes/admin/activity_log/ui/my_feature/simulate.html.twig') =]] -``` - -### Disable logging activities - -You can disable logging the activities with PHP API, for example, when loading large amounts of data in cases where you don't want logging to slow down the process or the actions to be included in the log. - -Call [`ActivityLogService::disable()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ActivityLog-ActivityLogServiceInterface.html#method_disable) - before running the relevant code, then [`ActivityLogService::enable()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ActivityLog-ActivityLogServiceInterface.html#method_enable) to restore the logging process: - -``` php -[[= include_code('code_samples/recent_activity/src/recent_activity_disable.php') =]] -``` - -When disabled, any call to [`ActivityLogService::save()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ActivityLog-ActivityLogServiceInterface.html#method_save) has no effect and no entries are written to the database. - -You can check the current state with [`ActivityLogService::isEnabled()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ActivityLog-ActivityLogServiceInterface.html#method_isEnabled) and [`ActivityLogService::isDisabled()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ActivityLog-ActivityLogServiceInterface.html#method_isDisabled). - ## REST API You can browse activity logs with REST API. diff --git a/docs/ai/ai.md b/docs/ai/ai.md index 775b6e4b6ef..f983eeb517a 100644 --- a/docs/ai/ai.md +++ b/docs/ai/ai.md @@ -8,13 +8,6 @@ month_change: false [[= product_name =]] includes built-in AI capabilities. For example, it can provide recommendations to product customers and content readers with the [Raptor connector](raptor_connector_guide.md), and assist editors in the back office with [AI Actions](ai_actions_guide.md). -The platform is also open to external AI integrations through [MCP (Model Context Protocol) servers](mcp_guide.md), which allow AI agents to interact with the system in a standardized way. -AI solutions are extensible. You can create [custom AI actions](extend_ai_actions.md) or expose [new MCP server capabilities](mcp_usage.md). - -AI integration goes even further: - -- Some AI agents can learn how to use the [REST](rest_api_usage.md) or [GraphQL](graphql.md) APIs. -- Other, like those integrated into IDEs, can learn how to use the [PHP API](php_api.md) and assist you in code development. [[= cards([ "ai/ai_actions/ai_actions", diff --git a/docs/ai/ai_actions/ai_actions.md b/docs/ai/ai_actions/ai_actions.md index 045f3486aea..aca185daa6a 100644 --- a/docs/ai/ai_actions/ai_actions.md +++ b/docs/ai/ai_actions/ai_actions.md @@ -9,13 +9,10 @@ month_change: false AI Actions enhance the usability and flexibility of [[= product_name =]] by automating various tasks. After you configure it, it can generate alt text for images or transform text passages. -You can also extend it to perform other tasks or support additional AI services. - ## Getting Started [[= cards([ "ai/ai_actions/ai_actions_guide", -"ai/ai_actions/configure_ai_actions", ("content_management/taxonomy/taxonomy#taxonomy-suggestions", "Taxonomy suggestions", "Learn how to use AI to suggest tags and categories"), ("permissions/policies#ai-actions", "Policies", "Learn about the available AI Actions policies"), ("https://doc.ibexa.co/projects/userguide/en/6.0/ai_actions/work_with_ai_actions/", "Work with AI Actions", "Create new AI actions or modify existing ones to work faster and increase creativity."), @@ -24,10 +21,7 @@ You can also extend it to perform other tasks or support additional AI services. ## Development [[= cards([ -"ai/ai_actions/extend_ai_actions", -"api/event_reference/ai_action_events", ("https://doc.ibexa.co/en/6.0/api/rest_api/rest_api_reference/rest_api_reference.html#tag/Connector-AI", "REST API Reference", "See the available endpoints for AI Actions"), "search/ai_actions_search_reference/action_configuration_criteria", "search/ai_actions_search_reference/action_configuration_sort_clauses", -("content_management/data_migration/importing_data#ai-action-configurations", "Importing AI actions", "Learn how to manage Action Configurations using data migrations"), ], columns=4) =]] diff --git a/docs/ai/ai_actions/ai_actions_guide.md b/docs/ai/ai_actions/ai_actions_guide.md index 0bf5abc073d..0f784ce51e4 100644 --- a/docs/ai/ai_actions/ai_actions_guide.md +++ b/docs/ai/ai_actions/ai_actions_guide.md @@ -11,13 +11,7 @@ Wherever you look, artificial intelligence becomes more and more important by en [[= product_name =]] is equipped with the AI Actions feature, which harnesses AI's potential to automate time-consuming editorial tasks. AI Actions is an extensible solution for integrating features provided by AI services into your workflows, all managed through a user-friendly interface. -Out-of-the-box, AI Actions solution includes two essential components: a framework package and an OpenAI connector package. -The Anthropic and Gemini connectors are also available - as [LTS updates](editions.md#lts-updates). - -AI Actions can integrate with [[[= product_name_connect =]]]([[= connect_doc =]]/general/ibexa_connect/), to give you an opportunity to build complex data transformation workflows without having to rely on custom code. -From the developer's perspective, the integration removes the burden of maintaining third-party AI handlers, and accelerates the deployment of AI-based solutions. - -AI Actions solution comes pre-configured with the following action types: +AI Actions solution comes with the following action types: - [Refine text](#refining-text): Rewrite existing text according to instructions set in a prompt - [Generate alternative text](#generating-alternative-text): Generate alt text for images for accessibility purposes @@ -25,31 +19,16 @@ AI Actions solution comes pre-configured with the following action types: ![AI Actions schematic](img/guide_ai_actions.png) -You can extend the solution's capabilities beyond the default setup by creating custom connector modules, allowing users to take advantage of additional AI services, or customize the way data is processed and interpreted. -For example, it could transform images, or generate illustrations for your articles based on their contents. -The possibilities are endless and you're not limited to a specific AI service, avoiding vendor lock-in. ## Availability -[[= product_name_cloud =]] is available in all [[= product_name =]] editions. -To begin using AI Actions, you must first [perform the initial configuration](configure_ai_actions.md). - -### Prerequisites - -Connectors with external AI services delivered by [[= product_name_base =]] require that you first install them, and [configure other settings, such as an API key and billing method](configure_ai_actions.md). - -Integration with [[= product_name_connect =]] requires that you first [get the credentials]([[= connect_doc =]]/general/ibexa_connect/#access-ibexa-connect) to your account, and the [API token](configure_ai_actions.md#create-token). - -!!! note "[[= product_name_connect =]] Availability" - - [[= product_name_connect =]] comes with all contracts signed from 2023. - If you signed your contract earlier, contact your customer success manager to use [[= product_name_connect =]]. +You can use AI Actions, unless your organization requested to disable all AI-powered features in your system. ## How it works -AI Actions rely on an extensible AI framework, which is responsible for gathering information from various sources, such as AI action types, AI action configurations, and contextual details like SiteAccess, user details, locale settings, and more. +AI Actions rely on an AI framework, which is responsible for gathering information from various sources, such as AI action types, AI action configurations, and contextual details like SiteAccess, user details, locale settings, and more. This data can then be combined with user input. -It's then passed to a service connector, such as the default OpenAI connector or the [[= product_name_connect =]] connector, for final processing on [[= product_name =]] side. +It's then passed to a service connector for final processing on [[= product_name =]] side. The service connector wraps all data into a prompt or another suitable format and sends it to an external service. When the external service returns a response, the response goes back through the service connector and passes to the framework. @@ -130,17 +109,8 @@ An intuitive AI Actions interface within the **Admin** panel displays a list of Here, you can search for specific actions and filter them by type or status. By accessing the detailed view of individual AI actions, you can quickly review all their parameters. -### Extensibility - -Built-in AI action types offer a good starting point, but the real power of AI Actions lies in extensibility. -Extending AI Actions opens up new possibilities for content management and editing. -Developers can define new models and AI action types that use the existing AI service or even integrate additional services. -The latter involves developing a new service connector, writing a handler that communicates with the new service, defining a new AI action type, and creating a form for configuring options, which extends the default action configuration form shown in the **Admin** panel. -For example, if this is your organization's requirement, a developer could write a handler that uses an AI service available internally, without exposing your data to a third-party service. - ## Use cases -Out of the box, after you configure access to the OpenAI service, AI Actions come with two action types that can help your organization with the following tasks. ### Refining text @@ -165,15 +135,3 @@ With some customization, administrators could use the API to run a batch process Content editors and product managers can use [taxonomy suggestions](taxonomy.md#taxonomy-suggestions) when assigning tags or product categories to content items and products. Instead of manually browsing through extensive taxonomy trees, editors can request suggestions based on the content's text fields, such as name and description. - -!!! note "Alternative suggestion provider" - - By default, embeddings used by the taxonomy suggestions feature are generated with OpenAI. - If you install and configure the [Google Gemini connector](configure_ai_actions.md#install-google-gemini-connector), you can modify the [taxonomy suggestions settings](taxonomy.md#change-embeddings-provider-to-google-gemini) and use Google Gemini as an alternative embeddings provider. - -### Performing advanced image to text analysis - -With some additional customization, store managers could benefit from automating part of product management by integrating their [[= product_name =]] with Google Cloud Vision and the [product catalog](product_catalog_guide.md) by using [[= product_name_connect =]]. -Instead of manually selecting and linking images stored in a [DAM](add_image_asset_from_dam.md) solution to their products, they could use of a no-code workflow where an AI service, for example, Google Cloud Vision, extracts text and attributes from product images, which are then matched with existing items in a product catalog. - -This would enable automatic product identification, tagging, and catalog updates, resulting in less manual work and more efficient product management. diff --git a/docs/ai/ai_actions/configure_ai_actions.md b/docs/ai/ai_actions/configure_ai_actions.md deleted file mode 100644 index 302b788cd67..00000000000 --- a/docs/ai/ai_actions/configure_ai_actions.md +++ /dev/null @@ -1,292 +0,0 @@ ---- -description: Configure AI Actions. -month_change: false ---- - -# Configure AI Actions - -AI Actions are available in [[= product_name =]] regardless of its edition. -To use this feature you must first configure the built-in service connectors or build your own ones. - -Once the framework is configured, before you can start using AI Actions, you can configure access to [[= product_name_base =]]-made service connectors by following the instructions below, or [create your own](extend_ai_actions.md#create-custom-action-handler). - -Only then you can restart you application and start [working with the AI Actions feature]([[= user_doc =]]/ai_actions/work_with_ai_actions/). - -!!! note "Taxonomy suggestions" - - The default OpenAI or the optional Google Gemini connectors can used by the [Taxonomy suggestions](taxonomy.md#taxonomy-suggestions) feature to generate embeddings for suggesting tags and product categories. - After you configure the OpenAI connector, or set up the optional Google Gemini connector and [modify the default taxonomy suggestions settings](taxonomy.md#change-embeddings-provider-to-google-gemini), you can [create AI actions that use the Text to Taxonomy action type]([[= user_doc =]]/ai_actions/work_with_ai_actions/#create-ai-actions-that-control-taxonomy-suggestions). - You can also create [your own embedding provider](taxonomy.md#replace-the-embedding-provider). - -## Configure access to OpenAI - -To use the built-in connector with the OpenAI service, you need to create an OpenAI account, [get an API key](https://help.openai.com/en/articles/4936850-where-do-i-find-my-openai-api-key), and make sure that you [set up a billing method](https://help.openai.com/en/articles/9038407-how-can-i-set-up-billing-for-my-account). - -Then, in the root folder of your project, modify the `.env` file: find the `OPENAI_API_KEY` variable and replace a placeholder value with the API key that you got from the AI service. - -```bash -###> ibexa/connector-openai ### -OPENAI_API_KEY= -###< ibexa/connector-openai ### -``` - -### Sample OpenAI action configurations - -The AI actions come with sample AI action configurations to quickly get you started on using the feature. - -Based on these examples, which reflect the most common use cases, you can learn to configure your own AI actions with greater ease. - -## Install Anthropic connector [[% include 'snippets/lts-update_badge.md' %]] - -Run the following command to install the package: - -``` bash -composer require ibexa/connector-anthropic -``` - -If not using Symfony Flex, enable the bundle in `config/bundles.php`: - -``` php {skip-validation} - Ibexa\Bundle\ConnectorAnthropic\IbexaConnectorAnthropicBundle::class => ['all' => true], -``` - -This adds the feature code, including basic handlers that let you refine text or generate alternative text for images. - -To use the connector with the Anthropic services, you need to create an account, make sure that you [set up a billing method](https://support.claude.com/en/articles/8325618-paid-plan-billing-faqs), and get an API key. - -1. Log in to your [Anthropic Claude console](https://platform.claude.com/login). - -2. Go to **API keys** and click **Create Key**. - -3. Select the workspace, enter a **Key Name** and click **Add**. - -4. Take a note of the API key, because it is displayed only once. - -Then, in the root folder of your project, modify the `.env` file: add an `ANTHROPIC_API_KEY` variable and populate its value with the API key that you got from the AI service. - -```bash -###> ibexa/connector-anthropic ### -ANTHROPIC_API_KEY= -###< ibexa/connector-anthropic ### -``` - -By default, when reaching out for responses, the Anthropic connector uses the [Claude Sonnet 4](https://platform.claude.com/docs/en/about-claude/models/overview) model. -Users can override this setting at runtime when they [edit or create an AI action]([[= user_doc =]]/ai_actions/work_with_ai_actions/#edit-existing-ai-actions). -You can also change the default values globally. -To do it, in `config/packages` folder, create a YAML file similar to this example: - -```yaml -ibexa_connector_anthropic: - text_to_text: - default_model: claude-sonnet-4-6 - default_temperature: 0.8 - default_max_tokens: 2045 - models: - claude-haiku-4-5-20251001: 'Claude Haiku 4.5 (fast, cost-efficient)' - claude-sonnet-4-6: 'Claude Sonnet 4.6 (recommended)' - claude-opus-4-6: 'Claude Opus 4.6 (advanced reasoning)' - claude-opus-4-7: 'Claude Opus 4.7 (most capable)' -``` - -You can now use the Anthropic connector in your project. - -!!! note "Current model availability" - - Anthropic regularly releases new models and deprecates older ones. - Before you configure the connector, check the [Anthropic models overview](https://platform.claude.com/docs/en/about-claude/models/overview) for the current list of supported model identifiers. - -## Install Google Gemini connector [[% include 'snippets/lts-update_badge.md' %]] - -Run the following command to install the package: - -``` bash -composer require ibexa/connector-gemini -``` - -Then, if not using Symfony Flex, enable the bundle in `config/bundles.php`: - -``` php -return [ - // ... - Ibexa\Bundle\ConnectorGemini\IbexaConnectorGeminiBundle::class => ['all' => true], -]; -``` - -This adds the feature code, including basic handlers that let you refine text or generate alternative text for images. - -### Get API key - -To use the connector with the Gemini services, you need to create an account, set up billing, enable Gemini API and get an API key. - -#### Create the Google Cloud project - -1. Sign in to the [Google Cloud Console](https://console.cloud.google.com/). -1. In the top bar, click **Default Gemini Project** to open a project picker. -1. Click **New project** and provide project details: - 1. Add project name, for example, "My project". - 1. Modify the automatically generated **Project ID** if necessary. - 1. Select location: choose your organization. -1. Click **Create**. - -#### Configure billing - -1. Navigate to the Google Cloud Console's **Billing** page. -1. If you do not have one, click **Add billing account** and add a payment method. -1. In **Your projects** tab, locate your project, and in its line, from the **Actions** menu, select **Change billing**. -1. Select your active billing account, and click **Set account**. - -#### Enable the Gemini API - -1. Navigate to the Google Cloud Console's **APIs & Services** page. -1. From the left-hand menu, select **Library** and search for the Generative Language API. -1. In the API's details page, click **Enable**. - -#### Generate the API key - -1. Go to [Google AI Studio](https://aistudio.google.com/app/api-keys)'s **API keys** page, and click **Create API key**. -1. Provide a name for the API key, select "My project" from a list of projects and click **Create key**. -1. Back in the **API keys** list, in your project's line, copy the API key. - -### Set API key in configuration - -Then, in the root folder of your project, modify the `.env` file: add an `GEMINI_API_KEY` variable and populate its value with the API key that you got from the AI service. - -```bash -###> ibexa/connector-gemini ### -GEMINI_API_KEY= -###< ibexa/connector-gemini ### -``` - -!!! note "Different API keys for different SiteAccesses" - - If there are multiple SiteAccesses in your installation, you can set different API keys for each SiteAccess. - To do it, set the keys under the `ibexa.system.` [configuration key](configuration.md#configuration-files), like so: - - ```yaml - ibexa: - system: - default: - connector_gemini: - gemini: - api_key: '%env(GEMINI_API_KEY)%' - base_url: 'https://generativelanguage.googleapis.com/v1beta/' # Google Gemini's API endpoint - ``` - -### Configure default models - -By default, when reaching out for responses, the Gemini connector uses the Gemini Pro [model](https://ai.google.dev/gemini-api/docs/models) for text refinement and Gemini Flash model for alternative text generation. -Users can override this setting at runtime when they [edit or create an AI action]([[= user_doc =]]/ai_actions/work_with_ai_actions/#edit-existing-ai-actions). -You can also change the default values globally. -To do it, in `config/packages` folder, create a YAML file similar to this example: - -```yaml -[[= include_file('code_samples/ai_actions/config/packages/ibexa_connector_gemini.yaml') =]] -``` - -When setting up models, make sure that you follow these rules: - -- `default_model` must reference a configured model -- `default_max_tokens` must not exceed the model’s limit -- If you use the same model for different action types, settings must be consistent - -!!! note "Google Gemini and taxonomy suggestions" - - To use Google Gemini for generating taxonomy suggestions, ensure that you [change the embeddings provider and model setting accordingly](taxonomy.md#change-embeddings-provider-to-google-gemini). - -You can now use the Gemini connector in your project. - -For more information, see [Extend Gemini connector](extend_ai_actions.md#extend-google-gemini-connector). - -## Configure access to [[= product_name_connect =]] - -First, get the credentials by contacting [Ibexa Support](https://support.ibexa.co). - -### Create team - -In [[= product_name_connect =]], set up the account, and [create a team]([[= connect_doc =]]/access_management/teams/#creating-teams). -Navigate to the team details page and note down the numerical value of the **Team id** variable. - -Creating a team matters, because [scenarios]([[= connect_doc =]]/scenarios/creating_a_scenario/) that process data coming from your AI action are associated with a team. -This way, if your organization has more than one [[= product_name =]] project, each project can be linked to a different team and so can be scenarios used in those projects. - -If specific users from the team are supposed to modify scenario settings, you must [assign the right roles]([[= connect_doc =]]/access_management/teams/#managing-teams) to them. - -### Create token - -Navigate to your [[= product_name_connect =]] user's profile, and on the **API ACCESS** tab, create a new token. -Select the following scopes to set permissions needed to enable the integration of platforms: - -- `custom-property-structures:read` -- `custom-property-structures:write` -- `hooks:read` -- `hooks:write` -- `scenarios:read` -- `scenarios:write` -- `team-variables:read` -- `team-variables:write` -- `teams:write` -- `templates:read` -- `templates:write` -- `udts:read` -- `udts:write` - -![Creating an API token](img/connect_api_token.png) - -Copy the token code that appears on the tokens list, next to the label. - -### Set up credentials - -In the root folder of your project, modify the `.env` file. -Replace a placeholder value of the `IBEXA_CONNECT_TOKEN` variable with the token that you got from [[= product_name_connect =]] and provide a value of the `IBEXA_CONNECT_TEAM_ID` variable. - -```bash -###> ibexa/connect ### -IBEXA_CONNECT_HOST=https://connect.ibexa.co -IBEXA_CONNECT_API_PATH=/api/v2/ -# Token can be created in the user's profile in Ibexa Connect, under the 'API ACCESS' section. -IBEXA_CONNECT_TOKEN= -# Use the URL below to read more on Ibexa Connect teams. -# https://doc.ibexa.co/projects/connect/en/latest/access_management/teams/ -IBEXA_CONNECT_TEAM_ID=2 -###< ibexa/connect ### -``` - -### Initiate integration - -Initiate the models provided by the handler by issuing the following command: - -```bash -php bin/console ibexa:connect:init-connect-ai -``` - -For example: - -```bash -php bin/console ibexa:connect:init-connect-ai 2 en connect-image-to-text connect-text-to-text -``` - -!!! note "Support for multiple [[= product_name_connect =]] languages" - - The [`language` attribute](https://developers.make.com/api-documentation/api-reference/templates#post-templates) determines the language in which template details such as module names will be displayed in [[= product_name_connect =]]'s UI. - -Then, create the `Ibexa AI handler` custom property in [[= product_name_connect =]] to store the list of available action handlers for this integration. -You can do it by running the following command: - -``` bash -php bin/console ibexa:connect:init-custom-property-structures -``` - -For example: - -``` bash -php bin/console ibexa:connect:init-custom-property-structures 4 connect-image-to-text connect-text-to-text -``` - -The `Ibexa AI handler` property attaches to a scenario to store information about the action handler associated with it. -When creating a new [[= product_name_connect =]]-based AI action, the back office of [[= product_name =]] shows only the existing scenarios that work with selected action handler. - -### Customize templates - -Return to the [[= product_name_connect =]] dashboard and modify the **Template for connect...handler** [templates]([[= connect_doc =]]/scenarios/scenario_templates/) by defining the logic needed to process the data. - -Once the templates are ready, you can build scenarios from them, either directly in [[= product_name_connect =]] or in [[[= product_name =]]'s user interface]([[= user_doc =]]/ai_actions/work_with_ai_actions/#create-new-ai-actions). diff --git a/docs/ai/mcp/mcp.md b/docs/ai/mcp/mcp.md index d6f7df2b662..567e6bc2aa6 100644 --- a/docs/ai/mcp/mcp.md +++ b/docs/ai/mcp/mcp.md @@ -1,17 +1,14 @@ --- description: Overview of MCP resources in Cohesivo page_type: landing_page -edition: lts-update month_change: false --- # MCP Servers The Model Context Protocol (MCP) and MCP Servers allow AI agents to interact with the system in a structured way. -The feature is available as an [LTS Update](editions.md#lts-updates) since v5.0.8. [[= cards([ "ai/mcp/mcp_guide", - "ai/mcp/mcp_config", "ai/mcp/mcp_usage", ], columns=3) =]] diff --git a/docs/ai/mcp/mcp_config.md b/docs/ai/mcp/mcp_config.md deleted file mode 100644 index f7a439b30b3..00000000000 --- a/docs/ai/mcp/mcp_config.md +++ /dev/null @@ -1,238 +0,0 @@ ---- -description: Configure an MCP server that exposes built-in and custom tools, prompts, and resources. -edition: lts-update -month_change: true ---- - -# Install and configure MCP Servers - -With [[= product_name =]]'s MCP Servers LTS Update package, you can expose [MCP servers](mcp_guide.md) to external AI agents. - -## Installation - -Run the following command to install the package: - -```bash -composer require ibexa/mcp -``` - -MCP Servers feature comes with [built-in tools](#built-in-tools) but doesn't come with a default configuration. -You have to create your own MCP servers by providing [their configuration](#mcp-server-configuration) and [enable JWT authentication for them](#jwt-mcp-firewall). - -## Configure authentication - -### JWT MCP firewall - -AI agents use JWT authentication against [[= product_name =]]'s MCP servers. - -In `config/packages/lexik_jwt_authentication.yaml`, [enable the `authorization_header` token extractor](development_security.md#jwt-authentication) to allow the use of JWT token bearer in `Authorization` header. - -In `config/packages/security.yaml`, make the following changes: - -- Uncomment the `ibexa_jwt_rest` firewall to enable requesting JWT tokens through REST or GraphQL API. -- Add the `ibexa_jwt_mcp` firewall to allow the use of JWT authentication against MCP servers. - -``` yaml hl_lines="4-9" -[[= include_code('code_samples/mcp/config/packages/mcp.security.yaml') =]] -``` - -!!! note "Authentication for the APIs" - - You don't need to activate JWT authentication for the REST or GraphQL API. - - For sample JWT token requests, see [REST JWT authentication](rest_api_authentication.md#jwt-authentication), [GraphQL JWT authentication](graphql.md#jwt-authentication) and [cURL test of MCP server](mcp_usage.md#perform-curl-test). - -### Repository user - -The AI agents authenticate against the MCP server with a JWT token generated for a specific repository user account. - -This repository user can be: - -- an individual user account (for example, of an editor or administrator) -- a dedicated account created specifically for AI integrations - -The repository user can generate a JWT token with their own account, or a secondary dedicated account, and pass the token to the MCP client. -A gateway could use a dedicated shared repository user to generate a JWT token and establish the connection. - -## MCP server configuration - -You define MCP servers within a repository configuration and then assign those servers to specific SiteAccess scopes. - -``` yaml -[[= include_code('code_samples/mcp/mcp.matrix.yaml', 1, 8) =]] -[[= include_code('code_samples/mcp/mcp.matrix.yaml', 12, 17) =]] -[[= include_code('code_samples/mcp/mcp.matrix.yaml', 31, 35) =]] -``` - -Servers are automatically registered as services with an ID following the pattern `ibexa.mcp.server..`. -You can list all defined servers by running the following command: - -```bash -php bin/console debug:container ibexa.mcp.server -``` - -Routes are built automatically from MCP server `path` configs. -Those routes are identified as `ibexa.mcp.`. -You can list them by running the following command: - -```bash -php bin/console debug:router --siteaccess= ibexa.mcp` -``` - -### MCP server options - -| Option | Type | Required | Default | Description | -|-----------------------------------------------------------------------------------------------------------------|---------|----------|--------------------------------------------------------------------------|------------------------------------------------------------------| -| `path` | string | Yes | | MCP server endpoint path (appended to SiteAccess-aware base URL) | -| `enabled` | boolean | No | `false` | Server state: decides whether it is enabled or disabled | -| `version` | string | No | `1.0.0` | MCP server version | -| [`description`](https://modelcontextprotocol.io/specification/2025-11-25/schema#implementation-description) | string | No | `null` | Server implementation description | -| [`instructions`](https://modelcontextprotocol.io/specification/2025-11-25/schema#initializeresult-instructions) | string | No | `null` | Prompt-like instructions provided to the AI agent | -| [`tools`](#tool-configuration) | array | No | `[]` | List of tool classes | -| [`discovery_cache`](#discovery-cache) | string | Yes | | PSR-6 or PSR-16 cache pool service identifier | -| [`session`](#session-storage) | object | No | `{ type: psr16,`
`service: ibexa.cache_pool }` | Session storage configuration | -| [`allowed_hosts`](#allowed-hosts) | array | No | `[`
`'localhost',`
`'127.0.0.1',`
`'[::1]'`
`]` | Accepted `Host` headers | - -!!! note "New servers are disabled by default" - - After you define a server, it remains disabled until you explicitly enable it. - -### Tool configuration - -The main capabilities of an MCP server are called [tools](https://modelcontextprotocol.io/specification/2025-11-25/server/tools). -They are the actions that an AI agent can invoke on the system. - -!!! note "MCP server design best practices" - - Avoid creating MCP servers with large tool sets. - Too many tools make it more difficult for the AI agent to select the appropriate action. - Instead, create multiple MCP servers with specific sets of tools dedicated to specific contexts or use cases. - When designing MCP servers, focus on the needs and tasks of the human user who actually interacts with the AI agent rather than exploring every technical capability. - -There are two ways to associate tools with a server: - -- By listing PHP classes (FQCNs) in the server's configuration `tools`. All tools marked with the `McpTool` attribute in those classes are automatically associated with the server (for example, for [built-in](#built-in-tools) or third party tools). -- By using the `servers` argument in [`McpTool` attribute](mcp_usage.md#tools) to explicitly associate a specific tool with MCP servers. - -#### Built-in tools - -MCP Servers LTS Update comes with the following **experimental** built-in tools: - -- `Ibexa\Mcp\Tool\ContentType\ContentTypeTools` - - `get_content_type` - gets a content type by its ID. - - `get_content_type_by_identifier` - gets a content type by its identifier. - - `get_content_type_list` - gets content types by their IDs. - - `create_content_type` - creates a draft for a new content type. - - `create_content_type_draft` - creates a draft for an existing content type. - - `get_content_type_draft` - gets a content type draft by content type ID. - - `publish_content_type_draft` - publishes a content type draft by content type ID. -- `Ibexa\Mcp\Tool\ContentType\FieldDefinitionTools` - - `add_field_definition` - adds a field definition to a content type draft. - - `update_field_definition` - updates a field definition in a content type draft. - - `remove_field_definition` - removes a field definition from a content type draft. -- `Ibexa\Mcp\Tool\ContentType\ContentTypeGroupTools` - - `get_content_type_groups` - gets all content type groups. -- `Ibexa\Mcp\Tool\TranslationTools` - - `list_languages` - lists all languages in the current SiteAccess. - - `list_content_languages` - lists languages which have translations for a given content item. - - `list_non_translated_content_ids` - lists IDs of content which have missing translations for a given language code. -- `Ibexa\Mcp\Tool\SeoTools` - - `get_non_seo_content_ids` - returns IDs of content items that are missing SEO optimization (no meta title tag). Useful for identifying content that needs SEO attention. - -``` yaml hl_lines="5-7" -[[= include_code('code_samples/mcp/mcp.matrix.yaml', 4, 7) =]] -[[= include_code('code_samples/mcp/mcp.matrix.yaml', 9, 11) =]] - # … -``` - -!!! caution "Experimental tools" - - The built-in tools are experimental and may change in future releases. - They are provided as examples of how to implement tools and how to configure them in an MCP server. - As-is, they may not cover all your needs or may not be practical to all AI agents. - If you use them, be prepared to update your MCP server configuration and tool usage when upgrading to a new version of [[= product_name =]]. - - See how to build your own tools in [Work with MCP servers](mcp_usage.md). - -### Discovery cache - -Discovery is cached to avoid scanning for capabilities on every request. -You must provide a PSR-6 or PSR-16 cache pool for this caching. - -For example, you could set up a dedicated Redis/Valkey: - -``` yaml -[[= include_code('code_samples/mcp/mcp.matrix.yaml', 19, 19) =]] -``` - -For a production cluster, it's recommended to use a Redis/Valkey cache pool so the cache can be shared by all nodes. - -Clear the cache pool after making changes: - -```bash -php bin/console cache:pool:clear cache.redis.mcp -``` - -!!! tip - - Use `ibexa.cache_pool` as service identifier to have the default [cache service](persistence_cache.md#cache-service). - -It can be set to `null` to disable caching to ease development, which isn't recommended for production environment. - -See another example of configuration in [Work with MCP servers](mcp_usage.md#configure-mcp-server). - -### Session storage - -MCP servers store session data in their own way. - -#### Options - -| Option | Type | Default | Description | -|-------------|---------|--------------------|----------------------------------------------------------------| -| `type` | enum | `psr16` | Session store type: [`psr16`](#psr-16) or [`file`](#file) | -| `service` | string | `ibexa.cache_pool` | PSR-16 or PSR-6 cache service ID for the `psr16` session store | -| `prefix` | string | `mcp_` | Key prefix for the `psr16` session store | -| `directory` | string | `null` | Directory path for the `file` session store | -| `ttl` | integer | `3600` | Session TTL in seconds | - -In production, it’s recommended to use [`psr16`](#psr-16) with Redis/Valkey, like with [regular sessions](clustering.md#shared-sessions). - -#### PSR-16 - -Sessions are stored with a PSR-16 or PSR-6 compatible cache implementation. -It requires that a `service` option points to a valid cache service ID. -Optionally, you could use a more specific `prefix` option than the default `mcp_` to avoid key collisions with other cache usages. -Such setup is suitable for production environments. - -``` yaml -[[= include_code('code_samples/mcp/mcp.matrix.yaml', 20, 23) =]] -[[= include_code('code_samples/mcp/mcp.matrix.yaml', 36, 45) =]] -``` - -#### File - -Sessions are stored on the filesystem. -This requires that you configure a directory. -Such setup is suitable for development environments. - -In this example, sessions are stored in the `var/cache//mcp/sessions/` directory (for example, `var/cache/dev/mcp/session/` for the `dev` environment, and `var/cache/prod/mcp/sessions/` for the `prod` environment): - -``` yaml -[[= include_code('code_samples/mcp/mcp.matrix.yaml', 25, 27) =]] -``` - -### Allowed hosts - -This parameter lists the domains, the `Host` headers, accepted by the MCP server. -The port is not part of the matching. -There is no wildcard character, all cases must be listed. -As item, you can use a hostname, an IP, or an IPv6. -IPv6 addresses must be bracketed, for example `[::1]`. - -In this example, only requests from `www.example.com` domain, or from 127.0.0.1 IP are accepted: - -``` yaml -[[= include_code('code_samples/mcp/mcp.matrix.yaml', 16, 16) =]] - - 'www.example.com' - - '127.0.0.1' -``` diff --git a/docs/ai/mcp/mcp_guide.md b/docs/ai/mcp/mcp_guide.md index 12ad3ee266c..2490036d4e8 100644 --- a/docs/ai/mcp/mcp_guide.md +++ b/docs/ai/mcp/mcp_guide.md @@ -1,6 +1,5 @@ --- description: MCP servers expose tools, specialized prompts, and resources to AI agents. -edition: lts-update month_change: false --- @@ -15,8 +14,8 @@ While [AI actions](ai_actions_guide.md) integrate AI with the back office, Because MCP is a standard protocol, many agents are already trained to use it. -They can interact directly with REST or GraphQL APIs if their users provide detailed instructions through prompts, skill files, etc. -However, when facing a specific REST or GraphQL API, an agent may misunderstand the purpose of endpoints, hallucinate paths, or send incorrectly structured parameters. +They can interact directly with the REST API if their users provide detailed instructions through prompts, skill files, etc. +However, when facing a specific REST API, an agent may misunderstand the purpose of endpoints, hallucinate paths, or send incorrectly structured parameters. MCP servers make the discovery of available capabilities much easier. They help AI agents translate natural language prompts into concrete actions on the system. @@ -25,18 +24,31 @@ They help AI agents translate natural language prompts into concrete actions on An MCP server allows the agent to discover available tools, inspect their parameters, learn how to use them, and select the correct action. -## Availability - -MCP Servers feature is an [LTS Update package](editions.md#lts-updates) available starting with the v5.0.8 in all [[= product_name =]] editions. - ## Capabilities -With the MCP Servers feature, you can: - -- create MCP servers [by using YAML configuration](mcp_config.md#mcp-server-configuration) -- assign different tools, prompts, and resources to different MCP servers, varying them for each site and purpose -- use [built-in tools](mcp_config.md#built-in-tools) included in the package -- [create custom server capabilities](mcp_usage.md#create-capability-class) with PHP API - -MCP servers are defined specifically for each [repository](repository_configuration.md) and assigned to individual [SiteAccesses](siteaccess.md) scopes. -This way you can build flexible configurations that match different contexts. +With the MCP Servers feature, you can use the tools included in the package. + +### Built-in tools + +MCP Servers LTS Update comes with the following built-in tools: + +- `Ibexa\Mcp\Tool\ContentType\ContentTypeTools` + - `get_content_type` - gets a content type by its ID. + - `get_content_type_by_identifier` - gets a content type by its identifier. + - `get_content_type_list` - gets content types by their IDs. + - `create_content_type` - creates a draft for a new content type. + - `create_content_type_draft` - creates a draft for an existing content type. + - `get_content_type_draft` - gets a content type draft by content type ID. + - `publish_content_type_draft` - publishes a content type draft by content type ID. +- `Ibexa\Mcp\Tool\ContentType\FieldDefinitionTools` + - `add_field_definition` - adds a field definition to a content type draft. + - `update_field_definition` - updates a field definition in a content type draft. + - `remove_field_definition` - removes a field definition from a content type draft. +- `Ibexa\Mcp\Tool\ContentType\ContentTypeGroupTools` + - `get_content_type_groups` - gets all content type groups. +- `Ibexa\Mcp\Tool\TranslationTools` + - `list_languages` - lists all languages in the current SiteAccess. + - `list_content_languages` - lists languages which have translations for a given content item. + - `list_non_translated_content_ids` - lists IDs of content which have missing translations for a given language code. +- `Ibexa\Mcp\Tool\SeoTools` + - `get_non_seo_content_ids` - returns IDs of content items that are missing SEO optimization (no meta title tag). Useful for identifying content that needs SEO attention. diff --git a/docs/ai/mcp/mcp_usage.md b/docs/ai/mcp/mcp_usage.md index c226a89f6cc..d5cc1eb20b0 100644 --- a/docs/ai/mcp/mcp_usage.md +++ b/docs/ai/mcp/mcp_usage.md @@ -1,13 +1,21 @@ --- description: Create custom capabilities for your MCP servers and test them. -edition: lts-update month_change: true +saas_review: + - siteaccess + - links_removed +saas_review_note: >- + An MCP server is declared for a repository and assigned to SiteAccesses in + configuration. Confirm how the server-to-SiteAccess assignment is expressed once + SiteAccess configuration moves to a UI. + + Links to the deleted editions.md and graphql.md pages and the generated PHP API + reference were removed; check that the surrounding text still reads correctly. --- # Work with MCP servers -The MCP Servers [LTS Update](editions.md#lts-updates) includes several [built-in tools](mcp_config.md#built-in-tools). -Additionally, you can create your own capabilities (tools, prompts, and resources) to expose custom features to AI agents through your MCP servers. +The MCP Servers feature includes several built-in tools. ## MCP server capabilities @@ -15,265 +23,10 @@ The [[= product_name =]] MCP server framework (`ibexa/mcp`) is built on top of t A PHP class that implements MCP server capabilities such as tools, prompts, or resources must: -- implement [`Ibexa\Contracts\Mcp\McpCapabilityInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Mcp-McpCapabilityInterface.html) so that it can be scanned for capabilities -- use attributes from the [`Ibexa\Contracts\Mcp\Attribute` namespace](/api/php_api/php_api_reference/namespaces/ibexa-contracts-mcp-attribute.html) to declare capabilities +- implement `Ibexa\Contracts\Mcp\McpCapabilityInterface` so that it can be scanned for capabilities +- use attributes from the `Ibexa\Contracts\Mcp\Attribute` namespace to declare capabilities -### Tools -The [`Ibexa\Contracts\Mcp\Attribute\McpTool` attribute](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Mcp-Attribute-McpTool.html) declares a method as an MCP tool. -It accepts the following optional arguments: - -- `servers` - array of server identifiers the tool is assigned to -
For more information, see [tools configuration](mcp_config.md#tool-configuration). -- `name` - tool codename - if not set, the function name is used -- `title` - tool title for user interfaces - if not set, the `name` is used -- `description` - tool description, used by AI agents to understand the tool's purpose -- `icons` - array of [`Mcp\Schema\Icon`](https://github.com/modelcontextprotocol/php-sdk/blob/main/src/Schema/Icon.php) instances -
For more information, see the [`icons` specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/index#icons). -- `outputSchema` - associative array describing a JSON object response -- `annotations` - [`Mcp\Schema\ToolAnnotations`](https://github.com/modelcontextprotocol/php-sdk/blob/main/src/Schema/ToolAnnotations.php) instance -
For more information, see the [`ToolAnnotations` specification](https://modelcontextprotocol.io/specification/2025-11-25/schema#toolannotations). -- `meta` - free-form array for additional metadata -
For more information, see the [`_meta` specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/index#_meta). - -The framework automatically builds an `inputSchema` from the method arguments and their types. -To customize or extend the generated schema, you can: - -- add descriptions with DocBlock `@param` tags -- use the [`Schema` attribute](https://github.com/php-mcp/server#-schema-generation-and-validation) - -If an argument is an [enum](https://www.php.net/manual/en/language.types.enumerations.php), its possible values are listed in the schema ([`UntitledSingleSelectEnumSchema`](https://modelcontextprotocol.io/specification/2025-11-25/schema#untitledsingleselectenumschema)). - -### Prompts - -MCP servers can also provide [prompt templates](https://modelcontextprotocol.io/specification/2025-11-25/server/prompts) to help users interact with AI agents connected to the server. - -Methods that return a prompt are marked with the [`Ibexa\Contracts\Mcp\Attribute\McpPrompt` attribute](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Mcp-Attribute-McpTool.html). - -It accepts several arguments that describe how the prompt is used: - -- `servers` - array of server identifiers exposing this prompt - required for prompts -- `name` (optional) - prompt codename - if not set, the method name is used -- `title` (optional) - prompt title - if not set, `name` is used -- `description` (optional) - human-readable prompt description -- `icons` (optional) - array of [`Mcp\Schema\Icon`](https://github.com/modelcontextprotocol/php-sdk/blob/main/src/Schema/Icon.php) instances -
For more information, see the [`icons` specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/index#icons). -- `meta` (optional) - rarely used free-form array for additional metadata -
For more information, see the [`_meta` specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/index#_meta). - -The framework automatically builds the `arguments` array from the method arguments and their types. -Prompt method arguments must be strings to comply with the [`GetPromptRequestParams` schema](https://modelcontextprotocol.io/specification/2025-11-25/schema#getpromptrequestparams). -To add argument descriptions, use DocBlock `@param` tags, which are mapped to the `description` defined by the [`PromptArgument` schema](https://modelcontextprotocol.io/specification/2025-11-25/schema#promptargument). - -## Example - -To keep the example focused on MCP server configuration and capability creation, it doesn't interact with the [[= product_name =]] repository. - -### Create user account - -In this example, the MCP server uses JWT tokens created with a dedicated user account. - -In [[= product_name =]]'s back office, create a user in the **Guest accounts** user group, with login `ibexa-example` and password `Ibexa-3xample`. - -### Configure MCP server - -This example introduces an MCP server named `example`, with a single tool called `greet`. -The server: - -- is enabled on the default repository -- is available in all SiteAccesses -- is accessible with the path `/mcp/example` -
For example: - - `http://localhost/mcp/example` - - `http://localhost/admin/mcp/example` -- uses file storage for both discovery cache and sessions - -!!! note "Storage choice recommendations" - - Filesystem storage is convenient for the sake of this example and for testing. - For production, it's recommended that you use Redis or Valkey to share cache among the cluster and improve performance. - - For development, you can set `discovery_cache: ~` to avoid clearing the cache after each change. - This example uses the filesystem storage to illustrate that you have to clear the cache pool to refresh the available capabilities, exactly as when deploying into production. - -In a new `config/packages/mcp.yaml` file, define a new MCP server for the `default` repository and assign it to all SiteAccesses: - -``` yaml -[[= include_code('code_samples/mcp/config/packages/mcp.yaml') =]] -``` - -Adapt the `allowed_hosts` to your case, for example, if you want to use a domain name instead of the equivalent `127.0.0.1` address. - -The server is automatically registered as a service with the ID `ibexa.mcp.server.default.example`: - -```bash -php bin/console debug:container ibexa.mcp.server.default.example -``` - -An `ibexa.mcp.example` route is now available: - -```bash -php bin/console debug:router ibexa.mcp.example -``` - -### Create capability class - -Create an `ExampleCapabilities` class that implements `McpCapabilityInterface`. - -The class contains: - -- a method marked with an [`McpTool` attribute](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Mcp-Attribute-McpTool.html) that associates it with the `example` server as the `greet` tool -- a method marked with an [`McpPrompt` attribute](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Mcp-Attribute-McpPrompt.html) that provides a prompt template to users - -``` php -[[= include_code('code_samples/mcp/src/Mcp/ExampleCapabilities.php') =]] -``` - -In this example, the `servers` attribute parameter associates only this tool with the `example` server. -Alternatively, you can assign all tools from the class to a server by using the `tools` parameter in the server configuration. -For more information, see [tools configuration](mcp_config.md#tool-configuration). - -For the prompt, the `servers` parameter is required. -Therefore, the example prompt must use it to be associated with the `example` server. - -During development and testing, you may need to clear the cache to ensure that new or modified capabilities are properly re-discovered. -In this example, use the following command: - -```bash -php bin/console cache:pool:clear cache.tagaware.filesystem -``` - -!!! tip "Cache clearing" - - During development, clear caches aggressively. - The following commands clear all cache types, regardless of where they are stored: - ```bash - php bin/console cache:clear - php bin/console cache:pool:clear --all - ``` - -### Create MCP server list command - -To check the MCP server configuration, create a small command that uses the MCP server configuration registry injected through [`McpServerConfigurationRegistryInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Mcp-McpServerConfigurationRegistryInterface.html) and autowiring: - -``` php -[[= include_code('code_samples/mcp/src/Command/McpServerListCommand.php') =]] -``` - -### Perform `curl` test - -To test the `example` MCP server, a sequence of `curl` commands is used to simulate the communication between an AI client and the MCP server. - -- Ask for a [JWT token through REST](/api/rest_api/rest_api_reference/rest_api_reference.html#tag/User-Token/operation/api_usertokenjwt_post). -- Initialize a connection to the MCP server. -- Validate the MCP Session ID. -- List the available tools. -- Call a tool. - -`jq`, `grep`, and `sed` are also used to parse or display outputs. - -First, use the shell script to set the [[= product_name =]]'s base URL, user credentials, and MCP server URL as variables for easier reuse: - -``` bash -[[= include_code('code_samples/mcp/mcp.sh', 5, 8) =]] -``` - -Before you can communicate with the MCP server, you must first request a JWT token through the REST API: - -``` bash -[[= include_code('code_samples/mcp/mcp.sh', 10, 24) =]] -``` - -``` json -[[= include_code('code_samples/mcp/mcp.sh.output.txt', 1, 7) =]] -``` - -Then, perform [initialization](https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle#initialization) to get an MCP session ID: - -``` bash -[[= include_code('code_samples/mcp/mcp.sh', 22, 45) =]] -``` - -``` http -[[= include_code('code_samples/mcp/mcp.sh.output.txt', 8, 16) =]] -``` - -``` json -[[= include_code('code_samples/mcp/mcp.sh.output.txt', 26, 51) =]] -``` - -Validate the initialization: - -``` bash -[[= include_code('code_samples/mcp/mcp.sh', 47, 53) =]] -``` - -``` http -[[= include_code('code_samples/mcp/mcp.sh.output.txt', 52, 56) =]] -``` - -Get the [list of tools](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#listing-tools): - -``` bash -[[= include_code('code_samples/mcp/mcp.sh', 55, 62) =]] -``` - -``` json -[[= include_code('code_samples/mcp/mcp.sh.output.txt', 69, 128) =]] -``` - -[Call](https://modelcontextprotocol.io/specification/2025-11-25/server/tools#calling-tools) the `greet` tool: - -``` bash -[[= include_code('code_samples/mcp/mcp.sh', 64, 77) =]] -``` - -``` json -[[= include_code('code_samples/mcp/mcp.sh.output.txt', 129, 148) =]] -``` - -Get the [list of prompts](https://modelcontextprotocol.io/specification/2025-11-25/server/prompts#listing-prompts): - -``` bash -[[= include_code('code_samples/mcp/mcp.sh', 79, 86) =]] -``` - -``` json -[[= include_code('code_samples/mcp/mcp.sh.output.txt', 149, 172) =]] -``` - -[Get the prompt](https://modelcontextprotocol.io/specification/2025-11-25/server/prompts#getting-a-prompt) of the `greet` method: - -``` bash -[[= include_code('code_samples/mcp/mcp.sh', 88, 101) =]] -``` - -``` json -[[= include_code('code_samples/mcp/mcp.sh.output.txt', 173, 187) =]] -``` - -### Perform MCP Inspector test - -You can test your server with the [MCP Inspector](https://modelcontextprotocol.io/docs/tools/inspector). -You still need to ask for a JWT token through REST or GraphQL APIs, and use it in the MCP Inspector configuration to connect to the server. - -You can use a web interface to obtain the JWT token: - -- [REST live documentation](rest_api_authentication.md#jwt-token-obtained-through-rest-documentation) -- [GraphiQL](graphql.md#jwt-authentication) - -#### MCP server settings - -In this example, the settings needed to use the MCP Inspector are as follows: - -- Transport Type: Streamable HTTP -- URL: actual domain and server `path`, for example `http://localhost/mcp/example` -- Connection Type: Via Proxy -- Authentication: - - Custom Headers: - - `Authorization` - - `Bearer ` - - OAuth 2.0 Flow: left unedited ![Left panel of MCP Inspector with connection settings for MCP server](img/mcp-inspector-config.png "MCP Inspector connection settings") diff --git a/docs/api/api.md b/docs/api/api.md index b7f13972d57..af11f2ef102 100644 --- a/docs/api/api.md +++ b/docs/api/api.md @@ -5,19 +5,9 @@ page_type: landing_page # API -[[= product_name =]] is an API-first product and provides APIs to handle content and repository information. - -## Web API +[[= product_name =]] is an API-first product and provides a REST API to handle content and repository information. [[= cards([ "api/rest_api/rest_api_usage/rest_api_usage", - "api/graphql/graphql", "ai/mcp/mcp", ], columns=3) =]] - -## PHP API - -[[= cards([ - "api/php_api/php_api", - "api/event_reference/event_reference", -], columns=3) =]] diff --git a/docs/api/rest_api/rest_api_authentication.md b/docs/api/rest_api/rest_api_authentication.md index 3e87258701d..d71934f6c0b 100644 --- a/docs/api/rest_api/rest_api_authentication.md +++ b/docs/api/rest_api/rest_api_authentication.md @@ -8,381 +8,13 @@ month_change: false 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). - -You can only use one of those methods at the same time. - -Using HTTPS for authenticated traffic is highly recommended. - -For other security related subjects, see: - -- [Cross-origin requests](rest_responses.md#cross-origin) -- [`access_control`]([[= symfony_doc =]]/security/access_control.html) - !!! caution "SiteAccess login" The anonymous user is used to perform authentification requests. Therefore, the "Anonymous" role must have `user/login` permission on the SiteAccess that matches the REST domain or is passed through the [`X-Siteaccess` header](rest_requests.md#siteaccess). -## Session-based authentication - -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 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. - -### Configuration - -Session is the default method and is already enabled, so no configuration required. -Enabling any other method disables session. - -### Usage examples - -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 - -##### Creating session - -To create a session, execute the following REST request: - -=== "XML" - - ``` http - POST /user/sessions HTTP/1.1 - Host: www.example.net - Accept: application/vnd.ibexa.api.Session+xml - Content-Type: application/vnd.ibexa.api.SessionInput+xml - ``` - - ```xml - - - admin - publish - - ``` - - ``` http - HTTP/1.1 201 Created - Location: /user/sessions/go327ij2cirpo59pb6rrv2a4el2 - Set-Cookie: IBX_SESSION_ID98defd6ee70dfb1dea416=go327ij2cirpo59pb6rrv2a4el2; domain=.example.net; path=/; expires=Wed, 13-Jan-2021 22:23:01 GMT; HttpOnly - Content-Type: application/vnd.ibexa.api.Session+xml - ``` - - ```xml - - - IBX_SESSION_ID98defd6ee70dfb1dea416 - go327ij2cirpo59pb6rrv2a4el2 - 23lk.neri34ijajedfw39orj-3j93 - - - ``` - -=== "JSON" - - ``` http - POST /user/sessions HTTP/1.1 - Host: www.example.net - Accept: application/vnd.ibexa.api.Session+json - Content-Type: application/vnd.ibexa.api.SessionInput+json - ``` - - ```json - { - "SessionInput": { - "login": "admin", - "password": "publish" - } - } - ``` - - ``` http - HTTP/1.1 201 Created - Location: /user/sessions/go327ij2cirpo59pb6rrv2a4el2 - Set-Cookie: IBX_SESSION_ID98defd6ee70dfb1dea416=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": { - "_media-type": "application\/vnd.ibexa.api.Session+json", - "_href": "\/api\/ibexa\/v2\/user\/sessions\/jg1nhinvepsb9ivd10hbjbdp4l", - "name": "IBX_SESSION_ID98defd6ee70dfb1dea416", - "identifier": "go327ij2cirpo59pb6rrv2a4el2", - "csrfToken": "23lk.neri34ijajedfw39orj-3j93", - "User": { - "_media-type": "application\/vnd.ibexa.api.User+json", - "_href": "\/api\/ibexa\/v2\/user\/users\/14" - } - } - } - ``` - -##### Logging in with active session - -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" - - ``` http - POST /user/sessions HTTP/1.1 - Host: www.example.net - Accept: application/vnd.ibexa.api.Session+xml - Content-Type: application/vnd.ibexa.api.SessionInput+xml - Cookie: IBX_SESSION_ID98defd6ee70dfb1dea416=go327ij2cirpo59pb6rrv2a4el2 - X-CSRF-Token: 23lk.neri34ijajedfw39orj-3j93 - ``` - - ```xml - - - admin - publish - - ``` - - ``` http - HTTP/1.1 200 OK - Content-Type: application/vnd.ibexa.api.Session+xml - ``` - - ```xml - - - IBX_SESSION_ID98defd6ee70dfb1dea416 - go327ij2cirpo59pb6rrv2a4el2 - 23lk.neri34ijajedfw39orj-3j93 - - - ``` - -=== "JSON" - - ``` http - POST /user/sessions HTTP/1.1 - Host: www.example.net - Accept: application/vnd.ibexa.api.Session+json - Content-Type: application/vnd.ibexa.api.SessionInput+json - Cookie: IBX_SESSION_ID98defd6ee70dfb1dea416=go327ij2cirpo59pb6rrv2a4el2 - X-CSRF-Token: 23lk.neri34ijajedfw39orj-3j93 - ``` - - ```xml - { - "SessionInput": { - "login": "admin", - "password": "publish" - } - } - ``` - - ``` http - HTTP/1.1 200 OK - Content-Type: application/vnd.ibexa.api.Session+json - ``` - - ```xml - { - "Session": { - "_media-type": "application\/vnd.ibexa.api.Session+json", - "_href": "\/api\/ibexa\/v2\/user\/sessions\/jg1nhinvepsb9ivd10hbjbdp4l", - "name": "IBX_SESSION_ID98defd6ee70dfb1dea416", - "identifier": "go327ij2cirpo59pb6rrv2a4el2", - "csrfToken": "23lk.neri34ijajedfw39orj-3j93", - "User": { - "_media-type": "application\/vnd.ibexa.api.User+json", - "_href": "\/api\/ibexa\/v2\/user\/users\/14" - } - } - } - ``` - -#### Using session - -##### Session cookie - -You can now add the previously set cookie to requests to be executed with the logged-in user. - -```http -GET /content/locations/1/5 HTTP/1.1 -Host: www.example.net -Accept: Accept: application/vnd.ibexa.api.Location+xml -Cookie: IBX_SESSION_ID98defd6ee70dfb1dea416=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 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. - -```http -DELETE /content/types/32 HTTP/1.1 -Host: www.example.net -Cookie: IBX_SESSION_ID98defd6ee70dfb1dea416=go327ij2cirpo59pb6rrv2a4el2 -X-CSRF-Token: 23lk.neri34ijajedfw39orj-3j93 -``` - -If an unsafe request is missing the CSRF token, or the token has incorrect value, an error is returned: `401 Unauthorized`. - -##### 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're logged into. -In browsers this action is blocked by lack of CSRF token. - -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 -- Authenticates using either: - - Session-based authentication - - "Client side session" by remembering user login/password - -Then, you have to make sure to confirm with the user if they want to perform an unsafe operation. - -Example: - -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`. - -#### Logging out from session - -To log out is to `DELETE` the session using its ID (like in the cookie). As this is an unsafe method, the CSRF token must be presented. - -```http -DELETE /user/sessions/go327ij2cirpo59pb6rrv2a4el2 HTTP/1.1 -Host: www.example.net -Cookie: IBX_SESSION_ID98defd6ee70dfb1dea416=go327ij2cirpo59pb6rrv2a4el2 -X-CSRF-Token: 23lk.neri34ijajedfw39orj-3j93 -``` - -## JWT authentication - -### Configuration - -See [JWT authentication](development_security.md#jwt-authentication) for configuration instructions. - -### Usage example - -After you configure JWT authentication for REST, you can get the JWT token through the following request: - -```http -POST /user/token/jwt HTTP/1.1 -Host: -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": { - "username": "admin", - "password": "publish" - } -} -``` - -If credentials are valid, the server response contains a token: - -```json -{ - "JWT": { - "_media-type": "application/vnd.ibexa.api.JWT+xml", - "_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9…-QBE4-6eKNjg" - } -} -``` - -You can then use this token in your request instead of username and password. - -```http -GET /content/locations/1/5/children -Host: -Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9…-QBE4-6eKNjg -Accept: application/vnd.ibexa.api.LocationList+json -``` - -#### JWT token obtained through REST documentation - -To obtain a JWT token with REST, you can use the live API documentation that is available on your development installation. -This documentation is only accessible when `kernel.debug` is set to `true`, similarly to a development environment. - -- open REST API live doc (for example at `http://localhost/api/ibexa/v2/doc`) -- go to **User Token** section's **POST /user/token/jwt** resource (for example, at `http://localhost/api/ibexa/v2/doc#/User%20Token/api_usertokenjwt_post`) -- click the **Try it out** button -- fill in the following adapted payload with the user credentials -- click the **Execute** button to get a token - -![REST API live documentation with a JWTInput payload](jwt-rest-doc-request.png "REST doc JWT token request") -![REST API live documentation with a JWTInput payload](jwt-rest-doc-response.png "REST doc JWT token response") - -## HTTP basic authentication - -For more information, see [HTTP Authentication: Basic and Digest Access Authentication](https://datatracker.ietf.org/doc/html/rfc2617). - -### Configuration - -If the installation has a dedicated host for REST, you can enable HTTP basic authentication only on this host by setting a firewall like in the following example before the `ibexa_front` one: - -```yaml -security: - firewalls: - # ... - ibexa_rest: - host: ^api\.example\.com$ - http_basic: - realm: Cohesivo REST API - #ibexa_front: - # ... -``` - -!!! 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. - - * 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 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)$`. - -### 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 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`. - -See the following raw HTTP request with basic authentication example: - -```http -GET / HTTP/1.1 -Host: api.example.com -Accept: application/vnd.ibexa.api.Root+json -Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== -``` - ## OAuth -For more information, see [OAuth 2.0 protocol for authorization](https://oauth.net/2/). +TODO: Oauth is the only authentication method. Add an example showing the whole flow. -## SSL client authentication - -The REST API provides authentication of a user by a subject in a client certificate delivered by the web server configured as SSL endpoint. +For more information, see [OAuth 2.0 protocol for authorization](https://oauth.net/2/). 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 222f825b7bf..238bc8e2776 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 @@ -7,32 +7,21 @@ description: The REST API covers objects in the Cohesivo Repository with regular The REST API in [[= product_name =]] allows you to interact with the [[= 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 by using the [Public PHP API](php_api.md) can also be done with the REST API. +Every interaction with the repository that you can do from the back office can also be done with the REST API. The REST API uses HTTP methods (such as `GET` and `PUBLISH`), and HTTP headers to specify the type of request. ## OpenAPI support -The REST API is built on top of [API Platform](https://api-platform.com/docs/symfony/) and meets the [OpenAPI](https://www.openapis.org/) standard. +The REST API meets the [OpenAPI](https://www.openapis.org/) standard. You can download the OpenAPI specification in: - [YAML format](/api/rest_api/rest_api_reference/openapi.yaml) - [JSON format](/api/rest_api/rest_api_reference/openapi.json) -You can also generate one for your project by running one of the commands below: - -``` bash -php bin/console ibexa:openapi --output=openapi.json # JSON output -php bin/console ibexa:openapi --yaml --output=openapi.yaml # YAML output -``` - Use the specification file with [available OpenAPI tools](https://tools.openapis.org/) to work faster with the API, for example, by generating libraries and clients for the API. -!!! note - - In [Symfony's `dev` environment](environments.md), you can access a REST API reference generated for your project by visiting the `/api/ibexa/v2/doc` route in the browser. - ## URIs The REST API is designed in such a way that the client can explore the Repository without constructing any URIs to resources. @@ -43,7 +32,7 @@ Starting from the [root resource](#rest-root), every response includes further l [REST reference](../rest_api_reference/rest_api_reference.html), for the sake of readability, uses no prefixes in the URIs. In practice, the `/api/ibexa/v2` prefixes all REST hrefs. -This prefix immediately follows the domain, and you can't use the [`URIElement` SiteAccess matcher](siteaccess_matching.md#urielement). +This prefix immediately follows the domain. If you need to the select a SiteAccess, see the [`X-Siteaccess` HTTP header](rest_requests.md#siteaccess). ### URI parameters @@ -90,15 +79,3 @@ The ISO-3166 country codes can be represented as: - 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). - -## REST communication summary - -- A REST route (URI) leads to a REST controller action. A REST route is composed of the root prefix (`ibexa.rest.path_prefix: /api/ibexa/v2`) and a resource path (for example, `/content/objects/{contentId}`). -- This controller action returns an `Ibexa\Rest\Value` descendant. - - This controller action might use the `Request` to build its result according to, for example, GET parameters, the `Accept` HTTP header, or the request payload and its `Content-Type` HTTP header. - - This controller action might wrap its return in a `CachedValue` which contains caching information for the reverse proxies. -- The `Ibexa\Bundle\Rest\EventListener\ResponseListener` attached to the `kernel.view event` is triggered, and passes the request and the controller action's result to the `AcceptHeaderVisitorDispatcher`. -- The `AcceptHeaderVisitorDispatcher` matches one of the `regexps` of an `ibexa.rest.output.visitor` service (an `Ibexa\Contracts\Rest\Output\Visitor`). The role of this `Output\Visitor` is to transform the value returned by the controller into XML or JSON output format. To do so, it combines an `Output\Generator` corresponding to the output format and a `ValueObjectVisitorDispatcher`. This `Output\Generator` is also adding the `media-type` attributes. -- The matched `Output\Visitor` uses its `ValueObjectVisitorDispatcher` to select the right `ValueObjectVisitor` according to the fully qualified class name (FQCN) of the controller result. A `ValueObjectVisitor` is a service tagged `ibexa.rest.output.value_object.visitor` and this tag has a property `type` pointing a FQCN. -- `ValueObjectVisitor`s recursively help to transform the controller result thanks to the abstraction layer of the `Generator`. -- The `Output\Visitor` returns the `Response` to send back to the client. 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 0fe823b589a..70a5422affc 100644 --- a/docs/api/rest_api/rest_api_usage/rest_requests.md +++ b/docs/api/rest_api/rest_api_usage/rest_requests.md @@ -40,8 +40,6 @@ For method action details per resource, see the [REST API reference](../rest_api If applicable, both methods are always mentioned in the specifications. -Unsafe methods require a CSRF token if [session-based authentication](rest_api_authentication.md#session-based-authentication) is used. - ### OPTIONS method Any REST API URI responds to an `OPTIONS` request. @@ -119,7 +117,7 @@ This header is also used to specify the response type you want the server to sen 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. +Also see Creating session examples. 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`. @@ -149,7 +147,7 @@ For example, it prevents a Content request to be executed with Anonymous user in 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). +One example is the creation of an authentication session. 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. @@ -157,30 +155,15 @@ When searching for content items (or locations), the query grammar is also parti ### Creating content with binary attachments -The example below is a command-line script to upload images. It's based on the [Symfony HttpClient]([[= symfony_doc =]]/http_client.html). - -This script: - -- receives an image path and optionally a name as command-line arguments, -- uses the [HTTP basic authentication](rest_api_authentication.md#http-basic-authentication), if it's enabled, -- creates a draft in the /Media/Images folder by posting (`POST`) data to [`/content/objects`](/api/rest_api/rest_api_reference/rest_api_reference.html#tag/Objects/operation/api_contentobjects_post), -- and, publishes (`PUBLISH`) the draft through [`/content/objects/{contentId}/versions/{versionNo}`](../rest_api_reference/rest_api_reference.html#managing-content-publish-a-content-version). - -=== "XML" - - ``` php - [[= include_code('code_samples/api/rest_api/create_image.xml.php', 1, None, 1) =]] - ``` - -=== "JSON" - - ``` php - [[= include_code('code_samples/api/rest_api/create_image.json.php', indent_level=1) =]] - ``` +To create content with a binary attachment, such as an image, post the content +data to [`/content/objects`](/api/rest_api/rest_api_reference/rest_api_reference.html#tag/Objects/operation/api_contentobjects_post) +to create a draft, then publish it through +[`/content/objects/{contentId}/versions/{versionNo}`](../rest_api_reference/rest_api_reference.html#managing-content-publish-a-content-version). +Authenticate the requests as described in HTTP basic authentication. ### Search (`/views`) -The `/views` route allows you to [search in the repository](search.md). It works similarly to its [PHP API counterpart](search_api.md). +The `/views` route allows you to [search in the repository](search.md). The model allows combining criteria using the logical operators `AND`, `OR` and `NOT`. 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 40b698dea06..0ebf86d4192 100644 --- a/docs/api/rest_api/rest_api_usage/rest_responses.md +++ b/docs/api/rest_api/rest_api_usage/rest_responses.md @@ -88,7 +88,7 @@ Content-Type: application/vnd.ibexa.api.Content+json Accept-Patch: application/vnd.ibexa.api.ContentUpdate+json ``` -Those example `Accept-Path` headers above indicate that the content could be modified by sending a [ContentUpdateStruct](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentUpdateStruct.html) in XML or JSON. +Those example `Accept-Patch` headers above indicate that the content could be modified by sending a `ContentUpdateStruct` in XML or JSON. ### Location header @@ -121,7 +121,6 @@ Location: /content/objects?remoteId=34720ff636e1d4ce512f762dc638e4ac ``` cURL can follow those redirections. On CLI, there is the `--location` option (or its shorthand `-L`). -In PHP, you can achieve the same effect with `CURLOPT_FOLLOWLOCATION`. The following command-line example follows the two redirections above and the `Accept` header is propagated: ```bash @@ -133,31 +132,12 @@ HTTP/1.1 200 OK Content-Type: application/vnd.ibexa.api.Content+json ``` -### Cross-origin - -[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. - -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/Guides/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). - -Using CORS isn't limited to REST API resources and can be used for any resource of the platform. - -The CORS bundle adds an `Access-Control-Allow-Origin` header to the response. - -#### Configuration - -To enable CORS, add regular expression for an allowed domain using the `.env` variable `CORS_ALLOW_ORIGIN`. - -For example, to allow the [JS test](testing_rest_api.md#js) 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`. - ## Response body -The Response body is often a serialization in XML or JSON of an object as it could be retrieved using the Public PHP API. +The response body (both JSON and XML) contain two types of nodes: -For example, the resource `/content/objects/52` with the `Accept: application/vnd.ibexa.api.ContentInfo+xml` header returns a serialized version of a [ContentInfo](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-ContentInfo.html) object. +- final nodes that fully give an information as a scalar value +- reference nodes which link to `href` where a new resource of a given `media-type` can be explored if you need to know more ```bash curl https://api.example.com/content/objects/52 --header 'Accept: application/vnd.ibexa.api.ContentInfo+xml'; @@ -185,8 +165,3 @@ curl https://api.example.com/content/objects/52 --header 'Accept: application/vn ``` - -The response body XML can contain two types of nodes: - -- Final nodes that fully give an information as a scalar value -- Reference nodes which link to `href` where a new resource of a given `media-type` can be explored if you need to know more 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 c44fe90fa9b..9475577395b 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 @@ -5,7 +5,7 @@ description: You can test operations in the REST API by using command line, PHP # Testing REST API 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/`. +You can, however, try opening the root resource located at `/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 with cURL, PHP or JS. @@ -19,22 +19,6 @@ For examples of using `curl`, refer to: - [Location header](rest_responses.md#location-header) - [ContentInfo body](rest_responses.md#response-body) -## PHP - -You can use [Symfony HttpClient]([[= symfony_doc =]]/http_client.html) to test REST API. -Open a PHP shell in a terminal with `php -a` and copy-paste this code into it: - -``` php -[[= include_code('code_samples/api/rest_api/load_content.php', 3, 9, remove_indent=True) =]] -``` - -`$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. - -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. @@ -71,7 +55,5 @@ 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. - -You can edit the `resource` URI to address another domain, but [cross-origin requests](rest_responses.md#cross-origin) must be allowed first. +By default, `52` is the Content ID of the home page. +If necessary, substitute `52` with the Content ID of an item in your system. diff --git a/docs/content_management/content_availability.md b/docs/content_management/content_availability.md index 37ecf7b1bf4..16cc887b327 100644 --- a/docs/content_management/content_availability.md +++ b/docs/content_management/content_availability.md @@ -21,8 +21,6 @@ corresponding to the current SiteAccess. 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. The Default availability flag is used for the out-of-the box content types representing content that should always be visible to the user, such as media files or user content items. diff --git a/docs/content_management/content_management.md b/docs/content_management/content_management.md index 02d6abe4efd..93f8e4f9836 100644 --- a/docs/content_management/content_management.md +++ b/docs/content_management/content_management.md @@ -14,5 +14,4 @@ page_type: landing_page "content_management/forms/forms", "content_management/taxonomy/taxonomy", "content_management/workflow/workflow", - "content_management/data_migration/data_migration", ], columns=4) =]] diff --git a/docs/content_management/content_management_guide.md b/docs/content_management/content_management_guide.md index 8d6422a3c2b..58c7effe6d3 100644 --- a/docs/content_management/content_management_guide.md +++ b/docs/content_management/content_management_guide.md @@ -10,11 +10,6 @@ The term “content management” covers all the tasks that you need to perform 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 - -Content management capabilities are available in all [[= product_name =]] editions. - ## How does it work [[= product_name =]] revolves around content management. Many things here are content items, including: @@ -31,11 +26,10 @@ Content management capabilities are available in all [[= product_name =]] editio 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. - +You can then build an external systems that uses [[= product_name =]] as a headless CMS, a single source of truth for anything related to content. ## 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**. 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. @@ -48,7 +42,6 @@ A structure of elements that *store* content information is referred to as the * [[= 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. The editing interface lets all users, including those with no coding experience, create or modify certain areas of the content model. @@ -100,7 +93,7 @@ For example, articles might have for example, a title, an author, a body, and an 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/). +[[= product_name =]] comes with a visual [Form Builder]([[= user_doc =]]/content_management/work_with_forms/). ## Content management capabilities @@ -212,7 +205,7 @@ For example, you can build Pages that contain different recommendations, dependi ## 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're ready to employ the content management features to good use. +With your [[= product_name =]] instance ready, you can 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. @@ -221,7 +214,7 @@ Since content management is an ongoing process, and, in your implementation, you 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 field types, then [create content types]([[= user_doc =]]/content_management/create_edit_content_items/). **2\. Define permissions** diff --git a/docs/content_management/content_model.md b/docs/content_management/content_model.md index 7a80c06ca4d..a20aef73daa 100644 --- a/docs/content_management/content_model.md +++ b/docs/content_management/content_model.md @@ -24,7 +24,7 @@ The fields can cover data ranging from single variables and text lines to media ### 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. +General information about a content item is stored in a `ContentInfo` object. `ContentInfo` doesn't include fields. It contains following information: **`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. @@ -83,8 +83,6 @@ The fields of a content item are defined by the content type to which the conten 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). - ### Field value validation 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. @@ -118,10 +116,6 @@ Depending on the field type, there may also be other, specific information to fi ![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). - ## Content versions Each content item can have multiple versions. 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 d4f01ae0c55..2fd646f6502 100644 --- a/docs/content_management/field_types/field_type_reference/addressfield.md +++ b/docs/content_management/field_types/field_type_reference/addressfield.md @@ -1,142 +1,59 @@ ---- -edition: experience ---- - - # Address field type 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 -provided by the `ibexa/fieldtype-address` package. - -## PHP API field type - -### Inputs - -| Type | Description | Example | -|----------|-----------------------------------------------|-------------------| -| `string` | Name of the address. | `My home address` | -| `string` | Country code in ISO 3166-1 alpha-2 format. | `PL` | -| `array` | Additional fields, defined by address format. | see below | - -### Example input - -``` php -use Ibexa\FieldTypeAddress\FieldType; - -new FieldType\Value( - 'My home address', - 'PL', - [ - 'city' => 'Warsaw', - 'region' => 'Masovian', - 'postal_code' => '11-123', - ] -); -``` - -### Validation - -This field type validates whether `Country` and `Name` fields have been filled out. - -### Value object - -#### Properties - -| Property | Type | Description | -|------------|----------|-----------------------------------------------| -| `$name` | `string` | Name of the address. | -| `$country` | `string` | Country code in ISO 3166-1 alpha-2 format. | -| `$fields` | `array` | Additional fields, defined by address format. | +| Name | Internal name | +|-----------|-----------------| +| `Address` | `ibexa_address` | -#### Constructor +## Field value -See above (Example input). +The field value is an object with the following keys: -### Formats +| Key | Type | Description | Example | +|-----------|----------|---------------------------------------------------------------|-------------------| +| `name` | `string` | Name of the address. | `My home address` | +| `country` | `string` | Country code in ISO 3166-1 alpha-2 format. | `NO` | +| `fields` | `object` | Additional fields, keyed by identifier. | See below. | -The following default configuration defines default fields for `personal` address type: +The keys available under `fields` depend on the address format configured for the country and on the `type` field definition setting. -```yaml -formats: - personal: - country: - default: - - region - - locality - - street - - postal_code -``` - -#### Modifying field configuration - -```yaml -formats: - billing_address: - country: - DE: - - tax_number - - city - - address - - postal_code -``` - -Adds (or alters) an address format for `DE` country of `billing_address` type. - -### Field form types - -By default, each field is a simple text input with a label made of field identifier. -To change the type of field, you need to listen to a specific event. -For each field below events are dispatched (in order): - -```yaml -ibexa.address.field.{FIELD_IDENTIFIER} -ibexa.address.field.{FIELD_IDENTIFIER}.{ADDRESS_TYPE} -ibexa.address.field.{FIELD_IDENTIFIER}.{ADDRESS_TYPE}.{COUNTRY_CODE} +``` json +{ + "fieldDefinitionIdentifier": "billing_address", + "languageCode": "eng-GB", + "fieldValue": { + "name": "Headquarters", + "country": "NO", + "fields": { + "region": "Company HQ location region", + "locality": "Company HQ location city", + "street": "Company HQ location street and building", + "postal_code": "00000", + "email": "company@email.invalid", + "phone_number": "+47 000 000 000" + } + } +} ``` -#### Example +## Validation -```yaml -ibexa.address.field.tax_number -ibexa.address.field.tax_number.billing_address -ibexa.address.field.tax_number.billing_address.DE -``` +This field type validates whether the `name` and `country` keys have been filled out. -#### Example event listener +## Settings -An event listener can also provide validation by using either one of [constraints provided by Symfony]([[= symfony_doc =]]/validation.html#supported-constraints), -or a custom constraint. +The field definition of this field type can be configured with a single option: -``` php -use Ibexa\Contracts\FieldTypeAddress\Event\MapFieldEvent; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\Extension\Core\Type\IntegerType; -use Symfony\Component\Validator\Constraints\Positive; +| Name | Type | Default value | Description | +|--------|----------|----------------|------------------------------------------------------------| +| `type` | `string` | `"personal"` | Identifier of the address format used by this field. | -class ExampleAddressSubscriber implements EventSubscriberInterface +``` json { - public static function getSubscribedEvents(): array - { - return [ - 'ibexa.address.field.tax_number.billing_address' => 'onBillingAddressTaxNumber', - ]; - } - - public function onBillingAddressTaxNumber(MapFieldEvent $event): void - { - $event->setLabel('VAT'); - $event->setType(IntegerType::class); - $event->setOptions([ - 'attr' => ['class' => 'some-tax-number'], - 'constraints' => [new Positive()], - ]); + "fieldSettings": { + "type": "personal" } } ``` 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 e43d8432e36..9ef675aa8b7 100644 --- a/docs/content_management/field_types/field_type_reference/authorfield.md +++ b/docs/content_management/field_types/field_type_reference/authorfield.md @@ -2,91 +2,55 @@ 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` | `ibexa_author` | mixed | `string` | - -## PHP API field type - -### Value object - -#### Properties - -| Attribute | Type | Description | Example | -|-----------|------------------------------------------|------------------|-----------| -| `authors` | `\Ibexa\Core\FieldType\Author\Author[]` | List of authors. | See below | - -Example: - -``` php -use Ibexa\Core\FieldType\Author; - -$authorList = new Author\Value([ - new Author\Author([ - 'id' => 1, - 'name' => 'Boba Fett', - 'email' => 'boba.fett@example.com', - ]), - new Author\Author([ - 'id' => 2, - 'name' => 'Darth Vader', - 'email' => 'darth.vader@example.com', - ]), -]); +| Name | Internal name | +|----------|----------------| +| `Author` | `ibexa_author` | + +## Field value + +The field value is an array of author objects, each with the following keys: + +| Key | Type | Description | Example | +|---------|-----------|------------------------------------|-------------------------| +| `id` | `integer` | Identifier of the author entry. | `1` | +| `name` | `string` | Name of the author. | `Boba Fett` | +| `email` | `string` | Email address of the author. | `boba.fett@example.com` | + +``` json +{ + "fieldDefinitionIdentifier": "authors", + "languageCode": "eng-GB", + "fieldValue": [ + { + "id": 1, + "name": "Boba Fett", + "email": "boba.fett@example.com" + }, + { + "id": 2, + "name": "Darth Vader", + "email": "darth.vader@example.com" + } + ] +} ``` -#### Hash format - -The hash format mostly matches the value object. It has the following key `authors`. - -Example - -``` php -[ - [ - 'id' => 1, - 'name' => 'Boba Fett', - 'email' => 'boba.fett@example.com', - ], - [ - 'id' => 2, - 'name' => 'Darth Vader', - 'email' => 'darth.vader@example.com', - ], -]; -``` - -#### String representation - -The string contains all the authors with their names and emails. - -Example: `John Doe john@doe.com` - -### Validation +## Validation 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: - -| Name | Type | Default value | Description | -|-----------------|---------|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------| -| `defaultAuthor` | `mixed` | `Type::DEFAULT_VALUE_EMPTY` | One of the `DEFAULT_*` constants, used by the administration interface for setting the default Field value. See below for more details. | - -Following `defaultAuthor` default value options are available as constants in the `Ibexa\Core\FieldType\Author\Type` class: - -| Constant | Description | -|------------------------|-------------------------------------------| -| `DEFAULT_VALUE_EMPTY` | Default value is empty. | -| `DEFAULT_CURRENT_USER` | Default value uses currently logged user. | +## Settings -``` php -// Author field type example settings +The field definition of this field type can be configured with a single option: -use Ibexa\Core\FieldType\Author\Type; +| Name | Type | Default value | Description | +|-----------------|-----------|---------------|-----------------------------------------------------------------------------------------------| +| `defaultAuthor` | `integer` | `0` | Default field value used by the editing interface. `0` means empty, `1` means current user. | -$settings = [ - 'defaultAuthor' => Type::DEFAULT_VALUE_EMPTY, -]; +``` json +{ + "fieldSettings": { + "defaultAuthor": 1 + } +} ``` 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 0d3d48903a3..527d5bf64e8 100644 --- a/docs/content_management/field_types/field_type_reference/binaryfilefield.md +++ b/docs/content_management/field_types/field_type_reference/binaryfilefield.md @@ -1,88 +1,77 @@ # 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. - -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` | `ibexa_binaryfile` | mixed | mixed | - -## PHP API field type - -### Value object - -#### 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 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 | -| `downloadCount` | integer | Number of times the file was downloaded | 0 | -| `inputUri` | string | Path to a local file when creating a field value, `null` when reading a field value | `path/to/document.pdf` | - -#### Constructor's hash format - -The hash format mostly matches the value object. It has the following keys: - -| Key | Status | Type | Description | -|-----------------|------------|---------|------------------------------------------------------------------------------------------| -| `inputUri` | mandatory | string | Path to the local file to be uploaded into the field. | -| `id` | deprecated | string | Backward compatibility alias for `inputUri`. | -| `path` | deprecated | string | Backward compatibility alias for `inputUri`. | -| `fileName` | optional | string | Name of the file when downloaded. If not given, the basename of `inputUri` is used | -| `fileSize` | optional | integer | Size of the file in bytes. If not given, the size of the `inputUri` target file is used. | -| `downloadCount` | optional | integer | Number of times the file was downloaded. If not given, set to `0` (zero). | -| `mimeType` | ignored | | | -| `uri` | ignored | | | - -Example: - -``` php -/** @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentCreateStruct $fileContentCreateStruct */ -$fileContentCreateStruct->setField('file', new Ibexa\Core\FieldType\BinaryFile\Value([ - 'fileName' => 'example.pdf', - 'inputUri' => '/tmp/example_for_website.pdf', -])); +This field type represents and handles a single binary file. It also counts the number of times the file has been downloaded. + +It's capable of handling virtually any file type and is typically used for storing document types, for example, PDF files, Word documents, or spreadsheets. +The maximum allowed file size is determined by the `FileSizeValidator` configuration of the field definition. + +| Name | Internal name | +|--------------|--------------------| +| `BinaryFile` | `ibexa_binaryfile` | + +## Field value + +The field value is an object with the following keys, or `null` when the field is empty: + +| Key | Type | Description | Example | +|-----------------|-----------|-----------------------------------------------------------------------------------------|-----------------------------------| +| `id` | `string` | Binary file identifier. | `application/63cd472dd7.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` | `integer` | File size, in bytes. | `1077923` | +| `mimeType` | `string` | The file's MIME type. | `application/pdf` | +| `uri` | `string` | Download URL of the file, prefixed with the same host as the REST request. See [Binary and Media download](binary_and_media_download.md). | `https://example.com/content/download/210/file/20130116_whitepaper.pdf` | +| `url` | `string` | Same value as `uri`. Kept for backward compatibility, use `uri` instead. | See `uri`. | +| `downloadCount` | `integer` | Number of times the file was downloaded. | `0` | +| `inputUri` | `string` | Internal storage path of the file. Read-only on output. | `var/site/storage/original/application/63cd472dd7.pdf` | +| `path` | `string` | Same value as `inputUri`. Kept for backward compatibility. | See `inputUri`. | + +``` json +{ + "fieldDefinitionIdentifier": "file", + "languageCode": "eng-GB", + "fieldValue": { + "id": "application/63cd472dd7.pdf", + "fileName": "20130116_whitepaper.pdf", + "fileSize": 1077923, + "mimeType": "application/pdf", + "uri": "https://example.com/content/download/210/file/20130116_whitepaper.pdf", + "downloadCount": 0 + } +} ``` -The original local file name `example_for_website.pdf` is forgotten. -When downloaded, the filename is `example.pdf`. - -To use a remote file, you have to download it locally first, then remove it after it's used in `ContentService::createContent`. +### Uploading a file -## REST API specifics +To send file contents, provide them as a base64-encoded string under the `data` key, together with `fileName`: -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 +``` json +{ + "fieldDefinitionIdentifier": "file", + "languageCode": "eng-GB", + "fieldValue": { + "fileName": "My file.pdf", + "fileSize": 17589, + "data": "JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBS..." + } +} +``` -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. +To keep the existing file while updating other keys, send the field value without the `data` key. -Example: `http://example.com/var/ezdemo_site/storage/original/application/63cd472dd7819da7b75e8e2fee507c68.pdf` +## Validation -### Creating content: `data` property +The field type supports `FileSizeValidator`, defining the maximum size of the file in bytes: -When creating BinaryFile content with the REST API, it's possible to provide data as a base64 encoded string, by using the `data` fieldValue key: +| Name | Type | Default value | Description | +|---------------|-----------|---------------|----------------------------------------| +| `maxFileSize` | `integer` | `null` | Maximum size of the file in bytes. | -``` xml - - file - eng-GB - - My file.pdf - 17589 - - - +``` json +{ + "validatorConfiguration": { + "FileSizeValidator": { + "maxFileSize": 10485760 + } + } +} ``` 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 b5d673b0047..1d6f5802899 100644 --- a/docs/content_management/field_types/field_type_reference/checkboxfield.md +++ b/docs/content_management/field_types/field_type_reference/checkboxfield.md @@ -1,49 +1,21 @@ # 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. -| Name | Internal name | Expected input type | -|------------|-----------------|---------------------| -| `Checkbox` | `ibexa_boolean` | `boolean` | +| Name | Internal name | +|------------|-----------------| +| `Checkbox` | `ibexa_boolean` | -## PHP API field type +## Field value -### Value object +The field value is a boolean: `true` when the checkbox is checked, `false` when it isn't. +It's never considered empty. -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Default value | Description | -|----------|-----------|---------------|--------------------------------------------------------------------------------| -| `$bool` | `boolean` | `false` | This property is used for the checkbox status, represented by a boolean value. | - -``` php -//Value object content examples -use Ibexa\Core\FieldType\Checkbox; - -// Instantiates a checkbox value with a default state (false) -$checkboxValue = new Checkbox\Value(); - -// Checked -$checkboxValue->bool = true; - -// Unchecked -$checkboxValue->bool = false; +``` json +{ + "fieldDefinitionIdentifier": "enable_comments", + "languageCode": "eng-GB", + "fieldValue": true +} ``` -##### Constructor - -The `Checkbox\Value` constructor accepts a boolean value: - -``` php -// Constructor example -use Ibexa\Core\FieldType\Checkbox; - -// Instantiates a checkbox value with a checked state -$checkboxValue = new Checkbox\Value(true); -``` - -##### String representation - -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 deleted file mode 100644 index 4aaab24ce54..00000000000 --- a/docs/content_management/field_types/field_type_reference/contentqueryfield.md +++ /dev/null @@ -1,11 +0,0 @@ -# Content query field type - -This field type maps an executable repository query to a field. - -| Name | Internal name | Expected input | -|---------|-----------------------|----------------| -| `Query` | `ibexa_content_query` | `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. - -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 7acea36ab33..af5e054c8e8 100644 --- a/docs/content_management/field_types/field_type_reference/countryfield.md +++ b/docs/content_management/field_types/field_type_reference/countryfield.md @@ -2,102 +2,41 @@ This field type represents one or multiple countries. -| Name | Internal name | Expected input | -|-----------|-----------------|----------------| -| `Country` | `ibexa_country` | `array` | +| Name | Internal name | +|-----------|-----------------| +| `Country` | `ibexa_country` | -## PHP API field type +## Field value -### Input expectations +The field value is an array of [Alpha-2](https://www.iso.org/iso-3166-country-codes.html) country codes, or `null` when the field is empty. -Example array: - -``` php -[ - 'JP' => [ - 'Name' => 'Japan', - 'Alpha2' => 'JP', - 'Alpha3' => 'JPN', - 'IDC' => 81, - ], -]; +``` json +{ + "fieldDefinitionIdentifier": "country", + "languageCode": "eng-GB", + "fieldValue": ["NO", "PL"] +} ``` -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). +On input, each entry can be a country Name, Alpha-2, or Alpha-3 code. +The stored and returned value always uses Alpha-2 codes. -### Validation +## 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 +## 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 a single option: | Name | Type | Default value | Description | |--------------|-----------|---------------|--------------------------------------------------------------------------------------------| | `isMultiple` | `boolean` | `false` | This setting allows (if true) or prohibits (if false) the selection of multiple countries. | -``` php -// Country FieldType example settings -$settings = [ - 'isMultiple' => true, -]; -``` - -### Hash format - -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 -/** @var \Ibexa\Contracts\Core\Repository\Values\Content\Content $content */ -$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. - -### Value object - -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|--------------|-----------|---------------------------------------------------------------------------------------| -| `$countries` | `array[]` | This property is used for the country selection provided as input, as its attributes. | - -``` php -// Value object content example -/** @var \Ibexa\Core\FieldType\Country\Value $value */ -$value->countries = [ - 'JP' => [ - 'Name' => 'Japan', - 'Alpha2' => 'JP', - 'Alpha3' => 'JPN', - 'IDC' => 81, - ], -]; -``` - -##### Constructor - -The `Country\Value` constructor initializes a new value object with the value provided. -It expects an array as input. - -``` php -// Constructor example -use Ibexa\Core\FieldType\Country as Country; - -// Instantiates a Country Value object -$countryValue = new Country\Value( - [ - 'JP' => [ - 'Name' => 'Japan', - 'Alpha2' => 'JP', - 'Alpha3' => 'JPN', - 'IDC' => 81, - ], - ] -); +``` json +{ + "fieldSettings": { + "isMultiple": true + } +} ``` 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 c2e2f4cfa30..5be96a66c71 100644 --- a/docs/content_management/field_types/field_type_reference/customergroupfield.md +++ b/docs/content_management/field_types/field_type_reference/customergroupfield.md @@ -2,18 +2,24 @@ 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 | +| Name | Internal name | +|------------------|------------------------| +| `Customer group` | `ibexa_customer_group` | -## PHP API field type +## Field value -### Value object +The field value is an object with a single key, or `null` when the field is empty: -#### Properties +| Key | Type | Description | Example | +|---------------------|-----------|---------------------------|---------| +| `customer_group_id` | `integer` | ID of the customer group. | `1` | -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|----------|---------|---------------------------| -| `$id` | `int` | ID of the customer group. | +``` json +{ + "fieldDefinitionIdentifier": "customer_group", + "languageCode": "eng-GB", + "fieldValue": { + "customer_group_id": 1 + } +} +``` 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 ad05e91a2d7..e4cef202694 100644 --- a/docs/content_management/field_types/field_type_reference/dateandtimefield.md +++ b/docs/content_management/field_types/field_type_reference/dateandtimefield.md @@ -2,107 +2,63 @@ This field type represents a full date and time information. -| Name | Internal name | Expected input type | -|---------------|-------------------|---------------------| -| `DateAndTime` | `ibexa_datetime` | mixed | - -## PHP API field type - -### Input expectations - -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's also possible to directly pass an instance of `\DateTime`. - -| Type | Example | -|-------------|------------------------------------| -| `integer` | `"2017-08-28 12:20 Europe/Berlin"` | -| `integer` | `1346149200` | -| `\DateTime` | `new \DateTime()` | - -### Value object - -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description| -|----------|-------------|------------| -| `$value` | `\DateTime` | The date and time value as an instance of `\DateTime`. | - -##### Constructor - -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 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 | -|-----------|---------------------------------------------------------------------|---------| -| D | Three letter representation of a day, range Mon to Sun | Wed | -| Y | Four digit representation of a year | 2016 | -| d | Two digit representation of a day, range 01 to 31 | 22 | -| m | Two digit representation of a month, range 01 to 12 | 05 | -| H | Two digit representation of an hour, 24-hour format, range 00 to 23 | 12 | -| i | Two digit representation of minutes, range 00 to 59 | 19 | -| s | Two digit representation of seconds, range 00 to 59 | 18 | - -Example: `Wed 2016-22-05 12:19:18` - -### Hash format - -Hash value of this field type is an array with two keys: +| Name | Internal name | +|---------------|------------------| +| `DateAndTime` | `ibexa_datetime` | + +## Field value + +The field value is an object with the following keys, or `null` when the field is empty: + +| 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). | `"Friday, 23-May-14 14:56:14 GMT+0000"` | + +``` json +{ + "fieldDefinitionIdentifier": "event_start", + "languageCode": "eng-GB", + "fieldValue": { + "timestamp": 1400856992, + "rfc850": "Friday, 23-May-14 14:56:14 GMT+0000" + } +} +``` -| 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 has precedence over the timestamp value. | `"Friday, 23-May-14 14:56:14 GMT+0000"` | +On input, you can provide any one of the following keys. `rfc850` takes precedence over `timestring`, which takes precedence over `timestamp`: -``` php -$hash = [ - 'timestamp' => 1400856992, - 'rfc850' => 'Friday, 23-May-14 14:56:14 GMT+0000', -]; -``` +| Key | Type | Description | Example | +|--------------|-----------|--------------------------------------------------------|------------------------------------| +| `rfc850` | `string` | Date and time as an RFC 850 string. | `"Friday, 23-May-14 14:56:14 GMT+0000"` | +| `timestring` | `string` | Date and time as a string in any commonly used format. | `"2017-08-28 12:20 Europe/Berlin"` | +| `timestamp` | `integer` | Date and time as a Unix timestamp. | `1346149200` | -### Validation +## Validation This field type doesn't perform any special validation of the input value. -### Settings +## Settings 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` | `?\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 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 - -use Ibexa\Core\FieldType\DateAndTime\Type; - -$settings = [ - 'useSeconds' => false, - 'defaultType' => Type::DEFAULT_EMPTY, - 'dateInterval' => null, -]; - -/** @var \Ibexa\Contracts\Core\Repository\ContentTypeService $contentTypeService */ -$dateAndTimeFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct( - 'my_date_and_time_field', - 'ibexa_datetime' -); -$dateAndTimeFieldCreateStruct->fieldSettings = $settings; +| Name | Type | Default value | Description | +|----------------|-----------|-------------------|------------------------------------------------------------------------------------------------------------------------------| +| `useSeconds` | `boolean` | `false` | Used to control displaying of seconds in the output. | +| `defaultType` | `string` | `"DEFAULT_EMPTY"` | Default field value used by the editing interface. See the values below. | +| `dateInterval` | `object` | `null` | Complements the `defaultType` setting and is used only when the latter is set to `"DEFAULT_CURRENT_DATE_ADJUSTED"`. The default input value is then adjusted by the given interval. | + +| Value | Description | +|-----------------------------------|----------------------------------------------------------------------------------------------| +| `"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. | + +``` json +{ + "fieldSettings": { + "useSeconds": false, + "defaultType": "DEFAULT_CURRENT_DATE" + } +} ``` 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 057ece589e1..460f2b8c571 100644 --- a/docs/content_management/field_types/field_type_reference/datefield.md +++ b/docs/content_management/field_types/field_type_reference/datefield.md @@ -2,98 +2,62 @@ This field type represents a date without time information. -| Name | Internal name | Expected input type | -|--------|---------------|---------------------| -| `Date` | `ibexa_date` | mixed | - -## PHP API field type - -### Input expectations - -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's also possible to directly pass an instance of `\DateTime`. - -| Type | Example | -|-------------|------------------------------------| -| `string` | `"2012-08-28 12:20 Europe/Berlin"` | -| `integer` | `1346149200` | -| `\DateTime` | `new \DateTime()` | - Time information is **not stored**. - 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: - -| Property | Type | Description | -|----------|-------------|---------------------------------------------| -| `$date` | `\DateTime` | This property is used for the text content. | - -##### String representation +| Name | Internal name | +|--------|---------------| +| `Date` | `ibexa_date` | -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). +## Field value -| Character | Description | Example | -|-----------|---------------------------------------------------------------------|-----------| -| l | Textual representation of a day of the week, range Monday to Sunday | Wednesday | -| d | Two digit representation of a day, range 01 to 31 | 22 | -| F | Textual representation of a month, range January to December | May | -| Y | Four digit representation of a year | 2016 | +The field value is an object with the following keys, or `null` when the field is empty: -Example: `Wednesday 22 May 2016` +| Key | Type | Description | Example | +|-------------|-----------|--------------------------------------------------------------------------------------|-----------------------------------------| +| `timestamp` | `integer` | Date information in [Unix format timestamp](https://en.wikipedia.org/wiki/Unix_time). | `1400856992` | +| `rfc850` | `string` | Date information as a string in [RFC 850 date format](https://datatracker.ietf.org/doc/html/rfc850). | `"Friday, 23-May-14 14:56:14 GMT+0000"` | -##### Constructor - -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: +``` json +{ + "fieldDefinitionIdentifier": "publication_date", + "languageCode": "eng-GB", + "fieldValue": { + "timestamp": 1400856992, + "rfc850": "Friday, 23-May-14 14:56:14 GMT+0000" + } +} +``` -| 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 has higher precedence over the timestamp value. | `"Friday, 23-May-14 14:56:14 GMT+0000"` | +On input, you can provide any one of the following keys. `rfc850` takes precedence over `timestring`, which takes precedence over `timestamp`: -``` php -// Example of the hash value in PHP -$hash = [ - 'timestamp' => 1400856992, - 'rfc850' => 'Friday, 23-May-14 14:56:14 GMT+0000', -]; -``` +| Key | Type | Description | Example | +|--------------|-----------|------------------------------------------------|------------------------------------| +| `rfc850` | `string` | Date as an RFC 850 string. | `"Friday, 23-May-14 14:56:14 GMT+0000"` | +| `timestring` | `string` | Date as a string in any commonly used format. | `"2012-08-28 12:20 Europe/Berlin"` | +| `timestamp` | `integer` | Date as a Unix timestamp. | `1346149200` | -### Validation +## Validation This field type doesn't perform any special validation of the input value. -### Settings +## Settings 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. | - -Following `defaultType` default value options are available as constants in the `Ibexa\Core\FieldType\Date\Type` class: - -| Constant | Description | -|------------------------|----------------------------------| -| `DEFAULT_EMPTY` | Default value is empty. | -| `DEFAULT_CURRENT_DATE` | Default value uses current date. | - -``` php -// Date field type example settings - -use Ibexa\Core\FieldType\Date\Type; - -$settings = [ - 'defaultType' => Type::DEFAULT_EMPTY, -]; +| Name | Type | Default value | Description | +|---------------|----------|-------------------|----------------------------------------------------------------------| +| `defaultType` | `string` | `"DEFAULT_EMPTY"` | Default field value used by the editing interface. See the values below. | + +| Value | Description | +|--------------------------|----------------------------------| +| `"DEFAULT_EMPTY"` | Default value is empty. | +| `"DEFAULT_CURRENT_DATE"` | Default value uses current date. | + +``` json +{ + "fieldSettings": { + "defaultType": "DEFAULT_CURRENT_DATE" + } +} ``` 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 06294cf899b..6ed50030f64 100644 --- a/docs/content_management/field_types/field_type_reference/emailaddressfield.md +++ b/docs/content_management/field_types/field_type_reference/emailaddressfield.md @@ -2,65 +2,27 @@ The EmailAddress field type represents an email address, in the form of a string. -| Name | Internal name | Expected input type | -|----------------|---------------|---------------------| -| `EmailAddress` | `ibexa_email` | `string` | +| Name | Internal name | +|----------------|---------------| +| `EmailAddress` | `ibexa_email` | -## PHP API field type +## Field value -### Value object +The field value is the email address as a string, or `null` when the field is empty. -#### Properties - -The `Value` class of this field type contains the following properties: - -| Property | Type | Description | -|----------|----------|-----------------------------------------------------------------------| -| `$email` | `string` | This property is used for the input string provided as email address. | - -``` php -// Value object content example - -use Ibexa\Core\FieldType\EmailAddress\Value; - -// Instantiates an EmailAddress Value object with default value (empty string) -$emailaddressValue = new Value(); - -// Email definition -$emailaddressValue->email = 'someuser@example.com'; -``` - -##### Constructor - -The `EmailAddress\Value` constructor initializes a new value object with the value provided. -It accepts a string as input. - -``` php -// Constructor example - -use Ibexa\Core\FieldType\EmailAddress\Value; - -// Instantiates an EmailAddress Value object -$emailaddressValue = new Value('someuser@example.com'); +``` json +{ + "fieldDefinitionIdentifier": "email", + "languageCode": "eng-GB", + "fieldValue": "someuser@example.com" +} ``` -##### String representation - -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. - -Example: `someuser@example.com` - -### Validation +## Validation -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. +This field type uses a validator to make sure that a valid email address has been provided. +If the validation fails, the request is rejected. -### Settings +## 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 a39315f7e70..711713ab839 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 @@ -12,58 +12,50 @@ 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'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). -Custom field types have to be programmed in PHP. -However, the built-in field types are usually enough for typical scenarios. The following table gives an overview of the supported field types that come with [[= product_name =]]. -## Available field types - -| Field type | Description | Searchable in Legacy Storage engine | Searchable with Solr/Elasticsearch | -|------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|------------------------------------| -| [Address](addressfield.md) | Stores an address. | No | No | -| [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 | -| [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. | Yes, in [Search](customergroupid_criterion.md) and [Price Search](price_customergroup_criterion.md) | Yes | -| [DateAndTime](dateandtimefield.md) | Stores a full date including time information. | Yes | Yes | -| [Date](datefield.md) | Stores date information. | Yes | Yes | -| [EmailAddress](emailaddressfield.md) | Validates and stores an email address. | Yes | Yes | -| [Float](floatfield.md) | Validates and stores a floating-point number. | No | Yes | -| [Form](formfield.md) | Stores a form. | No | Yes | -| [Image](imagefield.md) | Validates and stores an image. | No | Yes | -| [ImageAsset](imageassetfield.md) | Stores images in independent content items of a generic Image content type. | No | Yes | -| [Integer](integerfield.md) | Validates and stores an integer value. | Yes | Yes | -| [ISBN](isbnfield.md) | Handles International Standard Book Number (ISBN) in 10-digit or 13-digit format. | Yes | Yes | -| [Keyword](keywordfield.md) | Stores keywords. | Yes[^1^](#1-note-on-legacy-search-engine) | Yes | -| [MapLocation](maplocationfield.md) | Stores map coordinates. | Yes, with [`MapLocationDistance` Criterion](maplocationdistance_criterion.md) | Yes | -| [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 a pair of range values. | 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 | -| [Page](pagefield.md) | Stores a Page with a layout consisting of multiple zones. | N/A | N/A | -| [ProductSpecification](productspecificationfield.md) | Stores product attributes and VAT | Yes but only with [Product Search](product_search_criteria.md) | Yes | -| [Relation](relationfield.md) | Validates and stores a relation to a content item. | Yes, with both [`Field`](field_criterion.md) and [`FieldRelation`](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 | -| [RichText](richtextfield.md) | Validates and stores structured rich text in XML. | Yes[^1^](#1-note-on-legacy-search-engine) | Yes | -| [Selection](selectionfield.md) | Validates and stores a single selection or multiple choices from a list of options. | Yes[^1^](#1-note-on-legacy-search-engine) | Yes | -| [TaxonomyEntry](taxonomyentryfield.md) | Stores information about the Taxonomy tree. | No | Yes | -| [TaxonomyEntryAssignment](taxonomyentryassignmentfield.md) | Makes content taggable by Taxonomy. | No | Yes | -| [TextBlock](textblockfield.md) | Validates and stores a larger block of text. | Yes[^1^](#1-note-on-legacy-search-engine) | Yes | -| [TextLine](textlinefield.md) | Validates and stores a single line of text. | Yes | Yes | -| [Time](timefield.md) | Stores time information. | Yes | Yes | -| [Url](urlfield.md) | Stores a URL / address. | No | Yes | -| [User](userfield.md) | Validates and stores information about a user. | No | No | +Each field type reference page describes the JSON structure that the REST API returns for a field of that type, and that you send when you create or update it. +The **Internal name** column holds the value that the REST API uses as `fieldTypeIdentifier` in field payloads and as `fieldType` in field definitions. -**^[1]^ Note on Legacy Search Engine** +## Available field types -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). +| Field type | Internal name | Description | Searchable | +|---|---|---|---| +| [Address](addressfield.md) | `ibexa_address` | Stores an address. | No | +| [Author](authorfield.md) | `ibexa_author` | Stores a list of authors, each consisting of author name and author email. | Yes | +| [BinaryFile](binaryfilefield.md) | `ibexa_binaryfile` | Stores a file. | Yes | +| [Checkbox](checkboxfield.md) | `ibexa_boolean` | Stores a boolean value. | Yes | +| [Country](countryfield.md) | `ibexa_country` | Stores country names as a string. | Yes | +| [Customer group](customergroupfield.md) | `ibexa_customer_group` | Stores customer group to which a user belongs. | Yes | +| [DateAndTime](dateandtimefield.md) | `ibexa_datetime` | Stores a full date including time information. | Yes | +| [Date](datefield.md) | `ibexa_date` | Stores date information. | Yes | +| [EmailAddress](emailaddressfield.md) | `ibexa_email` | Validates and stores an email address. | Yes | +| [Float](floatfield.md) | `ibexa_float` | Validates and stores a floating-point number. | Yes | +| [Form](formfield.md) | `ibexa_form` | Stores a form. | Yes | +| [Image](imagefield.md) | `ibexa_image` | Validates and stores an image. | Yes | +| [ImageAsset](imageassetfield.md) | `ibexa_image_asset` | Stores images in independent content items of a generic Image content type. | Yes | +| [Integer](integerfield.md) | `ibexa_integer` | Validates and stores an integer value. | Yes | +| [ISBN](isbnfield.md) | `ibexa_isbn` | Handles International Standard Book Number (ISBN) in 10-digit or 13-digit format. | Yes | +| [Keyword](keywordfield.md) | `ibexa_keyword` | Stores keywords. | Yes | +| [MapLocation](maplocationfield.md) | `ibexa_gmap_location` | Stores map coordinates. | Yes | +| [Matrix](matrixfield.md) | `ibexa_matrix` | Represents and handles a table of rows and columns of data. | No | +| [Measurement](measurementfield.md) | `ibexa_measurement` | Validates and stores a unit of measure, and either a single measurement value, or a pair of range values. | Yes | +| [Media](mediafield.md) | `ibexa_media` | Validates and stores a media file. | Yes | +| [Page](pagefield.md) | `ibexa_landing_page` | Stores a Page with a layout consisting of multiple zones. | N/A | +| [ProductSpecification](productspecificationfield.md) | `ibexa_product_specification` | Stores product attributes and VAT | Yes | +| [Relation](relationfield.md) | `ibexa_object_relation` | Validates and stores a relation to a content item. | Yes | +| [RelationList](relationlistfield.md) | `ibexa_object_relation_list` | Validates and stores a list of relations to content items. | Yes | +| [RichText](richtextfield.md) | `ibexa_richtext` | Validates and stores structured rich text in XML. | Yes | +| [Selection](selectionfield.md) | `ibexa_selection` | Validates and stores a single selection or multiple choices from a list of options. | Yes | +| [TaxonomyEntry](taxonomyentryfield.md) | `ibexa_taxonomy_entry` | Stores information about the Taxonomy tree. | Yes | +| [TaxonomyEntryAssignment](taxonomyentryassignmentfield.md) | `ibexa_taxonomy_entry_assignment` | Makes content taggable by Taxonomy. | Yes | +| [TextBlock](textblockfield.md) | `ibexa_text` | Validates and stores a larger block of text. | Yes | +| [TextLine](textlinefield.md) | `ibexa_string` | Validates and stores a single line of text. | Yes | +| [Time](timefield.md) | `ibexa_time` | Stores time information. | Yes | +| [Url](urlfield.md) | `ibexa_url` | Stores a URL / address. | Yes | +| [User](userfield.md) | `ibexa_user` | Validates and stores information about a user. | No | 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 b8f36d8faaf..eb0710cedba 100644 --- a/docs/content_management/field_types/field_type_reference/floatfield.md +++ b/docs/content_management/field_types/field_type_reference/floatfield.md @@ -2,81 +2,43 @@ This field type stores numeric values which are provided as floats. -| Name | Internal name | Expected input | -|---------|---------------|----------------| -| `Float` | `ibexa_float` | `float` | +| Name | Internal name | +|---------|---------------| +| `Float` | `ibexa_float` | -## PHP API field type +## Field value -### Input expectations +The field value is a number, or `null` when the field is empty. +Both decimal and integer numbers are accepted as input, and numeric strings are cast to a float. -The field type expects a number as input. Both decimal and integer numbers are accepted. - -| Type | Example | -|---------|--------------| -| `float` | `194079.572` | -| `int` | `144` | - -### Value object - -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|----------|---------|---------------------------------------------------------------| -| `$value` | `float` | This property is used to store the value provided as a float. | - -``` php -// Value object content example - -use Ibexa\Core\FieldType\Float\Value as FloatValue; - -// Instantiates a Float Value object -$floatValue = new FloatValue(); - -$floatValue->value = 284.773; +``` json +{ + "fieldDefinitionIdentifier": "weight", + "languageCode": "eng-GB", + "fieldValue": 194079.572 +} ``` -##### Constructor - -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 - -use Ibexa\Core\FieldType\Float\Value as FloatValue; - -// Instantiates a Float Value object -$floatValue = new FloatValue(284.773); -``` - -### Validation +## Validation 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 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 - -/** @var \Ibexa\Contracts\Core\Repository\Repository $repository */ -$contentTypeService = $repository->getContentTypeService(); -$floatFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct('float', 'ibexa_float'); - -// Accept only numbers between 0.1 and 203.99 -$floatFieldCreateStruct->validatorConfiguration = [ - 'FileSizeValidator' => [ - 'minFloatValue' => 0.1, - 'maxFloatValue' => 203.99, - ], -]; +| Name | Type | Default value | Description | +|-----------------|---------|---------------|------------------------------------------------------------| +| `minFloatValue` | `float` | `null` | Minimum value that this field type allows as input. | +| `maxFloatValue` | `float` | `null` | Maximum value that this field type allows as input. | + +``` json +{ + "validatorConfiguration": { + "FloatValueValidator": { + "minFloatValue": 0.0, + "maxFloatValue": 1000.0 + } + } +} ``` -### Settings +## 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 8b9296472b0..ca145f05ef1 100644 --- a/docs/content_management/field_types/field_type_reference/formfield.md +++ b/docs/content_management/field_types/field_type_reference/formfield.md @@ -1,7 +1,3 @@ ---- -edition: experience ---- - # Form field type The Form field type stores a Form consisting of one or more form fields. @@ -10,4 +6,4 @@ The Form field type stores a Form consisting of one or more form fields. |--------|---------------| | `Form` | `ibexa_form` | -For more information about working with Forms, see [Forms](work_with_forms.md). +For more information about working with Forms, see the [Form Builder guide](form_builder_guide.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 f32fcff4530..d046539983b 100644 --- a/docs/content_management/field_types/field_type_reference/imageassetfield.md +++ b/docs/content_management/field_types/field_type_reference/imageassetfield.md @@ -7,101 +7,35 @@ It makes them reusable across system. |--------------|---------------------| | `ImageAsset` | `ibexa_image_asset` | -## Input expectations - -Example array: - -| Type | Description | Example | -|--------------------------------------------------------------|-------------------------------------------------|------------| -| `Ibexa\Core\FieldType\ImageAsset\Value` | Image Asset 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` | - -## Value object - -### Properties - -Value object of `ibexa_image_asset` contains the following properties: - -| Property | Type | Description | -|------------------------|----------|------------------------------------------------------------------| -| `destinationContentId` | `int` | Related content ID. | -| `alternativeText` | `string` | The alternative image text (for example "Picture of an apple."). | - -``` php -/** - * Value object content example. - * - * @var \Ibexa\Core\FieldType\ImageAsset\Value $imageAssetValue - * @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo - */ -$imageAssetValue->destinationContentId = $contentInfo->id; -$imageAssetValue->alternativeText = 'Picture of an apple.'; -``` - -#### Constructor - -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 - -use Ibexa\Core\FieldType\ImageAsset as ImageAsset; - -/** @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo */ -// Instantiates a ImageAsset Value object -$imageAssetValue = new ImageAsset\Value($contentInfo->id, 'Picture of an apple.'); +## Field value + +The field value is an object with the following keys: + +| Key | Type | Description | Example | +|------------------------|-------------------|-------------------------------------------------------------------------------------------------|--------------------------| +| `destinationContentId` | `integer`, `null` | ID of the content item that holds the image asset. | `150` | +| `alternativeText` | `string`, `null` | The alternative image text (for example "Picture of an apple."). | `Picture of an apple.` | +| `variations` | `object` | Available image variations, keyed by variation identifier. Read-only, added by the API on output only. | See below. | + +``` json +{ + "fieldDefinitionIdentifier": "image", + "languageCode": "eng-GB", + "fieldValue": { + "destinationContentId": 150, + "alternativeText": "Picture of an apple.", + "variations": { + "medium": { + "href": "/api/ibexa/v2/content/binary/images/150-345-1/variations/medium" + } + } + } +} ``` -### Validation - -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: - -| Name | Description | Default value | -|----------------------------|----------------------------------------|---------------| -| `content_type_identifier` | Content type used to store assets. | `image` | -| `content_field_identifier` | Field identifier used for asset data. | `image` | -| `name_field_identifier` | Field identifier used for asset name. | `name` | -| `parent_location_id` | Location where the assets are created. | `51` | - -Example configuration: - -``` yaml -ibexa: - system: - default: - fieldtypes: - ibexa_image_asset: - content_type_identifier: photo - content_field_identifier: image - name_field_identifier: title - parent_location_id: 106 -``` - -## 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`: - -```yaml -ibexa: - system: - default: - content_view: - asset_image: - default: - template: ::custom_image_asset_template.html.twig - match: [] -``` +When you create or update a field, provide `destinationContentId` and `alternativeText` only. +Each variation URI returns a `ContentImageVariation`, the same as for the [Image field type](imagefield.md#image-variations). -## Generating image variation from the Image Asset +## Validation -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). +This field type validates if `destinationContentId` points to a content item which has the correct content type. 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 51530e4b91f..c461e005c67 100644 --- a/docs/content_management/field_types/field_type_reference/imagefield.md +++ b/docs/content_management/field_types/field_type_reference/imagefield.md @@ -8,154 +8,140 @@ The Image field type allows you to store an image file. 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 - -### Value object - -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'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. | -| `imageId` | string | `240-1480` | A special image ID, used by REST. | -| `inputUri` | string | `var/storage/images/test/199-2-eng-GB/image.png` | Input image file URI. | -| `width` | int | `960` | Original image width in pixels. | -| `height` | int | `540` | Original image height in pixels. | - -### Settings - -This field type doesn't support settings. - -### Image variations - -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 | `200` | The variation's width in pixels. | -| `height` | int | `112` | The variation's height in pixels. | -| `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. | -| `dirPath` | string | `var/storage/images/test/199-2-eng-GB` | The path to the file. | -| `uri` | string | `var/storage/images/test/199-2-eng-GB/apple.png` | The variation's URI. Complete path with a name of image file. | -| `lastModified` | DateTime | ``"2017-08-282 12:20 Europe/Berlin"`` | When the variation was last modified. | - -### Field Definition options +## Field value + +The field value is an object with the following keys, or `null` when the field is empty: + +| Key | Type | Description | Example | +|-------------------|-----------|-------------------------------------------------------------------------------------------------|-----------------------------------------------| +| `id` | `string` | The image's unique identifier. Usually the path, or a part of the path. | `0/8/4/1/1480-1-eng-GB/image.png` | +| `alternativeText` | `string` | The alternative text, as entered in the field's properties. Optional unless the `AlternativeTextValidator` requires it. | `Picture of an apple.` | +| `fileName` | `string` | The original image's filename, without the path. | `image.png` | +| `fileSize` | `integer` | The original image's size, in bytes. | `37931` | +| `mime` | `string` | The image's MIME type. | `image/png` | +| `uri` | `string` | The original image's URI. | `/var/site/storage/images/0/8/4/1/1480-1-eng-GB/image.png` | +| `imageId` | `string` | Image ID used to address image variations. | `240-1480` | +| `inputUri` | `string` | Input image file URI. | `var/site/storage/images/0/8/4/1/1480-1-eng-GB/image.png` | +| `path` | `string` | Same value as `inputUri`, with a leading slash. | `/var/site/storage/images/0/8/4/1/1480-1-eng-GB/image.png` | +| `width` | `integer` | Original image width in pixels. | `960` | +| `height` | `integer` | Original image height in pixels. | `540` | +| `additionalData` | `object` | Extra information about the image, if available. | `{}` | +| `variations` | `object` | Available image variations, keyed by variation identifier. Read-only, added by the API on output only. | See below. | + +``` json +{ + "id": 1480, + "fieldDefinitionIdentifier": "image", + "languageCode": "eng-GB", + "fieldValue": { + "id": "0/8/4/1/1480-1-eng-GB/image.png", + "alternativeText": "Picture of an apple.", + "fileName": "image.png", + "fileSize": 37931, + "imageId": "240-1480", + "uri": "/var/site/storage/images/0/8/4/1/1480-1-eng-GB/image.png", + "inputUri": "var/site/storage/images/0/8/4/1/1480-1-eng-GB/image.png", + "width": 960, + "height": 540, + "variations": { + "articleimage": { + "href": "/api/ibexa/v2/content/binary/images/240-1480/variations/articleimage" + }, + "articlethumbnail": { + "href": "/api/ibexa/v2/content/binary/images/240-1480/variations/articlethumbnail" + } + } + } +} +``` -The Image field type supports one `FieldDefinition` option: the maximum size for the file. +## Image variations + +For each variation, the field value provides a URI. +Requesting that resource generates the variation if it doesn't exist yet, and returns the variation details as a `ContentImageVariation`: + +``` json +{ + "ContentImageVariation": { + "_media-type": "application/vnd.ibexa.api.ContentImageVariation+json", + "_href": "/api/ibexa/v2/content/binary/images/240-1480/variations/tiny", + "uri": "/var/site/storage/images/0/8/4/1/1480-1-eng-GB/image_tiny.png", + "contentType": "image/png", + "width": 30, + "height": 30, + "fileSize": 1361 + } +} +``` -!!! note +## Creating and updating an Image field - Maximum size is 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. +To send image contents, provide them as a base64-encoded string under the `data` key, together with `fileName`: -## Using an Image field - -To read more about handling images and image variations, see the [Images documentation](images.md). - -### With the REST API - -Image Fields within REST are exposed by the `application/vnd.ibexa.api.Content` media-type. -An Image field looks like this: - -``` xml - - 1480 - image - eng-GB - - /var/ezdemo_site/storage/images/0/8/4/1/1480-1-eng-GB/kidding.png - - kidding.png - 37931 - 240-1480 - /var/ezdemo_site/storage/images/0/8/4/1/1480-1-eng-GB/kidding.png - - - /api/ibexa/v2/content/binary/images/240-1480/variations/articleimage - - - /api/ibexa/v2/content/binary/images/240-1480/variations/articlethumbnail - - - - +``` json +{ + "fieldDefinitionIdentifier": "image", + "languageCode": "eng-GB", + "fieldValue": { + "fileName": "rest-rocks.jpg", + "alternativeText": "HTTP", + "data": "/9j/4AAQSkZJRgABAQEAZABkAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcG..." + } +} ``` -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 - - /var/ezdemo_site/storage/images/0/8/4/1/1480-1-eng-GB/kidding_tiny.png - image/png - 30 - 30 - 1361 - +Updating an Image field requires that you re-send the existing data. +You can do this by reusing the field value you read from the API, **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. + +``` json +{ + "fieldDefinitionIdentifier": "image", + "languageCode": "eng-GB", + "fieldValue": { + "id": "media/images/507-1-eng-GB/Existing-image.png", + "alternativeText": "Updated alternative text", + "fileName": "Updated-filename.png" + } +} ``` -### 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. - -#### Creating an Image field - -```xml - - - - - - - 247 - image - eng-GB - - rest-rocks.jpg - HTTP - - - - - +## Validation + +The field type supports the following validators: + +| Name | Type | Default value | Description | +|-----------------------------------------|-----------|---------------|------------------------------------------------------| +| `FileSizeValidator[maxFileSize]` | `numeric` | `null` | Maximum size of the image file in bytes. | +| `AlternativeTextValidator[required]` | `boolean` | `false` | When `true`, the `alternativeText` key is required. | + +``` json +{ + "validatorConfiguration": { + "FileSizeValidator": { + "maxFileSize": 10485760 + }, + "AlternativeTextValidator": { + "required": true + } + } +} ``` -### Updating an Image field +## Settings -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. +| Name | Type | Default value | Description | +|-------------|---------|---------------|-------------------------------------------------------------------------------------| +| `mimeTypes` | `array` | `[]` | MIME types accepted by the field. When empty, all image MIME types are accepted. | -``` xml - - - - - 247 - image - eng-GB - - media/images/507-1-eng-GB/Existing-image.png - Updated alternative text - Updated-filename.png - - - - +``` json +{ + "fieldSettings": { + "mimeTypes": ["image/jpeg", "image/png"] + } +} ``` + +## Using an Image field + +To read more about handling images, see the [Images documentation](images.md). 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 13155143136..f78f80bd93c 100644 --- a/docs/content_management/field_types/field_type_reference/integerfield.md +++ b/docs/content_management/field_types/field_type_reference/integerfield.md @@ -2,76 +2,42 @@ This field type represents an integer value. -| Name | Internal name | Expected input | -|-----------|-----------------|----------------| -| `Integer` | `ibexa_integer` | `integer` | +| Name | Internal name | +|-----------|-----------------| +| `Integer` | `ibexa_integer` | -## PHP API field type +## Field value -### Input expectations +The field value is an integer, or `null` when the field is empty. -| Type | Example | -|-----------|---------| -| `integer` | `2397` | - -### Value object - -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description| -|----------|-------|------------| -| `$value` | `int` | This property is used to store the value provided as an integer. | - -``` php -// Value object content example -/** @var \Ibexa\Core\FieldType\Integer\Value $integer */ -$integer->value = 8; -``` - -#### Constructor - -The `Integer\Value` constructor initializes a new value object with the value provided. -It expects a numeric, integer value. - -``` php -// Constructor example -use Ibexa\Core\FieldType\Integer; - -// Instantiates a Integer Value object -$integerValue = new Integer\Value(8); +``` json +{ + "fieldDefinitionIdentifier": "quantity", + "languageCode": "eng-GB", + "fieldValue": 2397 +} ``` -#### Hash format - -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 returns the integer value as a string. - -Example: `"8"` - -### Validation +## Validation -This field type supports `IntegerValueValidator`, defining maximum and minimum float value: +This field type supports `IntegerValueValidator`, defining maximum and minimum integer value: -|Name|Type|Default value|Description| -|------|------|------|------| -|`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.| +| Name | Type | Default value | Description | +|-------------------|-----------|---------------|--------------------------------------------------------------| +| `minIntegerValue` | `integer` | `null` | Minimum value that this field type allows as input. | +| `maxIntegerValue` | `integer` | `null` | Maximum value that this field type allows as input. | -``` php -// Example of validator configuration in PHP -$validatorConfiguration = [ - 'minIntegerValue' => 1, - 'maxIntegerValue' => 24, -]; +``` json +{ + "validatorConfiguration": { + "IntegerValueValidator": { + "minIntegerValue": 0, + "maxIntegerValue": 100 + } + } +} ``` -### Settings +## 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 57cd27dd50b..0a24fd41043 100644 --- a/docs/content_management/field_types/field_type_reference/isbnfield.md +++ b/docs/content_management/field_types/field_type_reference/isbnfield.md @@ -2,38 +2,38 @@ This field type represents an ISBN string either an ISBN-10 or ISBN-13 format. -| Name | Internal name | Expected input type | -|--------|---------------|---------------------| -| `ISBN` | `ibexa_isbn` | `string` | +| Name | Internal name | +|--------|---------------| +| `ISBN` | `ibexa_isbn` | -## PHP API field type +## Field value -### Value object +The field value is the ISBN as a string, or `null` when the field is empty. -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|----------|----------|--------------------------------------------| -| `$isbn` | `string` | This property is used for the ISBN string. | - -#### String representation +``` json +{ + "fieldDefinitionIdentifier": "isbn", + "languageCode": "eng-GB", + "fieldValue": "9783161484100" +} +``` -An ISBN's string representation is the `$isbn` property's value, as a string. +## Validation -#### Constructor +The input is validated as an ISBN-13 or ISBN-10 number, depending on the `isISBN13` field definition setting. -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. +## Settings -### Validation +The field definition of this field type can be configured with a single option: -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: +| Name | Type | Default value | Description | +|------------|-----------|---------------|--------------------------------------------------------------------------------| +| `isISBN13` | `boolean` | `true` | When `true`, input is validated as ISBN-13, otherwise it's validated as ISBN-10. | -``` php -[ - 'isISBN13' => true, -]; +``` json +{ + "fieldSettings": { + "isISBN13": true + } +} ``` 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 a46f8bb6775..454f13ff687 100644 --- a/docs/content_management/field_types/field_type_reference/keywordfield.md +++ b/docs/content_management/field_types/field_type_reference/keywordfield.md @@ -1,56 +1,19 @@ # 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 keywords. -| Name | Internal name | Expected input | -|-----------|-----------------|------------------------| -| `Keyword` | `ibexa_keyword` | `string[]` or `string` | +| Name | Internal name | +|-----------|-----------------| +| `Keyword` | `ibexa_keyword` | -## PHP API field type +## Field value -### Input expectations +The field value is an array of keywords, each one a string. -| Type | Example | -|------------|-----------------------------------------------------------| -| `string` | `"documentation"` | -| `string` | `"php, Ibexa Platform, html5"` | -| `string[]` | `[ "Ibexa", "Enterprise", "User Experience Management" ]` | - -### Value object - -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|-----------|------------|----------------------------------------| -| `$values` | `string[]` | Holds an array of keywords as strings. | - -``` php -// Value object content example -use Ibexa\Core\FieldType\Keyword\Value; - -// Instantiates a Value object -$keywordValue = new Value(); - -// Sets an array of keywords as a value -$keywordValue->values = ['php', 'css3', 'html5', 'Ibexa Platform']; -``` - -#### Constructor - -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. - -``` php -// Constructor example -use Ibexa\Core\FieldType\Keyword\Value; - -// Instantiates a Value object with an array of keywords -$keywordValue = new Value(['php5', 'css3', 'html5']); - -// Instantiates a Value object with a list of keywords in a string -// This is equivalent to the example above -$keywordValue = new Value('php5,css3,html5'); +``` json +{ + "fieldDefinitionIdentifier": "tags", + "languageCode": "eng-GB", + "fieldValue": ["Ibexa", "Enterprise", "User Experience Management"] +} ``` 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 a655f069c83..33dd73c92f2 100644 --- a/docs/content_management/field_types/field_type_reference/maplocationfield.md +++ b/docs/content_management/field_types/field_type_reference/maplocationfield.md @@ -2,50 +2,28 @@ This field type represents a geographical location. -As input it expects three values: - -- two float values latitude and longitude, -- a string value, corresponding to the name or address of the location. - -| Name | Internal name | Expected input | -|---------------|-----------------------|----------------| -| `MapLocation` | `ibexa_gmap_location` | `mixed` | - -## PHP API field type - -### Input expectations - -| Type | Example | -|---------|---------------------------------------------------------------------------------------| -| `array` | `[ 'latitude' => 59.928732, 'longitude' => 10.777888, 'address' => "Ibexa Nordics" ]` | - -### Value object - -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|--------------|----------|-------------------------------------------------------------------------| -| `$latitude` | `float` | This property stores the latitude value of the map location reference. | -| `$longitude` | `float` | This property stores the longitude value of the map location reference. | -| `$address` | `string` | This property stores the address of map location. | - -#### Constructor - -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 -use Ibexa\Core\FieldType\MapLocation as MapLocation; - -// Instantiates a MapLocation Value object -$MapLocationValue = new MapLocation\Value( - [ - 'latitude' => 59.928732, - 'longitude' => 10.777888, - 'address' => 'Ibexa Nordics', - ] -); +| Name | Internal name | +|---------------|-----------------------| +| `MapLocation` | `ibexa_gmap_location` | + +## Field value + +The field value is an object with the following keys, or `null` when the field is empty: + +| Key | Type | Description | Example | +|-------------|----------|------------------------------------------|-----------------| +| `latitude` | `float` | Latitude of the map location reference. | `59.928732` | +| `longitude` | `float` | Longitude of the map location reference. | `10.777888` | +| `address` | `string` | Address of the map location. | `Ibexa Nordics` | + +``` json +{ + "fieldDefinitionIdentifier": "location", + "languageCode": "eng-GB", + "fieldValue": { + "latitude": 59.928732, + "longitude": 10.777888, + "address": "Ibexa Nordics" + } +} ``` 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 276ffb56845..34ed88c453d 100644 --- a/docs/content_management/field_types/field_type_reference/matrixfield.md +++ b/docs/content_management/field_types/field_type_reference/matrixfield.md @@ -2,213 +2,63 @@ This field represents and handles a table of rows and columns of data. -| Name | Internal name | Expected input | -|----------|----------------|----------------| -| `Matrix` | `ibexa_matrix` | `array` | +| Name | Internal name | +|----------|----------------| +| `Matrix` | `ibexa_matrix` | -The Matrix field type is available via the Matrix Bundle provided by the [ibexa/fieldtype-matrix](https://github.com/ibexa/fieldtype-matrix) package. +## Field value -## PHP API field type +The field value is an object with a single `entries` key, holding an array of rows. +Each row is an object that maps the column identifiers defined in the field definition to cell values. -### Input expectations - -| Type | Description | Example | -|---------|----------------------------------------------------------------------------------------|-----------| -| `array` | array of `Ibexa\FieldTypeMatrix\FieldType\Value\Row` objects which contain column data | see below | - -Example of input: - -``` php -use Ibexa\FieldTypeMatrix\FieldType; - -new FieldType\Value([ - new FieldType\Value\Row(['col1' => 'Row 1, Col 1', 'col2' => 'Row 1, Col 2']), - new FieldType\Value\Row(['col1' => 'Row 2, Col 1', 'col2' => 'Row 2, Col 2']), - new FieldType\Value\Row(['col1' => 'Row 3, Col 1', 'col2' => 'Row 3, Col 2']), -]); -``` - -### Value object - -`Ibexa\FieldTypeMatrix\FieldType\Value` offers the following properties: - -|Property|Type|Description| -|------|------|------| -|`rows`|`RowsCollection`|Array of `Row` objects containing an array of cells (`Row::getCells()` returns array `['col1' => 'Value 1', /* ... */]`).| - -### Validation - -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. - -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 doesn't validate if `Minimum number of rows` is set to 3, because the second row is empty: - -``` php -use Ibexa\FieldTypeMatrix\FieldType; - -new FieldType\Value([ - new FieldType\Value\Row(['col1' => 'Row 1, Col 1', 'col2' => 'Row 1, Col 2']), - new FieldType\Value\Row(['col1' => '', 'col2' => '']), - new FieldType\Value\Row(['col1' => 'Row 3, Col 1', 'col2' => 'Row 3, Col 2']), -]); -``` - -## GraphQL field type operations - -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: - -- `{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: - -- `name`: `ibexa_string` -- `ingredients`: `ibexa_matrix` with two columns: `ingredient` and `quantity` - -```graphql -{ - content { - recipe(id: 123) { - name - ingredients { - ingredient - quantity - } - } - } -} -``` - -The Type returned for the Matrix field exposes columns defined in the field definition: - -```json +``` json { - "data": { - "content": { - "recipe": { - "name": "Cake ingredients", - "ingredients": [ - { - "ingredient": "Butter", - "quantity": "200 grams" - }, - { - "ingredient": "Sugar", - "quantity": "100 grams" - } + "fieldDefinitionIdentifier": "specification", + "languageCode": "eng-GB", + "fieldValue": { + "entries": [ + { + "col1": "Value 1", + "col2": "Value 2" + }, + { + "col1": "Value 3", + "col2": "Value 4" + } ] - } } - } } ``` -### Query for the field type and field definition's details +## Validation -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. - -```graphql -{ - content { - _types { - recipe { - ingredients { - settings { - minimumRows - columns { - name - identifier - } - } - } - } - } - } -} -``` +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. -The response lists the exposed field type settings: +If, after removing empty rows, the number of rows doesn't fulfill the configured `minimum_rows` setting, the field doesn't validate. -- minimumRows -- columns - - name - - identifier +## Settings -Example response: +| Name | Type | Default value | Description | +|----------------|-----------|---------------|-----------------------------------------------------------------------------------| +| `minimum_rows` | `integer` | `1` | Minimum number of rows that the field must contain. | +| `columns` | `array` | `[]` | Definitions of the columns, each with a unique `identifier` and a `name`. | -```json +``` json { - "data": { - "content": { - "_types": { - "recipe": { - "ingredients": { - "settings": { - "minimumRows": 1, - "columns": [ - { - "name": "ingredient", - "identifier": "ingredient" - }, - { - "name": "quantity", - "identifier": "quantity" - } - ] + "fieldSettings": { + "minimum_rows": 1, + "columns": [ + { + "identifier": "col1", + "name": "Column 1" + }, + { + "identifier": "col2", + "name": "Column 2" } - } - } - } - } - } -} -``` - -### 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: - -- `{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: - -- `name`: `"Cake Ingredient List"` -- `ingredients`: `ibexa_matrix` with two columns: `ingredient` and `quantity` - -```graphql - mutation AddRecipe { - createRecipe( - language: eng_GB - parentLocationId: 2, - input: { - name: "Cake Ingredient List", - ingredients: [ - {ingredient: "sugar", quantity: "100 grams"} - {ingredient: "butter", quantity: "200 grams"} - ] - } - ) { - name - } -} -``` - -The response confirms creation of the new Recipe field: - -```json -{ - "data": { - "createRecipe": { - "name": "Cake Ingredient List" + ] } - } } ``` 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 4ac2170dac0..7d1b3b35b5a 100644 --- a/docs/content_management/field_types/field_type_reference/measurementfield.md +++ b/docs/content_management/field_types/field_type_reference/measurementfield.md @@ -3,142 +3,89 @@ The Measurement field type represents measurement information. It stores the unit of measure, and either a single measurement value, or a pair of top and bottom values that defines a range. -| Name | Internal name | Expected input type | -|---------------|---------------------|----------------------------------------------------| -| `Measurement` | `ibexa_measurement` | `Ibexa\Contracts\Measurement\Value\ValueInterface` | - -## PHP API field type - -### Input expectations - -To create a value, you use a service that implements `Ibexa\Contracts\Measurement\MeasurementServiceInterface`. -You must inject the service directly with [dependency injection](php_api.md#service-container). -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: - -| Type | Example | -|---------------------------------------------------------|----------------------------------------------------------------------| -|`\Ibexa\Contracts\Measurement\Value\SimpleValueInterface`| `$measurementService->buildSimpleValue('length', 2.5, 'centimeter')` | -|`\Ibexa\Contracts\Measurement\Value\RangeValueInterface` | `$measurementService->buildRangeValue('length', 1.2, 4.5, 'inch')` | - -### Value object - -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|----------|----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `$value` | `Ibexa\Contracts\Measurement\Value\ValueInterface` | Stores the Measurement API Value, which can be either an instance of `Ibexa\Contracts\Measurement\Value\SimpleValueInterface` or `Ibexa\Contracts\Measurement\Value\RangeValueInterface`. | - -#### Constructor - -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: - -``` php -// Simple input (single value) example - -use Ibexa\Measurement\FieldType\MeasurementValue; - -/** @var \Ibexa\Contracts\Measurement\MeasurementServiceInterface $measurementService */ - -// Instantiates a Measurement Value object -$measurementValue = new MeasurementValue( - $measurementService->buildSimpleValue( - 'length', - 13.5, - 'centimeter' - ) -); +| Name | Internal name | +|---------------|---------------------| +| `Measurement` | `ibexa_measurement` | + +## Field value + +The field value is an object, or `null` when the field is empty. +Its shape depends on the `inputType` key: + +| Key | Type | Description | Example | +|--------------------------------|-----------|---------------------------------------------------------------------------|--------------| +| `measurementType` | `string` | Type of measurement, for example `length` or `mass`. | `length` | +| `measurementUnit` | `string` | Identifier of the unit of measure, for example `centimeter`. | `centimeter` | +| `inputType` | `integer` | `0` for a single value, `1` for a range. | `0` | +| `value` | `float` | The measurement value. Used when `inputType` is `0`. | `2.5` | +| `measurementRangeMinimumValue` | `float` | Bottom value of the range. Used when `inputType` is `1`. | `1.2` | +| `measurementRangeMaximumValue` | `float` | Top value of the range. Used when `inputType` is `1`. | `4.5` | + +A single value: + +``` json +{ + "fieldDefinitionIdentifier": "length", + "languageCode": "eng-GB", + "fieldValue": { + "measurementType": "length", + "measurementUnit": "centimeter", + "value": 2.5, + "inputType": 0 + } +} ``` -``` php -// Range input value example - -use Ibexa\Measurement\FieldType\MeasurementValue; - -/** @var \Ibexa\Contracts\Measurement\MeasurementServiceInterface $measurementService */ - -// Instantiates a Measurement Value object -$measurementValue = new MeasurementValue( - $measurementService->buildRangeValue( - 'volume', - 0.5, - 0.7, - 'liter' - ) -); +A range: + +``` json +{ + "fieldDefinitionIdentifier": "length", + "languageCode": "eng-GB", + "fieldValue": { + "measurementType": "length", + "measurementUnit": "inch", + "measurementRangeMinimumValue": 1.2, + "measurementRangeMaximumValue": 4.5, + "inputType": 1 + } +} ``` -### 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. - -### 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. -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): - -```yaml -ibexa_measurement: - types: - speed: - knot: { symbol: kt } - revolutions per minute: { symbol: RPM } - -ibexa: - system: - default: - measurement: - types: - speed: - - revolutions per minute +## Measurement types and units + +The following measurement types are available: `length`, `area`, `mass`, `pressure`, `speed`, `temperature`, `time`, `volume`, `datatransferrate`, and `energy`. +Each type comes with a set of units, for example `meter`, `centimeter`, `millimeter`, `foot`, `inch`, and `yard` for `length`. + +## Validation + +The field type validates the measurement type and unit passed in the value against the list of supported ones. + +The field type supports `MeasurementValidator`, which constrains what the field accepts: + +| Name | Type | Default value | Description | +|----------------------------|-----------|---------------|-------------------------------------------------------------------| +| `measurementType` | `string` | `null` | The only measurement type accepted by the field. | +| `measurementUnit` | `string` | `null` | The only unit of measure accepted by the field. | +| `inputType` | `integer` | `null` | `0` to accept a single value only, `1` to accept a range only. | +| `sign` | `string` | `null` | Comparison operator applied to `minimum` and `maximum`. | +| `minimum` | `float` | `null` | Minimum accepted value. | +| `maximum` | `float` | `null` | Maximum accepted value. | +| `defaultValue` | `float` | `null` | Default single value. | +| `defaultRangeMinimumValue` | `float` | `null` | Default bottom value of the range. | +| `defaultRangeMaximumValue` | `float` | `null` | Default top value of the range. | + +``` json +{ + "validatorConfiguration": { + "MeasurementValidator": { + "measurementType": "length", + "measurementUnit": "centimeter", + "inputType": 0, + "minimum": 0.0, + "maximum": 100.0 + } + } +} ``` -To add a new Measurement type with its own new units, add the following lines to your YAML configuration: - -```yaml hl_lines="4" -ibexa_measurement: - types: - my_type: - my_unit: { symbol: my, is_base_unit: true } -ibexa: - system: - default: - measurement: - types: - my_type: - - my_unit -``` - -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. - -Next, you need to define how the new unit should be converted under the `ibexa.system..ibexa_measurement` [configuration key](configuration.md#configuration-files): - -```yaml -ibexa_measurement: - conversion: - formulas: - - { source_unit: foo, target_unit: bar, formula: 'value / 100' } - types: - length: - foo: { symbol: foo } - bar: { symbol: bar } -``` - -!!! tip - - The `target_unit` must be an existing unit, for example meter, otherwise the conversion results in an error. 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 d29074113ef..689bbcfbd30 100644 --- a/docs/content_management/field_types/field_type_reference/mediafield.md +++ b/docs/content_management/field_types/field_type_reference/mediafield.md @@ -12,113 +12,95 @@ It's capable of handling the following types of files: - HTML5 Video - HTML5 Audio -| Name | Internal name | Expected input | -|---------|---------------|----------------| -| `Media` | `ibexa_media` | mixed | - -## 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. | - -### Value object - -#### Properties - -`Ibexa\Core\FieldType\Media\Value` offers the following properties. - -Both `Media` and `BinaryFile` Value and Type inherit from the `BinaryBase` abstract field type and share common properties. - -| Property | Type | Description | Example | -|-----------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| -| `id` | string | Media 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/63cd472dd7819da7b75e8e2fee507c68.mp4 | -| `fileName` | string | The human-readable file name, as exposed to the outside. Used to name the file when sending it for download. | butterflies.mp4 | -| `fileSize` | int | File size, in bytes. | 1077923 | -| `mimeType` | string | The file's MIME type. | video/mp4 | -| `uri` | string | The binary file's HTTP URI. If the URI doesn't include a host or protocol, it applies to the request domain. **The URI is not publicly readable, and must NOT be used to link to the file for download.** Use `ibexa_render_field` to generate a valid link to the download controller. | /var/ezdemo_site/storage/original/application/63cd472dd7819da7b75e8e2fee507c68.mp4 | -| `hasController` | boolean | Whether the media has a controller when being displayed. | true | -| `autoplay` | boolean | Whether the media should be automatically played. | true | -| `loop` | boolean | Whether the media should be played in a loop. | false | -| `height` | int | Height of the media. | 300 | -| `width` | int | Width of the media. | 400 | -| `path` | string | **deprecated** | | - -### Hash format - -The hash format mostly matches the value object. It has the following keys: - -- `id` -- `path` (for backwards compatibility) -- `fileName` -- `fileSize` -- `mimeType` -- `uri` -- `hasController` -- `autoplay` -- `loop` -- `height` -- `width` - -### Validation - -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 +| Name | Internal name | +|---------|---------------| +| `Media` | `ibexa_media` | + +## Field value + +The field value is an object with the following keys, or `null` when the field is empty: + +| Key | Type | Description | Example | +|-----------------|-----------|----------------------------------------------------------------------------|----------------------------------| +| `id` | `string` | Media file identifier. | `application/63cd472dd7.mp4` | +| `fileName` | `string` | The human-readable file name, as exposed to the outside. Used to name the file when sending it for download. | `butterflies.mp4` | +| `fileSize` | `integer` | File size, in bytes. | `1077923` | +| `mimeType` | `string` | The file's MIME type. | `video/mp4` | +| `uri` | `string` | Download URL of the media file. If it doesn't include a host or protocol, it applies to the request domain. See [Binary and Media download](binary_and_media_download.md). | `/content/download/210/media/butterflies.mp4` | +| `hasController` | `boolean` | Whether the media has a controller when being displayed. | `true` | +| `autoplay` | `boolean` | Whether the media should be automatically played. | `true` | +| `loop` | `boolean` | Whether the media should be played in a loop. | `false` | +| `height` | `integer` | Height of the media. | `300` | +| `width` | `integer` | Width of the media. | `400` | +| `inputUri` | `string` | Internal storage path of the file. Read-only on output. | `var/site/storage/original/application/63cd472dd7.mp4` | +| `path` | `string` | Same value as `inputUri`. Kept for backward compatibility. | See `inputUri`. | + +``` json +{ + "fieldDefinitionIdentifier": "media", + "languageCode": "eng-GB", + "fieldValue": { + "id": "application/63cd472dd7.mp4", + "fileName": "butterflies.mp4", + "fileSize": 1077923, + "mimeType": "video/mp4", + "uri": "/content/download/210/media/butterflies.mp4", + "hasController": true, + "autoplay": false, + "loop": false, + "width": 400, + "height": 300 + } +} +``` -use Ibexa\Core\FieldType\Media\Type; +### Uploading a file -/** @var \Ibexa\Contracts\Core\Repository\Repository $repository */ -$contentTypeService = $repository->getContentTypeService(); -$mediaFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct('media', 'ibexa_media'); +To send file contents, provide them as a base64-encoded string under the `data` key, together with `fileName`: -// Setting maximum file size to 5 megabytes -$mediaFieldCreateStruct->validatorConfiguration = [ - 'FileSizeValidator' => [ - 'maxFileSize' => 5 * 1024 * 1024, - ], -]; +``` json +{ + "fieldDefinitionIdentifier": "media", + "languageCode": "eng-GB", + "fieldValue": { + "fileName": "butterflies.mp4", + "data": "AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQ..." + } +} ``` -### Settings - -The field type supports the `mediaType` setting, defining how the media file should be handled in output. +To keep the existing file while updating other keys, send the field value without the `data` key. -| Name | Type | Default value | Description | -|-------------|-------|--------------------------|-------------------------------------------------------------| -| `mediaType` | mixed | `Type::TYPE_HTML5_VIDEO` | Type of the media, accepts one of the predefined constants. | +## Validation -List of all available `mediaType` constants is defined in the `Ibexa\Core\FieldType\Media\Type` class: +The field type supports `FileSizeValidator`, defining the maximum size of the media file in bytes: -| Name | Description | -|---------------------|-------------------------| -| `TYPE_FLASH` | Adobe Flash | -| `TYPE_QUICKTIME` | Apple QuickTime | -| `TYPE_REALPLAYER` | Real Media | -| `TYPE_SILVERLIGHT` | Silverlight | -| `TYPE_WINDOWSMEDIA` | Microsoft Windows Media | -| `TYPE_HTML5_VIDEO` | HTML5 Video | -| `TYPE_HTML5_AUDIO` | HTML5 Audio | +| Name | Type | Default value | Description | +|---------------|-----------|---------------|--------------------------------------| +| `maxFileSize` | `integer` | `null` | Maximum size of the file in bytes. | -``` php -// Example of using Media field type settings in PHP +## Settings -use Ibexa\Core\FieldType\Media\Type; - -/** @var \Ibexa\Contracts\Core\Repository\Repository $repository */ -$contentTypeService = $repository->getContentTypeService(); -$mediaFieldCreateStruct = $contentTypeService->newFieldDefinitionCreateStruct('media', 'ibexa_media'); +The field type supports the `mediaType` setting, defining how the media file should be handled in output. -// Setting Adobe Flash as the media type -$mediaFieldCreateStruct->fieldSettings = [ - 'mediaType' => Type::TYPE_FLASH, -]; +| Name | Type | Default value | Description | +|-------------|----------|----------------------|--------------------------------------------| +| `mediaType` | `string` | `"TYPE_HTML5_VIDEO"` | Type of the media. See the values below. | + +| Value | Description | +|-----------------------|-------------------------| +| `"TYPE_FLASH"` | Adobe Flash | +| `"TYPE_QUICKTIME"` | Apple QuickTime | +| `"TYPE_REALPLAYER"` | Real Media | +| `"TYPE_SILVERLIGHT"` | Silverlight | +| `"TYPE_WINDOWSMEDIA"` | Microsoft Windows Media | +| `"TYPE_HTML5_VIDEO"` | HTML5 Video | +| `"TYPE_HTML5_AUDIO"` | HTML5 Audio | + +``` json +{ + "fieldSettings": { + "mediaType": "TYPE_HTML5_VIDEO" + } +} ``` diff --git a/docs/content_management/field_types/field_type_reference/nullfield.md b/docs/content_management/field_types/field_type_reference/nullfield.md deleted file mode 100644 index d00fe4bbfdf..00000000000 --- a/docs/content_management/field_types/field_type_reference/nullfield.md +++ /dev/null @@ -1,39 +0,0 @@ -# Null field type - -This field type is used as fallback for migration scenarios, and for testing purposes. - -| Name | Internal name | Expected input type | -|--------|---------------|---------------------| -| `Null` | (variable) | mixed | - -## Description - -The Null field type aids 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 accepts anything provided as a value and is usually combined with: - -- 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 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 - -The following example shows how an `example` field type could be configured as a Null field type: - -``` yaml -# Null Fieldtype example configuration -services: - ibexa.field_type.example: - class: Ibexa\Core\FieldType\Null\Type - arguments: [example] - tags: [{name: ibexa.field_type, alias: example}] - ibexa.field_type.example.converter: - class: Ibexa\Core\Persistence\Legacy\Content\FieldValue\Converter\NullConverter - tags: [{name: ibexa.field_type.storage.legacy.converter, alias: example}] - ibexa.field_type.example.indexable: - class: Ibexa\Core\FieldType\Unindexed - tags: [{name: ibexa.field_type.indexable, alias: example}] -``` 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 2e0a43e7331..6a9386d17c0 100644 --- a/docs/content_management/field_types/field_type_reference/pagefield.md +++ b/docs/content_management/field_types/field_type_reference/pagefield.md @@ -1,17 +1,19 @@ ---- -edition: experience ---- - # 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 is only used in the page content type that is included in [[= product_name_exp =]]. -| Name | Internal name | Expected input | -|---------------|----------------------|-----------------| -| `LandingPage` | `ibexa_landing_page` | `string` (JSON) | +| Name | Internal name | +|---------------|----------------------| +| `LandingPage` | `ibexa_landing_page` | + +## Field value + +The field value is an object holding the serialized page structure: the layout identifier, the zones of that layout, and the blocks placed in each zone. +Its exact shape depends on the layout and on the [page blocks](page_blocks.md) used. + +Pages are normally built with Page Builder rather than assembled by hand. !!! caution "Page Builder" @@ -19,56 +21,3 @@ Page field type is only used in the page content type that is included in [[= pr This is caused by `ibexa_user` 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. - -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). - -## Blocks - -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 - -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 (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. - -To render a block inside the layout, use the Twig [`render_esi()`]([[= symfony_doc =]]/reference/twig_reference.html#render-esi) function to call `Ibexa\\Bundle\\FieldTypePage\\Controller\\BlockController::renderAction`. - -The `renderAction` has the following parameters: - -| Parameter | Description | -|----------------|----------------------------------------------------------------------------------| -| `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. | - -If your block needs to be dependent on query parameters like "page" and you already configured your custom block with a [`cacheable_query_params configuration`](page_blocks.md#block-configuration), pass `ibexa_append_cacheable_query_params(block)` as the third argument to the [`controller()` Twig function]([[= symfony_doc =]]/reference/twig_reference.html#controller) so that the HTTP cache can vary based on those query parameters. - -In a fresh installation, the feature is only used by the back office's [Dashboard blocks]([[= user_doc =]]/getting_started/dashboard/dashboard_block_reference/): "My content" and "Review queue". - -Example usage: - -``` html+twig -{{ render_esi(controller('Ibexa\\Bundle\\FieldTypePage\\Controller\\BlockController::renderAction', { - 'locationId': locationId, - 'blockId': block.id, - 'versionNo': versionInfo.versionNo, - 'languageCode': field.languageCode -}, ibexa_append_cacheable_query_params(block))) }} -``` - -As a whole a sample layout could look as follows: - -``` html+twig -[[= include_file('code_samples/page/pagefield_layout.html.twig') =]] -``` diff --git a/docs/content_management/field_types/field_type_reference/productspecificationfield.md b/docs/content_management/field_types/field_type_reference/productspecificationfield.md index ddea872a1b2..e8d00bd110b 100644 --- a/docs/content_management/field_types/field_type_reference/productspecificationfield.md +++ b/docs/content_management/field_types/field_type_reference/productspecificationfield.md @@ -1,16 +1,16 @@ --- -edition: headless month_change: false --- # Product specification field type -This field represents and handles [product attributes](products.md#product-attributes) and [VAT](prices.md#vat). +This field represents and handles [product attributes](products.md#product-attributes) and VAT. Consider it as internal to the [product catalog](product_catalog.md). -| Name | Internal name | Expected input | -|------------------------|-------------------------------|----------------| -| `ProductSpecification` | `ibexa_product_specification` | mixed | +| Name | Internal name | +|------------------------|-------------------------------| +| `ProductSpecification` | `ibexa_product_specification` | + !!! caution 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 78be9fe561c..aff08731475 100644 --- a/docs/content_management/field_types/field_type_reference/relationfield.md +++ b/docs/content_management/field_types/field_type_reference/relationfield.md @@ -2,74 +2,55 @@ 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` | `ibexa_object_relation` | mixed | - -## PHP API field type - -### Input expectations - -| Type | Example | -|-----------|---------| -| `string` | `"150"` | -| `integer` | `150` | - -### Value object - -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|------------------------|-----------------------------|-------------------------------------------------------------------------------------------| -| `$destinationContentId` | `string`, `int`, or `null` | This property is used to store the value provided, which represents the related content. | - -``` php -/** - * Value object content example. - * - * @var \Ibexa\Core\FieldType\Relation\Value $relation - * @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo - */ -$relation->destinationContentId = $contentInfo->id; -``` - -#### Constructor - -The `Relation\Value` constructor initializes a new value object with the value provided. It expects a mixed value. - -``` php -// Constructor example -use Ibexa\Core\FieldType\Relation as Relation; - -/** @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo */ -// Instantiates a Relation Value object -$relationValue = new Relation\Value($contentInfo->id); +| Name | Internal name | +|------------|-------------------------| +| `Relation` | `ibexa_object_relation` | + +## Field value + +The field value is an object with the following keys: + +| Key | Type | Description | Example | +|--------------------------|-------------------|-----------------------------------------------------------------------------------|----------------------------------| +| `destinationContentId` | `integer`, `null` | ID of the related content item. | `14` | +| `destinationContentHref` | `string` | REST URI of the related content item. Read-only, added by the API on output only. | `/api/ibexa/v2/content/objects/14` | + +``` json +{ + "fieldDefinitionIdentifier": "sales_rep", + "languageCode": "eng-GB", + "fieldValue": { + "destinationContentId": 14, + "destinationContentHref": "/api/ibexa/v2/content/objects/14" + } +} ``` -### Validation +When you create or update a field, provide `destinationContentId` only. -This field type validates whether the provided relation exists, but before that it checks that the value is either a string or an int. +## Validation -### Settings +This field type validates whether the provided relation exists. -The field definition of this field type can be configured with three options: +## Settings -| Name | Type | Default value | Description | -|-------------------------|----------|-----------------------------------|--------------------------------------------------------------------------------| -| `selectionMethod` | `int` | `Relation\Type::SELECTION_BROWSE` | *This setting is not implemented yet, only one selection method is available.* | -| `selectionRoot` | `string` | `null` | This setting defines the selection root. | -| `selectionContentTypes` | `array` | `[]` | An array of content type IDs that are allowed for related Content. | +The field definition of this field type can be configured with the following options: -``` php -// Relation FieldType example settings +| Name | Type | Default value | Description | +|-------------------------|-----------|---------------------|--------------------------------------------------------------------------------------------| +| `selectionMethod` | `string` | `"SELECTION_BROWSE"` | Method of selection in the editing interface. Only `"SELECTION_BROWSE"` is implemented. | +| `selectionRoot` | `string` | `null` | ID of the Location that the selection is rooted at. | +| `rootDefaultLocation` | `boolean` | `false` | When `true`, the selection starts from the default Location. | +| `selectionContentTypes` | `array` | `[]` | An array of content type identifiers that are allowed for the related content item. | -use Ibexa\Core\FieldType\Relation\Type; +On output, when `selectionRoot` is set, the API adds a read-only `selectionRootHref` key with the REST URI of that Location. -$settings = [ - 'selectionMethod' => 1, - 'selectionRoot' => null, - 'selectionContentTypes' => [], -]; +``` json +{ + "fieldSettings": { + "selectionMethod": "SELECTION_BROWSE", + "selectionRoot": "", + "selectionContentTypes": [] + } +} ``` 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 a658f288681..2207e03b064 100644 --- a/docs/content_management/field_types/field_type_reference/relationlistfield.md +++ b/docs/content_management/field_types/field_type_reference/relationlistfield.md @@ -2,124 +2,73 @@ This field type makes it possible to store and retrieve values of a relation to other content items. -| Name | Internal name | Expected input | -|----------------|------------------------|----------------| -| `RelationList` | `ibexa_object_relation_list` | `mixed` | - -## PHP API field type - -### Input expectations - -|Type|Description|Example| -|------|------|------| -|`int` or `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.| - -### Value Object - -#### Properties - -`Ibexa\Core\FieldType\RelationList\Value` contains the following properties: - -|Property|Type|Description|Example| -|------|------|------|------| -|`destinationContentIds`|`array`|An array of related Content IDs|`[ 24, 42 ]`| - -``` php -/** - * Value object content example. - * - * @var \Ibexa\Core\FieldType\RelationList\Value $relationList - * @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo1 - * @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo2 - */ -$relationList->destinationContentIds = [ - $contentInfo1->id, - $contentInfo2->id, - 170, -]; +| Name | Internal name | +|----------------|------------------------------| +| `RelationList` | `ibexa_object_relation_list` | + +## Field value + +The field value is an object with the following keys: + +| Key | Type | Description | Example | +|---------------------------|---------|--------------------------------------------------------------------------------------|--------------------------------------------------------------------| +| `destinationContentIds` | `array` | IDs of the related content items. | `[24, 42]` | +| `destinationContentHrefs` | `array` | REST URIs of the related content items. Read-only, added by the API on output only. | `["/api/ibexa/v2/content/objects/24", "/api/ibexa/v2/content/objects/42"]` | + +``` json +{ + "fieldDefinitionIdentifier": "related_articles", + "languageCode": "eng-GB", + "fieldValue": { + "destinationContentIds": [24, 42], + "destinationContentHrefs": [ + "/api/ibexa/v2/content/objects/24", + "/api/ibexa/v2/content/objects/42" + ] + } +} ``` -#### Constructor - -The `RelationList\Value` constructor initializes a new value object with the value provided. -It expects a mixed array as value. - -``` php -//Constructor example -use Ibexa\Core\FieldType\RelationList as RelationList; - -/** - * @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo1 - * @var \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo2 - */ -// Instantiates a RelationList Value object -$relationListValue = new RelationList\Value( - [ - $contentInfo1->id, - $contentInfo2->id, - 170, - ] -); -``` +When you create or update a field, provide `destinationContentIds` only. -### Validation +## Validation 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 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 `selectionMethod` specified is `"SELECTION_BROWSE"` or `"SELECTION_DROPDOWN"`. A validation error is returned if the value doesn't match. +- the `selectionDefaultLocation` specified is `null`, a string, or an integer. If the type validation fails, a validation error is returned. +- the value specified in `selectionContentTypes` is an array. If not, a validation error is returned. - the number of content items selected in the field isn't greater than the `selectionLimit`. !!! note The dropdown selection method isn't implemented yet. -### Settings +## Settings The field definition of this field type can be configured with the following options: -|Name|Type|Default value|Description| -|------|------|------|------| -|`selectionMethod`|`mixed`|`SELECTION_BROWSE`|Method of selection in the back-end interface.| -|`selectionDefaultLocation`|`string` or `integer`|`null`|ID of the default Location for the selection when using the back-end interface.| -|`selectionContentTypes`|`array`|`[]`|An array of content type IDs that are allowed for related Content.| - -Following selection methods are available: - -| Name| Description| -|-----|------------| -| `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.| - -``` php -// Example of using settings and validators configuration in PHP - -use Ibexa\Core\FieldType\RelationList\Type; - -$fieldSettings = [ - 'selectionMethod' => Type::SELECTION_BROWSE, - 'selectionDefaultLocation' => null, - 'selectionContentTypes' => [], - ]; - -$validators = [ - 'RelationListValueValidator' => [ - 'selectionLimit' => 0, - ], -]; +| Name | Type | Default value | Description | +|----------------------------|-----------------------|----------------------|---------------------------------------------------------------------------------------| +| `selectionMethod` | `string` | `"SELECTION_BROWSE"` | Method of selection in the editing interface. Only `"SELECTION_BROWSE"` is implemented. | +| `selectionDefaultLocation` | `string` or `integer` | `null` | ID of the default Location for the selection in the editing interface. | +| `rootDefaultLocation` | `boolean` | `false` | When `true`, the selection starts from the default Location. | +| `selectionContentTypes` | `array` | `[]` | An array of content type identifiers that are allowed for the related content items. | + +On output, when `selectionDefaultLocation` is set, the API adds a read-only `selectionDefaultLocationHref` key with the REST URI of that Location. + +## 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. | + +``` json +{ + "validatorConfiguration": { + "RelationListValueValidator": { + "selectionLimit": 5 + } + } +} ``` - -### GraphQL integration - -This field type is paginating the results when queried using [GraphQL](graphql.md). -To learn more, see [Pagination in GraphQL](graphql_queries.md#pagination). 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 1c91af55abd..b3cf2be003d 100644 --- a/docs/content_management/field_types/field_type_reference/richtextfield.md +++ b/docs/content_management/field_types/field_type_reference/richtextfield.md @@ -1,38 +1,35 @@ # 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. - This field type validates and stores structured rich text in [DocBook](https://docbook.org/) XML format, and exposes it in several formats. -| Name | Internal name | Expected input | -|------------|------------------|----------------| -| `RichText` | `ibexa_richtext` | mixed | - -## PHP API field type - -### Value object +| Name | Internal name | +|------------|------------------| +| `RichText` | `ibexa_richtext` | -`Ibexa\FieldTypeRichText\FieldType\RichText\Value` offers the following properties: +## Field value -| Property | Type | Description | -|----------|---------------|--------------------------------------------------------| -| `xml` | `DOMDocument` | Internal format value as an instance of `DOMDocument`. | +The field value is an object with the following keys: -### Input expectations +| Key | Type | Description | +|--------------|----------|-----------------------------------------------------------------------------------------------------| +| `xml` | `string` | The rich text in the field type's [internal format](#internal-format), a custom flavor of DocBook. | +| `xhtml5edit` | `string` | The same content in the [XHTML5 edit format](#xhtml5-edit-format). Read-only, added by the API on output only. | -| 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. | - -### Input formats +``` json +{ + "fieldDefinitionIdentifier": "description", + "languageCode": "eng-GB", + "fieldValue": { + "xml": "\n
\n This is a title.\n This is a paragraph.\n
\n", + "xhtml5edit": "\n
\n" + } +} +``` -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. +When you create or update a field, provide the `xml` key only. +If the input doesn't conform to the internal format, it's converted into it. -#### Internal format +### Internal format As its internal format, the RichText field type uses a [custom flavor of the DocBook format](#custom-docbook-format). @@ -48,9 +45,9 @@ As its internal format, the RichText field type uses a [custom flavor of the Doc
``` -#### XHTML5 edit format +### XHTML5 edit format -The XHTML5 format is used by the Online Editor. +The XHTML5 format is used by the Online Editor and is returned under the `xhtml5edit` key. ``` xml @@ -66,43 +63,8 @@ The XHTML5 format is used by the Online Editor. 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. - -The following example shows how to pass DocBook content to a [create struct](creating_content.md#creating-content-item-draft): - -``` php -/** - * @var \Ibexa\Contracts\Core\Repository\ContentService $contentService - * @var \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType $contentType - */ -$contentCreateStruct = $contentService->newContentCreateStruct($contentType, 'eng-GB'); - -$inputString = << -
- This is a title. - This is a paragraph. -
-DOCBOOK; - -$contentCreateStruct->setField('description', $inputString); -``` - -When creating RichText content with the REST API, use the `xml` key of the `fieldValue` tag: - -``` xml - - <?xml version="1.0" encoding="UTF-8"?> -<section xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ezxhtml="http://ibexa.co/xmlns/dxp/docbook/xhtml" xmlns:ezcustom="http://ibexa.co/xmlns/dxp/docbook/custom" version="5.0-variant ezpublish-1.0"> -<title ezxhtml:level="2">This is a title.</title> -</section> - - -``` +You provide the DocBook content as a string under the `xml` key of the field value. +The examples below show the DocBook markup that goes into that string. ### DocBook 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 8d76e61b6e1..52a72db6f24 100644 --- a/docs/content_management/field_types/field_type_reference/selectionfield.md +++ b/docs/content_management/field_types/field_type_reference/selectionfield.md @@ -1,88 +1,46 @@ # 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 defined in the field definition. -| Name | Internal name | Expected input type | -|-------------|-------------------|---------------------| -| `Selection` | `ibexa_selection` | mixed | +| Name | Internal name | +|-------------|-------------------| +| `Selection` | `ibexa_selection` | -## PHP API field type +## Field value -### Input expectations +The field value is an array of integers, each one the index of a selected option in the `options` field definition setting. -| Type | Example | -|---------|------------| -| `array` | `[ 1, 2 ]` | - -### Value object - -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|--------------|---------|-------------------------------------------------------------------------------------------------------------------| -| `$selection` | `int[]` | This property is used for the list of selections, which is a list of integer values, or one single integer value. | - -``` php -// Value object content examples - -/** @var \Ibexa\Core\FieldType\Selection\Value $value */ -// Single selection -$value->selection = [1]; - -// Multiple selection -$value->selection = [1, 4, 5]; -``` - -#### Constructor - -The `Selection\Value` constructor accepts an array of selected element identifiers. - -``` php -// Constructor example -use Ibexa\Core\FieldType\Selection as Selection; - -// Instanciates a selection value with items #1 and #2 selected -$selectionValue = new Selection\Value([1, 2]); +``` json +{ + "fieldDefinitionIdentifier": "size", + "languageCode": "eng-GB", + "fieldValue": [1, 2] +} ``` -#### String representation +## Validation -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. - -``` php -// Example of value in hash format - -$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. +This field type validates the input, verifying if all selected options exist in the field definition and checking if multiple selections are allowed in the field definition. +If any of these validations fail, the request is rejected. 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. | - -``` php -// Selection field type example settings - -use Ibexa\Core\FieldType\Selection\Type; - -$settings = [ - 'isMultiple' => true, - 'options' => [1 => 'One', 2 => 'Two', 3 => 'Three'], -]; +## Settings + +| Name | Type | Default value | Description | +|-----------------------|-----------|---------------|--------------------------------------------------------------------------------------| +| `isMultiple` | `boolean` | `false` | Used to allow or prohibit multiple selection from the option list. | +| `options` | `object` | `{}` | The list of options defined in the field definition, keyed by option index. | +| `multilingualOptions` | `object` | `{}` | The list of options per language code, keyed by language code and then option index. | + +``` json +{ + "fieldSettings": { + "isMultiple": true, + "options": { + "0": "Small", + "1": "Medium", + "2": "Large" + } + } +} ``` 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 5eb93397afe..4fdd5e0ce3e 100644 --- a/docs/content_management/field_types/field_type_reference/taxonomyentryassignmentfield.md +++ b/docs/content_management/field_types/field_type_reference/taxonomyentryassignmentfield.md @@ -2,7 +2,6 @@ `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" @@ -10,82 +9,46 @@ This field type assigns tags to the content in the data action, so then you can 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 | +| Name | Internal name | +|---------------------------|-----------------------------------| +| `TaxonomyEntryAssignment` | `ibexa_taxonomy_entry_assignment` | -## PHP API field type +## Field value -### Input expectations +The field value is an object with the following keys: -| Type | Description | Example | -|---------|---------------------------------------------------------------------------------------------------------------------------------------------|-----------| -| `array` | array with `Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry` objects under `taxonomy_entries` key and Taxonomy identifier under `taxonomy` key | see below | +| Key | Type | Description | Example | +|--------------------|----------|----------------------------------------------------------------------|----------------------| +| `taxonomy_entries` | `array` | IDs of the assigned taxonomy entries. | `[3]` | +| `taxonomy` | `string` | Identifier of the taxonomy that all the entries must be assigned to. | `product_categories` | -Example using an `Ibexa\Taxonomy\FieldType\TaxonomyEntryAssignment\Value` object: +The `taxonomy` value must match the `taxonomy` setting of the field definition. -``` php -use Ibexa\Contracts\Taxonomy\Service\TaxonomyServiceInterface; - -/** @var TaxonomyServiceInterface $taxonomyService */ -$taxonomyEntry1 = $taxonomyService->loadEntryByIdentifier('example_entry', 'tags'); -$taxonomyEntry2 = $taxonomyService->loadEntryByIdentifier('example_entry_2', 'tags'); -new \Ibexa\Taxonomy\FieldType\TaxonomyEntryAssignment\Value( - [ - $taxonomyEntry1, - $taxonomyEntry2, - // ... - ], - 'tags', -); -``` - -Example using array: - -``` php -use Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry; - -/** - * @var TaxonomyEntry $taxonomyEntry - * @var TaxonomyEntry $taxonomyEntry2 - */ -return [ - 'taxonomy_entries' => [$taxonomyEntry, $taxonomyEntry2], // load entries using TaxonomyService - 'taxonomy' => 'tags', -]; +``` json +{ + "fieldDefinitionIdentifier": "category", + "languageCode": "eng-GB", + "fieldValue": { + "taxonomy_entries": [3], + "taxonomy": "product_categories" + } +} ``` -### Value object - -#### Properties - -|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.| - -#### Constructor +## Validation -The constructor accepts `taxonomyEntries` and `taxonomy` as described above. +The field type validates if all taxonomy entries from the value are assigned to the configured taxonomy. -#### String representation +## Settings -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. +| Name | Type | Default value | Description | +|------------|----------|---------------|--------------------------------------------------------------| +| `taxonomy` | `string` | `null` | Identifier of the taxonomy from which the entries are chosen. | -#### Hash format - -An array of: - -- `taxonomy_entries` with numerical IDs of entries. -- `taxonomy` string identifier of a taxonomy. - -#### Validation - -The field type validates if all Taxonomy Entries from the value are assigned to the configured taxonomy. - -#### Settings - -| Name | Type | Default value | Description | -|------------|----------|---------------|--------------------------------------| -| `taxonomy` | `string` | `null` | Taxonomy from which entry is chosen. | +``` json +{ + "fieldSettings": { + "taxonomy": "product_categories" + } +} +``` 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 ac1daa0e7b2..44c88eb183c 100644 --- a/docs/content_management/field_types/field_type_reference/taxonomyentryfield.md +++ b/docs/content_management/field_types/field_type_reference/taxonomyentryfield.md @@ -2,82 +2,44 @@ TaxonomyEntry is a field type that stores information about the parent entry in the taxonomy tree, placing the taxonomy entry (tag or product category) in the taxonomy structure. -| Name | Internal name | Expected input | -|----------------|-----------------------|----------------| -| `TaxonomyEntry`| `ibexa_taxonomy_entry`| `array`| - -## PHP API field type - -### Input expectations - -A `TaxonomyEntry` field accepts an array with an `Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry` object. - -| Type | Description | Example | -|--------|-----------------|-----------------| -| `array` | array with an `Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry` object under the `taxonomy_entry` key | see below | - -Example using an `Ibexa\Taxonomy\FieldType\TaxonomyEntry\Value` object: - -``` php -use Ibexa\Contracts\Taxonomy\Service\TaxonomyServiceInterface; - -/** @var TaxonomyServiceInterface $taxonomyService */ -$taxonomyEntry = $taxonomyService->loadEntryByIdentifier('example_entry', 'tags'); -$taxonomyEntryField = new \Ibexa\Taxonomy\FieldType\TaxonomyEntry\Value($taxonomyEntry); -``` - -Example using array: - -``` php -use Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry; - -/** @var TaxonomyEntry $taxonomyEntry */ -return [ - 'taxonomy_entry' => $taxonomyEntry, // load Entry using TaxonomyService -]; +| Name | Internal name | +|-----------------|------------------------| +| `TaxonomyEntry` | `ibexa_taxonomy_entry` | + +## Field value + +The field value is an object with a single key: + +| Key | Type | Description | Example | +|------------------|-------------------|---------------------------------------------------|---------| +| `taxonomy_entry` | `integer`, `null` | ID of the selected taxonomy entry, or `null`. | `3` | + +``` json +{ + "fieldDefinitionIdentifier": "parent", + "languageCode": "eng-GB", + "fieldValue": { + "taxonomy_entry": 3 + } +} ``` -### Value object +## Validation -#### Properties +This field type doesn't perform any special validation of the input value. -|Property|Type|Description| -|--------|----|-----------| -|`taxonomyEntry`|`?Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry`|Stores selected taxonomy entry.| +## Settings -#### Constructor +The field definition of this field type can be configured with the following option: -The constructor accepts an `Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry` object. +| Name | Type | Default value | Description | +|------------|----------|---------------|--------------------------------------------| +| `taxonomy` | `string` | `null` | Identifier of the taxonomy from which you choose an entry. | -``` php -// Constructor example -use Ibexa\Contracts\Taxonomy\Service\TaxonomyServiceInterface; -use Ibexa\Taxonomy\FieldType\TaxonomyEntry; - -// Fetches TaxonomyEntry from TaxonomyService -/** @var TaxonomyServiceInterface $taxonomyService */ -$taxonomyEntry = $taxonomyService->loadEntryByIdentifier('example_entry', 'tags'); - -// Instantiates a taxonomy entry value -$taxonomyEntryFieldTypeValue = new TaxonomyEntry\Value($taxonomyEntry); +``` json +{ + "fieldSettings": { + "taxonomy": "tags" + } +} ``` - -#### String representation - -`taxonomyEntry` string identifier or empty string if no Taxonomy Entry is selected. - -#### Hash format - -An array with `taxonomy_entry` key containing `Ibexa\Contracts\Taxonomy\Value\TaxonomyEntry` object or `null`. - -#### Validation - -No validation. - -#### Settings - -The field definition of this field type can be configured with the following options: - -|Name|Type|Default value|Description| -|------|------|------|------| -|`taxonomy`|`string`|`null`|Taxonomy from which you choose an entry.| 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 62c3b2be6ca..729ebab8620 100644 --- a/docs/content_management/field_types/field_type_reference/textblockfield.md +++ b/docs/content_management/field_types/field_type_reference/textblockfield.md @@ -2,45 +2,38 @@ 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` | `ibexa_text` | `string` | +| Name | Internal name | +|-------------|---------------| +| `TextBlock` | `ibexa_text` | -## PHP API field type +## Field value -### Input expectations +The field value is the text as a string, or `null` when the field is empty. -| Type | Example | -|----------|-----------------------------------------| -| `string` | `"This is a block of unformatted text"` | +``` json +{ + "fieldDefinitionIdentifier": "body", + "languageCode": "eng-GB", + "fieldValue": "This is a block\nof unformatted text" +} +``` -### Value object - -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|----------|----------|---------------------------------------------| -| `$text` | `string` | This property is used for the text content. | - -##### String representation - -A TextBlock's string representation is the `$text` property's value, as a string. - -##### Constructor - -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 +## Validation This field type doesn't perform any special validation of the input value. -### Settings +## Settings + +The field definition of this field type can be configured with a single option: -Settings contain only one option: +| Name | Type | Default value | Description | +|------------|-----------|---------------|-----------------------------------------------------------| +| `textRows` | `integer` | `10` | Number of rows for the editing box in the editing interface. | -| Name | Type | Default value | Description | -|------------|-----------|---------------|---------------------------------------------------------------| -| `textRows` | `integer` | `10` | Number of rows for the editing box in the back-end interface. | +``` json +{ + "fieldSettings": { + "textRows": 10 + } +} +``` 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 abb5912f8ca..e49efc03228 100644 --- a/docs/content_management/field_types/field_type_reference/textlinefield.md +++ b/docs/content_management/field_types/field_type_reference/textlinefield.md @@ -3,43 +3,39 @@ 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` | `ibexa_string` | `string` | +| Name | Internal name | +|------------|----------------| +| `TextLine` | `ibexa_string` | -## PHP API field type +## Field value -### Value object +The field value is the text as a string, or `null` when the field is empty. -#### Properties - -The Value class of this field type contains the following properties: - -| Property | Type | Description | -|----------|----------|---------------------------------------------| -| `$text` | `string` | This property is used for the text content. | - -##### String representation - -A TextLine's string representation is the `$text` property's value, as a string. - -##### Constructor - -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. +``` json +{ + "fieldDefinitionIdentifier": "title", + "languageCode": "eng-GB", + "fieldValue": "Flipper Zero" +} +``` -### Validation +## 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 receives an array with `minStringLength` and `maxStringLength` like in the following representation: - -``` php -[ - 'StringLengthValidator' => [ - 'maxStringLength' => 60, - 'minStringLength' => 1, - ], -]; +The default value for both properties is `0`, which means that the validation is disabled by default. + +``` json +{ + "validatorConfiguration": { + "StringLengthValidator": { + "minStringLength": null, + "maxStringLength": 255 + } + } +} ``` + +## Settings + +This field type doesn't support settings. 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 14d3c58b334..4bba38017a1 100644 --- a/docs/content_management/field_types/field_type_reference/timefield.md +++ b/docs/content_management/field_types/field_type_reference/timefield.md @@ -3,78 +3,47 @@ This field type represents time information. Date information is **not stored**. - What is stored is the number of seconds, calculated from the beginning of the day in the given or the environment timezone. -| Name | Internal name | Expected input type | -|--------|---------------|---------------------| -| `Time` | `ibexa_time` | mixed | - -## PHP API field type - -### Input expectations - -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's also possible to directly pass an instance of `\DateTime`. - -| Type | Example | -|-------------|------------------------------------| -| `string` | `"2012-08-28 12:20 Europe/Berlin"` | -| `integer` | `1346149200` | -| `\DateTime` | `new \DateTime()` | - -### Value object - -#### Properties - -The Value class of this field type contains the following properties: +| Name | Internal name | +|--------|---------------| +| `Time` | `ibexa_time` | -| Property | Type | Description | -|----------|---------------------|-----------------------------------------------------------------------------------| -| `$time` | `integer` or `null` | Holds the time information as a number of seconds since the beginning of the day. | +## Field value -#### Constructor +The field value is an integer representing the number of seconds since the beginning of the day, or `null` when the field is empty. -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 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 | -|-----------|---------------------------------------------------------------------|---------| -| H | Two digit representation of an hour, 24-hour format, range 00 to 23 | 12 | -| i | Two digit representation of minutes, range 00 to 59 | 14 | -| s | Two digit representation of seconds, range 00 to 59 | 56 | - -Example: `"12:14:56"` - -#### Hash format - -Value in hash format is an integer representing a number of seconds since the beginning of the day. - -Example: `36000` +``` json +{ + "fieldDefinitionIdentifier": "opening_time", + "languageCode": "eng-GB", + "fieldValue": 36000 +} +``` -### Validation +## Validation This field type doesn't perform validation of the input value. -### Settings +## 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` | `Type::DEFAULT_EMPTY Type::DEFAULT_CURRENT_TIME` | `Type::DEFAULT_EMPTY` | The constant used here defines default input value when using back-end interface. | +| Name | Type | Default value | Description | +|---------------|-----------|-------------------|----------------------------------------------------------------------| +| `useSeconds` | `boolean` | `false` | Used to control displaying of seconds in the output. | +| `defaultType` | `string` | `"DEFAULT_EMPTY"` | Default field value used by the editing interface. See the values below. | -``` php -// Time field type example settings -use Ibexa\Core\FieldType\Time\Type; +| Value | Description | +|--------------------------|----------------------------------| +| `"DEFAULT_EMPTY"` | Default value is empty. | +| `"DEFAULT_CURRENT_TIME"` | Default value uses current time. | -$settings = [ - 'defaultType' => Type::DEFAULT_EMPTY, -]; +``` json +{ + "fieldSettings": { + "useSeconds": false, + "defaultType": "DEFAULT_CURRENT_TIME" + } +} ``` 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 065d2c8a349..bc6abd10401 100644 --- a/docs/content_management/field_types/field_type_reference/urlfield.md +++ b/docs/content_management/field_types/field_type_reference/urlfield.md @@ -1,74 +1,38 @@ # URL field type -This field type makes it possible to store and retrieve a URL. +This field type represents and handles a URL. It's formed by the combination of a link and the respective text. -| Name | Internal name | Expected input | -|-------|---------------|----------------| -| `Url` | `ibexa_url` | `string` | +| Name | Internal name | +|-------|---------------| +| `Url` | `ibexa_url` | -## PHP API field type +## Field value -### Input expectations +The field value is an object with the following keys, or `null` when the field is empty: -| Type | Description | Example | -|----------|-----------------------------------------------|------------------------| -| `string` | Link content provided to the value. | "https://www.ibexa.co" | -| `string` | Text content that represents the stored link. | "Ibexa" | +| Key | Type | Description | Example | +|--------|----------|------------------------------------------|-------------------------| +| `link` | `string` | The URL. | `https://www.ibexa.co/` | +| `text` | `string` | Text that represents the stored link. | `Ibexa` | -### Value object - -#### 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. | - -``` php -// Value object content example - -/** @var \Ibexa\Core\FieldType\Url\Value $url */ -$url->link = 'https://www.ibexa.co'; -$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. - -``` php -// Constructor example -use Ibexa\Core\FieldType\Url; - -// Instantiates an Url Value object -$UrlValue = new Url\Value('https://www.ibexa.co/', 'Ibexa'); +``` json +{ + "fieldDefinitionIdentifier": "website", + "languageCode": "eng-GB", + "fieldValue": { + "link": "https://www.ibexa.co/", + "text": "Ibexa" + } +} ``` -### Hash format +The `text` key is optional on input. -| Key | Type | Description | Example | -|--------|----------|---------------|-------------------------| -| `link` | `string` | Link content. | "https://www.ibexa.co/" | -| `text` | `string` | Text content. | "Ibexa" | - -``` php -// Example of the hash value in PHP -$hash = [ - 'link' => 'https://www.ibexa.co/', - 'text' => 'Ibexa', -]; -``` - -### Validation +## Validation This field type doesn't perform validation. -But some validation can be made afterward, see [External URL validation](url_management.md#external-url-validation) for more information. - -### Settings +## 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 8a470d803d9..c0f3e800201 100644 --- a/docs/content_management/field_types/field_type_reference/userfield.md +++ b/docs/content_management/field_types/field_type_reference/userfield.md @@ -2,28 +2,90 @@ This field type validates and stores information about a user. -| Name | Internal name | Expected input | -|--------|---------------|----------------| -| `User` | `ibexa_user` | ignored | - -## PHP API field type - -### Value object - -| Property | Type | Description | Example | -|--------------------|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------| -| `hasStoredLogin` | `boolean` | Denotes if user has stored login. | `true` | -| `contentId` | `int` or `string` | ID of the content item corresponding to the user. |`42`| -| `login` | `string` | Username. | `john` | -| `email` | `string` | The user's email address. | `john@smith.com` | -| `passwordHash` | `string` | Hash of the user's password. | `1234567890abcdef` | -| `passwordHashType` | `mixed` | Algorithm user for generating password hash as a `PASSWORD_HASH_*` constant defined in `Ibexa\Contracts\Core\Repository\Values\User\User` class. | `User::PASSWORD_HASH_PHP_DEFAULT` | -| `maxLogin` | `int` | Maximum number of concurrent logins. | `1000` | - -#### Available password hash types - -| Constant | Description | -|-------------------------------------------------------------------------------|---------------------------------------------------------------------------| -| `Ibexa\Contracts\Core\Repository\Values\User\User::DEFAULT_PASSWORD_HASH` | Default password hash, used when none is specified, may change over time. | -| `Ibexa\Contracts\Core\Repository\Values\User\User::PASSWORD_HASH_PHP_DEFAULT` | Passwords hashed by PHP's default algorithm, which may change over time. | -| `Ibexa\Contracts\Core\Repository\Values\User\User::PASSWORD_HASH_BCRYPT` | Bcrypt hash of the password. | +| Name | Internal name | +|--------|---------------| +| `User` | `ibexa_user` | + +## Field value + +The field value is an object with the following keys, or `null` when the field is empty: + +| Key | Type | Description | Example | +|---------------------|-------------------|----------------------------------------------------------------------------|--------------------------| +| `hasStoredLogin` | `boolean` | Denotes if the user has a stored login. | `true` | +| `contentId` | `integer` | ID of the content item corresponding to the user. | `144` | +| `login` | `string` | Username. | `jay.kowalski` | +| `email` | `string` | The user's email address. | `jay.kowalski@email.invalid` | +| `passwordUpdatedAt` | `integer`, `null` | Unix timestamp of the last password change. | `1682691427` | +| `enabled` | `boolean` | Whether the user account is enabled. | `false` | +| `maxLogin` | `integer` | Maximum number of concurrent logins. | `5` | +| `plainPassword` | `string`, `null` | Write-only. Set it to assign a new password. It's never returned on output. | `null` | + +``` json +{ + "fieldDefinitionIdentifier": "user", + "languageCode": "eng-GB", + "fieldValue": { + "hasStoredLogin": true, + "contentId": 144, + "login": "jay.kowalski", + "email": "jay.kowalski@email.invalid", + "passwordUpdatedAt": 1682691427, + "enabled": false, + "maxLogin": 5, + "plainPassword": null + } +} +``` + +!!! note "Password hashes are never exposed" + + The password hash and the hashing algorithm are stripped from the field value before it's returned. + Provide new passwords through the `plainPassword` key. + +## Validation + +The field type supports `PasswordValueValidator`, defining the password policy: + +| Name | Type | Default value | Description | +|---------------------------------------------|-----------|---------------|---------------------------------------------------------------------------| +| `requireAtLeastOneUpperCaseCharacter` | `integer` | `1` | Minimum number of required upper case characters. | +| `requireAtLeastOneLowerCaseCharacter` | `integer` | `1` | Minimum number of required lower case characters. | +| `requireAtLeastOneNumericCharacter` | `integer` | `1` | Minimum number of required numeric characters. | +| `requireAtLeastOneNonAlphanumericCharacter` | `integer` | `null` | Minimum number of required non-alphanumeric characters. | +| `requireNewPassword` | `integer` | `null` | Number of previous passwords that the new password must differ from. | +| `requireNotCompromisedPassword` | `boolean` | `false` | When `true`, the password is checked against known compromised passwords. | +| `minLength` | `integer` | `10` | Minimum password length. | + +``` json +{ + "validatorConfiguration": { + "PasswordValueValidator": { + "requireAtLeastOneUpperCaseCharacter": 1, + "requireAtLeastOneLowerCaseCharacter": 1, + "requireAtLeastOneNumericCharacter": 1, + "minLength": 10 + } + } +} +``` + +## Settings + +| Name | Type | Default value | Description | +|----------------------|-----------|---------------|----------------------------------------------------------------------------------| +| `PasswordTTL` | `integer` | `null` | Number of days after which the password expires. | +| `PasswordTTLWarning` | `integer` | `null` | Number of days before password expiry when the user starts getting a warning. | +| `RequireUniqueEmail` | `boolean` | `true` | When `true`, the email address must be unique across users. | +| `UsernamePattern` | `string` | `"^[^@]+$"` | Regular expression that the username must match. | + +``` json +{ + "fieldSettings": { + "PasswordTTL": 90, + "PasswordTTLWarning": 14, + "RequireUniqueEmail": true, + "UsernamePattern": "^[^@]+$" + } +} +``` diff --git a/docs/content_management/field_types/field_types.md b/docs/content_management/field_types/field_types.md index 64fc5f1106b..5672e6298a9 100644 --- a/docs/content_management/field_types/field_types.md +++ b/docs/content_management/field_types/field_types.md @@ -9,60 +9,7 @@ Field types are the smallest building blocks of content. Field types are responsible for: -- Storing data, either using the native storage engine mechanisms or specific means +- Storing data - Validating input data - Making the data searchable (if applicable) - 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. - -A custom field type must implement the **FieldType Service Provider Interfaces** -available in the [`Ibexa\Core\FieldType`](https://github.com/ibexa/core/tree/6.0/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). - -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) - -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: - -- 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** to store data from a `FieldValue` in an external service. -All non-standard [[= product_name =]] database tables (for example, `ibexa_url`) 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. - -## Creating content - -![Create content sequence](create_content_sequence.png) - -## Publishing content - -!!! note "indexLocation()" - - 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) - -## Updating content - -![Update content sequence](update_content_sequence.png) - -## Loading content - -![Load content sequence](load_content_sequence.png) diff --git a/docs/content_management/file_management/file_management.md b/docs/content_management/file_management/file_management.md deleted file mode 100644 index 0f105cab03f..00000000000 --- a/docs/content_management/file_management/file_management.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -description: Configurations and management of binary files. ---- - -# File management - -## Access binary files - -To access binary files from the PHP API, use the `Ibexa\Core\IO\IOServiceInterface::loadBinaryFile()` method: - -``` php -/** - * @var \Ibexa\Contracts\Core\Repository\Values\Content\Field $field - * @var \Ibexa\Core\IO\IOServiceInterface $ioService - */ -$file = $ioService->loadBinaryFile($field->value->id); -$fileContent = $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. - -### Native IO handler - -The IO API is organized around two types of handlers, both used by the IOService: - -- `Ibexa\Core\IO\IOMetadataHandler`: stores and reads metadata (such as validity or size) -- `Ibexa\Core\IO\IOBinarydataHandler`: stores and reads the actual binary data - -You can configure IO handlers using semantic configuration. IO handlers are configurable per SiteAccess. -See the default configuration: - -``` yaml -ibexa: - system: - default: - io: - metadata_handler: dfs - binarydata_handler: nfs -``` - -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 -ibexa_io: - binarydata_handlers: - nfs: - flysystem: - adapter: nfs_adapter - metadata_handlers: - dfs: - legacy_dfs_cluster: - connection: doctrine.dbal.dfs_connection -``` - -The `nfs_adapter`'s directory is based on your site settings, and is automatically set to `$var_dir$/$storage_dir$` (for example, `/path/to/ibexa/public/var/site/storage`). - -#### Permissions of generated files - -You can configure permissions of generated files under the `ibexa.system..io.permissions` [configuration key](configuration.md#configuration-files). - -``` yaml -ibexa: - system: - default: - io: - permissions: - files: 0750 #default is 0644 - directories: 0640 #default is 0755 -``` - -Both `files` and `directories` are optional. - -Default values: - -- 0644 for files -- 0755 for directories - -!!! note - - Make sure to configure permissions using a number and **not** a string. - "0644" is **not** interpreted by PHP as an octal number, and unexpected permissions can be applied. - -!!! note - - As SiteAccess configuration Flysystem's v2 native Local NFS adapter isn't supported, the following configuration should be used: - - ``` yaml - oneup_flysystem: - adapters: - nfs_adapter: - custom: - service: ibexa.io.nfs.adapter.site_access_aware - ``` - -### 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`). -[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 [[= product_name_base =]] custom `nfs_adapter`. -A basic configuration might look like the following: - -``` yaml -oneup_flysystem: - adapters: - nfs_adapter: - custom: - 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). - -!!! note - - Only the adapters are used here, not the filesystem configuration described in this 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 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 deleted file mode 100644 index f546600bdcb..00000000000 --- a/docs/content_management/file_management/file_url_handling.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -description: Manage files URL. ---- - -# File URL handling - -## IO URL decoration - -By default, images and binary files that are referenced by the content are served from the same server as the application, for example `/var/site/storage/images/3/6/4/6/6463-1-eng-GB/kidding.png`. -This is the default semantic configuration: - -``` yaml -ibexa: - system: - default: - io: - url_prefix: '$var_dir$/$storage_dir$' -``` - -`$var_dir$` and `$storage_dir$` are dynamic, [SiteAccess-aware settings](siteaccess_aware_configuration.md), and are replaced by their values in the execution context. - -## Serving images with nginx - -One common use case is to use an optimized nginx to serve images in an optimized way. The previous example image -could be made available as `http://static.example.com/var/site/storage/images/3/6/4/6/6463-1-eng-GB/kidding.png` -by setting up a separate server that maps the `/path/to/ibexa/public/var` directory. -The configuration would be as follows: - -``` yaml -ibexa: - system: - default: - io: - url_prefix: 'https://static.example.com/$var_dir$/$storage_dir$' -``` - -!!! caution - - 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. - -## `io.url_prefix` - -Any BinaryFile returned by the public PHP API is prefixed with the value of this setting, internally stored as `ibexa.site_access.config..io.url_prefix`. - -### `io.url_prefix` dynamic service container setting - -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'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. - -### Services - -#### URL decorators - -A `Ibexa\Core\IO\UrlDecorator` decorates and undecorates a specified string (URL). It has two mirror methods: `decorate` and `undecorate`. - -Two implementations are provided: `Prefix`, and `AbsolutePrefix`. They both add a prefix to a URL, but `AbsolutePrefix` ensures that unless the prefix is an external URL, the result is prepended with `/`. - -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 (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/form_builder_guide.md b/docs/content_management/forms/form_builder_guide.md index 72bc43c0bf9..9479f13539a 100644 --- a/docs/content_management/forms/form_builder_guide.md +++ b/docs/content_management/forms/form_builder_guide.md @@ -1,6 +1,5 @@ --- description: See the Form Builder product guide and learn how to create various forms to increase the functionality of your website. -edition: experience month_change: false --- @@ -14,9 +13,6 @@ By adding forms on the website, you can increase its functionality and improve u 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 - -Form Builder is available in [[= product_name_exp =]] and [[= product_name_com =]]. ## How does Form Builder work @@ -40,9 +36,7 @@ E. Discard button ### Form fields -To create forms, you can use available form fields or create custom ones. - -The available basic form fields are: +To create forms, use the available form fields: | Field name | Icon | Description| |----|----|----| @@ -73,7 +67,7 @@ To learn more, see [Work with forms]([[= user_doc =]]/content_management/work_wi ### 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. +Form 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. @@ -83,34 +77,6 @@ Using the buttons in the right corner, you can also edit, move, copy, hide, or s ![Forms management](img/forms_management.png) -### Form API - -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 [[= 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). -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, 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: - -1. define a new Form attribute in the configuration, -1. create a mapper, -1. add Symfony form type, -1. customize Form templates, -1. add scripts, -1. implement field, -1. implement field mapper, -1. create submission converter. - ### View results You can preview the results of each published form. @@ -122,12 +88,6 @@ Here you can view the details of each submission or delete any of them. The **Download submissions** button enables you to download all the submissions in a .CSV (comma-separated value) file. -!!! tip "Restricting access to form submissions" - - By default, back office users with access to the form content item can access the form submissions. - - If your form submissions require stricter access control than the form itself, you can introduce a [dedicated policy that manages access to submission data](custom_policies.md#restrict-access-to-form-submissions). - ## Benefits ### General overview @@ -141,11 +101,6 @@ Form Builder interface is plain, which makes the creation of forms fast and intu 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. -This allows you to create forms that fit your needs. - ### Analytic tool All the submissions can are visible in **Submissions** tab. diff --git a/docs/content_management/forms/forms.md b/docs/content_management/forms/forms.md index 663c1dbc276..3e1cf9d5c58 100644 --- a/docs/content_management/forms/forms.md +++ b/docs/content_management/forms/forms.md @@ -1,6 +1,5 @@ --- description: Forms are a type of content item that you can use to improve the functionality of your website. -edition: experience page_type: landing_page --- @@ -10,9 +9,4 @@ Forms are a type of content item that you can use to improve the functionality o [[= cards([ "content_management/forms/form_builder_guide", - "content_management/forms/work_with_forms", - "content_management/forms/form_api", - "content_management/forms/create_form_attribute", - "content_management/forms/create_custom_form_field", - "content_management/forms/customize_email_notifications", -], columns=3) =]] +], columns=2) =]] diff --git a/docs/content_management/forms/work_with_forms.md b/docs/content_management/forms/work_with_forms.md deleted file mode 100644 index 9e5d9fff339..00000000000 --- a/docs/content_management/forms/work_with_forms.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -description: Form Builder enables creating dynamic forms to use in surveys, questionnaires, sign-up forms and others. -edition: experience ---- - -# Forms - -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). - -[[% include 'snippets/forms_caution.md' %]] - -## Existing Form fields - -### Captcha field - -The Captcha Form field is based on [Gregwar/CaptchaBundle](https://github.com/Gregwar/CaptchaBundle). - -![Captcha field](extending_form_builder_captcha_default.png) - -You can customize the field by adding configuration to `config/packages/gregwar_captcha.yaml` under `gregwar_captcha`: - -``` yaml -gregwar_captcha: - as_url: true - width: 150 - invalid_message: Code does not match, please retry. - 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). - -![Custom captcha field](extending_form_builder_captcha_result.png) - -For information about available options, see [Gregwar/CaptchaBundle's documentation](https://github.com/Gregwar/CaptchaBundle#options). - -!!! 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). - -## 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: - -```bash -php bin/console ibexa:form-builder:purge-form-submissions [options] [--] -``` - -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'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`. -You can change it with the following configuration: - -``` yaml -ibexa: - system: - default: - form_builder: - upload_location_id: 54 -``` - -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 deleted file mode 100644 index 570e53e0492..00000000000 --- a/docs/content_management/images/add_image_asset_from_dam.md +++ /dev/null @@ -1,205 +0,0 @@ ---- -description: Configure a Digital Asset Management connector. -month_change: false ---- - -# Add Image Asset from Digital Asset Management - -With the Digital Asset Management (DAM) system connector you can use assets such as images directly from the DAM in your content. - -## DAM configuration - -You can configure a connection with a Digital Asset Management (DAM) system under the `ibexa.system..content.dam` [configuration key](configuration.md#configuration-files). - -``` yaml -ibexa: - system: - default: - content: - dam: [ dam_name ] -``` - -The configuration for each connector depends on the requirements of the specific DAM system. - -You can use the provided example DAM connector for [Unsplash](https://unsplash.com/), or [extend DAM support by creating a connector of your choice](#extend-dam-support-by-adding-custom-connector). - -To add the Unsplash connector to your system, add the `ibexa/connector-unsplash` bundle to your installation. - -## Add Image Asset in Page Builder [[% include 'snippets/experience_badge.md' %]] - -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`: - -``` html+twig -{% set dam_image = ibexa_field_value(content, 'image') %} -{% if dam_image.source is not null %} - {% set transformation = ibexa_dam_image_transformation(dam_image.source, '770px') %} - {% set asset = ibexa_dam_asset(dam_image.destinationContentId, dam_image.source, transformation) %} - {% set image_uri = asset.assetUri.path %} - -{% endif %} -``` - -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. - -For more information about displaying content, see [Content rendering](render_content.md). - -``` yaml -ibexa: - system: - site: - content_view: - embed: - image_dam: - template: '@ibexadesign/embed/dam.html.twig' - match: - Identifier\ContentType: -``` - -In your [configuration file](configuration.md#configuration-files) add the following configuration: - -``` yaml -dam_unsplash: - application_id: - utm_source: - variations: - 770px: - fm: jpg - q: 80 - w: 770 - fit: max -``` - -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. - -Now, when you use the Embed block in the Page Builder, you should see a DAM Image. - -For more information about block customization (defined templates, variations), see [Create custom block](4_create_a_custom_block.md). - -## Extend DAM support by adding custom connector - -To extend the DAM support built into [[= product_name =]], you must create a custom handler and transformation factory. - -!!! note "Wikimedia Commons licensing" - - Before you use Wikimedia Commons assets in a production environment, ensure that you comply with their [license requirements](https://commons.wikimedia.org/wiki/Commons:Reusing_content_outside_Wikimedia#How_to_comply_with_a_file's_license_requirements). - -### Create DAM handler - -This class handles searching through Wikimedia Commons for images and fetching image assets. - -In `src/Connector/Dam/Handler` folder, create the `WikimediaCommonsHandler.php` file that resembles the following example, -which implements [`search()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Connector-Dam-Handler-Handler.html#method_search) to query the server -and [`fetchAsset()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Connector-Dam-Handler-Handler.html#method_fetchAsset) to return asset objects: - -``` php -[[= include_code('code_samples/back_office/images/src/Connector/Dam/Handler/WikimediaCommonsHandler.php') =]] -``` - -Then, in `config/services.yaml`, register the handler as a service: - -```yaml -[[= include_file('code_samples/back_office/images/config/services.yaml', 9, 12) =]] -``` - -The `source` parameter passed in the tag is an identifier of this new DAM connector and is used in other places to glue elements together. - -### Create transformation factory - -The transformation factory maps [[= product_name =]]'s image variations to corresponding variations from Wikimedia Commons. - -In `src/Connector/Dam/Transformation` folder, create the `WikimediaCommonsTransformationFactory.php` file that resembles the following example, -which implements the [`TransformationFactory` interface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Connector-Dam-Variation-TransformationFactory.html): - -``` php -[[= include_code('code_samples/back_office/images/src/Connector/Dam/Transformation/WikimediaCommonsTransformationFactory.php') =]] -``` - -Then register the transformation factory as a service: - -```yaml -[[= include_file('code_samples/back_office/images/config/services.yaml', 13, 16) =]] -``` - -### Register variations generator - -The variation generator applies map parameters coming from the transformation factory to build a fetch request to the DAM. -The solution uses the built-in `URLBasedVariationGenerator` class, which adds all the map elements as query parameters to the request. - -For example, for an asset with the ID `Ibexa_Logo.svg`, the handler generates the Asset with [`AssetUri's URL`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Connector-Dam-AssetUri.html#method_getPath) equal to: - -`https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/Ibexa_Logo.svg` - -When the user requests a specific variation of the image, for example, "large", the variation generator modifies the URL and returns it in the following form: - -`https://commons.wikimedia.org/w/index.php?title=Special:Redirect/file/Ibexa_Logo.svg&width=300` - -For this to happen, register the variations generator as a service available for the custom `commons` connector: - -```yaml -[[= include_file('code_samples/back_office/images/config/services.yaml', 17, 21) =]] -``` - -### Configure tab for "Select from DAM" modal - -To enable selecting an image from the DAM system, a modal window pops up with tabs and panels that contain different search interfaces. - -In this example, the search only uses the main text input. -The tab and its corresponding panel are a service created by combining existing components, like in the case of other [back office tabs](back_office_tabs.md). - -The `commons_search_tab` service uses the `GenericSearchTab` class as a base, and the `GenericSearchType` form for search input. -It is linked to the `commons` DAM source and uses the identifier `commons`. -The DAM search tab is registered in the `connector-dam-search` [tab group](back_office_tabs.md#tab-groups) using the `ibexa.admin_ui.tab` tag. - -```yaml -[[= include_file('code_samples/back_office/images/config/services.yaml', 22, 33) =]] -``` - -### Create Twig template - -The template defines how images that come from Wikimedia Commons are displayed. - -In `templates/themes/standard/`, add the `commons_asset_view.html.twig` file that resembles the following example: - -```html+twig -[[= include_file('code_samples/back_office/images/templates/themes/standard/commons_asset_view.html.twig') =]] -``` - -Then, register the template and a fallback template in configuration files. -Replace `` with an [appropriate value](siteaccess_aware_configuration.md) that designates the SiteAccess or SiteAccess group, for example, `default` to use the template everywhere, including the back office: - -```yaml -[[= include_file('code_samples/back_office/images/config/packages/views.yaml') =]] -``` - -### Provide back office translation - -When the image asset field is displayed in the back office, a table of metadata follows. -This example uses new fields, so you need to provide translations for their labels, for example, in `translations/ibexa_fieldtypes_preview.en.yaml`: - -```yaml -[[= include_file('code_samples/back_office/images/translations/ibexa_fieldtypes_preview.en.yaml') =]] -``` - -### Add Wikimedia Commons connection to DAM configuration - -You can now configure a connection with Wikimedia Commons under the `ibexa.system..content.dam` key using the source identifier `commons`: - -```yaml -ibexa: - system: - default: - content: - dam: [ commons ] -``` - -Once you clear the cache, you can search for images to see whether images from the newly configured DAM are displayed correctly, including their variations. diff --git a/docs/content_management/images/configure_image_editor.md b/docs/content_management/images/configure_image_editor.md index ebbca8eed94..5ccf9187f79 100644 --- a/docs/content_management/images/configure_image_editor.md +++ b/docs/content_management/images/configure_image_editor.md @@ -1,5 +1,10 @@ --- description: Configure image editor to crop, flip, and modify images. +saas_review: + - siteaccess +saas_review_note: >- + Image Editor settings are SiteAccess-aware. Confirm how the SiteAccess scope is + chosen for them once SiteAccess configuration moves to a UI. --- # Configure Image Editor @@ -12,77 +17,4 @@ For more information, see [User Documentation]([[= user_doc =]]/image_management 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). - -## 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. - -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. - -``` yaml -[[= include_file('code_samples/back_office/image_editor/config/packages/image_editor.yaml', 0, 36) =]] -``` - -### Image file size optimization - -#### Image quality - -You can configure the quality of the images modified in the Image Editor with the following configuration. - -The setting accepts values between 0 and 1, which corresponds to the compression level, with 0 being the strongest compression. -The default quality is 0.92: - -``` yaml -[[= include_file('code_samples/back_office/image_editor/config/packages/image_editor.yaml', 0, 4) =]] [[= include_file('code_samples/back_office/image_editor/config/packages/image_editor.yaml', 39, 40) =]] -``` - -#### Gaussian blur strength - -You can configure the gaussian blur strength applied during image optimization with the following configuration. - -``` yaml -[[= include_file('code_samples/back_office/image_editor/config/packages/image_editor.yaml', 0, 4) =]] [[= include_file('code_samples/back_office/image_editor/config/packages/image_editor.yaml', 40, 41) =]] -``` - -The setting accepts float values between 0 and 10.0, where higher values increase blur and reduce file size, while lower values maintain sharpness. -The default value is 0.05. - -Processing large images with high blur values (above 5) can be time-consuming and may result in request timeouts. -Keep this in mind when configuring blur strength for environments that handle high-resolution images, and adjust [PHP's `max_execution_time`](https://www.php.net/manual/en/info.configuration.php#ini.max-execution-time) if needed. - -### Additional information - -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 =]]/image_management/edit_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: - -``` php -use Ibexa\Core\FieldType\Image\Value as FieldValue; -$value = new FieldValue([ - 'data' => [ - 'width' => '100', - 'height' => '200', - 'alternativeText' => 'test', - 'mime' => 'image/png', - 'id' => 1, - 'fileName' => 'image.png', - 'additionalData' => [ - 'focalPointX' => 50, - 'focalPointY' => 100, - 'author' => 'John Smith', - ], - ], - ]); -``` diff --git a/docs/content_management/images/fastly_io.md b/docs/content_management/images/fastly_io.md deleted file mode 100644 index d092b69519d..00000000000 --- a/docs/content_management/images/fastly_io.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -description: Configure Fastly Image Optimizer. ---- - -# Fastly Image Optimizer (Fastly IO) - -The Fastly Image Optimizer (Fastly IO) is an external service that provides real-time image optimization for multiple input and output formats. -It serves and caches image requests from your origin server, making your website faster and more efficient. - -To be able to configure this feature, you need [Fastly IO subscription](https://www.fastly.com/documentation/guides/full-site-delivery/image-optimization/about-fastly-image-optimizer/). - -## Enable shielding - -To use Fastly Image Optimizer, you first need a [working setup of [[= product_name =]] and Fastly](../../infrastructure_and_maintenance/cache/http_cache/reverse_proxy.md#using-varnish-or-fastly) -with shielding enabled. -To enable shielding, follow the steps in [Fastly Developer Documentation](https://www.fastly.com/documentation/guides/concepts/shielding/#enabling-and-disabling-shielding). -Remember to choose a shield location from the **Shielding** menu, as described in [Fastly User Documentation](https://www.fastly.com/documentation/guides/getting-started/hosts/shielding/#enabling-shielding). - -## VCL configuration - -To manipulate your Fastly VCL configuration directly from the command line, -you need to: - -- [install Fastly CLI](https://www.fastly.com/documentation/reference/tools/cli/#installing), -- define `FASTLY_SERVICE_ID` and `FASTLY_KEY` environmental variables, -- set optimizer restrictions by using the `ibexa_image_optimizer.vcl` file: - -```vcl -# Restrict optimizer by file path and extension -if (req.url.ext ~ "(?i)^(gif|png|jpe?g|webp)$") { - if (req.url.path ~ "^/var/([a-zA-Z0-9_-]+)/storage/images") { - set req.http.x-fastly-imageopto-api = "fastly"; - } -} -``` - -You can customize what image formats are included, for example: `gif|png|jpe?g|webp`, -and which paths should be used as a source of images, for example: `^/var/([a-zA-Z0-9_-]+)/storage/images`. -For more configuration options, see [Enabling image optimization](https://www.fastly.com/documentation/reference/io/#enabling-image-optimization). - -To apply your modifications or use the default configuration as-is, you can upload the `.vcl` file from the command line: - -```bash -fastly vcl snippet create --name="Ibexa Image Optimizer" --version=active --autoclone --type recv --content=vendor/ibexa/fastly/fastly/ibexa_image_optimizer.vcl -fastly service-version activate --version=latest -``` - -For more information about Fastly configuration and CLI usage examples, see [Configure and customize Fastly](fastly.md). - -## Define SiteAccess for Fastly IO - -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'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 -ibexa: - system: - my_siteaccess: - variation_handler_identifier: 'fastly' -``` - -You can also use environmental variables to configure a specific handler for a SiteAccess. -See the example below to configure it with the `.env` file: - -```bash -IBEXA_VARIATION_HANDLER_IDENTIFIER="fastly" -``` - -## Image configuration - -When you define image variation keys for Fastly IO, keep in mind -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 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://www.fastly.com/documentation/reference/io/). - -To generate your original image configuration run: - -```bash -php bin/console ibexa:fastly:migrate-configuration -``` - -Paste the following configuration to define the same variations for Fastly IO: - -```yaml -ibexa: - system: - default: - fastly_variations: - reference: - reference: original - configuration: - width: 600 - height: 600 - fit: bounds - small: - reference: reference - configuration: - width: 100 - height: 100 - fit: bounds - tiny: - reference: reference - configuration: - width: 30 - height: 30 - fit: bounds - medium: - reference: reference - configuration: - width: 200 - height: 200 - fit: bounds - large: - reference: reference - configuration: - width: 300 - height: 300 - fit: bounds - gallery: - reference: original - configuration: { } - ezplatform_admin_ui_profile_picture_user_menu: - reference: reference - configuration: - width: 30 - height: 30 - fit: bounds - crop: '30,30,x0,y0' -``` - -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](fastly_variations.png) diff --git a/docs/content_management/images/images.md b/docs/content_management/images/images.md index 243f11ba3f4..c0dde2f0be9 100644 --- a/docs/content_management/images/images.md +++ b/docs/content_management/images/images.md @@ -1,5 +1,5 @@ --- -description: Manage image assets by using DAM systems, configuring image variations, optimizing and using placeholders. +description: Manage image assets. month_change: false --- @@ -8,14 +8,6 @@ month_change: false 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. - -## 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. - -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. @@ -25,257 +17,13 @@ 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. -Run the following command to normalize image file names: - -``` bash -php bin/console ibexa:images:normalize-paths -``` - -Next, clear the cache: - -```bash -php bin/console cache:clear -``` - -and run the following: - -```bash -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. - -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. - -For more information, see the [bundle's documentation](https://symfony.com/bundles/LiipImagineBundle/current/configuration.html). - -!!! caution "Code injection in images" - - Images must be treated like any other user-submitted data - as potentially malicious. - - - EXIF metadata of an image may contain for example, HTML, JavaScript, or PHP code. - [[= product_name =]] itself doesn't parse EXIF metadata, but third-party bundles must be secured against this eventuality. - Make sure that metadata is properly escaped before use. - - Images may contain specially crafted flaws that exploit vulnerabilities in common image libraries - like GD or Imagick, leading to code execution. It's important to keep these libraries up to date with security updates. - -### 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`. - -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. - -``` bash -php bin/console ibexa:images:resize-original -f -``` - -You must provide the command with: - -- identifier of the image content type -- identifier of the field that you want to affect -- name of the image variation to apply to the images - -For example: - -``` bash -php bin/console ibexa:images:resize-original image photo -f small_image -``` - -You can also pass two additional parameters: - -- `iteration-count` is the number of images to be recreated in a single iteration, to reduce memory use. - The default value is `25`. -- `user` is the identifier of a User with proper permission who performs the operation (`read`, `versionread`, `edit` and `publish`). - The default value is `admin`. - -!!! caution - - The `resize-original` command publishes a new version of each content item it modifies. - -## Generating placeholder images - -With a placeholder generator you can download or generate placeholder images for any missing image. -It proves useful when you're working on an existing database and are unable to download uploaded images to your local development environment, due to, for example, a large size of files. - -If the original image cannot be resolved, the `PlaceholderAliasGenerator::getVariation` method generates a placeholder by delegating it to the implementation of the [PlaceholderProvider](https://github.com/ibexa/core/blob/6.0/src/bundle/Core/Imagine/PlaceholderProvider.php) interface, and saves it under the original path. - -In [[= product_name =]], there are two implementations of the `PlaceholderProvider` interface: - -- [GenericProvider](#genericprovider) -- [RemoteProvider](#remoteprovider) - -### GenericProvider - -The [`GenericProvider`](https://github.com/ibexa/core/blob/6.0/src/bundle/Core/Imagine/PlaceholderProvider.php) package generates placeholders with basic information about the original image (see [example 1](#configuration-examples)). - -![Placeholder image GenericProvider](placeholder_info.jpg "Example of a generic placeholder image") - -![Placeholder GenericProvider](placeholder_generic_provider.png "Generic placeholder images on a page") - -|Option|Default value|Description|Required?| -|------|-------------|-----------|-| -|fontpath|n/a|Path to the font file (*.ttf).|Yes| -|text|"IMAGE PLACEHOLDER %width%x%height%\n(%id%)"|Text which is displayed in the image placeholder. %width%, %height%, %id% in it's replaced with width, height and ID of the original image.| | -|fontsize|20|Size of the font in the image placeholder.| | -|foreground|#000000|Foreground color of the placeholder.| | -|secondary|#CCCCCC|Secondary color of the placeholder.| | -|background|#EEEEEE|Background color of the placeholder.| | - -### RemoteProvider +## Edit images -With the [`RemoteProvider`](https://github.com/ibexa/core/blob/6.0/src/bundle/Core/Imagine/PlaceholderProvider/RemoteProvider.php) you can download placeholders from: - -- remote sources, for example, (see [example 2](#configuration-examples)) -- live version of a site (see [example 3](#configuration-examples)) - -![Placeholder RemoteProvider - placecats.com](placeholder_remote_provider.jpg "Remote placeholder images on a page") - -|Option|Default value|Description| -|------|-------------|-----------| -|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): - -```yaml -ibexa: - # ... - image_placeholder: - : - provider: - options: -``` - -If there is no configuration assigned to the `binary_handler`, the placeholder generation is disabled. - -#### Configuration examples - -##### Example 1 - placeholders with basic information about original image - -```yaml -[[= include_file('code_samples/back_office/images/config/packages/images_basic.yaml') =]] -``` - -##### Example 2 - placeholders from remote source - -```yaml -[[= include_file('code_samples/back_office/images/config/packages/images_remote.yaml') =]] -``` - -##### Example 3 - placeholders from live version of a site - -```yaml -[[= include_file('code_samples/back_office/images/config/packages/images_live.yaml') =]] -``` - -## 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. - -!!! caution - - 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. - -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). - -Then, add a download route to the `config/routes.yaml` file: - -```yaml -[[= include_file('code_samples/back_office/images/config/routes.yaml') =]] -``` - -It points to a custom controller that handles the downloading of the SVG file. -The controller's definition (that you place in the `config/services.yaml` file under `services` key) and implementation are as follows: - -```yaml -[[= include_file('code_samples/back_office/images/config/services.yaml', 0, 8) =]] -``` - -``` php -[[= include_code('code_samples/back_office/images/src/SvgController.php') =]] -``` - -To be able to use a proper link in your templates, you also need a dedicated Twig extension: - -``` php -[[= include_code('code_samples/back_office/images/src/SvgExtension.php') =]] -``` - -Now you can load SVG files in your templates by using generated links and a newly created Twig helper: - -```twig -[[= include_file('code_samples/back_office/images/templates/themes/standard/svg_helper.html.twig') =]] -``` - -## Image optimization - -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. - -|Image format|Library| -|---|---| -|JPEG|JpegOptim| -|PNG|Either OptiPNG or Pngquant 2| -|SVG|SVGO 1| -|GIF|Gifsicle| -|WEBP|cwebp| - -Install these libraries using your package manager, for example: - -``` bash -sudo apt-get install optipng -``` - -### Customizing image optimizers - -When the Image Editor saves a modified image, the system dispatches the [`ConfigureImageOptimizersEvent`](other_events.md#image-editor) event before running the optimizer chain. -You can listen to this event to customize the list of image optimizers at runtime. - -The following example shows how to remove the Pngquant optimizer to prevent grayscale conversion of low-saturation PNG images: - -``` php -[[= include_code('code_samples/back_office/images/src/Event/RemovePngquantOptimizer.php') =]] -``` +When a content item contains fields of the [`ibexa_image`](imageassetfield.md) type, users can perform basic image editing functions with the Image Editor. +For more information, see [User Documentation]([[= user_doc =]]/image_management/edit_images/). ## Embedding images in Rich Text 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. - -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 -[[= include_file('code_samples/back_office/images/config/default_settings.yaml', 0, 2) =]] -``` - -You can set the template that is used when rendering embedded images in the `ibexa.default_view_templates.content.embed_image` container parameter: - -``` yaml -[[= include_file('code_samples/back_office/images/config/default_settings.yaml', 0, 1) =]] [[= include_file('code_samples/back_office/images/config/default_settings.yaml', 2, 3) =]] -``` +Content items that are identified as images are rendered in the Rich Text field. diff --git a/docs/content_management/locations.md b/docs/content_management/locations.md index 585fb7a4fe3..83721254e0e 100644 --- a/docs/content_management/locations.md +++ b/docs/content_management/locations.md @@ -21,8 +21,7 @@ A content item can have more than one location. It's then present in two or more 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. -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). +You can change the main location in the back office in the **Locations** tab. ![Locations](content_management_locations.png "Locations") @@ -44,7 +43,7 @@ can be viewed by selecting the **Content structure** tab in the Content mode int ![Content structure](content_management_tree.png "Content structure") 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). +The default ID number of this location is 2. It contains a Folder content item. ### Media @@ -54,9 +53,7 @@ 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). -It contains a Folder content item. +It's a folder that contains images, animations, documents and other files. ### Users @@ -70,10 +67,8 @@ 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. -The default ID number of the **Users** location is 5. -It contains user group content items. -### Forms [[% include 'snippets/experience_badge.md' %]] +### Forms **Forms** is the top level location that is intended for Forms created using the [Form Builder]([[= user_doc =]]/content_management/work_with_forms/#create-forms). diff --git a/docs/content_management/pages/ibexa_connect_scenario_block.md b/docs/content_management/pages/ibexa_connect_scenario_block.md deleted file mode 100644 index a3bd9a0fc43..00000000000 --- a/docs/content_management/pages/ibexa_connect_scenario_block.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -description: Work with Ibexa Connect scenario block that retrieves and displays data from an Ibexa Connect webhook. -edition: experience ---- - -# [[= product_name_connect =]] scenario block - -[[= 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). - -## Scenario block configuration - -In the following example you can learn how to configure [[= product_name_connect =]] scenario block with two available templates: `company_customers` and `external_clients`. - -### Block templates - -First, in `config/packages/ibexa_connect.yaml` add the following configuration: - -``` yaml -[[= 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. - -### 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. - -```yaml -[[= include_file('code_samples/page/ibexa_connect_scenario_block/config/packages/views.yaml') =]] -``` - -You also need to create `pagelayout.html.twig` file in `templates` folder: - -```html+twig -[[= include_file('code_samples/page/ibexa_connect_scenario_block/templates/pagelayout.html.twig') =]] -``` - -Then, in `templates/blocks` directory under `default.html.twig`, provide your block configuration: - -```html+twig -[[= include_file('code_samples/page/ibexa_connect_scenario_block/templates/blocks/default.html.twig') =]] -``` - -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 [[= 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. - -- 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`. -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. - -![Ibexa Connect webhook preview](ibexa_connect_webhook_preview.png) diff --git a/docs/content_management/pages/page_block_attributes.md b/docs/content_management/pages/page_block_attributes.md deleted file mode 100644 index f1611d11eee..00000000000 --- a/docs/content_management/pages/page_block_attributes.md +++ /dev/null @@ -1,213 +0,0 @@ ---- -description: Page blocks can contain multiple attributes, of both built-in and custom types. -month_change: false -edition: experience ---- - -# Page block attributes - -A block has attributes that the editor fills in when adding the block to a Page. - -[[% include 'snippets/page_block_cache_clear.md' %]] - -Each block can have the following properties: - -| Attribute | Description | -|--------------|--------------------------------------------------------------------------------------------------------------| -| `type` | Attribute type. | -| `name` | (Optional) The displayed name for the attribute. You can omit it, block identifier is then used as the name. Translatable using the `ibexa_page_builder_block_config` translation domain. | -| `value` | (Optional) The default value for the attribute. | -| `category` | (Optional) The tab where the attribute is displayed in the block edit modal. | -| `validators` | (Optional) [Validators](page_block_validators.md) checking the attribute value. | -| `options` | (Optional) Additional options, dependent on the attribute type. | - -## Block attribute types - -The following attribute types are available: - -|Type|Description|Options| -|----|----|----| -|`integer`|Integer value|-| -|`string`|String|-| -|`url`|URL|-| -|`text`|Text block|-| -|`richtext`|Rich text block (see [creating RichText block](create_custom_richtext_block.md))|-| -|`embed`|Embedded content item|`udw_config_name`: name of the [Universal Discovery Widget's configuration](browser.md#add-new-configuration) | -|`embedvideo`|Embedded content item|`udw_config_name`: name of the [Universal Discovery Widget's configuration](browser.md#add-new-configuration) | -|`select`|Drop-down with options to select|
  • `choices` lists the available options in `label: value` form
  • `multiple`, when set to true, allows selecting more than one option
| -|`checkbox`|Checkbox|Selects available option if `value: true`. Checkbox appearance in block configuration forms [can be configured](#configure-checkbox-appearance) | -|`multiple`|Checkbox(es)|`choices` lists the available options in `label: value` form.| -|`radio`|Radio buttons|`choices` lists the available options in `label: value` form.| -|`locationlist`|Location selection| `udw_config_name`: name of the [Universal Discovery Widget's configuration](browser.md#add-new-configuration) | -|`contenttypelist`|List of content types|-| -|`schedule_events`,
`schedule_snapshots`,
`schedule_initial_items`,
`schedule_slots`,
`schedule_loaded_snapshot`|Used in the Content Scheduler block|-| -|`nested_attribute`|Defines a group of attributes in a block.|
  • `attributes` - a list of attributes in the group. The attributes in the group are [configured](#page-block-attributes) as regular attributes
  • `multiple`, when set to true. New groups are added dynamically with the **+ Add** button
| - -When you define attributes, you can omit most keys as long as you use simple types that don't require additional options: - -``` yaml -attributes: - first_field: text - second_field: string - third_field: integer -``` - -The `embed`, `embedvideo`, and `locationlist` attribute types use the Universal Discovery Widget (UDW). -When creating a block with these types you can use the `udw_config_name` option to configure the UDW behavior. -See the [custom block example](create_custom_page_block.md#configure-block) to learn more. - -## Custom attribute types - -You can create custom attribute type to add to Page blocks. - -A custom attribute requires attribute type class, a mapper and a template. - -### Block attribute type - -First, create the attribute type class. - -It can extend one of the types available in `fieldtype-page/src/lib/Form/Type/BlockAttribute/`. -You can also use one of the [built-in Symfony types]([[= symfony_doc =]]/reference/forms/types.html), -for example `AbstractType` for any custom type or `IntegerType` for numeric types. - -To define the type, create a `src/Block/Attribute/MyStringAttributeType.php` file: - -``` php hl_lines="5 6 17" -[[= include_code('code_samples/page/custom_attribute/src/Block/Attribute/MyStringAttributeType.php') =]] -``` - -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 - -At this point, the attribute type configuration is complete, but it requires a mapper. -Depending on the complexity of the type, you can use a `GenericFormTypeMapper` or create your own. - -#### Generic mapper - -For a generic mapper, add a new service definition to `config/services.yaml`: - -``` yaml -[[= include_file('code_samples/page/custom_attribute/config/custom_services.yaml', 0, 7) =]] -``` - -#### Custom mapper - -To use a custom mapper, create a class that inherits from `Ibexa\Contracts\FieldTypePage\FieldType\Page\Block\Attribute\FormTypeMapper\AttributeFormTypeMapperInterface`, -for example in `src/Block/Attribute/MyStringAttributeMapper.php`: - -``` php -[[= include_code('code_samples/page/custom_attribute/src/Block/Attribute/MyStringAttributeMapper.php') =]] -``` - -Then, add a new service definition for your mapper to `config/services.yaml`: - -``` yaml -[[= include_file('code_samples/page/custom_attribute/config/custom_services.yaml', 8, 11) =]] -``` - -### Edit templates - -Next, configure a template for the attribute edit form by creating a `templates/themes/admin/custom_form_templates.html.twig` file: - -``` html+twig -[[= include_file('code_samples/page/custom_attribute/templates/themes/admin/custom_form_templates.html.twig') =]] -``` - -Add the template to your configuration under the `system..page_builder_forms` [configuration key](configuration.md#configuration-files): - -``` yaml -[[= include_file('code_samples/page/custom_attribute/config/packages/page_blocks.yaml', 16, 22) =]] -``` - -### Custom attribute configuration - -Now, you can create a block containing your custom attribute: - -``` yaml hl_lines="12-16" -[[= include_file('code_samples/page/custom_attribute/config/packages/page_blocks.yaml', 0, 15) =]] -``` - -### Nested attribute configuration - -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. - -Next, provide the configuration. See the example: - -``` yaml -[[= include_file('code_samples/page/custom_page_block/config/packages/nested_attribute.yaml', 0, 16) =]][[= include_file('code_samples/page/custom_page_block/config/packages/nested_attribute.yaml', 19, 23) =]] -``` - -To set validation for each nested attribute: - -``` yaml -[[= include_file('code_samples/page/custom_page_block/config/packages/nested_attribute.yaml', 9, 19) =]] -``` - -Validators can be also set on a parent attribute (group defining level), it means all validators apply to each nested attribute: - -``` yaml -[[= include_file('code_samples/page/custom_page_block/config/packages/nested_attribute.yaml', 9, 16) =]] [[= include_file('code_samples/page/custom_page_block/config/packages/nested_attribute.yaml', 19, 26) =]] -``` - -!!! caution "Moving attributes between groups" - - If you move an attribute between groups or add an ungrouped attribute to a group, - the block values are removed. - -## Help messages for form fields - -With the `help`, `help_attr`, and `help_html` field options, you can define help messages for fields in the Page block. - -You can set options with the following configuration: - -```yaml -ibexa_fieldtype_page: - blocks: - block_name: - attributes: - attribute_name: - options: - help: - text: 'Some example text' - html: true|false - attr: - class: 'class1 class2' -``` - -- `help.text` - defines a help message which is rendered below the field (maps to [`help`]([[= symfony_doc =]]/reference/forms/types/form.html#help)) -- `help.attr` - sets the HTML attributes for the element which displays the help message (maps to [`help_attr`]([[= symfony_doc =]]/reference/forms/types/form.html#help-attr)) -- `help.html` - enable (default) / disable (set to `true`) escaping the contents of the `help.text` option when rendering in the template (maps to [`help_html`]([[= symfony_doc =]]/reference/forms/types/form.html#help-html)) - -### Help message in nested attributes - -You can set the options for root or nested attribute, see the example configuration: - -```yaml -[[= include_file('code_samples/page/custom_attribute/config/packages/help_messages.yaml') =]] -``` - -![Help message](../img/page_block_help_message.png "Help message") - -## Configure checkbox appearance - -For blocks with an attribute of `checkbox` type, you can change the look of the checkbox in block configuration forms. - -You can do it by adding the `block_prefix: block_configuration_attribute_checkbox_toggle` option in the block configuration as follows: - -``` yaml hl_lines="4 5" -: - name: - type: checkbox - options: - block_prefix: block_configuration_attribute_checkbox_toggle -``` - -This setting changes the checkbox appearance to a toggle widget. - -![Toggle widget](toggle_widget.png) - -If you remove the above setting from the configuration, the attribute reverts to the default checkbox appearance. diff --git a/docs/content_management/pages/page_block_validators.md b/docs/content_management/pages/page_block_validators.md deleted file mode 100644 index 0ddd2f87e90..00000000000 --- a/docs/content_management/pages/page_block_validators.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -description: Set up rules for validating Page block content. -edition: experience ---- - -# Page block validators - -Validators check values passed to Page block attributes. -The following block validators are available: - -- `required` - checks whether the attribute is provided -- `regexp` - validates attribute according to the provided regular expression -- `not_blank` - checks whether the attribute isn't left empty -- `not_blank_richtext` - checks whether a `richtext` attribute isn't left empty -- `content_type` - checks whether the selected content types match the provided values -- `content_container` - checks whether the selected content item is a container - -!!! note - - 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 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: - -``` yaml -email: - type: string - name: E-mail address - validators: - regexp: - options: - pattern: '/^\S+@\S+\.\S+$/' - message: Provide a valid e-mail address -``` - -## Custom validators - -You can create Page block attributes with custom validators. - -The following example shows how to create a validator which requires that string attributes contain only alphanumeric characters. - -First, create classes that support your intended method of validation. -For example, in `src/Validator`, create an `AlphaOnly.php` file: - -``` php -[[= include_code('code_samples/page/custom_block_validator/src/Validator/AlphaOnly.php') =]] -``` - -In `src/Validator`, create an `AlphaOnlyValidator.php` class that performs the validation. - -``` php -[[= include_code('code_samples/page/custom_block_validator/src/Validator/AlphaOnlyValidator.php') =]] -``` - -Then, under `ibexa_fieldtype_page.block_validators`, enable the new validator in Page Builder: - -``` yaml -[[= include_file('code_samples/page/custom_block_validator/config/packages/page_blocks.yaml', 0, 3) =]] -``` - -Finally, add the validator to one of your block attributes, for example: - -``` yaml hl_lines="16-18" -[[= include_file('code_samples/page/custom_block_validator/config/packages/page_blocks.yaml', 0, 1) =]][[= include_file('code_samples/page/custom_block_validator/config/packages/page_blocks.yaml', 3, 20) =]] -``` - -### Custom required validator - -By default, only `not_blank` and `not_blank_richtext` validators mark a block attribute as required. - -If you create a custom validator `custom_not_blank` with attribute-specific logic, you can extend the `AttributeType` class with a Symfony form type extension to make sure that the attribute is also considered required: - -``` php hl_lines="15" -[[= include_code('code_samples/page/custom_block_validator/src/Form/Extension/AttributeTypeExtension.php') =]] -``` diff --git a/docs/content_management/pages/page_blocks.md b/docs/content_management/pages/page_blocks.md index 8fbafa83fe6..d033c56ccab 100644 --- a/docs/content_management/pages/page_blocks.md +++ b/docs/content_management/pages/page_blocks.md @@ -1,161 +1,8 @@ --- description: Use blocks to customize the content of a Page with dynamic content. -edition: experience --- # Page blocks -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 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' %]] - -## Block configuration - -Each configured block has an identifier and the following settings: - -| Setting | Description | -|---------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `name` | Name of the block used in the Page Builder interface. Translatable using the `ibexa_page_fieldtype` translation domain. Also accepts a [`help` key](#block-name-and-help-text) that adds a helper text under the **Name** field in the block configuration form. | -| `category` | Category in the Page Builder **Page blocks** toolbox that the block is shown in. Translatable using the `ibexa_page_fieldtype` translation domain. | -| `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 **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). | -| `cacheable_query_params` | (Optional) List of query parameters the block's [ESI HTTP cache](http_cache_configuration.md#when-to-use-esi) varies on.
For example, if the block is paginated using `?page=ℕ` from the page URL, add `page` to this list.
See the `ibexa_append_cacheable_query_params()` Twig function. | - -For example: - -``` yaml -[[= include_file('code_samples/page/custom_page_block/config/packages/page_blocks.yaml', 0, 12) =]][[= include_file('code_samples/page/custom_page_block/config/packages/page_blocks.yaml', 16, 17) =]]# ... -``` - -!!! tip - - For a full example of block configuration, see [Create custom Page block](create_custom_page_block.md). - -### Block name and help text - -The `name` setting accepts either a single translation key, a hard coded string of text that won't be translated, or an object with `text` and `help` property keys. -Both `text` and `help` are translatable using the `ibexa_page_fieldtype` translation domain. - -Scalar form: - -``` yaml -ibexa_fieldtype_page: - blocks: - my_block: - name: my_block.name.key -``` - -Structured form with a helper text: - -```yaml -ibexa_fieldtype_page: - blocks: - my_block: - name: - text: my_block.name.key - help: my_block.name.help.key -``` - -- `text` - corresponds to the block name. -- `help` - is an optional translation key whose translation is rendered as a helper text under the **Name** field in the block configuration form. - -![Help text](help_text.png) - -The same format is available for [React App blocks](react_app_block.md). - -### Overwriting existing blocks - -You can overwrite the following properties in the existing blocks: - -- `name` -- `category` -- `thumbnail` -- `views` - -## Block templates - -Page blocks can have multiple templates. -This allows you to create different styles for each block and let the editor choose them when adding the block from the UI. -They names are translatable using the `ibexa_page_builder_block_config` translation domain. - -``` yaml -[[= include_file('code_samples/page/custom_page_block/config/packages/page_blocks.yaml', 0, 3) =]][[= include_file('code_samples/page/custom_page_block/config/packages/page_blocks.yaml', 7, 16) =]] -``` - -`priority` defines the order of block views on the block configuration screen. -The highest number shows first on the list. - -!!! tip - - Default views have a `priority` of -255. - It's good practice to keep the value between -255 and 255. - -### Block modal template - -The template for the configuration modal of built-in Page blocks is contained in -`vendor/ibexa/page-builder/src/bundle/Resources/views/page_builder/block/config.html.twig`. - -You can override it by using the `configuration_template` [configuration key](configuration.md#configuration-files): - -``` yaml -[[= include_file('code_samples/page/custom_page_block/config/packages/page_blocks.yaml', 0, 7) =]] -``` - -The template can extend the default `config.html.twig` and modify its blocks. -Blocks `basic_tab_content` and `design_tab_content` correspond to the **Basic** and **Design** tabs in the modal. - -The following example wraps all form fields for block attributes in an ordered list: - -``` html+twig -[[= include_file('code_samples/page/custom_page_block/templates/themes/standard/blocks/event/config.html.twig') =]] -``` - -## Block events - -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. - -The following events are available: - -- `BlockDefinitionEvents::getBlockDefinitionEventName` - dispatched when block definition is created -- `BlockDefinitionEvents::getBlockAttributeDefinitionEventName` - dispatched when block attribute definition is created -- `BlockRenderEvents::getBlockPreRenderEventName` - dispatched before a block is rendered -- `BlockRenderEvents::getBlockPostRenderEventName` - dispatched after a block is rendered - -For example, to modify a block by adding a new parameter to it, you can create the following listener: - -``` php -[[= include_code('code_samples/page/page_listener/src/Block/Listener/MyBlockListener.php') =]] -``` - -Before the block is rendered, the listener adds `my_parameter` to it with value `parameter_value`. -You can use this parameter, for example, in block template: - -``` html+twig -[[= include_file('code_samples/page/page_listener/templates/themes/standard/block/my_block.html.twig') =]] -``` - -### 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. - -When creating a custom block with embeds, you can ensure such Relations are created using the block Relation collection event. - -The event is dispatched on content publication. -You can hook your event listener to the `BlockRelationEvents::getCollectBlockRelationsEventName` event. - -To expose relations, pass an array containing Content IDs to the `Ibexa\FieldTypePage\Event\CollectBlockRelationsEvent::setRelations()` method. -If embedded Content changes, old Relations are removed automatically. - -Providing Relations also invalidates HTTP cache for your block response in one of the related content items changes. +For a list of all page blocks that are available out-of-the-box, see [Page block reference]([[= user_doc =]]/content_management/block_reference/) in the user documentation. diff --git a/docs/content_management/pages/page_builder_guide.md b/docs/content_management/pages/page_builder_guide.md index 97e62c442ee..75e967ace42 100644 --- a/docs/content_management/pages/page_builder_guide.md +++ b/docs/content_management/pages/page_builder_guide.md @@ -1,6 +1,5 @@ --- description: Read about the Page Builder - a powerful tool for creating and modifying pages in Cohesivo. -edition: experience month_change: false --- @@ -41,14 +40,14 @@ Then, from the content tree choose the page and click **Edit**. Page Builder is a visual tool that allows you to create and edit any page in [[= product_name =]]. 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. +Creating pages in Page Builder involves composing content from ready-to-use elements - blocks. 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) ### Availability -Page Builder is available in [[=product_name_exp=]] and [[=product_name_com=]]. +Page Builder is available in [[= product_name =]]. ### How does Page Builder work @@ -122,10 +121,6 @@ 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 To customize your page in Page Builder you need to add blocks. @@ -135,7 +130,7 @@ When you add a new block to the drop zone, drop it in the blue highlighted area. ![Drop zone line](drop_zone_line.png) -Ready-to-use blocks available in [[= product_name =]] have their own, unique functions, but you can also [add your own, custom blocks](create_custom_page_block.md). All available tools and settings, that Page Builder comes with, enable you to customize the content appearing on the page. +Ready-to-use blocks available in [[= product_name =]] have their own, unique functions. All available tools and settings, that Page Builder comes with, enable you to customize the content appearing on the page. You can check all ready-to-use blocks available in Page Builder in User Documentation, [Block reference page]([[= user_doc =]]/content_management/block_reference/). diff --git a/docs/content_management/pages/pages.md b/docs/content_management/pages/pages.md index f5fb0af210f..0c62b090e19 100644 --- a/docs/content_management/pages/pages.md +++ b/docs/content_management/pages/pages.md @@ -1,7 +1,6 @@ --- description: Pages are block-based special types of content that editors can create and modify by using a visual drag-and-drop editor. page_type: landing_page -edition: experience --- # Pages @@ -11,7 +10,4 @@ Pages are block-based special types of content that editors can create and modif [[= cards([ "content_management/pages/page_builder_guide", "content_management/pages/page_blocks", - "content_management/pages/page_block_attributes", - "content_management/pages/page_block_validators", - "content_management/pages/create_custom_page_block", ], columns=3) =]] diff --git a/docs/content_management/pages/react_app_block.md b/docs/content_management/pages/react_app_block.md deleted file mode 100644 index fc1c6fb00f6..00000000000 --- a/docs/content_management/pages/react_app_block.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -description: Create a block that allows an editor to embed a preconfigured React component into a page. -edition: experience ---- - -# React App block - -React App block allows an editor to embed a preconfigured React application into a page. -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. - -It's common to all the blocks. - -[[% include 'snippets/page_block_cache_clear.md' %]] - -## React App Block configuration - -React App blocks are regular [Page blocks](page_blocks.md) and can be configured on field definition level as any other block. -File has exactly the same structure as regular YAML [block configuration](create_custom_page_block.md#configure-block), except: - -- additional `component` attribute which binds Page Builder block with React App -- `views` attribute is removed - -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. Also accepts a [`help` key](page_blocks.md#block-name-and-help-text) that adds a helper text under the **Name** field in the block configuration form. | -| `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 **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: - -``` yaml -[[= include_file('code_samples/page/react_app_block/config/packages/react_blocks.yaml') =]] -``` - -Each entry below `react_blocks` adds one block to the Page Builder with the defined name, category and thumbnail. -Both name and attributes support a short syntax and a long one for specifics. - -`Attributes` defined without sub-keys use the key as the identifier and name, and the value as the type: - -``` yaml -attributes: - b: integer -``` - -Sub-keys can be used to specify any of the usual [attributes configuration](page_block_attributes.md) key: - -``` yaml -attributes: - a: - name: Attribute A - type: string - options: - ... -``` - -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. - -## Create React App block - -In the following example, you learn how to create the `Calculator` React App block [configured in the previous section's example](#react-app-block-configuration). - -### Configure React App Block - -First, install React. -Run `yarn add react` command. - -Next, create a .jsx file which describes your component. -You can place it in any location. - -In the following example, create `Calculator.jsx` file in `assets/page-builder/components/` directory: - -``` js -[[= include_file('code_samples/page/react_app_block/assets/page-builder/components/Calculator.jsx') =]] -``` - -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. - -``` js -[[= include_file('code_samples/page/react_app_block/assets/page-builder/react/blocks/Calculator.js') =]] -``` - -Now, you should see new `Calculator` block in the Page Builder blocks list: - -![Calculator](calculator.png "Calculator - React App Block") - -Then, make sure that your [Page layout template](template_configuration.md#page-layout) (like `templates/themes/standard/pagelayout.html.twig`) has the following Twig code in its `{% block javascripts %}`: - -``` twig -{% if encore_entry_exists('react-blocks-js') %} - {{ encore_entry_script_tags('react-blocks-js') }} -{% endif %} -``` diff --git a/docs/content_management/rich_text/online_editor_guide.md b/docs/content_management/rich_text/online_editor_guide.md index a2a641e7b09..6b2f7053626 100644 --- a/docs/content_management/rich_text/online_editor_guide.md +++ b/docs/content_management/rich_text/online_editor_guide.md @@ -7,13 +7,10 @@ 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 and extensibility points to customize the editing experience and the available elements. - -Online Editor is based on [CKEditor 5](https://ckeditor.com/ckeditor-5/). ## Availability -Online Editor is available in all supported [[= product_name =]] versions and editions. +Online Editor is available in all supported [[= product_name =]] versions. ## How to get started @@ -41,43 +38,6 @@ While editing Rich Text fields, you can switch to distraction free mode that exp For more information, see [Distraction free mode]([[= user_doc =]]/content_management/create_edit_content_items/#distraction-free-mode). -### Custom tags - -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 -- 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. - -### Custom styles - -Custom styles allow specifying custom predefined templates for specific RichText elements. - -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. - -### Custom data attributes and CSS classes - -For each RichText element type, you can configure custom data attributes or CSS classes that the user can select when working in Online Editor. - -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-=""`. - -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. - -For more information, see [Extend Online Editor](extend_online_editor.md#custom-css-classes). - -### Plugins - -Online Editor is based on CKEditor 5, and you can use CKEditor's capabilities to [create plugins](extend_online_editor.md#add-ckeditor-plugins) for the editor. ## Benefits @@ -87,30 +47,9 @@ Online editor offers rich text editing tools familiar to most editors and contri ![Familiar editing tools](img/familiar_editing_tools.png) -The editor's toolbars can be customized and reorganized to for the specific project's needs. - -### Customizable text elements - -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. - -More extensive customization is available via custom tags: - -- 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. -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) - -Refer to [Extend Online Editor](extend_online_editor.md#link-tag) for a similar use case. ### Product marketing campaigns @@ -120,9 +59,3 @@ Products can be embedded as block-level or inline elements. You can use it to weave marketing content around your product data, showcasing your product capabilities and bringing it closer to your customers. See [Embed products in content](products.md#embed-products-in-content) for details. - -### 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. diff --git a/docs/content_management/rich_text/rich_text.md b/docs/content_management/rich_text/rich_text.md index 60013a8700c..77c755016cd 100644 --- a/docs/content_management/rich_text/rich_text.md +++ b/docs/content_management/rich_text/rich_text.md @@ -9,6 +9,4 @@ RichText is a type of field that you add in any content item in [[= product_name [[= cards([ "content_management/rich_text/online_editor_guide", - "content_management/rich_text/extend_online_editor", - "content_management/rich_text/create_custom_richtext_block", -], columns=3) =]] +], columns=1) =]] diff --git a/docs/content_management/taxonomy/taxonomy.md b/docs/content_management/taxonomy/taxonomy.md index 21be1039a15..9d161f30c93 100644 --- a/docs/content_management/taxonomy/taxonomy.md +++ b/docs/content_management/taxonomy/taxonomy.md @@ -7,304 +7,11 @@ month_change: false 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. +The system enables creating any entities with a tree structure and assign them to a content item. -Default tag configuration is available in `config/packages/ibexa_taxonomy.yaml` -The associated content type is `tag`. +The content type associated with taxonomy is called `tag`. -``` yaml -[[= include_file('code_samples/taxonomy/config/packages/ibexa_taxonomy.yaml', 0, 9) =]] -``` - -## 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.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. - -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. - -## Customize taxonomy structure - -You can create other taxonomies than the one predefined in the system, for example a Content category. - -To do it, first, create a new container to store the new taxonomy's items, for example a folder named "Content categories". - -Next, under the `ibexa_taxonomy.taxonomies` [key](configuration.md#configuration-files) add the following configuration: - -``` yaml -[[= include_file('code_samples/taxonomy/config/packages/ibexa_taxonomy.yaml', 0, 2) =]] # existing keys -[[= include_file('code_samples/taxonomy/config/packages/ibexa_taxonomy.yaml', 9, 16) =]] -``` - -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: - -- `name` of `ibexa_string` type and required. Use this field, as ``, for content name pattern. -- `category_identifier` of `ibexa_string` 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. - -### Hide Content tab - -The **Content** tab in taxonomy objects, for example, tags and categories, lists all Content assigned to the current taxonomy. -You can hide the **Content** tab in the **Categories** view. - -In configuration add `assigned_content_tab` with the flag `false` (for other taxonomies this flag is by default set to `true`): - -``` yaml hl_lines="11" -[[= include_file('code_samples/taxonomy/config/packages/ibexa_taxonomy.yaml', 0, 2) =]] # existing keys -[[= include_file('code_samples/taxonomy/config/packages/ibexa_taxonomy.yaml', 9, 17) =]] -``` - -### Hide menu item - -By default, for each taxonomy, a menu item is added to the main menu. -You can hide this menu item by setting a value of the `register_main_menu` configuration key: - -``` yaml hl_lines="6" -[[= include_file('code_samples/taxonomy/config/packages/ibexa_taxonomy.yaml', 0, 2) =]] # existing keys -[[= include_file('code_samples/taxonomy/config/packages/ibexa_taxonomy.yaml', 9, 10) =]] # existing keys -[[= include_file('code_samples/taxonomy/config/packages/ibexa_taxonomy.yaml', 17, 18) =]] -``` - -For more information about available functionalities of tags, see [User Documentation]([[= user_doc =]]/content_management/taxonomy/taxonomy/). - -## Hide delete button on large subtree - -The **Delete** button can be hidden when a taxonomy entry has many children. -By default, the button is hidden when there are 100 children or more. - -The `delete_subtree_size_limit` configuration is [SiteAccess-aware](siteaccess_aware_configuration.md), and can be set per SiteAccess, per SiteAccess group, or globally per default. -For example: - -```yaml -ibexa: - system: - default: # or a SiteAccess, or a SiteAccess group - taxonomy: - admin_ui: - delete_subtree_size_limit: 20 -``` - -## 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 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: - -- `--dry-run` to list deletable content items, without performing the deletion. -- `--force` to effectively delete the orphaned content items. - -The following example first lists the orphaned content items for taxonomy `tags`, and then deletes them: - -```bash -php bin/console ibexa:taxonomy:remove-orphaned-content tags --dry-run -php bin/console ibexa:taxonomy:remove-orphaned-content tags --force -``` ## Taxonomy suggestions -Once the feature is [enabled](#enable-taxonomy-suggestions), with taxonomy suggestions, editors can pick from suggestions generated by an AI service based on selected fields like the product's or content item's name and description instead of having to manually browse through taxonomy trees and selecting [product categories]([[= user_doc =]]/product_catalog/work_with_product_categories/#assign-product-categories-by-editing-product-details) or [tags]([[= user_doc =]]/content_management/create_edit_content_items/#add-taxonomy-entries). - -Taxonomy suggestions build on existing [AI Actions](ai_actions_guide.md) functionality. -The [`TaxonomyEmbeddingFieldProviderInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Taxonomy-Embedding-TaxonomyEmbeddingFieldProviderInterface.html) - service uses an existing taxonomy tree as reference, generating an embedding for each path in the taxonomy tree and storing it in the search index. - -For performance reasons, embeddings for the taxonomy tree entries are generated only in two cases: - -- when the search engine is reindexed, for example, right after you enable the feature and run the `ibexa:reindex` command -- when an individual taxonomy entry is created or modified, it's embedding is updated - -When the editor creates or edits a content item or a product, they can request that the application suggests tags or product categories to be associated with the item. -When it happens, the `Ibexa\Taxonomy\ActionHandler\TextToTaxonomyActionHandler` requests that an embedding is generated based on selected fields such as, for example, name and description. - -!!! note "Field selection" - - You select the actual text fields, whose values are used as source for the embedding generation, when you create an [AI action]([[= user_doc =]]/ai_actions/work_with_ai_actions/#create-ai-actions-that-use-ibexa-connect) that uses the `text-to-taxonomy` handler. - -The search engine then compares the generated embedding with the taxonomy path embeddings stored in its index. -By default, it selects the three best-matching taxonomy paths and presents them to the editor as suggestions. -The user can accept the suggestions, reject them, or request a new set of suggestions directly from the user interface. - -### Enable Taxonomy suggestions - -Taxonomy suggestions are built into the product and do not require additional installation. -However, before you can enable it, make sure the following prerequisites have been fulfilled: - -- [Search engine](search_engines.md): Taxonomy suggestions require a search engine that supports vector search. -The feature has been tested to work with Elasticsearch or Solr 9.8.1+. -- [AI Actions](ai_actions.md): To be able to process embeddings, Taxonomy suggestions require that you have the AI Actions configured to support the default [OpenAI](configure_ai_actions.md#configure-access-to-openai) or the optional [Google Gemini](configure_ai_actions.md#install-google-gemini-connector) service. - -!!! note "Alternative embeddings provider" - - To use Google Gemini as an alternative embeddings provider, you must also modify the default [taxonomy suggestions settings](taxonomy.md#change-embeddings-provider-to-google-gemini). - -#### Enable taxonomy embedding indexing - -Enable embedding indexing for taxonomy branches by changing the default setting from `false` to `true`. -Toggle this setting at any time to enable or disable indexing of taxonomy embeddings. - -```yaml hl_lines="6" -ibexa: - system: - default: - taxonomy: - search: - index_embeddings: true - default_embedding_model: 'text-embedding-ada-002' -``` - -If you are happy with the default settings, clear the cache and reindex the search engine. - -```bash -php bin/console cache:clear -php bin/console ibexa:reindex -``` - -#### Configure AI action - -Once you enable the Taxonomy suggestions feature, you must [configure an AI action]([[= user_doc =]]/ai_actions/work_with_ai_actions/#create-ai-actions-that-control-taxonomy-suggestions) that handles the generation of embeddings for newly created or edited content items or products. - -That's where you decide which exact fields from which content type should be used as input for embedding generation, how many suggestions are being presenter to the editor, and so on. - -After you do it, your users are be able to assign tags and/or product categories by using suggestions provided by an AI engine. - -### Customize Taxonomy suggestions - -You can modify the default behavior of the Taxonomy suggestions model by changing various settings. - -#### Change default number of suggestions - -By default, the system returns three suggestions. -You can change the default number if needed by altering the following setting: - -``` yaml hl_lines="4" -ibexa_taxonomy: - text_to_taxonomy: - default_suggested_taxonomies_limit: 5 -``` - -You can also override this setting per AI action by editing its configuration. - -#### Change default fields parsed when generating suggestions - -The following setting decides which fields are used to generate suggestions by default. -You can change the default setting, if needed. - -``` yaml hl_lines="6-9" -ibexa: - system: - default: - content_type_field_type_groups: - configurations: - vectorizable_fields: - - ibexa_string - - ibexa_text - - ibexa_richtext -``` - -This way you can limit field selection to meaningful text fields and avoid unsupported field types. -Like in the case of the number of suggestions, you can override this setting per AI action by editing its configuration. - -!!! tip - - When selecting the input data for embedding creation, it's recommended to include only the essential information and limit the number of tokens sent. - Otherwise, the embedding models can generate values that don't correspond closely to the actual meaning of the input. - -### Change embedding generation models or embedding provider - -By default, the system comes with a set of OpenAI models that can be used for embedding generation. -The following example shows these models listed in system configuration, together with a setting that controls what model is used when the editor requests taxonomy suggestions for an item. - -Also, here is where you can change the name of the model used by the provider, the embedding's dimensions, and other settings. - -```yaml hl_lines="20" -ibexa: - system: - default: - embedding_models: - text-embedding-3-small: - name: 'text-embedding-3-small' - dimensions: 1536 - field_suffix: '3small' - embedding_provider: 'ibexa_openai' - text-embedding-3-large: - name: 'text-embedding-3-large' - dimensions: 3072 - field_suffix: '3large' - embedding_provider: 'ibexa_openai' - text-embedding-ada-002: - name: 'text-embedding-ada-002' - dimensions: 1536 - field_suffix: 'ada002' - embedding_provider: 'ibexa_openai' - default_embedding_model: 'text-embedding-ada-002' -``` - -!!! caution "Change both embedding generation models" - - When you change the default suggestions generation model, ensure that you update the `ibexa.system.default.taxonomy.search.default_embedding_model` setting that is used for taxonomy indexing purposes. - Otherwise the taxonomy suggestions feature fails to find matching entries. - -#### Change embeddings provider to Google Gemini [[% include 'snippets/lts-update_badge.md' %]] - -Once you have installed and configured the [Google Gemini connector](configure_ai_actions.md#install-google-gemini-connector), you can modify the default configuration to use the `ibexa_gemini` embedding provider and one of the [supported models](https://ai.google.dev/gemini-api/docs/embeddings): - -```yaml hl_lines="15 22" -ibexa: - system: - default: - embedding_models: - gemini_embedding_001_1536: - name: 'gemini-embedding-001' - dimensions: 1536 - field_suffix: 'gemini_embedding_001_1536_dv' - embedding_provider: 'ibexa_gemini' - gemini_embedding_001_3072: - name: 'gemini-embedding-001' - dimensions: 3072 - field_suffix: 'gemini_embedding_001_3072_dv' - embedding_provider: 'ibexa_gemini' - default_embedding_model: 'gemini_embedding_001_1536' - -# ... - - taxonomy: - search: - index_embeddings: true - default_embedding_model: 'gemini_embedding_001_1536' -``` - -After you make the change: - -- Update the [Solr schema](field_type_search.md#configuring-solr) or [Elasticsearch mappings](configure_elasticsearch.md#fine-tune-the-search-results) by adding dynamic field definitions. Ensure that they match the dimensions (for example, 1536 or 3072) and suffixes that you defined above -- Clear the cache and reindex the search engine - -### Extending Taxonomy suggestions - -You can extend the feature by replacing the default code by exploring one of the following ideas. - -#### Replace the embedding provider - -By default, the system uses the `ibexa_openai` connector. -You can add your own embedding provider if needed. To do it: - -- Implement the [`EmbeddingProviderInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Search-Embedding-EmbeddingProviderInterface.html) -- Register the service with the `ibexa.embedding_provider` tag - -#### Extend the AI action form - -You can extend the `TextToTaxonomyOptionsType` AI action form by inheriting from `Ibexa\Bundle\Taxonomy\Form\Type\AbstractActionConfigurationOptions`. +With taxonomy suggestions, editors can pick from suggestions generated by an AI service based on selected fields like the product's or content item's name and description instead of having to manually browse through taxonomy trees and selecting [product categories]([[= user_doc =]]/product_catalog/work_with_product_categories/#assign-product-categories-by-editing-product-details) or [tags]([[= user_doc =]]/content_management/create_edit_content_items/#add-taxonomy-entries). diff --git a/docs/content_management/url_management/url_management.md b/docs/content_management/url_management/url_management.md index c649bef6734..503d8d4743e 100644 --- a/docs/content_management/url_management/url_management.md +++ b/docs/content_management/url_management/url_management.md @@ -1,6 +1,16 @@ --- description: Manage URL aliases and wildcards, and validate external URLs. month_change: false +saas_review: + - siteaccess + - links_removed +saas_review_note: >- + External URL validation is configured under the SiteAccess-aware url_checker key, + while URL aliases are not SiteAccess-aware but depend on the SiteAccess root path. + Confirm both statements once SiteAccess configuration moves to a UI. + + Links to the deleted install_cohesivo.md and field_type_storage.md pages were + removed; check that the surrounding text still reads correctly. --- # URL management @@ -21,202 +31,18 @@ Edit the entry to update the URL address in all the occurrences throughout the w When you edit the details of an entry to update the URL address, the status automatically changes to valid. -## External URL validation - -You can validate all the addresses from the URL table by executing the `ibexa:check-urls` command. -It validates the links by accessing them one by one and updates the value in the Last checked field. -If a broken link is found, its status is set to "invalid". - -The following protocols are currently supported: - -- `http` -- `https` -- `mailto` - -### Enabling automatic URL validation - -To enable automatic URL validation, set up a scheduled task to run the `ibexa:check-urls` command periodically. - -### Configuration - -The configuration of external URLs validation is SiteAccess-aware and is stored under the `ibexa.system..url_checker` [configuration key](configuration.md#configuration-files), for example: - -```yaml -ibexa: - system: - default: - url_checker: - handlers: - http: - enabled: true - batch_size: 64 - https: - enabled: true - ignore_certificate: false - mailto: - enabled: false -``` - -Available options are protocol-specific. -For details, see the tables below. - -#### http/https protocol - -| Option | Description | Default value | -|----------------------|----------------------------------------------------------------------------------------|-----------------------| -| enabled | Enables link validation. | true | -| timeout | Defines the time that the request is allowed to take (in seconds). | 10 | -| connection_timeout | Defines the time that the connect phase is allowed to take (in seconds). | 5 | -| batch_size | Defines a maximum number of asynchronous requests. | 10 | -| ignore_certificate | Decides if the peer's SSL certificate or the certificate name are verified against the host. | false | - -#### mailto protocol - -| Option | Description | Default value | -|--------------------|---------------------------------------------------------------------|---------------| -| enabled | Enables link validation. | true | - -For more information about [[= product_name_base =]] configuration, see [Configuration](configuration.md). - -### Custom protocol support - -You can extend the external URL address validation with a custom protocol. -To do this, you must provide a service that implements the [`Ibexa\Bundle\Core\URLChecker\URLHandlerInterface`](https://github.com/ibexa/core/blob/5.0/src/bundle/Core/URLChecker/URLHandlerInterface.php) interface. - -Then you must register the service with an `ibexa.url_checker.handler` tag, like in the following example: - -```yaml -app.url_checker.handler.custom: - class: 'App\URLChecker\Handler\CustomHandler' - tags: - - { name: ibexa.url_checker.handler, scheme: custom } -``` - -The `scheme` attribute is mandatory and has to correspond to the name of the protocol, for instance, `ftp`. ## 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 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. -!!! caution "Legacy storage engine limitation" +!!! caution "Storage limitation" - 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. + URL aliases that initially had the same name in multiple languages aren't archived. 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. -### URL alias pattern configuration - -You can configure how [[= product_name =]] generates URL aliases. -The configuration is stored under the `ibexa.url_alias.slug_converter` [configuration key](configuration.md#configuration-files), for example: - -``` yaml -ibexa: - url_alias: - slug_converter: - transformation: example_group - separator: dash - transformation_groups: - example_group: - commands: - - space_normalize - - hyphen_normalize - - apostrophe_normalize - - doublequote_normalize - - your_custom_command - cleanup_method: url_cleanup -``` - -| Option | Description | -|-----------------------|-----------------------------------------------------------------------------------------------------------| -| `transformation` | Indicates which pattern is used by default. | -| `separator` | Decides what separator is used. There are three types of separator available: dash, underscore and space. | -| `transformation_groups` | Contains the available patterns for URL generation. | - -A transformation group consists of an array of commands (see [all available commands](https://github.com/ibexa/core/tree/6.0/src/lib/Resources/slug_converter/transformations)) and a [`cleanupText`](https://github.com/ibexa/core/blob/6.0/src/lib/Persistence/Legacy/Content/UrlAlias/SlugConverter.php#L286). - -You can make use of pre-defined transformation groups. -You can also add your own, with your own set of commands. -To add commands to an existing group, provide the group name and list the commands that you want to add. - -### Regenerating URL aliases - -You can use the `ibexa:urls:regenerate-aliases` command to regenerate all URL aliases. -After the command is applied, old aliases redirect to the new ones. - -Use it when: - -- you change URL alias configuration and want to regenerate old aliases -- you encounter database corruption -- you have content that doesn't have a URL alias - -!!! caution - - 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: - -``` bash -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, for example, `ibexa:urls:regenerate-aliases --location-id=1 --location-id=2` - -## URL wildcards - -With wildcards, you can change the URL address for many content items at the same time, by replacing a portion of the destination's URL address. -For example, you might want to shorten the path, or make the path meaningful. - -For each URL wildcard definition you set the wildcard pattern and its destination. -Also, you can decide whether the user sees the content at the address that uses wildcards (Direct type), or is redirected to the original URL address of the destination (Forward type). - -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. - -Before you configure URL wildcards, you must enable the feature in configuration: - -``` yaml -ibexa: - url_wildcards: - enabled: true -``` - -### 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. - -!!! 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). - -### Configuring URL wildcards with the public PHP API - -You can create URL wildcards with the public PHP API by using the `URLWildcardService` service: - -``` php -/** @var \Ibexa\Contracts\Core\Repository\Repository $repository */ -$source = 'pictures/*/*'; -$destination = 'media/images/{1}/{2}'; -$redirect = true; - -$urlWildcardService = $repository->getURLWildcardService(); -$repository->sudo(static function ($repository) use ($urlWildcardService, $source, $destination, $redirect): void { - $urlWildcardService->create($source, $destination, $redirect); -}); -``` - -If `$redirect` is set to `true`, the redirection changes the URL address. -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 deleted file mode 100644 index a35612334e8..00000000000 --- a/docs/content_management/user_generated_content.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -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're meant to allow the implementation of user-generated content from the front end, without entering the back office. - -## Creating a new draft - -The `content/create/draft` route enables you to create a new draft for the selected content item. -Pass the ID of the content item as an argument. - -For example, `content/create/draft/59` creates a new draft of the content item with ID 59. - -## Creating a content item without using a draft - -The `/content/edit/nodraft` route shows a content item creation form for a given content type: - -| Argument | Type | Description | -|-------------------------|-----------|----------------------------------------------------------------------------| -| `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` | - -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: - -- `TextLine` -- `TextBlock` -- `Selection` -- `Checkbox` -- `User` -- `Date` -- `DateAndTime` -- `Time` -- `Integer` -- `Float` -- `URL` - -## Editing a content item - -To edit an existing draft, use the `/content/edit/draft/` route, with the following arguments: - -| Argument | Type | Description | -|-------------------------|-----------|--------------------------------------------------------------------------| -| `contentId` | `integer` | ContentId of the item to edit. | -| `versionNo` | `integer` | Number of the version to edit. The version must be an unpublished draft. | -| `languageCode` | `string` | Language code of the version. Example: `eng-GB` | - -For example, `/content/edit/draft/1/5/eng-GB` enables you to edit draft 5 of content item 1 in English. - -## Content editing templates - -You can use custom templates for the content editing forms. - -Define the templates under the `ibexa.system..content_edit_view` [configuration key](configuration.md#configuration-files): - -``` yaml -ibexa: - system: - default: - content_edit_view: - full: - : - template: content/edit/content_edit.html.twig - match: true - params: - viewbaseLayout: '@ibexadesign/ui/layout.html.twig' -``` diff --git a/docs/content_management/workflow/workflow.md b/docs/content_management/workflow/workflow.md index 772065da2df..f951856aaf6 100644 --- a/docs/content_management/workflow/workflow.md +++ b/docs/content_management/workflow/workflow.md @@ -8,86 +8,15 @@ The workflow functionality passes a content item version through a series of sta 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. +[[= product_name =]] comes pre-configured with a Quick Review workflow. Workflows are permission-aware. - -## Workflow configuration - -Each workflow consists of stages and transitions between them. - -The following example configuration defines a workflow where you can optionally pass a draft to be checked by the legal team. - -![Diagram of custom workflow](workflow_custom_diagram.png) - -``` yaml -[[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 0, 33) =]][[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 38, 51) =]][[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 54, 62) =]] -``` - -### Matchers - -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`. - -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). - -``` yaml -[[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 6, 9) =]] -``` - -### Stages - -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 doesn't appear on the dashboard or in Review Queue. - -One stage, listed under `initial_stage`, is the one that the workflow starts with. - -``` yaml hl_lines="13 14" -[[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 9, 23) =]] -``` - -### Transitions - -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). - -``` 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) =]] -``` - ### Reviewers 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. 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) =]] -``` - -#### Notifications - -To ensure that the assigned reviewers get a notification of a transition, configure the `actions.notify_reviewer` action for a stage. - -``` yaml hl_lines="4 5" -[[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 13, 18) =]] -``` - -The notification is displayed in the user menu: - -![Notification about content to review](workflow_notification.png) #### Draft locking @@ -95,53 +24,11 @@ You can configure draft assignment in a way that when a user sends a draft to re 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 - -You can automatically publish a content item once it goes through a specific transition. -To do so, configure the `publish` action for the transition: - -``` yaml hl_lines="7 8" -[[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 54, 62) =]] -``` - -### Disable Quick Review - -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) =]] -``` - -## Custom actions - -Besides the built-in actions of publishing content and notifying the reviewers, you can also [create custom workflow actions](add_custom_workflow_action.md). ## Workflow event timeline Workflow event timeline displays workflow transitions. -You can also use it to render custom entries in the timeline, for example system alerts on workflows. - -### Custom entry type - -To add a custom entry type, create a custom class extending `Ibexa\Workflow\WorkflowTimeline\Value\AbstractEntry`. -Use an `Ibexa\Contracts\Workflow\Event\TimelineEvents::COLLECT_ENTRIES` event to add your entries to the timeline. - -### Custom templates - -To provide custom templates for new event timeline entries, use the following configuration: - -``` yaml -ibexa: - system: - default: - workflows_config: - timeline_entry_templates: - - { template: '@IbexaWorkflow/ibexa_workflow/timeline/entries.html.twig', priority: 10 } -``` - -The template has to provide a block named `ez_workflow_timeline_entry_{ENTRY_IDENTIFIER}`. - ## Permissions You can limit access to workflows at stage and transition level. @@ -149,26 +36,3 @@ 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. 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'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. -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 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. - -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" -[[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 23, 43) =]][[= include_file('code_samples/workflow/custom_workflow/config/packages/workflows.yaml', 55, 63) =]] -``` - -You can check validation for a particular stage of the workflow even if the stage doesn't have any actions. diff --git a/docs/css/pills.css b/docs/css/pills.css index 11650e1c044..90ce784b401 100644 --- a/docs/css/pills.css +++ b/docs/css/pills.css @@ -7,27 +7,6 @@ margin-right: 8px; color: #A32768; } -.pill--headless { - color: #C4234A; - border-color: #C4234A; -} -.pill--headless::after { - content: "Headless"; -} -.pill--experience { - color: #D3822B; - border-color: #D3822B; -} -.pill--experience::after { - content: "Experience"; -} -.pill--lts-update { - color: #5DA7C0; - border-color: #5DA7C0; -} -.pill--lts-update::after { - content: "LTS Update"; -} .pill--new-feature { color: #2C9445; border-color: #2C9445; @@ -52,8 +31,4 @@ text-transform: lowercase; } -div.pills { - float: right; -} - /*# sourceMappingURL=pills.css.map */ diff --git a/docs/customer_management/cp_applications.md b/docs/customer_management/cp_applications.md index 2028e56b7fc..cc2e943338b 100644 --- a/docs/customer_management/cp_applications.md +++ b/docs/customer_management/cp_applications.md @@ -1,6 +1,5 @@ --- description: Customization of an approval process for new companies applications. -edition: experience --- # Customer Portal applications @@ -19,97 +18,3 @@ 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) - -## Customer Portal application configuration - -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`. - -```yaml -parameters: - ibexa.site_access.config.default.corporate_accounts.reasons: - reject: [Malicious intent / Spam] - on_hold: [Verification in progress] -``` - -### 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. -To change that duration, go to `config/packages/ibexa.yaml`. - -```yaml -framework: - rate_limiter: - corporate_account_application: - policy: 'fixed_window' - limit: 1 - interval: '5 minutes' - lock_factory: 'lock.corporate_account_application.factory' -``` - -## Customization of an approval process - -In this procedure, you add a new status to the approval process of business account application. - -### Add new status - -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') =]] -``` - -### Create new Form Type - -Next, create a new form type in `src/Form/VerifyType.php`. -It's displayed in the application review stage. - -``` php hl_lines="17-18 25" -[[= include_code('code_samples/customer_portal/src/Form/VerifyType.php') =]] -``` - -Line 29 defines where the form should be displayed, line 21 adds **Note** field, and line 22 adds the **Verify** button. - -### Create event subscriber to pass the form - -Add an event subscriber that passes a new form type to the frontend. -Create `src/Corporate/EventSubscriber/ApplicationDetailsViewSubscriber.php` following the example below: - -``` php hl_lines="35" -[[= include_code('code_samples/customer_portal/src/Corporate/EventSubscriber/ApplicationDetailsViewSubscriber.php') =]] -``` - -In line 39, you can see the `verify_form` parameter that passes the `verify` form to the application review view. - -### 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`. - -``` html+twig -[[= include_file('code_samples/customer_portal/templates/themes/admin/corporate_account/application/details.html.twig') =]] -``` - -It overrides the default view and adds a **Verify** button to the review view. -To check the progress, go to **Members** -> **Applications**. -Select one application from the list and inspect application review view for a new button. - -![Verify button](img/cp_new_status.png) - -### 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`. - -``` php hl_lines="42 68" -[[= include_code('code_samples/customer_portal/src/Corporate/EventSubscriber/VerifyStateEventSubscriber.php') =]] -``` - -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 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 deleted file mode 100644 index 004404e828e..00000000000 --- a/docs/customer_management/cp_configuration.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -description: Configure Customer Portal to fit the needs of your business. -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. - -## `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`. - -## Customer identifier - -`ibexa_default_settings.yaml` contains a setting that indicates what content types should be treated like Users in terms of, for example, usage in `UserService`: - -```yaml -ibexa: - system: - default: - user_content_type_identifier: ['user', 'customer'] -``` - -## 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). -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 -parameters: - ibexa.site_access.config.default.corporate_accounts.roles: - admin: Company Admin - buyer: Company Buyer - custom_role: Company Assistant -``` - -You can do it per SiteAccess or SiteAccess group by using [SiteAccess-aware configuration](siteaccess_aware_configuration.md). - -## 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. -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`. -To change content type names, adjust corporate account configuration in the following way: - -```yaml -ibexa_corporate_account: - content_type_mappings: - company: your_ct_identifier -``` - -!!! caution "Migration" - - If you decide to change deafult names of content types, during migration you have to adjust files accordingly. - -## Registration - -You can define what fields are required in the Customer Portal registration form. -To do so, [create and configure user registration form](create_user_registration_form.md). - -## 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). - -## 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. - -```yaml -ibexa: - system: - site_group: - content_view: - full: - confirmation_page: - template: "@@ibexadesign/customer_portal/account/forgot_password/confirmation_page.html.twig" - match: - Identifier\ContentType: confirmation_page -``` - -## 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. -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). diff --git a/docs/customer_management/cp_page_builder.md b/docs/customer_management/cp_page_builder.md deleted file mode 100644 index 9e6975b2256..00000000000 --- a/docs/customer_management/cp_page_builder.md +++ /dev/null @@ -1,258 +0,0 @@ ---- -description: Create unique Customer Portals for your clients with Page Builder. -edition: experience ---- - -# Create Customer Portal - -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 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 - -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. -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`. - -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. - -```yaml hl_lines="8 12 14 16" -ibexa: - siteaccess: - list: - - import - - site - - admin - - corporate - - custom_portal - groups: - site_group: [import, site] - storefront_group: [site] - corporate_group: [corporate, custom_portal] - system: - corporate_group: - languages: [eng-GB] - custom_portal: - languages: [ eng-GB ] - content: - tree_root: - location_id: 12345 # location_id_of_customer_portal - excluded_uri_prefixes: [ /media/, /images/ ] -``` - -Next, under the `ibexa.system.admin.page_builder` [configuration key](configuration.md#configuration-files), add `custom_portal` to [the SiteAccess list available to Page Builder](multisite_configuration.md#siteaccesses-and-page-builder): - -```yaml -ibexa: - system: - admin: - page_builder: - siteaccess_list: - - site - - corporate - - custom_portal -``` - -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) - -### Grant permissions to customers - -You need to grant the following permissions to company members, so they can view custom Customer Portal: - -- `user/login` to `custom_portal` SiteAccess -- `content/read` to the Customer Portal - -![Single Customer Portal permissions](img/single_cp_permissions.png) - -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 isn't a member of a company, this user cannot see the Customer Portal. - -## Create and configure multiple portals - -This setup is recommended for global markets or company specific portals, where each portal is design specifically for its users and their needs. - -### 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). -To do it, go to **Content** -> **Content structure**, and select **Create content**. -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'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) - -### 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`. - -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. - -```yaml hl_lines="8 12 14 16" -ibexa: - siteaccess: - list: - - import - - site - - admin - - corporate - - custom_portal - groups: - site_group: [import, site] - storefront_group: [site] - corporate_group: [corporate, custom_portal] - system: - corporate_group: - languages: [eng-GB] - custom_portal: - languages: [ eng-GB ] - content: - tree_root: - location_id: 12345 # location_id_of_customer_portals_root_folder - excluded_uri_prefixes: [ /media/, /images/ ] -``` - -Next, under the `ibexa.system.admin.page_builder` [configuration key](configuration.md#configuration-files), add `custom_portal` to [the SiteAccess list available to Page Builder](multisite_configuration.md#siteaccesses-and-page-builder): - -```yaml -ibexa: - system: - admin: - page_builder: - siteaccess_list: - - site - - corporate - - custom_portal -``` - -Now, you can go back to your Customer Portal's container. -All landing pages that you create in it use Customer Portal template. - -### 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: - -- `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'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 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. -Add portal mapping configuration in `config/services.yaml`: - -```yaml hl_lines="3 4" -parameters: - ibexa.corporate_account.customer_portal.customer_group_to_portal_map: - eu: - - 6bd4c938f9b3f668057c7e20987fac6c - - 7bf85988a77ee859f2466av2b42bd909 - us: - - 6ce85480aeaeed59f7431a12b46bc869 -``` - -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. -- Location remote ID of Customer Portal container or Customer Portal page. You can find it in the **Details** section. - -Portals are displayed to the Customer group in order specified in the configuration based on company member's permissions. - -#### Custom portal mapping - -You can specify your own custom logic for redirecting members to a specific Customer Portal. -To do so, implement `\Ibexa\Contracts\CorporateAccount\CustomerPortal\PickRule\CustomerPortalPickRule` and tag it with `ibexa.corporate_account.customer_portal.pick_rule`. - -### Multiple portals on single page - -You can allow company members to see multiple versions of Customer Portal on a single page by [combining SiteAccess matchers](siteaccess_matching.md#custom-matchers) with `Compound\LogicalAnd`: - -```yaml -ibexa: - siteaccess: - match: - Compound\LogicalAnd: - custom_portal: - matchers: - Map\Port: - eu: true - Map\Host: - example.com: true - match: custom_portal - Map\Host: - admin.example.com: site_admin -``` - -![Multiple portals in one view](img/cp_2_page_view.png) - -## Change Customer Portal layout - -You can change Customer Portal layout by adding your custom template under `ibexa.system..page_layout`: - -```yaml hl_lines="5" -ibexa: - system: - custom_portal: - languages: [ eng-GB ] - page_layout: "@App/my_page_layout.html.twig" - content: - tree_root: - location_id: 12345 #location_id_of_customer_portals_root_folder - excluded_uri_prefixes: [ /media/, /images/ ] -``` - -To generate the Customer Portal menu you should use `customer_portal.menu.main` key: - -```html+twig hl_lines="4" -{% block side_column %} -
- {% block left_sidebar %} - {% set main_menu = knp_menu_get('customer_portal.menu.main', [], {}) %} - {{ knp_menu_render(main_menu, { - depth: 1, - template: '@ibexadesign/customer_portal/menu.html.twig', - currentClass: 'active', - ancestorClass: 'active', - }) }} - {% endblock %} -
-{% endblock %} -``` - -To learn more about creating a menu, see [Add navigation menu](add_navigation_menu.md). diff --git a/docs/customer_management/customer_portal.md b/docs/customer_management/customer_portal.md index 659c4fec75c..aaef0d64781 100644 --- a/docs/customer_management/customer_portal.md +++ b/docs/customer_management/customer_portal.md @@ -1,6 +1,5 @@ --- description: Customer Portal allows your business clients to create and manage their company accounts. -edition: experience page_type: landing_page --- @@ -14,9 +13,6 @@ With this feature, your customers can self-register, edit their organization inf [[= cards([ "customer_management/customer_portal_guide", - "customer_management/cp_configuration", "customer_management/cp_applications", "users/invitations", - "customer_management/cp_page_builder", - "customer_management/create_user_registration_form", ], columns=3) =]] diff --git a/docs/customer_management/customer_portal_guide.md b/docs/customer_management/customer_portal_guide.md index 5fdb5470ee0..b3dccd0ee7f 100644 --- a/docs/customer_management/customer_portal_guide.md +++ b/docs/customer_management/customer_portal_guide.md @@ -1,6 +1,5 @@ --- description: Check all the capabilities and advantages that the Customer Portal offers to the clients by reading the Customer Portal product guide. -edition: experience --- # Customer Portal product guide @@ -15,7 +14,7 @@ With this feature, your customers can self-register, edit their organization inf ## Availability -Customer Portal is available in [[= product_name_exp =]]. It's also compatible with Product catalog and [[= product_name_connect =]]. +Customer Portal is available in [[= product_name =]]. It's also compatible with Product catalog and [[= product_name_connect =]]. ## How does Customer Portal work? @@ -40,11 +39,6 @@ If the built-in page blocks aren't sufficient to fulfill your needs, you can add ![Editable in Page Builder](img/cp_edit_in_page_builder.png) -You can allow company members to see multiple versions of Customer Portal on a single page by adding them under one Customer Portal container and combining SiteAccess matchers. -This setup is recommended for global markets or company-specific portals, where each portal is designed specifically for its customers and their needs. - -![Multiple portals](img/cp_2_page_view.png) - ### Company management The main company management takes place in the back office where each company has its own profile where sales representative can find: @@ -105,7 +99,6 @@ To apply for a business account, a company needs to provide their basic informat ![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: - on hold diff --git a/docs/getting_started/first_steps.md b/docs/getting_started/first_steps.md index 2cdbb1df347..ad4fe636179 100644 --- a/docs/getting_started/first_steps.md +++ b/docs/getting_started/first_steps.md @@ -1,45 +1,15 @@ --- -description: Start off working with Cohesivo by doing initial configuration and testing system capabilities. +description: Take your first steps in Cohesivo after you log in to the back office. --- # First steps -This page lists first steps you can take after installing [[= product_name =]]. -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). - -## 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: - -- Delete the file `config/packages/ibexa_welcome_page.yaml` -- Delete the `templates/themes/standard/full/welcome_page.html.twig` file -- Delete the `assets/scss` folder -- Delete all `translations/ibexa_platform_welcome_page.*` files -- In `webpack.config.js` remove the `Encore.addEntry` section and uncomment the last line, -so that the end of the file looks like this: - -``` js -module.exports = [ibexaConfig, ...customConfigs, projectConfig]; - -// uncomment this line if you've commented-out the above lines -module.exports = [ eZConfig, ibexaConfig, ...customConfigs ]; -``` +This page lists first steps you can take after you log in to [[= product_name =]] for the first time. +These steps are the most common actions you may need to take in a new site. ## Add a content type -1\. In your browser, go to the back office: `/admin`, and log in with the default username: `admin` using the password specified during installation. - -!!! caution "Password change" - - 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). +1\. In your browser, log in to the back office. 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). @@ -64,36 +34,7 @@ module.exports = [ eZConfig, ibexaConfig, ...customConfigs ]; 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. - -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`): - -``` yaml -site_group: - content_view: - full: - blog_post: - template: full\blog_post.html.twig - match: - Identifier\ContentType: [blog_post] -``` - -Content view templates use the [Twig templating engine](https://twig.symfony.com/). - -2\. Create a template file `templates/full/blog_post.html.twig`: - -``` html+twig -

{{ ibexa_render_field(content, 'title') }}

-
{{ ibexa_render_field(content, 'text') }}
-``` - -For more information, see [Templates](templates.md) and [Twig documentation](https://twig.symfony.com/doc/3.x/). - -## Create content and test view templates +## Create content 1\. Go to the back office, select **Content** -> **Content structure**, and create a new content item by clicking **Create content**. @@ -102,113 +43,41 @@ For more information, see [Templates](templates.md) and [Twig documentation](htt 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 is `/first-blog-post`. - -![Previewing Content](first-steps-preview-content.png) - -## Add SiteAccesses - -You can use SiteAccesses to serve different versions of the website. +[[= product_name =]] is headless, so the published content item is delivered over HTTP rather than rendered by the platform. +You can now fetch it with the REST API and display it in your own front end. -SiteAccesses are used depending on matching rules. -They're set up in YAML configuration under the `ibexa.siteaccess.list` key. +For more information, see [REST API](api.md) and [REST API authentication](rest_api_authentication.md). -1\. In `config/packages/ibexa.yaml` add a new SiteAccess called `de` for the German version of the website: +## SiteAccesses -``` yaml -ibexa: - # ... - siteaccess: - list: [site, de] - groups: - site_group: [site, de] -``` +A SiteAccess is a named context in which a request is served. +By using more than one SiteAccess you can serve several sites, or several versions of one site, from the same content. -The SiteAccess is automatically matched based on the last part of the URI. +Each incoming request is assigned to a SiteAccess based on the input data. +SiteAccesses can be gathered in groups, and many settings are SiteAccess-aware, which means that they can have a different value for each SiteAccess, and fall back to the value set for the group or for all SiteAccesses. -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 doesn't have permissions to view it. - See [section about permissions below](#set-up-permissions). - -For now the new SiteAccess doesn't differ from the main site. - -For more information, see [Multisite](multisite.md) and [SiteAccess matchers](siteaccess_matching.md#available-siteaccess-matchers). +For more information, see [Multisite](multisite.md) and [SiteAccess](siteaccess.md). ## 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`: - -``` yaml -site: - languages: [eng-GB] -de: - languages: - - ger-DE - - eng-GB -``` - -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`. +1\. 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. +2\. 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 as the target language and base the translation on the English source text. +3\. Select German as the target language and base the translation on the English source text. Edit the content item and publish it. -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) - -For more information, see [Languages](languages.md) and [Set up translation SiteAccess](set_up_translation_siteaccess.md). - -## Add a design - -The design engine enables you to use different themes consisting of templates and assets. -Each theme is stored in a separate folder and assigned to a SiteAccess. - -To create a new theme: - -1\. Add the following configuration at the bottom of `config/packages/ibexa.yaml` (at the same level as `ibexa`): - -``` yaml -ibexa_design_engine: - design_list: - site_design: [site_design] - de_design: [de_design] -``` - -2\. In configuration of the `de` SiteAccess (under `ibexa.system.de`) add: `design: de_design` - -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'` - -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. +The content item now exists in two languages. -8\. To see the difference between the different themes, compare what is displayed at `/` and `/de/` +For more information, see [Languages](languages.md). ## Set up permissions diff --git a/docs/getting_started/getting_started.md b/docs/getting_started/getting_started.md index 7bee7dbfb9b..744d031cfb5 100644 --- a/docs/getting_started/getting_started.md +++ b/docs/getting_started/getting_started.md @@ -1,5 +1,5 @@ --- -description: Get started working with Cohesivo by taking your first steps in a new installation. +description: Get started working with Cohesivo by taking your first steps after you log in. page_type: landing_page --- diff --git a/docs/ibexa_products/editions.md b/docs/ibexa_products/editions.md index c7ce71704bb..f31643e3c0e 100644 --- a/docs/ibexa_products/editions.md +++ b/docs/ibexa_products/editions.md @@ -33,10 +33,10 @@ Compare all features available in [[= product_name_headless =]], [[= product_nam | [Date and time attribute type](date_and_time.md) | ✔ | ✔ | ✔ | | [Symbol attribute type](symbol_attribute_type.md) | ✔ | ✔ | ✔ | | [Recommendations](raptor_connector_guide.md) | ✔ | ✔ | ✔ | -| [Migrations](managing_migrations.md) | ✔ | ✔ | ✔ | +| Migrations | ✔ | ✔ | ✔ | | [[[= product_name_connect =]]]([[= connect_doc =]]/) | ✔ | ✔ | ✔ | -| [OAuth client](oauth_client.md) | ✔ | ✔ | ✔ | -| [OAuth Server](oauth_server.md) | ✔ | ✔ | ✔ | +| OAuth client | ✔ | ✔ | ✔ | +| OAuth Server | ✔ | ✔ | ✔ | | [Site Factory](site_factory.md) | | ✔ | ✔ | | [Customizable Dashboard]([[= user_doc =]]/getting_started/dashboard/work_with_dashboard/#customize-dashboard) | | ✔ | ✔ | | [Page Builder](page_builder_guide.md) | | ✔ | ✔ | @@ -57,8 +57,6 @@ The features brought by LTS Updates become standard parts of the next LTS releas | Feature | [[= product_name_headless =]] | [[= product_name_exp =]] | [[= product_name_com =]] | |-----------------|-----------------|-----------------|-----------------| -| [Anthropic connector](configure_ai_actions.md#install-anthropic-connector) | ✔ | ✔ | ✔ | -| [Google Gemini connector](configure_ai_actions.md#install-google-gemini-connector) | ✔ | ✔ | ✔ | | [Integrated help](integrated_help.md) | ✔ | ✔ | ✔ | | [MCP servers](mcp_guide.md) | ✔ | ✔ | ✔ | | [Translations management](translations_management_guide.md) | ✔ | ✔ | ✔ | diff --git a/docs/ibexa_products/ibexa_experience.md b/docs/ibexa_products/ibexa_experience.md index 7860c8cb352..f064ac19e4d 100644 --- a/docs/ibexa_products/ibexa_experience.md +++ b/docs/ibexa_products/ibexa_experience.md @@ -12,7 +12,7 @@ It offers smooth consumer journey and great online experience. In everything you With Experience edition you can empower Editors to quickly create new pages or personalized content, and improve their daily work. It also provides tools for using segmentation and targeting, and it can be widely used in B2B thanks its features and integrations. -![Ibexa Experience](ibexa_experience.png) + ## Availability @@ -48,7 +48,7 @@ With its intuitive and user-friendly interface, you can develop pages, tailor co You build pages from ready-to-use elements called blocks, which can be easily configured and customized to suit your needs. Before you start building a page, you also need to select a layout. It has a significant impact on how the content pieces in the drop zones are arranged. -![Page Builder](page_builder.png) + #### Form Builder @@ -57,7 +57,7 @@ With this tool, you can design, deploy, and manage online forms quickly. You can create a variety of forms that consist of different fields, including sign-up forms, surveys, or questionnaires. Additionally, you can monitor and manage the information obtained from website visitors and adjust your forms if needed. -![Form Builder](form_builder.png) + #### Site Factory @@ -73,7 +73,7 @@ Starting from Experience edition of [[= product_name =]] you can [customize the You can tailor dashboard to your specific needs by choosing from a set of widgets. You can easily preview the sections that you use more often and omit the less significant ones. -![Customizable dashboard](customizable_dashboard.png) + #### Publish Later @@ -96,7 +96,7 @@ One of the tools that you can use right out of the box is the Targeting block th Segmentation is also useful with the [Recommendations](raptor_connector_guide.md). You can assign users to different recommendation groups and create advanced logic with operators to provide your audience with the best recommendations. -![Segments](segments.png) + #### [[= product_name_cdp =]] (Customer Data Platform) @@ -118,7 +118,7 @@ To use it, you must make arrangements with [[= product_name_base =]] to define t 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. -![Qualifio](qualifio.png) + ### Use cases diff --git a/docs/ibexa_products/ibexa_headless.md b/docs/ibexa_products/ibexa_headless.md index 0149c5e053a..9c6d5d8a908 100644 --- a/docs/ibexa_products/ibexa_headless.md +++ b/docs/ibexa_products/ibexa_headless.md @@ -12,7 +12,7 @@ It provides tools to collaboratively create content, and interfaces (API) to dis Multilingual, multichannel, extensible, [[= product_name_headless =]] is an advanced Content Management Framework (CMF) with product catalog capabilities, 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 @@ -44,12 +44,12 @@ By using a version control system and environment variables, you can deploy your Standard web APIs and [[[= product_name_connect =]]]([[= connect_doc =]]/general/ibexa_connect/) help establish interoperability, even if you aren't an advanced developer. -![Ibexa Headless data inputs and outputs](img/headless.png) + APIs summary: - The REST and GraphQL APIs give access to the content in standardized ways. -- The OAuth 2 [Client](oauth_client.md) and [Server](oauth_server.md) allow to connect to an SSO or be the SSO. +- The OAuth 2 Client and Server 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. diff --git a/docs/index.md b/docs/index.md index ca5b81aa9f3..4391640687d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,13 +3,13 @@
-

Ibexa Developer Documentation

+

Cohesivo Developer Documentation

How to start?

- -
- -
- + +
+
@@ -49,7 +49,7 @@
- Go through the First steps + Read the Product guides
@@ -59,8 +59,8 @@
-

The latest Cohesivo is v5.0 LTS

-
The latest v5.0 LTS release is [[= latest_tag_5_0 =]]. You can now update your application.
+

What's new in Cohesivo

+
Cohesivo is delivered as a service, so new capabilities reach you without an upgrade project. The release notes list what has been delivered.
Release notes @@ -73,12 +73,11 @@
-

The newest LTS Update is Translations management

-
Use machine translation, side-by-side editing view, and a review cycle to improve your translation experience.
+

Looking for the on-premise product?

+
Cohesivo is also available as an on-premise, self-hosted product that you install and extend yourself. It has its own documentation.
@@ -88,62 +87,7 @@
-
-
- -

Notable changes in v5.0

-
- -
-
- -
-
-
-
-
-
- -

Most popular pages

-
- -
-
- -
-
-
-
-
-
-

Manage your Cohesivo

+

What Cohesivo does

+
+
@@ -184,18 +155,50 @@
+
+
+
+
+ +

Most popular pages

+
+ +
+
+ +
+
+
+
diff --git a/docs/infrastructure_and_maintenance/security/security_checklist.md b/docs/infrastructure_and_maintenance/security/security_checklist.md index 004b216051c..765de6c9159 100644 --- a/docs/infrastructure_and_maintenance/security/security_checklist.md +++ b/docs/infrastructure_and_maintenance/security/security_checklist.md @@ -36,54 +36,6 @@ This is specially important for admin accounts and other privileged users. See [setting up password rules](passwords.md#password-rules). -### 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 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). -The account invitation feature defaults to "P7D" (seven days). - -### Disable Varnish when using Fastly - -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. -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. -`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`. - -### Use secure password hashing - -Use the most secure supported password hashing method. -This is currently `bcrypt`, and it's enabled by default. ### Use secure roles and policies @@ -100,11 +52,10 @@ Use the following checklist to ensure the roles and policies are secure: ### Don't use "hide" for read access restriction -The [visibility switcher](locations.md#location-visibility) is a convenient feature for withdrawing content from the frontend. -It acts as a filter in the frontend by default. +The [visibility switcher](locations.md#location-visibility) acts as a flag. 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. +Hidden content can be read through the REST API. 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**](sections.md) or [**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). @@ -115,35 +66,6 @@ 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'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 is set. It specifies what version of [[= product_name =]] 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 by setting `enabled: false`. - - ```yaml - ibexa_system_info: - system_info: - powered_by: - # major => v4 || minor => v4.6 || none - release: major - # true || false - enabled: false - ``` - -- 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: - - ```yaml - security: - access_control: - - { path: ^/search, roles: ROLE_USER} - ``` - ### Limit access to Code blocks The [Code block]([[= user_doc =]]/content_management/block_reference/#code-block) in Page Builder is designed to accept any HTML, which includes embedded JavaScript. @@ -151,86 +73,10 @@ This means that editors who have access to Code blocks could add malicious JS in As site administrator, be aware of this when giving editors access to the Page Builder features, and limit that access only to trusted editors. You can [limit access to specific blocks per content type]([[= user_doc =]]/content_management/configure_ct_field_settings/#default-configuration-of-pages) by defining which page blocks are available to editors. -### Activate JWT authentication for MCP, REST, or GraphQL - -To use [MCP servers](mcp_guide.md), you must enable JWT authentication for them. -You can also consider enabling JWT authentication for [REST](rest_api_usage.md) or [GraphQL](graphql.md) APIs. - -For more information, see [Development security](development_security.md#jwt-authentication). - -## Symfony - -### `APP_SECRET` and other secrets - -`APP_SECRET` needs to be a strong, random, securely stored value. -This applies also to other secrets that may be in use, like the Varnish invalidate token, the JWT passphrase, and any other application-specific secrets. - -- 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. There are several ways of handling it, like with environment variables or files like `.env.local`. Files are considered more secure. If you store the secrets in files, make sure to add those files to `.gitignore` or similar, so they will never be committed to version control systems. -- The secret must be long enough. 32 characters is minimum, longer is better. - -!!! tip - - The following command generates a 64-character-long secure random value: - - ```bash - php -r "print bin2hex(random_bytes(32));" - ``` - -!!! note - - On [[= product_name_cloud =]], if `APP_SECRET` isn't set, the system sets it to [`PLATFORM_PROJECT_ENTROPY`](https://fixed.docs.upsun.com/guides/symfony/environment-variables.html#symfony-environment-variables) - -### Symfony production mode - -Only expose Symfony production mode openly on the internet. -Don't expose the dev mode on the internet, otherwise you may disclose things like `phpinfo` and environment variables. - -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 [secrets management system]([[= symfony_doc =]]/configuration/secrets.html), all from Symfony. - -## PHP - -### Enable `zend.exception_ignore_args` in PHP 7.4 and newer - -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 that stack traces don't include arguments passed to functions. -Such arguments could include passwords or other sensitive information. -You should also make sure that no stack trace is ever visible to end users of production sites. Visible arguments are unsafe even if the stack traces only show up in log files. - -### Disable error output from PHP - -Symfony in production mode prevents exception messages from being visible to end users. -However, if Symfony fails to boot properly, such exceptions may end up being visible, including stack traces. -This can be prevented by [disabling error message output in PHP](https://www.php.net/manual/en/language.errors.basics.php). -The following `php.ini` configuration values should be used on production sites. -When using [[= product_name_cloud =]], the same settings can be configured in [[= product_name =]]'s `.platform.app.yaml` file. - -```ini -display_errors = Off -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. - -For more information, see [PHP's own security manual](https://www.php.net/manual/en/security.php). - -## Web server - -### Block execution of scripts in `var` directory - -Make sure that the web server blocks the execution of PHP files and other scripts in the `var` directory. -In your web server's virtual host configuration, see the line below `# Disable .php(3) and other executable extensions in the var directory`. - -### Security headers +## 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'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 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. @@ -250,29 +96,6 @@ 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. -### Disable weak cipher suites in TLS - -Consider blocking the use of TLS 1.2 and older versions. -The newer TLS 1.3 doesn't include the weaker cipher suites that are included in 1.2 and older. -Removing them means that attackers can't attempt to force other users to use weak ciphers and eavesdrop on their communications. -As of December 2024, TLS 1.3 is [supported by ca. 97% of global internet users](https://caniuse.com/tls1-3). -If you need to support Internet Explorer or old versions of other browsers, you can disable TLS 1.1 and older, leaving 1.2 and 1.3 enabled. - -When using [[= product_name_cloud =]], you can [set the minimum TLS version in `.platform/routes.yaml`](https://fixed.docs.upsun.com/define-routes/https.html#enforce-tls-13). - -### Enable HTTP Strict Transport Security (HSTS) - -HSTS forces clients to always communicate with your site over HTTPS. -[Most browsers support this](https://caniuse.com/stricttransportsecurity), and there is no downside for browsers that don't. -Read the requirements and instructions at [hstspreload.org](https://hstspreload.org/) before you enable HSTS. -Make sure to also include subdomains by means of the `includeSubDomains` setting. - -When using [[= product_name_cloud =]], you can [configure HSTS in `.platform/routes.yaml`](https://fixed.docs.upsun.com/define-routes/https.html#enable-http-strict-transport-security-hsts). - -Beware if you are using a Varnish proxy: -Your version of Varnish may not support HTTPS connections with your web server. -If so, make sure to only enable HSTS between your public-facing proxy and the clients. -When using [[= product_name_cloud =]], this is handled automatically. ## Domain @@ -294,41 +117,3 @@ Log in to their site to enable these protection settings and save the new config CAA allows domain owners to specify which Certificate Authorities (CAs) are permitted to issue SSL/TLS certificates for their domain. This prevents attackers from having certificates issued for domains they don't own, hindering some types of attack. CAA is configured in your DNS zone file. - -## Database - -### Use UTF8MB4 with MySQL/MariaDB - -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. - -### Secure access - -Secure the database access with strong passwords, keys, firewall, encryption in transit, encryption at rest, and so on, as needed. -When using [[= product_name_cloud =]], the provider handles this. - -## Underlying stack - -To avoid exposing your application to any DDOS vulnerabilities or other yet unknown security threats, make sure that you do the following: - -- 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. - -Those steps aren't needed when using [[= product_name_cloud =]], where the provider handles them. - -### 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. -- Update your Composer packages regularly. Don't underestimate [package security advisories](security_advisories.md#package-security-advisories) and update your dependencies so you can install the fixed versions. Also consider the risk of [supply chain attacks](https://en.wikipedia.org/wiki/Supply_chain_attack) which could be mitigated by adopting a policy of waiting a minimum amount of time before using new releases. -- Enable [GitHub Dependabot](https://docs.github.com/en/code-security/concepts/supply-chain-security/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. -- Ensure you get notifications about security fixes in JavaScript dependencies. - -### Monitor logs - -- Enable logging for [[= product_name =]], the web server, any frontend proxies, and the database. -- Monitor the logs for unusual and suspicious activity. Consider using log monitoring software to make this easier. -- Consider using different accounts for manual administrative tasks and for the day-to-day running of your installation. You could for instance configure [[= product_name =]] to use a different database user than the one you use during upgrades. This can make it easier to filter out noise in your log monitoring solution. diff --git a/docs/multisite/languages/back_office_translations.md b/docs/multisite/languages/back_office_translations.md deleted file mode 100644 index d72ab64f639..00000000000 --- a/docs/multisite/languages/back_office_translations.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -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 - -## Enabling back office languages - -All translations are available as a part of [[= product_name =]]. -To enable back office translations, use the following configuration: - -``` yaml -ibexa: - ui: - translations: - 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 is displayed in French. - -!!! tip "Checking browser language" - - 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 `php bin/console cache:clear --siteaccess=admin`. - -### Selecting back office language - -Once you have language packages enabled, you can switch the language of the back office in the **User Settings** menu. - -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'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. - -The method takes as arguments: - -- `id` of the message you want to translate -- an array of parameters -- domain of the string - -Here's an example: - -``` php hl_lines="12-14" -use Symfony\Contracts\Translation\TranslatorInterface; - -final readonly class MyService -{ - public function __construct(private TranslatorInterface $translator) - { - } - - public function getTranslatedDescription(): string - { - return $this->translator->trans( - 'custom.extension.description', - [], - 'custom_extension' - ); - } -} -``` - -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, for example, `custom_extension.en.xliff`. - -``` xml - - - -
- - The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. -
- - - My custom label - My custom label - key: custom.extension.description - - -
-
-``` - -To provide a translation into another language, add it in the `` tag. -For example, in `custom_extension.de.xliff`: - -``` xml - - My custom label - Meine benutzerdefinierte Bezeichnung - key: custom.extension.description - -``` - -The language to display is then selected automatically based on [user preferences or browser setup](#selecting-back-office-language). - -!!! note - - Run `composer run post-update-cmd` which installs your JavaScript translations by using `BazingaJsTranslationBundle`, - and clears the cache of the default SiteAccess. - - Run `php bin/console cache:clear --siteaccess=admin` to clear the back office cache. - You may need to replace `admin` with the back office's SiteAccess name used in your installation. diff --git a/docs/multisite/languages/languages.md b/docs/multisite/languages/languages.md index 3b0ae5f8f07..467672fa452 100644 --- a/docs/multisite/languages/languages.md +++ b/docs/multisite/languages/languages.md @@ -23,13 +23,6 @@ However, even if work on a draft takes time and other translations are updated i 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]([[= user_doc =]]/content_management/translate_content/) in the back office. -After adding a language be sure to dump all assets to the file system: - -```bash -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. @@ -62,136 +55,6 @@ 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 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 isn't mandatory, but can help to distinguish which SiteAccesses can be considered translation SiteAccesses. - -``` yaml -ibexa: - siteaccess: - default_siteaccess: eng - list: - - site - - eng - - fre - - site_admin - - groups: - frontend_group: - - site - - eng - - fre - - # ... - - system: - # Specifying which SiteAccesses are used for translation - frontend_group: - translation_siteaccesses: [fre, eng] - eng: - languages: [eng-GB] - fre: - languages: [fre-FR, eng-GB] - site: - languages: [eng-GB] -``` - -!!! note - - 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**. - -#### Custom locale configuration - -If you need to use a custom locale, you can configure it in `ibexa.yaml`, adding it to the *conversion map*: - -``` yaml -ibexa: - # Locale conversion map between eZ Publish format (e.g. fre-FR) to POSIX (e.g. fr_FR). - # The key is the eZ Publish locale. Check locale.yaml in IbexaCore to see natively supported locales. - locale_conversion: - eng-DE: en_DE -``` - -A locale *conversion map* example [can be found in `ibexa/core`, in `locale.yaml`](https://github.com/ibexa/core/blob/6.0/src/bundle/Core/Resources/config/locale.yml). - -### More complex translation setup - -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: - -``` yaml -ibexa: - siteaccess: - default_siteaccess: eng - list: - - site - - eng - - fre - - mobile_eng - - mobile_fre - - site_admin - - groups: - # This group can be used for common front settings - common_group: - - site - - eng - - fre - - mobile_eng - - mobile_fre - - frontend_group: - - site - - eng - - fre - - mobile_group: - - mobile_eng - - mobile_fre - - # ... - - system: - # Translation SiteAccesses for regular frontend - frontend_group: - translation_siteaccesses: [fre, eng] - - # Translation SiteAccesses for mobile frontend - mobile_group: - translation_siteaccesses: [mobile_fre, mobile_eng] - - eng: - languages: [eng-GB] - fre: - languages: [fre-FR, eng-GB] - site: - languages: [eng-GB] - - mobile_eng: - languages: [eng-GB] - mobile_fre: - languages: [fre-FR, eng-GB] -``` - -### Using implicit *related SiteAccesses* - -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 root `location_id` (see [Multisite](multisite.md)) ### Fallback languages and missing translations diff --git a/docs/multisite/multisite.md b/docs/multisite/multisite.md index 569f080395b..506c68b3c09 100644 --- a/docs/multisite/multisite.md +++ b/docs/multisite/multisite.md @@ -13,8 +13,6 @@ To quickly set up new sites with predefined site templates, use [Site Factory](s [[= cards([ "multisite/siteaccess/siteaccess", - "multisite/set_up_campaign_siteaccess", - "multisite/set_up_translation_siteaccess", "multisite/multisite_configuration", "multisite/site_factory/site_factory", "multisite/site_factory/site_factory_configuration", diff --git a/docs/multisite/multisite_configuration.md b/docs/multisite/multisite_configuration.md index 1945fa281ac..b8cbc383718 100644 --- a/docs/multisite/multisite_configuration.md +++ b/docs/multisite/multisite_configuration.md @@ -1,10 +1,10 @@ --- -description: Configure SiteAccesses to serve different content in different layouts. +description: Configure SiteAccesses to serve different content. --- # Multisite configuration -You can configure the available SiteAccesses under the `ibexa.siteaccess` [configuration key](configuration.md#configuration-files). +You can configure the available SiteAccesses by using the [configuration](configuration.md). ## SiteAccess configuration @@ -36,169 +36,3 @@ You can use groups when you want to use common settings for several SiteAccesses 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. -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. - -!!! caution - - Different SiteAccesses can only have different `var_dir` if they also have different repositories. - Make sure there are no special or Unicode characters in your `var_dir` values. - -### Default SiteAccess - -The `default_siteaccess` setting identifies which SiteAccess is used by default when no other SiteAccess matches. - -``` yaml -ibexa: - siteaccess: - default_siteaccess: site -``` - -### SiteAccess matching - -The `match` setting defines the rule or set of rules by which SiteAccesses are matched. - -For more information, see [SiteAccess matching](siteaccess_matching.md). - -``` yaml -ibexa: - siteaccess: - match: - URIElement: 1 -``` - -### 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`. - -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`: - -``` yaml -en: Company site -fr: Company site France -``` - -## Scope - -All SiteAccess-aware configuration is resolved depending on scope. - -The available scopes are: - -1. `global` -2. SiteAccess -3. SiteAccess group -4. `default` - -`global` overrides all other scopes. -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`. -To define a fallback, use `default`. - -``` yaml -ibexa: - system: - global: - # If set, this value is used regardless of any other configuration - site: - # This is used for the 'site' SiteAccess - site_group: - # This is overwritten by the SiteAccess above, since the SiteAccess has precedence - default: - # 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: - -``` yaml -ibexa: - system: - default: - content_view: - full: - article: - template: full/article.html.twig - match: - Identifier\ContentType: [article] -``` - -### SiteAccesses and Page Builder [[% include 'snippets/experience_badge.md' %]] - -To define which SiteAccesses are available in the submenu in Page Builder, use the following configuration: - -``` yaml -ibexa: - system: - admin: - page_builder: - siteaccess_list: [site, de, fr, no] - de: - page_builder: - siteaccess_list: [site, de] -``` - -If you're using multiple domains, list all domains for an admin SiteAccess under `siteaccess_hosts`: - -``` yaml -ibexa: - system: - admin: - page_builder: - siteaccess_list: [site, de, fr, no] - siteaccess_hosts: - - my_domain.com - - another_domain.org -``` - -!!! 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. - -#### SiteAccess switching in Page Builder - -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. - -Configure this under the `ibexa.systems..content.tree_root` [configuration key](configuration.md#configuration-files), for example: - -``` yaml -ibexa: - system: - : - content: - tree_root: - location_id: 42 - excluded_uri_prefixes: [/media/, /images/] - 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 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`. - It's an array of prefixes. So, for example, `[/media]` would also exclude `/mediation` from root limit. -- `index_page` is the page shown when you access the root index `/`. - -!!! note - - Prefixes aren't case sensitive. - Leading slashes (`/`) are automatically trimmed internally, so they can be ignored. - -!!! tip - - For an example of a multisite configuration, see [Set up campaign SiteAccess](set_up_campaign_siteaccess.md). diff --git a/docs/multisite/set_up_campaign_siteaccess.md b/docs/multisite/set_up_campaign_siteaccess.md deleted file mode 100644 index 506e188a68f..00000000000 --- a/docs/multisite/set_up_campaign_siteaccess.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -description: Create a special SiteAccess to host a campaign site with different content subtree. ---- - -# Set up campaign SiteAccess - -The following example shows how to set up a special `campaign` SiteAccess. -This SiteAccess serves a site devoted to a special campaign, separate from the main company website (`site` SiteAccess). - -The `campaign` site uses a different part of the content tree than the main site, but shares some media files with it. - -## Configure SiteAccesses - -First, in SiteAccess configuration, add the `campaign` SiteAccess to the list under the `ibexa.siteaccess` [configuration key](configuration.md#configuration-files): - -``` yaml -ibexa: - siteaccess: - list: [site, campaign] - groups: - site_group: [site, campaign] - default_siteaccess: site - match: - Map\URI: - summer-sale: campaign - site: site -``` - -The `match` setting ensures that when a visitor accesses the `/summer-sale` URI, they see the `campaign` SiteAccess. - -## Set root folder - -Next, with the following content structure, you need to separate the "Campaign" folder as root for the new site: - -![Content structure](config_content_structure.png "Content structure") - -To do it, set the root level for `campaign` to access the "Campaign" Location and its sub-items only: - -``` yaml -ibexa: - system: - campaign: - content: - tree_root: - # LocationId of "Campaign" - location_id: 57 -``` - -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're in a different part of the tree, via [`excluded_uri_prefixes`](multisite_configuration.md#location-tree): - -``` yaml -ibexa: - system: - campaign: - content: - tree_root: - location_id: 57 - 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'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. diff --git a/docs/multisite/set_up_translation_siteaccess.md b/docs/multisite/set_up_translation_siteaccess.md deleted file mode 100644 index ef471c792c3..00000000000 --- a/docs/multisite/set_up_translation_siteaccess.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -description: Set up SiteAccesses to hold different language versions of a site. ---- - -# Set up translation SiteAccess - -One of common uses for multisite installations is serving different language versions of a website. -To do this, set up multiple SiteAccesses, each corresponding to one language. -Proper configuration means avoiding duplicate content that could affect SEO. - -## Add a language - -First, add a new language for the whole installation. - -!!! tip - - For more details, see [Languages](languages.md). - -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: - -```bash -yarn encore -``` - -## Configure SiteAccesses - -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. - -For example: - -- `www.mysite.com` for English site -- `www.mysite.com/fr` for French site - -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 more. - -``` yaml -ibexa: - siteaccess: - list: [site, fr] - groups: - site_group: [site, fr] -``` - -Under the `ibexa.system` key, add the new SiteAccess. -Indicate that they're meant for translations under `site_group.translation_siteaccesses`: - -``` yaml -ibexa: - system: - site_group: - # ... - translation_siteaccesses: [fr] - fr: - languages: [fre-FR, eng-GB] - site: - languages: [eng-GB] -``` - -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 doesn't exist in French. - -Clear the cache by running: `php bin/console cache:clear`. - -## Set permissions - -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. 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/`. diff --git a/docs/multisite/site_factory/site_factory.md b/docs/multisite/site_factory/site_factory.md index 3afd0628e94..a1d661517a1 100644 --- a/docs/multisite/site_factory/site_factory.md +++ b/docs/multisite/site_factory/site_factory.md @@ -1,176 +1,16 @@ --- month_change: false 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. -It enables you to configure new sites without editing [YAML-based SiteAccess configuration](multisite_configuration.md). +Site Factory is a site management interface, integrated with the back office, enabling you to configure new sites. -!!! 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. +## Provide access -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: - -- [Enable Site Factory section](#enable-site-factory) -- [Disable Site Factory section](#disable-site-factory) - -## Enable Site Factory - -To enable Site Factory, set the `ibexa_site_factory.enabled` [configuration key](configuration.md#configuration-files) to `true`. - -### Configure designs - -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. - -Add the groups under the `ibexa.siteaccess` [configuration key](configuration.md#configuration-files): - -``` yaml -ibexa: - siteaccess: - # ... - groups: - site_group: [import, site] - storefront_group: [site] - corporate_group: [corporate] - example_site_factory_group_1: [ ] - example_site_factory_group_2: [ ] - - system: - example_site_factory_group_1: - example_site_factory_group_2: -``` - -Uncomment the SiteAccess matcher (`Ibexa\SiteFactory\SiteAccessMatcher`): - -``` yaml -ibexa: - siteaccess: - match: - '@Ibexa\SiteFactory\SiteAccessMatcher': ~ -``` - -Next, add the [design engine](design_engine.md) configuration for new specific designs and their theme lists: - -``` yaml -ibexa_design_engine: - design_list: - example_1: [example_1_theme] - example_2: [example_2_theme] -``` - -Finally, configure designs for empty SiteAccess groups: - -``` yaml -ibexa: - system: - example_site_factory_group_1: - design: example_1 - example_site_factory_group_2: - design: example_2 -``` - -### Add site template configuration - -Add thumbnails and names for your site templates: - -```yaml -ibexa_site_factory: - templates: - site1: - siteaccess_group: example_site_factory_group_1 - name: Example site 1 - thumbnail: /path/to/image/example-thumbnail_1.png - site2: - siteaccess_group: example_site_factory_group_2 - name: Example site 2 - 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**. - -There, you should be able to add a new site and choose a design for it. - -### Define domains - -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 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` - -Take a look into the `doc/docker/multihost.yml` file. Here you can define domains. -To add a new domain, add it in `command:` and under frontend and backend aliases as shown in the example below: - -```yaml hl_lines="3 6 11" -services: - web: - command: /bin/bash -c "cd /var/www && cp -a doc/nginx/ibexa_params.d /etc/nginx && bin/vhost.sh --host-name=site.example.com --host-alias='admin.example.com test.example.com' --template-file=doc/nginx/vhost.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" - networks: - frontend: - aliases: - - site.example.com - - admin.example.com - - test.example.com - backend: - aliases: - - site.example.com - - admin.example.com - - test.example.com -``` - -Next, you must define the domains in `etc/hosts`: - -`0.0.0.0 site.example.com admin.example.com test.example.com www.admin.example.com` - -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: - -- `http://site.example.com:8080/` -- `http://admin.example.com:8080/` -- `http://localhost:8080/` -- `http://test.example.com:8080/` - -![Site Factory enabled](site_factory_site_list.png "Site Factory enabled") - -### Define site directory - -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 -ibexa: - system: - default: - site_factory: - sites_location_id: 42 -``` - -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. +To set the Site Factory up, provide sufficient permissions to the users. Set the below policies to allow users to: @@ -183,41 +23,3 @@ Set the below policies to allow users to: 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 =]]/website_organization/work_with_sites/). - -## Disable Site Factory - -Enabled Site Factory may cause following performance issues: - -- [ConfigResolver](dynamic_configuration.md#configresolver) looks for SiteAccesses in the database -- 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'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's uncommented. - -3\. Remove separate connection to database in `config/packages/doctrine.yaml`. - -``` yaml -doctrine: - dbal: - connections: - # ... - # This connection is dedicated for SiteFactory to avoid known issues - site_factory: -``` - -4\. Remove separate cache pool in `config/packages/cache.yaml`. - -``` yaml -framework: - cache: - # ... - pools: - # This pool should be used only by SiteFactory bundle - site_factory_pool: -``` - -The Site Factory should be disabled. diff --git a/docs/multisite/site_factory/site_factory_configuration.md b/docs/multisite/site_factory/site_factory_configuration.md index 865447a463b..58f7f592c67 100644 --- a/docs/multisite/site_factory/site_factory_configuration.md +++ b/docs/multisite/site_factory/site_factory_configuration.md @@ -1,40 +1,9 @@ --- description: Configure Site Factory, including site skeletons. -edition: experience --- # Site Factory configuration -## 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. - -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): - -``` yaml hl_lines="7 12" -ibexa_site_factory: - templates: - site1: - siteaccess_group: example_site_factory_group_1 - name: example_site_1 - thumbnail: /path/to/image/example-thumbnail_1.png - parent_location_id: 62 - site2: - siteaccess_group: example_site_factory_group_2 - name: example_site_2 - thumbnail: /path/to/image/example-thumbnail_2.png - 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 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. @@ -66,45 +35,3 @@ 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 - -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. - -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: - templates: - : - # ... - user_group_skeleton_ids: [ , , ... ] - user_group_skeleton_remote_ids: [ , , ... ] -``` - -Manage the permissions associated to the user group skeleton by [assigning roles]([[= user_doc =]]/permission_management/work_with_permissions/#assign-a-role-to-users). -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. - -## 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. - -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: - # ... - enabled: true - update_roles: [Anonymous, Administrator] -``` - -For more information about roles and policies, see [Permissions](permissions.md). diff --git a/docs/multisite/siteaccess/siteaccess.md b/docs/multisite/siteaccess/siteaccess.md index 3a1e79a126f..1290cec4d97 100644 --- a/docs/multisite/siteaccess/siteaccess.md +++ b/docs/multisite/siteaccess/siteaccess.md @@ -9,23 +9,4 @@ A SiteAccess is a set of configuration settings that the application uses when y When the user visits the site, the system analyzes the URI and compares it to rules specified in the configuration. If it finds a set of fitting rules, this SiteAccess is used. -Each SiteAccess can have different: - -- [templates and designs](design_engine.md) -- [languages](set_up_translation_siteaccess.md) -- [tree roots](multisite_configuration.md#location-tree) -- [repositories](persistence_cache.md#multi-repository-setup) -- [recommendations](connector_installation_configuration.md#siteaccess-aware-configuration) - -Many other settings in the application are also configured per SiteAccess (also known as "SiteAccess-aware"). - -!!! tip - - When possible, always use semantic (SiteAccess-aware) configuration. - Manually editing internal settings is possible, but at your own risk, as unexpected behavior can occur. - -[[= cards([ - "multisite/siteaccess/siteaccess_matching", - "multisite/siteaccess/siteaccess_aware_configuration", - "multisite/siteaccess/injecting_siteaccess", -], columns=3) =]] +Each SiteAccess can have different [configuration](configuration.md). diff --git a/docs/multisite/siteaccess/siteaccess_aware_configuration.md b/docs/multisite/siteaccess/siteaccess_aware_configuration.md deleted file mode 100644 index 24cc5f136b2..00000000000 --- a/docs/multisite/siteaccess/siteaccess_aware_configuration.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -description: Make sure your custom development's configuration can be used with SiteAccesses. ---- - -# 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, 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). -For this, internal keys need to follow the format `..`. where: - -- `namespace` is specific to your app or bundle -- `scope` is the SiteAccess, SiteAccess group, `default` or `global` -- `parameter_name` is the actual setting *identifier* - -For more information about the ConfigResolver, namespaces and scopes, see [configuration basics](configuration.md). - -!!! 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). - -The example below assumes you're using an `Acme\ExampleBundle`. -Remember to register the bundle by adding it to `config/bundles.php`: - -``` php {skip-validation} -return [ - // ... - 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: - -``` php hl_lines="19" -[[= include_code('code_samples/multisite/siteaccess/Configuration.php') =]] -``` - -!!! note - - Default name for the *SiteAccess root node* is `system`, but you can customize it. - To do this, pass the name you want to use as a second argument of `$this->generateScopeBaseNode()`. - -This enables you to use the following SiteAccess-aware configuration: - -``` yaml -acme_example: - system: - : - name: name_1 - custom_setting: - number: 456 - enabled: true - : - name: name_2 - custom_setting: - string: value - number: 123 - enabled: false -``` - -## Mapping to internal settings - -Semantic configuration must always be mapped to internal key/value settings within the service container. -You usually do it in the [service container](php_api.md#service-container) extension. - -``` php -[[= include_file('code_samples/multisite/siteaccess/AcmeExampleExtension.php', 0, 42) =]][[= include_file('code_samples/multisite/siteaccess/AcmeExampleExtension.php', 53, 62) =]] -``` - -You can also map simple settings by calling `$processor->mapSetting()`, without having to call `$processor->mapConfig()` with a callable. - -``` php -[[= include_code('code_samples/multisite/siteaccess/AcmeExampleExtension.php', 45, 46, remove_indent=True) =]] -``` - -!!! caution "Important" - - Always ensure you have defined and loaded default settings. - -In `@AcmeExampleBundle/Resources/config/default_settings.yaml`: - -``` yaml -parameters: - acme_example.default.name: name_1 - acme_example.default.custom_setting: - string: ~ - number: 0 - enabled: false -``` - -### Merging hash values between scopes - -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 -[[= include_code('code_samples/multisite/siteaccess/AcmeExampleExtension.php', 49, 49, remove_indent=True) =]] -``` - -Consider the following default config in `default_settings.yaml`: - -``` yaml -parameters: - acme_example.default.custom_setting: - string: ~ - os_types: [windows] - number: 0 - enabled: false - language: php -``` - -And then this semantic configuration in `config/packages/acme.yaml`: - -``` yaml -acme_example: - system: - siteaccess_group: - custom_setting: - string: value - number: 123 - - # Assuming "siteaccess1" is part of "siteaccess_group" - siteaccess1: - custom_setting: - os_types: [linux, macos] - number: 456 - enabled: true - 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: - -``` yaml -parameters: - acme_example.siteaccess1.custom_setting: - string: value - os_types: [linux, macos] - number: 456 - enabled: true - language: javascript -``` - -#### 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. - -You can add another level by passing `ContextualizerInterface::MERGE_FROM_SECOND_LEVEL` as the third argument to `$contextualizer->mapConfigArray()`: - -``` php -[[= include_code('code_samples/multisite/siteaccess/AcmeExampleExtension.php', 52, 53, remove_indent=True) =]] -``` - -When you use `ContextualizerInterface::MERGE_FROM_SECOND_LEVEL` with the configuration above, you get the following result: - -``` yaml -parameters: - acme_example.siteaccess1.custom_setting: - string: value - os_types: [windows, linux, macos] - number: 456 - enabled: true - 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. - -!!! note - - 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 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()`. diff --git a/docs/multisite/siteaccess/siteaccess_matching.md b/docs/multisite/siteaccess/siteaccess_matching.md deleted file mode 100644 index 299ce702c4b..00000000000 --- a/docs/multisite/siteaccess/siteaccess_matching.md +++ /dev/null @@ -1,301 +0,0 @@ ---- -description: Use SiteAccess matchers to control which site is served when and to which user. -page_type: reference ---- - -# SiteAccess matching - -To be usable, every SiteAccess must be matched by one of configured matchers. -By default, all SiteAccesses are matched using `URIElement: 1`. - -You can configure SiteAccess matchers under the `ibexa.siteaccess.match` [configuration key](configuration.md#configuration-files): - -``` yaml -ibexa: - siteaccess: - list: [site, event] - groups: - site_group: [site, event] - default_siteaccess: site - match: - Map\URI: - site: site - campaign: event -``` - -`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: - -```yaml -ibexa: - siteaccess: - match: - Compound\LogicalAnd: - corporate: - matchers: - Map\URI: - corporate: true - Map\Host: - my.site: true - match: corporate - Map\Host: - my.site: mysite -``` - -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 (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()`. - -## Available SiteAccess matchers - -- [`URIElement`](#urielement) -- [`URIText`](#uritext) -- [`HostElement`](#hostelement) -- [`HostText`](#hosttext) -- [`Map\Host`](#maphost) -- [`Map\URI`](#mapuri) -- [`Map\Port`](#mapport) -- [`Ibexa\SiteFactory\SiteAccessMatcher`](#ibexasitefactorysiteaccessmatcher) - -### `URIElement` - -Maps a URI element to a SiteAccess. - -In configuration, provide the element number you want to match (starting from 1). - -``` yaml -ibexa: - siteaccess: - match: - URIElement: 2 -``` - -!!! note - - When you use a value > 1, the matcher concatenates the elements with `_`. - -Example URI `/my_site/company/pages` matches SiteAccess `my_site_company`. - -### `URIText` - -Matches URI using prefix and suffix sub-strings in the first URI segment. - -In configuration, provide the prefix and/or suffix (neither is required). - -``` yaml -ibexa: - siteaccess: - match: - URIText: - prefix: main- - suffix: /company -``` - -Example URI `/main-event/company/page` matched SiteAccess `event`. - -### `HostElement` - -Maps an element in the host name to a SiteAccess. - -In configuration, provide the element number you want to match (starting from 1). - -``` yaml -ibexa: - siteaccess: - match: - HostElement: 2 -``` - -Example host name `www.example.com` matches SiteAccess `example`. - -### `HostText` - -Matches a SiteAccess in the host name, using pre and/or post sub-strings. - -In configuration, provide the prefix and/or suffix (none are required). - -``` yaml -ibexa: - siteaccess: - match: - HostText: - prefix: www. - suffix: .com -``` - -Example host name `www.example.com` matches SiteAccess `example`. - -### `Map\Host` - -Maps a host name to a SiteAccess. - -In configuration, provide a hash map of host/SiteAccess. - -``` yaml -ibexa: - siteaccess: - match: - Map\Host: - www.page.com: event - adm.another-page.fr: event_admin -``` - -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. - -### `Map\URI` - -Maps a URI to a SiteAccess. - -In configuration, provide a hash map of URI/SiteAccess. - -```yaml -ibexa: - siteaccess: - match: - Map\URI: - campaign: event - site: site -``` - -Example URI `/campaign/general/articles` matches SiteAccess `event`. - -### `Map\Port` - -Maps a port to a SiteAccess. - -In configuration, provide a hash map of Port/SiteAccess. - -``` yaml -ibexa: - siteaccess: - match: - Map\Port: - 80: event - 8080: site -``` - -Example URL `http://my_site.com:8080/content` matches SiteAccess `site`. - -### `Ibexa\SiteFactory\SiteAccessMatcher` [[% include 'snippets/experience_badge.md' %]] - -Enables the use of [Site Factory](site_factory.md). -Doesn't take any parameters in configuration: - -``` yaml -ibexa: - siteaccess: - match: - '@Ibexa\SiteFactory\SiteAccessMatcher': ~ -``` - -## Custom matchers - -Beside the built-in matchers, you can also use your own services to match SiteAcceses: - -``` yaml -ibexa: - siteaccess: - list: [site] - groups: - site_group: [site] - default_siteaccess: site - match: - '@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). - -## Combining SiteAccess matchers - -You can combine more than one SiteAccess matcher to match more complex situations, for example: - -- `http://example.com/en` matches `site_en` (match host example.com and the `en` URI element) -- `http://example.com/fr` matches `site_fr` (match host example.com and the `fr` URI element) -- `http://admin.example.com` matches `site_admin` (match host admin.example.com) - -To combine matchers, use compound logical matchers: - -- `Compound\LogicalAnd` -- `Compound\LogicalOr` - -Each compound matcher specifies two or more sub-matchers. -A rule applies if all the matchers combined with the logical matcher are positive. - -To get the result above, you need to combine `Map\Host` and `Map\Uri` using `LogicalAnd`. -When both the URI and host match, the SiteAccess configured with `match` is used. - -``` yaml -ibexa: - siteaccess: - match: - Compound\LogicalAnd: - # You don't need to specify matching values (true is enough). - site_en: - matchers: - Map\URI: - en: true - Map\Host: - example.com: true - match: site_en - site_fr: - matchers: - Map\URI: - fr: true - Map\Host: - example.com: true - match: site_fr - Map\Host: - admin.example.com: site_admin -``` - -When using `Compound\LogicalAnd`, all inner matchers must match. -All matchers must implement `VersatileMatcher`. -When using `Compound\LogicalOr`, the first inner matcher succeeding wins. - -## Matching by request header - -You can define which SiteAccess to use by setting an `X-Siteaccess` header in your request. -This can be useful for REST requests. - -In such a case, `X-Siteaccess` must be the SiteAccess name (for example, `site` or `en`). - -## Matching by environment variable - -You can also define which SiteAccess to use directly by using the `EZPUBLISH_SITEACCESS` environment variable. - -This is recommended if you want to get performance gain since no matching logic is done in this case. - -You can define this environment variable directly in web server configuration: - -``` vcl - -# This configuration assumes that mod_env is activated - - DocumentRoot "/path/to/ibexa/web/folder" - ServerName example.com - ServerAlias www.example.com - SetEnv EZPUBLISH_SITEACCESS demo_site - -``` - -!!! tip - - You can configure the variable by using the PHP-FPM configuration file. - For more information, see [PHP-FPM documentation](https://www.php.net/manual/en/install.fpm.configuration.php). - -!!! note "Precedence" - - The precedence order for SiteAccess matching is the following (the first matched wins): - - 1. Request header - 1. Environment variable - 1. Configured matchers diff --git a/docs/multisite/translations_management/configure_translations_management.md b/docs/multisite/translations_management/configure_translations_management.md index e359b4987ac..b5f31d74a7e 100644 --- a/docs/multisite/translations_management/configure_translations_management.md +++ b/docs/multisite/translations_management/configure_translations_management.md @@ -1,15 +1,14 @@ --- -description: Install translations management and configure translation providers, language pairs, and more. -edition: lts-update +description: Configure translation providers, language pairs, and more for translations management. month_change: true --- # Configure translations management -`ibexa/translations-management` extends [[= product_name =]]'s built-in language management tools that editors use for content item and product translation. -It introduces a plugin that handles automatic translations through the translation provider system by connecting to REST APIs and AI services. -By using the new [side-by-side editing interface](#side-by-side-translation-view), editors can compare source and target values, provide content item and product translations in a single view, and reject or approve translations. -There are multiple extension points that you can use to [customize different areas of the translation workflow](extend_translations_management.md). +[[= product_name =]]'s language management tools allow editors to smoothly work with content item and product translation. +By using automatic translations, editors can quickly translate fields of content items and products into another languages. + +By using the [side-by-side editing interface](#side-by-side-translation-view), editors can compare source and target values, provide content item and product translations in a single view, and reject or approve translations. !!! note "Translation limitations" @@ -21,183 +20,15 @@ There are multiple extension points that you can use to [customize different are Also, [product attributes](products.md#product-attributes) remain non-translatable and are inactive in the side-by-side translation view. -## Install package - -To install the Translations management [LTS Update](editions.md#lts-updates), run the following command: - -```bash -composer require ibexa/translations-management -``` - -If you're installing Translations management LTS Update as part of the installation process of a fresh [[= product_name =]] instance, this step copies the migration files into the project's migrations directory. -It also creates the database tables required for the review workflow, and adds the default action configurations in the database. -Otherwise follow the steps below. - -### Existing installations - -To add the Translations management LTS Update to an existing [[= product_name =]] instance, after installation, you must create database tables and action configurations yourself. - -#### Modify database schema - -Add the tables needed by the bundle: - -=== "MySQL" - - ```sql - [[= include_code('code_samples/translations_management/install/schema.mysql.sql', indent_level=1) =]] - ``` - -=== "PostgreSQL" - - ```sql - [[= include_code('code_samples/translations_management/install/schema.postgresql.sql', indent_level=1) =]] - ``` - -The script creates the required data structures, but doesn't add any data to the database. - -#### Add action configurations - -To complete the setup, import and run the AI Action Configuration migrations required by the [AI connectors](configure_ai_actions.md) that you use: - -```bash -php bin/console ibexa:migrations:import vendor/ibexa/translations-management/src/bundle/Resources/migrations/2026_05_06_15_00_auto_translate_openai_action_configuration.yaml -php bin/console ibexa:migrations:import vendor/ibexa/translations-management/src/bundle/Resources/migrations/2026_05_11_10_00_auto_translate_gemini_action_configuration.yaml -php bin/console ibexa:migrations:import vendor/ibexa/translations-management/src/bundle/Resources/migrations/2026_05_12_08_30_auto_translate_anthropic_action_configuration.yaml -php bin/console ibexa:migrations:migrate -``` - -## Configure translation providers - -Translation providers are the services that perform the actual text translation. -If you fail to configure them, the automatic translation feature is disabled in the editor's UI, and a message is displayed that prompts the user to contact the administrator. - -The Translations management package comes with two types of translation services: - -- **REST API-based providers** - call a translation service such as Google Translate or DeepL directly by using an API key. -- **AI-based providers** - send translation requests through the [AI Actions](configure_ai_actions.md) framework, relying on the same model selection and policy controls as other AI features in [[= product_name =]]. - -!!! note "Prerequisites for the default translation providers" - - Before you can configure translation providers, you must meet the following prerequisites: - - - For the REST API-based translation providers, add API keys that you obtain from the machine translation services to the `.env` file in the root directory of your project. - - For the AI-based translation providers, [configure AI Actions and the corresponding connectors](configure_ai_actions.md). - -Out of the box, Translations management can support the following translation providers: - -| Provider | Type | -|---|---| -| Google Translate | REST API | -| DeepL | REST API | -| OpenAI | AI Actions | -| Anthropic (Claude) | AI Actions | -| Google Gemini | AI Actions | - -### Built-in AI providers - -If you meet the above prerequisites, and you install the Translations management package, the installation process automatically creates AI [Action Configurations](extend_ai_actions.md#action-configurations) for OpenAI (`auto_translate_openai`), Google Gemini (`auto_translate_gemini`), and Anthropic Claude (`auto_translate_anthropic`). - -You can use them directly in provider configuration: - -| Action Configuration identifier | Handler | Default model | -|---|---|---| -| `auto_translate_openai` | `openai-text-to-text` | `gpt-5` | -| `auto_translate_gemini` | `gemini-text-to-text` | `gemini-pro-latest` | -| `auto_translate_anthropic` | `anthropic-text-to-text` | `claude-sonnet-4-20250514` | - -You can then [customize these configurations in the UI]([[= user_doc =]]/ai_actions/work_with_ai_actions/#edit-existing-ai-actions). - -### Add YAML configuration - -In `config/packages`, create a `translations_management.yaml` file. -You configure the providers in the SiteAccess-aware `translations_management` namespace. - -``` yaml -ibexa: - system: - default: - translations_management: - auto_translate: - providers: - google: - apiKey: '%env(GOOGLE_TRANSLATE_API_KEY)%' - deepl: - apiKey: '%env(DEEPL_API_KEY)%' - openai: - actionConfigurationIdentifier: 'auto_translate_openai' - anthropic: - actionConfigurationIdentifier: 'auto_translate_anthropic' - gemini: - actionConfigurationIdentifier: 'auto_translate_gemini' -``` - -The `apiKey` values must reference API key values that you added to the `.env` file. -The `actionConfigurationIdentifier` values must reference existing Action Configurations. -If a value is missing or empty, the provider doesn't appear in the UI as a selectable option. - -#### Advanced translation provider options - -In addition to their required authentication keys, all providers support two optional ones: - -- `supportedLanguageCodes` - overrides the default list of language codes that this provider accepts -- `languageCodesMap` - maps language codes used by [[= product_name =]], for example, `eng-GB`, to the provider-specific codes the API expects - -REST API-based providers come with their own language code lists and mappings, therefore both settings are optional. -If configured, they replace the built-in defaults, so use them to restrict available languages or override mappings. - -!!! tip "Default values" - - To check the built-in defaults for the existing providers, run: - - ``` bash - php bin/console debug:container --parameters | grep ibexa.translations_management.auto_translate.provider - ``` - - The output lists the default `supported_language_codes` and `language_codes_map` values for each configured provider, which you can use as a reference. - -AI-based providers don't provide built-in language code lists or mappings. -If `supportedLanguageCodes` is not configured, all enabled languages are used, converted to POSIX format. -If `languageCodesMap` is not configured, the system automatically tries to match [[= product_name =]] language codes to the one supported by the provider by trying different format variants, for example, `eng-GB`, `en-GB`, or `en`. -If no match is found, an `UnsupportedLanguageException` is thrown at runtime. -Therefore, for AI-based providers, it's recommended that you explicitly configure both options. - -``` yaml -ibexa: - system: - default: - translations_management: - auto_translate: - providers: - # ... - openai: - actionConfigurationIdentifier: 'auto_translate_openai' - supportedLanguageCodes: - - 'eng-GB' - - 'ger-DE' - - 'fre-FR' - languageCodesMap: - eng-GB: 'en' - ger-DE: 'de' - fre-FR: 'fr' -``` - -The `supportedLanguageCodes` setting controls which languages are available when creating [language pairs](#define-language-pairs) for this provider. - -!!! note "Identifier normalization" - - Provider identifiers are normalized from hyphens to underscores during configuration processing. - Use one format consistently. - If you mix `my-provider` and `my_provider` for the same provider, it results in an exception. ## Define language pairs Language pair definitions decide which provider handles each source-to-target language combination by default. -For example, you can decide that English to French translations should use DeepL. When an editor [opens the translation modal]([[= user_doc =]]/content_management/translate_content/#add-new-translation) and selects a matching language combination, the provider that you chose is pre-selected in the dropdown. The editor can override the pre-selection. The list of languages available when creating a language pair is determined by what each provider supports. -You can only select the languages that are present in a provider's [supported list](#advanced-translation-provider-options) for that provider's pairs. +You can only select the languages that are present in a provider's supported list for that provider's pairs. You [manage language pairs in the back office]([[= user_doc =]]/content_management/translate_content/#manage-translation-services-and-language-pairs). @@ -208,12 +39,6 @@ The [side-by-side translation view]([[= user_doc =]]/content_management/translat Content types that contain the `ibexa_landing_page` or `ibexa_form` fields can't be opened in the side-by-side translation view. Editors can open them in the standard single-language editor. -You can exclude the support for additional content types if needed. -To do it, [define custom exclusion rules](extend_translations_management.md#define-custom-exclusion-rules). - -!!! note "Meta fields" - - Fields marked with [`meta: true`](content_tab_switcher.md#add-meta-tab) and fields that belong to groups listed in [`admin_ui_forms.content_edit.meta_field_groups_list`](content_tab_switcher.md#configure-field-groups-for-meta-tab) aren't rendered in the side-by-side translation view. For a description of the side-by-side view and its functions from the editor's perspective, see [User Documentation]([[= user_doc =]]/content_management/translate_content/#side-by-side-translation-view). @@ -224,12 +49,3 @@ Each editor can configure them independently, and they don't affect other users. For example, editors can choose whether the target language column appears on the left or right in the side-by-side translation view. By default, the target is on the right, and each editor can override this default. - -You can change the system-wide default in configuration: - -``` yaml -parameters: - ibexa.site_access.config.default.translations_management.default_side_by_side_column_order: source_right_target_left -``` - -The accepted values are `source_left_target_right` (default) and `source_right_target_left`. diff --git a/docs/multisite/translations_management/translations_management.md b/docs/multisite/translations_management/translations_management.md index 71682f03437..cd008c000ff 100644 --- a/docs/multisite/translations_management/translations_management.md +++ b/docs/multisite/translations_management/translations_management.md @@ -1,6 +1,5 @@ --- description: Translations management brings multiple features that help managers, developers and localization teams automate multilingual content delivery. -edition: lts-update page_type: landing_page month_change: true --- @@ -12,9 +11,5 @@ Translations management helps [[= product_name =]] developers and editors delive [[= cards([ "multisite/translations_management/translations_management_guide", "multisite/translations_management/configure_translations_management", - "multisite/translations_management/translate_with_cli", - "multisite/translations_management/extend_translations_management", - "api/event_reference/translations_management_events", - ("api/php_api/php_api_reference/namespaces/ibexa-contracts-translationsmanagement.html", "PHP API Reference", "Ibexa\\Contracts\\TranslationsManagement"), ], columns=3) =]] diff --git a/docs/multisite/translations_management/translations_management_guide.md b/docs/multisite/translations_management/translations_management_guide.md index 3062385e203..5cebbcd1e9d 100644 --- a/docs/multisite/translations_management/translations_management_guide.md +++ b/docs/multisite/translations_management/translations_management_guide.md @@ -1,6 +1,5 @@ --- description: Translations management helps managers, developers and localization teams with multilingual content delivery. -edition: lts-update month_change: true --- @@ -17,14 +16,10 @@ Content managers, editors, translators, and proofreaders who work with multiling The Translations management package addresses these pain points through a side-by-side view, machine translation and the ability to invite reviewers to collaborate on the translation of content items or products. -The package integrates with the [AI Actions framework](ai_actions_guide.md) to support machine translation providers such as Google Translate and DeepL, and AI-powered translation services like OpenAI, Anthropic, and Google Gemini. +The package integrates with the [AI Actions](ai_actions_guide.md) to support AI-powered translation services through [[= ai_product_name =]]. Administrators can manage providers and configure default provider-to-language-pair mappings directly in [[= product_name =]]'s back office, while editors can trigger machine translation from the content editing interface. -## Availability - -Translations management is an opt-in capability available as an [LTS Update](editions.md#lts-updates) for all [[= product_name =]] editions, starting with the v5.0.10 version. - ## How it works Before the translation flow can happen, an administrator sets up the translation providers and assigns language pairs to them. @@ -47,8 +42,6 @@ Editors see the configured provider pre-selected when creating a new translation ![Creating a language pair](translations_management_language_pairs.png "Creating a language pair") -The package provides integrations with several translation providers, including REST API-based services such as Google Translate and DeepL, and AI-powered services through the [AI Actions](ai_actions_guide.md). - ### Side-by-side translation view Translations management introduces a [side-by-side translation view]([[= user_doc =]]/content_management/translate_content/#side-by-side-translation-view) that displays the read-only source language content next to an editable target language form. @@ -71,37 +64,22 @@ Editors can: Products are editable in the side-by-side view, but [product attributes aren't translatable](products.md#product-attributes). -### Command-line translation - -The Translations management package exposes a [console command](translate_with_cli.md) for translating content items from the command line. -You can use it for batch processing or automated workflows. - ### Translation review When a draft translation of a content item or product is created by going through the automatic translation process in the back office, the system creates a review status record and marks the draft as "For review". -The console command bypasses this and drafts created with command-line translation aren't assigned a review status. Editors can [accept or reject the translation]([[= user_doc =]]/content_management/translate_content/#review-automatic-translation) directly in the side-by-side view. Accepted drafts are marked as "Translated". When the editor rejects the translation, the status doesn't change, but the system records that the draft translation required corrections for statistical purposes. A draft translation in the "Translated" state can't be rejected anymore. -The `ibexa_auto_translation_review` workflow is separate from the [editorial workflow](workflow.md). +This translation workflow is separate from the [editorial workflow](workflow.md). Accepting or rejecting draft translations does not trigger editorial workflow transitions or notifications. !!! note "No review for human translations" Draft translations that were created by a human don't have a review status. -### Extensibility - -Developers can [extend the translations management](extend_translations_management.md) package: - -- create custom translation providers -- add support for custom fields -- add custom content type exclusion rules -- tap into the translation lifecycle with [events](translations_management_events.md) - ## Benefits ### Streamlined translation process diff --git a/docs/on_premise.md b/docs/on_premise.md new file mode 100644 index 00000000000..23d9fd7e2cc --- /dev/null +++ b/docs/on_premise.md @@ -0,0 +1,7 @@ +--- +description: Cohesivo On-premise +--- + +# Cohesivo On-premise + +TODO: Combine Headless, Experience, Commerce into a product guide for On-Premise diff --git a/docs/permissions/limitation_reference.md b/docs/permissions/limitation_reference.md index e91605627c8..c9f2c213cdf 100644 --- a/docs/permissions/limitation_reference.md +++ b/docs/permissions/limitation_reference.md @@ -9,7 +9,6 @@ month_change: false ## Blocking limitation A generic limitation type to use when no other limitation has been implemented. -Without any limitation assigned, a `LimitationNotFoundException` is thrown. 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. @@ -19,21 +18,6 @@ It's called "blocking" because it always informs the permissions system that the |------|------|------| |``|``|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. -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 - ibexa.api.role.limitation_type.function_list: - class: Ibexa\Core\Limitation\BlockingLimitationType - arguments: ['FunctionList'] - tags: - - {name: ibexa.permissions.limitation_type, alias: FunctionList} -``` - ## Activity log Owner limitation The Activity log Owner (`ActivityLogOwner`) limitation specifies if a user can see only their own [recent activity](recent_activity.md) log entries, and not entries from other users. @@ -95,7 +79,7 @@ If you also combine it with `Owner of Parent` limitation, you effectively limit |------|------|------| |``|``|All valid content type IDs can be set as value(s)| -## Field Group limitation [[% include 'snippets/experience_badge.md' %]] +## Field Group limitation 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. @@ -226,7 +210,7 @@ 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' %]] +## Segment group limitation The segment group (`SegmentGroup`) limitation specifies whether the user has access segments within a specific segment group. diff --git a/docs/permissions/limitations.md b/docs/permissions/limitations.md index 0885f6db3d8..12eca2ce5c0 100644 --- a/docs/permissions/limitations.md +++ b/docs/permissions/limitations.md @@ -18,12 +18,6 @@ Certain limitations also serve as role limitations, which means they can be used Currently, this covers [subtree of location](limitation_reference.md#subtree-limitation) and [Section](limitation_reference.md#section-limitation). `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` based on `Limitation` value and current user which `SearchService` by default applies to Search Criteria for filtering search based on permissions. | ## Limitation reference diff --git a/docs/permissions/permission_overview.md b/docs/permissions/permission_overview.md index 5f89078342d..7bc3f48bdaa 100644 --- a/docs/permissions/permission_overview.md +++ b/docs/permissions/permission_overview.md @@ -31,54 +31,3 @@ Instead, try to organize your content so that it can be covered with general rol 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 doesn't have access to the controller unless they have the `section/view` policy: - -``` php {skip-validation} -use Ibexa\Core\MVC\Symfony\Security\Authorization\Attribute; - -public function performAccessCheck(): void -{ - parent::performAccessCheck(); - $this->denyAccessUnlessGranted(new Attribute('section', 'view')); -} -``` - -`Attribute` accepts three arguments: - -- `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. - -### Checking user access - -To check if a user has access to an operation, use the `isGranted()` method. -For example, to check if content can be assigned to a Section: - -``` php {skip-validation} -$hasAccess = $this->isGranted( - new Attribute('section', 'assign', ['valueObject' => $contentInfo, 'targets' => [$section]]) -); -``` - -You can also use the permission resolver (`Ibexa\Core\Repository\Permission\PermissionResolver`). -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. - -### Blocking access to controller action - -To block access to a specific action of the controller, add the following to the action's definition: - -``` php {skip-validation} -$this->denyAccessUnlessGranted(new Attribute('state', 'administrate')); -``` diff --git a/docs/permissions/permission_use_cases.md b/docs/permissions/permission_use_cases.md index 2e3805be4f1..97bf1055237 100644 --- a/docs/permissions/permission_use_cases.md +++ b/docs/permissions/permission_use_cases.md @@ -18,17 +18,15 @@ To allow the user to enter the back office interface and view all content, set t 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' %]] +## Create content without publishing -You can use this option together with [[= product_name_exp =]]'s content review options. +You can use this option together with [[= product_name =]]'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 or proofreader). - `content/create` - `content/edit` -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: diff --git a/docs/permissions/policies.md b/docs/permissions/policies.md index 8611e376c65..85f8a8a2eda 100644 --- a/docs/permissions/policies.md +++ b/docs/permissions/policies.md @@ -87,7 +87,7 @@ Each role you assign to user or user group consists of policies which define, wh | | `setup` | unused | | | | `system_info` | view the **System Information** tab in Admin | | -#### Sites [[% include 'snippets/experience_badge.md' %]] +#### Sites | Module | Function | Effect | Possible limitations | |---------------------|------------------------------|-------------------------------------------------------------------------------------------------------|----------------------| @@ -123,7 +123,7 @@ Each role you assign to user or user group consists of policies which define, wh | | `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) | +| | `publish` | publish content. Without this Policy, the User can only save drafts or send them for review | [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) | | | `restore` | restore content from Trash | | diff --git a/docs/product_catalog/add_remote_pim_support.md b/docs/product_catalog/add_remote_pim_support.md deleted file mode 100644 index bdfc39d7b38..00000000000 --- a/docs/product_catalog/add_remote_pim_support.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -description: Install and configure the Remote PIM example package. ---- - -# Add Remote PIM support - -[[= product_name =]] provides flexible product catalog infrastructure that works with external Product Information Management (PIM) systems. -For advanced product data management without custom development, you can use the readily available [[[= pim_product_name =]] integration](quable/quable.md) with [[= product_name =]]. - -To implement [Remote PIM support](product_catalog_guide.md#remote-pim-support) for a custom integration, you can build upon a foundation provided by [[= product_name_base =]]. - -While doing so, you must implement services that process data coming from the remote PIM. - -Before you create your own solution, you can [install an example package](#install-remote-pim-example-package) and modify it to connect to your external data source. - -## Implement services - -To connect to your remote PIM, provide your implementation of the following services that process product data: - -- AssetService, used to get assets assigned to a product. -- AttributeDefinitionService, used to get information about product attributes. -- AttributeGroupService, used to get information about product attribute groups. -- ProductService, used to get product information. -- ProductTypeService, used to work with product types. - -## Switch to the new product catalog engine - -To inform the application that the product catalog engine has been replaced by an external one, in `config/packages/ibexa_product_catalog.yaml`, set the new product catalog engine, for example: - -``` yaml -ibexa_product_catalog: - engines: - : - type: - options: - root_location_remote_id: ibexa_product_catalog_root -``` - -Then configure the application to use the engine defined above as the default product data repository: - -``` yaml -ibexa: - repositories: - : - # ... - product_catalog: - engine: -``` - -!!! note "Enabling the remote PIM support" - - By default, the `ibexa.repositories..product_catalog.engine.type` key is set to `local`, which informs [[= product_name =]] that the built-in product catalog capabilities are used. - By changing this setting and the `ibexa.repositories..product_catalog.engine` setting from `default` to your custom value, you inform [[= product_name =]] that you're using a remote PIM. - -## Install Remote PIM example package - -The example implementation provides services that take over the role of services provided by the product catalog package. -You can modify them to suit your needs. - -Install the `ibexa/example-in-memory-product-catalog` package: - -``` bash -composer config repositories.remote-pim vcs https://github.com/ibexa/example-in-memory-product-catalog -composer require ibexa/example-in-memory-product-catalog: -``` diff --git a/docs/product_catalog/attributes/date_and_time.md b/docs/product_catalog/attributes/date_and_time.md index e07ddc1a766..c61c5ffc763 100644 --- a/docs/product_catalog/attributes/date_and_time.md +++ b/docs/product_catalog/attributes/date_and_time.md @@ -10,7 +10,7 @@ You can use it to store, for example, manufacturing dates, expiration dates, or ## Usage -You can manage the date and time attribute type through the back office, [data migrations](importing_data.md#date-and-time-attributes), REST, or through the PHP API. +You can manage the date and time attribute type through the back office or REST/ It also supports [searching](product_search_criteria.md) by using [DateTimeAttribute](datetimeattribute_criterion.md) and [DateTimeAttributeRange](datetimeattributerange_criterion.md) criteria. ![Creating a product using a date and time attribute with "trimester" accuracy level](img/datetime.png "Creating a product using a date and time attribute with "trimester" accuracy level") diff --git a/docs/product_catalog/attributes/symbol_attribute_type.md b/docs/product_catalog/attributes/symbol_attribute_type.md index 2df3d0e7691..f2efca18bb2 100644 --- a/docs/product_catalog/attributes/symbol_attribute_type.md +++ b/docs/product_catalog/attributes/symbol_attribute_type.md @@ -10,7 +10,7 @@ This feature allows you to store standard product identifiers (such as EAN or IS ## Build-in symbol attribute formats -The built-in symbol attribute formats in `ibexa/product-catalog-symbol-attribute` are listed below: +The built-in symbol attribute formats are listed below: | Name | Description | Example | |-----------------|-----------------|-----------------| @@ -29,59 +29,6 @@ The built-in symbol attribute formats in `ibexa/product-catalog-symbol-attribute Maximum length of the symbol value is 160 characters. -## Create custom symbol attribute format - -Under the `ibexa_product_catalog_symbol_attribute.formats` key, you can use configuration to create your own symbol format. - -See the example below: - -``` yaml -ibexa_product_catalog_symbol_attribute: - formats: - manufacturer_part_number: - name: 'Manufacturer Part Number' - pattern: '/^[A-Z]{3}-\d{5}$/' - examples: - - 'RPI-14645' - - 'MSS-24827' - - 'SEE-15444' -``` - -This following example specifies the format for a "Manufacturer Part Number", defined with the `manufacturer_part_number` identifier. - -The pattern is specified using a regular expression. -According to the pattern option, the attribute value: - -- must be a string -- begins with three capital letters (A-Z), followed by a hyphen ("-") -- ends with five digits (0-9), with no other characters before or after - -Certain formats, such as the International Standard Book Number (ISBN-10) and the European Article Number (EAN-13), contain checksum digits and are self-validating. - -To validate checksum of symbol: - -1\. Create a class implementing the [`\Ibexa\Contracts\ProductCatalogSymbolAttribute\Value\ChecksumInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalogSymbolAttribute-Value-ChecksumInterface.html) interface. - -2\. Register the class as a service using the `ibexa.product_catalog.attribute.symbol.checksum` tag and specify the format identifier using the `format` attribute. - -See below the example implementation of checksum validation using Luhn formula: - -``` php -[[= include_code('code_samples/product_catalog/Symbol/Format/Checksum/LuhnChecksum.php') =]] -``` - -Example service definition: - -``` yaml -services: - App\PIM\Symbol\Format\Checksum\LuhnChecksum: - tags: - - name: ibexa.product_catalog.attribute.symbol.checksum - format: my_format -``` - -The format attribute (`my_format`) is the identifier used under the `ibexa_product_catalog_symbol_attribute.formats` key. - ## Search for products with given symbol attribute You can use `SymbolAttribute` Search Criterion to find products by symbol attribute: diff --git a/docs/product_catalog/enable_purchasing_products.md b/docs/product_catalog/enable_purchasing_products.md deleted file mode 100644 index ed73b78fafa..00000000000 --- a/docs/product_catalog/enable_purchasing_products.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -description: Ensure your product catalog is ready for use with full configuration of products that enables purchasing them in the frontend shop. ---- - -# Enable purchasing products - -To enable adding product to cart and purchasing from the catalog, the following configuration is required: - -- at least [one region and one currency for the shop](#region-and-currency) -- [VAT rates per region](#vat-rates) and for each product type -- at least one [price](prices.md) for the product -- [availability](products.md#product-availability-and-stock) with positive or infinite stock for the product or product variant - -!!! note "Configuring products in the UI" - - After you configure the region, currency and VAT rates for regions in settings, the store manager must set up the remaining parameters in the UI, such as, [VAT rates per product type]([[= user_doc =]]/product_catalog/create_product_types/#vat), descriptions, attributes, assets, [prices]([[= user_doc =]]/product_catalog/manage_prices/), and [availability]([[= user_doc =]]/product_catalog/manage_availability_and_stock/) per product. - - For more information, see [User Documentation]([[= user_doc =]]/product_catalog/products/#product-completeness). - -## Region and currency - -All currencies available in the system must be enabled in the back office under **Product Catalog** -> **Currencies**. - -Additionally, you must configure currencies valid for specific SiteAccesses under the `ibexa.system..product_catalog.currencies` [configuration key](configuration.md#configuration-files): - -``` yaml -ibexa: - system: - default: - product_catalog: - currencies: - - EUR - - GBP - - PLN - regions: - - germany - - uk - - poland -``` - -In the `ibexa_storefront.yaml` file, under the `ibexa.system..product_catalog.regions` configuration key, regions are set with `default` value. Remember to either exclude this element or extend it by [configuring other regions](enable_purchasing_products.md#configuring-other-regions-and-currencies). - -```yaml -ibexa: - system: - storefront_group: - product_catalog: - currencies: - - EUR - - PLN - regions: - - germany - - poland - another_storefront_group: - product_catalog: - currencies: - - GBP - regions: - - uk -``` - -This example uses the currencies and regions set in the [VAT rates' example below](#vat-rates). - -### Configuring other regions and currencies - -By default, the system always uses the first currency and the first region configured. - -To implement a different logic, for example a switcher for preferred currencies and regions, you need to subscribe to `Ibexa\Contracts\ProductCatalog\Events\CurrencyResolveEvent` and `Ibexa\Contracts\ProductCatalog\Events\RegionResolveEvent` in your customization. - -## VAT rates - -You set up VAT percentage values corresponding to VAT rates in configuration: - -``` yaml -ibexa: - repositories: - default: - product_catalog: - engine: default - regions: - germany: # Shorthand VAT configuration format - vat_categories: - standard: 19 - reduced: 7 - none: ~ - poland: # Current VAT configuration format - vat_categories: - standard: - value: 23 - reduced: - value: 8 - zero: - value: 0 - none: - value: 0 - extras: - not_applicable: true -``` - -!!! note - - The above example presents two acceptable formats of VAT configuration. - For each VAT category, setting a value to "null" (`~`) is equal to making the following setting: - - ``` yaml - none: - value: 0 - extras: - not_applicable: true - ``` - -You can then assign VAT rates that apply to every product type in each of the supported regions. -To do it, in the back office, [open the product type for editing]([[= user_doc =]]/product_catalog/create_product_types/#vat), and navigate to the **VAT rates** area. - -![Assigning VAT rates to a product type](catalog_vat_rates.png "Assigning VAT rates to a product type") diff --git a/docs/product_catalog/prices.md b/docs/product_catalog/prices.md index 90315eab2d2..d8da4283891 100644 --- a/docs/product_catalog/prices.md +++ b/docs/product_catalog/prices.md @@ -1,5 +1,14 @@ --- description: The price engine calculates product prices taking into account customer groups, currencies and taxes. +saas_review: + - siteaccess + - links_removed +saas_review_note: >- + States that a VAT rate can be set globally, meaning per SiteAccess. Confirm the + per-SiteAccess scope of VAT rates once SiteAccess configuration moves to a UI. + + Links to the deleted discounts.md page and the generated PHP API reference were + removed; check that the surrounding text still reads correctly. --- # Prices @@ -13,19 +22,9 @@ You can set up basic price rules depending on [customer groups](customer_groups. Use this option to globally manage custom prices, for example for your resellers. Each customer group can have a default price discount that applies to all products. -### Assign prices dynamically -You could create a customer group resolver that provides custom price logic, for example, by retrieving user address from the customer profile, and assigning a customer group to the customer based on the address. - -Such resolver must implement the [`Ibexa\Contracts\ProductCatalog\CustomerGroupResolverInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-CustomerGroupResolverInterface.html) interface. - -You must then register it as a service with the `ibexa.product_catalog.customer_group.resolver` tag. ## Currency [[= product_name =]] ships with a list of available currencies, and you can also add custom currencies. To use currencies in your shop, you need to first enable them in the back office. - -## VAT - -You can [configure VAT rate globally](product_catalog_configuration.md#vat-rates) (per SiteAccess), or set it individually for each product type and product. diff --git a/docs/product_catalog/product_catalog.md b/docs/product_catalog/product_catalog.md index be02c6b51c0..aca4edb1261 100644 --- a/docs/product_catalog/product_catalog.md +++ b/docs/product_catalog/product_catalog.md @@ -10,13 +10,12 @@ The Product Catalog provides comprehensive capabilities for managing products of [[= product_name =]] offers robust product catalog infrastructure that can be used standalone. -You can also use [[[= pim_product_name =]]](/product_catalog/quable/quable.md) add-on that fully integrates into the [[= product_name_base =]] ecosystem, or the [Remote PIM](add_remote_pim_support.md) to add integration with any external PIM system. +You can also use [[[= pim_product_name =]]](/product_catalog/quable/quable.md) add-on that fully integrates into the [[= product_name_base =]] ecosystem. [[= cards([ "product_catalog/product_catalog_guide", "product_catalog/quable/quable", "product_catalog/products", "product_catalog/catalogs", - "product_catalog/product_catalog_configuration", "product_catalog/prices", ], columns=3) =]] diff --git a/docs/product_catalog/product_catalog_configuration.md b/docs/product_catalog/product_catalog_configuration.md deleted file mode 100644 index c81748b657b..00000000000 --- a/docs/product_catalog/product_catalog_configuration.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -description: Configure product catalog settings per repository, with different catalog engines and VAT configurations. ---- - -# Product catalog configuration - -You can configure the product catalog per [Repository](repository_configuration.md). - -Under `ibexa.repositories..product_catalog` [configuration key](configuration.md#configuration-files), indicate the catalog engine to use: - -``` yaml -ibexa: - repositories: - default: - storage: ~ - search: - engine: '%search_engine%' - connection: default - product_catalog: - engine: 'default' -``` - -The `default` engine is available out of the box, and configured under `ibexa_product_catalog`: - -``` yaml -ibexa_product_catalog: - engines: - default: - type: local - options: - root_location_remote_id: e5ce2e391bd94e26a5cd88746f24ecce - product_type_group_identifier: 'product' -``` - -The `local` type is the built-in type of catalog based on the content repository. -With [[[= pim_product_name =]] integration](/product_catalog/quable/quable_guide.md) add-on installed and configured, by using the `quable` type you can retrieve product data coming from [[= pim_product_name =]]. - -You can use a single engine across all repositories, or assign different ones per repository. -Each repository can use only one product catalog engine. - -Under `options.product_type_group_identifier` you can define the identifier of the content type Group used for storing products. - -`root_location_remote_id` indicates the remote ID of the location where products are stored. - -## VAT rates - -To set up different VAT rates for different regions (countries), you can use the following configuration under the `ibexa.repositories..product_catalog.regions` [configuration key](configuration.md#configuration-files), for example: - -``` yaml hl_lines="11 12 17 18" -ibexa: - repositories: - : - product_catalog: - engine: default - regions: - : - vat_categories: - standard: - value: 18 - extras: - : - reduced: - value: 6 - zero: - value: 0 - none: - value: ~ -``` - -VAT rates configuration accepts additional flags under the `extras` key. -It's an extension point that you can build upon to add custom functionalities. -You can use it, for example, to pass additional information to the UI or define region-specific exclusions when calculating the tax values. - -For each VAT category value, setting a value to "null" (~) is equal to making the following setting: - -``` yaml - none: - value: 0 - extras: - not_applicable: true -``` - -## Code generation strategy - -Product codes for variants are generated automatically based on the selected strategy. - -The following strategies are available: - -- `incremental` (default) - variant code consists of base product code plus index, for example: `ErgoDesk-1`, `ErgoDesk-2`. -- `random` - variant code consists of base product code plus random string of characters, for example: `ErgoDesk-62E7B3379AEB4`, `ErgoDesk-62E7B3379AFBC` - -You can choose the strategy with the following configuration: - -``` yaml hl_lines="8" -ibexa_product_catalog: - engines: - default: - type: local - options: - root_location_remote_id: ibexa_product_catalog_root - product_type_group_identifier: 'product' - variant_code_generator_strategy: 'random' -``` - -You can also [create your own custom code generation strategy](create_product_code_generator.md). - -## Catalogs - -### Catalog filters - -You can configure which [catalog filters](catalogs.md) are applied by default with the following configuration: - -``` yaml -ibexa: - system: - admin: - product_catalog: - catalogs: - default_filters: - - product_code - - product_availability -``` - -The order of filters in this configuration reflects the order in which they're displayed in the back office. diff --git a/docs/product_catalog/product_catalog_guide.md b/docs/product_catalog/product_catalog_guide.md index 703be82a908..9f48b2e0bf4 100644 --- a/docs/product_catalog/product_catalog_guide.md +++ b/docs/product_catalog/product_catalog_guide.md @@ -1,6 +1,17 @@ --- description: The product catalog guide provides a full description of the features and capabilities for managing products, their specifications, variants, pricing, and organization. month_change: false +saas_review: + - siteaccess + - links_removed +saas_review_note: >- + States that a VAT rate can be set globally, meaning per SiteAccess. Confirm the + per-SiteAccess scope of VAT rates once SiteAccess configuration moves to a UI. + + Links to the deleted create_custom_attribute_type.md, product_api.md, + shipping_management.md, discounts_guide.md, create_custom_catalog_filter.md, + commerce.md and content_aware_cache.md pages were removed; check that the + surrounding text still reads correctly. --- # Product catalog guide @@ -12,7 +23,7 @@ It lets you create, configure, and manage products, their specifications, assets ## Availability -Product catalog capabilities are available in all [[= product_name =]] editions. +Product catalog capabilities are available in [[= product_name =]]. ## How does product catalog work @@ -37,7 +48,7 @@ Product specifications rely on product attributes. Available attributes are defi Each product has its own, specific attributes. You can describe a product in technical terms, define its physical characteristics such as size, color, or shape, or functional characteristics (for example, for a laptop it could be the operating system, amount of memory, or available ports). -Product attributes can belong to one of existing types (for example, numbers, selection, or checkout), but you can also [add custom attribute types](create_custom_attribute_type.md). +Product attributes can belong to one of existing types, for example, numbers, selection, or checkout. Attributes are used as criteria for filtering and searching for products. You can also configure selected product attributes to be used as a basis for variants. @@ -48,7 +59,7 @@ For more information, see [Product attributes](products.md#product-attributes) a ### Product variants One product can have multiple versions, for example, there can be a t-shirt in different colors. -You can [create variants of products](product_api.md#creating-variants), differing in some characteristics, based on product attributes. +You can create variants of products, differing in some characteristics, based on product attributes. ![Product variants](img/product_attributes.png) @@ -97,12 +108,10 @@ Currencies are used when calculating product price. In the system you can find a ### Regions Each product or product type can have different regional pricing and regional VAT rate. -You can configure regions in [YAML configuration](enable_purchasing_products.md#region-and-currency). ### VAT For each product you can configure VAT rate. You can set it globally (per SiteAccess) or individually for each product type and product. -To set up different VAT rates for different regions (countries),you need to first configure them in [YAML configuration](enable_purchasing_products.md#vat-rates). ### Base price @@ -125,7 +134,7 @@ When you create or edit a product, under the product name, you can see visual in Product completeness doesn't impact product availability or visibility on the storefront. It is intended to help you ensure that product data is properly populated. -As long as your product meets [basic requirements](enable_purchasing_products.md), it can be published and made available for purchase regardless of its completeness score. +As long as your product meets the requirements, it can be published and made available for purchase regardless of its completeness score. ### Catalogs @@ -140,7 +149,7 @@ You can then modify the copied catalog and save the updated version. When you create a new catalog, all products are included in it by default. To have a better overview for a specific group of products, you can filter the list by: -- price (Solr or Elasticsearch only) +- price - product attributes - product type - product code @@ -149,85 +158,11 @@ To have a better overview for a specific group of products, you can filter the l - the date when the product was created Catalog filters let you narrow down the products from the product catalog that are available in the given catalog. -Besides, the built-in catalog filters, you can also [create custom ones](create_custom_catalog_filter.md). -### Remote PIM support +### Quable PIM integration -[[= product_name =]] provides flexible product catalog infrastructure that works with external PIM systems. - -In [[= product_name =]], products are created and maintained by using the REST API or the back office, and their data is stored in a local database. -However, in your project or organization, you might have an existing product database, or be specifically concerned about product information security. -To address such needs, [[= product_name =]] provides remote PIM support. -You can install and configure a readily available [[[= pim_product_name =]] integration](/product_catalog/quable/quable.md) add-on, or build a custom one to connect to a remote PIM or ERP system, pull product data and present it on your website. - -![Remote PIM](img/remote_pim_support.png) - -An example implementation is delivered as an optional package that you can [install and customize](add_remote_pim_support.md) to fulfill your requirements. - -#### Capabilities - -With remote PIM support, you can take advantage of the following capabilities: - -##### Product marketing - -Use the product information coming from another system in your marketing campaigns to promote certain products or brands. -By embedding the products within content items and landing pages, you can leverage [[= product_name =]] marketing capabilities to showcase products. - -##### Pricing, stock and availability - -A product can only be ordered when it has defined [availability]([[= user_doc =]]/product_catalog/manage_availability_and_stock/), stock and [pricing information]([[= user_doc =]]/product_catalog/manage_prices/). - -By default, such information is held in the [[= product_name =]]'s local database. -In your specific scenario, you can implement the support for availability and pricing information coming from an external source as well, by using a price/availability matching strategy that is an extension point exposed in the Product catalog module. - -#### Limitations - -The limitation of remote PIM depend on implementation details of specific integration and may arise in areas relying on [content model](content_model.md). - -To see the limitations of the [[= pim_product_name =]] integration add-on, see [[[= pim_product_name =]] known limitations](/product_catalog/quable/quable_guide.md#known-limitations). - -##### Searching - -Filtering and pagination function the same as with the product catalog, relying on product attributes for effective organization of product data. -However, criteria and sort clauses within product catalog relying on [[= product_name =]]'s content model are not supported. - -Depending on your source of product information, you might need to adjust the implementation to be compatible with your data format. -For reference, you could review the [`CriterionVisitor` class](https://github.com/ibexa/example-in-memory-product-catalog/blob/main/src/lib/PIM/InMemory/CriterionVisitor.php) that is part of [Remote PIM example package](add_remote_pim_support.md#install-remote-pim-example-package). - -For more information about product search, see [Product Search Criteria reference](product_search_criteria.md) and [Product Sort Clauses](product_sort_clauses.md). - -##### Catalogs - -Depending on the implementation, creating [catalogs](#catalogs) might be supported, but the criteria for filtering can be limited. - -The default implementation, which serves as a basis for the example remote PIM package, has some limitations: certain functionalities either don't operate or operate within defined constraints. -Therefore, if your specific requirements aren't met, you may need to extend [[= product_name =]]. - -##### Editing product types, products and product attributes - - Editing product type, product and product attribute information stored in the remote PIM is impossible due to their read-only status. - This means that, functionally speaking, communication with PIM is uni-directional, and information is pulled from a remote source but cannot be updated. - -##### Content-model-based features - -The following features rely on [[= product_name =]]'s content model capabilities, which aren't supported by the default implementation of remote PIM support. -Therefore, if your specific requirements aren't met, you must extend the application by using extension points exposed in the product catalog module. - -- Assets -- Product variants -- Product categories -- Taxonomy -- URL aliases - -##### Simplified presentation of product-related blocks and views - -Enabling Remote PIM impacts a number of application views and blocks, such as Product view, Product list, Catalog, and Product Collection. -They're simplified, for example, they don't include thumbnails and other assets, or refer to URL aliases. -You can customize them by extending the default implementation. - -##### Limited HTTP Caching - -In the context of remote PIM, it's impossible to use [content-aware HTTP caching](content_aware_cache.md) with `ibexa_http_cache_tag_relation_ids`. +You can store product information inside [[= product_name =]], or you can store it inside ([[= pim_product_name =]]). +For more information, see [Quable integration](quable.md). ## How to get started @@ -266,11 +201,6 @@ It makes it possible to have multiple-level variants of the products complicated ![Multiple-level variants](img/multilevel_variants.png) -### Extensible availability - -By default, you can configure products with specific number in stock, or with infinite availability. -You can also extend the availability mechanism to cover other use cases, such as pre-orders. - ### Regional pricing including regional VAT rates Each product type can have different regional pricing and regional VAT rate. diff --git a/docs/product_catalog/products.md b/docs/product_catalog/products.md index 44421c12376..2acdcb349ca 100644 --- a/docs/product_catalog/products.md +++ b/docs/product_catalog/products.md @@ -66,7 +66,8 @@ You can create product variants automatically based on attributes that have the You can create variants for any combination of values of selected attributes. In the back office you can automatically generate all possible variants for a product. -Codes for product variants are generated automatically based on the [selected strategy](product_catalog_configuration.md#code-generation-strategy). +Codes for product variants are generated automatically based on the base product code. +For example, for a base product code `ErgoDesk`, the variants codes are `ErgoDesk-1`, `ErgoDesk-2`. Each product variant has separate availability and stock information. Each variant can also have separate price rules. @@ -85,8 +86,6 @@ You can embed products directly into content, including the [landing pages](page Use it to build marketing campaigns directly around the products, bridging product marketing and product data together. -To customize the design of the embedded products, see [Customize product embed templates](customize_product_embed_templates.md). - ## Product availability and stock Product availability defines whether a product is available in the catalog. @@ -108,12 +107,9 @@ The product catalog distinguishes between two types of availability: - Availability as a value set per product or variant - Availability represents whether the product was set as **Available**, for example in the [back office **Availability** tab]([[= user_doc =]]/product_catalog/manage_availability_and_stock/#set-product-availability) or [PHP API](product_api.md#product-availability). + Availability represents whether the product was set as **Available**, for example in the [back office **Availability** tab]([[= user_doc =]]/product_catalog/manage_availability_and_stock/#set-product-availability). - Computed availability Computed availability represents whether the product can actually be ordered. - By default, a product can only be ordered when it's set as available and has either positive or infinite stock. - -You can implement a custom strategy to handle different selling scenarios, such as minimum order quantity, minimum stock quantity, or region-specific availability. -For more information, see [Create custom availability strategy](create_custom_availability_strategy.md). + A product can only be ordered when it's set as available and has either positive or infinite stock. diff --git a/docs/product_catalog/quable/configure_quable_connector.md b/docs/product_catalog/quable/configure_quable_connector.md deleted file mode 100644 index 80c9c3d7a49..00000000000 --- a/docs/product_catalog/quable/configure_quable_connector.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -description: Quable connector configuration reference for Cohesivo -page_type: reference -month_change: false ---- - -# Configure [[= pim_product_name =]] connector - -You can customize the behavior of the [[= pim_product_name =]] integration add-on by using the following [configuration](configuration.md). - -## Configuration example - -In `config/packages/ibexa_connector_quable.yaml`, specify your configuration by using the `ibexa_connector_quable` key: - -``` yaml -ibexa_connector_quable: - enabled: true - instance_url: 'https://example.quable.com' - api_token: '' - channel_code: '' - webhook_secret: '' # Needed for webhook authentication - language_map: - eng-GB: en_GB - fre-FR: fr_FR - throw_on_invalid_criteria: '%kernel.debug%' - throw_on_invalid_mapping: '%kernel.debug%' - cache: - enabled: true - attribute: true - attribute_group: true - product: true - product_type: true -``` - -## Configuration options - -| Parameter | Default value | Description | -|-----------|--------------------------|-------------| -| `enabled` | `false` | Enables the connector. | -| `instance_url` | string | Base URL of your [[= pim_product_name =]] instance, for example `https://example.quable.com`. | -| `api_token` | string | [Read Access API token](https://docs.quable.com/v5-EN/docs/api-tokens) used to authenticate requests to [[= pim_product_name =]]. | -| `channel_code` | string | Code of the [[[= pim_product_name =]] channel](https://docs.quable.com/v5-EN/docs/content-channels) used as the source of product data. | -| `webhook_secret` | string | Secret expected in the [webhook](https://docs.quable.com/v5-EN/docs/webhook) authorization header. | -| `language_map` | Empty | Maps [[= product_name =]] language codes (for example, `eng-GB`) to [[= pim_product_name =]] locale codes (for example, `en_GB`). For more information, see [Set up [[= pim_product_name =]] languages](/product_catalog/quable/install_quable.md#set-up-languages). | -| `throw_on_invalid_criteria` | `%kernel.debug%` | Controls behavior for unsupported search criteria: `true` throws an exception, `false` only logs unsupported criteria. | -| `throw_on_invalid_mapping` | `%kernel.debug%` | Controls behavior for mapping errors during data transformation: `true` throws an exception, `false` only logs mapping errors. | -| `cache.enabled` | `true` | Global cache switch for the connector. When set to `false`, only [in-memory cache](persistence_cache.md#in-memory-cache-configuration) is used. When set to `true`, [Symfony's `cache.app` cache pool]([[= symfony_doc =]]/cache.html#system-cache-and-application-cache) is used. | -| `cache.attribute` | `true` | Enables caching for attribute definition requests. | -| `cache.`
`attribute_group` | `true` | Enables caching for attribute group requests. | -| `cache.`
`product` | `true` | Enables caching for product requests. | -| `cache.`
`product_type` | `true` | Enables caching for product type requests. | - -In production environments, it's recommended to: - -- keep the `api_token` and the `webhook_secret` [secure](security_checklist.md#app_secret-and-other-secrets) -- enable caching for better performance, by using Redis or Valkey as [persistence cache](persistence_cache.md#redisvalkey) -- disable `throw_on_invalid_criteria` and `throw_on_invalid_mapping` to prevent non-critical errors from causing application crashes diff --git a/docs/product_catalog/quable/install_quable.md b/docs/product_catalog/quable/install_quable.md deleted file mode 100644 index 8607059948f..00000000000 --- a/docs/product_catalog/quable/install_quable.md +++ /dev/null @@ -1,184 +0,0 @@ ---- -description: Install and configure Quable connector for Cohesivo -month_change: false ---- - -# Install [[= pim_product_name =]] connector - -To integrate [[= product_name =]] with [[= pim_product_name =]], you need to install the [[= pim_product_name =]] connector packages, configure the connection, and set up synchronization. - -## Create [[= pim_product_name =]] instance - -Before installing the [[= pim_product_name =]] connector, ensure you have access to a [[[= pim_product_name =]] instance](https://www.quable.com). - -## Install package - -Run the following command to install the required package: - -``` bash -composer require ibexa/connector-quable -``` - -The command adds the [[= pim_product_name =]] connector code, including services that enable communication with [[= pim_product_name =]]. - -## Get API credentials - -To connect to [[= pim_product_name =]], you need an API token: - -1. Log in to your [[= pim_product_name =]] instance, for example, `https://example.quable.com`. -2. Navigate to the [API Tokens](https://docs.quable.com/v5-EN/docs/api-tokens) section. -3. Create a new **Read Access Token** for use in the configuration. - -## Configure [[= pim_product_name =]] connector - -In `config/packages/ibexa_connector_quable.yaml`, specify the configuration for the [[= pim_product_name =]] connector: - -``` yaml -ibexa_connector_quable: - instance_url: 'https://example.quable.com' - api_token: '' - channel_code: '' -``` - -Replace `` with the Read Access API token you obtained from [[= pim_product_name =]] in the previous step. - -[[[= pim_product_name =]]'s channels](https://docs.quable.com/v5-EN/docs/content-channels) allow you to distribute your product information to defined recipients, for example e-commerce platforms. -Select the [[= pim_product_name =]] channel that you want to integrate within [[= product_name =]]. - -For all available configuration options, see [Configure [[= pim_product_name =]]](configure_quable_connector.md). - -## Configure product catalog engine - -To use [[= pim_product_name =]] as a product data source, configure [[= product_name =]]'s [product catalog](product_catalog_guide.md) to use the [[= pim_product_name =]] engine. - -### Define [[= pim_product_name =]] engine - -In `config/packages/ibexa_product_catalog.yaml`, add a new engine configuration: - -``` yaml hl_lines="8-13" -ibexa_product_catalog: - engines: - local: - type: local - options: - root_location_remote_id: ibexa_product_catalog_root - product_type_group_identifier: product - quable: - type: quable - options: - taxonomy: quable - root_location_remote_id: ibexa_product_catalog_root - product_type_group_identifier: product -``` - -This configuration defines two engines: the default `local` engine and the new `quable` engine, allowing you to work with products defined within [[= pim_product_name =]]. - -To learn more about product catalog configuration, see [Product catalog configuration](product_catalog_configuration.md). - -The [[= pim_product_name =]] integration add-on comes with a new [taxonomy](taxonomy.md) called `quable`. -By setting the `ibexa_product_catalog.engines.quable.options.taxonomy` key to `quable`, you configure the engine to use it for storing product categories. - -### Set [[= pim_product_name =]] as default engine - -In your repository configuration, typically in `config/packages/ibexa.yaml`, configure the product catalog to use the [[= pim_product_name =]] engine as the product data source: - -``` yaml hl_lines="9" -ibexa: - repositories: - default: - storage: ~ - search: - engine: '%search_engine%' - connection: default - product_catalog: - engine: quable - regions: - default: ~ -``` - -## Set up languages - -To use the products from [[= pim_product_name =]] within [[= product_name =]] content, make sure the [data languages](https://docs.quable.com/v5-EN/docs/data-languages) in [[= pim_product_name =]] have corresponding [languages](languages.md) in [[= product_name =]]. - -To compare the language configuration in both systems, run the following command: - -``` bash -php bin/console ibexa:quable:languages:check -``` - -Based on the command output, configure the `language_map` in `config/packages/ibexa_connector_quable.yaml`, mapping each [[= product_name =]] language code to its [[= pim_product_name =]] locale code as in the following example: - -``` yaml -ibexa_connector_quable: - # ... - language_map: - eng-GB: en_GB - fre-FR: fr_FR -``` - -The system uses the language map to retrieve data in the correct language from [[= pim_product_name =]]. - -After configuring the map, rerun the `ibexa:quable:languages:check` command to confirm all languages are correctly mapped. - -## Synchronize taxonomy - -After configuring the integration, synchronize [product classifications from [[= pim_product_name =]]](https://docs.quable.com/v5-EN/docs/documents-classification-new-version) to [[= product_name =]]'s [taxonomies](taxonomy.md). - -Run the following command to synchronize classifications: - -``` bash -php bin/console ibexa:quable:classification:sync -``` - -This command imports the product classification structure from [[= pim_product_name =]] into [[= product_name =]], ensuring that product categories are aligned. - -!!! tip - - To keep the classifications aligned, it's recommended that you run the `ibexa:quable:classification:sync` command every night, even when using synchronization with webhooks. - -## Set up real-time synchronization - -[[= pim_product_name =]] can notify [[= product_name =]] about product data and classification changes in real-time by using webhooks. -This invalidates the cache kept in [[= product_name =]], ensuring that product information stays up to date. - -Webhook configuration must be set up in both [[= pim_product_name =]] and [[= product_name =]]. - -### Create webhook in [[= pim_product_name =]] - -1. Create a new [webhook in [[= pim_product_name =]]](https://docs.quable.com/v5-EN/docs/webhook). -2. Set the webhook code (used as the webhook name). -3. Provide the URL to your [[= product_name =]] instance suffixed by `/webhook/quable`, for example: `https://example.com/webhook/quable`. -4. Mark it as **Activated**. -5. Enter a secret value for the **Authorization Header**. -6. Choose the following scopes: - - - Products: created, updated, deleted - - Classifications: created, updated, deleted - -The **Authorization Header** value is a [secret that must be kept secure](security_checklist.md#app_secret-and-other-secrets). - -!!! note - - For local development and testing, you can consider using one of the available [tunnel providers](https://github.com/anderspitman/awesome-tunneling) to make your local instance accessible from the internet. - -### Configure webhook in [[= product_name =]] - -In `config/packages/ibexa_connector_quable.yaml`, specify the configuration for the [[= pim_product_name =]] connector: - -``` yaml -ibexa_connector_quable: - - # ... - webhook_secret: '' -``` - -!!! caution - - [[[= pim_product_name =]] uses dynamic IP addresses](https://faq.quable.com/en/articles/8250056-what-are-the-ip-addresses-of-quable-to-add-to-the-whitelist) to connect to [[= product_name =]]. - If your [[= product_name =]] instance is protected by a firewall, make sure your configuration allows connections from changing IP addresses. - -### Configure background task - -[[= product_name =]] webhook processes [[= pim_product_name =]]'s classification change events and queues them to be processed in the background. - -To process them, [configure Ibexa Messenger](background_tasks.md) and make sure the `messenger:consume` command is run periodically. diff --git a/docs/product_catalog/quable/quable.md b/docs/product_catalog/quable/quable.md index 1d3229b3546..162bbbc3e30 100644 --- a/docs/product_catalog/quable/quable.md +++ b/docs/product_catalog/quable/quable.md @@ -9,8 +9,7 @@ month_change: false [[= product_name =]] integrates with [[[= pim_product_name =]]](https://www.quable.com/en) to provide product information management as part of the [[= product_name_base =]] orchestration platform. [[= pim_product_name =]] is [[= product_name_base =]]’s PIM solution for managing complex product catalogs and serves as the single source of truth, available as an add-on for [[= product_name =]]. -Once you install and configure it, the integration performs an initial synchronization of product data, followed by ongoing updates via webhooks. -Products can be viewed, selected, and embedded in [[= product_name =]], while all product management operations remain handled in [[= pim_product_name =]]. +With the integration set up, products can be viewed, selected, and embedded in [[= product_name =]], while all product management operations remain handled in [[= pim_product_name =]]. ## Getting started @@ -24,8 +23,5 @@ Products can be viewed, selected, and embedded in [[= product_name =]], while al ## Development [[= cards([ - "product_catalog/quable/install_quable", - "product_catalog/quable/configure_quable_connector", - "product_catalog/quable/quable_api", ("https://developers.quable.com/", "Quable technical documentation", "Explore Quable's technical documentation"), ]) =]] diff --git a/docs/product_catalog/quable/quable_guide.md b/docs/product_catalog/quable/quable_guide.md index dc8c3692a5b..887864b949e 100644 --- a/docs/product_catalog/quable/quable_guide.md +++ b/docs/product_catalog/quable/quable_guide.md @@ -16,15 +16,13 @@ This approach eliminates the need to manage product data in multiple systems, wh ## Availability -The integration with [[= pim_product_name =]] is available as an add-on for all [[= product_name =]] editions. +The integration with [[= pim_product_name =]] is available as an add-on for [[= product_name =]]. -Before installing and enabling the add-on, ensure that you have an active [[= pim_product_name =]] instance with defined products, classifications, and channels. - -Then, [perform the initial configuration](install_quable.md). +Before enabling it, ensure that you have an active [[= pim_product_name =]] instance with defined products, classifications, and channels. ## How does [[= pim_product_name =]] integration work -The integration is built on [[= product_name =]]'s [Remote PIM framework](add_remote_pim_support.md), which enables connection to external product data sources. +The integration enables connection to external product data sources. Once configured, the system performs: diff --git a/docs/product_guides/product_guides.md b/docs/product_guides/product_guides.md index 76e986fe292..f43caaaf4c8 100644 --- a/docs/product_guides/product_guides.md +++ b/docs/product_guides/product_guides.md @@ -6,8 +6,8 @@ month_change: false # Product guides -[[= product_name =]] product editions come with a variety of features. -Discover the primary ones with the help of product guides. Condensed content allows you to quickly learn about their availability, capabilities, and benefits. +[[= product_name =]] comes with a variety of features. +Discover the primary ones with the help of product guides. Condensed content allows you to quickly learn about their capabilities and benefits. [[= cards([ "users/user_management_guide", diff --git a/docs/qualifio/create_campaign.md b/docs/qualifio/create_campaign.md index 3f36c838a61..28e904ec372 100644 --- a/docs/qualifio/create_campaign.md +++ b/docs/qualifio/create_campaign.md @@ -1,6 +1,5 @@ --- description: Create a campaign with Qualifio. -edition: experience --- # Create [[= product_name_engage =]] campaign diff --git a/docs/qualifio/integrate_ibexa_connect.md b/docs/qualifio/integrate_ibexa_connect.md index 302d59db7df..0b7b086a529 100644 --- a/docs/qualifio/integrate_ibexa_connect.md +++ b/docs/qualifio/integrate_ibexa_connect.md @@ -1,6 +1,5 @@ --- description: Integrate Qualifio with Ibexa Connect. -edition: experience --- # Integrate with [[= product_name_connect =]] diff --git a/docs/qualifio/qualifio.md b/docs/qualifio/qualifio.md index 94316de59be..4642cdffad6 100644 --- a/docs/qualifio/qualifio.md +++ b/docs/qualifio/qualifio.md @@ -1,6 +1,5 @@ --- description: Use Qualifio to collect customer data by creating interactive content. -edition: experience month_change: false --- @@ -11,8 +10,11 @@ It gives you the ability to use the [Qualifio](https://qualifio.com/) tools to e 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. +To use [[= product_name_engage =]], you must first make arrangements with [[= product_name_base =]]. + +For more information, see [[[= product_name_engage =]] in User Documentation]([[= user_doc =]]/qualifio/qualifio/#request-access). + [[= cards([ - "qualifio/install_qualifio", "qualifio/create_campaign", "qualifio/integrate_ibexa_connect", -], columns=3) =]] +], columns=2) =]] diff --git a/docs/raptor_cdp/raptor_cdp.md b/docs/raptor_cdp/raptor_cdp.md index 918ebbdf9d3..b136fd3f8e0 100644 --- a/docs/raptor_cdp/raptor_cdp.md +++ b/docs/raptor_cdp/raptor_cdp.md @@ -1,6 +1,5 @@ --- description: Raptor CDP is a software system designed to collect and organize customer data from multiple sources to build comprehensive customer profiles. -edition: experience --- # [[= product_name_cdp =]] integration @@ -19,4 +18,3 @@ It allows you to create individual customer profiles that enable you to personal 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](raptor_cdp_activation.md). diff --git a/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_activation.md b/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_activation.md deleted file mode 100644 index d436a15a1c7..00000000000 --- a/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_activation.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -description: Step-by-step activation procedure of Raptor CDP. -page_type: landing_page -edition: experience ---- - -# Activate [[= product_name_cdp =]] - -Follow a step-by-step procedure that allows you to activate [[= product_name_cdp =]]. - -Activation includes configuration, data export and adding tracking. - -[[= cards([ - "raptor_cdp/raptor_cdp_activation/raptor_cdp_configuration", - "raptor_cdp/raptor_cdp_activation/raptor_cdp_data_export", - "raptor_cdp/raptor_cdp_activation/raptor_cdp_add_tracking", -], columns=3) =]] diff --git a/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_add_tracking.md b/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_add_tracking.md index 81ee5236537..a828bddfd17 100644 --- a/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_add_tracking.md +++ b/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_add_tracking.md @@ -1,28 +1,15 @@ --- description: Adding tracking in Raptor CDP. -edition: experience --- # Track with [[= product_name_cdp =]] The final step is setting up a tracking script that identifies visitors and records their interactions. -You can set it up in two ways: -- with Raptor's built in tracking functions -- manually, with tracking scripts +## Set up tracking with tracking scripts -## Set up tracking with built-in Raptor tracking functions -If your project uses the [Raptor connector](raptor_connector.md), use the built-in [Raptor tracking functions](tracking_functions.md). -This recommended approach supports both client-side and server-side tracking, handles cookie consent, and sets the tracking cookie required for [anonymous user segmentation](raptor_cdp_configuration.md#anonymous-user-segmentation). - -For setup instructions, see [Raptor tracking functions](tracking_functions.md). - -## Manually set up tracking with tracking scripts - -If you aren't using the Raptor connector, you can set up tracking manually. - -It requires a head tracking script between the `` tags on your website, a main script after the head script, and cookie consent. +The tracking script 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 manually, see [Raptor documentation](https://content.raptorservices.com/help-center/client-side-tracking). diff --git a/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_configuration.md b/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_configuration.md deleted file mode 100644 index 3723fdc21cf..00000000000 --- a/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_configuration.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -description: Step-by-step configuration procedure of Raptor CDP. -edition: experience ---- - -# Configure [[= product_name_cdp =]] - -To configure [[= product_name_cdp =]], use the `ibexa.system..cdp` [configuration key](configuration.md#configuration-files): - -```yaml -ibexa: - system: - default: - cdp: - account_number: 123456 - data_export: - user_data: - transport: stream_file - stream_file: - stream_id: 00000000-00000000-00000000-00000000 - content_data: - transport: stream_file - stream_file: - stream_id: 00000000-00000000-00000000-00000000 - product_data: - transport: stream_file - stream_file: - stream_id: 00000000-00000000-00000000-00000000 - activations: - - - client_id: '%env(CDP_ACTIVATION_CLIENT_ID)%' - client_secret: '%env(CDP_ACTIVATION_CLIENT_SECRET)%' - segment_group_identifier: example_segment_group_identifier - membership: # For anonymous user segmentation - activation_id: '%env(CDP_MEMBERSHIP_ACTIVATION_ID)%' - api_key: '%env(CDP_MEMBERSHIP_API_KEY)%' - base_url: 'https://cdp-api.raptorsmartadvisor.com' - timeout: 5 -``` - -- `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're random and secure -- `segment_group_identifier` - a [location](#segment-group) to which CDP data is imported -- `membership` - configuration that enables support for [anonymous user segmentation](#anonymous-user-segmentation) -- `membership.activation_id` and `membership.api_key` - credentials for the CDP Membership API, required for [anonymous user segmentation](#anonymous-user-segmentation) -- `membership.base_url` - base URL of the CDP Membership API (default: `https://cdp-api.raptorsmartadvisor.com`) -- `membership.timeout` - timeout in seconds for Membership API requests (default: `5`) - -## Account number - -Now, fill in the account number. -Log in to [[= product_name_cdp =]] and in the top right corner, select available accounts. - -![List of available accounts](../img/raptor_cdp_accounts.png) - -A pop-up window displays a list of all available accounts and their numbers. - -![Account number](../img/raptor_cdp_account_number.png) - -## Segment group - -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. - -!!! 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. - -![Creating a new segment group](../img/raptor_cdp_create_segment_group.png) - -Next, add a segment group identifier to the configuration. - -## Anonymous user segmentation - -To set up [segmentation for anonymous users](raptor_cdp_guide.md#anonymous-user-segmentation), take the following steps: - -### Set up CDP API activation - -Create an activation of type "CDP API" in the Raptor dashboard. -For instructions, see [CDP API activations](https://content.raptorservices.com/help-center/cdp/activations/cdp-api) in Raptor documentation. - -### Configure website tracking dataflow - -Set up a "Website tracking" dataflow with `coid` (cookie ID) as the person identifier so that Raptor can use the tracking data in the CDP. - -For more information, see [Website tracking dataflow](https://content.raptorservices.com/help-center/tools/datamanager/introduction-to-the-data-manager) in Raptor documentation. - -### Configuration - -Add the `membership.activation_id` and `membership.api_key` credentials to your [`ibexa.system..cdp` configuration](#configuration), using the credentials for [CDP API activation](#set-up-cdp-api-activation). -To control for how long resolved segment memberships are cached per visitor, use the `ibexa_segmentation.anonymous.cache` configuration key: - -```yaml -# config/packages/ibexa_segmentation.yaml -ibexa_segmentation: - anonymous: - cache: - enabled: true # default; set to false to disable - ttl: 300 # cache lifetime in seconds, default 300 (5 minutes) - pool: 'ibexa.cache_pool' # Symfony cache pool service ID, default ibexa.cache_pool -``` - -- `enabled` - whether to cache CDP segment results per visitor cookie. Disabling this causes an additional API call to Raptor on every request -- `ttl` - how long resolved segment results are cached per visitor (in seconds) -- `pool` - the Symfony cache pool used to store the results diff --git a/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_data_export.md b/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_data_export.md deleted file mode 100644 index 81b3bf46a72..00000000000 --- a/docs/raptor_cdp/raptor_cdp_activation/raptor_cdp_data_export.md +++ /dev/null @@ -1,208 +0,0 @@ ---- -description: Step-by-step data export procedure in Raptor CDP. -edition: experience ---- - -# Export [[= product_name_cdp =]] data - -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 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'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**. -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. - -Next, you need to export your data to the CDP. -Go to your installation and use this command: - -- for User: - -```bash -php bin/console ibexa:cdp:stream-user-data --draft -``` - -- for Product: - -```bash -php bin/console ibexa:cdp:stream-product-data --draft -``` - -- for Content: - -```bash -php bin/console ibexa:cdp:stream-content-data --draft -``` - -There are two versions of this command `--draft/--no-draft`. -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. - -You can extend exported user data with custom fields from your user content, such as date of birth, preferences, or other profile information. -For more information, see [Data customization](raptor_cdp_data_customization.md#export-additional-user-data). - -Next, go back to [[= product_name_cdp =]] and select **Validate & download**. -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 data points 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 isn't available. - -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 - -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. - -If you have [extended user data export with custom fields](raptor_cdp_data_customization.md#export-additional-user-data), those fields appear as additional columns in this section. -Make sure to add them to your schema in Raptor so they can be used for segmentation and recommendations. - -Next, select **Create schema based on the downloaded columns**. -It moves you to Schema Creator. -There, choose **PersonalData** as a parent and name the schema. - -![Create new schema](../img/raptor_cdp_create_new_schema.png) - -Next, select all the columns and set Person Identifier as **userid**. - -![Person Identifier](../img/raptor_cdp_person_identifier.png) - -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 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**. - -![Map userid to id](../img/raptor_cdp_userid_mapid.png) - -## Activation - -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 -php bin/console ibexa:cdp:stream-user-data --no-draft -``` - -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 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. - -In the Audience Builder, you can also connect created audiences to the activations. - -## Activation - -Activation synchronises data from [[= product_name_cdp =]] to [[= product_name =]]. -When you specify a segment, you can activate it on multiple communication channels, such as newsletters or commercials. -You can configure multiple activations based data flows. - -First, from the menu bar, select **Activations** and create a new **Ibexa** activation. -Specify name of your activation, select `userid` as **Person Identifier** and click **Next**. - -![General Information - Activation](../img/raptor_cdp_activation_general_info.png) - -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'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. - -- **Base URL** - URL of your instance with added `/cdp/webhook` at the end. - -![Ibexa Information - Activation](../img/raptor_cdp_activation_ibexa_info.png) - -Finally, you can specify the audiences you wish to include. - -!!! note "CDP requests" - - All CDP requests are logged in with `debug` severity. - -### [[= product_name_base =]] Messenger support for large batches of data - -CDP uses [[= product_name_base =]] Messenger to process incoming data from [Raptor](https://www.raptorservices.com/). -This approach improves performance and reliability when processing large amounts of CDP user records. -For more information, see [Background tasks: How it works](background_tasks.md#how-it-works). - -By using Messenger while working with large batches of data, requests are queued instead of being processed synchronously: - -- queuing items starts automatically once a certain number of actions is reached (below this number, items are processed in a single request, using the standard synchronous behavior) -- every single data is recorded in the database -- a background worker retrieves records from the queue, processing them one by one or in batches, depending on the [Messenger]([[= symfony_doc =]]/messenger.html) configuration -- processing happens at set intervals to avoid timeouts and keep the system stable - -1\. Make sure that the transport layer is [defined properly](background_tasks.md#configure-package) in [[= product_name_base =]] Messenger configuration. - -2\. Add `bulk_async_threshold` setting in the `config/packages/ibexa_cdp.yaml` configuration: - -``` bash -ibexa_cdp: - bulk_async_threshold: 100 # Default: 100 items -``` - -Available options: - -- `bulk_async_threshold` (integer, default: 100) - minimum number of items required to trigger asynchronous processing - - below threshold - items are processed immediately in a single request, using the standard synchronous behavior - - at/above threshold - items are automatically dispatched to the asynchronous queue for background processing - -3\. Make sure that the [worker starts](background_tasks.md#start-worker) together with the application to watch the transport bus: - -``` bash -php bin/console messenger:consume ibexa.messenger.transport --bus=ibexa.messenger.bus -``` - -For more information, see [Start background task worker](background_tasks.md#start-worker). - -### CDP Monolog channel - -CDP Monolog channel handles webhook logs for easier separation of logs. - -```bash -- { name: monolog.logger, channel: ibexa.cdp.webhook } -``` - -It's possible to configure `ibexa.cdp.webhook` Monolog channel to direct all logs to specific stream, file, or service. -This allows webhook logs to be stored separately from the main application logs for easier debugging and analysis. - -To do it, in `config/packages/monolog.yaml` file, define a new handler for the `ibexa.cdp.webhook` channel that directs CPD Webhook events to a separate file. -It can be configured in both `dev` and `prod` environments, for example: - -```yaml -monolog: - handlers: - cdp_webhook: - type: stream - path: "%kernel.logs_dir%/cdp_webhook_%kernel.environment%.log" - level: debug - channels: [ 'ibexa.cdp.webhook' ] -``` - -If you want to avoid redundant or duplicate entries in the other logs, exclude the webhook channel by: - -```yaml -channels: ["!ibexa.cdp.webhook"] -``` diff --git a/docs/raptor_cdp/raptor_cdp_guide.md b/docs/raptor_cdp/raptor_cdp_guide.md index cbd14615898..f13d0b2a281 100644 --- a/docs/raptor_cdp/raptor_cdp_guide.md +++ b/docs/raptor_cdp/raptor_cdp_guide.md @@ -1,6 +1,5 @@ --- description: The Raptor CDP product guide describes all the possibilities that the Customer Data Platform offers to help you build great customer experiences. -edition: experience --- # [[= product_name_cdp =]] product guide @@ -16,9 +15,6 @@ This central data storage supports business growth with a scalable infrastructur 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. -## Availability - -[[= product_name_cdp =]] is available in [[= product_name_exp =]] and [[= product_name_com =]] editions. ## How does [[= product_name_cdp =]] work @@ -29,14 +25,11 @@ Customer data is gathered through a system of trackers embedded in various areas ![CDP - how does it work](img/cdp.png) -### Installation and configuration +### Getting started -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](/raptor_cdp/raptor_cdp_installation.md#register-in-raptor-cdp-dashboard). +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. 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](/raptor_cdp/raptor_cdp_installation.md#install-package) that is opt-in and needs to be downloaded separately. -Last step is to go through the [configuration process](raptor_cdp_configuration.md). - ### Customer profile In [[= product_name_cdp =]] you can build 360° customer profiles. @@ -65,19 +58,6 @@ 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](raptor_cdp_data_export_schedule.md#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 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 - -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. - -For more information, see [CDP data export](raptor_cdp_data_export.md). ### Data customization @@ -85,8 +65,6 @@ For more information, see [CDP data export](raptor_cdp_data_export.md). 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](raptor_cdp_data_customization.md) documentation in Developer Documentation. - ### Client-side Tracking The final step is setting up a tracking script. diff --git a/docs/recommendations/raptor_integration/connector_installation_configuration.md b/docs/recommendations/raptor_integration/connector_installation_configuration.md deleted file mode 100644 index 28527b31564..00000000000 --- a/docs/recommendations/raptor_integration/connector_installation_configuration.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -description: To configure the Raptor integration, follow the step-by-step procedure described below. -month_change: false ---- - -# Install and configure [[= product_name_cdp_base =]] - -To configure the [[[= product_name_cdp_base =]]](https://www.raptorservices.com/) integration add-on, follow the step-by-step procedure below. - -## Install [[= product_name_cdp_base =]] connector - -Before you can proceed to configuring the integration with [[= product_name_cdp_base =]], install the [[= product_name_cdp_base =]] connector. -To do it, run the following command: - -``` bash -composer require ibexa/connector-raptor -``` - -!!! note - - The [Ibexa Messenger](background_tasks.md) package is installed automatically as a dependency, but must be configured to enable server-side tracking. - See the Ibexa Messenger documentation for [configuration](background_tasks.md#configure-package) details. - -## SiteAccess-aware configuration - -To configure the [[= product_name_cdp_base =]] connector, use the `ibexa.system..connector_raptor` configuration key in the `config/packages/ibexa_connector_raptor.yaml` file: - -``` yaml -[[= include_file('code_samples/recommendations/config/packages/ibexa_connector_raptor.yaml', 0, 17) =]] -``` - -- `enabled` - enables or disables the connector for a given scope. Default value: `true`. If set to `false`, no tracking or recommendation requests are executed. -- `customer_id` - an identifier used to authenticate requests to the recommendation engine. You can find this value as ["Account number"](connector_installation_configuration.md#customer-id) in [[= product_name_cdp_base =]] Control Panel. -- `tracking_type` - defines how user events are sent to the tracking API. Default value: `client`. Possible values: - - `client` - tracking is executed in the browser using JavaScript snippets generated by the Twig functions and included in the templates. This approach may be blocked by ad blockers. - - `server` - tracking is handled on the backend, with events sent directly to the tracking API. It's not affected by ad blockers. - - `hybrid` - tracking is executed in the browser by a first-party JavaScript provided by [[= product_name =]] instead of [[= product_name_cdp_base =]] and then forwarded by the [[= product_name =]] server to the [[= product_name_cdp_base =]] SaaS. For more information, see [Hybrid tracking](hybrid_tracking.md). -- `recommendations_api_key` - an API key used to authenticate requests to the Recommendations API. This key allows the connector to retrieve personalized recommendations from the recommendation engine. You can find this value as ["API key"](connector_installation_configuration.md#recommendations-api-key) in [[= product_name_cdp_base =]] Control Panel. -- `recommendations_api_uri` (optional) - overrides the default [[= product_name_cdp_base =]] address, do not set it unless a custom endpoint is required. -- `cookie_id_lifetime_days` (optional) - the lifetime in days of the server-side tracking identifier cookies. Default value: `365` days. Minimum value: `1` day. - -By default, `tracking_type` is set to `client` as client-side tracking is the standard [[= product_name_cdp_base =]] mode. -To understand the differences between client and server tracking types, including their advantages and disadvantages, refer to the [[[= product_name_cdp_base =]] documentation](https://content.raptorservices.com/help-center/client-side-vs.-server-side-tracking). - -!!! note - - Only one tracking mode can be enabled at a time. - Client-side and server-side tracking cannot be used together. - -### Customer ID - -To find the value for the `customer_id` identifier, log in to [[= product_name_cdp_base =]] Control Panel, and look for "Account number": - -A. In the top-left corner, above the account name, you can find the account number for the currently active account. -B. Click the arrow icon in the top-left corner to expand the window. There you can see a list of all your accounts, with their numbers shown in the “Account number” column on the right. This way, if you have multiple accounts, you can locate and copy the number of any of your accounts, not just the active one. - -![Account number](account_number.png) - -### Recommendations API key - -To find the value for the `recommendations_api_key`, log in to [[= product_name_cdp_base =]] Control Panel, and look for "API key". -To do it, in the left panel, open the **Recommendations** section, and select **Website**. -Next, click on the Web module you’re interested in. -In the top-right corner, click the three-dot icon and select **API information**. -A new window appears, where you can find the "API key" value. -Click **Show API information** and copy the value. - -![API key](api_key.png) - -## Global configuration (non-SiteAccess-aware) - -The following settings are global and apply to the entire application (they are not scoped per SiteAccess): - -- `strict_exceptions` – when enabled, tracking exceptions are thrown instead of being silently handled. Default value: `%kernel.debug%`. - -- `hybrid_tracking_proxy_path` - by default, it's set to `/raptor/track`. The client-side shim sends tracking events to this same-origin endpoint, which forwards them to [[= product_name_cdp_base =]] asynchronously. - -This value can be overridden in `config/packages/ibexa_connector_raptor.yaml` file, for example: - -``` yaml hl_lines="18-21" -[[= include_file('code_samples/recommendations/config/packages/ibexa_connector_raptor.yaml') =]] -``` diff --git a/docs/recommendations/raptor_integration/raptor_connector.md b/docs/recommendations/raptor_integration/raptor_connector.md index 529531dd002..9f34ee0e34a 100644 --- a/docs/recommendations/raptor_integration/raptor_connector.md +++ b/docs/recommendations/raptor_integration/raptor_connector.md @@ -12,24 +12,12 @@ Its primary goal is to enable editors and managers to deliver personalized exper By combining content management capabilities with advanced recommendation features, the connector allows teams to build and manage personalized experiences across integrated tools. -The connector ensures a smooth and unified integration layer, enabling: - -- event tracking through the tracking API -- personalized delivery of content and product recommendations through the Recommendations API -- flexible, SiteAccess-aware configuration This approach reduces integration complexity while providing a scalable foundation for personalization use cases across multiple sites and markets. -To configure the integration with [[= product_name_cdp_base =]], follow a step-by-step procedure that allows you to activate the [[= product_name_cdp_base =]] connector. -Activation includes [configuration](connector_installation_configuration.md), adding tracking scripts and events, and using [Page Builder](page_builder_guide.md) blocks. For more information about tracking, check the [[= product_name_cdp_base =]] documentation: [Implementing tracking](https://content.raptorservices.com/help-center/data-management#implementing-tracking). [[= cards([ - "recommendations/raptor_integration/connector_installation_configuration", - "recommendations/raptor_integration/tracking_functions", - "recommendations/raptor_integration/hybrid_tracking", - "recommendations/raptor_integration/tracking_php_api", "recommendations/raptor_integration/recommendation_blocks", - "recommendations/raptor_integration/custom_recommendation_rendering", -], columns=3) =]] +], columns=2) =]] diff --git a/docs/recommendations/raptor_integration/raptor_connector_guide.md b/docs/recommendations/raptor_integration/raptor_connector_guide.md index b50d699ff49..f765aa171c6 100644 --- a/docs/recommendations/raptor_integration/raptor_connector_guide.md +++ b/docs/recommendations/raptor_integration/raptor_connector_guide.md @@ -5,8 +5,7 @@ month_change: false # [[= product_name_cdp_base =]] integration product guide -Discover [[[= product_name_cdp_base =]]](https://www.raptorservices.com/) integration - an add-on that is focused on recommendations and tracking customer behaviors. -It includes the connector with tracking scripts and events that are used to track and analyze customer behaviors, and a set of Recommendation blocks. +Discover [[[= product_name_cdp_base =]]](https://www.raptorservices.com/) integration - an add-on that is focused on recommendations for your visitors. ## What is [[= product_name_cdp_base =]] integration @@ -16,41 +15,22 @@ Its primary goal is to enable editors and managers to deliver personalized exper By bringing content and recommendations together, the connector makes it easy to build and manage personalized experiences. -It provides a seamless integration layer that supports: - -- event tracking of user interactions through the Tracking API -- personalized delivery of content and product recommendations through the Recommendations API -- flexible SiteAccess-aware configuration adapted to different sites and contexts This approach simplifies integration while supporting personalization across different sites and markets. ## Availability -[[= product_name_cdp_base =]] integration elements, such as tracking, Twig functions, and public API, are available in all supported [[= product_name =]] editions starting from v5.0.7 version. - -Recommendation blocks provided in Page Builder, are available in [[= product_name_exp =]] and [[= product_name_com =]] editions. +To use the [[= product_name_cdp_base =]] integration, you must first make arrangements with [[= product_name_base =]]. -## How does [[= product_name_cdp_base =]] tracking work +## [[= product_name_cdp_base =]] tracking To start [tracking](https://content.raptorservices.com/help-center/introduction-to-tracking-documentation) user interactions, the tracking script needs to be added to the website’s layout. -Tracking can be set up either on the client-side, server-side, or using hybrid mode, depending on how you want to capture and process the events. - -The tracking works differently depending on the mode you choose. -In server-side mode, tracking happens on the server, handling all events without loading scripts in the browser. -In client-side mode, it inserts script tags so tracking runs directly in the browser. -In hybrid mode, the browser loads a first-party [shim](https://en.wikipedia.org/wiki/Shim_(computing)) that forwards tracking events to a same-origin proxy endpoint instead of the [[= product_name_cdp_base =]] SaaS script, helping prevent ad blockers from blocking tracking. -For more information, see [Hybrid tracking](hybrid_tracking.md). - -You can switch between tracking modes at any time by changing the tracking type to fit your setup and needs. ## Capabilities ### Tracking -[[= product_name_cdp_base =]] [tracking functions](tracking_functions.md) allow you to collect data about how users interact with your products and content. - -You can track product visits to better understand what users are viewing. -Provided Twig functions simplify the implementation, allowing developers to quickly add tracking to templates without complex setup. +[[= product_name_cdp_base =]] tracking allows you to collect data about how users interact with your products and content. This gives you the data you need to better understand user behavior, improve recommendations, and support personalization. @@ -89,11 +69,6 @@ Recommendation blocks are organized into dedicated categories, each grouping blo For a complete description of Recommendation blocks see [Recommendation blocks in User Documentation]([[= user_doc =]]/recommendations/raptor_integration/raptor_recommendation_blocks/). -### Advanced usage for complex tracking scenarios - -For more complex tracking requirements, [PHP API](tracking_php_api.md) provides direct access to the service. -It lets you track custom user actions, create more detailed tracking logic, and support scenarios not covered by the standard setups. - ## Benefits ### Understand user behavior @@ -126,8 +101,3 @@ Start building predictions of their behaviors and suggest products your visitors Use the [[= product_name_cdp_base =]] service in your Commerce shop and see how recommendations drive sales. Keep track of which recommendations are shown to visitors and measure conversion rates to evaluate their effectiveness against your goals. - -### Flexible tracking with PHP API - -Tracking using PHP API gives you full control over how events are recorded and processed. -You can use it for complex scenarios, so tracking can be adapted to your specific needs or business requirements. diff --git a/docs/recommendations/raptor_integration/recommendation_blocks.md b/docs/recommendations/raptor_integration/recommendation_blocks.md index 9d5e03977d9..e219b129ea5 100644 --- a/docs/recommendations/raptor_integration/recommendation_blocks.md +++ b/docs/recommendations/raptor_integration/recommendation_blocks.md @@ -1,6 +1,5 @@ --- description: Recommendation blocks in Page Builder -edition: experience month_change: false --- diff --git a/docs/release_notes.md b/docs/release_notes.md index f4dc31b777c..f1e07ffa87d 100644 --- a/docs/release_notes.md +++ b/docs/release_notes.md @@ -1,12 +1,12 @@ --- -description: Ibexa DXP v5.0 incorporates features brought by LTS Updates from previous versions, brings upgrades to the tech stack and improvements to developer experience. -title: Ibexa DXP v5.0 LTS +description: Cohesivo release notes list the new features and improvements delivered to the platform. +title: Cohesivo release notes month_change: true --- -[[= release_notes_filters('Ibexa DXP v5.0 LTS', ['Headless', 'Experience', 'LTS Update', 'New feature', 'First release']) =]] +[[= release_notes_filters('Cohesivo release notes', ['New feature', 'First release']) =]]
@@ -16,7 +16,7 @@ month_change: true [[= release_note_entry_begin( 'TODO: Release notes for SaaS', date, - ['Headless', 'Experience', 'LTS Update', 'New feature'] + ['New feature'] ) =]] diff --git a/docs/search/activity_log_search_reference/action_criterion.md b/docs/search/activity_log_search_reference/action_criterion.md index 71b9c14cd53..1b58d6d4a91 100644 --- a/docs/search/activity_log_search_reference/action_criterion.md +++ b/docs/search/activity_log_search_reference/action_criterion.md @@ -7,17 +7,3 @@ matches activity log group that has a log entry with one of the given actions. - `actions` - list of action name strings. A set of built-in names is available as `ActivityLogServiceInterface`'s `ACTION_` prefixed constants. - -## Example - -``` php -use Ibexa\Contracts\ActivityLog\ActivityLogServiceInterface; -use Ibexa\Contracts\ActivityLog\Values\ActivityLog as ActivityLog; - -$query = new ActivityLog\Query([ - new ActivityLog\Criterion\ActionCriterion([ - ActivityLogServiceInterface::ACTION_DELETE, - ActivityLogServiceInterface::ACTION_TRASH, - ]), -]); -``` diff --git a/docs/search/activity_log_search_reference/activity_log_criteria.md b/docs/search/activity_log_search_reference/activity_log_criteria.md index c9f64c3188b..a9f991d5662 100644 --- a/docs/search/activity_log_search_reference/activity_log_criteria.md +++ b/docs/search/activity_log_search_reference/activity_log_criteria.md @@ -12,7 +12,7 @@ Those Criteria are to be used with `Ibexa\Contracts\ActivityLog\Values\ActivityL They're applied to log entry groups. For example, with the criterion `ActionCriterion`, you get log entry groups that have at least one entry with this action (and possibly other actions as well). -See [Searching in the Activity Log groups](recent_activity.md#searching-in-the-activity-log-groups) for how to use a query, and an example combining several criteria. +See [Recent activity](../../administration/recent_activity/recent_activity.md#rest-api) for how to browse the activity log over the REST API. ## Value-based criteria diff --git a/docs/search/activity_log_search_reference/activity_log_sort_clauses.md b/docs/search/activity_log_search_reference/activity_log_sort_clauses.md index 41ebc3e92bd..ac1a8fdc4c5 100644 --- a/docs/search/activity_log_search_reference/activity_log_sort_clauses.md +++ b/docs/search/activity_log_search_reference/activity_log_sort_clauses.md @@ -1,6 +1,6 @@ # Activity Log Search Sort Clauses reference -See [Searching in the Activity Log groups](recent_activity.md#searching-in-the-activity-log-groups) for the whole API. +See [Recent activity](../../administration/recent_activity/recent_activity.md#rest-api) for how to browse the activity log over the REST API. Sort Clauses are found in the `Ibexa\Contracts\ActivityLog\Values\ActivityLog\SortClause` namespace. diff --git a/docs/search/activity_log_search_reference/logged_at_criterion.md b/docs/search/activity_log_search_reference/logged_at_criterion.md index c39b486fa3f..538e7b869a3 100644 --- a/docs/search/activity_log_search_reference/logged_at_criterion.md +++ b/docs/search/activity_log_search_reference/logged_at_criterion.md @@ -15,15 +15,3 @@ The `LoggedAtCriterion` Activity Log Criterion matches activity log group that h | Less than or equal | `<=` | `LoggedAtCriterion::LTE` | | Greater than | `>` | `LoggedAtCriterion::GT` | | Greater than or equal | `>=` | `LoggedAtCriterion::GTE` | - -## Example - -The following example is to match all activity log groups that aren't older than a day: - -``` php -use Ibexa\Contracts\ActivityLog\Values\ActivityLog as ActivityLog; - -$query = new ActivityLog\Query([ - new ActivityLog\Criterion\LoggedAtCriterion(new \DateTime('- 1 day'), ActivityLog\Criterion\LoggedAtCriterion::GTE), -]); -``` diff --git a/docs/search/activity_log_search_reference/object_criterion.md b/docs/search/activity_log_search_reference/object_criterion.md index 55e7b069319..f058f6dbd53 100644 --- a/docs/search/activity_log_search_reference/object_criterion.md +++ b/docs/search/activity_log_search_reference/object_criterion.md @@ -6,21 +6,3 @@ The `ObjectCriterion` Activity Log Criterion matches log group with a log entry - `objectClass` - a class of the object concerned by the searched log entries - `ids` - an optional list of object IDs - -## Examples - -``` php -use Ibexa\Contracts\ActivityLog\Values\ActivityLog as ActivityLog; - -$query = new ActivityLog\Query([ - new ActivityLog\Criterion\ObjectCriterion(Ibexa\Contracts\Core\Repository\Values\Content\Content::class), -]); -``` - -``` php -use Ibexa\Contracts\ActivityLog\Values\ActivityLog as ActivityLog; - -$query = new ActivityLog\Query([ - new ActivityLog\Criterion\ObjectCriterion(Ibexa\Contracts\ProductCatalog\Values\ProductVariantInterface::class, ['123', '234', '345']), -]); -``` diff --git a/docs/search/activity_log_search_reference/object_name_criterion.md b/docs/search/activity_log_search_reference/object_name_criterion.md index 1eea5139c36..fc9cc7d6f75 100644 --- a/docs/search/activity_log_search_reference/object_name_criterion.md +++ b/docs/search/activity_log_search_reference/object_name_criterion.md @@ -10,13 +10,3 @@ The `ObjectNameCriterion` Activity Log Criterion matches log groups that have a - `ObjectNameCriterion::OPERATOR_STARTS_WITH` - `ObjectNameCriterion::OPERATOR_ENDS_WITH` - `ObjectNameCriterion::OPERATOR_EQUALS` - -## Example - -``` php -use Ibexa\Contracts\ActivityLog\Values\ActivityLog as ActivityLog; - -$query = new ActivityLog\Query([ - new ActivityLog\Criterion\ObjectNameCriterion('Ibexa', ActivityLog\Criterion\ObjectNameCriterion::OPERATOR_CONTAINS), -]); -``` diff --git a/docs/search/activity_log_search_reference/user_criterion.md b/docs/search/activity_log_search_reference/user_criterion.md index 871f6e61135..075dc781841 100644 --- a/docs/search/activity_log_search_reference/user_criterion.md +++ b/docs/search/activity_log_search_reference/user_criterion.md @@ -5,13 +5,3 @@ The `UserCriterion` Activity Log Criterion matches log groups that have an activ ## Argument - `ids` - list of user IDs - -## Example - -``` php -use Ibexa\Contracts\ActivityLog\Values\ActivityLog as ActivityLog; - -$query = new ActivityLog\Query([ - new ActivityLog\Criterion\UserCriterion([10, 14]), -]); -``` diff --git a/docs/search/aggregation_reference/aggregation_reference.md b/docs/search/aggregation_reference/aggregation_reference.md index 7ae970f8e7e..0cf903eb8af 100644 --- a/docs/search/aggregation_reference/aggregation_reference.md +++ b/docs/search/aggregation_reference/aggregation_reference.md @@ -5,7 +5,7 @@ page_type: reference # Aggregation reference -[Aggregation](search_api.md#aggregation) is used to group search results into categories. +Aggregation is used to group search results into categories. There are three types of aggregations: diff --git a/docs/search/aggregation_reference/authorterm_aggregation.md b/docs/search/aggregation_reference/authorterm_aggregation.md index d170997b61c..8a0c4facec3 100644 --- a/docs/search/aggregation_reference/authorterm_aggregation.md +++ b/docs/search/aggregation_reference/authorterm_aggregation.md @@ -4,20 +4,8 @@ description: AuthorTermAggregation # AuthorTermAggregation -The field-based [AuthorTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-AuthorTermAggregation.html) aggregates search results by the value of the Author field. +The field-based AuthorTermAggregation aggregates search results by the value of the Author field. ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\AuthorTermAggregation('author', 'article', 'authors'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/basepricestats_aggregation.md b/docs/search/aggregation_reference/basepricestats_aggregation.md index 492aad61f06..8a8602cc0b6 100644 --- a/docs/search/aggregation_reference/basepricestats_aggregation.md +++ b/docs/search/aggregation_reference/basepricestats_aggregation.md @@ -17,17 +17,3 @@ You can use the provided getters to access the values: - `name` - name of the Aggregation - `\Ibexa\Contracts\ProductCatalog\Values\CurrencyInterface` - currency of the price - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\CurrencyInterface; -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Aggregation\BasePriceStatsAggregation; - -/** @var CurrencyInterface $currency */ -$query = new ProductQuery(); -$query->setAggregations([ - new BasePriceStatsAggregation('base_price_stats_aggregation', $currency), -]); -``` diff --git a/docs/search/aggregation_reference/checkboxterm_aggregation.md b/docs/search/aggregation_reference/checkboxterm_aggregation.md index 7f503ff8323..3e2693fff3a 100644 --- a/docs/search/aggregation_reference/checkboxterm_aggregation.md +++ b/docs/search/aggregation_reference/checkboxterm_aggregation.md @@ -4,20 +4,8 @@ description: CheckboxTermAggregation # CheckboxTermAggregation -The field-based [CheckboxTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-CheckboxTermAggregation.html) aggregates search results by the value of the Checkbox field. +The field-based CheckboxTermAggregation aggregates search results by the value of the Checkbox field. ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\CheckboxTermAggregation('checkbox', 'article', 'enable_comments'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/contenttypegroupterm_aggregation.md b/docs/search/aggregation_reference/contenttypegroupterm_aggregation.md index 0a77afbe985..242c39bd7c0 100644 --- a/docs/search/aggregation_reference/contenttypegroupterm_aggregation.md +++ b/docs/search/aggregation_reference/contenttypegroupterm_aggregation.md @@ -4,20 +4,8 @@ description: ContentTypeGroupTermAggregation # ContentTypeGroupTermAggregation -The [ContentTypeGroupTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-ContentTypeGroupTermAggregation.html) aggregates search results by the content item's content type group. +The ContentTypeGroupTermAggregation aggregates search results by the content item's content type group. ## Arguments - `name` - name of the Aggregation object - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\ContentTypeGroupTermAggregation('content_type_group'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/contenttypeterm_aggregation.md b/docs/search/aggregation_reference/contenttypeterm_aggregation.md index 62d729603c1..c7c484cd19e 100644 --- a/docs/search/aggregation_reference/contenttypeterm_aggregation.md +++ b/docs/search/aggregation_reference/contenttypeterm_aggregation.md @@ -4,20 +4,8 @@ description: ContentTypeTermAggregation # ContentTypeTermAggregation -The [ContentTypeTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-ContentTypeTermAggregation.html) aggregates search results by the content item's content type. +The ContentTypeTermAggregation aggregates search results by the content item's content type. ## Arguments - `name` - name of the Aggregation object - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\ContentTypeTermAggregation('content_type'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/countryterm_aggregation.md b/docs/search/aggregation_reference/countryterm_aggregation.md index 81e34ddde96..2d341c8374b 100644 --- a/docs/search/aggregation_reference/countryterm_aggregation.md +++ b/docs/search/aggregation_reference/countryterm_aggregation.md @@ -4,20 +4,8 @@ description: CountryTermAggregation # CountryTermAggregation -The field-based [CountryTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-CountryTermAggregation.html) aggregates search results by the value of the Country field. +The field-based CountryTermAggregation aggregates search results by the value of the Country field. ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\CountryTermAggregation('country', 'article', 'country'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/custompricestats_aggregation.md b/docs/search/aggregation_reference/custompricestats_aggregation.md index 1433c97352c..5b483fefef3 100644 --- a/docs/search/aggregation_reference/custompricestats_aggregation.md +++ b/docs/search/aggregation_reference/custompricestats_aggregation.md @@ -17,21 +17,3 @@ The CustomPriceStatsAggregation aggregates search results by the value of the cu - `name` - name of the Aggregation - `\Ibexa\Contracts\ProductCatalog\Values\CurrencyInterface` - currency of the price - `\Ibexa\Contracts\ProductCatalog\Values\CustomerGroupInterface|null` - customer group that defines custom pricing, by default it's the one assigned to current user - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\CurrencyInterface; -use Ibexa\Contracts\ProductCatalog\Values\CustomerGroupInterface; -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Aggregation\CustomPriceStatsAggregation; - -/** - * @var CurrencyInterface $currency - * @var CustomerGroupInterface $customerGroup - */ -$query = new ProductQuery(); -$query->setAggregations([ - new CustomPriceStatsAggregation('custom_price_stats_aggregation', $currency, $customerGroup), -]); -``` diff --git a/docs/search/aggregation_reference/datemetadatarange_aggregation.md b/docs/search/aggregation_reference/datemetadatarange_aggregation.md index 5b766dc53f8..e905e5b3503 100644 --- a/docs/search/aggregation_reference/datemetadatarange_aggregation.md +++ b/docs/search/aggregation_reference/datemetadatarange_aggregation.md @@ -4,29 +4,10 @@ description: DateMetadataRangeAggregation # DateMetadataRangeAggregation -The [DateMetadataRangeAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-CountryTermAggregation.html) aggregates search results by the value of the content items' date metadata. +The DateMetadataRangeAggregation aggregates search results by the value of the content items' date metadata. ## Arguments - `name` - name of the Aggregation object - `type` - string representing the type of the Aggregation (`MODIFIED` or `PUBLISHED`) - `ranges` - array of Range objects that define the borders of the specific range sets - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range; - -$query = new Query(); -$query->aggregations[] = new Aggregation\DateMetadataRangeAggregation( - 'date_metadata', - Aggregation\DateMetadataRangeAggregation::PUBLISHED, - [ - Range::ofDateTime(null, new DateTime('2020-06-01')), - Range::ofDateTime(new DateTime('2020-06-01'), new DateTime('2020-12-31')), - Range::ofDateTime(new DateTime('2020-12-31'), null), - ] -); -``` diff --git a/docs/search/aggregation_reference/daterange_aggregation.md b/docs/search/aggregation_reference/daterange_aggregation.md index 5a4a9b9edd8..0a2c3cf004a 100644 --- a/docs/search/aggregation_reference/daterange_aggregation.md +++ b/docs/search/aggregation_reference/daterange_aggregation.md @@ -4,30 +4,10 @@ description: DateRangeAggregation # DateRangeAggregation -The field-based [DateRangeAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-DateRangeAggregation.html) aggregates search results by the value of the Date, DateTime, or Time field. +The field-based DateRangeAggregation aggregates search results by the value of the Date, DateTime, or Time field. ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - `ranges` - array of Range objects that define the borders of the specific range sets - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\DateRangeAggregation( - 'date', - 'event', - 'event_date', - [ - Range::ofDateTime(null, new DateTime('2020-06-01')), - Range::ofDateTime(new DateTime('2020-06-01'), new DateTime('2020-12-31')), - Range::ofDateTime(new DateTime('2020-12-31'), null), -] -); -``` diff --git a/docs/search/aggregation_reference/datetimerange_aggregation.md b/docs/search/aggregation_reference/datetimerange_aggregation.md index 8e4cab9f28c..53aad2161bb 100644 --- a/docs/search/aggregation_reference/datetimerange_aggregation.md +++ b/docs/search/aggregation_reference/datetimerange_aggregation.md @@ -4,30 +4,10 @@ description: DateTimeRangeAggregation # DateTimeRangeAggregation -The field-based [DateTimeRangeAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-DateTimeRangeAggregation.html) aggregates search results by the value of the Date, DateTime, or Time field. +The field-based DateTimeRangeAggregation aggregates search results by the value of the Date, DateTime, or Time field. ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - `ranges` - array of Range objects that define the borders of the specific range sets - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\DateTimeRangeAggregation( - 'date', - 'event', - 'event_date', - [ - Range::ofDateTime(null, new DateTime('2020-06-01')), - Range::ofDateTime(new DateTime('2020-06-01'), new DateTime('2020-12-31')), - Range::ofDateTime(new DateTime('2020-12-31'), null), -] -); -``` diff --git a/docs/search/aggregation_reference/floatrange_aggregation.md b/docs/search/aggregation_reference/floatrange_aggregation.md index e5451c4979d..817630826de 100644 --- a/docs/search/aggregation_reference/floatrange_aggregation.md +++ b/docs/search/aggregation_reference/floatrange_aggregation.md @@ -4,30 +4,10 @@ description: FloatRangeAggregation # FloatRangeAggregation -The field-based [FloatRangeAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-FloatRangeAggregation.html) aggregates search results by the value of the Float field. +The field-based FloatRangeAggregation aggregates search results by the value of the Float field. ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - `ranges` - array of Range objects that define the borders of the specific range sets - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\FloatRangeAggregation( - 'float', - 'product', - 'weight', - [ - Range::ofFloat(null, 0.25), - Range::ofFloat(0.25, 0.75), - Range::ofFloat(0.75, null), -] -); -``` diff --git a/docs/search/aggregation_reference/floatstats_aggregation.md b/docs/search/aggregation_reference/floatstats_aggregation.md index 5fc94453788..a82ba25b753 100644 --- a/docs/search/aggregation_reference/floatstats_aggregation.md +++ b/docs/search/aggregation_reference/floatstats_aggregation.md @@ -4,7 +4,7 @@ description: FloatStatsAggregation # FloatStatsAggregation -The field-based [FloatStatsAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-FloatStatsAggregation.html) aggregates search results by the value of the Float field and provides statistical information for the values. +The field-based FloatStatsAggregation aggregates search results by the value of the Float field and provides statistical information for the values. You can use the provided getters to access the values: - sum (`getSum()`) @@ -16,13 +16,3 @@ You can use the provided getters to access the values: ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\FloatStatsAggregation('float', 'product', 'weight'); -``` diff --git a/docs/search/aggregation_reference/integerrange_aggregation.md b/docs/search/aggregation_reference/integerrange_aggregation.md index 4080d205218..31f96c7da0c 100644 --- a/docs/search/aggregation_reference/integerrange_aggregation.md +++ b/docs/search/aggregation_reference/integerrange_aggregation.md @@ -4,30 +4,10 @@ description: IntegerRangeAggregation # IntegerRangeAggregation -The field-based [IntegerRangeAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-IntegerRangeAggregation.html) aggregates search results by the value of the Integer field. +The field-based IntegerRangeAggregation aggregates search results by the value of the Integer field. ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - `ranges` - array of Range objects that define the borders of the specific range sets - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\IntegerRangeAggregation( - 'integer', - 'product', - 'amount', - [ - Range::ofInt(null, 12), - Range::ofInt(12, 24), - Range::ofInt(24, null), -] -); -``` diff --git a/docs/search/aggregation_reference/integerstats_aggregation.md b/docs/search/aggregation_reference/integerstats_aggregation.md index ff31603d22c..72acad2c38e 100644 --- a/docs/search/aggregation_reference/integerstats_aggregation.md +++ b/docs/search/aggregation_reference/integerstats_aggregation.md @@ -4,7 +4,7 @@ description: IntegerStatsAggregation # IntegerStatsAggregation -The field-based [IntegerStatsAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-IntegerStatsAggregation.html) aggregates search results by the value of the Integer field and provides statistical information for the values. You can use the provided getters to access the values: +The field-based IntegerStatsAggregation aggregates search results by the value of the Integer field and provides statistical information for the values. You can use the provided getters to access the values: - sum (`getSum()`) - count of values (`getCount()`) @@ -15,13 +15,3 @@ The field-based [IntegerStatsAggregation](/api/php_api/php_api_reference/classes ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\IntegerStatsAggregation('integer', 'product', 'amount'); -``` diff --git a/docs/search/aggregation_reference/keywordterm_aggregation.md b/docs/search/aggregation_reference/keywordterm_aggregation.md index 4457069e313..45fa456762e 100644 --- a/docs/search/aggregation_reference/keywordterm_aggregation.md +++ b/docs/search/aggregation_reference/keywordterm_aggregation.md @@ -4,20 +4,8 @@ description: KeywordTermAggregation # KeywordTermAggregation -The field-based [KeywordTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-KeywordTermAggregation.html) aggregates search results by the value of the Keyword field. +The field-based KeywordTermAggregation aggregates search results by the value of the Keyword field. ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\KeywordTermAggregation('keyword', 'article', 'tags'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/languageterm_aggregation.md b/docs/search/aggregation_reference/languageterm_aggregation.md index 41a7f88dbba..dbc6cd4c33e 100644 --- a/docs/search/aggregation_reference/languageterm_aggregation.md +++ b/docs/search/aggregation_reference/languageterm_aggregation.md @@ -4,20 +4,8 @@ description: LanguageTermAggregation # LanguageTermAggregation -The [LanguageTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-LanguageTermAggregation.html) aggregates search results by the content item's language. +The LanguageTermAggregation aggregates search results by the content item's language. ## Arguments - `name` - name of the Aggregation object - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\LanguageTermAggregation('language'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/locationchildrenterm_aggregation.md b/docs/search/aggregation_reference/locationchildrenterm_aggregation.md index 077bdaca942..0f5de4920c3 100644 --- a/docs/search/aggregation_reference/locationchildrenterm_aggregation.md +++ b/docs/search/aggregation_reference/locationchildrenterm_aggregation.md @@ -4,20 +4,8 @@ description: LocationChildrenTermAggregation # LocationChildrenTermAggregation -The [LocationChildrenTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Location-LocationChildrenTermAggregation.html) aggregates search results by the number of children of a location. +The LocationChildrenTermAggregation aggregates search results by the number of children of a location. ## Arguments - `name` - name of the Aggregation object - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new LocationQuery(); -$query->aggregations[] = new Aggregation\Location\LocationChildrenTermAggregation('location_children'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/objectstateterm_aggregation.md b/docs/search/aggregation_reference/objectstateterm_aggregation.md index cd5b1ffa133..de88b0e0a7a 100644 --- a/docs/search/aggregation_reference/objectstateterm_aggregation.md +++ b/docs/search/aggregation_reference/objectstateterm_aggregation.md @@ -4,21 +4,9 @@ description: ObjectStateTermAggregation # ObjectStateTermAggregation -The [ObjectStateTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-ObjectStateTermAggregation.html) aggregates search results by the content item's object state. +The ObjectStateTermAggregation aggregates search results by the content item's object state. ## Arguments - `name` - name of the Aggregation object - `objectStateGroupIdentifier` - string representing the identifier of the object state group to aggregate results by - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\ObjectStateTermAggregation('object_state', 'ibexa_lock'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/product_attribute_aggregations.md b/docs/search/aggregation_reference/product_attribute_aggregations.md index 845092669d9..5e3e8fb3548 100644 --- a/docs/search/aggregation_reference/product_attribute_aggregations.md +++ b/docs/search/aggregation_reference/product_attribute_aggregations.md @@ -24,30 +24,3 @@ Depending on attribute type, the following aggregations are available: Range aggregations (`ProductAttributeFloatRangeAggregation` and `ProductAttributeIntegerRangeAggregation`) additionally take: - `ranges` - array of Range objects that define the borders of the specific range sets - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Aggregation\AttributeSelectionTermAggregation; - -$query = new ProductQuery(); -$query->setAggregations([ - new AttributeSelectionTermAggregation('skin', 'skin_type'), -]); -``` - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range; -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Aggregation\AttributeIntegerRangeAggregation; - -$query = new ProductQuery(); -$query->setAggregations([ - new AttributeIntegerRangeAggregation('buttons', 'number_of_buttons', [ - Range::ofInt(null, 5), - Range::ofInt(5, 10), - Range::ofInt(10, null), - ]), -]); -``` diff --git a/docs/search/aggregation_reference/productavailabilityterm_aggregation.md b/docs/search/aggregation_reference/productavailabilityterm_aggregation.md index 946fb1d611a..3be98e5a0be 100644 --- a/docs/search/aggregation_reference/productavailabilityterm_aggregation.md +++ b/docs/search/aggregation_reference/productavailabilityterm_aggregation.md @@ -9,15 +9,3 @@ The ProductAvailabilityTermAggregation aggregates search results by product avai ## Arguments - `name` - name of the Aggregation object - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Aggregation\ProductAvailabilityTermAggregation; - -$query = new ProductQuery(); -$query->setAggregations([ - new ProductAvailabilityTermAggregation('product_availability'), -]); -``` diff --git a/docs/search/aggregation_reference/productpricerange_aggregation.md b/docs/search/aggregation_reference/productpricerange_aggregation.md index ea1455dbc9c..32da874c58e 100644 --- a/docs/search/aggregation_reference/productpricerange_aggregation.md +++ b/docs/search/aggregation_reference/productpricerange_aggregation.md @@ -11,19 +11,3 @@ The ProductPriceRangeAggregation aggregates search results by the value of the p - `name` - name of the Aggregation - `currencyCode` - currency code of the price - `ranges` - array of Range objects that define the borders of the specific range sets - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range; -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Aggregation\ProductPriceRangeAggregation; - -$query = new ProductQuery(); -$query->setAggregations([ - new ProductPriceRangeAggregation('price', 'PLN', [ - Range::ofInt(0, 10000), - Range::ofInt(10000, null), - ]), -]); -``` diff --git a/docs/search/aggregation_reference/productstockrange_aggregation.md b/docs/search/aggregation_reference/productstockrange_aggregation.md index d098fe6bcaf..7ce1efb5800 100644 --- a/docs/search/aggregation_reference/productstockrange_aggregation.md +++ b/docs/search/aggregation_reference/productstockrange_aggregation.md @@ -10,20 +10,3 @@ The ProductStockRangeAggregation aggregates search results by products' numerica - `name` - name of the Aggregation - `ranges` - array of Range objects that define the borders of the specific range sets - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range; -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Aggregation\ProductStockRangeAggregation; - -$productQuery = new ProductQuery(); -$productQuery->setAggregations([ - new ProductStockRangeAggregation('stock', [ - Range::ofInt(null, 10), - Range::ofInt(10, 100), - Range::ofInt(100, null), - ]), -]); -``` diff --git a/docs/search/aggregation_reference/producttypeterm_aggregation.md b/docs/search/aggregation_reference/producttypeterm_aggregation.md index d5f5c10c26f..8e130b9bc3e 100644 --- a/docs/search/aggregation_reference/producttypeterm_aggregation.md +++ b/docs/search/aggregation_reference/producttypeterm_aggregation.md @@ -9,15 +9,3 @@ The ProductTypeTermAggregation aggregates search results by the product type. ## Arguments - `name` - name of the Aggregation object - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Aggregation\ProductTypeTermAggregation; - -$query = new ProductQuery(); -$query->setAggregations([ - new ProductTypeTermAggregation('product_type'), -]); -``` diff --git a/docs/search/aggregation_reference/rawrange_aggregation.md b/docs/search/aggregation_reference/rawrange_aggregation.md index 1e0d36e81a9..8c02e0f557c 100644 --- a/docs/search/aggregation_reference/rawrange_aggregation.md +++ b/docs/search/aggregation_reference/rawrange_aggregation.md @@ -4,7 +4,7 @@ description: RawRangeAggregation # RawRangeAggregation -The [RawRangeAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-RawRangeAggregation.html) aggregates search results by the value of the selected search index field. +The RawRangeAggregation aggregates search results by the value of the selected search index field. ## Arguments @@ -18,17 +18,3 @@ The [RawRangeAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts To keep your project search engine independent, don't use the `RawRangeAggregation` Aggregation in production code. Valid use cases are: testing, or temporary (one-off) tools. - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range; - -$query = new LocationQuery(); -$query->aggregations[] = new Aggregation\RawRangeAggregation('priority', 'priority_id', [ - Range::ofInt(1, 10), - Range::ofInt(10, 100), -]); -``` diff --git a/docs/search/aggregation_reference/rawstats_aggregation.md b/docs/search/aggregation_reference/rawstats_aggregation.md index 67315492d62..4e38c46d947 100644 --- a/docs/search/aggregation_reference/rawstats_aggregation.md +++ b/docs/search/aggregation_reference/rawstats_aggregation.md @@ -4,7 +4,7 @@ description: RawStatsAggregation # RawStatsAggregation -The [RawStatsAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-RawStatsAggregation.html) aggregates search results by the value of the selected search index field and provides statistical information for the values. +The RawStatsAggregation aggregates search results by the value of the selected search index field and provides statistical information for the values. You can use the provided getters to access the values: - sum (`getSum()`) @@ -24,13 +24,3 @@ You can use the provided getters to access the values: To keep your project search engine independent, don't use the `RawStatsAggregation` Aggregation in production code. Valid use cases are: testing, or temporary (one-off) tools. - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\RawStatsAggregation('location_depth', 'depth_i'); -``` diff --git a/docs/search/aggregation_reference/rawterm_aggregation.md b/docs/search/aggregation_reference/rawterm_aggregation.md index a1b4aee7eb9..1d29af26f6d 100644 --- a/docs/search/aggregation_reference/rawterm_aggregation.md +++ b/docs/search/aggregation_reference/rawterm_aggregation.md @@ -4,7 +4,7 @@ description: RawTermAggregation # RawTermAggregation -The [RawTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-RawTermAggregation.html) aggregates search results by the value of the selected search index field. +The RawTermAggregation aggregates search results by the value of the selected search index field. ## Arguments @@ -17,15 +17,3 @@ The [RawTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts- To keep your project search engine independent, don't use the `RawTermAggregation` Aggregation in production code. Valid use cases are: testing, or temporary (one-off) tools. - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\RawTermAggregation('content_per_content_type', 'content_type_id_id'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/sectionterm_aggregation.md b/docs/search/aggregation_reference/sectionterm_aggregation.md index 0dc3a5ae991..3a3a94f0960 100644 --- a/docs/search/aggregation_reference/sectionterm_aggregation.md +++ b/docs/search/aggregation_reference/sectionterm_aggregation.md @@ -4,20 +4,8 @@ description: SectionTermAggregation # SectionTermAggregation -The [SectionTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-SectionTermAggregation.html) aggregates search results by the content item's section. +The SectionTermAggregation aggregates search results by the content item's section. ## Arguments - `name` - name of the Aggregation object - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\SectionTermAggregation('section'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/selectionterm_aggregation.md b/docs/search/aggregation_reference/selectionterm_aggregation.md index 17164582ba3..3e75926ddee 100644 --- a/docs/search/aggregation_reference/selectionterm_aggregation.md +++ b/docs/search/aggregation_reference/selectionterm_aggregation.md @@ -4,20 +4,8 @@ description: SelectionTermAggregation # SelectionTermAggregation -The field-based [SelectionTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-SelectionTermAggregation.html) aggregates search results by the value of the Selection field. +The field-based SelectionTermAggregation aggregates search results by the value of the Selection field. ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\SelectionTermAggregation('selection', 'article', 'select'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/subtreeterm_aggregation.md b/docs/search/aggregation_reference/subtreeterm_aggregation.md index 902a59f5bd0..5655014b165 100644 --- a/docs/search/aggregation_reference/subtreeterm_aggregation.md +++ b/docs/search/aggregation_reference/subtreeterm_aggregation.md @@ -4,21 +4,9 @@ description: SubtreeTermAggregation # SubtreeTermAggregation -The [SubtreeTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Location-SubtreeTermAggregation.html) aggregates search results by the location's subtree path. +The SubtreeTermAggregation aggregates search results by the location's subtree path. ## Arguments - `name` - name of the Aggregation object - `pathString` - string representing the pathstring to aggregate results by - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\Location\SubtreeTermAggregation('pathstring', '/1/2/'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/taxonomyentryid_aggregation.md b/docs/search/aggregation_reference/taxonomyentryid_aggregation.md index ce35d66f949..808bb3b60ec 100644 --- a/docs/search/aggregation_reference/taxonomyentryid_aggregation.md +++ b/docs/search/aggregation_reference/taxonomyentryid_aggregation.md @@ -10,21 +10,3 @@ The `TaxonomyEntryIdAggregation` aggregates search results by the content item's - `name` - name of the Aggregation object - `taxonomyIdentifier` - identifier of the taxonomy to aggregate results by - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Taxonomy\Search\Query\Aggregation as Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\TaxonomyEntryIdAggregation('taxonomy', 'tags'); -``` - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\Taxonomy\Search\Query\Aggregation\TaxonomyEntryIdAggregation; - -$query = new ProductQuery(); -$query->setAggregations([new TaxonomyEntryIdAggregation('categories', 'product_categories')]); -``` diff --git a/docs/search/aggregation_reference/timerange_aggregation.md b/docs/search/aggregation_reference/timerange_aggregation.md index bd1fc9a1e84..d2707863ca8 100644 --- a/docs/search/aggregation_reference/timerange_aggregation.md +++ b/docs/search/aggregation_reference/timerange_aggregation.md @@ -4,34 +4,10 @@ description: TimeRangeAggregation # TimeRangeAggregation -The field-based [TimeRangeAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-Field-TimeRangeAggregation.html) aggregates search results by the value of the Date, DateTime, or Time field. +The field-based TimeRangeAggregation aggregates search results by the value of the Date, DateTime, or Time field. ## Arguments [[= include_file('docs/snippets/aggregation_arguments.md') =]] - `ranges` - array of Range objects that define the borders of the specific range sets - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range; - -$timestamp = mktime(14, 0, 0); -if ($timestamp === false) { - throw new RuntimeException('Failed to create timestamp with mktime.'); -} - -$query = new Query(); -$query->aggregations[] = new Aggregation\Field\TimeRangeAggregation( - 'date', - 'event', - 'event_time', - [ - Range::ofInt(null, $timestamp), - Range::ofInt($timestamp, null), -] -); -``` diff --git a/docs/search/aggregation_reference/usermetadataterm_aggregation.md b/docs/search/aggregation_reference/usermetadataterm_aggregation.md index b61f72f1096..abebd0a3187 100644 --- a/docs/search/aggregation_reference/usermetadataterm_aggregation.md +++ b/docs/search/aggregation_reference/usermetadataterm_aggregation.md @@ -4,20 +4,8 @@ description: UserMetadataTermAggregation # UserMetadataTermAggregation -The [UserMetadataTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-UserMetadataTermAggregation.html) aggregates search results by the User content item's metadata. +The UserMetadataTermAggregation aggregates search results by the User content item's metadata. ## Arguments - `name` - name of the Aggregation object - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\UserMetadataTermAggregation('user_metadata'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/aggregation_reference/visibilityterm_aggregation.md b/docs/search/aggregation_reference/visibilityterm_aggregation.md index 843cb5a36c7..1fa03e009a8 100644 --- a/docs/search/aggregation_reference/visibilityterm_aggregation.md +++ b/docs/search/aggregation_reference/visibilityterm_aggregation.md @@ -4,20 +4,8 @@ description: VisibilityTermAggregation # VisibilityTermAggregation -The [VisibilityTermAggregation](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Aggregation-VisibilityTermAggregation.html) aggregates search results by the content item's visibility. +The VisibilityTermAggregation aggregates search results by the content item's visibility. ## Arguments - `name` - name of the Aggregation object - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation; - -$query = new Query(); -$query->aggregations[] = new Aggregation\VisibilityTermAggregation('visibility'); -``` - -[[= include_file('docs/snippets/search_term_aggregation_settings.md') =]] diff --git a/docs/search/ai_actions_search_reference/action_configuration_criteria.md b/docs/search/ai_actions_search_reference/action_configuration_criteria.md index 198c442a21b..e51d8fe97be 100644 --- a/docs/search/ai_actions_search_reference/action_configuration_criteria.md +++ b/docs/search/ai_actions_search_reference/action_configuration_criteria.md @@ -5,24 +5,13 @@ description: Search Criteria available for Action Configuration search # Action Configuration Search Criterion reference -Search criteria are found in the `Ibexa\Contracts\ConnectorAi\ActionConfiguration\Query\Criterion` namespace, implementing the [CriterionInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-CriterionInterface.html) interface: +Search criteria are found in the `Ibexa\Contracts\ConnectorAi\ActionConfiguration\Query\Criterion` namespace, implementing the CriterionInterface interface: | Criterion | Description | |---|---| -| [Name](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-Criterion-Name.html) | Find Action Configurations matching given name. Use [FieldValueCriterion's constants](/api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constants) like `FieldValueCriterion::COMPARISON_CONTAINS` or `FieldValueCriterion::COMPARISON_STARTS_WITH` to specify the matching condition| -| [Enabled](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-Criterion-Enabled.html) | Find enabled or disabled Action Configurations | -| [Identifier](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-Criterion-Identifier.html) | Find Action Configuration having the exact given identifier | -| [LogicalAnd](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-Criterion-LogicalAnd.html) | Composite criterion to group multiple criteria using the AND condition | -| [LogicalOr](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-Criterion-LogicalOr.html) | Composite criterion to group multiple criteria using the OR condition | -| [Type](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-Criterion-Type.html) | Find Action Configuration having the exact given type | - -The following example shows how to use them to find specific Action Configurations: - -``` php -[[= include_code('code_samples/ai_actions/src/Query/Search.php') =]] -``` - -The result set contains Action Configurations that are: - -- enabled, and -- with an identifier equal to `casual` or with a name starting with `Casual`. +| Name | Find Action Configurations matching given name. Use FieldValueCriterion's constants like `FieldValueCriterion::COMPARISON_CONTAINS` or `FieldValueCriterion::COMPARISON_STARTS_WITH` to specify the matching condition| +| Enabled | Find enabled or disabled Action Configurations | +| Identifier | Find Action Configuration having the exact given identifier | +| LogicalAnd | Composite criterion to group multiple criteria using the AND condition | +| LogicalOr | Composite criterion to group multiple criteria using the OR condition | +| Type | Find Action Configuration having the exact given type | diff --git a/docs/search/ai_actions_search_reference/action_configuration_sort_clauses.md b/docs/search/ai_actions_search_reference/action_configuration_sort_clauses.md index 46dc5cca99b..5a4db9f9d2c 100644 --- a/docs/search/ai_actions_search_reference/action_configuration_sort_clauses.md +++ b/docs/search/ai_actions_search_reference/action_configuration_sort_clauses.md @@ -5,19 +5,8 @@ description: Sort Clauses available for Action Configuration search # Action Configuration Search Sort Clauses reference -Sort Clauses are found in the `Ibexa\Contracts\ConnectorAi\ActionConfiguration\Query\SortClause` namespace, implementing the [SortClauseInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-SortClauseInterface.html) interface: +Sort Clauses are found in the `Ibexa\Contracts\ConnectorAi\ActionConfiguration\Query\SortClause` namespace, implementing the SortClauseInterface interface: -- [Enabled](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-SortClause-Enabled.html) -- [Id](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-SortClause-Id.html) -- [Identifier](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ConnectorAi-ActionConfiguration-Query-SortClause-Identifier.html) - -The following example shows how to use them to sort the searched Action Configurations: - -``` php -[[= include_code('code_samples/ai_actions/src/Query/Search.php') =]] -``` - -The search results are sorted by: - -- status, with enabled on top -- identifier, in ascending order. +- Enabled +- Id +- Identifier diff --git a/docs/search/content_type_search_reference/content_type_criteria.md b/docs/search/content_type_search_reference/content_type_criteria.md index 18b6a7d538e..a068486dc80 100644 --- a/docs/search/content_type_search_reference/content_type_criteria.md +++ b/docs/search/content_type_search_reference/content_type_criteria.md @@ -6,22 +6,14 @@ month_change: false # Content Type Search Criteria reference -Content Type Search Criteria are only supported by [Content Type Search (`ContentTypeService::findContentTypes`)](managing_content.md#finding-and-filtering-content-types). - | Criterion | Description | |-------|-------------| -| [ContainsFieldDefinitionId](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-Criterion-ContainsFieldDefinitionId.html) | Matches content types that contain a field definition with the specified ID. | -| [ContentTypeGroupId](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-Criterion-ContentTypeGroupId.html) | Matches content types by their assigned group ID. | -| [ContentTypeGroupName](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-Criterion-ContentTypeGroupName.html) | Matches content types by the name of their assigned group. | -| [ContentTypeId](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-Criterion-ContentTypeId.html) | Matches content types by their ID. | -| [ContentTypeIdentifier](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-Criterion-ContentTypeIdentifier.html) | Matches content types by their identifier. | -| [IsSystem](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-Criterion-IsSystem.html) | Matches content types based on whether the group they belong to is system or not. | -| [LogicalAnd](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-Criterion-LogicalAnd.html) | Implements a logical AND Criterion. It matches if ALL of the provided Criteria match. | -| [LogicalOr](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-Criterion-LogicalOr.html) | Implements a logical OR Criterion. It matches if at least one of the provided Criteria matches. | -| [LogicalNot](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-Criterion-LogicalNot.html) | Implements a logical NOT Criterion. It matches if the provided Criterion doesn't match. | - -The following example shows how to use them to search for content types: - -``` php hl_lines="29-31" -[[= include_code('code_samples/api/public_php_api/src/Command/FindContentTypeCommand.php') =]] -``` +| ContainsFieldDefinitionId | Matches content types that contain a field definition with the specified ID. | +| ContentTypeGroupId | Matches content types by their assigned group ID. | +| ContentTypeGroupName | Matches content types by the name of their assigned group. | +| ContentTypeId | Matches content types by their ID. | +| ContentTypeIdentifier | Matches content types by their identifier. | +| IsSystem | Matches content types based on whether the group they belong to is system or not. | +| LogicalAnd | Implements a logical AND Criterion. It matches if ALL of the provided Criteria match. | +| LogicalOr | Implements a logical OR Criterion. It matches if at least one of the provided Criteria matches. | +| LogicalNot | Implements a logical NOT Criterion. It matches if the provided Criterion doesn't match. | diff --git a/docs/search/content_type_search_reference/content_type_sort_clauses.md b/docs/search/content_type_search_reference/content_type_sort_clauses.md index 6943d5d9af1..c3550287781 100644 --- a/docs/search/content_type_search_reference/content_type_sort_clauses.md +++ b/docs/search/content_type_search_reference/content_type_sort_clauses.md @@ -6,20 +6,11 @@ month_change: false # Content Type Search Sort Clauses Content Type Search Sort Clauses are the sorting options for content types. -They're only supported by [Content Type Search (`ContentTypeService::findContentTypes`)](managing_content.md#finding-and-filtering-content-types). -Sort Clauses are found in the [`Ibexa\Contracts\Core\Repository\Values\ContentType\Query\SortClause`](/api/php_api/php_api_reference/namespaces/ibexa-contracts-core-repository-values-contenttype-query-sortclause.html) namespace: +Sort Clauses are found in the `Ibexa\Contracts\Core\Repository\Values\ContentType\Query\SortClause` namespace: | Name | Description | | --- | --- | -| [Id](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-SortClause-Id.html)| Sort by content type's id | -| [Identifier](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-SortClause-Identifier.html)| Sort by content type's identifier | -| [Name](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-ContentType-Query-SortClause-Name.html)| Sort by content type's name | - -The following example shows how to use them to sort the searched content types: - -``` php hl_lines="34-36" -[[= include_code('code_samples/api/public_php_api/src/Command/FindContentTypeCommand.php') =]] -``` - -You can change the default sorting order by using the `SORT_ASC` and `SORT_DESC` constants from [`AbstractSortClause`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-AbstractSortClause.html#constants). +| Id| Sort by content type's id | +| Identifier| Sort by content type's identifier | +| Name| Sort by content type's name | diff --git a/docs/search/criteria_reference/ancestor_criterion.md b/docs/search/criteria_reference/ancestor_criterion.md index 024d8c3c9cb..ff653b8488e 100644 --- a/docs/search/criteria_reference/ancestor_criterion.md +++ b/docs/search/criteria_reference/ancestor_criterion.md @@ -4,7 +4,7 @@ description: Ancestor Search Criterion # Ancestor Criterion -The [`Ancestor` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-Ancestor.html) searches for content that is an ancestor of the provided location, including this location. +The `Ancestor` Search Criterion searches for content that is an ancestor of the provided location, including this location. ## Arguments @@ -12,19 +12,6 @@ The [`Ancestor` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-C ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -/** @var \Ibexa\Contracts\Core\Repository\LocationService $locationService */ -$query->query = new Criterion\Ancestor([$locationService->loadLocation(62)->pathString]); -``` - -### REST API - === "XML" ```xml @@ -47,37 +34,4 @@ $query->query = new Criterion\Ancestor([$locationService->loadLocation(62)->path ## Use case -You can use the Ancestor Search Criterion to create a list of breadcrumbs leading to the Location: - -``` php hl_lines="8" -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$locationId = 12345; - -$query = new LocationQuery(); -/** @var \Ibexa\Contracts\Core\Repository\LocationService $locationService */ -$query->query = new Criterion\Ancestor([$locationService->loadLocation($locationId)->pathString]); - -/** @var \Ibexa\Contracts\Core\Repository\SearchService $searchService */ -$results = $searchService->findLocations($query); -$breadcrumbs = []; -foreach ($results->searchHits as $searchHit) { - $breadcrumbs[] = $searchHit; -} - -return $this->render('parts/breadcrumbs.html.twig', [ - 'breadcrumbs' => $breadcrumbs, -]); -``` - -``` html+twig -{% for breadcrumb in breadcrumbs %} - {% if not loop.first %} -> {% endif %} - {% if not loop.last %} - {{ breadcrumb.valueObject.contentInfo.name }} - {% else %} - {{ breadcrumb.valueObject.contentInfo.name }} - {% endif %} -{% endfor %} -``` +You can use the `Ancestor` Search Criterion to create a list of breadcrumbs leading to a location, because it matches every ancestor of that location, including the location itself. diff --git a/docs/search/criteria_reference/attributegroupidentifier_criterion.md b/docs/search/criteria_reference/attributegroupidentifier_criterion.md index 29e49a5ba47..58027341c36 100644 --- a/docs/search/criteria_reference/attributegroupidentifier_criterion.md +++ b/docs/search/criteria_reference/attributegroupidentifier_criterion.md @@ -12,8 +12,6 @@ The `AttributeGroupIdentifier` Search Criterion searches for products by the val ## Example -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/attributename_criterion.md b/docs/search/criteria_reference/attributename_criterion.md index 76eacd55949..f2d295baff6 100644 --- a/docs/search/criteria_reference/attributename_criterion.md +++ b/docs/search/criteria_reference/attributename_criterion.md @@ -12,8 +12,6 @@ The `AttributeName` Search Criterion searches for products by the value of their ## Example -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/baseprice_criterion.md b/docs/search/criteria_reference/baseprice_criterion.md index c834d0b4166..adaf948ab59 100644 --- a/docs/search/criteria_reference/baseprice_criterion.md +++ b/docs/search/criteria_reference/baseprice_criterion.md @@ -4,7 +4,7 @@ description: BasePrice Search Criterion # BasePrice Criterion -The [`BasePrice` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-BasePrice.html) searches for products by their base price. +The `BasePrice` Search Criterion searches for products by their base price. ## Arguments @@ -14,20 +14,3 @@ The [`BasePrice` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa- ## Limitations The `BasePrice` Criterion isn't available in the Legacy Search engine. - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\BasePrice( - \Money\Money::EUR(12900), - \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\Operator::GTE - ) -); -``` diff --git a/docs/search/criteria_reference/catalogidentifier_criterion.md b/docs/search/criteria_reference/catalogidentifier_criterion.md index 45418e29d12..a261585e356 100644 --- a/docs/search/criteria_reference/catalogidentifier_criterion.md +++ b/docs/search/criteria_reference/catalogidentifier_criterion.md @@ -12,8 +12,6 @@ The `CatalogIdentifier` Search Criterion searches for a catalog by the value of ## Example -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/catalogname_criterion.md b/docs/search/criteria_reference/catalogname_criterion.md index 03e1cc6b83a..871ba47df0c 100644 --- a/docs/search/criteria_reference/catalogname_criterion.md +++ b/docs/search/criteria_reference/catalogname_criterion.md @@ -12,8 +12,6 @@ The `CatalogName` Search Criterion searches for catalogs by the value of their n ## Example -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/catalogstatus_criterion.md b/docs/search/criteria_reference/catalogstatus_criterion.md index 652adf48741..2779df8c51d 100644 --- a/docs/search/criteria_reference/catalogstatus_criterion.md +++ b/docs/search/criteria_reference/catalogstatus_criterion.md @@ -12,8 +12,6 @@ The `CatalogStatus` Search Criterion searches for catalogs by the value of their ## Example -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/checkboxattribute_criterion.md b/docs/search/criteria_reference/checkboxattribute_criterion.md index 64fefc9895b..73d7c45b66f 100644 --- a/docs/search/criteria_reference/checkboxattribute_criterion.md +++ b/docs/search/criteria_reference/checkboxattribute_criterion.md @@ -10,17 +10,3 @@ The `CheckboxAttribute` Search Criterion searches for products by the value of t - `identifier` - string representing the attribute - `value` - bool representing the attribute value - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\CheckboxAttribute('automatic', true) -); -``` diff --git a/docs/search/criteria_reference/colorattribute_criterion.md b/docs/search/criteria_reference/colorattribute_criterion.md index 2de0571bbb1..1dbb828618b 100644 --- a/docs/search/criteria_reference/colorattribute_criterion.md +++ b/docs/search/criteria_reference/colorattribute_criterion.md @@ -13,20 +13,6 @@ The `ColorAttribute` Search Criterion searches for products by the value of thei ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\ColorAttribute('color', ['#FF0000']) -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/contentid_criterion.md b/docs/search/criteria_reference/contentid_criterion.md index 0a547c22aec..cb4a6e38cb6 100644 --- a/docs/search/criteria_reference/contentid_criterion.md +++ b/docs/search/criteria_reference/contentid_criterion.md @@ -4,7 +4,7 @@ description: ContentId Search Criterion # ContentId Criterion -The [`ContentId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-ContentId.html) searches for content by its ID. +The `ContentId` Search Criterion searches for content by its ID. ## Arguments @@ -12,18 +12,6 @@ The [`ContentId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa- ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\ContentId([62, 64]); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/contentname_criterion.md b/docs/search/criteria_reference/contentname_criterion.md index c91512386c3..6011e6aedc5 100644 --- a/docs/search/criteria_reference/contentname_criterion.md +++ b/docs/search/criteria_reference/contentname_criterion.md @@ -12,18 +12,6 @@ The [`ContentName` Search Criterion](https://github.com/ibexa/core/blob/6.0/src/ ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\ContentName('*phone'); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/contenttypegroupid_criterion.md b/docs/search/criteria_reference/contenttypegroupid_criterion.md index d901be3cf69..27ff20148f4 100644 --- a/docs/search/criteria_reference/contenttypegroupid_criterion.md +++ b/docs/search/criteria_reference/contenttypegroupid_criterion.md @@ -4,7 +4,7 @@ description: ContentTypeGroupId Search Criterion # ContentTypeGroupId Criterion -The [`ContentTypeGroupId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-ContentTypeGroupId.html) searches for content based on the ID of its content type group. +The `ContentTypeGroupId` Search Criterion searches for content based on the ID of its content type group. ## Arguments @@ -12,18 +12,6 @@ The [`ContentTypeGroupId` Search Criterion](/api/php_api/php_api_reference/class ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\ContentTypeGroupId([1, 2]); -``` - -### REST API - === "XML" ```xml @@ -46,21 +34,5 @@ $query->query = new Criterion\ContentTypeGroupId([1, 2]); ## Use case -You can use the `ContentTypeGroupId` Criterion to query all Media content items -(the default ID for the Media content type group is 3): - -``` php hl_lines="6" -use Ibexa\Contracts\Core\Repository\SearchService; -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\ContentTypeGroupId([3]); - -/** @var SearchService $searchService */ -$results = $searchService->findContent($query); -$media = []; -foreach ($results->searchHits as $searchHit) { - $media[] = $searchHit; -} -``` +You can use the `ContentTypeGroupId` Criterion to query all Media content items. +The default ID for the Media content type group is 3. diff --git a/docs/search/criteria_reference/contenttypeid_criterion.md b/docs/search/criteria_reference/contenttypeid_criterion.md index 853ba1b9089..7edbdae1e9a 100644 --- a/docs/search/criteria_reference/contenttypeid_criterion.md +++ b/docs/search/criteria_reference/contenttypeid_criterion.md @@ -4,7 +4,7 @@ description: ContentTypeId Search Criterion # ContentTypeId Criterion -The [`ContentTypeId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-ContentTypeId.html) searches for content based on the ID of its content type. +The `ContentTypeId` Search Criterion searches for content based on the ID of its content type. ## Arguments @@ -12,18 +12,6 @@ The [`ContentTypeId` Search Criterion](/api/php_api/php_api_reference/classes/Ib ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\ContentTypeId([44]); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/contenttypeidentifier_criterion.md b/docs/search/criteria_reference/contenttypeidentifier_criterion.md index 1d980812ff0..3b400d21a44 100644 --- a/docs/search/criteria_reference/contenttypeidentifier_criterion.md +++ b/docs/search/criteria_reference/contenttypeidentifier_criterion.md @@ -4,7 +4,7 @@ description: ContentTypeIdentifier Search Criterion # ContentTypeIdentifier Criterion -The [`ContentTypeIdentifier` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-ContentTypeIdentifier.html) searches for content based on the identifier of its content type. +The `ContentTypeIdentifier` Search Criterion searches for content based on the identifier of its content type. ## Arguments @@ -12,18 +12,6 @@ The [`ContentTypeIdentifier` Search Criterion](/api/php_api/php_api_reference/cl ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\ContentTypeIdentifier(['article', 'blog_post']); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/createdat_criterion.md b/docs/search/criteria_reference/createdat_criterion.md index 1c146535aad..6891fd5180e 100644 --- a/docs/search/criteria_reference/createdat_criterion.md +++ b/docs/search/criteria_reference/createdat_criterion.md @@ -13,22 +13,6 @@ The `CreatedAt` Search Criterion searches for products based on the date when th ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$criteria = new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\CreatedAt( - new DateTime('2023-03-01'), - \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\Operator::GTE, -); - -$productQuery = new ProductQuery(null, $criteria); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/createdatrange_criterion.md b/docs/search/criteria_reference/createdatrange_criterion.md index 04a1265c202..fe860215cad 100644 --- a/docs/search/criteria_reference/createdatrange_criterion.md +++ b/docs/search/criteria_reference/createdatrange_criterion.md @@ -13,22 +13,6 @@ The `CreatedAtRange` Search Criterion searches for products based on the date ra ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$criteria = new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\CreatedAtRange( - new \DateTimeImmutable('2020-07-10T00:00:00+00:00'), - new \DateTimeImmutable('2023-07-12T00:00:00+00:00') -); - -$productQuery = new ProductQuery(null, $criteria); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/currencycode_criterion.md b/docs/search/criteria_reference/currencycode_criterion.md index 7c6b98cbe51..4b8ab315d35 100644 --- a/docs/search/criteria_reference/currencycode_criterion.md +++ b/docs/search/criteria_reference/currencycode_criterion.md @@ -13,15 +13,3 @@ The `CurrencyCodeCriterion` Search Criterion searches for currencies by their co ## Limitations The `CurrencyCodeCriterion` Criterion isn't available in Solr or Elasticsearch engines. - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Currency\CurrencyQuery; - -$query = new CurrencyQuery( - new \Ibexa\Contracts\ProductCatalog\Values\Currency\Query\Criterion\CurrencyCodeCriterion('EUR') -); -``` diff --git a/docs/search/criteria_reference/customergroupid_criterion.md b/docs/search/criteria_reference/customergroupid_criterion.md index 44c7b31977c..8bf2d16795a 100644 --- a/docs/search/criteria_reference/customergroupid_criterion.md +++ b/docs/search/criteria_reference/customergroupid_criterion.md @@ -9,15 +9,3 @@ The `CustomerGroupId` Search Criterion searches for content based on the ID of i ## Arguments - `value` - int(s) representing the customer group ID(s) - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\ProductCatalog\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\CustomerGroupId(1); -``` diff --git a/docs/search/criteria_reference/customfield_criterion.md b/docs/search/criteria_reference/customfield_criterion.md index 67f9e2e307a..633133ba501 100644 --- a/docs/search/criteria_reference/customfield_criterion.md +++ b/docs/search/criteria_reference/customfield_criterion.md @@ -5,24 +5,12 @@ month_change: false # Custom Field Criterion -The [`CustomField` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-CustomField.html) searches for content or locations based on the contents of the search index fields. +The `CustomField` Search Criterion searches for content or locations based on the contents of the search index fields. The allowed syntax and operator support might differ between search engines and the type of queried field. ## Arguments - `target` - string representing the identifier of the search index field -- `operator` - one of [Operator](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-Operator.html) constants +- `operator` - one of Operator constants - `value` - the value to query for - -## Limitations - -The `CustomField` Criterion isn't available in [Repository filtering](search_api.md#repository-filtering). - -## Example - -### PHP - -``` php -[[= include_code('code_samples/search/content/customfield_criterion.php') =]] -``` diff --git a/docs/search/criteria_reference/customprice_criterion.md b/docs/search/criteria_reference/customprice_criterion.md index 0855e9e5960..2f108b09e9b 100644 --- a/docs/search/criteria_reference/customprice_criterion.md +++ b/docs/search/criteria_reference/customprice_criterion.md @@ -16,22 +16,3 @@ If you don't provide a customer group, the query uses the group related to the c ## Limitations The `CustomPrice` Criterion isn't available in the Legacy Search engine. - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -/** @var \Ibexa\Contracts\ProductCatalog\Values\CustomerGroupInterface $customerGroup */ -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\CustomPrice( - \Money\Money::EUR(13800), - \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\Operator::GTE, - $customerGroup - ) -); -``` diff --git a/docs/search/criteria_reference/datemetadata_criterion.md b/docs/search/criteria_reference/datemetadata_criterion.md index 200a02d3e22..bb25dd7a3c5 100644 --- a/docs/search/criteria_reference/datemetadata_criterion.md +++ b/docs/search/criteria_reference/datemetadata_criterion.md @@ -4,7 +4,7 @@ description: DateMetadata Search Criterion # DateMetadata Criterion -The [`DateMetadata` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-DateMetadata.html) searches for content based on the date when it was created or last modified. +The `DateMetadata` Search Criterion searches for content based on the date when it was created or last modified. ## Arguments @@ -14,22 +14,6 @@ The [`DateMetadata` Search Criterion](/api/php_api/php_api_reference/classes/Ibe ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\DateMetadata( - Criterion\DateMetadata::CREATED, - Criterion\Operator::BETWEEN, - [1576800000, 1576972800] -); -``` - -### REST API - === "XML" ```xml @@ -60,18 +44,4 @@ $query->query = new Criterion\DateMetadata( ## Use case -You can use the `DateMetadata` Criterion to search for blog posts that have been created within the last week: - -``` php hl_lines="9" -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new LocationQuery(); -$date = strtotime('-1 week'); -$query->query = new Criterion\LogicalAnd( - [ - new Criterion\ContentTypeIdentifier('blog_post'), - new Criterion\DateMetadata(Criterion\DateMetadata::CREATED, Criterion\Operator::GTE, $date), - ] -); -``` +You can use the `DateMetadata` Criterion to search for blog posts that have been created within the last week, by combining it with a content type Criterion and the `GTE` operator. diff --git a/docs/search/criteria_reference/datetimeattribute_criterion.md b/docs/search/criteria_reference/datetimeattribute_criterion.md index 19bad71f315..8bdfe2d1920 100644 --- a/docs/search/criteria_reference/datetimeattribute_criterion.md +++ b/docs/search/criteria_reference/datetimeattribute_criterion.md @@ -4,7 +4,7 @@ description: DateTimeAttribute Criterion # DateTimeAttribute criterion -The [`DateTimeAttribute Search Criterion`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalogDateTimeAttribute-Search-Criterion-DateTimeAttribute.html) searches for products by value of a specified attribute, based on the [date and time attribute](date_and_time.md) type. +The `DateTimeAttribute Search Criterion` searches for products by value of a specified attribute, based on the [date and time attribute](date_and_time.md) type. ## Arguments @@ -15,19 +15,9 @@ The [`DateTimeAttribute Search Criterion`](/api/php_api/php_api_reference/classe The following operators are supported: -- [FieldValueCriterion::COMPARISON_EQ](/api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_EQ) -- [FieldValueCriterion::COMPARISON_NEQ](/api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_NEQ) -- [FieldValueCriterion::COMPARISON_LT](/api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_LT) -- [FieldValueCriterion::COMPARISON_LTE](/api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_LTE) -- [FieldValueCriterion::COMPARISON_GT](/api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_GT) -- [FieldValueCriterion::COMPARISON_GTE](/api/php_api/php_api_reference/classes/Ibexa-Contracts-CoreSearch-Values-Query-Criterion-FieldValueCriterion.html#constant_COMPARISON_GTE) - -## Example - -### PHP - -The following example lists all products for which the `event_date` attribute has value equal to 2025-07-06. - -``` php -[[= include_code('code_samples/back_office/search/src/Query/DateTimeAttributeQuery.php') =]] -``` +- `FieldValueCriterion::COMPARISON_EQ` +- `FieldValueCriterion::COMPARISON_NEQ` +- `FieldValueCriterion::COMPARISON_LT` +- `FieldValueCriterion::COMPARISON_LTE` +- `FieldValueCriterion::COMPARISON_GT` +- `FieldValueCriterion::COMPARISON_GTE` \ No newline at end of file diff --git a/docs/search/criteria_reference/datetimeattributerange_criterion.md b/docs/search/criteria_reference/datetimeattributerange_criterion.md index cfa267c9f14..bcf3d697ff1 100644 --- a/docs/search/criteria_reference/datetimeattributerange_criterion.md +++ b/docs/search/criteria_reference/datetimeattributerange_criterion.md @@ -4,20 +4,10 @@ description: DateTimeAttributeRange Criterion # DateTimeAttributeRange criterion -The [`DateTimeAttributeRange Search Criterion`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalogDateTimeAttribute-Search-Criterion-DateTimeAttributeRange.html) searches for products by value of a specified attribute, which must be based on the [date and time attribute](date_and_time.md) type. +The `DateTimeAttributeRange Search Criterion` searches for products by value of a specified attribute, which must be based on the [date and time attribute](date_and_time.md) type. ## Arguments - `identifier` - attribute's identifier (string) - `min` - lower range value (inclusive) of [DateTimeImmutable](https://www.php.net/manual/en/class.datetimeimmutable.php) type. Optional. - `max` - upper range value (inclusive) of [DateTimeImmutable](https://www.php.net/manual/en/class.datetimeimmutable.php) type. Optional. - -## Example - -### PHP - -The following example lists all products for which the `event_date` attribute has value greater than 2025-01-01. - -``` php -[[= include_code('code_samples/back_office/search/src/Query/DateTimeAttributeRangeQuery.php') =]] -``` diff --git a/docs/search/criteria_reference/depth_criterion.md b/docs/search/criteria_reference/depth_criterion.md index 984ccb64353..53159828884 100644 --- a/docs/search/criteria_reference/depth_criterion.md +++ b/docs/search/criteria_reference/depth_criterion.md @@ -4,7 +4,7 @@ description: Depth Search Criterion # Depth Criterion -The [`Location\Depth` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-Location-Depth.html) searches for locations based on their depth in the content tree. +The `Location\Depth` Search Criterion searches for locations based on their depth in the content tree. This Criterion is available only for Location Search. @@ -18,15 +18,3 @@ The `value` argument requires: - a list of ints for `Operator::IN` - exactly two ints for `Operator::BETWEEN` - a single int for other Operators - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\Location\Depth(Criterion\Operator::LT, 3); -``` diff --git a/docs/search/criteria_reference/field_criterion.md b/docs/search/criteria_reference/field_criterion.md index c873d733059..2ed5b08effd 100644 --- a/docs/search/criteria_reference/field_criterion.md +++ b/docs/search/criteria_reference/field_criterion.md @@ -4,7 +4,7 @@ description: Field Search Criterion # Field Criterion -The [`Field` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-Field.html) searches for content based on the content of one of its fields. +The `Field` Search Criterion searches for content based on the content of one of its fields. ## Arguments @@ -17,24 +17,8 @@ The `LIKE` operator works together with wildcards (`*`). Without a wildcards its The `CONTAINS` operator works with collection fields like the Country field type, enabling you to retrieve results when the query value is one of the values of the collection. Querying for a collection with the `EQ` operator returns result only when the whole collection equals the query values. -## Limitations - -The `Field` Criterion isn't available in [Repository filtering](search_api.md#repository-filtering). - ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\Field('name', Criterion\Operator::CONTAINS, 'Platform'); -``` - -### REST API - === "XML" ```xml @@ -67,17 +51,4 @@ $query->query = new Criterion\Field('name', Criterion\Operator::CONTAINS, 'Platf ## Use case -You can use the `Field` Criterion to search for articles that contain the word "featured": - -``` php hl_lines="8" -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new LocationQuery(); -$query->query = new Criterion\LogicalAnd( - [ - new Criterion\ContentTypeIdentifier('article'), - new Criterion\Field('name', Criterion\Operator::CONTAINS, 'Featured'), - ] -); -``` +You can use the `Field` Criterion to search for articles whose `name` field contains the word "Featured", by combining it with a content type Criterion and the `CONTAINS` operator. diff --git a/docs/search/criteria_reference/fieldrelation_criterion.md b/docs/search/criteria_reference/fieldrelation_criterion.md index 9640f43c2c6..016e0aa2a26 100644 --- a/docs/search/criteria_reference/fieldrelation_criterion.md +++ b/docs/search/criteria_reference/fieldrelation_criterion.md @@ -4,7 +4,7 @@ description: FieldRelation Search Criterion # FieldRelation Criterion -The [`FieldRelation` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-FieldRelation.html) searches for content based on the content items it has Relations to. +The `FieldRelation` Search Criterion searches for content based on the content items it has Relations to. ## Arguments @@ -13,19 +13,3 @@ The [`FieldRelation` Search Criterion](/api/php_api/php_api_reference/classes/Ib - `value` - array of ints representing the Relation content IDs to search for Use of IN means the Relation needs to have one of the provided IDs, while CONTAINS implies it needs to have all provided IDs. - -## Limitations - -The `FieldRelation` Criterion isn't available in [Repository filtering](search_api.md#repository-filtering). - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\FieldRelation('relations', Criterion\Operator::CONTAINS, [55, 63]); -``` diff --git a/docs/search/criteria_reference/floatattribute_criterion.md b/docs/search/criteria_reference/floatattribute_criterion.md index 928f495b7a7..e833d5fa41d 100644 --- a/docs/search/criteria_reference/floatattribute_criterion.md +++ b/docs/search/criteria_reference/floatattribute_criterion.md @@ -13,23 +13,6 @@ The `FloatAttribute` Search Criterion searches for products by the value of thei ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\FloatAttribute( - 'length', - 16.5 - ) -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/floatattributerange_criterion.md b/docs/search/criteria_reference/floatattributerange_criterion.md index 83f90e63717..c4d4ac8715e 100644 --- a/docs/search/criteria_reference/floatattributerange_criterion.md +++ b/docs/search/criteria_reference/floatattributerange_criterion.md @@ -14,8 +14,6 @@ The `FloatAttributeRange` Search Criterion searches for products by the range of ## Example -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/fulltext_criterion.md b/docs/search/criteria_reference/fulltext_criterion.md index a9ac61cfbec..b5aacec5923 100644 --- a/docs/search/criteria_reference/fulltext_criterion.md +++ b/docs/search/criteria_reference/fulltext_criterion.md @@ -4,7 +4,7 @@ description: Full-Text Search Criterion # Full-Text Criterion -The [`FullText` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-FullText.html) searches for content based on the full text content of its fields. +The `FullText` Search Criterion searches for content based on the full text content of its fields. ## Arguments @@ -33,42 +33,8 @@ supports asterisks as wildcards located at the beginning or end of a query. When using the Elasticsearch search engine, a full text query performs an OR query by default, while the OR and AND operators return unexpected results. -The `FullText` Criterion isn't available in [Repository filtering](search_api.md#repository-filtering). - ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\FullText('victory'); -``` - -Using double quotes to indicate a phrase: - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\FullText('"world cup"'); -``` - -Using the AND operator and parenthesis to search for both words at the same time: - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\FullText('baseball AND cup'); -``` - -### REST API - === "XML" ```xml @@ -91,15 +57,8 @@ $query->query = new Criterion\FullText('baseball AND cup'); ## Use cases -Assume the following search query: - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\FullText('(cup AND ba*ball) "breaking news"'); -``` +Assume a full-text search for `(cup AND ba*ball) "breaking news"`, +which combines grouping, the `AND` operator, a wildcard, and a quoted phrase. It returns content containing phrases such as "Breaking news", "Baseball world cup", "Basketball cup", or "Breaking news: Baseball world cup victory". diff --git a/docs/search/criteria_reference/image_criterion.md b/docs/search/criteria_reference/image_criterion.md index 43ad087a37a..66f674a0f26 100644 --- a/docs/search/criteria_reference/image_criterion.md +++ b/docs/search/criteria_reference/image_criterion.md @@ -13,39 +13,6 @@ The `Image` Search Criterion searches for image by specified image attributes. ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$imageCriteriaData = [ - 'mimeTypes' => [ - 'image/png', - ], - 'orientation' => [ - 'image/png', - ], - 'width' => [ - 'min' => 0, // (default: 0, optional) - 'max' => 1000, // (default: null, optional) - ], - 'height' => [ - 'min' => 0, // (default: 0, optional) - 'max' => 1000, // (default: null, optional) - ], - 'size' => [ - 'min' => 0, // (default: 0, optional) - 'max' => 2, // (default: null, optional) - ], -]; - -$query = new Query(); -$query->query = new Criterion\Image('image', $imageCriteriaData); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/imagedimensions_criterion.md b/docs/search/criteria_reference/imagedimensions_criterion.md index 85bad978be2..0c94dd8757e 100644 --- a/docs/search/criteria_reference/imagedimensions_criterion.md +++ b/docs/search/criteria_reference/imagedimensions_criterion.md @@ -13,29 +13,6 @@ The `Dimensions` Search Criterion searches for image with specified dimensions. ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$imageCriteriaData = [ - 'width' => [ - 'min' => 100, // (default: 0, optional) - 'max' => 1000, // (default: null, optional) - ], - 'height' => [ - 'min' => 500, // (default: 0, optional) - 'max' => 1500, // (default: null, optional) - ], -]; - -$query->query = new Criterion\Image\Dimensions('image', $imageCriteriaData); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/imagefilesize_criterion.md b/docs/search/criteria_reference/imagefilesize_criterion.md index 284d4507d21..ea6f1fa0a51 100644 --- a/docs/search/criteria_reference/imagefilesize_criterion.md +++ b/docs/search/criteria_reference/imagefilesize_criterion.md @@ -14,18 +14,6 @@ The `FileSize` Search Criterion searches for image with specified size. ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\Image\FileSize('image', 0, 1.5); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/imageheight_criterion.md b/docs/search/criteria_reference/imageheight_criterion.md index ff8402b4ae7..0db5aff05a1 100644 --- a/docs/search/criteria_reference/imageheight_criterion.md +++ b/docs/search/criteria_reference/imageheight_criterion.md @@ -11,15 +11,3 @@ The `Height` Search Criterion searches for image with specified height. - `fieldDefIdentifier` - string representing the identifier of the field - (optional) `minValue` - int representing minimum file height expressed in pixels, default: 0 - (optional) `maxValue` - int representing maximum file height expressed in pixels, default: `null` - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\Image\Height('image', 0, 1500); -``` diff --git a/docs/search/criteria_reference/imagemimetype_criterion.md b/docs/search/criteria_reference/imagemimetype_criterion.md index 0564efd8da9..ce206326889 100644 --- a/docs/search/criteria_reference/imagemimetype_criterion.md +++ b/docs/search/criteria_reference/imagemimetype_criterion.md @@ -13,33 +13,6 @@ The `MimeType` Search Criterion searches for image with specified mime type(s). ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\Image\MimeType('image', 'image/jpeg'); -``` - -or - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$mimeTypes = [ - 'image/jpeg', - 'image/png', -]; - -$query->query = new Criterion\Image\MimeType('image', $mimeTypes); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/imageorientation_criterion.md b/docs/search/criteria_reference/imageorientation_criterion.md index 73d54f75b0a..41d5ec77645 100644 --- a/docs/search/criteria_reference/imageorientation_criterion.md +++ b/docs/search/criteria_reference/imageorientation_criterion.md @@ -14,36 +14,6 @@ Supported orientation values: landscape, portrait and square. ## Example -### PHP - -#### Single orientation value - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Image\Orientation; - -$query = new Query(); -$query->query = new Orientation('image', 'landscape'); -``` - -#### Multiple orientation values - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Image\Orientation; - -$query = new Query(); -$orientations = [ - 'landscape', - 'portrait', -]; - -$query->query = new Orientation('image', $orientations); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/imagewidth_criterion.md b/docs/search/criteria_reference/imagewidth_criterion.md index 63aa7708020..43841f0200e 100644 --- a/docs/search/criteria_reference/imagewidth_criterion.md +++ b/docs/search/criteria_reference/imagewidth_criterion.md @@ -11,15 +11,3 @@ The `Width` Search Criterion searches for image with specified width. - `fieldDefIdentifier` - string representing the identifier of the field - (optional) `minValue` - int representing minimum file width expressed in pixels, default: 0 - (optional) `maxValue` - int representing maximum file width expressed in pixels, default: `null` - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\Image\Width('image', 150, 1000); -``` diff --git a/docs/search/criteria_reference/integerattribute_criterion.md b/docs/search/criteria_reference/integerattribute_criterion.md index 9981cabd3c6..601c5bcf526 100644 --- a/docs/search/criteria_reference/integerattribute_criterion.md +++ b/docs/search/criteria_reference/integerattribute_criterion.md @@ -13,23 +13,6 @@ The `IntegerAttribute` Search Criterion searches for products by the value of th ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\IntegerAttribute( - 'size', - 38 - ) -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/integerattributerange_criterion.md b/docs/search/criteria_reference/integerattributerange_criterion.md index 6ff7f6ce4d4..14eb8299217 100644 --- a/docs/search/criteria_reference/integerattributerange_criterion.md +++ b/docs/search/criteria_reference/integerattributerange_criterion.md @@ -14,8 +14,6 @@ The `IntegerAttributeRange` Search Criterion searches for products by the range ## Example -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/isbookmarked_criterion.md b/docs/search/criteria_reference/isbookmarked_criterion.md index 59bc53565e1..3ac396bf4dc 100644 --- a/docs/search/criteria_reference/isbookmarked_criterion.md +++ b/docs/search/criteria_reference/isbookmarked_criterion.md @@ -5,7 +5,7 @@ month_change: false # IsBookmarked Criterion -The [`IsBookmarked` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-Location-IsBookmarked.html) +The `IsBookmarked` Search Criterion searches for location based on whether it's bookmarked or not. It works with current user reference. @@ -17,14 +17,6 @@ This Criterion is available only for location Search. ## Example -### PHP - -``` php -[[= include_code('code_samples/search/location/isbookmarked_criterion.php', 3, remove_indent=True) =]] -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/iscontainer_criterion.md b/docs/search/criteria_reference/iscontainer_criterion.md index 1edc2ba3a4c..e03a47cbf6e 100644 --- a/docs/search/criteria_reference/iscontainer_criterion.md +++ b/docs/search/criteria_reference/iscontainer_criterion.md @@ -5,21 +5,8 @@ month_change: false # IsContainer Criterion -The [`IsContainer` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-IsContainer.html) searches for content items based on whether they are containers (i.e., can contain other content items). +The `IsContainer` Search Criterion searches for content items based on whether they are containers (i.e., can contain other content items). ## Arguments - `value` – boolean (optional, default: `true`). If `true`, searches for content that is a container. If `false`, searches for content that is not a container. - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\IsContainer(); // Finds containers -$query->query = new Criterion\IsContainer(false); // Finds non-containers -``` diff --git a/docs/search/criteria_reference/iscurrencyenabled_criterion.md b/docs/search/criteria_reference/iscurrencyenabled_criterion.md index d4705842110..0778fdf0fd7 100644 --- a/docs/search/criteria_reference/iscurrencyenabled_criterion.md +++ b/docs/search/criteria_reference/iscurrencyenabled_criterion.md @@ -14,15 +14,3 @@ or disabled Currencies (`false`) ## Limitations The `IsCurrencyEnabledCriterion` Criterion isn't available in Solr or Elasticsearch engines. - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Currency\CurrencyQuery; - -$query = new CurrencyQuery( - new \Ibexa\Contracts\ProductCatalog\Values\Currency\Query\Criterion\IsCurrencyEnabledCriterion() -); -``` diff --git a/docs/search/criteria_reference/isfieldempty_criterion.md b/docs/search/criteria_reference/isfieldempty_criterion.md index c4ca0506f22..e516149a1c1 100644 --- a/docs/search/criteria_reference/isfieldempty_criterion.md +++ b/docs/search/criteria_reference/isfieldempty_criterion.md @@ -4,7 +4,7 @@ description: IsFieldEmpty Search Criterion # IsFieldEmpty Criterion -The [`IsFieldEmpty` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-IsFieldEmpty.html) searches for content based on whether a specified field is empty or not. +The `IsFieldEmpty` Search Criterion searches for content based on whether a specified field is empty or not. ## Arguments @@ -14,38 +14,11 @@ or non-empty fields (`false`) ## Limitations -The `IsFieldEmpty` Criterion isn't available in [Repository filtering](search_api.md#repository-filtering). - The Richtext field type (`ibexa_richtext`) isn't searchable in the Legacy search engine. The `IsFieldEmpty` criterion doesn't work for [Taxonomy entry assignment](taxonomyentryassignmentfield.md) fields. For this use case, use [`TaxonomyNoEntries`](taxonomy_no_entries.md) instead. -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\IsFieldEmpty('title'); -``` - ## Use case -You can use the `IsFieldEmpty` Criterion to search for articles that don't have an image: - -``` php hl_lines="8" -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new LocationQuery(); -$query->query = new Criterion\LogicalAnd( - [ - new Criterion\ContentTypeIdentifier('article'), - new Criterion\IsFieldEmpty('image'), - ] -); -``` +You can use the `IsFieldEmpty` Criterion to search for articles that don't have an image, by combining it with a content type Criterion and targeting the `image` field. diff --git a/docs/search/criteria_reference/ismainlocation_criterion.md b/docs/search/criteria_reference/ismainlocation_criterion.md index d3790a5045e..2ed93d926e6 100644 --- a/docs/search/criteria_reference/ismainlocation_criterion.md +++ b/docs/search/criteria_reference/ismainlocation_criterion.md @@ -4,7 +4,7 @@ description: IsMainLocation Search Criterion # IsMainLocation Criterion -The [`IsMainLocation` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-LanguageCode.html) searches for locations based on whether they're the main location of a content item or not. +The `IsMainLocation` Search Criterion searches for locations based on whether they're the main location of a content item or not. This Criterion is available only for Location Search. @@ -12,16 +12,3 @@ This Criterion is available only for Location Search. - `value` - `IsMainLocation::MAIN` (0) or `IsMainLocation::NOT_MAIN` (1), representing whether to search for a main or not main location - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Location\IsMainLocation; - -$query = new Query(); -$query->query = new Criterion\Location\IsMainLocation(IsMainLocation::MAIN); -``` diff --git a/docs/search/criteria_reference/isproductbased_criterion.md b/docs/search/criteria_reference/isproductbased_criterion.md index 507450e3e3c..9cab362f248 100644 --- a/docs/search/criteria_reference/isproductbased_criterion.md +++ b/docs/search/criteria_reference/isproductbased_criterion.md @@ -5,15 +5,3 @@ description: IsProductBased Search Criterion # IsProductBased Criterion The `IsProductBased` Search Criterion searches for content that plays the role of a Product. - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new \Ibexa\Contracts\ProductCatalog\Values\Content\Query\Criterion\IsProductBased(); -``` diff --git a/docs/search/criteria_reference/isuserbased_criterion.md b/docs/search/criteria_reference/isuserbased_criterion.md index b07c5cd58d5..487e446866f 100644 --- a/docs/search/criteria_reference/isuserbased_criterion.md +++ b/docs/search/criteria_reference/isuserbased_criterion.md @@ -4,12 +4,11 @@ description: IsUserBased Search Criterion # IsUserBased Criterion -The [`IsUserBased` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-IsUserBased.html) searches for content that plays the role of a User account. +The `IsUserBased` Search Criterion searches for content that plays the role of a User account. !!! note In the default setup only the user content type is treated as user accounts. - However, you can also [set other content types to be treated as such](repository_configuration.md#user-identifiers). ## Arguments @@ -22,18 +21,6 @@ The `IsUserBased` Criterion isn't available in Solr or Elasticsearch engines. ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\IsUserBased(); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/isuserenabled_criterion.md b/docs/search/criteria_reference/isuserenabled_criterion.md index bd61b058f5d..bcee0ea6a9f 100644 --- a/docs/search/criteria_reference/isuserenabled_criterion.md +++ b/docs/search/criteria_reference/isuserenabled_criterion.md @@ -5,7 +5,7 @@ month_change: false # IsUserEnabled Criterion -The [`IsUserEnabled` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-IsUserEnabled.html) searches for user accounts that are enabled or disabled. +The `IsUserEnabled` Search Criterion searches for user accounts that are enabled or disabled. ## Arguments @@ -13,18 +13,6 @@ The [`IsUserEnabled` Search Criterion](/api/php_api/php_api_reference/classes/Ib ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\IsUserEnabled(); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/isvirtual_criterion.md b/docs/search/criteria_reference/isvirtual_criterion.md index 5f2bb3aa029..51cb7640450 100644 --- a/docs/search/criteria_reference/isvirtual_criterion.md +++ b/docs/search/criteria_reference/isvirtual_criterion.md @@ -12,20 +12,6 @@ The `IsVirtual` Search Criterion searches for virtual or physical products. ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\IsVirtual(true) -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/languagecode_criterion.md b/docs/search/criteria_reference/languagecode_criterion.md index 7b74156f66d..5424ee73c38 100644 --- a/docs/search/criteria_reference/languagecode_criterion.md +++ b/docs/search/criteria_reference/languagecode_criterion.md @@ -4,7 +4,7 @@ description: LanguageCode Search Criterion # LanguageCode Criterion -The [`LanguageCode` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-Location.html) searches for content based on whether it's translated into the selected language. +The `LanguageCode` Search Criterion searches for content based on whether it's translated into the selected language. ## Arguments @@ -13,18 +13,6 @@ The [`LanguageCode` Search Criterion](/api/php_api/php_api_reference/classes/Ibe ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\LanguageCode('ger-DE', false); -``` - -### REST API - === "XML" ```xml @@ -48,28 +36,4 @@ $query->query = new Criterion\LanguageCode('ger-DE', false); ## Use case You can use the `LanguageCode` Criterion to search for articles that are lacking a translation -into a specific language: - -``` php hl_lines="9" -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new LocationQuery(); -$query->query = new Criterion\LogicalAnd( - [ - new Criterion\ContentTypeIdentifier('article'), - new Criterion\LogicalNot( - new Criterion\LanguageCode('ger-DE', false) - ), - ] -); - -/** @var \Ibexa\Contracts\Core\Repository\SearchService $searchService */ -$results = $searchService->findContent($query); -$articlesToTranslate = []; -foreach ($results->searchHits as $searchHit) { - $articlesToTranslate[] = $searchHit; -} - -return $articlesToTranslate; -``` +into a specific language, by negating it and setting `matchAlwaysAvailable` to `false`. diff --git a/docs/search/criteria_reference/locationid_criterion.md b/docs/search/criteria_reference/locationid_criterion.md index 7fba54c3f77..9c50a49147a 100644 --- a/docs/search/criteria_reference/locationid_criterion.md +++ b/docs/search/criteria_reference/locationid_criterion.md @@ -4,7 +4,7 @@ description: LocationId Search Criterion # LocationId Criterion -The [`LocationId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-LocationId.html) searches for content based in the location ID. +The `LocationId` Search Criterion searches for content based in the location ID. ## Arguments @@ -12,18 +12,6 @@ The [`LocationId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\LocationId(62); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/locationremoteid_criterion.md b/docs/search/criteria_reference/locationremoteid_criterion.md index e51cadb8c10..7e0088fcd5e 100644 --- a/docs/search/criteria_reference/locationremoteid_criterion.md +++ b/docs/search/criteria_reference/locationremoteid_criterion.md @@ -4,7 +4,7 @@ description: LocationRemoteId Search Criterion # LocationRemoteId Criterion -The [`LocationRemoteId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-LocationRemoteId.html) searches for content based in the location remote ID. +The `LocationRemoteId` Search Criterion searches for content based in the location remote ID. ## Arguments @@ -12,18 +12,6 @@ The [`LocationRemoteId` Search Criterion](/api/php_api/php_api_reference/classes ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\LocationRemoteId(['4d1e5f216c0a7aaab7f005ffd4b6a8a8', 'b81ef3e62b514188bfddd2a80d447d34']); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/logicaland_criterion.md b/docs/search/criteria_reference/logicaland_criterion.md index b5eac8a4b39..19e3a2febd0 100644 --- a/docs/search/criteria_reference/logicaland_criterion.md +++ b/docs/search/criteria_reference/logicaland_criterion.md @@ -4,9 +4,9 @@ description: LogicalAnd Search Criterion # LogicalAnd Criterion -The [`LogicalAnd` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-LogicalAnd.html) matches content if all provided Criteria match. +The `LogicalAnd` Search Criterion matches content if all provided Criteria match. -When querying for [products](product_api.md), use [LogicalAnd](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-LogicalAnd.html) instead. +When querying for products, use LogicalAnd instead. ## Arguments @@ -14,23 +14,6 @@ When querying for [products](product_api.md), use [LogicalAnd](/api/php_api/php_ ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\LogicalAnd( - [ - new Criterion\ContentTypeIdentifier('article'), - new Criterion\SectionIdentifier(['sports', 'news']), - ] -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/logicalnot_criterion.md b/docs/search/criteria_reference/logicalnot_criterion.md index b1796be8d80..daa7fc12e08 100644 --- a/docs/search/criteria_reference/logicalnot_criterion.md +++ b/docs/search/criteria_reference/logicalnot_criterion.md @@ -4,7 +4,7 @@ description: LogicalNot Search Criterion # LogicalNot Criterion -The [`LogicalNot` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-LogicalNot.html) matches content URL if the provided Criterion doesn't match. +The `LogicalNot` Search Criterion matches content URL if the provided Criterion doesn't match. It takes only one Criterion in the array parameter. @@ -14,20 +14,6 @@ It takes only one Criterion in the array parameter. ## Example -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$contentTypeIdentifier = 'article'; - -$query = new Query(); -$query->filter = new Criterion\LogicalNot( - new Criterion\ContentTypeIdentifier($contentTypeIdentifier) -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/logicalor_criterion.md b/docs/search/criteria_reference/logicalor_criterion.md index 0bbc57cd921..92ab3e4733f 100644 --- a/docs/search/criteria_reference/logicalor_criterion.md +++ b/docs/search/criteria_reference/logicalor_criterion.md @@ -4,9 +4,9 @@ description: LogicalOr Search Criterion # LogicalOr Criterion -The [`LogicalOr` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-LogicalOr.html) matches content if at least one of the provided Criteria matches. +The `LogicalOr` Search Criterion matches content if at least one of the provided Criteria matches. -When querying for [products](product_api.md), use [LogicalOr](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-LogicalOr.html) instead. +When querying for products, use LogicalOr instead. ## Arguments @@ -14,23 +14,6 @@ When querying for [products](product_api.md), use [LogicalOr](/api/php_api/php_a ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->filter = new Criterion\LogicalOr( - [ - new Criterion\ContentTypeIdentifier('article'), - new Criterion\SectionIdentifier(['sports', 'news']), - ] -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/maplocationdistance_criterion.md b/docs/search/criteria_reference/maplocationdistance_criterion.md index c70c3755241..06a5115bb14 100644 --- a/docs/search/criteria_reference/maplocationdistance_criterion.md +++ b/docs/search/criteria_reference/maplocationdistance_criterion.md @@ -4,7 +4,7 @@ description: MapLocationDistance Search Criterion # MapLocationDistance Criterion -The [`MapLocationDistance` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-MapLocationDistance.html) searches content based on the distance between the location contained in a MapLocation field and the provided coordinates. +The `MapLocationDistance` Search Criterion searches content based on the distance between the location contained in a MapLocation field and the provided coordinates. ## Arguments @@ -18,19 +18,3 @@ The `distance` argument requires: - a list of floats for `Operator::IN` or `Operator::BETWEEN` - a single float for other Operators - -## Limitations - -The `MapLocationDistance` Criterion isn't available in [Repository filtering](search_api.md#repository-filtering). - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\MapLocationDistance('location', Criterion\Operator::LTE, 5, 51.395973, 22.531696); -``` diff --git a/docs/search/criteria_reference/matchall_criterion.md b/docs/search/criteria_reference/matchall_criterion.md index 054fa715a25..1a4c9026e97 100644 --- a/docs/search/criteria_reference/matchall_criterion.md +++ b/docs/search/criteria_reference/matchall_criterion.md @@ -4,7 +4,7 @@ description: MatchAll Search Criterion # MatchAll Criterion -The [`MatchAll` content](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-MatchAll.html) and [`MatchAll` product](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-MatchAll.html) search criteria are auxiliary criteria that returns all search results. +The `MatchAll` content and `MatchAll` product search criteria are auxiliary criteria that returns all search results. They're used internally when no filter or query is provided on a Query object. The criteria take no arguments. diff --git a/docs/search/criteria_reference/matchnone_criterion.md b/docs/search/criteria_reference/matchnone_criterion.md index 87aa89292a4..dbc9c0125a5 100644 --- a/docs/search/criteria_reference/matchnone_criterion.md +++ b/docs/search/criteria_reference/matchnone_criterion.md @@ -4,7 +4,7 @@ description: MatchNone Search Criterion # MatchNone Criterion -The [`MatchNone` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-MatchNone.html) is an auxiliary Criterion that returns no search results. +The `MatchNone` Search Criterion is an auxiliary Criterion that returns no search results. It's used internally when no filter or query is provided on a Query object. The Criterion takes no arguments. diff --git a/docs/search/criteria_reference/notification_datecreated_criterion.md b/docs/search/criteria_reference/notification_datecreated_criterion.md index a74bf65200b..5941cf7a3b1 100644 --- a/docs/search/criteria_reference/notification_datecreated_criterion.md +++ b/docs/search/criteria_reference/notification_datecreated_criterion.md @@ -11,11 +11,3 @@ The `DateCreated` Search Criterion searches for notifications based on the date - `created` - date to be matched, provided as a `DateTimeInterface` object - `operator` - optional operator string (GTE, LTE) - -## Example - -### PHP - -``` php hl_lines="14-15 17" -[[= include_code('code_samples/notifications/Src/Query/search.php') =]] -``` diff --git a/docs/search/criteria_reference/notification_status_criterion.md b/docs/search/criteria_reference/notification_status_criterion.md index 6dd02a2b04b..6fc86dada9a 100644 --- a/docs/search/criteria_reference/notification_status_criterion.md +++ b/docs/search/criteria_reference/notification_status_criterion.md @@ -10,11 +10,3 @@ The `Status` Search Criterion searches for notifications based on notification s ## Arguments - `status` - Boolean value that represents the status of the notification - -## Example - -### PHP - -``` php hl_lines="12" -[[= include_code('code_samples/notifications/Src/Query/search.php') =]] -``` diff --git a/docs/search/criteria_reference/notification_type_criterion.md b/docs/search/criteria_reference/notification_type_criterion.md index edc395d61c5..8f59c94ecba 100644 --- a/docs/search/criteria_reference/notification_type_criterion.md +++ b/docs/search/criteria_reference/notification_type_criterion.md @@ -10,11 +10,3 @@ The `Type` Search Criterion searches for notifications by their types. ## Arguments - `type` - string that represents the type of the notification, takes values defined in notification workflow - -## Example - -### PHP - -``` php hl_lines="11" -[[= include_code('code_samples/notifications/Src/Query/search.php') =]] -``` diff --git a/docs/search/criteria_reference/objectstateid_criterion.md b/docs/search/criteria_reference/objectstateid_criterion.md index d4de1e801b8..ed0ae7cfa40 100644 --- a/docs/search/criteria_reference/objectstateid_criterion.md +++ b/docs/search/criteria_reference/objectstateid_criterion.md @@ -4,7 +4,7 @@ description: ObjectStateId Search Criterion # ObjectStateId Criterion -The [`ObjectStateId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-ObjectStateId.html) searches for content based on its object state ID. +The `ObjectStateId` Search Criterion searches for content based on its object state ID. ## Arguments @@ -12,18 +12,6 @@ The [`ObjectStateId` Search Criterion](/api/php_api/php_api_reference/classes/Ib ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\ObjectStateId([4, 5]); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/objectstateidentifier_criterion.md b/docs/search/criteria_reference/objectstateidentifier_criterion.md index 90cdbc36d47..630957592f3 100644 --- a/docs/search/criteria_reference/objectstateidentifier_criterion.md +++ b/docs/search/criteria_reference/objectstateidentifier_criterion.md @@ -4,7 +4,7 @@ description: ObjectStateIdentifier Search Criterion # ObjectStateIdentifier Criterion -The [`ObjectStateIdentifier` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-ObjectStateId.html) searches for content based on its object state identifier. +The `ObjectStateIdentifier` Search Criterion searches for content based on its object state identifier. ## Arguments @@ -13,26 +13,6 @@ The [`ObjectStateIdentifier` Search Criterion](/api/php_api/php_api_reference/cl ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\ObjectStateIdentifier(['ready']); -``` - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\ObjectStateIdentifier(['not_locked'], 'ibexa_lock'); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/parentlocationid_criterion.md b/docs/search/criteria_reference/parentlocationid_criterion.md index eb1514964ba..f4dc3203eb6 100644 --- a/docs/search/criteria_reference/parentlocationid_criterion.md +++ b/docs/search/criteria_reference/parentlocationid_criterion.md @@ -4,7 +4,7 @@ description: ParentLocationId Search Criterion # ParentLocationId Criterion -The [`ParentLocationId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-ParentLocationId.html) +The `ParentLocationId` Search Criterion searches for content based on the Location ID of its parent. ## Arguments @@ -13,18 +13,6 @@ searches for content based on the Location ID of its parent. ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\ParentLocationId([54, 58]); -``` - -### REST API - === "XML" ```xml @@ -47,37 +35,4 @@ $query->query = new Criterion\ParentLocationId([54, 58]); ## Use case -You can use the `ParentLocationId` Search Criterion to list blog posts contained in a blog: - -``` php hl_lines="9" -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$locationId = 12345; - -$query = new LocationQuery(); -$query->query = new Criterion\LogicalAnd([ - new Criterion\Visibility(Criterion\Visibility::VISIBLE), - new Criterion\ParentLocationId($locationId), -]); - -/** @var \Ibexa\Contracts\Core\Repository\SearchService $searchService */ -$results = $searchService->findLocations($query); -$posts = []; -foreach ($results->searchHits as $searchHit) { - $posts[] = $searchHit; -} - -return $this->render('full/blog.html.twig', [ - 'posts' => $posts, -]); -``` - -``` html+twig -

Posts:

-
    - {% for post in posts %} -
  • {{ post.valueObject.contentInfo.name }}
  • - {% endfor %} -
-``` +You can use the `ParentLocationId` Search Criterion to list blog posts contained in a blog, by combining it with the `Visibility` Criterion so that hidden posts are excluded. diff --git a/docs/search/criteria_reference/price_currency_criterion.md b/docs/search/criteria_reference/price_currency_criterion.md index c96105d174b..33aa2e44ea4 100644 --- a/docs/search/criteria_reference/price_currency_criterion.md +++ b/docs/search/criteria_reference/price_currency_criterion.md @@ -9,19 +9,3 @@ The `Currency` Search Criterion searches for prices based on the given currency. ## Arguments - `currency` - a single object or an array of `CurrencyInterface` objects that represent the currency (`Ibexa\Contracts\ProductCatalog\Values\CurrencyInterface`) - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; -use Ibexa\Contracts\ProductCatalog\Values\Price\PriceQuery; - -/** @var \Ibexa\Contracts\ProductCatalog\CurrencyServiceInterface $currencyService */ -$currency = $currencyService->getCurrencyByCode('EUR'); - -$query = new PriceQuery( - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\Currency($currency) -); -``` diff --git a/docs/search/criteria_reference/price_customergroup_criterion.md b/docs/search/criteria_reference/price_customergroup_criterion.md index 2c33e1bd647..58bd98547f4 100644 --- a/docs/search/criteria_reference/price_customergroup_criterion.md +++ b/docs/search/criteria_reference/price_customergroup_criterion.md @@ -9,19 +9,3 @@ The `CustomerGroup` Search Criterion searches for prices based on the customer g ## Arguments - `customer_group` - a single object or an array or `CustomerGroupInterface` objects that represent the customer group (`Ibexa\Contracts\ProductCatalog\Values\CustomerGroupInterface`) - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; -use Ibexa\Contracts\ProductCatalog\Values\Price\PriceQuery; - -/** @var \Ibexa\Contracts\ProductCatalog\CustomerGroupServiceInterface $customerGroupService */ -$customerGroup = $customerGroupService->getCustomerGroup(123); - -$query = new PriceQuery( - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\CustomerGroup($customerGroup) -); -``` diff --git a/docs/search/criteria_reference/price_isbaseprice_criterion.md b/docs/search/criteria_reference/price_isbaseprice_criterion.md index 56efe39038f..626737a9370 100644 --- a/docs/search/criteria_reference/price_isbaseprice_criterion.md +++ b/docs/search/criteria_reference/price_isbaseprice_criterion.md @@ -13,16 +13,3 @@ This Criterion takes no arguments. ## Limitations The `IsBasePrice` Criterion isn't available in Solr or Elasticsearch engines. - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; -use Ibexa\Contracts\ProductCatalog\Values\Price\PriceQuery; - -$query = new PriceQuery( - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\IsBasePrice() -); -``` diff --git a/docs/search/criteria_reference/price_iscustomprice_criterion.md b/docs/search/criteria_reference/price_iscustomprice_criterion.md index 0aa2ec2afb7..331971b404a 100644 --- a/docs/search/criteria_reference/price_iscustomprice_criterion.md +++ b/docs/search/criteria_reference/price_iscustomprice_criterion.md @@ -13,16 +13,3 @@ This Criterion takes no arguments. ## Limitations The `IsCustomPrice` Criterion isn't available in Solr or Elasticsearch engines. - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; -use Ibexa\Contracts\ProductCatalog\Values\Price\PriceQuery; - -$query = new PriceQuery( - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\IsCustomPrice() -); -``` diff --git a/docs/search/criteria_reference/price_logicaland_criterion.md b/docs/search/criteria_reference/price_logicaland_criterion.md index 5d234ee1ac7..32704d4a021 100644 --- a/docs/search/criteria_reference/price_logicaland_criterion.md +++ b/docs/search/criteria_reference/price_logicaland_criterion.md @@ -9,19 +9,3 @@ The `LogicalAnd` Search Criterion matches prices if all provided Criteria match. ## Arguments - `criterion` - a set of Criteria combined by the logical operator - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Price\PriceQuery; - -/** @var \Ibexa\Contracts\ProductCatalog\Values\CurrencyInterface $currencyUSD */ -$query = new PriceQuery( - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\LogicalAnd( - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\Currency($currencyUSD), - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\IsCustomPrice() - ) -); -``` diff --git a/docs/search/criteria_reference/price_logicalor_criterion.md b/docs/search/criteria_reference/price_logicalor_criterion.md index b650b87a80b..cdf1426aa0f 100644 --- a/docs/search/criteria_reference/price_logicalor_criterion.md +++ b/docs/search/criteria_reference/price_logicalor_criterion.md @@ -9,22 +9,3 @@ The `LogicalOr` Search Criterion matches prices if at least one of the provided ## Arguments - `criterion` - a set of Criteria combined by the logical operator - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Price\PriceQuery; - -/** - * @var \Ibexa\Contracts\ProductCatalog\Values\CurrencyInterface $currencyUSD - * @var \Ibexa\Contracts\ProductCatalog\Values\CurrencyInterface $currencyEUR - */ -$query = new PriceQuery( - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\LogicalOr( - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\Currency($currencyUSD), - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\Currency($currencyEUR) - ) -); -``` diff --git a/docs/search/criteria_reference/price_product_criterion.md b/docs/search/criteria_reference/price_product_criterion.md index ff213b6a058..4473fac1bc9 100644 --- a/docs/search/criteria_reference/price_product_criterion.md +++ b/docs/search/criteria_reference/price_product_criterion.md @@ -9,16 +9,3 @@ The `Product` Search Criterion searches for prices based on product codes. ## Arguments - `product_code` - a string that represents a product code or an array of codes - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; -use Ibexa\Contracts\ProductCatalog\Values\Price\PriceQuery; - -$query = new PriceQuery( - new \Ibexa\Contracts\ProductCatalog\Values\Price\Query\Criterion\Product('ergo_desk') -); -``` diff --git a/docs/search/criteria_reference/price_search_criteria.md b/docs/search/criteria_reference/price_search_criteria.md index b0b50c4c762..475485a865f 100644 --- a/docs/search/criteria_reference/price_search_criteria.md +++ b/docs/search/criteria_reference/price_search_criteria.md @@ -5,7 +5,7 @@ page_type: reference # Price Search Criteria reference -Price Search Criteria are only supported by [Price Search (`ProductPriceServiceInterface::findPrices`)](price_api.md#prices). +Price Search Criteria are only supported by price search. With these Criteria you can filter prices by currency, customer group, product, and more. diff --git a/docs/search/criteria_reference/priority_criterion.md b/docs/search/criteria_reference/priority_criterion.md index feffcf99ac1..c13d3dcc8ee 100644 --- a/docs/search/criteria_reference/priority_criterion.md +++ b/docs/search/criteria_reference/priority_criterion.md @@ -4,7 +4,7 @@ description: Priority Search Criterion # Priority Criterion -The [`Location\Priority` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-Location-Priority.html) searches for locations based on their priority. +The `Location\Priority` Search Criterion searches for locations based on their priority. This Criterion is available only for Location Search. @@ -17,15 +17,3 @@ The `value` argument requires: - a list of ints for `Operator::BETWEEN` - a single int for other Operators - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\Location\Priority(Criterion\Operator::GTE, 50); -``` diff --git a/docs/search/criteria_reference/product_search_criteria.md b/docs/search/criteria_reference/product_search_criteria.md index e1bff9f7cd2..a766ca2b2d2 100644 --- a/docs/search/criteria_reference/product_search_criteria.md +++ b/docs/search/criteria_reference/product_search_criteria.md @@ -6,7 +6,7 @@ month_change: false # Product Search Criteria reference -Product Search Criteria are supported by [product and product variant search](product_api.md#products) with the following methods: +Product Search Criteria are supported by product and product variant search. - `ProductServiceInterface::findProducts()` - `ProductServiceInterface::findProductVariants()` @@ -16,7 +16,7 @@ Search Criterion let you filter product by specific attributes, for example, col ## Product Search Criteria -To query for products coming from [[= pim_product_name =]], see [[[= pim_product_name =]] Search API](/product_catalog/quable/quable_api.md#search-for-products) for details about the integration. +To query for products coming from [[= pim_product_name =]], see [[[= pim_product_name =]]](../../product_catalog/quable/quable.md) for details about the integration. |Search Criterion|Search based on|Local product catalog|[[= pim_product_name =]]| |-----|-----|-----|-----| diff --git a/docs/search/criteria_reference/productavailability_criterion.md b/docs/search/criteria_reference/productavailability_criterion.md index 89b76bdaa77..229f078452b 100644 --- a/docs/search/criteria_reference/productavailability_criterion.md +++ b/docs/search/criteria_reference/productavailability_criterion.md @@ -7,9 +7,7 @@ month_change: false The `ProductAvailability` Search Criterion searches for products by the availability flag, the boolean value set per product or variant. -To search for products that can be ordered, recreate the availability conditions with [existing product search criteria](product_search_criteria.md), for example [LogicalAnd](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-LogicalAnd.html), [LogicalOr](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-LogicalOr.html), and [`ProductStock`](productstock_criterion.md). -To recreate complex [custom availability strategies](create_custom_availability_strategy.md), you might need to implement [custom search criteria](search_criteria_and_sort_clauses.md#custom-criteria-and-sort-clauses) for the conditions not covered by the built-in ones. - +To search for products that can be ordered, recreate the availability conditions with [existing product search criteria](product_search_criteria.md), for example LogicalAnd, LogicalOr, and [`ProductStock`](productstock_criterion.md). For more information, see [Availability and computed availability](products.md#availability-and-computed-availability). ## Arguments @@ -18,20 +16,6 @@ For more information, see [Availability and computed availability](products.md#a ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\ProductAvailability(true) -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/productcategory_criterion.md b/docs/search/criteria_reference/productcategory_criterion.md index 8ca37ebc9c1..47b93b0fe9b 100644 --- a/docs/search/criteria_reference/productcategory_criterion.md +++ b/docs/search/criteria_reference/productcategory_criterion.md @@ -12,20 +12,6 @@ The `ProductCategory` Search Criterion searches for products by the category the ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\ProductCategory([2, 3]) -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/productcategorysubtree_criterion.md b/docs/search/criteria_reference/productcategorysubtree_criterion.md index 10847905595..1c0831835ec 100644 --- a/docs/search/criteria_reference/productcategorysubtree_criterion.md +++ b/docs/search/criteria_reference/productcategorysubtree_criterion.md @@ -12,11 +12,3 @@ Unlike the [`ProductCategory` criterion](productcategory_criterion.md), which ma ## Arguments - `taxonomyEntryId` - int representing the ID of the root taxonomy entry (product category) of the subtree to search within - -## Example - -### PHP - -``` php -[[= include_code('code_samples/back_office/search/src/Query/ProductCategorySubtreeQuery.php') =]] -``` diff --git a/docs/search/criteria_reference/productcode_criterion.md b/docs/search/criteria_reference/productcode_criterion.md index 39d7e1b1afd..0224486d7b5 100644 --- a/docs/search/criteria_reference/productcode_criterion.md +++ b/docs/search/criteria_reference/productcode_criterion.md @@ -12,20 +12,6 @@ The `ProductCode` Search Criterion searches for products by their codes. ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\ProductCode(['ergo_desk', 'alter_desk']) -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/productname_criterion.md b/docs/search/criteria_reference/productname_criterion.md index 5a3d9a18cf3..6b8a71c4407 100644 --- a/docs/search/criteria_reference/productname_criterion.md +++ b/docs/search/criteria_reference/productname_criterion.md @@ -12,20 +12,6 @@ The `ProductName` Search Criterion searches for products by their names. ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\ProductName('sofa*') -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/productstock_criterion.md b/docs/search/criteria_reference/productstock_criterion.md index 710041b3611..f7e22ca20f6 100644 --- a/docs/search/criteria_reference/productstock_criterion.md +++ b/docs/search/criteria_reference/productstock_criterion.md @@ -10,27 +10,3 @@ The `ProductStock` Search Criterion searches for products by their numerical sto - `value` - the numerical stock to search for - (optional) `operator` - operator string (`=` `<` `<=` `>` `>=`) - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$productQuery = new ProductQuery( - null, - new Criterion\ProductStock(10) -); -``` - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$productQuery = new ProductQuery( - null, - new Criterion\ProductStock(50, '>=') -); -``` diff --git a/docs/search/criteria_reference/productstockrange_criterion.md b/docs/search/criteria_reference/productstockrange_criterion.md index b185a705c80..ebeb97e09ea 100644 --- a/docs/search/criteria_reference/productstockrange_criterion.md +++ b/docs/search/criteria_reference/productstockrange_criterion.md @@ -10,17 +10,3 @@ The `ProductStockRange` Search Criterion searches for products by their numerica - `min` - minimum stock - `max` - maximum stock - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$productQuery = new ProductQuery( - null, - new Criterion\ProductStockRange(10, 120) -); -``` diff --git a/docs/search/criteria_reference/producttype_criterion.md b/docs/search/criteria_reference/producttype_criterion.md index c98fbcdc09e..2548e257a1b 100644 --- a/docs/search/criteria_reference/producttype_criterion.md +++ b/docs/search/criteria_reference/producttype_criterion.md @@ -12,20 +12,6 @@ The `ProductType` Search Criterion searches for products by their codes. ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\ProductType(['dress']) -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/rangemeasurementattributemaximum_criterion.md b/docs/search/criteria_reference/rangemeasurementattributemaximum_criterion.md index 7a5a71edaea..6c9c44278d2 100644 --- a/docs/search/criteria_reference/rangemeasurementattributemaximum_criterion.md +++ b/docs/search/criteria_reference/rangemeasurementattributemaximum_criterion.md @@ -10,23 +10,3 @@ The `RangeMeasurementAttributeMaximum` Search Criterion searches for products by - `identifier` - string representing the attribute - `value` - `\Ibexa\Contracts\Measurement\Value\SimpleValueInterface` object representing the maximum attribute value - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -/** @var \Ibexa\Contracts\Measurement\MeasurementServiceInterface $measurementService */ -$value = $measurementService->buildSimpleValue('length', 150, 'centimeter'); - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\Measurement\Product\Query\Criterion\RangeMeasurementAttributeMaximum( - 'length', - $value - ) -); -``` diff --git a/docs/search/criteria_reference/rangemeasurementattributeminimum_criterion.md b/docs/search/criteria_reference/rangemeasurementattributeminimum_criterion.md index 7f103eee099..eb47bf9b77e 100644 --- a/docs/search/criteria_reference/rangemeasurementattributeminimum_criterion.md +++ b/docs/search/criteria_reference/rangemeasurementattributeminimum_criterion.md @@ -10,23 +10,3 @@ The `RangeMeasurementAttributeMinimum` Search Criterion searches for products by - `identifier` - string representing the attribute - `value` - `\Ibexa\Contracts\Measurement\Value\SimpleValueInterface` object representing the minimum attribute value - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -/** @var \Ibexa\Contracts\Measurement\MeasurementServiceInterface $measurementService */ -$value = $measurementService->buildSimpleValue('length', 100, 'centimeter'); - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\Measurement\Product\Query\Criterion\RangeMeasurementAttributeMinimum( - 'length', - $value - ) -); -``` diff --git a/docs/search/criteria_reference/remoteid_criterion.md b/docs/search/criteria_reference/remoteid_criterion.md index 948ec2c7e88..0d057d6e959 100644 --- a/docs/search/criteria_reference/remoteid_criterion.md +++ b/docs/search/criteria_reference/remoteid_criterion.md @@ -4,7 +4,7 @@ description: RemoteId / ContentRemoteId Search Criterion # RemoteId / ContentRemoteId Criterion -The [`RemoteId` / `ContentRemoteId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-RemoteId.html) +The `RemoteId` / `ContentRemoteId` Search Criterion searches for content based on its remote content ID. ## Arguments @@ -13,18 +13,6 @@ searches for content based on its remote content ID. ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\RemoteId('abab615dcf26699a4291657152da4337'); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/search_criteria_reference.md b/docs/search/criteria_reference/search_criteria_reference.md index 0a6638217c5..d777a515d91 100644 --- a/docs/search/criteria_reference/search_criteria_reference.md +++ b/docs/search/criteria_reference/search_criteria_reference.md @@ -5,7 +5,7 @@ month_change: false # Search Criteria reference -Search Criteria are filters for content and location Search and [Repository filtering](search_api.md#repository-filtering). +Search Criteria are filters for content and location Search. Criteria can take some of the following arguments: @@ -78,8 +78,7 @@ Due to this storage limitation, searching content using the Country field type o ### Logical operators -All Logical operators are supported by Content and Location Search and -[Repository filtering](search_api.md#repository-filtering). +All Logical operators are supported by Content and Location Search. | Search Criterion | Search based on | |---------------------------------------|-------------------------------------------------------------------------------------------------| diff --git a/docs/search/criteria_reference/sectionid_criterion.md b/docs/search/criteria_reference/sectionid_criterion.md index b7879fed3bc..bc27efef424 100644 --- a/docs/search/criteria_reference/sectionid_criterion.md +++ b/docs/search/criteria_reference/sectionid_criterion.md @@ -4,7 +4,7 @@ description: SectionId Search Criterion # SectionId Criterion -The [`SectionId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-SectionId.html) searches for content based on the ID of the Section it's assigned to. +The `SectionId` Search Criterion searches for content based on the ID of the Section it's assigned to. ## Arguments @@ -12,18 +12,6 @@ The [`SectionId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa- ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\SectionId(3); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/sectionidentifier_criterion.md b/docs/search/criteria_reference/sectionidentifier_criterion.md index e043a3ac820..ae26b8d6464 100644 --- a/docs/search/criteria_reference/sectionidentifier_criterion.md +++ b/docs/search/criteria_reference/sectionidentifier_criterion.md @@ -4,7 +4,7 @@ description: SectionIdentifier Search Criterion # SectionIdentifier Criterion -The [`SectionIdentifier` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-SectionIdentifier.html) searches for content based on the identifier of the Section it's assigned to. +The `SectionIdentifier` Search Criterion searches for content based on the identifier of the Section it's assigned to. ## Arguments @@ -12,18 +12,6 @@ The [`SectionIdentifier` Search Criterion](/api/php_api/php_api_reference/classe ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\SectionIdentifier(['sports', 'news']); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/selectionattribute_criterion.md b/docs/search/criteria_reference/selectionattribute_criterion.md index cbaf0be3648..abcdf2d59ab 100644 --- a/docs/search/criteria_reference/selectionattribute_criterion.md +++ b/docs/search/criteria_reference/selectionattribute_criterion.md @@ -13,23 +13,6 @@ The `SelectionAttribute` Search Criterion searches for products by the value of ## Example -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\SelectionAttribute( - 'fabric_type', - ['cotton'] - ) -); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/sibling_criterion.md b/docs/search/criteria_reference/sibling_criterion.md index e1504c979c0..33d65a075d3 100644 --- a/docs/search/criteria_reference/sibling_criterion.md +++ b/docs/search/criteria_reference/sibling_criterion.md @@ -4,7 +4,7 @@ description: Sibling Search Criterion # Sibling Criterion -The [`Sibling` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-Sibling.html) searches for content under the same parent as the indicated location. +The `Sibling` Search Criterion searches for content under the same parent as the indicated location. ## Arguments @@ -13,32 +13,6 @@ The [`Sibling` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Co ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\Sibling(59, 2); -``` - -You can also use the named constructor `Criterion\Sibling::fromLocation` and provide it with the location object: - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -/** @var \Ibexa\Contracts\Core\Repository\LocationService $locationService */ -$location = $locationService->loadLocation(59); -$query->query = Criterion\Sibling::fromLocation($location); -``` - -### REST API - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/simplemeasurementattribute_criterion.md b/docs/search/criteria_reference/simplemeasurementattribute_criterion.md index 7cd56eb2c38..441741aad94 100644 --- a/docs/search/criteria_reference/simplemeasurementattribute_criterion.md +++ b/docs/search/criteria_reference/simplemeasurementattribute_criterion.md @@ -10,23 +10,3 @@ The `SimpleMeasurementAttribute` Search Criterion searches for products by the v - `identifier` - string representing the attribute - `value` - `Ibexa\Contracts\Measurement\Value\SimpleValueInterface` object representing the attribute value - -## Example - -### PHP - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; -use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; - -/** @var \Ibexa\Contracts\Measurement\MeasurementServiceInterface $measurementService */ -$value = $measurementService->buildSimpleValue('length', 120, 'centimeter'); - -$query = new ProductQuery( - null, - new \Ibexa\Contracts\Measurement\Product\Query\Criterion\SimpleMeasurementAttribute( - 'width', - $value - ) -); -``` diff --git a/docs/search/criteria_reference/subtree_criterion.md b/docs/search/criteria_reference/subtree_criterion.md index 53d5fa7bb2a..55d16d976a2 100644 --- a/docs/search/criteria_reference/subtree_criterion.md +++ b/docs/search/criteria_reference/subtree_criterion.md @@ -4,7 +4,7 @@ description: Subtree Search Criterion # Subtree Criterion -The [`Subtree` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-Subtree.html) searches for content based on its location ID subtree path. +The `Subtree` Search Criterion searches for content based on its location ID subtree path. It returns the content item and all the content items below it in the subtree. ## Arguments @@ -13,18 +13,6 @@ It returns the content item and all the content items below it in the subtree. ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\Subtree('/1/2/71/72/'); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/symbolattribute_criterion.md b/docs/search/criteria_reference/symbolattribute_criterion.md index 8b6d47f3c8e..1205fec11d4 100644 --- a/docs/search/criteria_reference/symbolattribute_criterion.md +++ b/docs/search/criteria_reference/symbolattribute_criterion.md @@ -10,11 +10,3 @@ The `SymbolAttribute` Search Criterion searches for products by [symbol attribut - `identifier` - identifier of the format - `value` - array with the values to search for - -## Example - -### PHP - -``` php -[[= include_code('code_samples/back_office/search/src/Query/SymbolAttributeTypeQuery.php') =]] -``` diff --git a/docs/search/criteria_reference/taxonomy_entry_id.md b/docs/search/criteria_reference/taxonomy_entry_id.md index 968931e2a61..d97414c13c4 100644 --- a/docs/search/criteria_reference/taxonomy_entry_id.md +++ b/docs/search/criteria_reference/taxonomy_entry_id.md @@ -4,30 +4,8 @@ description: TaxonomyEntryId Search Criterion # TaxonomyEntryId Criterion -The [`TaxonomyEntryId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Taxonomy-Search-Query-Criterion-TaxonomyEntryId.html) searches for content based on the ID of the Taxonomy Entry it's assigned to. +The `TaxonomyEntryId` Search Criterion searches for content based on the ID of the Taxonomy Entry it's assigned to. ## Arguments - `value` - int(s) representing the IDs of the Tag(s) - -## Example - -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Taxonomy\Search\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\TaxonomyEntryId(1); -``` - -Add an array of ID's to find Content tagged with at least one of the tags (OR). - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Taxonomy\Search\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\TaxonomyEntryId([1, 2, 3]); -``` diff --git a/docs/search/criteria_reference/taxonomy_no_entries.md b/docs/search/criteria_reference/taxonomy_no_entries.md index 3cff3fb5665..78299c7f8db 100644 --- a/docs/search/criteria_reference/taxonomy_no_entries.md +++ b/docs/search/criteria_reference/taxonomy_no_entries.md @@ -4,26 +4,11 @@ description: TaxonomyNoEntries Search Criterion # TaxonomyNoEntries Criterion -The [`TaxonomyNoEntries`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Taxonomy-Search-Query-Criterion-TaxonomyNoEntries.html) Search Criterion searches for content that has no entries assigned from the specified [taxonomy](taxonomy.md). +The `TaxonomyNoEntries` Search Criterion searches for content that has no entries assigned from the specified [taxonomy](taxonomy.md). Use it when you need to find content items to which no taxonomy entries have been assigned (for example, articles without tags). -It's available for all supported search engines and in [repository filtering](search_api.md#repository-filtering). +It's available for all supported search engines. ## Arguments - `taxonomy` - `string` representing the identifier of the taxonomy (for example, `tags` or `categories`) - -## Example - -### PHP - -The following example searches for articles that have no entries assigned in the `tags` taxonomy: - -``` php hl_lines="11-16" -[[= include_code('code_samples/search/content/taxonomy_no_entries_criterion.php') =]] -``` - -The criteria limit the results to content that matches all of the conditions listed below: - -- content has no entries assigned in the `tags` taxonomy -- content type is `article` diff --git a/docs/search/criteria_reference/taxonomy_subtree.md b/docs/search/criteria_reference/taxonomy_subtree.md index 2203a7b08b9..a0b6e081fb2 100644 --- a/docs/search/criteria_reference/taxonomy_subtree.md +++ b/docs/search/criteria_reference/taxonomy_subtree.md @@ -4,23 +4,8 @@ description: TaxonomySubtree Search Criterion # TaxonomySubtree Criterion -The [`TaxonomySubtree`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Taxonomy-Search-Query-Criterion-TaxonomySubtree.html) Search Criterion searches for content assigned to the specified [taxonomy](taxonomy.md) entry or any of its descendants. +The `TaxonomySubtree` Search Criterion searches for content assigned to the specified [taxonomy](taxonomy.md) entry or any of its descendants. ## Arguments - `taxonomyEntryId` - `int` representing the ID of the taxonomy entry that is the root of the subtree - -## Example - -### PHP - -The following example searches for articles assigned to taxonomy entry with ID `42` or any of its child entries: - -``` php hl_lines="11-16" -[[= include_code('code_samples/search/content/taxonomy_subtree_criterion.php') =]] -``` - -The criteria limit the results to content that match all of the conditions listed below: - -- content is assigned to taxonomy entry `42` or any of its descendants -- content type is `article` diff --git a/docs/search/criteria_reference/updated_at_criterion.md b/docs/search/criteria_reference/updated_at_criterion.md index 7f48d0f6d93..a40cb2b17e0 100644 --- a/docs/search/criteria_reference/updated_at_criterion.md +++ b/docs/search/criteria_reference/updated_at_criterion.md @@ -16,22 +16,14 @@ The `UpdatedAt` Search Criterion searches for products based on the date when th | Operator | Value | Description | |----------|-------|-------------| -| [`Operator::EQ`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-Operator.html#constant_EQ) | `=` | Matches products updated exactly on the given date (default) | -| [`Operator::GT`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-Operator.html#constant_GT) | `>` | Matches products updated after the given date | -| [`Operator::GTE`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-Operator.html#constant_GTE) | `>=` | Matches products updated on or after the given date | -| [`Operator::LT`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-Operator.html#constant_LT) | `<` | Matches products updated before the given date | -| [`Operator::LTE`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-Operator.html#constant_LTE) | `<=` | Matches products updated on or before the given date | +| `Operator::EQ` | `=` | Matches products updated exactly on the given date (default) | +| `Operator::GT` | `>` | Matches products updated after the given date | +| `Operator::GTE` | `>=` | Matches products updated on or after the given date | +| `Operator::LT` | `<` | Matches products updated before the given date | +| `Operator::LTE` | `<=` | Matches products updated on or before the given date | ## Example -### PHP - -``` php -[[= include_code('code_samples/back_office/search/src/Query/UpdatedAtQuery.php') =]] -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/updated_at_range_criterion.md b/docs/search/criteria_reference/updated_at_range_criterion.md index 49e5dd26fae..123e90aa421 100644 --- a/docs/search/criteria_reference/updated_at_range_criterion.md +++ b/docs/search/criteria_reference/updated_at_range_criterion.md @@ -16,14 +16,6 @@ At least one of `min` or `max` must be provided. ## Example -### PHP - -``` php -[[= include_code('code_samples/back_office/search/src/Query/UpdatedAtRangeQuery.php') =]] -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/useremail_criterion.md b/docs/search/criteria_reference/useremail_criterion.md index 9402e1c9991..555d2ce75e7 100644 --- a/docs/search/criteria_reference/useremail_criterion.md +++ b/docs/search/criteria_reference/useremail_criterion.md @@ -4,7 +4,7 @@ description: UserEmail Search Criterion # UserEmail Criterion -The [`UserEmail` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-UserEmail.html) searches for content based on the email assigned to the user account. +The `UserEmail` Search Criterion searches for content based on the email assigned to the user account. ## Arguments @@ -17,26 +17,6 @@ Solr search engine and Elasticsearch support IN and EQ operators only. ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\UserEmail(['johndoe']); -``` - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\UserEmail('nospam*', Criterion\Operator::LIKE); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/userid_criterion.md b/docs/search/criteria_reference/userid_criterion.md index cfdf847d0ff..729718bb4b1 100644 --- a/docs/search/criteria_reference/userid_criterion.md +++ b/docs/search/criteria_reference/userid_criterion.md @@ -4,7 +4,7 @@ description: UserId Search Criterion # UserId Criterion -The [`UserId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-UserId.html) searches for content based on the User ID. +The `UserId` Search Criterion searches for content based on the User ID. ## Arguments @@ -12,18 +12,6 @@ The [`UserId` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Con ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\UserId([14]); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/userlogin_criterion.md b/docs/search/criteria_reference/userlogin_criterion.md index 74647dfbf19..c9e1370bacf 100644 --- a/docs/search/criteria_reference/userlogin_criterion.md +++ b/docs/search/criteria_reference/userlogin_criterion.md @@ -4,7 +4,7 @@ description: UserLogin Search Criterion # UserLogin Criterion -The [`UserLogin` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-UserLogin.html) searches for content based on the User ID. +The `UserLogin` Search Criterion searches for content based on the User ID. ## Arguments @@ -17,26 +17,6 @@ Solr search engine and Elasticsearch support IN and EQ operators only. ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\UserLogin(['johndoe']); -``` - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\UserLogin('adm*', Criterion\Operator::LIKE); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/criteria_reference/usermetadata_criterion.md b/docs/search/criteria_reference/usermetadata_criterion.md index ef6939f9b82..a59326fc952 100644 --- a/docs/search/criteria_reference/usermetadata_criterion.md +++ b/docs/search/criteria_reference/usermetadata_criterion.md @@ -4,7 +4,7 @@ description: UserMetadata Search Criterion # UserMetadata Criterion -The [`UserMetadata` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-UserMetadata.html) searches for content based on its creator or modifier. +The `UserMetadata` Search Criterion searches for content based on its creator or modifier. ## Arguments @@ -14,18 +14,6 @@ The [`UserMetadata` Search Criterion](/api/php_api/php_api_reference/classes/Ibe ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\UserMetadata(Criterion\UserMetadata::GROUP, Criterion\Operator::EQ, 12); -``` - -### REST API - === "XML" ```xml @@ -58,20 +46,4 @@ $query->query = new Criterion\UserMetadata(Criterion\UserMetadata::GROUP, Criter ## Use case -You can use the `UserMetadata` Criterion to search for blog posts created by the Contributor user group: - -``` php hl_lines="11" -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -// ID of your custom Contributor User Group -$contributorGroupId = 32; - -$query = new LocationQuery(); -$query->query = new Criterion\LogicalAnd( - [ - new Criterion\ContentTypeIdentifier('blog_post'), - new Criterion\UserMetadata(Criterion\UserMetadata::GROUP, Criterion\Operator::EQ, $contributorGroupId), - ] -); -``` +You can use the `UserMetadata` Criterion to search for blog posts created by a specific user group, such as Contributor, by using the `GROUP` target with the `EQ` operator. diff --git a/docs/search/criteria_reference/visibility_criterion.md b/docs/search/criteria_reference/visibility_criterion.md index 86a4829471b..c5572d99acc 100644 --- a/docs/search/criteria_reference/visibility_criterion.md +++ b/docs/search/criteria_reference/visibility_criterion.md @@ -4,7 +4,7 @@ description: Visibility Search Criterion # Visibility Criterion -The [`Visibility` Search Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Criterion-Visibility.html) searches for content based on whether it's visible or not. +The `Visibility` Search Criterion searches for content based on whether it's visible or not. This Criterion takes into account both hiding content and hiding locations. @@ -18,18 +18,6 @@ Use Location Search to avoid this. ## Example -### PHP - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion; - -$query = new Query(); -$query->query = new Criterion\Visibility(Criterion\Visibility::HIDDEN); -``` - -### REST API - === "XML" ```xml diff --git a/docs/search/embeddings_reference/embeddings_reference.md b/docs/search/embeddings_reference/embeddings_reference.md deleted file mode 100644 index eb02f66c929..00000000000 --- a/docs/search/embeddings_reference/embeddings_reference.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -month_change: false -description: Embedding queries, embedding configuration, providers, and embedding search fields ---- - -# Embeddings search reference - -Embeddings provide vector representations of content or text, enabling [semantic similarity search](search_api.md#search-with-embeddings). -Foundational abstractions are provided for embedding-based search, while embedding providers generate vector representations. - -Searching with embeddings is designed for use with the [Taxonomy suggestions](taxonomy.md#taxonomy-suggestions) feature. -The [`Ibexa\Contracts\Taxonomy\Search\Query\Value\TaxonomyEmbedding`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Taxonomy-Search-Query-Value-TaxonomyEmbedding.html) class allows embedding queries to target taxonomy data. - -!!! note "Feature support" - - Searching with embeddings requires a search engine that supports it, such as Elasticsearch or Solr 9.8.1+. - -## Core query objects - -### EmbeddingQuery - -- [`Ibexa\Contracts\Core\Repository\Values\Content\EmbeddingQuery`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-EmbeddingQuery.html) represents a semantic similarity search request. - It encapsulates an [Embedding](#embedding) instance and supports pagination, aggregations, and result counting through the same API as standard content queries. - - !!! note "Embedding query properties" - - Embedding queries do not use criteria for similarity, but for additional filtering applied through the query filter. - Also, embedding queries do not allow standard Query properties supported by [search engines](search_engines.md) other than the Legacy Search, such as `query`, `sortClauses`, or `spellcheck`. - -- [EmbeddingQueryBuilder](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-EmbeddingQueryBuilder.html) is a builder for constructing `EmbeddingQuery` instances. - It helps construct queries consistently and integrates embedding queries with the search query pipeline. - You must provide the required embedding value by using the `withEmbedding` method - -### Embedding - -- [`Ibexa\Contracts\Core\Repository\Values\Content\Query\Embedding`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-Embedding.html) represents the vector input used -for similarity search. - It stores embedding values as float arrays, while providers generate those vectors from text input - -## Query execution - -Embedding queries are executed by the search engine by using the configured embedding model and provider. - -At runtime, the system resolves the appropriate embedding provider and ensures that the embedding vector is compatible with the configured model. -Runtime validation includes validating vector dimensionality and selecting the correct indexed field for similarity search. -Field selection is determined by the configured embedding model and backend specific query mapping, while vector dimensionality is validated when the query reaches the search engine. - -## Embedding providers - -Embedding providers implement the contract for generating vector representations of input data. -Out of the box, embedding search integration is provided for `TaxonomyEmbedding`. -If you use a custom embedding value type, implement matching embedding visitors for your [search engine](search_engines.md). -Otherwise, query execution may fail due to no visitor available. - -- [`Ibexa\Contracts\Core\Search\Embedding\EmbeddingProviderInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Search-Embedding-EmbeddingProviderInterface.html) generates embeddings for the provided text or other input - -- [`Ibexa\Contracts\Core\Search\Embedding\EmbeddingProviderRegistryInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Search-Embedding-EmbeddingProviderRegistryInterface.html) lists available embedding providers or gets one by its identifier - -- [`Ibexa\Contracts\Core\Search\Embedding\EmbeddingProviderResolverInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Search-Embedding-EmbeddingProviderResolverInterface.html) determines the embedding provider to be used for generating embeddings based on the system configuration, or a demand passed through the `resolveByModelIdentifier` method - -## Configuration - -Models used to resolve embedding queries must be configured per SiteAccess in [system configuration](configuration.md). -Each entry defines the model's name, vector dimensionality, the field suffix, and the embedding provider that generates vectors. -Field suffixes assigned to the models must be unique, as they become part of the indexed field name. -You select the default model by setting a value in the `default_embedding_model` key. - -``` yaml -ibexa: - system: - default: - embedding_models: - text-embedding-3-small: - name: 'text-embedding-3-small' - dimensions: 1536 - field_suffix: '3small' - embedding_provider: 'ibexa_openai' - default_embedding_model: text-embedding-ada-002 -``` - -For a real-life example of embedding models configuration, see [Taxonomy suggestions](taxonomy.md#change-embedding-generation-models-or-embedding-provider). - -- [EmbeddingConfigurationInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Search-Embedding-EmbeddingConfigurationInterface.html) allows access to the embedding model configuration in the system (for example, list of available models, default model name, default provider, field suffix, and so on) - -## Embedding fields - -Embedding vectors are stored in dedicated search fields. -These fields can be used by the search engine to perform vector similarity comparisons when embedding queries are executed. - -``` php -[[= include_code('code_samples/api/public_php_api/src/embedding_fields.php') =]] -``` - -Once you create a field, subscribe to the `ContentIndexCreateEvent` indexing event that [adds the field to the index](index_custom_elasticsearch_data.md). - -- [`Ibexa\Contracts\Core\Search\FieldType\EmbeddingFieldFactory`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Search-FieldType-EmbeddingFieldFactory.html) creates dedicated search fields that store embedding vectors - -## Validation - -- [`Ibexa\Contracts\Core\Repository\Values\Content\QueryValidatorInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-QueryValidatorInterface.html) validates embedding query structure before execution diff --git a/docs/search/search.md b/docs/search/search.md index 1b4d7bf5f9b..ea2bae8d83b 100644 --- a/docs/search/search.md +++ b/docs/search/search.md @@ -1,20 +1,12 @@ --- -description: Cohesivo search functionalities allow working with three search engines and using search API to run complex and precise queries about content and products. +description: Cohesivo search functionalities allow running complex and precise queries about content and products. page_type: landing_page --- # Search -[[= product_name =]] exposes a very powerful [Search API](search_api.md), allowing both full-text search and querying the content repository by using several built-in Search Criteria and Sort Clauses. -These are supported across different search engines, allowing you to plug in another search engine without changing your code. +[[= product_name =]] exposes a very powerful Search API, allowing both full-text search and querying the content repository by using several built-in Search Criteria and Sort Clauses. [[= cards([ - "search/search_engines/search_engines", - "search/search_engines/elasticsearch/elasticsearch_overview", - "search/search_engines/solr_search_engine/solr_overview", - "search/search_api", "search/search_criteria_and_sort_clauses", - "search/extensibility/create_custom_search_criterion", - "search/extensibility/create_custom_sort_clause", - "search/extensibility/create_custom_aggregation", ], columns=4) =]] diff --git a/docs/search/search_criteria_and_sort_clauses.md b/docs/search/search_criteria_and_sort_clauses.md index 8de6ee81f10..e0d5352dfdb 100644 --- a/docs/search/search_criteria_and_sort_clauses.md +++ b/docs/search/search_criteria_and_sort_clauses.md @@ -4,114 +4,31 @@ description: Search Criteria and Sort Clauses help you fine-tune searches done b # Search Criteria and Sort Clauses -Search Criteria and Sort Clauses are value object classes used for building a search query, to define filter criteria and ordering of the result set. -[[= product_name =]] provides a number of standard Search Criteria and Sort Clauses that you can use out of the box and that should cover the majority of use cases. +Search Criteria and Sort Clauses are the building blocks of a search query: Criteria +select which content is returned, and Sort Clauses order the results. +[[= product_name =]] provides a number of standard Search Criteria and Sort Clauses +that cover the majority of use cases. -For an example of how to use and combine Criteria and Sort Clauses, refer to [Searching in PHP API](search_api.md). +For the full list, see the [Search Criteria reference](criteria_reference/search_criteria_reference.md) +and the [Sort Clause reference](sort_clause_reference/sort_clause_reference.md). -## Search engine handling of Search Criteria and Sort Clauses +## Content and Location search -As Search Criteria and Sort Clauses are value objects which are used to define the query from API perspective, they're common for all storage engines. -Each storage engine needs to implement its own handlers for the corresponding Criterion and Sort Clause value object, which are used to translate the value object into a storage-specific search query. +There are two basic types of search: you can search for content items, or for locations. -As an example take a look at the [`ContentId` Criterion handler](https://github.com/ibexa/core/blob/6.0/src/lib/Search/Legacy/Content/Common/Gateway/CriterionHandler/ContentId.php) in Legacy search engine or [`ContentId` Criterion handler](https://github.com/ibexa/solr/blob/6.0/src/lib/Query/Common/CriterionVisitor/ContentIdIn.php) in Solr search engine. +All Criteria and Sort Clauses are accepted by Location search, but not all of them can +be used with Content search. +The reason is that while one location always has exactly one content item, one content +item can have several locations. +In that context some Criteria and Sort Clauses would produce ambiguous queries, so +Content search refuses the Criteria and Sort Clauses that apply specifically to +locations. -## Custom Criteria and Sort Clauses - -Sometimes you may find that standard Search Criteria and Sort Clauses provided with [[= product_name =]] aren't sufficient for your needs. -Most often this is the case if you have a custom field type using external storage which cannot be searched using the standard field Criterion. - -!!! note - - Legacy (SQL-based) search can also be used in `ibexa_keyword` external storage. - -In such cases you can implement a custom Criterion or Sort Clause, together with the corresponding handlers for the storage engine you're using. - -!!! caution "Using Field Criterion or Sort Clause with large databases" - - Field Criterion and Sort Clause don't perform well by design when using SQL database. - If you have a large database and want to use them, you either need to use the Solr search engine, or develop your own Custom Criterion or Sort Clause. This way you can avoid using the attributes (fields) database table, and instead use a custom simplified table which can handle the amount of data you have. - -### Difference between Content and Location Search - -There are two basic types of searches, you can either search for locations or for content. -Each type has dedicated methods in the Search Service: - -| Type of search | Method in Search Service | -|----------------|--------------------------| -| Content | `findContent()` | -| Content | `findContentInfo()` | -| Content | `findSingle()` | -| Location | `findLocations()` | - -All Criteria and Sort Clauses are accepted with Location Search, but not all of them can be used with Content Search. -The reason for this is that while one location always has exactly one content item, one content item can have multiple locations. -In this context some Criteria and Sort Clauses would produce ambiguous queries that would not be accepted by Content Search. - -Content Search explicitly refuses to accept Criteria and Sort Clauses implementing these abstract classes: - -- `Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Location` -- `Ibexa\Contracts\Core\Repository\Values\Content\SortClause\Criterion\Location` - -### Configuring custom Criterion and Sort Clause handlers - -After you have implemented your Criterion / Sort Clause and its handler, you need to configure the handler for the [service container](php_api.md#service-container) by using dedicated service tags for each type of search. -Doing so automatically registers it and handle your Criterion / Search Clause when it's given as a parameter to one of the Search Service methods. - -Available tags for Criterion handlers in Legacy Storage Engine are: - -- `ibexa.search.legacy.gateway.criterion_handler.content` -- `ibexa.search.legacy.gateway.criterion_handler.location` - -Available tags for Sort Clause handlers in Legacy Storage Engine are: - -- `ibexa.search.legacy.gateway.sort_clause_handler.content` -- `ibexa.search.legacy.gateway.sort_clause_handler.location` - -!!! note - - You can find all the native handlers and the tags for the Legacy Storage Engine in files located in `core/src/lib/Resources/settings/storage_engines/`. - -!!! tip - - When you search in trash, use the following service tags: - - - for Criterion handlers: `ibexa.core.trash.search.legacy.gateway.criterion_handler` - - for Sort Clause handlers: `ibexa.core.trash.search.legacy.gateway.sort_clause_handler` - - For more information about searching for content items in Trash, see [Search in trash](search_api.md#search-in-trash). - - For more information about the Criteria and Sort Clauses that are supported when searching for trashed content items, see [Searching in trash reference](search_in_trash_reference.md). - -The following example shows how to register a ContentId Criterion handler, common for both Content and Location Search: - -``` yaml -services: - Ibexa\Core\Search\Legacy\Content\Common\Gateway\CriterionHandler\ContentId: - arguments: ['@ibexa.api.storage_engine.legacy.dbhandler'] - tags: - - {name: ibexa.search.legacy.gateway.criterion_handler.content} - - {name: ibexa.search.legacy.gateway.criterion_handler.location} -``` - -The following example shows how to register a Depth Sort Clause handler for Location Search: - -``` yaml -Ibexa\Core\Search\Legacy\Content\Location\Gateway\SortClauseHandler\Location\Depth: - arguments: ['@ibexa.api.storage_engine.legacy.dbhandler'] - tags: - - {name: ibexa.search.legacy.gateway.sort_clause_handler.location} -``` - -For more information about passing parameters, see [Symfony Service Container documentation]([[= symfony_doc =]]/service_container.html#service-container-parameters). - -## Search using custom Field Criterion [REST] +## Search using a custom Field Criterion REST search can be performed by calling the `POST /views` method with a custom `FieldCriterion`. This allows you to build custom content logic queries with nested logical operators OR/AND/NOT. -Custom Field Criterion search mirrors the one already existing in PHP API `Ibexa\Contracts\Core\Repository\Values\Content\Query\Criterion\Field` by exposing it to REST. - ### Example of custom Content Query ```json diff --git a/docs/search/search_in_trash_reference.md b/docs/search/search_in_trash_reference.md index 59f7b80aca6..863c5f1d2f9 100644 --- a/docs/search/search_in_trash_reference.md +++ b/docs/search/search_in_trash_reference.md @@ -6,8 +6,7 @@ month_change: false # Search in trash reference -When you [search for content items that are held in trash](search_api.md#search-in-trash), you can apply only a limited subset of Search Criteria and Sort Clauses -which can be used by [`Ibexa\Contracts\Core\Repository\TrashService::findTrashItems`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-TrashService.html#method_findTrashItems). +When you search for content items that are held in trash, you can apply only a limited subset of Search Criteria and Sort Clauses. Some sort clauses are exclusive to trash search. ## Search Criteria diff --git a/docs/search/sort_clause_reference/baseprice_sort_clause.md b/docs/search/sort_clause_reference/baseprice_sort_clause.md index b19edc4e071..0cd32456082 100644 --- a/docs/search/sort_clause_reference/baseprice_sort_clause.md +++ b/docs/search/sort_clause_reference/baseprice_sort_clause.md @@ -14,19 +14,3 @@ The `BasePrice` Sort Clause sorts search results by the product's base price. ## Limitations The `BasePrice` Sort Clause isn't available in the Legacy Search engine. - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\CurrencyInterface; -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; - -/** @var CurrencyInterface $currency */ -$sortClauses = [ - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\SortClause\BasePrice( - $currency, - ProductQuery::SORT_ASC - ), -]; -$productQuery = new ProductQuery(null, null, $sortClauses); -``` diff --git a/docs/search/sort_clause_reference/contentid_sort_clause.md b/docs/search/sort_clause_reference/contentid_sort_clause.md index e41e3f3bfde..c7fb7febdc5 100644 --- a/docs/search/sort_clause_reference/contentid_sort_clause.md +++ b/docs/search/sort_clause_reference/contentid_sort_clause.md @@ -4,18 +4,8 @@ description: ContentId Sort Clause # ContentId Sort Clause -The [`ContentId` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-ContentId.html) sorts search results by the content items' IDs. +The `ContentId` Sort Clause sorts search results by the content items' IDs. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\ContentId()]; -``` diff --git a/docs/search/sort_clause_reference/contentname_sort_clause.md b/docs/search/sort_clause_reference/contentname_sort_clause.md index 51fd8ceee35..59353da582d 100644 --- a/docs/search/sort_clause_reference/contentname_sort_clause.md +++ b/docs/search/sort_clause_reference/contentname_sort_clause.md @@ -4,18 +4,8 @@ description: ContentName Sort Clause # ContentName Sort Clause -The [`ContentName` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-ContentName.html) sorts search results by the content items' names. +The `ContentName` Sort Clause sorts search results by the content items' names. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\ContentName()]; -``` diff --git a/docs/search/sort_clause_reference/contenttranslatedname_sort_clause.md b/docs/search/sort_clause_reference/contenttranslatedname_sort_clause.md index 317de177050..0e17974bfba 100644 --- a/docs/search/sort_clause_reference/contenttranslatedname_sort_clause.md +++ b/docs/search/sort_clause_reference/contenttranslatedname_sort_clause.md @@ -4,22 +4,8 @@ description: ContentTranslatedName Sort Clause # ContentTranslatedName Sort Clause -The [`ContentTranslatedName` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-ContentTranslatedName.html) sorts search results by the content items' translated names. +The `ContentTranslatedName` Sort Clause sorts search results by the content items' translated names. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Limitations - -The `ContentTranslatedName` Sort Clause isn't available in [Repository filtering](search_api.md#repository-filtering). - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\ContentTranslatedName()]; -``` diff --git a/docs/search/sort_clause_reference/contenttypename_sort_clause.md b/docs/search/sort_clause_reference/contenttypename_sort_clause.md index 80d031a0183..00d67e36d8f 100644 --- a/docs/search/sort_clause_reference/contenttypename_sort_clause.md +++ b/docs/search/sort_clause_reference/contenttypename_sort_clause.md @@ -4,18 +4,8 @@ description: ContentTypeName Sort Clause # ContentTypeName Sort Clause -The [`ContentTypeName` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Trash-ContentTypeName.html) sorts the results of searching in Trash by the name of the content item's content type. +The `ContentTypeName` Sort Clause sorts the results of searching in Trash by the name of the content item's content type. ## Arguments - (optional) `sortDirection` - Query constant, either `Query::SORT_ASC` or `Query::SORT_DESC` - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new Query(); -$query->sortClauses = [new SortClause\Trash\ContentTypeName()]; -``` diff --git a/docs/search/sort_clause_reference/createdat_sort_clause.md b/docs/search/sort_clause_reference/createdat_sort_clause.md index f68a4944fa7..6265a6ed607 100644 --- a/docs/search/sort_clause_reference/createdat_sort_clause.md +++ b/docs/search/sort_clause_reference/createdat_sort_clause.md @@ -9,19 +9,3 @@ The `CreatedAt` Sort Clause sorts search results by the date and time of the cre ## Arguments - (optional) `sortDirection` - `CreatedAt` constant, either `CreatedAt::SORT_ASC` or `CreatedAt::SORT_DESC` - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; - -$productQuery = new ProductQuery( - null, - null, - [ - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\SortClause\CreatedAt( - \Ibexa\Contracts\ProductCatalog\Values\Product\Query\SortClause\CreatedAt::SORT_ASC - ), - ] -); -``` diff --git a/docs/search/sort_clause_reference/customfield_sort_clause.md b/docs/search/sort_clause_reference/customfield_sort_clause.md index 64e8602e17a..92a8301c90e 100644 --- a/docs/search/sort_clause_reference/customfield_sort_clause.md +++ b/docs/search/sort_clause_reference/customfield_sort_clause.md @@ -4,7 +4,7 @@ description: CustomField Sort Clause # CustomField Sort Clause -The [`CustomField` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-CustomField.html) sorts search results by raw search index fields. +The `CustomField` Sort Clause sorts search results by raw search index fields. ## Arguments @@ -17,15 +17,3 @@ The [`CustomField` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Con To keep your project search engine independent, don't use the `CustomField` Sort Clause in production code. Valid use cases are: testing, or temporary (one-off) tools. - -The `CustomField` Sort Clause isn't available in [Repository filtering](search_api.md#repository-filtering). - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\CustomField('my_custom_field_s')]; -``` diff --git a/docs/search/sort_clause_reference/customprice_sort_clause.md b/docs/search/sort_clause_reference/customprice_sort_clause.md index 3d8fdc15f02..877585063d6 100644 --- a/docs/search/sort_clause_reference/customprice_sort_clause.md +++ b/docs/search/sort_clause_reference/customprice_sort_clause.md @@ -16,24 +16,3 @@ If you don't provide a customer group, the query uses the group related to the c ## Limitations The `CustomPrice` Sort Clause isn't available in the Legacy Search engine. - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\CurrencyInterface; -use Ibexa\Contracts\ProductCatalog\Values\CustomerGroupInterface; -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; - -/** - * @var CurrencyInterface $currency - * @var CustomerGroupInterface $customerGroup - */ -$sortClauses = [ - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\SortClause\CustomPrice( - $currency, - ProductQuery::SORT_ASC, - $customerGroup - ), -]; -$productQuery = new ProductQuery(null, null, $sortClauses); -``` diff --git a/docs/search/sort_clause_reference/datemodified_sort_clause.md b/docs/search/sort_clause_reference/datemodified_sort_clause.md index a626be31a29..895060e685b 100644 --- a/docs/search/sort_clause_reference/datemodified_sort_clause.md +++ b/docs/search/sort_clause_reference/datemodified_sort_clause.md @@ -4,18 +4,8 @@ description: DateModified Sort Clause # DateModified Sort Clause -The [`DateModified` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-DateModified.html) sorts search results by the date and time of the last modification of a content item. +The `DateModified` Sort Clause sorts search results by the date and time of the last modification of a content item. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\DateModified()]; -``` diff --git a/docs/search/sort_clause_reference/datepublished_sort_clause.md b/docs/search/sort_clause_reference/datepublished_sort_clause.md index 92a25e1f6ed..f6c0edfdf86 100644 --- a/docs/search/sort_clause_reference/datepublished_sort_clause.md +++ b/docs/search/sort_clause_reference/datepublished_sort_clause.md @@ -4,18 +4,8 @@ description: DatePublished Sort Clause # DatePublished Sort Clause -The [`DatePublished` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-DatePublished.html) sorts search results by the date and time of the first publication of a content item. +The `DatePublished` Sort Clause sorts search results by the date and time of the first publication of a content item. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\DatePublished()]; -``` diff --git a/docs/search/sort_clause_reference/datetrashed_sort_clause.md b/docs/search/sort_clause_reference/datetrashed_sort_clause.md index 4bfa6d9e416..99437b28b91 100644 --- a/docs/search/sort_clause_reference/datetrashed_sort_clause.md +++ b/docs/search/sort_clause_reference/datetrashed_sort_clause.md @@ -4,18 +4,8 @@ description: DateTrashed Sort Clause # DateTrashed Sort Clause -The [`DateTrashed` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Trash-DateTrashed.html) sorts the results of searching in Trash by the date and time when the content item was sent to trash. +The `DateTrashed` Sort Clause sorts the results of searching in Trash by the date and time when the content item was sent to trash. ## Arguments - (optional) `sortDirection` - Query constant, either `Query::SORT_ASC` or `Query::SORT_DESC` - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new Query(); -$query->sortClauses = [new SortClause\Trash\DateTrashed()]; -``` diff --git a/docs/search/sort_clause_reference/depth_sort_clause.md b/docs/search/sort_clause_reference/depth_sort_clause.md index fabdb17a8ec..829f03fd1e1 100644 --- a/docs/search/sort_clause_reference/depth_sort_clause.md +++ b/docs/search/sort_clause_reference/depth_sort_clause.md @@ -4,18 +4,8 @@ description: Depth Sort Clause # Depth Sort Clause -The [`Location\Depth` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Location-Depth.html) sorts search results by the depth of the location in the content tree. +The `Location\Depth` Sort Clause sorts search results by the depth of the location in the content tree. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\Location\Depth()]; -``` diff --git a/docs/search/sort_clause_reference/field_sort_clause.md b/docs/search/sort_clause_reference/field_sort_clause.md index b32776ee185..fd0a8de4101 100644 --- a/docs/search/sort_clause_reference/field_sort_clause.md +++ b/docs/search/sort_clause_reference/field_sort_clause.md @@ -4,7 +4,7 @@ description: Field Sort Clause # Field Sort Clause -The [`Field` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Field.html) sorts search results by the value of one of the content items' fields. +The `Field` Sort Clause sorts search results by the value of one of the content items' fields. Search results of the provided content type are sorted in field value order. Results of the query that don't belong to the content type are ranked lower. @@ -13,17 +13,3 @@ Results of the query that don't belong to the content type are ranked lower. - `typeIdentifier` - string representing the identifier of the content type to which the field belongs - `fieldIdentifier` - string representing the identifier of the field to sort by [[= include_file('docs/snippets/sort_direction.md') =]] - -## Limitations - -The `Field` Sort Clause isn't available in [Repository filtering](search_api.md#repository-filtering). - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\Field('article', 'title')]; -``` diff --git a/docs/search/sort_clause_reference/id_sort_clause.md b/docs/search/sort_clause_reference/id_sort_clause.md index 2132a64d37c..11d064c4f4e 100644 --- a/docs/search/sort_clause_reference/id_sort_clause.md +++ b/docs/search/sort_clause_reference/id_sort_clause.md @@ -4,18 +4,8 @@ description: Id Sort Clause # Id Sort Clause -The [`Location\Id` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Location-Id.html) sorts search results by the ID of the location. +The `Location\Id` Sort Clause sorts search results by the ID of the location. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\Location\Id()]; -``` diff --git a/docs/search/sort_clause_reference/ismainlocation_sort_clause.md b/docs/search/sort_clause_reference/ismainlocation_sort_clause.md index b1c763e6b8a..5300e808a03 100644 --- a/docs/search/sort_clause_reference/ismainlocation_sort_clause.md +++ b/docs/search/sort_clause_reference/ismainlocation_sort_clause.md @@ -4,24 +4,10 @@ description: IsMainLocation Sort Clause # IsMainLocation Sort Clause -The [`Location\IsMainLocation` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Location-IsMainLocation.html) sorts search results by whether their location is the main location of the content item. +The `Location\IsMainLocation` Sort Clause sorts search results by whether their location is the main location of the content item. Locations that aren't main locations are ranked as lower values (for example, with ascending order they're returned first). ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Limitations - -The `Location\IsMainLocation` Sort Clause isn't available in [Repository filtering](search_api.md#repository-filtering). - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\Location\IsMainLocation()]; -``` diff --git a/docs/search/sort_clause_reference/maplocationdistance_sort_clause.md b/docs/search/sort_clause_reference/maplocationdistance_sort_clause.md index 6ed59fd5712..32454bec83d 100644 --- a/docs/search/sort_clause_reference/maplocationdistance_sort_clause.md +++ b/docs/search/sort_clause_reference/maplocationdistance_sort_clause.md @@ -4,7 +4,7 @@ description: MapLocationDistance Sort Clause # MapLocationDistance Sort Clause -The [`MapLocationDistance` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-MapLocationDistance.html) sorts search results by the distance of the indicated MapLocation field to the provided location. +The `MapLocationDistance` Sort Clause sorts search results by the distance of the indicated MapLocation field to the provided location. ## Arguments @@ -12,17 +12,3 @@ The [`MapLocationDistance` Sort Clause](/api/php_api/php_api_reference/classes/I - `fieldIdentifier` - string representing the identifier of the MapLocation field to sort by - `latitude` - float representing the latitude of the location to calculate distance to - `longitude`- float representing the longitude of the location to calculate distance to [[= include_file('docs/snippets/sort_direction.md') =]] - -## Limitations - -The `MapLocationDistance` Sort Clause isn't available in [Repository filtering](search_api.md#repository-filtering). - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\MapLocationDistance('place', 'location', 49.542889, 20.111349)]; -``` diff --git a/docs/search/sort_clause_reference/path_sort_clause.md b/docs/search/sort_clause_reference/path_sort_clause.md index ba5812567b1..6e1a813c1c7 100644 --- a/docs/search/sort_clause_reference/path_sort_clause.md +++ b/docs/search/sort_clause_reference/path_sort_clause.md @@ -4,7 +4,7 @@ description: Path Sort Clause # Path Sort Clause -The [`Location\Path` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Location-Path.html) sorts search results by the pathString of the location. +The `Location\Path` Sort Clause sorts search results by the pathString of the location. !!! note @@ -13,13 +13,3 @@ The [`Location\Path` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-C ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\Location\Path()]; -``` diff --git a/docs/search/sort_clause_reference/priority_sort_clause.md b/docs/search/sort_clause_reference/priority_sort_clause.md index d1eec92ae09..05ffcc3d445 100644 --- a/docs/search/sort_clause_reference/priority_sort_clause.md +++ b/docs/search/sort_clause_reference/priority_sort_clause.md @@ -4,18 +4,8 @@ description: Priority Sort Clause # Priority Sort Clause -The [`Location\Priority` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Location-Priority.html) sorts search results by the priority of the location. +The `Location\Priority` Sort Clause sorts search results by the priority of the location. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\Location\Priority()]; -``` diff --git a/docs/search/sort_clause_reference/product_sort_clauses.md b/docs/search/sort_clause_reference/product_sort_clauses.md index e4d146f0bc8..27806cf51e3 100644 --- a/docs/search/sort_clause_reference/product_sort_clauses.md +++ b/docs/search/sort_clause_reference/product_sort_clauses.md @@ -5,11 +5,11 @@ page_type: reference # Product Sort Clauses -Product Sort Clauses are only supported by [Product Search (`ProductServiceInterface::findProduct`)](product_api.md#products). +Product Sort Clauses are only supported by product search. By using Sort Clause you can filter product by specific attributes, for example: price, code, or availability. -To sort products coming from [[= pim_product_name =]], see [[[= pim_product_name =]] Search API](../../product_catalog/quable/quable_api.md#search-for-products) for details about the add-on. +To sort products coming from [[= pim_product_name =]], see [[[= pim_product_name =]]](../../product_catalog/quable/quable.md) for details about the add-on. | Sort Clause | Sorting based on | Local product catalog | [[= pim_product_name =]] | |-----|-----|-----|-----| diff --git a/docs/search/sort_clause_reference/productavailability_sort_clause.md b/docs/search/sort_clause_reference/productavailability_sort_clause.md index 9ef70c1406d..a2b381da36e 100644 --- a/docs/search/sort_clause_reference/productavailability_sort_clause.md +++ b/docs/search/sort_clause_reference/productavailability_sort_clause.md @@ -9,17 +9,3 @@ The `ProductAvailability` Sort Clause sorts search results by whether they have ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; - -$query = new ProductQuery( - null, - null, - [ - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\SortClause\ProductAvailability(), - ] -); -``` diff --git a/docs/search/sort_clause_reference/productcode_sort_clause.md b/docs/search/sort_clause_reference/productcode_sort_clause.md index 8b205822345..9d3070ed193 100644 --- a/docs/search/sort_clause_reference/productcode_sort_clause.md +++ b/docs/search/sort_clause_reference/productcode_sort_clause.md @@ -9,17 +9,3 @@ The `ProductCode` Sort Clause sorts search results by the product code. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; - -$query = new ProductQuery( - null, - null, - [ - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\SortClause\ProductCode(), - ] -); -``` diff --git a/docs/search/sort_clause_reference/productname_sort_clause.md b/docs/search/sort_clause_reference/productname_sort_clause.md index a7f8b4c3cdc..cbf01bcfdac 100644 --- a/docs/search/sort_clause_reference/productname_sort_clause.md +++ b/docs/search/sort_clause_reference/productname_sort_clause.md @@ -9,17 +9,3 @@ The `ProductName` Sort Clause sorts search results by the Product code. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; - -$query = new ProductQuery( - null, - null, - [ - new \Ibexa\Contracts\ProductCatalog\Values\Product\Query\SortClause\ProductName(), - ] -); -``` diff --git a/docs/search/sort_clause_reference/random_sort_clause.md b/docs/search/sort_clause_reference/random_sort_clause.md index a8963b33e6f..155181b04eb 100644 --- a/docs/search/sort_clause_reference/random_sort_clause.md +++ b/docs/search/sort_clause_reference/random_sort_clause.md @@ -4,7 +4,7 @@ description: Random Sort Clause # Random Sort Clause -The [`Random` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Random.html) orders search results randomly. +The `Random` Sort Clause orders search results randomly. ## Arguments @@ -13,15 +13,4 @@ The [`Random` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contract ## Limitations -The `Random` Sort Clause isn't available in [Repository filtering](search_api.md#repository-filtering). In Elasticsearch engine, you cannot combine the `Random` Sort Clause with any other Sort Clause. - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\Random()]; -``` diff --git a/docs/search/sort_clause_reference/score_sort_clause.md b/docs/search/sort_clause_reference/score_sort_clause.md index 39215791c2d..457a357abb4 100644 --- a/docs/search/sort_clause_reference/score_sort_clause.md +++ b/docs/search/sort_clause_reference/score_sort_clause.md @@ -4,22 +4,8 @@ description: Score Sort Clause # Score Sort Clause -The [`Score` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Score.html) orders search results by their score. +The `Score` Sort Clause orders search results by their score. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Limitations - -The `Score` Sort Clause isn't available in [Repository filtering](search_api.md#repository-filtering). - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\Score()]; -``` diff --git a/docs/search/sort_clause_reference/sectionidentifier_sort_clause.md b/docs/search/sort_clause_reference/sectionidentifier_sort_clause.md index 3a11bc14e62..e7861c2ff98 100644 --- a/docs/search/sort_clause_reference/sectionidentifier_sort_clause.md +++ b/docs/search/sort_clause_reference/sectionidentifier_sort_clause.md @@ -4,7 +4,7 @@ description: SectionIdentifier Sort Clause # SectionIdentifier Sort Clause -The [`SectionIdentifier` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-SectionIdentifier.html) sorts search results by the Section IDs of the content items. +The `SectionIdentifier` Sort Clause sorts search results by the Section IDs of the content items. ## Arguments @@ -13,13 +13,3 @@ The [`SectionIdentifier` Sort Clause](/api/php_api/php_api_reference/classes/Ibe !!! note Solr search engine uses the `Query::SORT_DESC` sort direction by default. - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\SectionIdentifier()]; -``` diff --git a/docs/search/sort_clause_reference/sectionname_sort_clause.md b/docs/search/sort_clause_reference/sectionname_sort_clause.md index 3abdd458e16..97d1c764d95 100644 --- a/docs/search/sort_clause_reference/sectionname_sort_clause.md +++ b/docs/search/sort_clause_reference/sectionname_sort_clause.md @@ -4,18 +4,8 @@ description: SectionName Sort Clause # SectionName Sort Clause -The [`SectionName` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-SectionName.html) sorts search results by the Section name of the content items. +The `SectionName` Sort Clause sorts search results by the Section name of the content items. ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\SectionName()]; -``` diff --git a/docs/search/sort_clause_reference/sort_clause_reference.md b/docs/search/sort_clause_reference/sort_clause_reference.md index e5ad8fdf544..f9234c61a47 100644 --- a/docs/search/sort_clause_reference/sort_clause_reference.md +++ b/docs/search/sort_clause_reference/sort_clause_reference.md @@ -6,8 +6,7 @@ month_change: false # Sort Clause reference -Sort Clauses are the sorting options for Content and Location Search and -[Repository filtering](search_api.md#repository-filtering). +Sort Clauses are the sorting options for Content and Location Search. Capabilities of individual Sort Clauses can depend on the search engine. diff --git a/docs/search/sort_clause_reference/userlogin_sort_clause.md b/docs/search/sort_clause_reference/userlogin_sort_clause.md index 0389b841349..94a69f4d49b 100644 --- a/docs/search/sort_clause_reference/userlogin_sort_clause.md +++ b/docs/search/sort_clause_reference/userlogin_sort_clause.md @@ -4,18 +4,8 @@ description: UserLogin Sort Clause # UserLogin Sort Clause -The [`UserLogin` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Trash-UserLogin.html) sorts the results of searching in Trash by the login of the content item's creator. +The `UserLogin` Sort Clause sorts the results of searching in Trash by the login of the content item's creator. ## Arguments - (optional) `sortDirection` - Query constant, either `Query::SORT_ASC` or `Query::SORT_DESC` - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\Query; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new Query(); -$query->sortClauses = [new SortClause\Trash\UserLogin()]; -``` diff --git a/docs/search/sort_clause_reference/visibility_sort_clause.md b/docs/search/sort_clause_reference/visibility_sort_clause.md index 8ee670136b1..4a416b0fc3e 100644 --- a/docs/search/sort_clause_reference/visibility_sort_clause.md +++ b/docs/search/sort_clause_reference/visibility_sort_clause.md @@ -4,20 +4,10 @@ description: Visibility Sort Clause # Visibility Sort Clause -The [`Location\Visibility` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Content-Query-SortClause-Location-Visibility.html) sorts search results by whether the location is visible or not. +The `Location\Visibility` Sort Clause sorts search results by whether the location is visible or not. Locations that aren't visible are ranked as higher values (for example, with ascending order they're returned last). ## Arguments [[= include_file('docs/snippets/sort_direction.md') =]] - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\Content\LocationQuery; -use Ibexa\Contracts\Core\Repository\Values\Content\Query\SortClause; - -$query = new LocationQuery(); -$query->sortClauses = [new SortClause\Location\Visibility()]; -``` diff --git a/docs/search/url_search_reference/id_url_sort_clause.md b/docs/search/url_search_reference/id_url_sort_clause.md deleted file mode 100644 index 6e21977453a..00000000000 --- a/docs/search/url_search_reference/id_url_sort_clause.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -description: Id Sort Clause ---- - -# Id Sort Clause - -The [`SortClause\Id` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-SortClause-Id.html) sorts search results by the ID of the URL. - -## Arguments - -- `sortDirection` (optional) - the direction of the sorting, either `\Ibexa\Contracts\Core\Repository\Values\URL\Query\SortClause::SORT_ASC` (default) or `\Ibexa\Contracts\Core\Repository\Values\URL\Query\SortClause::SORT_DESC` - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\URL\Query\SortClause; -use Ibexa\Contracts\Core\Repository\Values\URL\URLQuery; - -// ... - -$query = new URLQuery(); -$query->sortClauses = [new SortClause\Id()]; -``` diff --git a/docs/search/url_search_reference/logicaland_url_criterion.md b/docs/search/url_search_reference/logicaland_url_criterion.md deleted file mode 100644 index c4b0e6a60f9..00000000000 --- a/docs/search/url_search_reference/logicaland_url_criterion.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -description: LogicalAnd Criterion ---- - -# LogicalAnd Criterion - -The [`LogicalAnd` URL Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-Criterion-LogicalAnd.html) matches a URL if all provided Criteria match. - -## Arguments - -- `criterion` - the set of Criteria combined by the logical operator - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\URL\Query\Criterion; -use Ibexa\Contracts\Core\Repository\Values\URL\URLQuery; - -$query = new URLQuery(); -$query->filter = new Criterion\LogicalAnd( - [ - new Criterion\Validity(true), - new Criterion\Pattern('ibexa.co'), - ] -); -``` diff --git a/docs/search/url_search_reference/logicalnot_url_criterion.md b/docs/search/url_search_reference/logicalnot_url_criterion.md deleted file mode 100644 index eed8ab36a41..00000000000 --- a/docs/search/url_search_reference/logicalnot_url_criterion.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -description: LogicalNot Criterion ---- - -# LogicalNot Criterion - -The [`LogicalNot` URL Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-Criterion-LogicalNot.html) matches a URL if the provided Criterion doesn't match. - -It takes only one Criterion in the array parameter. - -## Arguments - -- `criterion` - represents the Criterion that should be negated - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\URL\Query\Criterion; -use Ibexa\Contracts\Core\Repository\Values\URL\URLQuery; - -$query = new URLQuery(); -$query->filter = new Criterion\LogicalNot( - new Criterion\Pattern('ibexa.co') -); -``` diff --git a/docs/search/url_search_reference/logicalor_url_criterion.md b/docs/search/url_search_reference/logicalor_url_criterion.md deleted file mode 100644 index aef8778e22a..00000000000 --- a/docs/search/url_search_reference/logicalor_url_criterion.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -description: LogicalOr Criterion ---- - -# LogicalOr Criterion - -The [`LogicalOr` URL Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-Criterion-LogicalOr.html) matches a URL if at least one of the provided Criteria match. - -## Arguments - -- `criterion` - the set of Criteria combined by the logical operator - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\URL\Query\Criterion; -use Ibexa\Contracts\Core\Repository\Values\URL\URLQuery; - -$query = new URLQuery(); -$query->filter = new Criterion\LogicalOr( - [ - new Criterion\SectionIdentifier(['sports', 'news']), - new Criterion\Pattern('ibexa.co'), - ] -); -``` diff --git a/docs/search/url_search_reference/matchall_url_criterion.md b/docs/search/url_search_reference/matchall_url_criterion.md deleted file mode 100644 index 615ad74ee8b..00000000000 --- a/docs/search/url_search_reference/matchall_url_criterion.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -description: MatchAll Criterion ---- - -# MatchAll Criterion - -The [`MatchAll` URL Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-Criterion-MatchAll.html) is an auxiliary Criterion that returns all search results. -It's used internally when no filter or query is provided on a Query object. - -The Criterion takes no arguments. diff --git a/docs/search/url_search_reference/matchnone_url_criterion.md b/docs/search/url_search_reference/matchnone_url_criterion.md deleted file mode 100644 index 00c80e5f825..00000000000 --- a/docs/search/url_search_reference/matchnone_url_criterion.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -description: MatchNone Criterion ---- - -# MatchNone Criterion - -The [`MatchNone` URL Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-Criterion-MatchNone.html) is an auxiliary Criterion that returns no search results. -It's used internally when no filter or query is provided on a Query object. - -The Criterion takes no arguments. diff --git a/docs/search/url_search_reference/pattern_url_criterion.md b/docs/search/url_search_reference/pattern_url_criterion.md deleted file mode 100644 index 822ebac541f..00000000000 --- a/docs/search/url_search_reference/pattern_url_criterion.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -description: Pattern Criterion ---- - -# Pattern Criterion - -The [`Pattern` URL Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-Criterion-SectionId.html) matches URLs that contain the provided pattern. - -## Arguments - -- `pattern` - string representing the pattern that needs to be a part of the URL - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\URL\Query\Criterion; -use Ibexa\Contracts\Core\Repository\Values\URL\URLQuery; - -$query = new URLQuery(); -$query->filter = new Criterion\Pattern('ibexa.co'); -``` diff --git a/docs/search/url_search_reference/sectionid_url_criterion.md b/docs/search/url_search_reference/sectionid_url_criterion.md deleted file mode 100644 index 5de5f9b9eaa..00000000000 --- a/docs/search/url_search_reference/sectionid_url_criterion.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -description: SectionId Criterion ---- - -# SectionId Criterion - -The [`SectionId` URL Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-Criterion-SectionId.html) matches URLs based on the ID of the related content Section. - -## Arguments - -- `sectionIds` - array of ints representing the IDs of the related content Sections - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\URL\Query\Criterion; -use Ibexa\Contracts\Core\Repository\Values\URL\URLQuery; - -$query = new URLQuery(); -$query->filter = new Criterion\SectionId([1, 3]); -``` diff --git a/docs/search/url_search_reference/sectionidentifier_url_criterion.md b/docs/search/url_search_reference/sectionidentifier_url_criterion.md deleted file mode 100644 index ce4209876b5..00000000000 --- a/docs/search/url_search_reference/sectionidentifier_url_criterion.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -description: SectionIdentifier Criterion ---- - -# SectionIdentifier Criterion - -The [SectionIdentifier URL Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-Criterion-SectionIdentifier.html) matches URLs related to the content placed in a specified section identifier. - -## Arguments - -- `sectionIdentifiers` - string(s) representing the identifiers of the Section(s) - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\URL\Query\Criterion; -use Ibexa\Contracts\Core\Repository\Values\URL\URLQuery; - -$query = new URLQuery(); -$query->filter = new Criterion\SectionIdentifier(['standard', 'media']); -``` diff --git a/docs/search/url_search_reference/url_search_criteria.md b/docs/search/url_search_reference/url_search_criteria.md deleted file mode 100644 index af047ae0b1f..00000000000 --- a/docs/search/url_search_reference/url_search_criteria.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -description: URL Search Criteria help define and fine-tune search queries for URLs. -page_type: reference ---- - -# URL Search Criteria reference - -URL Search Criteria are only supported by [URL Search (`URLService::findUrls`)](url_api.md). - -|URL criteria|URL based on| -|------------|------------| -|[LogicalAnd](logicaland_url_criterion.md)|Implements a logical AND Criterion. It matches if ALL of the provided Criteria match.| -|[LogicalNot](logicalnot_url_criterion.md)|Implements a logical NOT Criterion. It matches if the provided Criterion doesn't match.| -|[LogicalOr](logicalor_url_criterion.md)|Implements a logical OR Criterion. It matches if at least one of the provided Criteria match.| -|[MatchAll](matchall_url_criterion.md)|Returns all URL results.| -|[MatchNone](matchnone_url_criterion.md)|Returns no URL results.| -|[Pattern](pattern_url_criterion.md)|Matches URLs that contain a pattern.| -|[SectionId](sectionid_url_criterion.md)|Matches URLs from content placed in the Section with the specified ID.| -|[SectionIdentifier](sectionidentifier_url_criterion.md)|Matches URLs from content placed in Sections with the specified identifiers.| -|[Validity](validity_url_criterion.md)|Matches URLs based on validity flag.| -|[VisibleOnly](visibleonly_url_criterion.md)|Matches URLs from published content.| diff --git a/docs/search/url_search_reference/url_search_sort_clauses.md b/docs/search/url_search_reference/url_search_sort_clauses.md deleted file mode 100644 index e052cc26a74..00000000000 --- a/docs/search/url_search_reference/url_search_sort_clauses.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -description: URL Sort Clauses -page_type: reference ---- - -# URL Sort Clauses - -URL Sort Clauses are the sorting options for URLs. -They're only supported by [URL Search (`URLService::findUrls`)](url_api.md). - -All URL Sort Clauses can take the following optional argument: - -- `sortDirection` - the direction of the sorting, either `\Ibexa\Contracts\Core\Repository\Values\URL\Query\SortClause::SORT_ASC` (default) or `\Ibexa\Contracts\Core\Repository\Values\URL\Query\SortClause::SORT_DESC` - -| Sort Clause | Sorting based on | -|-----|-----| -|[Id](id_url_sort_clause.md)|URL ID| -|[URL](url_url_sort_clause.md)|URL address| diff --git a/docs/search/url_search_reference/url_url_sort_clause.md b/docs/search/url_search_reference/url_url_sort_clause.md deleted file mode 100644 index 4d6aa1f43e9..00000000000 --- a/docs/search/url_search_reference/url_url_sort_clause.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -description: URL Sort Clause ---- - -# URL Sort Clause - -The [`SortClause\Url` Sort Clause](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-SortClause-URL.html) sorts search results by the URLs. - -## Arguments - -- `sortDirection` - the direction of the sorting, either `\Ibexa\Contracts\Core\Repository\Values\URL\Query\SortClause::SORT_ASC` (default) or `\Ibexa\Contracts\Core\Repository\Values\URL\Query\SortClause::SORT_DESC` - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\URL\Query\SortClause; -use Ibexa\Contracts\Core\Repository\Values\URL\URLQuery; - -// ... - -$query = new URLQuery(); -$query->sortClauses = [new SortClause\URL()]; -``` diff --git a/docs/search/url_search_reference/validity_url_criterion.md b/docs/search/url_search_reference/validity_url_criterion.md deleted file mode 100644 index f80bd7262c0..00000000000 --- a/docs/search/url_search_reference/validity_url_criterion.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -description: Validity Criterion ---- - -# Validity Criterion - -The [Validity URL Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-Criterion-Validity.html) matches URLs based on a validity flag. - -## Arguments - -- `isValid` - bool representing whether the matcher selects only valid URLs - -## Example - -``` php -use Ibexa\Contracts\Core\Repository\Values\URL\Query\Criterion; -use Ibexa\Contracts\Core\Repository\Values\URL\URLQuery; - -$query = new URLQuery(); -$query->filter = new Criterion\Validity(true); -``` diff --git a/docs/search/url_search_reference/visibleonly_url_criterion.md b/docs/search/url_search_reference/visibleonly_url_criterion.md deleted file mode 100644 index 1d4b53ea2f7..00000000000 --- a/docs/search/url_search_reference/visibleonly_url_criterion.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -description: VisibleOnly Criterion ---- - -# VisibleOnly Criterion - -The [`VisibleOnly` URL Criterion](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-URL-Query-Criterion-VisibleOnly.html) matches URLs from the published content. - -The Criterion takes no arguments. diff --git a/docs/users/customer_groups.md b/docs/users/customer_groups.md index 4788eb37386..1a27b25b8a3 100644 --- a/docs/users/customer_groups.md +++ b/docs/users/customer_groups.md @@ -11,7 +11,7 @@ For example, you can offer a 10% discount for all products in the catalog to use !!! tip - Customer groups aren't the same as [user groups](user_registration.md#user-groups). + Customer groups aren't the same as user groups. User groups concern all users in the system and can be used, for example, to handle permissions. Customer groups refer specifically to the product catalog functionalities and enable handling prices. diff --git a/docs/users/invitations.md b/docs/users/invitations.md index ddcebdd860c..1928e6628e7 100644 --- a/docs/users/invitations.md +++ b/docs/users/invitations.md @@ -14,33 +14,8 @@ You can limit the ability to invite other members to specific user groups, such ## Creating and sending invitations -Invitations are created with [InvitationService](/api/php_api/php_api_reference/classes/Ibexa-Contracts-User-Invitation-InvitationService.html), but sending them requires additional setup. -[[= product_name =]] provides you with `Ibexa\User\Invitation\MailSender` implementation of `InvitationSender` interface for sending invitations via email. -If you want to send invitations through different channels, you need to create a custom setup. +Invitations are sent by email. +The invitation contains a link that lets the recipient create their account. -## Invitation and registration form templates - -### Semantic configuration - -To set up custom templates for invitation or registration forms, create a template file and inform the system, through configuration, when to use this template. - -You might also set a SiteAccess under `scope`, to which the new user is invited. -If the SiteAccess isn't set, it falls back to the default `site` value. - -For example, use the following [configuration](configuration.md#configuration-files): - -```yaml -ibexa: - system: - : - user_invitation: - hash_expiration_time: P7D - templates: - mail: "@@App/invitation/mail.html.twig" -``` - -Here, you can specify which template should be used for the invitation mail, and what should be the expiration time for the invitation link included in that mail. -If a user doesn't click the invitation link sent to them in time, you can refresh the invitation. -Refresh resets the time limit and changes the hash in the invitation link. - -You can find more registration related templates in [Register new users documentation](user_registration.md#other-user-management-templates). +## Invitation expiration +If a user doesn't click the invitation link sent to them in time, you can refresh the invitation to reset the time limit. diff --git a/docs/users/login_methods.md b/docs/users/login_methods.md deleted file mode 100644 index 029b6a29bf9..00000000000 --- a/docs/users/login_methods.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -description: Set up user login methods. ---- - -# Login methods - -Two login methods are available: with user name or with email. - -Providers for these two methods are `ibexa.security.user_provider.username` and `ibexa.security.user_provider.email`. - -You can configure which method is allowed under the `security` [configuration key](configuration.md#configuration-files): - -``` yaml -security: - providers: - ibexa: - chain: - providers: [ibexa_username, ibexa_email] - - ibexa_username: - id: ibexa.security.user_provider.username - - ibexa_email: - id: ibexa.security.user_provider.email - - firewalls: - #... - ibexa_front: - # ... - provider: ibexa -``` - -You can customize per user field whether the email address used as a login method must be unique or not. - -To check that all existing user accounts have unique emails, run the `ibexa:user:audit-database` command. -It lists all user accounts with duplicate emails. - -!!! caution - - Because logging in with email was not available until version v3.0, you can come across issues if you use the option on an existing database. - - This may happen if more than one account uses the same email address. - Login through the user name is still available. - - To resolve the issues, run `ibexa:user:audit-database` and manually modify accounts that have duplicate emails. - -## Login rules - -You can set the rules for allowed user names in the back office per user field. -The rules are set by using regular expressions. - -For example, to ensure that user names can only contain lowercase letters, set `[a-z]+$` as **Username pattern**: - -![Setting a user name pattern](username_pattern.png) - -To check that all existing user accounts have names that fit the current pattern, run the `ibexa:user:audit-database` command. -It checks all user accounts in the database and lists those that don't fit the pattern. diff --git a/docs/users/passwords.md b/docs/users/passwords.md index 371b6c0ac02..b986262a6b9 100644 --- a/docs/users/passwords.md +++ b/docs/users/passwords.md @@ -1,5 +1,16 @@ --- description: Set up user password rules. +saas_review: + - siteaccess + - links_removed +saas_review_note: >- + The password recovery token validity is set with a SiteAccess-scoped security + parameter. Confirm how that per-SiteAccess setting is exposed once SiteAccess + configuration moves to a UI. + + Links to the deleted add_forgot_password_option.md, add_login_form.md and + repository_configuration.md pages were removed; check that the surrounding text + still reads correctly. --- # Passwords @@ -10,45 +21,8 @@ The user may request to change their password, or may forget it and ask to have To change password, the user must have the `user/password` permission. -When the user requests a reset of a forgotten password, an email is sent to them with a token. -It allows them to create a new password. +When the user requests a reset of a forgotten password, an email is sent to them and it allows them to create a new password. -For information about how to create and configure the template, see [Add forgot password option](add_forgot_password_option.md) - -The template for this email is located in `Resources/views/forgot_password/mail/forgot_user_password.html.twig` in `ibexa/user`. -You can [customize it according to your needs](add_login_form.md#customize-login-form). - -The validity of the password recovery token can be set by using the `ibexa.system..security.token_interval_spec` parameter. -By default, it's set to `PT1H` (one hour). - -## Revoking passwords - -In case of a security situation such as a data leakage, you may need to force users to change their passwords. -You can do it with the help of the `ibexa:user:expire-password` command, which revokes the passwords for specific users, user groups, or users belonging to the chosen content type. - -To select which users to revoke passwords for, use one of the following options with the command: - -- `--user-id|-u` - the ID of the user. Accepts multiple user IDs -- `--user-group-id|-ug` - the ID of the user group. Accepts multiple group IDs -- `--user-content-type-identifier|-ct` - the identifier of the user content type. Accepts multiple content types - -You can use the following additional options with the command: - -- `--force|-f` - commits the change, otherwise the command only performs a dry run -- `--iteration-count|-c` - defines how many users are fetched at once. Lowering this value helps with memory issues -- `--password-ttl|-t` - number of days after which new passwords expire. Used when the command enables password expiration for user content types that don't use it yet. - -For example, to revoke the passwords of all users of the `user` content type, run: - -``` bash -php bin/console ibexa:user:expire-password --user-content-type-identifier=user --force -``` - -To perform a dry run (without saving the results) of revoking passwords of all users from user group 13, run: - -``` bash -php bin/console ibexa:user:expire-password --user-group-id=13 -``` ## Password rules @@ -66,7 +40,6 @@ To access the password settings: !!! tip There can be other content types that function as users, beyond the built-in user content type. - For details, see [User Identifiers](repository_configuration.md#user-identifiers). ## Password attributes diff --git a/docs/users/user_management_guide.md b/docs/users/user_management_guide.md index 3e964c76e80..d584a274fb1 100644 --- a/docs/users/user_management_guide.md +++ b/docs/users/user_management_guide.md @@ -30,8 +30,6 @@ Here's how it works: - Roles and permissions - define roles and assign permissions to them. This ensures that users have appropriate access to content and functionalities. Roles can be customized to match the organization's specific needs. -- Authentication methods - enable multiple authentication methods, including traditional username and password, OAuth, and external service logins. This flexibility allows organizations to adapt to various user authentication requirements. - - User segmentation - segment users based on criteria such as demographics, behavior, or preferences. This segmentation enables personalized content delivery and targeted marketing. - Invitations - invite users to join a platform streamlining an onboarding process, sending invitations for exclusive content or events. @@ -58,26 +56,10 @@ To help you understand further the role each element serves, here's a brief summ - Policy - is a set of rules or conditions that determine under what circumstances a specific permission is granted or denied by applying limitations. Policies allow for fine-grained control of access based on various factors, such as user attributes or system states. -### Custom policies - -[Tailor user access control](custom_policies.md) to your unique requirements by using custom policies. -Define complex rules and access criteria for different users or groups. - ### Limitations -[Implement limitations](limitations.md) on user actions based on specific criteria, such as time-based restrictions or geographic locations. - -### Authentication methods - -[[= product_name_base =]] offers flexibility in authentication methods to cater to different user bases and security requirements. - -![Log in via Google](log_in_via_google.png) - -Available options: +[Define](limitations.md) on user actions based on specific criteria, such as time-based restrictions or geographic locations. -- [Username and password](passwords.md) - ideal for most users, this traditional method offers a secure login process with username and password. -- [OAuth client](oauth_client.md) - integrating OAuth authentication allows users to log in using their existing social media credentials (like Google, Facebook, and Twitter), or the enterprise's system (like Active Directory or LDAP). -- [OAuth server](oauth_server.md) - client applications (such as mobile apps) can authenticate a user by using the platform's login screen, then access resources. ### Invitations @@ -117,7 +99,7 @@ With role-based access control and personalized content, users have a more engag ### Enhanced security -The flexible authentication methods and permission management help safeguard sensitive data and maintain security. +The permission management helps safeguard sensitive data and maintain security. With the ability to define and manage user roles and permissions, clients can ensure that sensitive data and actions are protected. User management helps prevent unauthorized access. diff --git a/docs/users/user_registration.md b/docs/users/user_registration.md deleted file mode 100644 index ae02535ba1e..00000000000 --- a/docs/users/user_registration.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -description: Register new users. ---- - -# Register new users - -You can allow your users to create accounts by using the `/register` route. -This route leads to a registration form that, when filled in, creates a new user content item in the repository. -To give your users a possibility to register themselves, follow the instructions on [enabling account registration](8_enable_account_registration.md). - -## User types - -There are two user types defined: `users` and `customers`. -`users` are back office users that are involved in creating the page such as editors, and `customers` are frontend users. -To decide where the user should be registered to, you need to specify their user type under the `ibexa.system..user_type_identifier` [configuration key](configuration.md#configuration-files). - -```yaml -ibexa: - system: - : - user_registration: - user_type_identifier: user -``` - -## User groups - -By default, new users generated in this way are placed in the Guest accounts group. -You can select a different default group in the following section of configuration: - -``` yaml -ibexa: - system: - default: - user_registration: - group_remote_id: -``` - -## Registration form field configuration - -To modify the registration form template, add or remove fields under the `allowed_field_definitions_identifiers` [configuration key](configuration.md#configuration-files): - -```yaml -ibexa: - system: - : - user_registration: - user_type_identifier: user - form: - allowed_field_definitions_identifiers: - - first_name - - last_name - - user_account -``` - -## Other user management templates - -You can also modify form templates in the following way: - -### Changing user password - -``` yaml -ibexa: - system: - : - user_change_password: - templates: - form: -``` - -### Password recovery forms - -``` yaml -ibexa.site_access.config..user_forgot_password.templates.form -ibexa.site_access.config..user_forgot_password_success.templates.form -ibexa.site_access.config..user_forgot_password_login.templates.form -ibexa.site_access.config..user_forgot_password.templates.mail -``` - -### Resetting password - -``` yaml -ibexa.site_access.config..user_reset_password.templates.form -ibexa.site_access.config..user_reset_password.templates.invalid_link -ibexa.site_access.config..user_reset_password.templates.success -``` - -### User settings - -``` yaml -ibexa.site_access.config..user_settings.templates.list -ibexa.site_access.config..user_settings.templates.update -``` - -### Changing registration form templates - -To change the registration form template, follow the instructions in [Invitation and registration form templates](invitations.md#invitation-and-registration-form-templates). diff --git a/docs/users/users.md b/docs/users/users.md index 04a1152c1df..3dea1135b3e 100644 --- a/docs/users/users.md +++ b/docs/users/users.md @@ -13,23 +13,7 @@ All such user accounts have the same underlying mechanism and enable you to cont [[= cards([ "users/user_management_guide", "users/invitations", -"users/user_registration", -"users/update_basic_user_data", -], columns=4) =]] +"users/passwords", +"users/customer_groups", -## Authenticate users - -[[= cards([ - "users/login_methods", - "users/passwords", - "users/user_authentication", - "users/oauth_client", - "users/oauth_server", -], columns=5) =]] - -## Group users - -[[= cards([ - "users/customer_groups", - "users/segment_api", -], columns=2) =]] +], columns=3) =]] diff --git a/lychee.toml.dist b/lychee.toml.dist index 11feca9fb62..18dfdfe6f9f 100644 --- a/lychee.toml.dist +++ b/lychee.toml.dist @@ -90,10 +90,6 @@ exclude_path = [ "site/search/search_index.json", "site/assets", "site/sitemap.xml", - # PHP API reference HTML is generated by phpDocumentor and uses to resolve - # relative links — lychee does not honour tags and would flag them as broken. - # Links pointing *to* these files from other pages are still checked. - "site/api/php_api/php_api_reference/", ] # Check the specified file extensions diff --git a/main.py b/main.py index 358439eb51a..5b6205f4809 100644 --- a/main.py +++ b/main.py @@ -229,7 +229,7 @@ def slugify(text: str) -> str: return text.lower().replace(' ', '-') def validate_categories(categories: List[str]) -> None: - available_categories = ['Headless', 'Experience', 'LTS Update', 'New feature', 'First release'] + available_categories = ['New feature', 'First release'] for category in categories: if category not in available_categories: diff --git a/mkdocs.yml b/mkdocs.yml index 78b2e261c0f..50726a66676 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,6 +1,6 @@ INHERIT: plugins.yml -site_name: Developer Documentation +site_name: Cohesivo Developer Documentation repo_url: https://github.com/ibexa/documentation-developer edit_uri: blob/saas/docs site_url: https://doc.ibexa.co/en/saas/ @@ -19,96 +19,26 @@ not_in_nav: | personalization/legacy_recommendation_api.md /snippets/* nav: - - Ibexa Developer Documentation: index.md + - Cohesivo Developer Documentation: index.md - Cohesivo editions: + - On-premise Cohesivo: on_premise.md - Editions: ibexa_products/editions.md - Cohesivo Headless: ibexa_products/ibexa_headless.md - Cohesivo Experience: ibexa_products/ibexa_experience.md - Getting started: - Getting started: getting_started/getting_started.md - First steps: getting_started/first_steps.md - - Tutorials: - - Tutorials: tutorials/tutorials.md - - Beginner tutorial: - - Beginner tutorial: tutorials/beginner_tutorial/beginner_tutorial.md - - 1. Get ready: tutorials/beginner_tutorial/1_get_ready.md - - 2. Create the content model: tutorials/beginner_tutorial/2_create_the_content_model.md - - 3. Customize the front page: tutorials/beginner_tutorial/3_customize_the_front_page.md - - 4. Display a single content item: tutorials/beginner_tutorial/4_display_single_content_item.md - - 5. Display a list of content items: tutorials/beginner_tutorial/5_display_a_list_of_content_items.md - - 6. Improve configuration: tutorials/beginner_tutorial/6_improve_configuration.md - - 7. Embed content: tutorials/beginner_tutorial/7_embed_content.md - - 8. Enable account registration: tutorials/beginner_tutorial/8_enable_account_registration.md - - Page and Form tutorial: - - Page and Form tutorial: tutorials/page_and_form_tutorial/page_and_form_tutorial.md - - 1. Get a starter website: tutorials/page_and_form_tutorial/1_get_a_starter_website.md - - 2. Prepare the landing page: tutorials/page_and_form_tutorial/2_prepare_the_landing_page.md - - 3. Use existing blocks: tutorials/page_and_form_tutorial/3_use_existing_blocks.md - - 4. Create a custom block: tutorials/page_and_form_tutorial/4_create_a_custom_block.md - - 5. Create a newsletter form: tutorials/page_and_form_tutorial/5_create_newsletter_form.md - - Generic field type: - - Creating Point 2D field type: tutorials/generic_field_type/creating_a_point2d_field_type.md - - 1. Implement Value class: tutorials/generic_field_type/1_implement_the_point2d_value_class.md - - 2. Define field type: tutorials/generic_field_type/2_define_point2d_field_type.md - - 3. Create a form: tutorials/generic_field_type/3_create_form_for_point2d.md - - 4. Introduce a template: tutorials/generic_field_type/4_introduce_a_template.md - - 5. Add a new Field: tutorials/generic_field_type/5_add_a_field.md - - 6. Implement settings: tutorials/generic_field_type/6_settings.md - - 7. Add basic validation: tutorials/generic_field_type/7_add_a_validation.md - - 8. Data migration: tutorials/generic_field_type/8_data_migration.md - API: - API: api/api.md - - PHP API: - - PHP API usage: api/php_api/php_api.md - - PHP API reference: api/php_api/php_api_reference/index.html - - REST API: - - REST API usage: - - REST API usage: api/rest_api/rest_api_usage/rest_api_usage.md - - REST requests: api/rest_api/rest_api_usage/rest_requests.md - - REST responses: api/rest_api/rest_api_usage/rest_responses.md - - Testing REST API: api/rest_api/rest_api_usage/testing_rest_api.md - - REST API reference: api/rest_api/rest_api_reference/rest_api_reference.html - - Extending REST API: - - Adding custom media type: api/rest_api/extending_rest_api/adding_custom_media_type.md - - Creating new REST resource: api/rest_api/extending_rest_api/creating_new_rest_resource.md - - REST API authentication: api/rest_api/rest_api_authentication.md - - GraphQL: - - GraphQL: api/graphql/graphql.md - - GraphQL queries: api/graphql/graphql_queries.md - - GraphQL operations: api/graphql/graphql_operations.md - - GraphQL customization: api/graphql/graphql_customization.md - - GraphQL custom field type: api/graphql/graphql_custom_ft.md - - Event reference: - - Event reference: api/event_reference/event_reference.md - - Content events: api/event_reference/content_events.md - - Content type events: api/event_reference/content_type_events.md - - Location events: api/event_reference/location_events.md - - Language events: api/event_reference/language_events.md - - Section events: api/event_reference/section_events.md - - Object state events: api/event_reference/object_state_events.md - - Taxonomy events: api/event_reference/taxonomy_events.md - - Role events: api/event_reference/role_events.md - - User events: api/event_reference/user_events.md - - Segmentation events: api/event_reference/segmentation_events.md - - Page events: api/event_reference/page_events.md - - Site events: api/event_reference/site_events.md - - URL events: api/event_reference/url_events.md - - Trash events: api/event_reference/trash_events.md - - Twig Components: api/event_reference/twig_component_events.md - - AI Action events: api/event_reference/ai_action_events.md - - Integrated help events: api/event_reference/integrated_help_events.md - - Translations management events: api/event_reference/translations_management_events.md - - Other events: api/event_reference/other_events.md + - REST API usage: + - REST API usage: api/rest_api/rest_api_usage/rest_api_usage.md + - REST requests: api/rest_api/rest_api_usage/rest_requests.md + - REST responses: api/rest_api/rest_api_usage/rest_responses.md + - Testing REST API: api/rest_api/rest_api_usage/testing_rest_api.md + - REST API reference: api/rest_api/rest_api_reference/rest_api_reference.html + - REST API authentication: api/rest_api/rest_api_authentication.md - Administration: - Administration: administration/administration.md - - Project organization: - - Project organization: administration/project_organization/project_organization.md - - Architecture: administration/project_organization/architecture.md - - Bundles: administration/project_organization/bundles.md - - Dashboard: - - Configure default dashboard: administration/dashboard/configure_default_dashboard.md - - Customize dashboard: administration/dashboard/customize_dashboard.md - - PHP API Dashboard service: administration/dashboard/php_api_dashboard_service.md - Admin panel: - Admin panel: administration/admin_panel/admin_panel.md - Users: administration/admin_panel/users_admin_panel.md @@ -125,46 +55,11 @@ nav: - Object States: administration/content_organization/object_states.md - Configuration: - Configuration: administration/configuration/configuration.md - - Dynamic configuration: administration/configuration/dynamic_configuration.md - - Repository configuration: administration/configuration/repository_configuration.md - Back office: - Back office: administration/back_office/back_office.md - - Configuration: administration/back_office/back_office_configuration.md - - Content tree: administration/back_office/content_tree.md - - Back office elements: - - Reusable components: administration/back_office/back_office_elements/reusable_components.md - - Add drop-downs: administration/back_office/back_office_elements/add_dropdowns.md - - Custom icons: administration/back_office/back_office_elements/custom_icons.md - - Add drag and drop: administration/back_office/back_office_elements/add_drag_and_drop.md - - Custom components: administration/back_office/back_office_elements/custom_components.md - - Formatting date and time: administration/back_office/back_office_elements/formatting_date_and_time.md - - Extending thumbnails: administration/back_office/back_office_elements/extending_thumbnails.md - - Importing assets from a bundle: administration/back_office/back_office_elements/importing_assets_from_bundle.md - - Back office tabs: - - Back office tabs: administration/back_office/back_office_tabs/back_office_tabs.md - - Create dashboard tab: administration/back_office/back_office_tabs/create_dashboard_tab.md - - Tab switcher in Content edit page: administration/back_office/content_tab_switcher.md - - Add anchor menu to content type edit screen: administration/back_office/content_type_anchor_menu.md - - Back office menus: - - Back office menus: administration/back_office/back_office_menus/back_office_menus.md - - Add menu item: administration/back_office/back_office_menus/add_menu_item.md - - Add user setting: administration/back_office/add_user_setting.md - - Customize calendar: administration/back_office/customize_calendar.md - - Browser: - - Browser: administration/back_office/browser/browser.md - - Add browser tab: administration/back_office/browser/add_browser_tab.md - - Multi-file upload: administration/back_office/multifile_upload.md - - Sub-items list: administration/back_office/subitems_list.md - - Notifications: administration/back_office/notifications.md - Integrated help: - Integrated help: administration/back_office/integrated_help.md - - Customize integrated help: administration/back_office/customize_integrated_help.md - Product tour: administration/back_office/product_tour.md - - Configure product tour: administration/back_office/configure_product_tour.md - - Customize product tour: administration/back_office/customize_product_tour.md - - Customize search: - - Customize search suggestion: administration/back_office/customize_search_suggestion.md - - Customize search sorting: administration/back_office/customize_search_sorting.md - Recent activity: administration/recent_activity/recent_activity.md - Content management: - Content management: content_management/content_management.md @@ -173,84 +68,32 @@ nav: - Locations: content_management/locations.md - Content Relations: content_management/content_relations.md - Content availability: content_management/content_availability.md - - Taxonomy: - - Taxonomy: content_management/taxonomy/taxonomy.md - - Taxonomy API: content_management/taxonomy/taxonomy_api.md + - Taxonomy: content_management/taxonomy/taxonomy.md - Images: - Images: content_management/images/images.md - Configure Image Editor: content_management/images/configure_image_editor.md - - Extend Image Editor: content_management/images/extend_image_editor.md - - Add Image Asset from DAM: content_management/images/add_image_asset_from_dam.md - - Fastly Image Optimizer: content_management/images/fastly_io.md - RichText: - RichText: content_management/rich_text/rich_text.md - Online Editor guide: content_management/rich_text/online_editor_guide.md - - Extend Online Editor: content_management/rich_text/extend_online_editor.md - - Create custom RichText block: content_management/rich_text/create_custom_richtext_block.md - File management: - - File management: content_management/file_management/file_management.md - Binary and Media download: content_management/file_management/binary_and_media_download.md - - File URL handling: content_management/file_management/file_url_handling.md - Pages: - Pages: content_management/pages/pages.md - Page Builder guide: content_management/pages/page_builder_guide.md - Page blocks: content_management/pages/page_blocks.md - - Page block attributes: content_management/pages/page_block_attributes.md - - Page block validators: content_management/pages/page_block_validators.md - - Create custom Page block: content_management/pages/create_custom_page_block.md - - React App page block: content_management/pages/react_app_block.md - - Ibexa Connect scenario block: content_management/pages/ibexa_connect_scenario_block.md - Forms: - Forms: content_management/forms/forms.md - Form Builder guide: content_management/forms/form_builder_guide.md - - Work with Forms: content_management/forms/work_with_forms.md - - Form API: content_management/forms/form_api.md - - Create custom Form field: content_management/forms/create_custom_form_field.md - - Create Form attribute: content_management/forms/create_form_attribute.md - - Customize email notifications: content_management/forms/customize_email_notifications.md - - Workflow: - - Workflow: content_management/workflow/workflow.md - - Workflow API: content_management/workflow/workflow_api.md - - Add custom workflow action: content_management/workflow/add_custom_workflow_action.md - - URL management: - - URL management: content_management/url_management/url_management.md - - URL API: content_management/url_management/url_api.md - - User-generated content: content_management/user_generated_content.md - - Content API: - - Browsing content: content_management/content_api/browsing_content.md - - Creating content: content_management/content_api/creating_content.md - - Managing content: content_management/content_api/managing_content.md - - Content management API: - - Bookmark API: content_management/content_management_api/bookmark_api.md - - Section API: content_management/content_management_api/section_api.md - - Object state API: content_management/content_management_api/object_state_api.md - - Data migration: - - Data migration: content_management/data_migration/data_migration.md - - Importing data: content_management/data_migration/importing_data.md - - Exporting data: content_management/data_migration/exporting_data.md - - Managing migrations: content_management/data_migration/managing_migrations.md - - Data migration actions: content_management/data_migration/data_migration_actions.md - - Create data migration step: content_management/data_migration/create_data_migration_step.md - - Create data migration action: content_management/data_migration/create_data_migration_action.md - - Add data migration matcher: content_management/data_migration/add_data_migration_matcher.md - - Data migration API: content_management/data_migration/data_migration_api.md + - Workflow: content_management/workflow/workflow.md + - URL management: content_management/url_management/url_management.md - Field types: - Field types: content_management/field_types/field_types.md - - Type and Value: content_management/field_types/type_and_value.md - - Form and template: content_management/field_types/form_and_template.md - - Storage: content_management/field_types/field_type_storage.md - - Validation: content_management/field_types/field_type_validation.md - - Searching: content_management/field_types/field_type_search.md - - Create custom generic field type: content_management/field_types/create_custom_generic_field_type.md - - Create custom field type comparison: content_management/field_types/create_custom_field_type_comparison.md - - Customize field type metadata: content_management/field_types/customize_field_type_metadata.md - Field type reference: - Field type reference: content_management/field_types/field_type_reference/field_type_reference.md - Address field type: content_management/field_types/field_type_reference/addressfield.md - Author field type: content_management/field_types/field_type_reference/authorfield.md - BinaryFile field type: content_management/field_types/field_type_reference/binaryfilefield.md - Checkbox field type: content_management/field_types/field_type_reference/checkboxfield.md - - Content query field type: content_management/field_types/field_type_reference/contentqueryfield.md - Country field type: content_management/field_types/field_type_reference/countryfield.md - CustomerGroup field type: content_management/field_types/field_type_reference/customergroupfield.md - DateAndTime field type: content_management/field_types/field_type_reference/dateandtimefield.md @@ -267,7 +110,6 @@ nav: - Matrix field type: content_management/field_types/field_type_reference/matrixfield.md - Measurement field type: content_management/field_types/field_type_reference/measurementfield.md - Media field type: content_management/field_types/field_type_reference/mediafield.md - - Null field type: content_management/field_types/field_type_reference/nullfield.md - Page field type: content_management/field_types/field_type_reference/pagefield.md - ProductSpecification field type: content_management/field_types/field_type_reference/productspecificationfield.md - Relation field type: content_management/field_types/field_type_reference/relationfield.md @@ -281,51 +123,14 @@ nav: - Time field type: content_management/field_types/field_type_reference/timefield.md - URL field type: content_management/field_types/field_type_reference/urlfield.md - User field type: content_management/field_types/field_type_reference/userfield.md - - Templating: - - Templating: templating/templating.md - - Render content: - - Render content: templating/render_content/render_content.md - - Render Page: templating/render_content/render_page.md - - Render content in PHP: templating/render_content/render_content_in_php.md - - Templates: - - Templates: templating/templates/templates.md - - Template configuration: templating/templates/template_configuration.md - - View matcher reference: templating/templates/view_matcher_reference.md - - Create custom view matcher: templating/templates/create_custom_view_matcher.md - - Assets: templating/assets.md - - Image variations: templating/image_variations.md - - Twig Components: templating/components.md - - URLs and routes: - - URLs and routes: templating/urls_and_routes/urls_and_routes.md - - Design engine: - - Design engine: templating/design_engine/design_engine.md - - Add new design: templating/design_engine/add_new_design.md - - Queries and controllers: - - Content queries: templating/queries_and_controllers/content_queries.md - - Built-in Query types: templating/queries_and_controllers/built-in_query_types.md - - Create custom Query type: templating/queries_and_controllers/create_custom_query_type.md - - Controllers: templating/queries_and_controllers/controllers.md - - Embed and list content: - - List content: templating/embed_and_list_content/list_content.md - - Embed content: templating/embed_and_list_content/embed_content.md - - Render images: templating/embed_and_list_content/render_images.md - - Layout: - - Add breadcrumbs: templating/layout/add_breadcrumbs.md - - Add forgot password option: templating/layout/add_forgot_password_option.md - - Add login form: templating/layout/add_login_form.md - - Add navigation menu: templating/layout/add_navigation_menu.md - - Add search form to front page: templating/layout/add_search_form.md - AI: - AI: ai/ai.md - AI Actions: - AI Actions: ai/ai_actions/ai_actions.md - AI Actions guide: ai/ai_actions/ai_actions_guide.md - - Configure AI Actions: ai/ai_actions/configure_ai_actions.md - - Extend AI Actions: ai/ai_actions/extend_ai_actions.md - MCP Servers: - MCP Servers: ai/mcp/mcp.md - MCP Servers guide: ai/mcp/mcp_guide.md - - Install MCP Servers: ai/mcp/mcp_config.md - Work with MCP servers: ai/mcp/mcp_usage.md - Product catalog: - Product catalog: product_catalog/product_catalog.md @@ -333,39 +138,18 @@ nav: - Quable integration: - Quable integration: product_catalog/quable/quable.md - Quable product guide: product_catalog/quable/quable_guide.md - - Install Quable: product_catalog/quable/install_quable.md - - Configure Quable: product_catalog/quable/configure_quable_connector.md - - Quable API: product_catalog/quable/quable_api.md - - Product catalog configuration: product_catalog/product_catalog_configuration.md - Products: product_catalog/products.md - Attributes: - Date and Time attribute: product_catalog/attributes/date_and_time.md - Symbol attribute type: product_catalog/attributes/symbol_attribute_type.md - - Product API: product_catalog/product_api.md - Catalogs: product_catalog/catalogs.md - - Catalog API: product_catalog/catalog_api.md - - Enable purchasing products: product_catalog/enable_purchasing_products.md - Prices: product_catalog/prices.md - - Price API: product_catalog/price_api.md - - Customize product catalog: - - Customize product catalog: product_catalog/customize_product_catalog.md - - Create custom attribute type: product_catalog/create_custom_attribute_type.md - - Create custom availability strategy: product_catalog/create_custom_availability_strategy.md - - Create custom catalog filter: product_catalog/create_custom_catalog_filter.md - - Create custom name schema: product_catalog/create_custom_name_schema_strategy.md - - Create product code generator: product_catalog/create_product_code_generator.md - - Customize product embed templates: product_catalog/customize_product_embed_templates.md - - Add remote PIM support: product_catalog/add_remote_pim_support.md - Customer management: - Customer Portal: customer_management/customer_portal.md - Customer Portal guide: customer_management/customer_portal_guide.md - - Customer Portal configuration: customer_management/cp_configuration.md - - Create Customer Portal: customer_management/cp_page_builder.md - Customer Portal Applications: customer_management/cp_applications.md - - Create registration form: customer_management/create_user_registration_form.md - Data collection: - Qualifio integration: qualifio/qualifio.md - - Install Qualifio: qualifio/install_qualifio.md - Create campaign with Qualifio: qualifio/create_campaign.md - Integrate Qualifio with Ibexa Connect: qualifio/integrate_ibexa_connect.md - Multisite: @@ -373,24 +157,15 @@ nav: - Multisite configuration: multisite/multisite_configuration.md - SiteAccess: - SiteAccess: multisite/siteaccess/siteaccess.md - - SiteAccess matching: multisite/siteaccess/siteaccess_matching.md - - SiteAccess-aware configuration: multisite/siteaccess/siteaccess_aware_configuration.md - - Injecting SiteAccess: multisite/siteaccess/injecting_siteaccess.md - - Set up campaign SiteAccess: multisite/set_up_campaign_siteaccess.md - - Set up translation SiteAccess: multisite/set_up_translation_siteaccess.md - Site Factory: - Site Factory: multisite/site_factory/site_factory.md - Site Factory configuration: multisite/site_factory/site_factory_configuration.md - Languages: - Languages: multisite/languages/languages.md - - Language API: multisite/languages/language_api.md - - Back office translations: multisite/languages/back_office_translations.md - Translations management: - Translations management: multisite/translations_management/translations_management.md - Translations management guide: multisite/translations_management/translations_management_guide.md - Configure translations management: multisite/translations_management/configure_translations_management.md - - Translate content items with CLI: multisite/translations_management/translate_with_cli.md - - Extend translations management: multisite/translations_management/extend_translations_management.md - Permissions: - Permissions: permissions/permissions.md - Permission overview: permissions/permission_overview.md @@ -398,58 +173,26 @@ nav: - Policies: permissions/policies.md - Limitations: permissions/limitations.md - Limitation reference: permissions/limitation_reference.md - - Custom policies: permissions/custom_policies.md - Users: - Users: users/users.md - User management guide: users/user_management_guide.md - User setup: - Invitations: users/invitations.md - - Registration: users/user_registration.md - - Update basic user data: users/update_basic_user_data.md - User authentication: - - Login methods: users/login_methods.md - Passwords: users/passwords.md - - User authentication: users/user_authentication.md - - OAuth client: users/oauth_client.md - - OAuth server: users/oauth_server.md - User grouping: - Customer groups: users/customer_groups.md - - Segment API: users/segment_api.md - Recommendations: - Raptor integration: recommendations/raptor_integration/raptor_connector.md - Raptor integration guide: recommendations/raptor_integration/raptor_connector_guide.md - - Install and configure Raptor: recommendations/raptor_integration/connector_installation_configuration.md - - Track with Raptor: - - Tracking functions: recommendations/raptor_integration/tracking_functions.md - - Hybrid tracking: recommendations/raptor_integration/hybrid_tracking.md - - Tracking with PHP API: recommendations/raptor_integration/tracking_php_api.md - Recommendation blocks: recommendations/raptor_integration/recommendation_blocks.md - - Render recommendations: recommendations/raptor_integration/custom_recommendation_rendering.md - Customer Data Platform: - Raptor CDP integration: raptor_cdp/raptor_cdp.md - Raptor CDP guide: raptor_cdp/raptor_cdp_guide.md - - Install Raptor CDP: raptor_cdp/raptor_cdp_installation.md - Activate Raptor CDP: - - Activate Raptor CDP: raptor_cdp/raptor_cdp_activation/raptor_cdp_activation.md - - Configure Raptor CDP: raptor_cdp/raptor_cdp_activation/raptor_cdp_configuration.md - - Export Raptor CDP data: raptor_cdp/raptor_cdp_activation/raptor_cdp_data_export.md - Track with Raptor CDP: raptor_cdp/raptor_cdp_activation/raptor_cdp_add_tracking.md - - Schedule Raptor CDP data export: raptor_cdp/raptor_cdp_data_export_schedule.md - - Customize Raptor CDP data: raptor_cdp/raptor_cdp_data_customization.md - Search: - Search: search/search.md - - Search engines: - - Search engines: search/search_engines/search_engines.md - - Elasticsearch search engine: - - Overview: search/search_engines/elasticsearch/elasticsearch_overview.md - - Configure Elasticsearch: search/search_engines/elasticsearch/configure_elasticsearch.md - - Solr search engine: - - Overview: search/search_engines/solr_search_engine/solr_overview.md - - Configure Solr: search/search_engines/solr_search_engine/configure_solr.md - - Legacy search engine: - - Overview: search/search_engines/legacy_search_engine/legacy_search_overview.md - - Configure repository: search/search_engines/legacy_search_engine/configure_repository.md - - Search API: search/search_api.md - Search Criteria and Sort Clauses: search/search_criteria_and_sort_clauses.md - Search Criteria reference: - Search Criteria reference: search/criteria_reference/search_criteria_reference.md @@ -554,18 +297,6 @@ nav: - LogicalAnd: search/criteria_reference/price_logicaland_criterion.md - LogicalOr: search/criteria_reference/price_logicalor_criterion.md - Product: search/criteria_reference/price_product_criterion.md - - URL Search Criteria: - - URL Search Criteria: search/url_search_reference/url_search_criteria.md - - MatchAll Criterion: search/url_search_reference/matchall_url_criterion.md - - MatchNone Criterion: search/url_search_reference/matchnone_url_criterion.md - - Pattern Criterion: search/url_search_reference/pattern_url_criterion.md - - SectionId Criterion: search/url_search_reference/sectionid_url_criterion.md - - SectionIdentifier Criterion: search/url_search_reference/sectionidentifier_url_criterion.md - - Validity Criterion: search/url_search_reference/validity_url_criterion.md - - VisibleOnly Criterion: search/url_search_reference/visibleonly_url_criterion.md - - LogicalAnd Criterion: search/url_search_reference/logicaland_url_criterion.md - - LogicalNot Criterion: search/url_search_reference/logicalnot_url_criterion.md - - LogicalOr Criterion: search/url_search_reference/logicalor_url_criterion.md - Activity Log Search Criteria: - Activity Log Search Criteria: search/activity_log_search_reference/activity_log_criteria.md - ActionCriterion: search/activity_log_search_reference/action_criterion.md @@ -614,10 +345,6 @@ nav: - ProductStockRange: search/criteria_reference/productstockrange_criterion.md - ProductCode: search/sort_clause_reference/productcode_sort_clause.md - ProductName: search/sort_clause_reference/productname_sort_clause.md - - URL Sort Clauses: - - URL Sort Clauses: search/url_search_reference/url_search_sort_clauses.md - - Id Sort Clause: search/url_search_reference/id_url_sort_clause.md - - Url Sort Clause: search/url_search_reference/url_url_sort_clause.md - Activity Log Sort Clauses: search/activity_log_search_reference/activity_log_sort_clauses.md - Action Configuration Sort Clauses: search/ai_actions_search_reference/action_configuration_sort_clauses.md - Aggregation reference: @@ -660,48 +387,11 @@ nav: - ProductPriceRangeAggregation: search/aggregation_reference/productpricerange_aggregation.md - ProductTypeTermAggregation: search/aggregation_reference/producttypeterm_aggregation.md - TaxonomyEntryIdAggregation: search/aggregation_reference/taxonomyentryid_aggregation.md - - Embeddings search reference: search/embeddings_reference/embeddings_reference.md - Search in trash reference: search/search_in_trash_reference.md - - Extend search: - - Create custom Search Criterion: search/extensibility/create_custom_search_criterion.md - - Create custom Sort Clause: search/extensibility/create_custom_sort_clause.md - - Create custom Aggregation: search/extensibility/create_custom_aggregation.md - - Solr document field mappers: search/extensibility/solr_document_field_mappers.md - - Index custom Elasticsearch data: search/extensibility/index_custom_elasticsearch_data.md - - Customize Elasticsearch index structure: search/extensibility/customize_elasticsearch_index_structure.md - - Manipulate Elasticsearch query: search/extensibility/manipulate_elasticsearch_query.md - - Reindex search: search/reindex_search.md - - Infrastructure and maintenance: - - Infrastructure and maintenance: infrastructure_and_maintenance/infrastructure_and_maintenance.md - - Request lifecycle: infrastructure_and_maintenance/request_lifecycle.md - - Databases: infrastructure_and_maintenance/databases.md - - Cache: - - Cache: infrastructure_and_maintenance/cache/cache.md - - HTTP cache: - - HTTP cache: infrastructure_and_maintenance/cache/http_cache/http_cache.md - - HTTP cache configuration: infrastructure_and_maintenance/cache/http_cache/http_cache_configuration.md - - Reverse proxy: infrastructure_and_maintenance/cache/http_cache/reverse_proxy.md - - Context-aware HTTP cache: infrastructure_and_maintenance/cache/http_cache/context_aware_cache.md - - Content-aware HTTP cache: infrastructure_and_maintenance/cache/http_cache/content_aware_cache.md - - Configure and customize Fastly: infrastructure_and_maintenance/cache/http_cache/fastly.md - - Persistence cache: infrastructure_and_maintenance/cache/persistence_cache.md - - Clustering: - - Clustering: infrastructure_and_maintenance/clustering/clustering.md - - Clustering with AWS S3: infrastructure_and_maintenance/clustering/clustering_with_aws_s3.md - - DevOps: infrastructure_and_maintenance/devops.md - - Backup: infrastructure_and_maintenance/backup.md - - Performance: infrastructure_and_maintenance/performance.md - - Background tasks: infrastructure_and_maintenance/background_tasks.md - - Environments: infrastructure_and_maintenance/environments.md - - Sessions: infrastructure_and_maintenance/sessions.md - - Security: - - Development security: infrastructure_and_maintenance/security/development_security.md - - Security checklist: infrastructure_and_maintenance/security/security_checklist.md - - Reporting issues: infrastructure_and_maintenance/security/reporting_issues.md - - Security advisories: infrastructure_and_maintenance/security/security_advisories.md - - Support and maintenance FAQ: infrastructure_and_maintenance/support_and_maintenance_faq.md - - Product guides: - - Product guides: product_guides/product_guides.md + - Security: + - Security checklist: infrastructure_and_maintenance/security/security_checklist.md + - Reporting issues: infrastructure_and_maintenance/security/reporting_issues.md + - Product guides: product_guides/product_guides.md - Release notes: release_notes.md theme: @@ -718,7 +408,7 @@ theme: palette: primary: 'blue grey' accent: 'deep orange' - logo: 'images/ibexa-dxp-logo.png' + logo: 'images/cohesivo-logo.png' extra: append_bootstrap: @@ -726,7 +416,7 @@ extra: - '/guidelines/resources/' - '/index.md' related_docs: - - title: 'Developer Documentation' + - title: 'Cohesivo Developer Documentation' url: '/' - title: 'User Documentation' url: '/projects/userguide' @@ -734,20 +424,19 @@ extra: url: '/projects/connect' # Global variables - site_display_name: 'Ibexa Documentation' + site_display_name: 'Cohesivo Documentation' product_name_base: 'Ibexa' product_name: 'Cohesivo' - product_name_content: 'Ibexa Content' product_name_headless: 'Ibexa Headless' product_name_exp: 'Ibexa Experience' product_name_com: 'Ibexa Commerce' + product_name_cloud: 'Ibexa Cloud' product_name_cdp: 'Raptor CDP' product_name_cdp_base: 'Raptor' product_name_connect: 'Ibexa Connect' - product_name_cloud: 'Ibexa Cloud' - product_name_oss: 'Ibexa OSS' product_name_engage: 'Qualifio' pim_product_name: 'Quable' + ai_product_name: 'Ibexa Agentic Marketing Platform' eol_versions: ['2.5', '3.3'] diff --git a/plugins.yml b/plugins.yml index 200e74b895b..fffab4243e6 100644 --- a/plugins.yml +++ b/plugins.yml @@ -9,523 +9,12 @@ plugins: j2_comment_start_string: '[[#' j2_comment_end_string: '#]]' - tags - - redirects: - redirect_maps: - 'api/field_types_reference/xmltextfield.md': 'content_management/field_types/field_type_reference/field_type_reference.md' - 'extending/extending_image_editor.md': 'content_management/images/extend_image_editor.md' - 'guide/configuration/config_connector.md': 'content_management/images/add_image_asset_from_dam.md' - 'guide/image_editor.md': 'content_management/images/configure_image_editor.md' - 'guide/images.md': 'content_management/images/images.md' - 'guide/config_back_office.md': 'administration/back_office/back_office_configuration.md' - 'guide/config_connector.md': 'content_management/images/add_image_asset_from_dam.md' - 'guide/config_dynamic.md': 'administration/configuration/dynamic_configuration.md' - 'guide/config_repository.md': 'administration/configuration/repository_configuration.md' - 'guide/configuration.md': 'administration/configuration/configuration.md' - 'guide/search/extend_solr.md': 'search/search_engines/solr_search_engine/solr_overview.md' - 'guide/search/extend_elasticsearch.md': 'search/search_engines/elasticsearch/elasticsearch_overview.md' - - 'api/public_php_api.md': 'api/php_api/php_api.md' - 'api/rest_api_usage.md': 'api/rest_api/rest_api_usage/rest_api_usage.md' - 'api/rest_api_requests.md': 'api/rest_api/rest_api_usage/rest_requests.md' - 'api/rest_api_responses.md': 'api/rest_api/rest_api_usage/rest_responses.md' - 'api/rest_api_testing.md': 'api/rest_api/rest_api_usage/testing_rest_api.md' - 'api/rest_api_extension_media_type.md': 'api/rest_api/extending_rest_api/adding_custom_media_type.md' - 'api/rest_api_extension_resource.md': 'api/rest_api/extending_rest_api/creating_new_rest_resource.md' - 'api/rest_api_authentication.md': 'api/rest_api/rest_api_authentication.md' - 'api/graphql.md': 'api/graphql/graphql.md' - 'api/graphql_queries.md': 'api/graphql/graphql_queries.md' - 'api/graphql_operations.md': 'api/graphql/graphql_operations.md' - 'api/graphql_customization.md': 'api/graphql/graphql_customization.md' - - 'guide/repository/event_reference/event_reference.md': 'api/event_reference/event_reference.md' - 'guide/repository/event_reference/content_events.md': 'api/event_reference/content_events.md' - 'guide/repository/event_reference/content_type_events.md': 'api/event_reference/content_type_events.md' - 'guide/repository/event_reference/location_events.md': 'api/event_reference/location_events.md' - 'guide/repository/event_reference/language_events.md': 'api/event_reference/language_events.md' - 'guide/repository/event_reference/section_events.md': 'api/event_reference/section_events.md' - 'guide/repository/event_reference/object_state_events.md': 'api/event_reference/object_state_events.md' - 'guide/repository/event_reference/role_events.md': 'api/event_reference/role_events.md' - 'guide/repository/event_reference/user_events.md': 'api/event_reference/user_events.md' - 'guide/repository/event_reference/page_events.md': 'api/event_reference/page_events.md' - 'guide/repository/event_reference/site_events.md': 'api/event_reference/site_events.md' - 'guide/repository/event_reference/shop_events.md': 'api/event_reference/event_reference.md' - 'guide/repository/event_reference/url_events.md': 'api/event_reference/url_events.md' - 'guide/repository/event_reference/trash_events.md': 'api/event_reference/trash_events.md' - 'guide/repository/event_reference/other_events.md': 'api/event_reference/other_events.md' - - 'guide/project_organization.md': 'administration/project_organization/project_organization.md' - 'guide/architecture.md': 'administration/project_organization/architecture.md' - 'guide/bundles.md': 'administration/project_organization/bundles.md' - 'guide/admin_panel.md': 'administration/admin_panel/admin_panel.md' - 'administration/admin_panel.md': 'administration/admin_panel/admin_panel.md' - 'guide/configuration/configuration.md': 'administration/configuration/configuration.md' - 'guide/configuration/config_dynamic.md': 'administration/configuration/dynamic_configuration.md' - 'guide/configuration/config_repository.md': 'administration/configuration/repository_configuration.md' - - 'extending/extending_back_office.md': 'administration/back_office/back_office.md' - 'extending/config_back_office.md': 'administration/back_office/back_office_configuration.md' - 'extending/content_tree.md': 'administration/back_office/content_tree.md' - 'extending/reusable_back_office_templates.md': 'administration/back_office/back_office_elements/reusable_components.md' - 'extending/creating_custom_dropdowns.md': 'administration/back_office/back_office_elements/add_dropdowns.md' - 'extending/custom_icons.md': 'administration/back_office/back_office_elements/custom_icons.md' - 'extending/drag_and_drop.md': 'administration/back_office/back_office_elements/add_drag_and_drop.md' - 'extending/custom_components.md': 'administration/back_office/back_office_elements/custom_components.md' - 'extending/extending_date_and_time.md': 'administration/back_office/back_office_elements/formatting_date_and_time.md' - 'extending/extending_thumbnails.md': 'administration/back_office/back_office_elements/extending_thumbnails.md' - 'extending/import_assets_from_bundle.md': 'administration/back_office/back_office_elements/importing_assets_from_bundle.md' - 'extending/tabs/back_office_tabs.md': 'administration/back_office/back_office_tabs/back_office_tabs.md' - 'extending/tabs/add_dashboard_tab.md': 'administration/back_office/back_office_tabs/create_dashboard_tab.md' - 'extending/menus/back_office_menus.md': 'administration/back_office/back_office_menus/back_office_menus.md' - 'extending/menus/add_menu_item.md': 'administration/back_office/back_office_menus/add_menu_item.md' - 'extending/add_user_setting.md': 'administration/back_office/add_user_setting.md' - 'extending/customize_calendar.md': 'administration/back_office/customize_calendar.md' - 'extending/extending_udw.md': 'administration/back_office/browser/browser.md' - 'extending/add_udw_tab.md': 'administration/back_office/browser/add_browser_tab.md' - 'extending/extending_multifile_upload.md': 'administration/back_office/multifile_upload.md' - 'extending/extending_subitems_list.md': 'administration/back_office/subitems_list.md' - 'guide/sending_notifications.md': 'administration/back_office/notifications.md' - - 'guide/content_management.md': 'content_management/content_model.md' - 'guide/content_model.md': 'content_management/content_model.md' - 'guide/taxonomy/taxonomy.md': 'content_management/taxonomy/taxonomy.md' - 'guide/images/images.md': 'content_management/images/images.md' - 'guide/images/image_editor.md': 'content_management/images/configure_image_editor.md' - 'guide/images/extending_image_editor.md': 'content_management/images/extend_image_editor.md' - 'guide/images/config_connector.md': 'content_management/images/add_image_asset_from_dam.md' - 'extending/extending_online_editor.md': 'content_management/rich_text/extend_online_editor.md' - 'extending/richtext_block.md': 'content_management/rich_text/create_custom_richtext_block.md' - 'guide/file_management/file_management.md': 'content_management/file_management/file_management.md' - 'guide/file_management/binary_media_download.md': 'content_management/file_management/binary_and_media_download.md' - 'guide/file_management/handling_file_url.md': 'content_management/file_management/file_url_handling.md' - 'guide/page/page_blocks.md': 'content_management/pages/page_blocks.md' - 'guide/page/page_block_attributes.md': 'content_management/pages/page_block_attributes.md' - 'guide/page/page_block_validators.md': 'content_management/pages/page_block_validators.md' - 'guide/page/create_custom_page_block.md': 'content_management/pages/create_custom_page_block.md' - 'guide/form_builder/forms.md': 'content_management/forms/forms.md' - 'api/public_php_api_managing_forms.md': 'content_management/forms/form_api.md' - 'ibexa_products/experience.md': 'ibexa_products/ibexa_experience.md' - 'ibexa_products/headless.md': 'ibexa_products/ibexa_headless.md' - 'personalization/personalization_brochure.md': 'recommendations/raptor_integration/raptor_connector_guide.md' - 'guide/form_builder/create_custom_form_field.md': 'content_management/forms/create_custom_form_field.md' - 'guide/form_builder/customize_email_notifications.md': 'content_management/forms/customize_email_notifications.md' - 'guide/workflow/workflow.md': 'content_management/workflow/workflow.md' - 'guide/workflow/add_custom_workflow_action.md': 'content_management/workflow/add_custom_workflow_action.md' - 'guide/url_management.md': 'content_management/url_management/url_management.md' - 'api/public_php_api_url_service.md': 'content_management/url_management/url_api.md' - 'guide/user_generated_content.md': 'content_management/user_generated_content.md' - - 'api/public_php_api_browsing.md': 'content_management/content_api/browsing_content.md' - 'api/public_php_api_creating_content.md': 'content_management/content_api/creating_content.md' - 'api/public_php_api_managing_content.md': 'content_management/content_api/managing_content.md' - - 'guide/data_migration/data_migration.md': 'content_management/data_migration/data_migration.md' - 'guide/data_migration/importing_data.md': 'content_management/data_migration/importing_data.md' - 'guide/data_migration/exporting_data.md': 'content_management/data_migration/exporting_data.md' - 'guide/data_migration/migration_management.md': 'content_management/data_migration/managing_migrations.md' - 'guide/data_migration/data_migration_actions.md': 'content_management/data_migration/data_migration_actions.md' - 'guide/data_migration/create_migration_action.md': 'content_management/data_migration/create_data_migration_action.md' - 'guide/data_migration/create_migration_step.md': 'content_management/data_migration/create_data_migration_step.md' - 'guide/data_migration/add_data_migration_matcher.md': 'content_management/data_migration/add_data_migration_matcher.md' - 'api/public_php_api_managing_migrations.md': 'content_management/data_migration/data_migration_api.md' - 'api/field_type_api.md': 'content_management/field_types/field_types.md' - 'api/field_type_type_and_value.md': 'content_management/field_types/type_and_value.md' - 'api/field_type_form_and_template.md': 'content_management/field_types/form_and_template.md' - 'api/field_type_storage.md': 'content_management/field_types/field_type_storage.md' - 'api/field_type_validation.md': 'content_management/field_types/field_type_validation.md' - 'api/field_type_search.md': 'content_management/field_types/field_type_search.md' - 'api/field_type/create_custom_generic_field_type.md': 'content_management/field_types/create_custom_generic_field_type.md' - 'api/field_type/create_custom_field_type_comparison.md': 'content_management/field_types/create_custom_field_type_comparison.md' - 'api/field_type_reference.md': 'content_management/field_types/field_type_reference/field_type_reference.md' - 'api/field_types_reference/authorfield.md': 'content_management/field_types/field_type_reference/authorfield.md' - 'api/field_types_reference/binaryfilefield.md': 'content_management/field_types/field_type_reference/binaryfilefield.md' - 'api/field_types_reference/checkboxfield.md': 'content_management/field_types/field_type_reference/checkboxfield.md' - 'api/field_types_reference/contentqueryfield.md': 'content_management/field_types/field_type_reference/contentqueryfield.md' - 'api/field_types_reference/countryfield.md': 'content_management/field_types/field_type_reference/countryfield.md' - 'api/field_types_reference/customergroupfield.md': 'content_management/field_types/field_type_reference/customergroupfield.md' - 'api/field_types_reference/dateandtimefield.md': 'content_management/field_types/field_type_reference/dateandtimefield.md' - 'api/field_types_reference/datefield.md': 'content_management/field_types/field_type_reference/datefield.md' - 'api/field_types_reference/emailaddressfield.md': 'content_management/field_types/field_type_reference/emailaddressfield.md' - 'api/field_types_reference/floatfield.md': 'content_management/field_types/field_type_reference/floatfield.md' - 'api/field_types_reference/formfield.md': 'content_management/field_types/field_type_reference/formfield.md' - 'api/field_types_reference/imagefield.md': 'content_management/field_types/field_type_reference/imagefield.md' - 'api/field_types_reference/imageassetfield.md': 'content_management/field_types/field_type_reference/imageassetfield.md' - 'api/field_types_reference/integerfield.md': 'content_management/field_types/field_type_reference/integerfield.md' - 'api/field_types_reference/isbnfield.md': 'content_management/field_types/field_type_reference/isbnfield.md' - 'api/field_types_reference/keywordfield.md': 'content_management/field_types/field_type_reference/keywordfield.md' - 'api/field_types_reference/maplocationfield.md': 'content_management/field_types/field_type_reference/maplocationfield.md' - 'api/field_types_reference/matrixfield.md': 'content_management/field_types/field_type_reference/matrixfield.md' - 'api/field_types_reference/measurementfield.md': 'content_management/field_types/field_type_reference/measurementfield.md' - 'api/field_types_reference/mediafield.md': 'content_management/field_types/field_type_reference/mediafield.md' - 'api/field_types_reference/nullfield.md': 'content_management/field_types/field_type_reference/nullfield.md' - 'api/field_types_reference/pagefield.md': 'content_management/field_types/field_type_reference/pagefield.md' - 'api/field_types_reference/relationfield.md': 'content_management/field_types/field_type_reference/relationfield.md' - 'api/field_types_reference/relationlistfield.md': 'content_management/field_types/field_type_reference/relationlistfield.md' - 'api/field_types_reference/richtextfield.md': 'content_management/field_types/field_type_reference/richtextfield.md' - 'api/field_types_reference/selectionfield.md': 'content_management/field_types/field_type_reference/selectionfield.md' - 'api/field_types_reference/sesexternaldata.md': 'content_management/field_types/field_type_reference/field_type_reference.md' - 'content_management/field_types/field_type_reference/sesexternaldata.md': 'content_management/field_types/field_type_reference/field_type_reference.md' - 'api/field_types_reference/sesprofiledata.md': 'content_management/field_types/field_type_reference/field_type_reference.md' - 'content_management/field_types/field_type_reference/sesprofiledata.md': 'content_management/field_types/field_type_reference/field_type_reference.md' - 'api/field_types_reference/sesselection.md': 'content_management/field_types/field_type_reference/productspecificationfield.md' - 'content_management/field_types/field_type_reference/sesselection.md': 'content_management/field_types/field_type_reference/productspecificationfield.md' - 'api/field_types_reference/specificationstype.md': 'content_management/field_types/field_type_reference/productspecificationfield.md' - 'content_management/field_types/field_type_reference/specificationstype.md': 'content_management/field_types/field_type_reference/productspecificationfield.md' - 'api/field_types_reference/textblockfield.md': 'content_management/field_types/field_type_reference/textblockfield.md' - 'api/field_types_reference/textlinefield.md': 'content_management/field_types/field_type_reference/textlinefield.md' - 'api/field_types_reference/timefield.md': 'content_management/field_types/field_type_reference/timefield.md' - 'api/field_types_reference/urlfield.md': 'content_management/field_types/field_type_reference/urlfield.md' - 'api/field_types_reference/userfield.md': 'content_management/field_types/field_type_reference/userfield.md' - - 'guide/content_rendering/render_content/render_content.md': 'templating/render_content/render_content.md' - 'guide/content_rendering/render_content/render_page.md': 'templating/render_content/render_page.md' - 'guide/content_rendering/templates/templates.md': 'templating/templates/templates.md' - 'guide/content_rendering/templates/template_configuration.md': 'templating/templates/template_configuration.md' - 'guide/content_rendering/templates/view_matcher_reference.md': 'templating/templates/view_matcher_reference.md' - 'guide/content_rendering/templates/custom_view_matcher.md': 'templating/templates/create_custom_view_matcher.md' - 'guide/content_rendering/assets.md': 'templating/assets.md' - 'guide/content_rendering/image_variations.md': 'templating/image_variations.md' - 'guide/content_rendering/urls_and_routes.md': 'templating/urls_and_routes/urls_and_routes.md' - 'guide/content_rendering/design_engine/design_engine.md': 'templating/design_engine/design_engine.md' - 'guide/content_rendering/design_engine/add_new_design.md': 'templating/design_engine/add_new_design.md' - 'guide/content_rendering/queries_and_controllers/content_queries.md': 'templating/queries_and_controllers/content_queries.md' - 'guide/content_rendering/queries_and_controllers/built-in_query_types.md': 'templating/queries_and_controllers/built-in_query_types.md' - 'guide/content_rendering/queries_and_controllers/custom_query_type.md': 'templating/queries_and_controllers/create_custom_query_type.md' - 'guide/content_rendering/queries_and_controllers/controllers.md': 'templating/queries_and_controllers/controllers.md' - 'guide/content_rendering/embed_and_list_content/list_content.md': 'templating/embed_and_list_content/list_content.md' - 'guide/content_rendering/embed_and_list_content/embed_content.md': 'templating/embed_and_list_content/embed_content.md' - 'guide/content_rendering/embed_and_list_content/render_images.md': 'templating/embed_and_list_content/render_images.md' - 'guide/content_rendering/layout/add_breadcrumbs.md': 'templating/layout/add_breadcrumbs.md' - 'guide/content_rendering/layout/add_forgot_password.md': 'templating/layout/add_forgot_password_option.md' - 'guide/content_rendering/layout/add_login_form.md': 'templating/layout/add_login_form.md' - 'guide/content_rendering/layout/add_menu.md': 'templating/layout/add_navigation_menu.md' - 'guide/content_rendering/layout/add_search_form.md': 'templating/layout/add_search_form.md' - 'guide/content_rendering/layout/add_register_user_template.md': 'customer_management/create_user_registration_form.md' - 'guide/content_rendering/layout/customize_basket.md': 'templating/layout/add_search_form.md' - - 'guide/catalog/catalog.md': 'product_catalog/product_catalog.md' - 'guide/catalog/catalog_configuration.md': 'product_catalog/product_catalog_configuration.md' - 'api/public_php_api_managing_catalog.md': 'product_catalog/product_api.md' - 'guide/catalog/enable_purchasing_products.md': 'product_catalog/enable_purchasing_products.md' - 'guide/catalog/create_custom_attribute_type.md': 'product_catalog/create_custom_attribute_type.md' - 'guide/pricing/price_engine.md': 'product_catalog/prices.md' - 'api/public_php_api_managing_prices.md': 'product_catalog/price_api.md' - 'guide/bestsellers.md': 'product_catalog/product_catalog.md' - 'pim/bestsellers.md': 'product_catalog/product_catalog.md' - - 'pim/pim.md': 'product_catalog/product_catalog.md' - 'pim/pim_guide.md': 'product_catalog/product_catalog_guide.md' - 'pim/pim_configuration.md': 'product_catalog/product_catalog_configuration.md' - 'pim/products.md': 'product_catalog/products.md' - 'pim/attributes/date_and_time.md': 'product_catalog/attributes/date_and_time.md' - 'pim/attributes/symbol_attribute_type.md': 'product_catalog/attributes/symbol_attribute_type.md' - 'pim/product_api.md': 'product_catalog/product_api.md' - 'pim/catalogs.md': 'product_catalog/catalogs.md' - 'pim/catalog_api.md': 'product_catalog/catalog_api.md' - 'pim/enable_purchasing_products.md': 'product_catalog/enable_purchasing_products.md' - 'pim/prices.md': 'product_catalog/prices.md' - 'pim/price_api.md': 'product_catalog/price_api.md' - 'pim/customize_pim.md': 'product_catalog/customize_product_catalog.md' - 'pim/create_custom_attribute_type.md': 'product_catalog/create_custom_attribute_type.md' - 'pim/create_product_code_generator.md': 'product_catalog/create_product_code_generator.md' - 'pim/create_custom_catalog_filter.md': 'product_catalog/create_custom_catalog_filter.md' - 'pim/create_custom_name_schema_strategy.md': 'product_catalog/create_custom_name_schema_strategy.md' - 'pim/add_remote_pim_support.md': 'product_catalog/add_remote_pim_support.md' - - - 'guide/multisite/multisite.md': 'multisite/multisite.md' - 'guide/multisite/multisite_configuration.md': 'multisite/multisite_configuration.md' - 'guide/multisite/set_up_campaign_siteaccess.md': 'multisite/set_up_campaign_siteaccess.md' - 'guide/multisite/set_up_translation_siteaccess.md': 'multisite/set_up_translation_siteaccess.md' - 'guide/multisite/site_factory.md': 'multisite/site_factory/site_factory.md' - 'guide/multisite/site_factory_configuration.md': 'multisite/site_factory/site_factory_configuration.md' - 'guide/multisite/siteaccess_matching.md': 'multisite/siteaccess/siteaccess_matching.md' - 'guide/multisite/injecting_siteaccess.md': 'multisite/siteaccess/injecting_siteaccess.md' - 'guide/multisite/siteaccess_aware_configuration.md': 'multisite/siteaccess/siteaccess_aware_configuration.md' - 'guide/internationalization.md': 'multisite/languages/languages.md' - 'guide/back_office_translations.md': 'multisite/languages/back_office_translations.md' - 'guide/shop_translations.md': 'multisite/languages/languages.md' - - 'guide/permissions.md': 'permissions/permissions.md' - 'guide/permission_use_cases.md': 'permissions/permission_use_cases.md' - 'guide/limitations.md': 'permissions/limitations.md' - 'guide/limitation_reference.md': 'permissions/limitation_reference.md' - 'guide/custom_policies.md': 'permissions/custom_policies.md' - - 'guide/user_management/user_management.md': 'users/users.md' - 'api/public_php_api_managing_users.md': 'users/segment_api.md' - 'guide/user_management/customer_groups.md': 'users/customer_groups.md' - 'guide/user_management/login_and_registration.md': 'users/users.md' - 'users/login_and_registration.md': 'users/users.md' - 'users/user_management.md': 'users/users.md' - 'guide/user_management/oauth.md': 'users/oauth_client.md' - 'users/oauth_authentication.md': 'users/oauth_client.md' - 'guide/user_management/login_via_external_service.md': 'users/oauth_client.md' - 'users/add_login_through_external_service.md': 'users/oauth_client.md' - 'guide/user_management/token.md': 'users/users.md' - 'users/token.md': 'users/users.md' - 'guide/customers/customers.md': 'users/users.md' - 'users/customers/customers.md': 'users/users.md' - 'guide/customers/customer_api/customer_api.md': 'users/users.md' - 'users/customers/customer_api.md': 'users/users.md' - 'guide/customers/customer_api/customer_profile_data.md': 'users/users.md' - 'users/customers/customer_profile_data.md': 'users/users.md' - 'guide/customers/customer_api/configuration_for_customer_data.md': 'users/users.md' - 'users/customers/customer_data_configuration.md': 'users/users.md' - 'guide/personalization/personalization.md': 'recommendations/raptor_integration/raptor_connector.md' - 'guide/personalization/enabling_personalization.md': 'recommendations/raptor_integration/connector_installation_configuration.md' - 'guide/personalization/basic_integration.md': 'recommendations/raptor_integration/raptor_connector.md' - 'guide/personalization/developer_guide/tracking_api.md': 'recommendations/raptor_integration/raptor_connector.md' - 'guide/personalization/developer_guide/importing_historical_user_tracking_data.md': 'recommendations/raptor_integration/tracking_functions.md' - 'guide/personalization/developer_guide/tracking_with_ibexa-tracker.md': 'recommendations/raptor_integration/tracking_functions.md' - 'guide/personalization/developer_guide/recommendation_api.md': 'recommendations/raptor_integration/raptor_connector.md' - 'guide/personalization/developer_guide/content_api.md': 'recommendations/raptor_integration/raptor_connector.md' - 'guide/personalization/developer_guide/user_api.md': 'recommendations/raptor_integration/raptor_connector.md' - 'guide/personalization/developer_guide/attributes_search_elastic.md': 'recommendations/raptor_integration/raptor_connector.md' - 'guide/personalization/best_practices/tracking_integration.md': 'recommendations/raptor_integration/tracking_functions.md' - 'guide/personalization/best_practices/recommendation_integration.md': 'recommendations/raptor_integration/recommendation_blocks.md' - - 'personalization/personalization.md': 'recommendations/raptor_integration/raptor_connector.md' - 'personalization/personalization_guide.md': 'recommendations/raptor_integration/raptor_connector_guide.md' - 'personalization/how_it_works.md': 'recommendations/raptor_integration/raptor_connector.md' - 'personalization/enable_personalization.md': 'recommendations/raptor_integration/connector_installation_configuration.md' - 'personalization/integrate_recommendation_service.md': 'recommendations/raptor_integration/raptor_connector.md' - 'personalization/tracking_integration.md': 'recommendations/raptor_integration/tracking_functions.md' - 'personalization/recommendation_integration.md': 'recommendations/raptor_integration/recommendation_blocks.md' - 'personalization/api_reference/api_reference.md': 'recommendations/raptor_integration/raptor_connector.md' - 'personalization/api_reference/content_api.md': 'recommendations/raptor_integration/raptor_connector.md' - 'personalization/api_reference/recommendation_api.md': 'recommendations/raptor_integration/raptor_connector.md' - 'personalization/api_reference/tracking_api.md': 'recommendations/raptor_integration/raptor_connector.md' - 'personalization/api_reference/user_api.md': 'recommendations/raptor_integration/raptor_connector.md' - 'personalization/importing_historical_user_tracking_data.md': 'recommendations/raptor_integration/tracking_functions.md' - 'personalization/tracking_with_ibexa-tracker.md': 'recommendations/raptor_integration/tracking_functions.md' - 'personalization/attribute_search_in_elasticsearch.md': 'recommendations/raptor_integration/raptor_connector.md' - 'personalization/legacy_recommendation_api.md': 'recommendations/raptor_integration/raptor_connector.md' - - 'guide/search/search.md': 'search/search.md' - 'guide/search/elastic.md': 'search/search_engines/elasticsearch/elasticsearch_overview.md' - 'guide/search/solr.md': 'search/search_engines/solr_search_engine/solr_overview.md' - 'api/public_php_api_search.md': 'search/search_api.md' - 'guide/search/criteria_reference/search_criteria_reference.md': 'search/criteria_reference/search_criteria_reference.md' - 'guide/search/criteria_reference/ancestor_criterion.md': 'search/criteria_reference/ancestor_criterion.md' - 'guide/search/criteria_reference/contentid_criterion.md': 'search/criteria_reference/contentid_criterion.md' - 'guide/search/criteria_reference/contenttypegroupid_criterion.md': 'search/criteria_reference/contenttypegroupid_criterion.md' - 'guide/search/criteria_reference/contenttypeid_criterion.md': 'search/criteria_reference/contenttypeid_criterion.md' - 'guide/search/criteria_reference/contenttypeidentifier_criterion.md': 'search/criteria_reference/contenttypeidentifier_criterion.md' - 'guide/search/criteria_reference/currencycode_criterion.md': 'search/criteria_reference/currencycode_criterion.md' - 'guide/search/criteria_reference/customergroupid_criterion.md': 'search/criteria_reference/customergroupid_criterion.md' - 'guide/search/criteria_reference/datemetadata_criterion.md': 'search/criteria_reference/datemetadata_criterion.md' - 'guide/search/criteria_reference/depth_criterion.md': 'search/criteria_reference/depth_criterion.md' - 'guide/search/criteria_reference/field_criterion.md': 'search/criteria_reference/field_criterion.md' - 'guide/search/criteria_reference/fieldrelation_criterion.md': 'search/criteria_reference/fieldrelation_criterion.md' - 'guide/search/criteria_reference/fulltext_criterion.md': 'search/criteria_reference/fulltext_criterion.md' - 'guide/search/criteria_reference/iscurrencyenabled_criterion.md': 'search/criteria_reference/iscurrencyenabled_criterion.md' - 'guide/search/criteria_reference/isfieldempty_criterion.md': 'search/criteria_reference/isfieldempty_criterion.md' - 'guide/search/criteria_reference/ismainlocation_criterion.md': 'search/criteria_reference/ismainlocation_criterion.md' - 'guide/search/criteria_reference/isproductbased_criterion.md': 'search/criteria_reference/isproductbased_criterion.md' - 'guide/search/criteria_reference/isuserbased_criterion.md': 'search/criteria_reference/isuserbased_criterion.md' - 'guide/search/criteria_reference/isuserenabled_criterion.md': 'search/criteria_reference/isuserenabled_criterion.md' - 'guide/search/criteria_reference/languagecode_criterion.md': 'search/criteria_reference/languagecode_criterion.md' - 'guide/search/criteria_reference/locationid_criterion.md': 'search/criteria_reference/locationid_criterion.md' - 'guide/search/criteria_reference/locationremoteid_criterion.md': 'search/criteria_reference/locationremoteid_criterion.md' - 'guide/search/criteria_reference/maplocationdistance_criterion.md': 'search/criteria_reference/maplocationdistance_criterion.md' - 'guide/search/criteria_reference/matchall_criterion.md': 'search/criteria_reference/matchall_criterion.md' - 'guide/search/criteria_reference/matchnone_criterion.md': 'search/criteria_reference/matchnone_criterion.md' - 'guide/search/criteria_reference/objectstateid_criterion.md': 'search/criteria_reference/objectstateid_criterion.md' - 'guide/search/criteria_reference/objectstateidentifier_criterion.md': 'search/criteria_reference/objectstateidentifier_criterion.md' - 'guide/search/criteria_reference/parentlocationid_criterion.md': 'search/criteria_reference/parentlocationid_criterion.md' - 'guide/search/criteria_reference/priority_criterion.md': 'search/criteria_reference/priority_criterion.md' - 'guide/search/criteria_reference/remoteid_criterion.md': 'search/criteria_reference/remoteid_criterion.md' - 'guide/search/criteria_reference/sectionid_criterion.md': 'search/criteria_reference/sectionid_criterion.md' - 'guide/search/criteria_reference/sectionidentifier_criterion.md': 'search/criteria_reference/sectionidentifier_criterion.md' - 'guide/search/criteria_reference/sibling_criterion.md': 'search/criteria_reference/sibling_criterion.md' - 'guide/search/criteria_reference/subtree_criterion.md': 'search/criteria_reference/subtree_criterion.md' - 'guide/search/criteria_reference/useremail_criterion.md': 'search/criteria_reference/useremail_criterion.md' - 'guide/search/criteria_reference/userid_criterion.md': 'search/criteria_reference/userid_criterion.md' - 'guide/search/criteria_reference/userlogin_criterion.md': 'search/criteria_reference/userlogin_criterion.md' - 'guide/search/criteria_reference/usermetadata_criterion.md': 'search/criteria_reference/usermetadata_criterion.md' - 'guide/search/criteria_reference/visibility_criterion.md': 'search/criteria_reference/visibility_criterion.md' - 'guide/search/criteria_reference/logicaland_criterion.md': 'search/criteria_reference/logicaland_criterion.md' - 'guide/search/criteria_reference/logicalnot_criterion.md': 'search/criteria_reference/logicalnot_criterion.md' - 'guide/search/criteria_reference/logicalor_criterion.md': 'search/criteria_reference/logicalor_criterion.md' - 'guide/search/criteria_reference/baseprice_criterion.md': 'search/criteria_reference/baseprice_criterion.md' - 'guide/search/criteria_reference/checkboxattribute_criterion.md': 'search/criteria_reference/checkboxattribute_criterion.md' - 'guide/search/criteria_reference/colorattribute_criterion.md': 'search/criteria_reference/colorattribute_criterion.md' - 'guide/search/criteria_reference/createdat_criterion.md': 'search/criteria_reference/createdat_criterion.md' - 'guide/search/criteria_reference/createdatrange_criterion.md': 'search/criteria_reference/createdatrange_criterion.md' - 'guide/search/criteria_reference/customprice_criterion.md': 'search/criteria_reference/customprice_criterion.md' - 'guide/search/criteria_reference/floatattribute_criterion.md': 'search/criteria_reference/floatattribute_criterion.md' - 'guide/search/criteria_reference/integerattribute_criterion.md': 'search/criteria_reference/integerattribute_criterion.md' - 'guide/search/criteria_reference/productavailability_criterion.md': 'search/criteria_reference/productavailability_criterion.md' - 'guide/search/criteria_reference/productcategory_criterion.md': 'search/criteria_reference/productcategory_criterion.md' - 'guide/search/criteria_reference/productcode_criterion.md': 'search/criteria_reference/productcode_criterion.md' - 'guide/search/criteria_reference/productname_criterion.md': 'search/criteria_reference/productname_criterion.md' - 'guide/search/criteria_reference/producttype_criterion.md': 'search/criteria_reference/producttype_criterion.md' - 'guide/search/criteria_reference/selectionattribute_criterion.md': 'search/criteria_reference/selectionattribute_criterion.md' - 'guide/search/sort_clause_reference/sort_clause_reference.md': 'search/sort_clause_reference/sort_clause_reference.md' - 'guide/search/sort_clause_reference/contentid_sort_clause.md': 'search/sort_clause_reference/contentid_sort_clause.md' - 'guide/search/sort_clause_reference/contentname_sort_clause.md': 'search/sort_clause_reference/contentname_sort_clause.md' - 'guide/search/sort_clause_reference/contenttranslatedname_sort_clause.md': 'search/sort_clause_reference/contenttranslatedname_sort_clause.md' - 'guide/search/sort_clause_reference/contenttypename_sort_clause.md': 'search/sort_clause_reference/contenttypename_sort_clause.md' - 'guide/search/sort_clause_reference/customfield_sort_clause.md': 'search/sort_clause_reference/customfield_sort_clause.md' - 'guide/search/sort_clause_reference/datemodified_sort_clause.md': 'search/sort_clause_reference/datemodified_sort_clause.md' - 'guide/search/sort_clause_reference/datepublished_sort_clause.md': 'search/sort_clause_reference/datepublished_sort_clause.md' - 'guide/search/sort_clause_reference/datetrashed_sort_clause.md': 'search/sort_clause_reference/datetrashed_sort_clause.md' - 'guide/search/sort_clause_reference/depth_sort_clause.md': 'search/sort_clause_reference/depth_sort_clause.md' - 'guide/search/sort_clause_reference/field_sort_clause.md': 'search/sort_clause_reference/field_sort_clause.md' - 'guide/search/sort_clause_reference/id_sort_clause.md': 'search/sort_clause_reference/id_sort_clause.md' - 'guide/search/sort_clause_reference/ismainlocation_sort_clause.md': 'search/sort_clause_reference/ismainlocation_sort_clause.md' - 'guide/search/sort_clause_reference/maplocationdistance_sort_clause.md': 'search/sort_clause_reference/maplocationdistance_sort_clause.md' - 'guide/search/sort_clause_reference/path_sort_clause.md': 'search/sort_clause_reference/path_sort_clause.md' - 'guide/search/sort_clause_reference/priority_sort_clause.md': 'search/sort_clause_reference/priority_sort_clause.md' - 'guide/search/sort_clause_reference/random_sort_clause.md': 'search/sort_clause_reference/random_sort_clause.md' - 'guide/search/sort_clause_reference/score_sort_clause.md': 'search/sort_clause_reference/score_sort_clause.md' - 'guide/search/sort_clause_reference/sectionidentifier_sort_clause.md': 'search/sort_clause_reference/sectionidentifier_sort_clause.md' - 'guide/search/sort_clause_reference/sectionname_sort_clause.md': 'search/sort_clause_reference/sectionname_sort_clause.md' - 'guide/search/sort_clause_reference/userlogin_sort_clause.md': 'search/sort_clause_reference/userlogin_sort_clause.md' - 'guide/search/sort_clause_reference/visibility_sort_clause.md': 'search/sort_clause_reference/visibility_sort_clause.md' - 'guide/search/sort_clause_reference/createdat_sort_clause.md': 'search/sort_clause_reference/createdat_sort_clause.md' - 'guide/search/sort_clause_reference/productavailability_sort_clause.md': 'search/sort_clause_reference/productavailability_sort_clause.md' - 'guide/search/sort_clause_reference/productcode_sort_clause.md': 'search/sort_clause_reference/productcode_sort_clause.md' - 'guide/search/sort_clause_reference/productname_sort_clause.md': 'search/sort_clause_reference/productname_sort_clause.md' - 'guide/search/aggregation_reference/aggregation_reference.md': 'search/aggregation_reference/aggregation_reference.md' - 'guide/search/aggregation_reference/contenttypeterm_aggregation.md': 'search/aggregation_reference/contenttypeterm_aggregation.md' - 'guide/search/aggregation_reference/contenttypegroupterm_aggregation.md': 'search/aggregation_reference/contenttypegroupterm_aggregation.md' - 'guide/search/aggregation_reference/datemetadatarange_aggregation.md': 'search/aggregation_reference/datemetadatarange_aggregation.md' - 'guide/search/aggregation_reference/languageterm_aggregation.md': 'search/aggregation_reference/languageterm_aggregation.md' - 'guide/search/aggregation_reference/locationchildrenterm_aggregation.md': 'search/aggregation_reference/locationchildrenterm_aggregation.md' - 'guide/search/aggregation_reference/objectstateterm_aggregation.md': 'search/aggregation_reference/objectstateterm_aggregation.md' - 'guide/search/aggregation_reference/rawrange_aggregation.md': 'search/aggregation_reference/rawrange_aggregation.md' - 'guide/search/aggregation_reference/rawstats_aggregation.md': 'search/aggregation_reference/rawstats_aggregation.md' - 'guide/search/aggregation_reference/rawterm_aggregation.md': 'search/aggregation_reference/rawterm_aggregation.md' - 'guide/search/aggregation_reference/sectionterm_aggregation.md': 'search/aggregation_reference/sectionterm_aggregation.md' - 'guide/search/aggregation_reference/subtreeterm_aggregation.md': 'search/aggregation_reference/subtreeterm_aggregation.md' - 'guide/search/aggregation_reference/usermetadataterm_aggregation.md': 'search/aggregation_reference/usermetadataterm_aggregation.md' - 'guide/search/aggregation_reference/visibilityterm_aggregation.md': 'search/aggregation_reference/visibilityterm_aggregation.md' - 'guide/search/aggregation_reference/authorterm_aggregation.md': 'search/aggregation_reference/authorterm_aggregation.md' - 'guide/search/aggregation_reference/checkboxterm_aggregation.md': 'search/aggregation_reference/checkboxterm_aggregation.md' - 'guide/search/aggregation_reference/countryterm_aggregation.md': 'search/aggregation_reference/countryterm_aggregation.md' - 'guide/search/aggregation_reference/daterange_aggregation.md': 'search/aggregation_reference/daterange_aggregation.md' - 'guide/search/aggregation_reference/datetimerange_aggregation.md': 'search/aggregation_reference/datetimerange_aggregation.md' - 'guide/search/aggregation_reference/floatrange_aggregation.md': 'search/aggregation_reference/floatrange_aggregation.md' - 'guide/search/aggregation_reference/floatstats_aggregation.md': 'search/aggregation_reference/floatstats_aggregation.md' - 'guide/search/aggregation_reference/integerrange_aggregation.md': 'search/aggregation_reference/integerrange_aggregation.md' - 'guide/search/aggregation_reference/integerstats_aggregation.md': 'search/aggregation_reference/integerstats_aggregation.md' - 'guide/search/aggregation_reference/keywordterm_aggregation.md': 'search/aggregation_reference/keywordterm_aggregation.md' - 'guide/search/aggregation_reference/selectionterm_aggregation.md': 'search/aggregation_reference/selectionterm_aggregation.md' - 'guide/search/aggregation_reference/timerange_aggregation.md': 'search/aggregation_reference/timerange_aggregation.md' - 'guide/search/url_search_reference/url_search_reference.md': 'search/url_search_reference/url_search_criteria.md' - 'search/url_search_reference/url_search_reference.md': 'search/url_search_reference/url_search_criteria.md' - 'guide/search/url_search_reference/id_url_sort_clause.md': 'search/url_search_reference/id_url_sort_clause.md' - 'guide/search/url_search_reference/url_url_sort_clause.md': 'search/url_search_reference/url_url_sort_clause.md' - 'guide/search/url_search_reference/matchall_url_criterion.md': 'search/url_search_reference/matchall_url_criterion.md' - 'guide/search/url_search_reference/matchnone_url_criterion.md': 'search/url_search_reference/matchnone_url_criterion.md' - 'guide/search/url_search_reference/pattern_url_criterion.md': 'search/url_search_reference/pattern_url_criterion.md' - 'guide/search/url_search_reference/sectionid_url_criterion.md': 'search/url_search_reference/sectionid_url_criterion.md' - 'guide/search/url_search_reference/sectionidentifier_url_criterion.md': 'search/url_search_reference/sectionidentifier_url_criterion.md' - 'guide/search/url_search_reference/validity_url_criterion.md': 'search/url_search_reference/validity_url_criterion.md' - 'guide/search/url_search_reference/visibleonly_url_criterion.md': 'search/url_search_reference/visibleonly_url_criterion.md' - 'guide/search/url_search_reference/logicaland_url_criterion.md': 'search/url_search_reference/logicaland_url_criterion.md' - 'guide/search/url_search_reference/logicalnot_url_criterion.md': 'search/url_search_reference/logicalnot_url_criterion.md' - 'guide/search/url_search_reference/logicalor_url_criterion.md': 'search/url_search_reference/logicalor_url_criterion.md' - 'guide/search/search_in_trash_reference.md': 'search/search_in_trash_reference.md' - 'guide/search/extensibility/create_custom_search_criterion.md': 'search/extensibility/create_custom_search_criterion.md' - 'guide/search/extensibility/create_custom_sort_clause.md': 'search/extensibility/create_custom_sort_clause.md' - 'guide/search/extensibility/create_custom_aggregation.md': 'search/extensibility/create_custom_aggregation.md' - 'guide/search/extensibility/solr_document_field_mappers.md': 'search/extensibility/solr_document_field_mappers.md' - 'guide/search/extensibility/index_custom_elasticsearch_data.md': 'search/extensibility/index_custom_elasticsearch_data.md' - 'guide/search/extensibility/manipulate_elasticsearch_query.md': 'search/extensibility/manipulate_elasticsearch_query.md' - 'guide/search/shop_search/shop_search.md': 'search/search.md' - 'guide/search/shop_search/search_configuration.md': 'search/search.md' - 'guide/search/shop_search/search_api.md': 'search/search.md' - 'guide/search/shop_search/search_indexing.md': 'search/search.md' - 'guide/search/shop_search/search_synonyms.md': 'search/search.md' - 'guide/search/shop_search/search_autosuggest.md': 'search/search.md' - 'search/shop_search/shop_search.md': 'search/search.md' - 'search/shop_search/search_configuration.md': 'search/search.md' - 'search/shop_search/shop_search_api.md': 'search/search.md' - 'search/shop_search/search_indexing.md': 'search/search.md' - 'search/shop_search/search_synonyms.md': 'search/search.md' - 'search/shop_search/search_autosuggest.md': 'search/search.md' - 'search/search_engines/elastic_search/configure_elastic_search.md': 'search/search_engines/elasticsearch/configure_elasticsearch.md' - 'search/search_engines/elastic_search/elastic_search_overview.md': 'search/search_engines/elasticsearch/elasticsearch_overview.md' - - 'api/public_php_api_managing_repository.md': 'content_management/content_management_api/bookmark_api.md' - 'guide/request_lifecycle.md': 'infrastructure_and_maintenance/request_lifecycle.md' - 'guide/databases.md': 'infrastructure_and_maintenance/databases.md' - 'guide/cache/http_cache.md': 'infrastructure_and_maintenance/cache/http_cache/http_cache.md' - 'guide/cache/http_cache_config.md': 'infrastructure_and_maintenance/cache/http_cache/http_cache_configuration.md' - 'guide/cache/symfony_reverse_proxy.md': 'infrastructure_and_maintenance/cache/http_cache/reverse_proxy.md' - 'guide/cache/context_aware_cache.md': 'infrastructure_and_maintenance/cache/http_cache/context_aware_cache.md' - 'guide/cache/content_aware_cache.md': 'infrastructure_and_maintenance/cache/http_cache/content_aware_cache.md' - 'guide/persistence_cache.md': 'infrastructure_and_maintenance/cache/persistence_cache.md' - 'guide/cache/shop_caching.md': 'infrastructure_and_maintenance/cache/cache.md' - 'guide/clustering.md': 'infrastructure_and_maintenance/clustering/clustering.md' - 'guide/clustering_aws_s3.md': 'infrastructure_and_maintenance/clustering/clustering_with_aws_s3.md' - 'guide/devops.md': 'infrastructure_and_maintenance/devops.md' - 'guide/backup.md': 'infrastructure_and_maintenance/backup.md' - 'guide/performance.md': 'infrastructure_and_maintenance/performance.md' - 'guide/environments.md': 'infrastructure_and_maintenance/environments.md' - 'guide/sessions.md': 'infrastructure_and_maintenance/sessions.md' - 'guide/security.md': 'infrastructure_and_maintenance/security/development_security.md' - 'guide/security_checklist.md': 'infrastructure_and_maintenance/security/security_checklist.md' - 'guide/reporting_issues.md': 'infrastructure_and_maintenance/security/reporting_issues.md' - 'community_resources/support_maintenance_faq.md': 'infrastructure_and_maintenance/support_and_maintenance_faq.md' - - - - 'templating/layout/create_user_registration_form.md': 'customer_management/create_user_registration_form.md' - - 'tutorials/platform_beginner/building_a_bicycle_route_tracker_in_ez_platform.md': 'tutorials/beginner_tutorial/beginner_tutorial.md' - 'tutorials/platform_beginner/1_get_ready.md': 'tutorials/beginner_tutorial/1_get_ready.md' - 'tutorials/platform_beginner/2_create_the_content_model.md': 'tutorials/beginner_tutorial/2_create_the_content_model.md' - 'tutorials/platform_beginner/3_customize_the_front_page.md': 'tutorials/beginner_tutorial/3_customize_the_front_page.md' - 'tutorials/platform_beginner/4_display_single_content_item.md': 'tutorials/beginner_tutorial/4_display_single_content_item.md' - 'tutorials/platform_beginner/5_display_a_list_of_content_items.md': 'tutorials/beginner_tutorial/5_display_a_list_of_content_items.md' - 'tutorials/platform_beginner/6_improve_configuration.md': 'tutorials/beginner_tutorial/6_improve_configuration.md' - 'tutorials/platform_beginner/7_embed_content.md': 'tutorials/beginner_tutorial/7_embed_content.md' - 'tutorials/platform_beginner/8_enable_account_registration.md': 'tutorials/beginner_tutorial/8_enable_account_registration.md' - 'tutorials/enterprise_beginner/ez_enterprise_beginner_tutorial_-_its_a_dogs_world.md': 'tutorials/page_and_form_tutorial/page_and_form_tutorial.md' - 'tutorials/enterprise_beginner/1_get_a_starter_website.md': 'tutorials/page_and_form_tutorial/1_get_a_starter_website.md' - 'tutorials/enterprise_beginner/2_prepare_the_landing_page.md': 'tutorials/page_and_form_tutorial/2_prepare_the_landing_page.md' - 'tutorials/enterprise_beginner/3_use_existing_blocks.md': 'tutorials/page_and_form_tutorial/3_use_existing_blocks.md' - 'tutorials/enterprise_beginner/4_create_a_custom_block.md': 'tutorials/page_and_form_tutorial/4_create_a_custom_block.md' - 'tutorials/enterprise_beginner/5_create_newsletter_form.md': 'tutorials/page_and_form_tutorial/5_create_newsletter_form.md' - - 'infrastructure_and_maintenance/repository_api.md': 'api/php_api/php_api.md' - - 'content_management/customize_field_type_metadata.md': 'content_management/field_types/customize_field_type_metadata.md' - - - - 'ai_actions/ai_actions.md': 'ai/ai_actions/ai_actions.md' - 'ai_actions/ai_actions_guide.md': 'ai/ai_actions/ai_actions_guide.md' - 'ai_actions/install_ai_actions.md': 'ai/ai_actions/configure_ai_actions.md' - 'ai_actions/configure_ai_actions.md': 'ai/ai_actions/configure_ai_actions.md' - 'ai_actions/extend_ai_actions.md': 'ai/ai_actions/extend_ai_actions.md' - - 'cdp/cdp_activation/cdp_add_clientside_tracking.md': 'raptor_cdp/raptor_cdp_activation/raptor_cdp_add_tracking.md' - 'ibexa_engage/ibexa_engage.md': 'qualifio/qualifio.md' - 'ibexa_engage/install_ibexa_engage.md': 'qualifio/install_qualifio.md' - 'ibexa_engage/create_campaign.md': 'qualifio/create_campaign.md' - 'ibexa_engage/integrate_ibexa_connect.md': 'qualifio/integrate_ibexa_connect.md' - 'cdp/cdp.md': 'raptor_cdp/raptor_cdp.md' - 'cdp/cdp_guide.md': 'raptor_cdp/raptor_cdp_guide.md' - 'cdp/cdp_installation.md': 'raptor_cdp/raptor_cdp_installation.md' - 'cdp/cdp_data_customization.md': 'raptor_cdp/raptor_cdp_data_customization.md' - 'cdp/cdp_data_export_schedule.md': 'raptor_cdp/raptor_cdp_data_export_schedule.md' - 'cdp/cdp_activation/cdp_activation.md': 'raptor_cdp/raptor_cdp_activation/raptor_cdp_activation.md' - 'cdp/cdp_activation/cdp_configuration.md': 'raptor_cdp/raptor_cdp_activation/raptor_cdp_configuration.md' - 'cdp/cdp_activation/cdp_data_export.md': 'raptor_cdp/raptor_cdp_activation/raptor_cdp_data_export.md' - 'cdp/cdp_activation/cdp_add_tracking.md': 'raptor_cdp/raptor_cdp_activation/raptor_cdp_add_tracking.md' - 'multisite/languages/automated_translations.md': 'multisite/translations_management/configure_translations_management.md' - - - llmstxt: preprocess: llmstxt_preprocess.py # The "> " prefix renders the description as a blockquote summary, # as expected by the llms.txt spec (https://llmstxt.org) markdown_description: >- - > Developer documentation for Cohesivo — architecture, APIs, templating, and extensibility for building and customizing Ibexa DXP projects. + > Developer documentation for Cohesivo. # Pin links in the generated Markdown (and llms.txt) to this branch's # version instead of site_url's en/latest, without affecting the HTML diff --git a/scss/_variables.scss b/scss/_variables.scss index 60e417ceccd..1ba4b7d1948 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -22,9 +22,6 @@ $color-light-400: #ECECF1; $color-dark: #131C26; $color-dark-400: #71767C; -$color-headless: #C4234A; -$color-experience: #D3822B; -$color-lts-update: #5DA7C0; $color-new-feature: #2C9445; $color-first-release: #2C9445; diff --git a/scss/pills.scss b/scss/pills.scss index 0333f20d866..145958b3730 100644 --- a/scss/pills.scss +++ b/scss/pills.scss @@ -11,9 +11,6 @@ color: variables.$color-primary-main; $types: ( - "headless": (variables.$color-headless, "Headless"), - "experience": (variables.$color-experience, "Experience"), - "lts-update": (variables.$color-lts-update, "LTS Update"), "new-feature": (variables.$color-new-feature, "New feature"), "first-release": (variables.$color-first-release, "First release") ); @@ -45,7 +42,3 @@ text-transform: lowercase; } } - -div.pills { - float: right; -} diff --git a/tests/Yaml/YamlSamplesProvider.php b/tests/Yaml/YamlSamplesProvider.php index 0624536097e..5dbc63da458 100644 --- a/tests/Yaml/YamlSamplesProvider.php +++ b/tests/Yaml/YamlSamplesProvider.php @@ -8,7 +8,7 @@ namespace Ibexa\Tests\Documentation\Yaml; -use Ibexa\Tests\Documentation\InlineSamples\MarkdownExtractor; +use Ibexa\Tests\Documentation\Markdown\MarkdownYamlExtractor; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; @@ -70,7 +70,7 @@ private function iterateCodeSampleYaml(): iterable */ private function iterateMarkdownYamlBlocks(): iterable { - $extractor = new MarkdownExtractor('yaml'); + $extractor = new MarkdownYamlExtractor(); $iterator = new RecursiveIteratorIterator( new RecursiveDirectoryIterator(self::DOCS_DIR, RecursiveDirectoryIterator::SKIP_DOTS) ); diff --git a/tests/python/test_build_package_docs.py b/tests/python/test_build_package_docs.py index 7977b251da2..6e22ae252d0 100644 --- a/tests/python/test_build_package_docs.py +++ b/tests/python/test_build_package_docs.py @@ -236,7 +236,7 @@ def test_pointer_is_removed_without_leaving_a_double_blank_line(self): ) assert strip_llms_txt_pointer(content) == "# Getting started\n\nBody text here.\n" - def test_description_and_editions_lines_are_kept(self): + def test_description_and_trailing_content_are_kept(self): content = ( "# Heading\n" "\n" @@ -244,10 +244,10 @@ def test_description_and_editions_lines_are_kept(self): "\n" "Some page description.\n" "\n" - "Editions: Content, Experience\n" + "See also: Some related page.\n" ) assert strip_llms_txt_pointer(content) == ( - "# Heading\n\nSome page description.\n\nEditions: Content, Experience\n" + "# Heading\n\nSome page description.\n\nSee also: Some related page.\n" ) def test_nested_project_url_is_also_stripped(self): diff --git a/tests/python/test_page_metadata.py b/tests/python/test_page_metadata.py index 0638a534857..41c05b62c2d 100644 --- a/tests/python/test_page_metadata.py +++ b/tests/python/test_page_metadata.py @@ -1,5 +1,4 @@ from llms_txt.llmstxt_preprocess import ( - editions_from_frontmatter, expand_macros, inject_page_metadata, ) @@ -13,18 +12,11 @@ def test_llms_txt_pointer_always_inserted_after_first_h1(): assert inject_page_metadata(content) == ( f"# Title\n\n{LLMS_TXT_LINE}\n\nBody text." ) - assert inject_page_metadata(content, description="", editions=[]) == ( + assert inject_page_metadata(content, description="") == ( f"# Title\n\n{LLMS_TXT_LINE}\n\nBody text." ) -def test_editions_inserted_after_first_h1(): - content = "# Title\n\nBody text." - assert inject_page_metadata(content, editions=["Experience"]) == ( - f"# Title\n\n{LLMS_TXT_LINE}\n\nEditions: Experience\n\nBody text." - ) - - def test_description_inserted_after_first_h1(): content = "# Title\n\nBody text." assert inject_page_metadata(content, description="Configure the Storefront.") == ( @@ -32,17 +24,10 @@ def test_description_inserted_after_first_h1(): ) -def test_description_comes_before_editions(): - content = "# Title\n\nBody text." - assert inject_page_metadata(content, description="A description.", editions=["Experience"]) == ( - f"# Title\n\n{LLMS_TXT_LINE}\n\nA description.\n\nEditions: Experience\n\nBody text." - ) - - def test_prepended_when_no_h1(): content = "Body text." - assert inject_page_metadata(content, description="A description.", editions=["Experience"]) == ( - f"{LLMS_TXT_LINE}\n\nA description.\n\nEditions: Experience\n\nBody text." + assert inject_page_metadata(content, description="A description.") == ( + f"{LLMS_TXT_LINE}\n\nA description.\n\nBody text." ) @@ -57,27 +42,6 @@ def test_llms_txt_url_respects_nested_site_path(): assert result == f"# Title\n\n{nested_line}\n\nBody text." -def test_frontmatter_edition_string(): - assert editions_from_frontmatter({"edition": "headless experience"}) == ["Headless", "Experience"] - - -def test_frontmatter_editions_list(): - assert editions_from_frontmatter({"editions": ["headless", "lts-update"]}) == ["Headless", "LTS Update"] - - -def test_frontmatter_edition_and_editions_merged(): - result = editions_from_frontmatter({"edition": "experience", "editions": ["headless"]}) - assert result == ["Experience", "Headless"] - - -def test_unknown_edition_passes_through(): - assert editions_from_frontmatter({"edition": "custom"}) == ["custom"] - - -def test_empty_frontmatter(): - assert editions_from_frontmatter({}) == [] - - def test_expand_macros_substitutes_scalars(): variables = {"product_name": "Ibexa DXP", "product_name_cdp": "Ibexa CDP"} assert expand_macros("Install [[= product_name_cdp =]] with [[= product_name =]].", variables) == ( diff --git a/tests/python/test_preprocess.py b/tests/python/test_preprocess.py index 81914e48c75..d2cda8277d3 100644 --- a/tests/python/test_preprocess.py +++ b/tests/python/test_preprocess.py @@ -50,11 +50,11 @@ def test_release_note_tags_appended_to_heading(): html = ( '

Connector v5.0.7

' '
' - '
' - '
' + '
' + '
' "
" ) - assert "## Connector v5.0.7 (Headless, Experience)" in to_markdown(html) + assert "## Connector v5.0.7 (New feature, First release)" in to_markdown(html) def test_admonition_becomes_blockquote(): @@ -106,34 +106,6 @@ def test_card_with_empty_title_raises(): to_markdown(html) -def test_inline_pill_becomes_parenthetical(): - html = '

Feature is available.

' - assert "Feature (Experience) is available." in to_markdown(html) - - -def test_adjacent_inline_pills_merged(): - # Structure from update_from_5.0: pills separated by a space in a heading. - html = ( - '

Database update ' - ' ' - '' - '

' - ) - result = to_markdown(html) - assert "### Database update (Headless, Experience)" in result - assert ") (" not in result - - -def test_three_adjacent_inline_pills_merged(): - html = ( - "

Feature" - ' ' - ' ' - ' is available.

' - ) - assert "Feature (Headless, Experience, LTS Update) is available." in to_markdown(html) - - def test_ol_start_attribute_preserved(): #
    (a list interrupted by other content) keeps its numbering. html = "
    1. a
    2. b

    note

    1. c
    2. d
    " diff --git a/tests/yaml-validation-baseline.yaml b/tests/yaml-validation-baseline.yaml index 36d1cdcad4f..64a585cb5ed 100644 --- a/tests/yaml-validation-baseline.yaml +++ b/tests/yaml-validation-baseline.yaml @@ -22,131 +22,41 @@ ignoreErrors: line: 0 hash: 48b8c1ee7a1f481c5c83d1d90ed43723cc8dd59fac24adc798f0492d7fac7a89 message: '~The child config "stages" under "ibexa\.system\.default\.workflows\.quick_review" must be configured\.~' - - - path: docs/administration/back_office/back_office_elements/extending_thumbnails.md - line: 108 - hash: 65a44481f05186cf38bb2efd4583c49faf2b58dc4c197d40a611cd8610a77d97 - message: '~Unable to parse at line 1 \(near " App\\Thumbnails\\FieldValueUrl\:"\)\.~' - path: docs/administration/back_office/configure_product_tour.md - line: 26 + line: 23 hash: 4cfc5ac559eb8db38edb6c8a29872883a95886b61cdae2b343a5ebaf4a9bca8e message: '~The value "\" is not allowed for path "ibexa\.system\.\\>\.product_tour\.\\.type"\. Permissible values\: "general", "targetable"\.~' - - - path: docs/content_management/data_migration/data_migration_actions.md - line: 171 - hash: 023288ce392e2e051ac32ea3525bdecebc301a860789c8d2128042885122bfa9 - message: '~Unable to parse at line 1 \(near " actions\:"\)\.~' - - - path: docs/content_management/data_migration/data_migration_actions.md - line: 114 - hash: 29c25d5ed7cc6b7c435b3d2b6f4e64946ea4f37a27b1e32330a205757a74e56e - message: '~Unable to parse at line 1 \(near " actions\:"\)\.~' - - - path: docs/content_management/data_migration/data_migration_actions.md - line: 150 - hash: 379c053c8d40a701b0931b2e753d1256ece028d3c2e96a86fad3c884d480a48f - message: '~Unable to parse at line 1 \(near " actions\:"\)\.~' - - - path: docs/content_management/data_migration/data_migration_actions.md - line: 80 - hash: 6ebbedc8bf843bdc28aa23e5604ad9795153e5abcf808839229b08a37386f7eb - message: '~Unable to parse at line 1 \(near " actions\:"\)\.~' - - - path: docs/content_management/data_migration/data_migration_actions.md - line: 194 - hash: 93777839119c361b8b3a2708d47240128ef27643dce015decc1bf4edf0e8cb8f - message: '~Unable to parse at line 1 \(near " actions\:"\)\.~' - - - path: docs/content_management/data_migration/data_migration_actions.md - line: 98 - hash: 9bb6cf8c03a90b8fdf1c8a9e45a4b9d918bfc65afb2e3f31f913cde4042c55d1 - message: '~Unable to parse at line 1 \(near " actions\:"\)\.~' - - - path: docs/content_management/data_migration/data_migration_actions.md - line: 127 - hash: c730d746b624933585bd7f985fc773625750b8385a3755e7735d50e49e4964b2 - message: '~Unable to parse at line 1 \(near " actions\:"\)\.~' - - - path: docs/content_management/data_migration/data_migration_actions.md - line: 89 - hash: d330a24eee42024868c98fcffb2c446706570fea05d05ec3b7309297ba49e3b4 - message: '~Unable to parse at line 1 \(near " actions\:"\)\.~' - - - path: docs/content_management/data_migration/data_migration_actions.md - line: 107 - hash: e4d25af95785fe407cc135a608c778ff3232db0ce36e0bf5ce2039b249e29dc7 - message: '~Unable to parse at line 1 \(near " actions\:"\)\.~' - - - path: docs/content_management/data_migration/importing_data.md - line: 250 - hash: 5fff20465655d9e52a258e3c1b1347a62b0f558d9e733bb377c003d5021822eb - message: '~Unable to parse at line 1 \(near " \- fieldDefIdentifier\: show_children"\)\.~' - - - path: docs/content_management/data_migration/importing_data.md - line: 278 - hash: 7cec0a6d723dcb0d3d87904910e4870f05b885764116e447b8a4fe19025b8289 - message: '~Unable to parse at line 1 \(near " \- fieldDefIdentifier\: project_directory"\)\.~' - - - path: docs/content_management/data_migration/importing_data.md - line: 270 - hash: a08babaebc91ceb742a9a81a04be4d9e975291019794a0658bef1f99e62dccea - message: '~Unable to parse at line 1 \(near " \- fieldDefIdentifier\: some_field"\)\.~' - - - path: docs/content_management/data_migration/importing_data.md - line: 381 - hash: c94bdd7b27818ae0138b8c5bdba1ff33d77e25918609c1741f2c4d4236dcaff1 - message: '~Unable to parse at line 1 \(near " \- fieldDefIdentifier\: image"\)\.~' - path: docs/content_management/taxonomy/taxonomy.md - line: 195 + line: 172 hash: 968846dbeb558b9eb914194845153634b45d8a993977bc321fc9df8e3d29d9cb message: '~The child config "default_embedding_max_tokens" under "ibexa_taxonomy\.text_to_taxonomy" must be configured\: Maximum number of tokens sent when generating embeddings~' - path: docs/content_management/workflow/workflow.md - line: 135 + line: 131 hash: 0fdf8c632c4f5abed2f8af4fa177bf8afd9b129a48ff1fb611923135b856f865 message: '~The child config "matcher_value_templates" under "ibexa\.system\.default\.workflows_config" must be configured\: Matcher templates configuration\.~' - path: docs/customer_management/cp_page_builder.md - line: 35 + line: 34 hash: 6915e3e4985cf6b8d99ae25c59ddf2f735fa927fdddb4b2a9e095475b86d02db message: '~The child config "default_siteaccess" under "ibexa\.siteaccess" must be configured\: Name of the default siteaccess~' - path: docs/customer_management/cp_page_builder.md - line: 119 + line: 118 hash: 833557b1406f91474d3420c809f8cf7ffc7ebefcf12aa37e66d31c291c73a2e6 message: '~The child config "default_siteaccess" under "ibexa\.siteaccess" must be configured\: Name of the default siteaccess~' - path: docs/customer_management/cp_page_builder.md - line: 207 + line: 206 hash: 98de256c0b149da15bea944ff56da3dad8bf968f5aad2d2882855d8844541dc1 message: '~The child config "list" under "ibexa\.siteaccess" must be configured\: Available SiteAccess list~' - path: docs/getting_started/first_steps.md - line: 120 + line: 115 hash: d6956fc656de2808d27e294db9f4a5a1a66630f046ea21b8e75da2f658984f99 message: '~The child config "default_siteaccess" under "ibexa\.siteaccess" must be configured\: Name of the default siteaccess~' - - - path: docs/infrastructure_and_maintenance/cache/http_cache/reverse_proxy.md - line: 148 - hash: 15a7e49dc68c59afa39e10276a448edf6f9e501374b2a75d43c0edaa7882f5e2 - message: '~The child config "fastly" under "ibexa\.system\.my_siteaccess_group\.http_cache" must be configured\.~' - - - path: docs/infrastructure_and_maintenance/cache/http_cache/reverse_proxy.md - line: 131 - hash: 68ea24e38b23f9efbfe4d689cffb5eb147ea6f332dc334fecc3f25f0117c4fb8 - message: '~The child config "fastly" under "ibexa\.system\.my_siteaccess_group\.http_cache" must be configured\.~' - - - path: docs/infrastructure_and_maintenance/security/development_security.md - line: 20 - hash: 0521cbcc27827c7ee2160a512158a19c89f1d51eb64a69d1b4600eb45a2505dd - message: '~Unrecognized option "require_previous_session" under "security\.firewalls\.ibexa_front\.form_login"\. Available options are "always_use_default_target_path", "check_path", "csrf_parameter", "csrf_token_id", "default_target_path", "enable_csrf", "failure_forward", "failure_handler", "failure_path", "failure_path_parameter", "form_only", "login_path", "password_parameter", "post_only", "provider", "remember_me", "success_handler", "target_path_parameter", "use_forward", "use_referer", "username_parameter"\.~' - - - path: docs/infrastructure_and_maintenance/security/security_checklist.md - line: 142 - hash: 65986b42415e23ed46aec11a3fb7398b138665b9fb75432e1457c7ebf89d18ec - message: '~The child config "firewalls" under "security" must be configured\.~' - path: docs/multisite/languages/languages.md line: 78 @@ -179,17 +89,17 @@ ignoreErrors: message: '~The child config "default_siteaccess" under "ibexa\.siteaccess" must be configured\: Name of the default siteaccess~' - path: docs/multisite/site_factory/site_factory.md - line: 58 + line: 57 hash: a1f0951071e5dec4f362284872b59167d59d3ff180e607e089c8a84488fb2c3d message: '~The child config "list" under "ibexa\.siteaccess" must be configured\: Available SiteAccess list~' - path: docs/multisite/site_factory/site_factory.md - line: 40 + line: 39 hash: e51a407b99ce4b87b710537f7caf45ad7528f720e4f2a1caf3c67ad647cc83f1 message: '~The child config "list" under "ibexa\.siteaccess" must be configured\: Available SiteAccess list~' - path: docs/multisite/site_factory/site_factory_configuration.md - line: 81 + line: 80 hash: 8721257146510878c104fbcddf27e0bf14afb71aba069a5a38b31f86b8d90db2 message: '~The child config "siteaccess_group" under "ibexa_site_factory\.templates\.\" must be configured\.~' - @@ -257,26 +167,6 @@ ignoreErrors: line: 77 hash: 86fafb34287eaa9ce0fc52bec555e34c8e91f61778421cff734c8d42eb40e300 message: '~Unable to parse at line 1 \(near " none\:"\)\.~' - - - path: docs/recommendations/raptor_integration/tracking_functions.md - line: 34 - hash: ca52a936f86a66c78951579cee005c4f5b87d844b8ff5d0b2f587b6aa68054b9 - message: '~Duplicate key "connector_raptor" detected at line 6 \(near "\# Hybrid tracking"\)\.~' - - - path: docs/templating/design_engine/add_new_design.md - line: 16 - hash: 00526df40a7b678b4caa97a887e2c6a47689cf3e2e3d52ff42b7ef1b9a74aa0d - message: '~The child config "match" under "ibexa\.siteaccess" must be configured\: Siteaccess match configuration\. First key is the matcher class, value is passed to the matcher\. Key can be a service identifier \(prepended by "@"\), or a FQ class name \(prepended by "\\"\)~' - - - path: docs/templating/templates/template_configuration.md - line: 99 - hash: 2c225195371a55292ddf28e3ab7ef44855d194211bf48753fc65da1a93ef112c - message: '~Duplicate key "match" detected at line 3 \(near "match\: \[\]"\)\.~' - - - path: docs/users/oauth_server.md - line: 78 - hash: 44b149828628395857cf579b36ec8b838e136e016e372061af2499c567c408ae - message: '~The child config "firewalls" under "security" must be configured\.~' - path: docs/users/user_authentication.md line: 41 diff --git a/theme/main.html b/theme/main.html index f54fda51a16..93b264cd5ee 100644 --- a/theme/main.html +++ b/theme/main.html @@ -87,16 +87,6 @@ {% endfor %} - {% if page.meta.edition or page.meta.editions %} -
    - {% if page.meta.edition == 'lts-update' or 'lts-update' in page.meta.editions %} - - {% endif %} - {% if page.meta.edition == 'experience' or 'experience' in page.meta.editions %} - - {% endif %} -
    - {% endif %} {% if config.extra.current_version_is_eol %} {% include "partials/eol_warning.html" %} {% endif %} diff --git a/tools/api_refs/README.md b/tools/api_refs/README.md index 26000776669..d3b8110a19f 100644 --- a/tools/api_refs/README.md +++ b/tools/api_refs/README.md @@ -1,34 +1,34 @@ -# PHP API Ref +# REST API Ref ## Install/Dependencies -Requires [`jq`](https://stedolan.github.io/jq/download/) +Requires [`jq`](https://stedolan.github.io/jq/download/) and the [Redocly CLI](https://redocly.com/docs/cli/installation). ## Basic usage -`tools/api_refs/api_refs.sh` is a script generating PHP & REST API References, by default, under `docs/api/php_api/php_api_reference/` and `docs/api/rest_api/rest_api_reference/`. +`tools/api_refs/api_refs.sh` is a script generating the REST API Reference and the OpenAPI specification, +by default, under `docs/api/rest_api/rest_api_reference/`. + +It installs a temporary Ibexa DXP, dumps its OpenAPI schema with `bin/console ibexa:openapi`, +fixes the dumped schema with `tools/api_refs/openapi.php`, and renders the reference with Redocly. - For Composer, if you do not use a global authentication to retrieve _Commerce_ edition, a path to an auth.json file can be given as first optional argument. For example: ``` tools/api_refs/api_refs.sh ~/www/ibexa-dxp-commerce/auth.json ``` -- The second optional argument can be a path to an output directory to use instead of the default one. For example, using the Composer global authentication file as first argument and the path to directory (which is created if it doesn't exist yet): - ``` - tools/api_refs/api_refs.sh ~/.composer/auth.json ./docs/api/php_api/php_api_reference-TMP - ``` -- The next three optional arguments are the REST API files - - 3rd argument is the reference HTML file path - - 4th argument is the file path for the OpenAPI specification in YAML format - - 5th argument is the file path for the OpenAPI specification in JSON format +- The next three optional arguments are the REST API output files + - 2nd argument is the reference HTML file path + - 3rd argument is the file path for the OpenAPI specification in YAML format + - 4th argument is the file path for the OpenAPI specification in JSON format ## Rebuild example ```bash tools/api_refs/api_refs.sh -git add docs/api/php_api/php_api_reference/ -git commit -m "Rebuild PHP API Ref's HTML" +git add docs/api/rest_api/rest_api_reference/ +git commit -m "Rebuild REST API Ref's HTML" git push ``` @@ -36,25 +36,19 @@ git push In `tools/api_refs/api_refs.sh`: -`PHPDOC_VERSION` should always target the last version of phpDocumentor. - `DXP_VERSION` should target the version of Ibexa DXP Commerce corresponding to the doc's branch. +`DXP_ADD_ONS` lists the packages installed on top of the edition so that their REST endpoints are dumped. + ### Templates -Custom templates are located in `tools/api_refs/.phpdoc/template/` directory. -They are overriding the default templates from a phpDocumentor version. -The default templates version is not always the same as the phpDocumentor binary version. -To update the default templates version, the overriding custom templates must be updated as well to obtain a better or equal result without bug. -See `PHPDOC_VERSION` and `PHPDOC_TEMPLATE_VERSION`. +The reference is rendered by Redocly from `tools/api_refs/redocly.hbs`, +configured by `tools/api_refs/redocly.yaml`, which is generated from `tools/api_refs/redocly.yaml.template`. ## Advanced usage `tools/api_refs/api_refs.sh` has a set of internal variables that might be edited for particular usages. -`PHPDOC_CONF` can be changed to use a different config file. -For example, when working on the design, the set of parsed files can be reduced for a quicker PHP API Reference compilation. - `PHP_BINARY` can be edited, for example, to use a different PHP version than the default, to change verbosity, or to add `-d memory_limit=-1`. ```bash @@ -80,12 +74,11 @@ FORCE_DXP_INSTALL=0; ``` If you change some of those values, please do not commit those changes, and don't commit their output. -To prevent that, you can make a local copy, and use this copy to generate in a temporary output directory: +To prevent that, you can make a local copy, and use this copy to generate into temporary output files: ```bash cp tools/api_refs/api_refs.sh tools/api_refs/api_refs.dev.sh -nano tools/api_refs/api_refs.dev.sh # Edit and make your changes. For example, change PHPDOC_CONF to use phpdoc.dev.xml. -nano tools/api_refs/phpdoc.dev.xml # Edit and make your changes. For example, target only your package. -tools/api_refs/api_refs.dev.sh ~/.composer/auth.json ./docs/api/php_api/php_api_reference-TMP +nano tools/api_refs/api_refs.dev.sh # Edit and make your changes. +tools/api_refs/api_refs.dev.sh ~/.composer/auth.json ./rest_api_reference-TMP.html ./openapi-TMP.yaml ./openapi-TMP.json ``` ### Creating a build of dev version @@ -93,13 +86,12 @@ tools/api_refs/api_refs.dev.sh ~/.composer/auth.json ./docs/api/php_api/php_api_ To build the reference for an unreleased version, set the following variables: - `DXP_VERSION` -- `BASE_DXP_BRANCH` - `VIRTUAL_DXP_VERSION` For example, to build the API Reference based on the development version of the DXP before the 5.0.10 release, run: ``` bash -DXP_VERSION=v5.0.x-dev BASE_DXP_BRANCH=5.0 VIRTUAL_DXP_VERSION=5.0.10 tools/api_refs/api_refs.sh ~/my/path/to/auth.json +DXP_VERSION=v5.0.x-dev VIRTUAL_DXP_VERSION=5.0.10 tools/api_refs/api_refs.sh ~/my/path/to/auth.json ``` ### Test a branch @@ -129,13 +121,13 @@ fi; #### By using `gh` -With [GitHub CLI `gh`](https://cli.github.com/), you can trigger a GitHub Action workflow to build the API References. +With [GitHub CLI `gh`](https://cli.github.com/), you can trigger a GitHub Action workflow to build the API Reference. ```bash gh workflow run api_refs.yaml -f version= -f use_dev_version= --ref -f base_branch= -f work_branch= -f force= ``` -`-f version=` to pass the Ibexa DXP version tag for which the API References are built. +`-f version=` to pass the Ibexa DXP version tag for which the API Reference is built. `-f use_dev_version=` to use the released version designed by the tag, or to use the development version (`v5.0.x-dev`) for an incoming tag. `--ref ` to use the `api_refs.yaml` workflow from a given branch instead of the default branch (`5.0`). `-f base_branch=` to use the `api_refs.sh` from a given branch and make a PR to that branch. @@ -144,13 +136,13 @@ gh workflow run api_refs.yaml -f version= -f use_dev_version= - Examples: -Build from the dev branch `5.0.x-dev` API references for `v5.0.999`: +Build from the dev branch `5.0.x-dev` API reference for `v5.0.999`: ```bash gh workflow run api_refs.yaml -f version=v5.0.999 -f use_dev_version=true ``` -Rebuild references for the released version `v5.0.10` from `my-tools`'s `api_refs.yaml` with `my-tools`'s tools and commit the result into `my-api-refs` even if it already exists: +Rebuild the reference for the released version `v5.0.10` from `my-tools`'s `api_refs.yaml` with `my-tools`'s tools and commit the result into `my-api-refs` even if it already exists: ```bash gh workflow run api_refs.yaml -f version=v5.0.10 --ref my-builder -f base_branch=my-builder -f work_branch=my-api-refs -f force=true @@ -158,5 +150,5 @@ gh workflow run api_refs.yaml -f version=v5.0.10 --ref my-builder -f base_branch #### By using web UI -On the GitHub repository page, go to the "Actions" tab and, in the workflow list, select ["Build API Refs"](https://github.com/ibexa/documentation-developer/actions/workflows/api_refs.yaml). +On the GitHub repository page, go to the "Actions" tab and, in the workflow list, select ["Build REST API Reference"](https://github.com/ibexa/documentation-developer/actions/workflows/api_refs.yaml). On top right of the past workflow table, unfold "Run workflow" menu, set the fields, then click "Run workflow" button. diff --git a/tools/api_refs/api_refs.sh b/tools/api_refs/api_refs.sh index 249bf3ca0ff..8d16b2963fd 100755 --- a/tools/api_refs/api_refs.sh +++ b/tools/api_refs/api_refs.sh @@ -3,43 +3,24 @@ set +x; AUTH_JSON=$(realpath ${1:-~/.composer/auth.json}); # Path to an auth.json file allowing to install the targeted edition and version -PHP_API_OUTPUT_DIR=${2:-./docs/api/php_api/php_api_reference}; # Path to the directory where the built PHP API Reference is hosted -REST_API_OUTPUT_FILE=${3:-./docs/api/rest_api/rest_api_reference/rest_api_reference.html}; # Path to the REST API Reference file -REST_API_OPENAPI_FILE_YAML=${4:-./docs/api/rest_api/rest_api_reference/openapi.yaml}; # Path to the REST API OpenAPI spec file -REST_API_OPENAPI_FILE_JSON=${5:-./docs/api/rest_api/rest_api_reference/openapi.json}; # Path to the REST API OpenAPI spec file +REST_API_OUTPUT_FILE=${2:-./docs/api/rest_api/rest_api_reference/rest_api_reference.html}; # Path to the REST API Reference file +REST_API_OPENAPI_FILE_YAML=${3:-./docs/api/rest_api/rest_api_reference/openapi.yaml}; # Path to the REST API OpenAPI spec file +REST_API_OPENAPI_FILE_JSON=${4:-./docs/api/rest_api/rest_api_reference/openapi.json}; # Path to the REST API OpenAPI spec file DXP_EDITION='commerce'; # Edition from and for which the Reference is built DXP_VERSION="${DXP_VERSION:-6.0.*}"; # Version from and for which the Reference is built; can be overridden by the DXP_VERSION env var (e.g. v5.0.x-dev for a dev build) -DXP_ADD_ONS=(rector integrated-help fieldtype-richtext-rte connector-anthropic connector-gemini shopping-list cdp connector-raptor connector-quable mcp); # Packages not included in $DXP_EDITION but added to the Reference, listed without their vendor "ibexa" -DXP_EDITIONS=(oss headless experience commerce); # Available editions ordered by ascending capabilities -SF_VERSION='7.4'; # Symfony version used by Ibexa DXP -PHPDOC_VERSION='3.10.0'; # Version of phpDocumentor used to build the Reference -PHPDOC_CONF="$(pwd)/tools/api_refs/phpdoc.dist.xml"; # Absolute path to phpDocumentor configuration file -#PHPDOC_CONF="$(pwd)/tools/api_refs/phpdoc.dev.xml"; # Absolute path to phpDocumentor configuration file -PHPDOC_TEMPLATE_VERSION='3.10.0'; # Version of the phpDocumentor base template set -PHPDOC_DIR="$(pwd)/tools/api_refs/.phpdoc"; # Absolute path to phpDocumentor resource directory (containing the override template set) +DXP_ADD_ONS=(integrated-help fieldtype-richtext-rte connector-anthropic connector-gemini shopping-list cdp connector-raptor connector-quable mcp); # Packages not included in $DXP_EDITION but added to the Reference, listed without their vendor "ibexa" REDOCLY_CONFIG_TEMPLATE="$(pwd)/tools/api_refs/redocly.yaml.template"; # Absolute path to Redocly configuration template file REDOCLY_CONFIG="$(pwd)/tools/api_refs/redocly.yaml"; # Absolute path to Redocly configuration file (generated from template) REDOCLY_TEMPLATE="$(pwd)/tools/api_refs/redocly.hbs"; # Absolute path to Redocly wrapping template OPENAPI_FIX="$(pwd)/tools/api_refs/openapi.php"; # A script editing and fixing few things on the dumped schema (should be temporary and fixes reported to source) -PHP_BINARY="php -d error_reporting=`php -r 'echo E_ALL & ~E_DEPRECATED;'`"; # Avoid depreciation messages from phpDocumentor/Reflection/issues/529 when using PHP 8.2 or higher +PHP_BINARY="php -d error_reporting=`php -r 'echo E_ALL & ~E_DEPRECATED;'`"; # Avoid deprecation messages from the Symfony console when using PHP 8.2 or higher COMPOSER_BINARY='composer'; -TMP_DXP_DIR=/tmp/ibexa-dxp-phpdoc; # Absolute path of the temporary directory in which Ibexa DXP will be installed and the PHP API Reference built +TMP_DXP_DIR=/tmp/ibexa-dxp-openapi; # Absolute path of the temporary directory in which Ibexa DXP will be installed and the REST API Reference built FORCE_DXP_INSTALL=1; # If 1, empty the temporary directory, install DXP from scratch, build, remove temporary directory; if 0, potentially reuse the DXP already installed in temporary directory, keep temporary directory for future uses. -BASE_DXP_BRANCH="${BASE_DXP_BRANCH:-}"; # Branch from and for which the Reference is built when using a dev branch as version; can be overridden by the BASE_DXP_BRANCH env var VIRTUAL_DXP_VERSION="${VIRTUAL_DXP_VERSION:-}"; # Version for which the reference is supposedly built when using dev branch as version; can be overridden by the VIRTUAL_DXP_VERSION env var -if [ ! -d $PHP_API_OUTPUT_DIR ]; then - echo -n "Creating ${PHP_API_OUTPUT_DIR}… "; - mkdir -p $PHP_API_OUTPUT_DIR; - if [ $? -eq 0 ]; then - echo 'OK'; - else - exit 1; - fi; -fi; -PHP_API_OUTPUT_DIR=$(realpath $PHP_API_OUTPUT_DIR); # Transform into absolute path before changing the working directory REST_API_OUTPUT_FILE=$(realpath $REST_API_OUTPUT_FILE); # Transform into absolute path before changing the working directory REST_API_OPENAPI_FILE_YAML=$(realpath $REST_API_OPENAPI_FILE_YAML); # Transform into absolute path before changing the working directory REST_API_OPENAPI_FILE_JSON=$(realpath $REST_API_OPENAPI_FILE_JSON); # Transform into absolute path before changing the working directory @@ -106,121 +87,10 @@ if [ 0 -eq $DXP_ALREADY_EXISTS ]; then done; fi; -if [[ "$DXP_VERSION" == *".x-dev" ]]; then - GIT_REF=$BASE_DXP_BRANCH; -elif [[ "$DXP_VERSION" == "v"* ]]; then - GIT_REF="$DXP_VERSION"; -else - GIT_REF="v$DXP_VERSION"; -fi - -if [ 0 -eq $DXP_ALREADY_EXISTS ]; then - echo -n 'Building package→edition map… '; - PACKAGE_MAP='' - NAMESPACE_MAP='' - for edition in ${DXP_EDITIONS[@]}; do - echo -n "${edition}… "; - while IFS= read -r line; do - package=$(echo $line | cut -d '"' -f 2); - if [[ ! "${DXP_EDITIONS[*]}" =~ "${package/ibexa\//}" ]]; then - PACKAGE_MAP="$PACKAGE_MAP\n'$package': '$edition'," - NAMESPACES=$($COMPOSER_BINARY show "$package" --available --format=json | \ - jq -r --arg PACKAGE "$package" '"'\''\(.autoload | ."psr-4" | try to_entries[] catch empty | .key[:-1] | sub("\\\\";"\\\\\\";"g"))'\'': '\''\($PACKAGE)'\'',"') - NAMESPACE_MAP="$NAMESPACE_MAP\n$NAMESPACES" - fi; - done <<< "$(curl --no-progress-meter "https://raw.githubusercontent.com/ibexa/$edition/$GIT_REF/composer.json" | jq .require | grep -E "(ibexa|ezsystems|silversolutions)")"; - if [ "$edition" == "$DXP_EDITION" ]; then - break; - fi; - done; - echo 'OK'; - - echo -n 'Building namespace→edition map… '; - for package in "${DXP_ADD_ONS[@]}"; do - NAMESPACES=$($COMPOSER_BINARY show "ibexa/$package" --available --format=json | \ - jq -r --arg PACKAGE "ibexa/$package" '"'\''\(.autoload | ."psr-4" | try to_entries[] catch empty | .key[:-1] | sub("\\\\";"\\\\\\";"g"))'\'': '\''\($PACKAGE)'\'',"') - NAMESPACE_MAP="$NAMESPACE_MAP\n$NAMESPACES" - PACKAGE_MAP="$PACKAGE_MAP\n'ibexa/$package': 'optional'," - done; - echo 'OK'; - - echo -n "Store package→edition and namespace→edition maps into ${map}… "; - map=$PHPDOC_DIR/template/package-edition-map.twig; - if [[ -f $map ]]; then - rm $map; - fi; - PACKAGE_MAP="{% set package_edition_map = {\n$PACKAGE_MAP\n} %}" - NAMESPACE_MAP="{% set namespace_package_map = {\n$NAMESPACE_MAP\n} %}" - { - echo -e "$PACKAGE_MAP"; - echo -e "$NAMESPACE_MAP"; - echo '{% block content %}{% endblock %}' - } >> "$map"; - echo 'OK'; -fi; - if [[ "$DXP_VERSION" == *".x-dev" ]]; then DXP_VERSION=$VIRTUAL_DXP_VERSION; fi; -echo 'Set up phpDocumentor…'; -sed "s/version number=\".*\"/version number=\"$DXP_VERSION\"/" $PHPDOC_CONF > ./phpdoc.dist.xml; -mkdir .phpdoc; - -if [ "$PHPDOC_VERSION" != "$PHPDOC_TEMPLATE_VERSION" ]; then - echo 'Set phpDocumentor base templates…'; - git clone -n -b "v$PHPDOC_TEMPLATE_VERSION" --depth=1 --filter=tree:0 https://github.com/phpDocumentor/phpDocumentor - cd phpDocumentor; - git sparse-checkout set --no-cone data/templates/default/; - git checkout; - mv data/templates/default ../.phpdoc/template; - cd -; - rm -rf phpDocumentor; -fi; - -echo 'Set phpDocumentor override templates…'; -cp -R $PHPDOC_DIR ./; -mkdir -p php_api_reference/js; -mv ./.phpdoc/template/fonts ./php_api_reference/; -mv ./.phpdoc/template/images ./php_api_reference/; -mv ./.phpdoc/template/js/*.js ./php_api_reference/js/; - -echo 'Set Symfony version…'; -sed "s/symfony_version = '.*'/symfony_version = '$SF_VERSION'/" $PHPDOC_DIR/template/base.html.twig > ./.phpdoc/template/base.html.twig; - -echo 'Run phpDocumentor…'; -curl -LO "https://github.com/phpDocumentor/phpDocumentor/releases/download/v$PHPDOC_VERSION/phpDocumentor.phar"; -PHPDOC_BIN='phpDocumentor.phar'; -if [[ "$PHPDOC_VERSION" == "3.4."* ]]; then - PHPDOC_BIN='phpDocumentor.phar run'; -fi; -$PHP_BINARY $PHPDOC_BIN -t php_api_reference; -if [ $? -eq 0 ]; then - echo -n 'Remove unneeded from phpDocumentor output… '; - rm -rf ./php_api_reference/files ./php_api_reference/graphs ./php_api_reference/indices ./php_api_reference/packages; - rm -f ./php_api_reference/images/apple-touch-icon.png ./php_api_reference/images/favicon-16x16.png ./php_api_reference/images/favicon-32x32.png ./php_api_reference/images/favicon.ico; - rm -f ./php_api_reference/classes/Symfony-*.html ./php_api_reference/namespaces/symfony*.html; - echo -n 'Remove Symfony namespace from index… '; - awk 'NR==FNR{if (/.*"fqsen": "\\\\Symfony.*/) for (i=-1;i<=3;i++) del[NR+i]; next} !(FNR in del)' \ - ./php_api_reference/js/searchIndex.js \ - ./php_api_reference/js/searchIndex.js \ - > ./php_api_reference/js/searchIndex.new.js; - mv -f ./php_api_reference/js/searchIndex.new.js ./php_api_reference/js/searchIndex.js; - echo -n "Copy phpDocumentor output to ${PHP_API_OUTPUT_DIR}… "; - cp -rf ./php_api_reference/* $PHP_API_OUTPUT_DIR; - echo -n 'Remove surplus… '; - while IFS= read -r line; do - file="$(echo $line | sed -r 's/Only in (.*): (.*)/\1\/\2/')"; - if [[ $file = $PHP_API_OUTPUT_DIR/* ]]; then - rm -rf $file; - fi; - done <<< "$(diff -qr ./php_api_reference $PHP_API_OUTPUT_DIR | grep 'Only in ')"; - echo 'OK.'; -else - echo 'A phpDocumentor error prevents PHP Reference update.'; - exit 3; -fi; - if [ 0 -eq $DXP_ALREADY_EXISTS ]; then echo 'Set up DXP recipes…'; git init -b main && git add . && git commit -m "Installed Ibexa Commerce" > /dev/null; @@ -229,10 +99,10 @@ fi; echo 'Dump REST OpenAPI schema… '; $PHP_BINARY bin/console ibexa:openapi --yaml \ - | sed "s@info:@info:\n x-logo:\n url: 'https://doc.ibexa.co/en/latest/images/ibexa-dxp-logo.png'@" \ + | sed "s@info:@info:\n x-logo:\n url: 'https://doc.ibexa.co/en/saas/images/cohesivo-logo.png'@" \ > openapi.yaml; $PHP_BINARY bin/console ibexa:openapi \ - | sed 's@"info": {@"info": {\n "x-logo": {\n "url": "https://doc.ibexa.co/en/latest/images/ibexa-dxp-logo.png"\n },@' \ + | sed 's@"info": {@"info": {\n "x-logo": {\n "url": "https://doc.ibexa.co/en/saas/images/cohesivo-logo.png"\n },@' \ > openapi.json; echo 'Fix REST OpenAPI schema… '; $PHP_BINARY $OPENAPI_FIX; diff --git a/tools/api_refs/redocly.hbs b/tools/api_refs/redocly.hbs index adc027ee0a5..eb1c52e97db 100644 --- a/tools/api_refs/redocly.hbs +++ b/tools/api_refs/redocly.hbs @@ -38,7 +38,7 @@ }); // Style logo - let logo = document.querySelector('img[src$="ibexa-dxp-logo.png"]'); + let logo = document.querySelector('img[src$="cohesivo-logo.png"]'); logo.onclick = () => { let pathParts = document.location.pathname.split('/').slice(0, 3); document.location = pathParts.join('/') + '/api/rest_api/rest_api_usage/rest_api_usage/'; diff --git a/tools/llm_package/dump_class_paths.php b/tools/llm_package/dump_class_paths.php index 0d7e04f4672..8995af382b1 100644 --- a/tools/llm_package/dump_class_paths.php +++ b/tools/llm_package/dump_class_paths.php @@ -67,7 +67,7 @@ file_put_contents( $outputPath, - json_encode($map, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n" + json_encode($map, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_FORCE_OBJECT) . "\n" ); printf("Resolved %d/%d API-referenced classes into %s\n", count($map), count($slugs), $outputPath); diff --git a/tools/llms_txt/hooks.py b/tools/llms_txt/hooks.py index ddce34edfe6..4457f99e980 100644 --- a/tools/llms_txt/hooks.py +++ b/tools/llms_txt/hooks.py @@ -18,7 +18,6 @@ from llms_txt.llmstxt_preprocess import ( absolutize_image_urls, - editions_from_frontmatter, expand_macros, inject_page_metadata, renumber_ordered_lists, @@ -66,7 +65,6 @@ def on_page_content(html: str, *, page: "Page", config: "MkDocsConfig", **kwargs return frontmatter = _read_frontmatter(page, config) - editions = editions_from_frontmatter(frontmatter) description = expand_macros(str(frontmatter.get("description") or ""), config.get("extra") or {}) if "[[=" in description: # Unresolved macros must not leak into the output. @@ -75,7 +73,7 @@ def on_page_content(html: str, *, page: "Page", config: "MkDocsConfig", **kwargs # userguide project published under /projects/userguide/), unlike # a hardcoded root-relative "/llms.txt". llms_txt_url = urljoin(llmstxt._base_url, "llms.txt") - content = inject_page_metadata(page_info.content, description, editions, llms_txt_url) + content = inject_page_metadata(page_info.content, description, llms_txt_url) content = renumber_ordered_lists(content) # Same base URL and page directory the plugin uses for making link hrefs absolute. page_dir = PurePosixPath(page.file.dest_uri).parent.as_posix() diff --git a/tools/llms_txt/llmstxt_preprocess.py b/tools/llms_txt/llmstxt_preprocess.py index f1055ce6d4f..de444b96f04 100644 --- a/tools/llms_txt/llmstxt_preprocess.py +++ b/tools/llms_txt/llmstxt_preprocess.py @@ -8,8 +8,8 @@ mkdocs-llmstxt plugin (configured in ``plugins.yml``) before the HTML is converted to Markdown. - Markdown post-processing helpers (``renumber_ordered_lists``, - ``inject_edition_badges``, ``editions_from_frontmatter``) applied by - ``hooks.py`` to the Markdown the plugin generated. + ``inject_page_metadata``) applied by ``hooks.py`` to the Markdown the + plugin generated. This package (``llms_txt``) is installed as a dependency by other Ibexa doc sites, which each keep a thin root-level ``llmstxt_preprocess.py`` shim @@ -25,20 +25,11 @@ from bs4 import BeautifulSoup as Soup, NavigableString -PILL_CLASS_TO_EDITION = { - "pill--lts-update": "LTS Update", - "pill--experience": "Experience", - "pill--headless": "Headless", +PILL_CLASS_TO_CATEGORY = { "pill--new-feature": "New feature", "pill--first-release": "First release", } -FRONTMATTER_EDITION_DISPLAY = { - "lts-update": "LTS Update", - "experience": "Experience", - "headless": "Headless", -} - def preprocess(soup: Soup, output: str) -> None: """ @@ -47,16 +38,11 @@ def preprocess(soup: Soup, output: str) -> None: Runs with autoclean disabled so we can control the order: 1. Expand tabbed sets with labels before autoclean removes tabbed-labels. 2. Run autoclean-equivalent cleanup. - 3. Replace inline edition badge spans with readable text. - 4. Remove release notes filter UI. - 5. Convert card macros to markdown lists. - - Note: frontmatter edition injection is handled in hooks.py on_page_content, - where page.file.src_path is available directly. + 3. Remove release notes filter UI. + 4. Convert card macros to markdown lists. """ _process_tabbed_sets(soup) _autoclean(soup) - _process_inline_pills(soup) _process_release_note_tags(soup) _process_release_note_dates(soup) _process_release_notes_filters(soup) @@ -183,82 +169,29 @@ def _should_remove(tag) -> bool: Soup(f"{html_module.escape(code_elem.get_text())}", "html.parser") ) -# --------------------------------------------------------------------------- -# Inline edition badge spans (from snippet includes) -# --------------------------------------------------------------------------- - -def _pill_edition(node) -> str: - """Return the edition name of an inline pill span, or '' if not one.""" - if getattr(node, "name", None) != "span": - return "" - classes = node.get("class") or [] - if "pill--inline" not in classes: - return "" - for pill_cls, edition_name in PILL_CLASS_TO_EDITION.items(): - if pill_cls in classes: - return edition_name - return "" - - -def _process_inline_pills(soup: Soup) -> None: - """Replace inline edition pill spans with readable text. - - Consecutive pills (possibly separated by whitespace) are merged into a - single parenthetical, e.g. ' (Headless, Experience)' instead of - ' (Headless) (Experience)'. - """ - for span in soup.find_all("span", class_="pill--inline"): - if span.parent is None: # already consumed as part of a previous run - continue - edition = _pill_edition(span) - if not edition: - continue - - # Collect the run of pills that follow, skipping whitespace between them. - editions = [edition] - consumed = [] - node = span.next_sibling - pending_whitespace = [] - while node is not None: - if isinstance(node, NavigableString) and not node.strip(): - pending_whitespace.append(node) - node = node.next_sibling - continue - next_edition = _pill_edition(node) - if not next_edition: - break - editions.append(next_edition) - consumed += pending_whitespace + [node] - pending_whitespace = [] - node = node.next_sibling - - for extra_node in consumed: - extra_node.extract() - span.replace_with(soup.new_string(f" ({', '.join(editions)})")) - def _process_release_note_tags(soup: Soup) -> None: - """Append edition labels from release-note__tags divs to their preceding heading. + """Append release-note category labels from release-note__tags divs to their preceding heading. Release notes use a
    block after each

    containing empty
    elements rendered via CSS. This converts them to a readable parenthetical on the heading, e.g.: - ## Google Gemini connector v5.0.7 (Headless, Experience, LTS Update, New feature) + ## Google Gemini connector v5.0.7 (New feature, First release) """ for tags_div in soup.find_all("div", class_="release-note__tags"): - editions = [] + categories = [] for pill_div in tags_div.find_all("div"): classes = pill_div.get("class", []) - for pill_cls, name in PILL_CLASS_TO_EDITION.items(): + for pill_cls, name in PILL_CLASS_TO_CATEGORY.items(): if pill_cls in classes: - editions.append(name) + categories.append(name) break heading = tags_div.find_previous_sibling(["h1", "h2", "h3", "h4"]) - if heading and editions: + if heading and categories: # Insert before the permalink anchor so it's part of the heading text anchor = heading.find("a", class_="headerlink") - label = NavigableString(f" ({', '.join(editions)})") + label = NavigableString(f" ({', '.join(categories)})") if anchor: anchor.insert_before(label) else: @@ -399,20 +332,6 @@ def _process_cards(soup: Soup) -> None: # Markdown post-processing (applied by hooks.py to the generated Markdown) # --------------------------------------------------------------------------- -def editions_from_frontmatter(frontmatter: dict) -> list: - """Map ``edition``/``editions`` frontmatter values to display names.""" - - def _to_list(value): - if isinstance(value, list): - return value - if isinstance(value, str): - return value.split() - return [] - - all_editions = _to_list(frontmatter.get("edition")) + _to_list(frontmatter.get("editions") or []) - return [FRONTMATTER_EDITION_DISPLAY.get(e, e) for e in all_editions if e] - - _MACRO_RE = re.compile(r"\[\[=\s*(\w+)\s*=\]\]") @@ -431,9 +350,9 @@ def _substitute(match: re.Match) -> str: def inject_page_metadata( - content: str, description: str = "", editions: list = (), llms_txt_url: str = "/llms.txt" + content: str, description: str = "", llms_txt_url: str = "/llms.txt" ) -> str: - """Insert the llms.txt pointer, page description, and an 'Editions: X, Y' line after the first h1 heading. + """Insert the llms.txt pointer and page description after the first h1 heading. ``llms_txt_url`` must be the absolute URL of *this site's own* llms.txt (e.g. via ``urljoin(base_url, "llms.txt")``), not a hardcoded root-relative @@ -443,8 +362,6 @@ def inject_page_metadata( metadata_lines = ["", f"> For the complete documentation index, see [llms.txt]({llms_txt_url})."] if description: metadata_lines += ["", description] - if editions: - metadata_lines += ["", "Editions: " + ", ".join(editions)] lines = content.split("\n") for i, line in enumerate(lines):