diff --git a/code_samples/back_office/components/twig_components.yaml b/code_samples/back_office/components/twig_components.yaml index bfcfc70e1e..6e0458f4d0 100644 --- a/code_samples/back_office/components/twig_components.yaml +++ b/code_samples/back_office/components/twig_components.yaml @@ -1,18 +1,5 @@ ibexa_twig_components: admin-ui-user-menu: - custom-html-component: - type: html - arguments: - content: 'Hello world!' - custom-template-component: - type: template - arguments: - template: '@ibexadesign/ui/component/user_thumbnail/user_thumbnail.html.twig' - parameters: - user_content: - name: "Thumbnail" - thumbnail: - resource: https://placecats.com/100/100 custom-controller-component: type: controller arguments: @@ -20,15 +7,18 @@ ibexa_twig_components: parameters: parameter1: 'custom' parameter2: true - admin-ui-stylesheet-head: - custom-link-component: - type: stylesheet + custom-html-component: + type: html + priority: 0 arguments: - href: 'https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback' - rel: stylesheet - crossorigin: anonymous - integrity: sha384-LN/mLhO/GN6Ge8ZPvI7uRsZpiXmtSkep+aFlJcHa8by4TvA34o1am9sa88eUzKTD - type: text/css + content: 'Hello world!' + admin-ui-user-menu: + duplicated_user_menu: + type: menu + arguments: + name: ezplatform_admin_ui.menu.user + template: '@ibexadesign/ui/menu/user.html.twig' + depth: 1 admin-ui-script-head: custom-script-component: type: script @@ -39,3 +29,23 @@ ibexa_twig_components: async: true integrity: sha384-Ewi2bBDtPbbu4/+fs8sIbBJ3zVl0LDOSznfhFR/JBK+SzggdRdX8XQKauWmI9HH2 type: text/javascript + admin-ui-stylesheet-head: + custom-link-component: + type: stylesheet + arguments: + href: 'https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback' + rel: stylesheet + crossorigin: anonymous + integrity: sha384-LN/mLhO/GN6Ge8ZPvI7uRsZpiXmtSkep+aFlJcHa8by4TvA34o1am9sa88eUzKTD + type: text/css + admin-ui-global-search: + custom-template-component: + type: template + priority: 50 + arguments: + template: '@ibexadesign/ui/component/user_thumbnail/user_thumbnail.html.twig' + parameters: + user_content: + name: "Thumbnail" + thumbnail: + resource: https://placecats.com/100/100 diff --git a/code_samples/back_office/search/src/Query/SymbolAttributeTypeQuery.php b/code_samples/back_office/search/src/Query/SymbolAttributeTypeQuery.php new file mode 100644 index 0000000000..2c449d97b8 --- /dev/null +++ b/code_samples/back_office/search/src/Query/SymbolAttributeTypeQuery.php @@ -0,0 +1,9 @@ +setFilter(new SymbolAttribute('ean', ['5023920187205'])); +/** @var \Ibexa\Contracts\ProductCatalog\ProductServiceInterface $productService */ +$results = $productService->findProducts($query); diff --git a/code_samples/data_migration/examples/discounts/discount_code_create.yaml b/code_samples/data_migration/examples/discounts/discount_code_create.yaml new file mode 100644 index 0000000000..7b2358d364 --- /dev/null +++ b/code_samples/data_migration/examples/discounts/discount_code_create.yaml @@ -0,0 +1,7 @@ +type: discount_code +mode: create +code: summer10 +global_usage_limit: 100 # Optional +user_usage_limit: 5 # Optional +created_at: '2023-01-01T12:00:00+00:00' # Optional +creator_id: 42 # Optional diff --git a/code_samples/discounts/src/Command/ManageDiscountsCommand.php b/code_samples/discounts/src/Command/ManageDiscountsCommand.php index 6243da8ca6..0471f80201 100644 --- a/code_samples/discounts/src/Command/ManageDiscountsCommand.php +++ b/code_samples/discounts/src/Command/ManageDiscountsCommand.php @@ -59,7 +59,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int $discountCodeCreateStruct = new DiscountCodeCreateStruct( 'summer10', - null, // Unlimited usage + 10, // Global usage limit + null, // Unlimited usage per customer $this->permissionResolver->getCurrentUserReference()->getUserId(), $now ); @@ -78,7 +79,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int new IsInRegions(['germany', 'france']), new IsProductInArray(['product-1', 'product-2']), new IsInCurrency('EUR'), - new IsValidDiscountCode($discountCode->getCode(), $discountCode->getUsedLimit()), + new IsValidDiscountCode( + $discountCode->getCode(), + $discountCode->getGlobalLimit(), + $discountCode->getUsedLimit() + ), ]) ->setTranslations([ new DiscountTranslationStruct('eng-GB', 'Discount name', 'This is a discount description', 'Promotion Label', 'Promotion Description'), diff --git a/code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php b/code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php new file mode 100644 index 0000000000..2860f9aec9 --- /dev/null +++ b/code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php @@ -0,0 +1,46 @@ +getDigits($value); + + $count = count($digits); + $total = 0; + for ($i = $count - 2; $i >= 0; $i -= 2) { + $digit = $digits[$i]; + if ($i % 2 === 0) { + $digit *= 2; + } + + $total += $digit > 9 ? $digit - 9 : $digit; + } + + $checksum = $digits[$count - 1]; + + return $total + $checksum === 0; + } + + /** + * Returns an array of digits from the given value (skipping any formatting characters). + * + * @return int[] + */ + private function getDigits(string $value): array + { + $chars = array_filter( + str_split($value), + static fn (string $char): bool => $char !== '-' + ); + + return array_map('intval', array_values($chars)); + } +} diff --git a/code_samples/symbol_attribute/config/mysql/symbol_attribute.sql b/code_samples/symbol_attribute/config/mysql/symbol_attribute.sql new file mode 100644 index 0000000000..5157c20e37 --- /dev/null +++ b/code_samples/symbol_attribute/config/mysql/symbol_attribute.sql @@ -0,0 +1,2 @@ +CREATE TABLE ibexa_product_specification_attribute_symbol (id INT NOT NULL, value VARCHAR(160) DEFAULT NULL, INDEX ibexa_product_specification_attribute_symbol_value_idx (value), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_520_ci` ENGINE = InnoDB; +ALTER TABLE ibexa_product_specification_attribute_symbol ADD CONSTRAINT ibexa_product_specification_attribute_symbol_fk FOREIGN KEY (id) REFERENCES ibexa_product_specification_attribute (id) ON UPDATE CASCADE ON DELETE CASCADE \ No newline at end of file diff --git a/code_samples/symbol_attribute/config/postgresql/symbol_attribute.sql b/code_samples/symbol_attribute/config/postgresql/symbol_attribute.sql new file mode 100644 index 0000000000..4ad6b65bef --- /dev/null +++ b/code_samples/symbol_attribute/config/postgresql/symbol_attribute.sql @@ -0,0 +1,3 @@ +CREATE TABLE ibexa_product_specification_attribute_symbol (id INT NOT NULL, value VARCHAR(160) DEFAULT NULL, PRIMARY KEY(id)); +CREATE INDEX ibexa_product_specification_attribute_symbol_value_idx ON ibexa_product_specification_attribute_symbol (value); +ALTER TABLE ibexa_product_specification_attribute_symbol ADD CONSTRAINT ibexa_product_specification_attribute_symbol_fk FOREIGN KEY (id) REFERENCES ibexa_product_specification_attribute (id) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE; \ No newline at end of file diff --git a/composer.json b/composer.json index eebf291e30..734baa69ba 100644 --- a/composer.json +++ b/composer.json @@ -70,7 +70,8 @@ "ibexa/twig-components": "~4.6.x-dev", "ibexa/tree-builder": "~4.6.x-dev", "ibexa/discounts": "~4.6.x-dev", - "ibexa/discounts-codes": "~4.6.x-dev" + "ibexa/discounts-codes": "~4.6.x-dev", + "ibexa/product-catalog-symbol-attribute": "~4.6.x-dev" }, "scripts": { "fix-cs": "php-cs-fixer fix --config=.php-cs-fixer.php -v --show-progress=dots", diff --git a/docs/administration/back_office/back_office_elements/custom_components.md b/docs/administration/back_office/back_office_elements/custom_components.md index ddc6040590..c93e5d0b51 100644 --- a/docs/administration/back_office/back_office_elements/custom_components.md +++ b/docs/administration/back_office/back_office_elements/custom_components.md @@ -47,6 +47,7 @@ The available groups for the back office are: |`admin-ui-systeminfo-tab-groups`| `vendor/ibexa/system-info/src/bundle/Resources/views/themes/admin/system_info/info.html.twig` | |`admin-ui-user-menu`| `vendor/ibexa/admin-ui-ui/src/bundle/Resources/views/themes/admin/ui/layout.html.twig` | |`admin-ui-user-profile-blocks`| `vendor/ibexa/admin-ui/src/bundle/Resources/views/themes/admin/account/profile/view.html.twig` | +|`admin-ui-versions-table-before`|`vendor/ibexa/admin-ui/src/bundle/Resources/views/themes/admin/content/tab/versions/table.html.twig`| For more information, see [this example using few of those components](components.md#example). diff --git a/docs/api/event_reference/discounts_events.md b/docs/api/event_reference/discounts_events.md index f33e24214c..5a7098e23e 100644 --- a/docs/api/event_reference/discounts_events.md +++ b/docs/api/event_reference/discounts_events.md @@ -15,12 +15,12 @@ The events below are dispatched when managing [discounts](discounts_guide.md): | Event | Dispatched by | |---|---| -|[BeforeCreateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeCreateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) -|[CreateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) -|[BeforeDeleteDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeDeleteDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) -|[DeleteDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-DeleteDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) +|[BeforeCreateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeCreateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | +|[CreateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-CreateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | +|[BeforeDeleteDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeDeleteDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | +|[DeleteDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-DeleteDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | |[BeforeUpdateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-BeforeUpdateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html)| -|[UpdateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-UpdateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html)| +|[UpdateDiscountEvent](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Event-UpdateDiscountEvent.html)| [DiscountServiceInterface](/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-DiscountServiceInterface.html) | ## Form events diff --git a/docs/api/graphql/graphql_queries.md b/docs/api/graphql/graphql_queries.md index d38629b8dd..a4efa75763 100644 --- a/docs/api/graphql/graphql_queries.md +++ b/docs/api/graphql/graphql_queries.md @@ -838,3 +838,7 @@ children(first: 3, after: "YXJyYXljb25uZWN0aW9uOjM=") ### Get Matrix field type To get a Matrix field type with GraphQL, see [Matrix field type reference](matrixfield.md). + +### Enable pagination for RelationList field type + +To learn how to enable pagination for RelationList field type, see the [RelationList field type reference](relationlistfield.md). diff --git a/docs/content_management/data_migration/importing_data.md b/docs/content_management/data_migration/importing_data.md index 5eadd34005..c6c2fdba7d 100644 --- a/docs/content_management/data_migration/importing_data.md +++ b/docs/content_management/data_migration/importing_data.md @@ -56,6 +56,7 @@ The following data migration step modes are available: | `currency` | ✔ | ✔ | ✔ | | | `customer_group` | ✔ | ✔ | ✔ | | | `discount` | ✔ | ✔ | | | +| `discount_code` | ✔ | | | | | `language` | ✔ | | | | | `location` | | ✔ | | ✔ | | `object_state` | ✔ | | | | @@ -531,6 +532,14 @@ The provided conditions overwrite any already existing ones. For a list of available conditions, see [Discounts API](discounts_api.md#conditions). +### Discount codes [[% include 'snippets/lts-update_badge.md' %]] + +You can create a discount code as in the following example: + +``` yaml +[[= include_file('code_samples/data_migration/examples/discounts/discount_code_create.yaml') =]] +``` + ## Criteria When using `update` or `delete` modes, you can use criteria to identify the objects to operate on. 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 86ef67f760..ab6a4f5f9d 100644 --- a/docs/content_management/field_types/field_type_reference/relationlistfield.md +++ b/docs/content_management/field_types/field_type_reference/relationlistfield.md @@ -107,3 +107,33 @@ $validators = [ ] ]; ``` + +### Enable pagination in GraphQL + +To enable pagination for Relation List field type, set the `ibexa.graphql.schema.ibexa_object_relation_list.enable_pagination` parameter to `true`. + +!!! note + + The pagination is enabled by default in [[= product_name =]] v5 and the parameter is removed. + +This allows you to query for only a subset of relations, as in the following example: + +``` graphql +query { + content { + relations(contentId: 71) { + rel(first: 5) { + totalCount, + edges { + node { + _contentInfo { + id + } + } + } + } + } + } +} +``` + diff --git a/docs/discounts/discounts_api.md b/docs/discounts/discounts_api.md index cb0fc19931..d8ab35759c 100644 --- a/docs/discounts/discounts_api.md +++ b/docs/discounts/discounts_api.md @@ -113,9 +113,9 @@ The example below contains a Command creating a cart discount. The discount: - [depends](#conditions) on - being bought from Germany or France - 2 products - - a `summer10` [discount code](#discount-codes) which can be used unlimited number of times + - a `summer10` [discount code](#discount-codes) which can be used only 10 times, but a single customer can use the code multiple times -``` php hl_lines="60-66 68-92" +``` php hl_lines="60-67 69-97" [[= include_file('code_samples/discounts/src/Command/ManageDiscountsCommand.php') =]] ``` diff --git a/docs/discounts/discounts_guide.md b/docs/discounts/discounts_guide.md index 7c0364bb2f..71a1eef50d 100644 --- a/docs/discounts/discounts_guide.md +++ b/docs/discounts/discounts_guide.md @@ -59,6 +59,7 @@ A shopping cart can have multiple active discounts, but a specific product can o When two or more discounts can be applied to a single product, the system evaluates the following properties to choose the right one: +- discount code existence (discounts with discount codes have priority over the others) - discount activation place (cart discounts rank higher over catalog discounts) - discount priority (higher priority ranks higher) - discount creation date (newer discounts rank higher) @@ -107,7 +108,8 @@ These conditions can include: For **cart discounts**, you can specify an additional text value that needs to be entered in the cart for the discount to apply. -The discount code usage can be limited per customer: +The discount code usage can be limited globally, for example by making the discount valid only for the first 10 customers before it expires. +You can also limit the usage per customer: - single use: every customer can use this code only once - limited use: every customer can use the code a specified number of times diff --git a/docs/getting_started/requirements.md b/docs/getting_started/requirements.md index ed4dc19758..ed41f984ff 100644 --- a/docs/getting_started/requirements.md +++ b/docs/getting_started/requirements.md @@ -125,6 +125,10 @@ For production setups it's recommended that you use Varnish/Fastly, Redis, NFS/E ## PHP +=== "[[= product_name =]] v4.6" + + - 8.3 + === "[[= product_name =]] v4.6" - 8.3 @@ -208,25 +212,54 @@ For production setups it's recommended that you use Varnish/Fastly, Redis, NFS/E === "[[= product_name =]] v5.0" - - For content search, Solr 8.11.1 or higher. - Alternatively, Elasticsearch 7.16.2 or higher 7.x version. + |Name|Version| + |---|---| + |Solr|8.11.1+ or 9.8.1+| + |Elasticsearch| 7.16.2+ | + + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. === "[[= product_name =]] v4.6" - - For content search, Solr 7.7 LTS or Solr 8, recommended 8.11.1 or higher. - Alternatively, Elasticsearch 7.16.2 or higher 7.x version. - - The above solutions require Oracle Java/Open JDK. The minimum requirement is 8 LTS, recommended 11 LTS. - Newer versions aren't supported. + |Name|Version| + |---|---| + |Solr|8.11.1+ or 9.8.1+| + |Elasticsearch| 7.16.2+ | + + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. === "[[= product_name =]] v3.3" - - For content search, Solr 7.7 LTS or Solr 8, recommended 8.11.1 or higher. - Alternatively, Elasticsearch 7.16.2 or higher 7.x version. + |Name|Version| + |---|---| + |Solr|7.7 LTS or 8.11.1+| + |Elasticsearch| 7.16.2+ | + + If you see a "+" next to the product version, it indicates a recommended version or higher within the same major release. + For example, "1.18+" means any 1.x version equal to or higher than 1.18, but not 2.x. + - For BinaryFile field indexing, Apache Tika 1.20 or higher 1.x version, recommended 1.28.1 or higher. - The above solutions require Oracle Java/Open JDK. The minimum requirement is 8 LTS, recommended 11 LTS. Newer versions aren't supported. ## Graphic Handler +=== "[[= product_name =]] v5.0" + + - GraphicsMagick + - ImageMagick + - GD + + Optionally, if you intend to edit [PNG, SVG, GIF or WEBP files in the Image Editor](images.md#image-optimization), or use it with image variations: + + - JpegOptim + - Optipng + - Pngquant 2 + - SVGO 1 + - Gifsicle + - cwebp + === "[[= product_name =]] v4.6" - GraphicsMagick @@ -288,6 +321,10 @@ For production setups it's recommended that you use Varnish/Fastly, Redis, NFS/E ## Filesystem +=== "[[= product_name =]] v5.0" + + - Linux ext4 / XFS + === "[[= product_name =]] v4.6" - Linux ext4 / XFS @@ -339,6 +376,16 @@ For production setups it's recommended that you use Varnish/Fastly, Redis, NFS/E ## Browser +=== "[[= product_name =]] v5.0" + + [[= product_name =]] is developed to work with *any* web browser that supports modern standards, on *any* screen resolution suitable for web, running on *any* device. + However, for the Editorial and Administration User Interfaces, you need: a minimum of 1366-by-768 screen resolution, a desktop or tablet device, and a recommended/supported browser among the ones found below. + + - Mozilla® Firefox® most recent stable version (recommended) + - Google Chrome™ most recent stable version (recommended) + - Chromium™ based browsers such as Microsoft® Edge® and Opera®, most recent stable version, desktop *and* tablet + - Apple® Safari® most recent stable version, desktop *and* tablet + === "[[= product_name =]] v4.6" [[= product_name =]] is developed to work with *any* web browser that supports modern standards, on *any* screen resolution suitable for web, running on *any* device. diff --git a/docs/ibexa_products/editions.md b/docs/ibexa_products/editions.md index 02b083b3ca..6accca22ad 100644 --- a/docs/ibexa_products/editions.md +++ b/docs/ibexa_products/editions.md @@ -65,3 +65,4 @@ The features brought by LTS Updates become standard parts of the next LTS releas | [AI Actions](ai_actions_guide.md) | ✔ | ✔ | ✔ | | [Date and time attribute type](date_and_time.md) | ✔ | ✔ | ✔ | | [Discounts](discounts.md) | | | ✔ | +| [Symbol attribute type](symbol_attribute_type.md) | ✔ | ✔ | ✔ | \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index 1817ac9673..800c80464c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -89,11 +89,11 @@
-

The newest LTS Update is Discounts

-
Install it to reduce prices on specific products, making deals more attractive to potential buyers.
+

The newest LTS Update is the Symbol attribute

+
Use it to store standarized identifiers of your products.
diff --git a/docs/permissions/limitation_reference.md b/docs/permissions/limitation_reference.md index 09e49157c9..01b3cddad9 100644 --- a/docs/permissions/limitation_reference.md +++ b/docs/permissions/limitation_reference.md @@ -320,6 +320,41 @@ This limitation can be used as a role limitation. For more information on how to restrict user's access to part of the subtree, see [the example in the Admin management section](permission_use_cases.md#restrict-editing-to-part-of-the-tree). +## Taxonomy limitation + +The taxonomy (`Taxonomy`) limitation specifies with which [taxonomies](taxonomy.md) (tags, product categories, or custom ones) user can interact. + +The supported policies are: + +- `taxonomy/read` +- `taxonomy/manage` +- `taxonomy/assign` + +### Possible values + +|Value|UI value|Description| +|------|------|------| +|Taxonomy identifiers|Taxonomy names|List of allowed taxonomies| + + +## Taxonomy Subtree limitation + +The taxonomy subtree (`TaxonomySubtree`) limitation specifies whether the user has access to a specific subtree within the [taxonomy](taxonomy.md) tree. +Once a tag is selected, user can interact with it and all the child tags below it in the taxonomy tree. +In addition, it grants read-only access to all the parent tags (up to the taxonomy root) so that the user can see the context. + +The supported policies are: + +- `taxonomy/read` +- `taxonomy/manage` +- `taxonomy/assign` + +### Possible values + +|Value|UI value|Description| +|------|------|------| +|Tag IDs|Selected tags| All valid Tag IDs are allowed| + ## Version Lock limitation The Version Lock (`VersionLock`) limitation specifies whether the user can perform actions, for example, edit or unlock, on content items that are in a workflow. diff --git a/docs/pim/attributes/symbol_attribute_type.md b/docs/pim/attributes/symbol_attribute_type.md new file mode 100644 index 0000000000..7f541efc0f --- /dev/null +++ b/docs/pim/attributes/symbol_attribute_type.md @@ -0,0 +1,138 @@ +--- +description: Create a symbol attribute type that enables for the efficient representation of string-based values while enforcing their format in product specifications. +edition: lts-update +--- + +# Symbol attribute type + +The Symbol attribute type LTS update enables the efficient representation of string-based data and enforces their format in product specifications. + +This feature allows you to store standard product identifiers (such as EAN or ISBN) in the [Product Information Management](pim_guide.md) system. + +## Installation + +### Download the bundle + +To get the most recent stable version of this bundle, open a command terminal, navigate to your project directory, and run the following command: + +``` bash +composer require ibexa/product-catalog-symbol-attribute +``` + +### Enable the bundle + +Symfony Flex enables and configures the `IbexaProductCatalogSymbolAttributeBundle` automatically. +If you don't use it, you can manually enable this bundle by adding the line below to the Kernel of your project: + +``` php +// config/bundles.php + +return [ + // ... + Ibexa\Bundle\ProductCatalogSymbolAttribute\IbexaProductCatalogSymbolAttributeBundle::class => ['all' => true], + // ... +]; +``` + +### Update database schema + +To store symbol attribute values, the `IbexaProductCatalogSymbolAttributeBundle` needs an extra table. +The following SQL query can be used to build the required database structure: + +=== "MySQL" + + ``` sql + [[= include_file('code_samples/symbol_attribute/config/mysql/symbol_attribute.sql', glue=' ') =]] + ``` + +=== "PostgreSQL" + + ``` sql + [[= include_file('code_samples/symbol_attribute/config/postgresql/symbol_attribute.sql', glue=' ') =]] + ``` + +### Create symbol attribute definition (optional) + +Now, you're able to define symbol attributes at this point. + +To create symbol attribute definition, in the back office, go to **Product catalog** -> **Attributes**, and click **Create**. +Then, choose **Symbol** attribute type. + +## Build-in symbol attribute formats + +The built-in symbol attribute formats in `ibexa/product-catalog-symbol-attribute` are listed below: + +| Name | Description | Example | +|-----------------|-----------------|-----------------| +| Generic | Accepts any string value | #FR1.2 | +| Generic (alphabetic characters only) | Accepts any string value that contais only letters | ABCD | +| Generic (digits only) | Accepts any string value that contais only digits | 123456 | +| Generic (alphanumeric characters only) | Accepts any string value that contains only letters or digits | 2N6405G | +| Generic (hexadecimal digits only) | Accepts any string value that contains only hexadecimal digits (digits or A-F characters) | DEADBEEF | +| EAN-8 | European Article Number (8 characters) | 96385074 | +| EAN-13 | European Article Number (13 characters) | 5023920187205 | +| EAN-14 | European Article Number (14 characters) | 12345678901231 | +| ISBN-10 | International Standard Book Number (10 characters) | 0-19-852663-6 | +| ISBN-13 | International Standard Book Number (13 characters) | 978-1-86197-876-9 | + +!!! caution + + 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_file('code_samples/pim/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: + +For more information, see [SymbolAttribute Criterion](symbolattribute_criterion.md). diff --git a/docs/release_notes/ibexa_dxp_v4.6.md b/docs/release_notes/ibexa_dxp_v4.6.md index efa690c945..e630e9d6c4 100644 --- a/docs/release_notes/ibexa_dxp_v4.6.md +++ b/docs/release_notes/ibexa_dxp_v4.6.md @@ -10,6 +10,110 @@ month_change: true
+[[% set version = 'v4.6.22' %]] +[[= release_note_entry_begin("Symbol attribute", '2025-08-05', ['Headless', 'Experience', 'Commerce', 'LTS Update', 'New feature']) =]] + +The Symbol attribute allows you to store standarized identifiers of your products in the [Product Information Management](pim_guide.md) system. + +For more information, see [Symbol attribute type](symbol_attribute_type.md). + +#### PHP API + +The PHP API has been enhanced with the following new classes: + +- [`Ibexa\Contracts\ProductCatalogSymbolAttribute\Search\Criterion\SymbolAttribute`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalogSymbolAttribute-Search-Criterion-SymbolAttribute.html) +- [`Ibexa\Contracts\ProductCatalogSymbolAttribute\Value\ChecksumInterface`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalogSymbolAttribute-Value-ChecksumInterface.html) + +[[= release_note_entry_end() =]] + +[[= release_note_entry_begin("Discounts " + version, '2025-08-05', ['LTS Update', 'Commerce']) =]] + +#### Global discount codes limits + +- You can now [limit the number of times](discounts_guide.md#discount-codes) a discount code can be used before it expires. The discounts created before this release are set to unlimited global usage + +#### Discount codes prioritization + +- Discounts with discount codes now have priority over the other discounts + +#### Discount codes migrations + +- You can now create discount codes using [data migrations](importing_data.md#discount-codes) + +#### PHP API + +The PHP API has been enhanced with the following new classes: + +- [`Ibexa\Contracts\Discounts\Value\DiscountConditionsInterface`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-DiscountConditionsInterface.html) +- [`Ibexa\Contracts\Discounts\Value\Query\SortClause\OverridePrioritization`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-Discounts-Value-Query-SortClause-OverridePrioritization.html) + +[[= release_note_entry_end() =]] +[[= release_note_entry_begin("Ibexa DXP " + version, '2025-08-05', ['Headless', 'Experience', 'Commerce', 'New feature']) =]] + +#### Special characters in online editor + +The [online editor](online_editor_guide.md) now allows to easily enter special characters like currency symbols. +It uses the [special characters plugin](https://ckeditor.com/docs/ckeditor5/latest/features/special-characters.html), + +![Special characters in online editor](4.6_special_characters.png "Special characters in online editor") + +#### Support for Solr 9 + +With this release, [[= product_name =]] starts supporting [Solr 9](requirements.md#search). + +Solr 9 comes with support for [Dense Vector Search](https://solr.apache.org/guide/solr/latest/query-guide/dense-vector-search.html), paving the way for incoming improvements to the [AI Actions](ai_actions.md) feature. + +#### Improved content creation interface + +The editing interface of the back office has been improved to better highlight the language, creator, and the publication date when working with content items. + +![Improved interface for content creation](4.6_improved_editing.png "Improved interface for content creation") + +#### Twig Components + +With the latest changes to [Twig Components](components.md), you can: + +- set component priority when using YAML configuration +- render a menu with help of the new Menu component + +The list of built-in Twig Component groups has been expanded and includes: + +- one new group for the [back office](custom_components.md) (`admin-ui-versions-table-before`) +- eight new groups for [storefront](customize_storefront_layout.md#customize-with-twig-components) + +#### Taxonomy Subtree limitation + +You can now manage access to [taxonomy items](taxonomy.md) more effectively by using the new [Taxonomy Subtree limitation](limitation_reference.md#taxonomy-subtree-limitation). + +In addition, you can now use the [Taxonomy limitation](limitation_reference.md#taxonomy-limitation) together with the `taxonomy/assign` policy. + +#### Pagination for ezobjectrelationlist in GraphQL + +To improve performance and gain greater control over the returned responses from the [GraphQL API](graphql.md), you can now [enable pagination](relationlistfield.md#enable-pagination-in-graphql) of relations specified using the RelationList field type. + +#### Breaking changes + +- The `Ibexa\FieldTypeRichText\RichText\Validator\CustomTagsValidator` class has been renamed to `Ibexa\FieldTypeRichText\RichText\Validator\CustomTemplateValidator`, expanding its responsibility to validate both [custom tags](extend_online_editor.md#configure-custom-tags) and [custom styles](extend_online_editor.md#configure-custom-styles) +- The `Ibexa\Contracts\AdminUi\Permission\PermissionCheckContextProviderInterface` interface has been removed +- The `Ibexa\Contracts\AdminUi\Values\PermissionCheckContext` class has been removed + +#### PHP API + +The PHP API has been enhanced with the following new classes: + +- [`Ibexa\Contracts\Cart\Exception\VatCalculationExceptionInterface`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-Cart-Exception-VatCalculationExceptionInterface.html) +- [`Ibexa\Contracts\Core\Repository\Values\Notification\CriterionHandlerInterface`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Notification-CriterionHandlerInterface.html) +- [`Ibexa\Contracts\Core\Repository\Values\Notification\Query\CriterionInterface`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Notification-Query-CriterionInterface.html) +- [`Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion\DateCreated`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Notification-Query-Criterion-DateCreated.html) +- [`Ibexa\Contracts\Core\Repository\Values\Notification\Query\NotificationQuery`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-Values-Notification-Query-NotificationQuery.html) +- [`Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\AbstractPriceRange`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-AbstractPriceRange.html) +- [`Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\CustomPriceRange`](https://doc.ibexa.co/en/4.6/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-Query-Criterion-CustomPriceRange.html) + +#### Full changelog + +[[% include 'snippets/release_46.md' %]] +[[= release_note_entry_end() =]] + [[% set version = 'v4.6.21' %]] [[= release_note_entry_begin("Discounts " + version, '2025-06-11', ['LTS Update', 'Commerce']) =]] diff --git a/docs/release_notes/img/4.6_improved_editing.png b/docs/release_notes/img/4.6_improved_editing.png new file mode 100644 index 0000000000..b514cd145d Binary files /dev/null and b/docs/release_notes/img/4.6_improved_editing.png differ diff --git a/docs/release_notes/img/4.6_special_characters.png b/docs/release_notes/img/4.6_special_characters.png new file mode 100644 index 0000000000..37f278b2f3 Binary files /dev/null and b/docs/release_notes/img/4.6_special_characters.png differ diff --git a/docs/search/criteria_reference/product_search_criteria.md b/docs/search/criteria_reference/product_search_criteria.md index a31f6cabbc..35a3948ac3 100644 --- a/docs/search/criteria_reference/product_search_criteria.md +++ b/docs/search/criteria_reference/product_search_criteria.md @@ -42,4 +42,4 @@ Search Criterion let you filter product by specific attributes, for example, col |[RangeMeasurementAttributeMinimum](rangemeasurementattributeminimum_criterion.md)|Minimum value of product's measurement attribute| |[SelectionAttribute](selectionattribute_criterion.md)|Value of product's selection attribute| |[SimpleMeasurementAttribute](simplemeasurementattribute_criterion.md)|Value of product's measurement attribute| - +|[SymbolAttribute](symbolattribute_criterion.md)|Value of product's symbol attribute| diff --git a/docs/search/criteria_reference/symbolattribute_criterion.md b/docs/search/criteria_reference/symbolattribute_criterion.md new file mode 100644 index 0000000000..53c6a241cd --- /dev/null +++ b/docs/search/criteria_reference/symbolattribute_criterion.md @@ -0,0 +1,21 @@ +--- +description: SymbolAttribute Criterion +edition: lts-update +--- + +# SymbolAttributeCriterion + +The `SymbolAttribute` Search Criterion searches for products by [symbol attribute](symbol_attribute_type.md). + +## Arguments + +- `identifier` - identifier of the format +- `value` - array with the values to search for + +## Example + +### PHP + +``` php +[[= include_file('code_samples/back_office/search/src/Query/SymbolAttributeTypeQuery.php') =]] +``` \ No newline at end of file diff --git a/docs/search/search_engines/solr_search_engine/install_solr.md b/docs/search/search_engines/solr_search_engine/install_solr.md index fd619b8ab5..7fd54664a6 100644 --- a/docs/search/search_engines/solr_search_engine/install_solr.md +++ b/docs/search/search_engines/solr_search_engine/install_solr.md @@ -13,30 +13,71 @@ For configuring Solr in other ways, including examples, see [Solr Cores and `sol !!! note "Solr versions" - Supported Solr versions are Solr 7 and 8. Using most recent version of Solr 7.7 or 8.11 is recommended. + Supported Solr versions are Solr 7, 8 and 9. + Using the most recent version of Solr is recommended. Download and extract Solr: - [solr-7.7.2.tgz](http://archive.apache.org/dist/lucene/solr/7.7.2/solr-7.7.2.tgz) or [solr-7.7.2.zip](http://archive.apache.org/dist/lucene/solr/7.7.2/solr-7.7.2.zip) - [solr-8.11.2.tgz](https://www.apache.org/dyn/closer.lua/lucene/solr/8.11.2/solr-8.11.2.tgz) or [solr-8.11.2.zip](https://www.apache.org/dyn/closer.lua/lucene/solr/8.11.2/solr-8.11.2.zip) +- [solr-9.8.1.tgz](https://archive.apache.org/dist/solr/solr/9.8.1/solr-9.8.1.tgz) -Copy the necessary configuration files. In the example below from the root of your project to the place you extracted Solr: +Copy the necessary configuration files. +The examples below copy from the root of your DXP project to the place you've extracted Solr: -``` bash -# Make sure to replace the /opt/solr/ path with where you have placed Solr -cd /opt/solr -mkdir -p server/ibexa/template -cp -R /vendor/ibexa/solr/src/lib/Resources/config/solr/* server/ibexa/template -cp server/solr/configsets/_default/conf/{solrconfig.xml,stopwords.txt,synonyms.txt} server/ibexa/template -cp server/solr/solr.xml server/ibexa - -# Modify solrconfig.xml to remove the section that doesn't agree with your schema -sed -i.bak '//d' server/ibexa/template/solrconfig.xml - -# Start Solr (but apply autocommit settings below first if you need to) -bin/solr -s ibexa -bin/solr create_core -c collection1 -d server/ibexa/template -``` +=== "Solr 9" + + [[= product_name =]] provides the following required configuration files: + + - `vendor/ibexa/solr/src/lib/Resources/config/solr/solr.languages` directory + - `vendor/ibexa/solr/src/lib/Resources/config/solr/managed-schema.xml` + - `vendor/ibexa/solr/src/lib/Resources/config/solr/custom-fields-types-solr9.xml` + - `vendor/ibexa/solr/src/lib/Resources/config/solr/language-fieldtypes.xml` + + + ``` bash + # Make sure to replace the /opt/solr/ path with where you have placed Solr + cd /opt/solr + mkdir -p server/ibexa/template/conf + cp -R /vendor/ibexa/solr/src/lib/Resources/config/solr/solr.languages server/ibexa/template/conf + cp -R /vendor/ibexa/solr/src/lib/Resources/config/solr/{managed-schema.xml,custom-fields-types-solr9.xml,language-fieldtypes.xml} server/ibexa/template/conf + cp server/solr/configsets/_default/conf/{solrconfig.xml,stopwords.txt,synonyms.txt} server/ibexa/template/conf + cp server/solr/solr.xml server/ibexa + + # Modify solrconfig.xml to remove the section that doesn't agree with your schema + sed -i.bak '//d' server/ibexa/template/conf/solrconfig.xml + + # Start Solr (but apply autocommit settings below first if you need to) + # The configuration path is an absolute path + bin/solr -s ibexa + bin/solr create_core -c collection1 -d /opt/solr/server/ibexa/template + ``` + +=== "Solr 7 and 8" + + [[= product_name =]] provides the following required configuration files: + + - `vendor/ibexa/solr/src/lib/Resources/config/solr/solr.languages` directory + - `vendor/ibexa/solr/src/lib/Resources/config/solr/schema.xml` + - `vendor/ibexa/solr/src/lib/Resources/config/solr/custom-fields-types.xml` + - `vendor/ibexa/solr/src/lib/Resources/config/solr/language-fieldtypes.xml` + + ``` bash + # Make sure to replace the /opt/solr/ path with where you have placed Solr + cd /opt/solr + mkdir -p server/ibexa/template + cp -R /vendor/ibexa/solr/src/lib/Resources/config/solr/solr.languages server/ibexa/template + cp -R /vendor/ibexa/solr/src/lib/Resources/config/solr/{schema.xml,custom-fields-types.xml,language-fieldtypes.xml} server/ibexa/template + cp server/solr/configsets/_default/conf/{solrconfig.xml,stopwords.txt,synonyms.txt} server/ibexa/template + cp server/solr/solr.xml server/ibexa + + # Modify solrconfig.xml to remove the section that doesn't agree with your schema + sed -i.bak '//d' server/ibexa/template/solrconfig.xml + + # Start Solr (but apply autocommit settings below first if you need to) + bin/solr -s ibexa + bin/solr create_core -c collection1 -d server/ibexa/template + ``` #### Set up SolrCloud @@ -50,6 +91,8 @@ To set SolrCloud up follow [SolrCloud reference guide](https://solr.apache.org/g ### Continue Solr configuration +#### Configure commit frequency + The bundle doesn't commit Solr index changes directly on repository updates, leaving it up to you to tune this using `solrconfig.xml` as best practice suggests. This setting is **required** if you want to see the changes after publish. @@ -69,9 +112,41 @@ It's strongly recommended to set-up `solrconfig.xml` like this: ``` +#### Configure spellcheck + +Configure the spellcheck component in `solrconfig.xml`: + +```xml + + + default + meta_content__text_t + solr.DirectSolrSpellChecker + internal + 0.5 + 2 + 1 + 5 + 4 + 0.01 + + +``` + +Add this `spellcheck` component to the `/select` request handler: + +```xml + + + spellcheck + + + +``` + ### Generate Solr configuration automatically -The command line tool `bin/generate-solr-config.sh` generates Solr 7 configuration automatically. +The command line tool `bin/generate-solr-config.sh` generates Solr configuration automatically. It can be used for deploying to [[= product_name_cloud =]] (Platform.sh) and on-premise installs. Execute the script from the [[= product_name =]] root directory for further information: @@ -91,6 +166,16 @@ The config further below assumes you have parameters set up for Solr DSN and sea env(SOLR_CORE): collection1 ``` +### Configure Solr version + +When using Solr 9, it's required to set the `version` parameter with the Solr version. +The parameter is optional when using lower Solr versions. + +``` yaml +ibexa_solr: + version: '9.8.1' +``` + ### Single-core example (default) Out of the box in [[= product_name =]] the following is enabled for a setup: @@ -145,6 +230,7 @@ If full language analysis features are preferred, then each language can be conf ``` yaml ibexa_solr: + version: '9.8.1' # Required only if using Solr 9 endpoints: endpoint0: dsn: '%solr_dsn%' diff --git a/docs/templating/components.md b/docs/templating/components.md index adcd682604..16bbfb807e 100644 --- a/docs/templating/components.md +++ b/docs/templating/components.md @@ -8,9 +8,12 @@ month_change: true Twig Components are widgets (for example, **My dashboard** blocks from Headless edition) and HTML code (for example, a tag for loading JS or CSS files) that you can inject into the existing templates to customize and extend the user interface. They are combined into groups that are rendered in designated templates. -Built-in Twig Component groups are available for the [back office](custom_components.md), but you can create your own for use anywhere. +Twig Component groups are available for: -To learn which groups are available in a given view, use the [integration with Symfony Profiler](#symfony-profiler-integration). +- [back office](custom_components.md) +- [storefront](customize_storefront_layout.md) + +To learn which groups are available in a given view, use the [integration Symfony Profiler](#symfony-profiler-integration). ## Create Twig Component @@ -44,11 +47,12 @@ ibexa_twig_components: # Component name google_tag_manager: type: script + priority: 50 arguments: src: 'https://...' ``` -The Component priority cannot be specified when using the YAML configuration, but it allows you to use the built-in components to quickly achieve common goals. +YAML configuration allows you to use the built-in components to quickly achieve common goals. You can use an unique group name when creating a Twig Component to create your own group. @@ -56,11 +60,25 @@ You can use an unique group name when creating a Twig Component to create your o | Name | Description | YAML type | |---|---|---| +| [Controller](https://github.com/ibexa/twig-components/blob/main/src/lib/Component/ControllerComponent.php) | Renders a Symfony controller |`controller` | +| [HTML](https://github.com/ibexa/twig-components/blob/main/src/lib/Component/HtmlComponent.php) | Renders static HTML |`html` | +| [Menu](https://github.com/ibexa/twig-components/blob/main/src/lib/Component/MenuComponent.php) | Renders a [menu](https://symfony.com/bundles/KnpMenuBundle/current/index.html) |`menu` | | [Script](https://github.com/ibexa/twig-components/blob/main/src/lib/Component/ScriptComponent.php) | Renders a [`