From 8b3e1f50af823543c7f5cfde2aa180b844d6ca34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Fri, 8 May 2026 11:35:07 +0200 Subject: [PATCH 1/7] Expanded product availability --- .../src/Command/ProductCommand.php | 21 ++++-- .../availability/config/custom_services.yaml | 4 ++ ...abilityPurchasableWithoutStockStrategy.php | 68 +++++++++++++++++++ ...hasableWithoutStockAvailabilityContext.php | 9 +++ .../create_custom_availability_strategy.md | 53 +++++++++++++++ docs/pim/customize_pim.md | 1 + docs/pim/product_api.md | 32 ++++++--- docs/pim/products.md | 22 ++++-- .../productavailability_criterion.md | 8 ++- mkdocs.yml | 3 +- 10 files changed, 199 insertions(+), 22 deletions(-) create mode 100644 code_samples/pim/availability/config/custom_services.yaml create mode 100644 code_samples/pim/availability/src/ProductAvailabilityPurchasableWithoutStockStrategy.php create mode 100644 code_samples/pim/availability/src/PurchasableWithoutStockAvailabilityContext.php create mode 100644 docs/pim/create_custom_availability_strategy.md diff --git a/code_samples/api/product_catalog/src/Command/ProductCommand.php b/code_samples/api/product_catalog/src/Command/ProductCommand.php index 530fabcd51..8d615d461e 100644 --- a/code_samples/api/product_catalog/src/Command/ProductCommand.php +++ b/code_samples/api/product_catalog/src/Command/ProductCommand.php @@ -10,6 +10,7 @@ use Ibexa\Contracts\ProductCatalog\ProductTypeServiceInterface; use Ibexa\Contracts\ProductCatalog\Values\Availability\ProductAvailabilityCreateStruct; use Ibexa\Contracts\ProductCatalog\Values\Availability\ProductAvailabilityUpdateStruct; +use App\ProductCatalog\Availability\PurchasableWithoutStockAvailabilityContext; use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; use Ibexa\Contracts\ProductCatalog\Values\Product\Query\SortClause; @@ -98,26 +99,34 @@ protected function execute(InputInterface $input, OutputInterface $output): int $product = $this->productService->getProduct('NEWMODIFIEDPRODUCT'); - $productAvailabilityCreateStruct = new ProductAvailabilityCreateStruct($product, true, true); + $productAvailabilityCreateStruct = new ProductAvailabilityCreateStruct($product, false, true); $this->productAvailabilityService->createProductAvailability($productAvailabilityCreateStruct); if ($this->productAvailabilityService->hasAvailability($product)) { $availability = $this->productAvailabilityService->getAvailability($product); - $output->write($availability->isAvailable() ? 'Available' : 'Unavailable'); - $output->writeln(' with stock ' . $availability->getStock()); - - $availability = $this->productAvailabilityService->getAvailability($product); + $output->writeln($availability->getAvailability() ? 'Available flag: true' : 'Available flag: false'); + $output->writeln($availability->getComputedAvailability() ? 'Can be ordered: true' : 'Can be ordered: false'); + $output->writeln('Stock: ' . $availability->getStock()); $productAvailabilityUpdateStruct = new ProductAvailabilityUpdateStruct($product, true, false, 80); $this->productAvailabilityService->updateProductAvailability($productAvailabilityUpdateStruct); - $output->write($availability->isAvailable() ? 'Available' : 'Unavailable'); + $output->writeln($availability->getAvailability() ? 'Available flag: true' : 'Available flag: false'); + $output->writeln($availability->getComputedAvailability() ? 'Can be ordered: true' : 'Can be ordered: false'); $output->writeln(' available now with stock ' . $availability->getStock()); } + $availability = $this->productAvailabilityService->getAvailability( + $product, + new PurchasableWithoutStockAvailabilityContext() + ); + + $canBeOrdered = $availability->getComputedAvailability(); + $output->writeln('Can be ordered: ' . ($canBeOrdered ? 'true' : 'false') . ', Stock: ' . $availability->getStock()); + $this->localProductService->deleteProduct($product); return self::SUCCESS; diff --git a/code_samples/pim/availability/config/custom_services.yaml b/code_samples/pim/availability/config/custom_services.yaml new file mode 100644 index 0000000000..8a99cbe0b3 --- /dev/null +++ b/code_samples/pim/availability/config/custom_services.yaml @@ -0,0 +1,4 @@ +services: + App\ProductCatalog\Availability\ProductAvailabilityPurchasableWithoutStockStrategy: + tags: + - { name: ibexa.product_catalog.availability.strategy } diff --git a/code_samples/pim/availability/src/ProductAvailabilityPurchasableWithoutStockStrategy.php b/code_samples/pim/availability/src/ProductAvailabilityPurchasableWithoutStockStrategy.php new file mode 100644 index 0000000000..5827493b42 --- /dev/null +++ b/code_samples/pim/availability/src/ProductAvailabilityPurchasableWithoutStockStrategy.php @@ -0,0 +1,68 @@ +handler->find($product->getCode()); + + $rawAvailableFlag = $productAvailability->isAvailable(); + $stock = $productAvailability->getStock(); + $isInfinite = $productAvailability->isInfinite(); + + $computedAvailable = $this->calculateAvailability( + $rawAvailableFlag, + $stock, + $isInfinite, + ); + + return new Availability( + $product, + $rawAvailableFlag, + $computedAvailable, + $isInfinite, + $stock, + ); + } + + private function calculateAvailability( + bool $rawAvailable, + ?int $stock, + bool $isInfinite, + ): bool { + if ($rawAvailable === false) { + return false; + } + + if ($isInfinite) { + return true; + } + + if ($stock === null) { + return true; + } + + return $stock >= 0; + } +} diff --git a/code_samples/pim/availability/src/PurchasableWithoutStockAvailabilityContext.php b/code_samples/pim/availability/src/PurchasableWithoutStockAvailabilityContext.php new file mode 100644 index 0000000000..e8e8e547f6 --- /dev/null +++ b/code_samples/pim/availability/src/PurchasableWithoutStockAvailabilityContext.php @@ -0,0 +1,9 @@ + Date: Fri, 8 May 2026 11:36:04 +0200 Subject: [PATCH 2/7] Fixer --- code_samples/api/product_catalog/src/Command/ProductCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code_samples/api/product_catalog/src/Command/ProductCommand.php b/code_samples/api/product_catalog/src/Command/ProductCommand.php index 8d615d461e..4f486d7c4b 100644 --- a/code_samples/api/product_catalog/src/Command/ProductCommand.php +++ b/code_samples/api/product_catalog/src/Command/ProductCommand.php @@ -2,6 +2,7 @@ namespace App\Command; +use App\ProductCatalog\Availability\PurchasableWithoutStockAvailabilityContext; use Ibexa\Contracts\Core\Repository\PermissionResolver; use Ibexa\Contracts\Core\Repository\UserService; use Ibexa\Contracts\ProductCatalog\Local\LocalProductServiceInterface; @@ -10,7 +11,6 @@ use Ibexa\Contracts\ProductCatalog\ProductTypeServiceInterface; use Ibexa\Contracts\ProductCatalog\Values\Availability\ProductAvailabilityCreateStruct; use Ibexa\Contracts\ProductCatalog\Values\Availability\ProductAvailabilityUpdateStruct; -use App\ProductCatalog\Availability\PurchasableWithoutStockAvailabilityContext; use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery; use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion; use Ibexa\Contracts\ProductCatalog\Values\Product\Query\SortClause; From 2fcdf0c5c7f9ba9d7d66a7ac94785f5b5da91bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Fri, 8 May 2026 11:37:34 +0200 Subject: [PATCH 3/7] Adapted to PHP 7,4 --- ...ctAvailabilityPurchasableWithoutStockStrategy.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/code_samples/pim/availability/src/ProductAvailabilityPurchasableWithoutStockStrategy.php b/code_samples/pim/availability/src/ProductAvailabilityPurchasableWithoutStockStrategy.php index 5827493b42..384e2757ac 100644 --- a/code_samples/pim/availability/src/ProductAvailabilityPurchasableWithoutStockStrategy.php +++ b/code_samples/pim/availability/src/ProductAvailabilityPurchasableWithoutStockStrategy.php @@ -11,9 +11,11 @@ final class ProductAvailabilityPurchasableWithoutStockStrategy implements ProductAvailabilityStrategyInterface { - public function __construct( - private readonly HandlerInterface $handler, - ) { + private HandlerInterface $handler; + + public function __construct(HandlerInterface $handler) + { + $this->handler = $handler; } public function accept(AvailabilityContextInterface $context): bool @@ -23,7 +25,7 @@ public function accept(AvailabilityContextInterface $context): bool public function getProductAvailability( ProductInterface $product, - AvailabilityContextInterface $context, + AvailabilityContextInterface $context ): AvailabilityInterface { $productAvailability = $this->handler->find($product->getCode()); @@ -49,7 +51,7 @@ public function getProductAvailability( private function calculateAvailability( bool $rawAvailable, ?int $stock, - bool $isInfinite, + bool $isInfinite ): bool { if ($rawAvailable === false) { return false; From 6ccb073695504c7e3f409a268656ebbf81aa0e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Fri, 8 May 2026 11:41:14 +0200 Subject: [PATCH 4/7] Vale --- docs/pim/create_custom_availability_strategy.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/pim/create_custom_availability_strategy.md b/docs/pim/create_custom_availability_strategy.md index a3d39b799f..153ac26593 100644 --- a/docs/pim/create_custom_availability_strategy.md +++ b/docs/pim/create_custom_availability_strategy.md @@ -1,16 +1,16 @@ --- -description: +description: Implement custom availability strategies to handle different business scenarios, for example pre-orders or per-region availability. --- # Create custom availability strategy -The product catalog uses an availability strategy to calculate [computed availability](products.md#availability-and-computed-availability) for a product. -The default strategy determines whether a product can be ordered based on its stored availability and stock. +The product catalog uses an availability strategy to calculate [computed availability](products.md#availability-and-computed-availability) for a product, deciding whether the customers can order it. +The default is based on the product availability and stock amount. -You can replace this logic with a custom strategy to handle specific business scenarios, for example preoders, minimum order quantities, or per-region availability. +You can replace this logic with a custom strategy to handle specific business scenarios, for example pre-oders, minimum order quantities, or per-region availability. The following example implements an availability strategy which allows buying products when they're set as available, without taking their stock into account. -You could use it for [virtual products](products.md#product-types) or in preorder scenarios. +You could use it for [virtual products](products.md#product-types) or in pre-order scenarios. ## Create a custom availability context From 4ec36b7a4c3cd924c5417cd6480c1b236e69d8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Fri, 8 May 2026 12:01:46 +0200 Subject: [PATCH 5/7] Adjusted code samples --- docs/pim/product_api.md | 50 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/docs/pim/product_api.md b/docs/pim/product_api.md index 72449268fb..16d64ee93b 100644 --- a/docs/pim/product_api.md +++ b/docs/pim/product_api.md @@ -21,7 +21,7 @@ month_change: false Get an individual product by using the `ProductServiceInterface::getProduct()` method: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductCommand.php', 68, 71) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductCommand.php', 70, 72, remove_indent=True) =]] ``` Find multiple products with `ProductServiceInterface::findProducts()`. @@ -29,7 +29,7 @@ Find multiple products with `ProductServiceInterface::findProducts()`. Provide the method with optional filter, query or Sort Clauses. ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductCommand.php', 72, 82) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductCommand.php', 74, 83, remove_indent=True) =]] ``` See [Product Search Criteria](product_search_criteria.md) and [Product Sort Clauses](product_sort_clauses.md) references for more information about how to use the [`ProductQuery`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Product-ProductQuery.html) class. @@ -39,7 +39,7 @@ See [Product Search Criteria](product_search_criteria.md) and [Product Sort Clau To create, update and delete products, use the `LocalProductServiceInterface`. ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductCommand.php', 93, 97) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductCommand.php', 95, 98, remove_indent=True) =]] ``` To create a product, use `LocalProductServiceInterface::newProductCreateStruct()` to get a [`ProductCreateStruct`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Local-Values-Product-ProductCreateStruct.html). @@ -47,13 +47,13 @@ Provide the method with the product type object and the main language code. You also need to set (at least) the code for the product and the required Field of the underlying content type, `name`: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductCommand.php', 83, 90) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductCommand.php', 85, 89, remove_indent=True) =]] ``` To delete a product, use `LocalProductServiceInterface::deleteProduct()`: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductCommand.php', 120, 121) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductCommand.php', 130, 130, remove_indent=True) =]] ``` ### Product variants @@ -65,13 +65,13 @@ A `ProductVariantQuery` lets you define the offset and limit of the variant quer The default offset is 0, and limit is 25. ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductVariantCommand.php', 57, 60) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductVariantCommand.php', 58, 60, remove_indent=True) =]] ``` From a variant ([`ProductVariantInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-ProductVariantInterface.html)), you can access the attributes that are used to generate the variant by using `ProductVariantInterface::getDiscriminatorAttributes()`. ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductVariantCommand.php', 61, 68) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductVariantCommand.php', 62, 68, remove_indent=True) =]] ``` #### Creating variants @@ -81,7 +81,7 @@ This method takes the product and an array of [`ProductVariantCreateStruct`](/ap `ProductVariantCreateStruct` specifies the attribute values and the code for the new variant. ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductVariantCommand.php', 70, 76) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductVariantCommand.php', 71, 76, remove_indent=True) =]] ``` ### Product assets @@ -91,14 +91,14 @@ You can get assets assigned to a product by using [`AssetServiceInterface`](/api Use `AssetServiceInterface` to get a single asset by providing the product object and the assets's ID as parameters: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductAssetCommand.php', 54, 56) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductAssetCommand.php', 55, 56, remove_indent=True) =]] ``` To get all assets assigned to a product, use `AssetServiceInterface::findAssets()`. You can retrieve the tags (corresponding to attribute values) of assets with the `AssetInterface::getTags()` method: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductAssetCommand.php', 57, 66) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductAssetCommand.php', 58, 66, remove_indent=True) =]] ``` ## Product types @@ -112,19 +112,19 @@ To create a product type, use [`LocalProductTypeServiceInterface`](/api/php_api/ First, create a product type struct with `LocalProductTypeServiceInterface::newProductTypeCreateStruct()`, providing the identifier and main language code: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 62, 66) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 63, 66, remove_indent=True) =]] ``` You can set names in multiple languages by using `setNames()`: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 67, 71) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 68, 71, remove_indent=True) =]] ``` To create a virtual product type (for products that don't require shipping), use `setVirtual()`: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 72, 73) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 73, 73, remove_indent=True) =]] ``` #### Adding field definitions @@ -133,7 +133,7 @@ To add custom field definitions to the product type, use `getContentTypeCreateSt For more information about working with content types, see [Adding content types](../content_management/content_api/managing_content.md#adding-content-types). ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 76, 83) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 77, 83, remove_indent=True) =]] ``` #### Assigning attributes @@ -143,13 +143,13 @@ To assign product attributes to the product type, use `setAssignedAttributesDefi First, retrieve the attribute definition by using [`AttributeDefinitionServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-AttributeDefinitionServiceInterface.html): ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 84, 85) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 85, 85, remove_indent=True) =]] ``` Then create the assignment struct with the attribute definition, and set whether it's required and whether it's a discriminator (used for product variants): ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 86, 93) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 87, 93, remove_indent=True) =]] ``` For more information about working with attributes through PHP API, see [Attributes](#attributes). @@ -159,7 +159,7 @@ For more information about working with attributes through PHP API, see [Attribu Finally, create the product type with `LocalProductTypeServiceInterface::createProductType()`: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 94, 95) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 94, 95, remove_indent=True) =]] ``` ### Getting product types @@ -167,13 +167,13 @@ Finally, create the product type with `LocalProductTypeServiceInterface::createP Get a product type object by using `ProductTypeServiceInterface::getProductType()`: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 96, 97) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 97, 97, remove_indent=True) =]] ``` You can also get a list of product types with `ProductTypeServiceInterface::findProductTypes()`: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 100, 105) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/ProductTypeCommand.php', 101, 105, remove_indent=True) =]] ``` ## Product availability @@ -211,8 +211,6 @@ The second parameter defines whether product is available, and the third whether [[= include_code('code_samples/api/product_catalog/src/Command/ProductCommand.php', 113, 115, remove_indent=True) =]] ``` - - ## Attributes To get information about product attribute groups, use the [`AttributeGroupServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-AttributeGroupServiceInterface.html), or [`LocalAttributeGroupServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Local-LocalAttributeGroupServiceInterface.html) to modify attribute groups. @@ -221,24 +219,24 @@ To get information about product attribute groups, use the [`AttributeGroupServi `AttributeGroupServiceInterface::findAttributeGroups()` gets attribute groups, all of them or filtered with an optional [`AttributeGroupQuery`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-AttributeGroup-AttributeGroupQuery.html) object: ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/AttributeCommand.php', 71, 72) =]] -[[= include_file('code_samples/api/product_catalog/src/Command/AttributeCommand.php', 92, 97) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/AttributeCommand.php', 72, 72, remove_indent=True) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/AttributeCommand.php', 93, 97, remove_indent=True) =]] ``` To create an attribute group, use `LocalAttributeGroupServiceinterface::createAttributeGroup()` and provide it with an [`AttributeGroupCreateStruct`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Local-Values-AttributeGroup-AttributeGroupCreateStruct.html): ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/AttributeCommand.php', 66, 70) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/AttributeCommand.php', 67, 70, remove_indent=True) =]] ``` To get information about product attributes, use the [`AttributeDefinitionServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-AttributeDefinitionServiceInterface.html), or [`LocalAttributeDefinitionServiceInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Local-LocalAttributeDefinitionServiceInterface.html) to modify attributes. ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/AttributeCommand.php', 78, 80) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/AttributeCommand.php', 79, 80, remove_indent=True) =]] ``` To create an attribute, use `LocalAttributeGroupServiceinterface::createAttributeDefinition()` and provide it with an [`AttributeDefinitionCreateStruct`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Local-Values-AttributeDefinition-AttributeDefinitionCreateStruct.html): ``` php -[[= include_file('code_samples/api/product_catalog/src/Command/AttributeCommand.php', 83, 89) =]] +[[= include_code('code_samples/api/product_catalog/src/Command/AttributeCommand.php', 84, 89, remove_indent=True) =]] ``` From b3ef778b833f577d256d265fa3ecbdb14bc1fe01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Fri, 8 May 2026 12:40:43 +0200 Subject: [PATCH 6/7] Preoder --- docs/pim/create_custom_availability_strategy.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/pim/create_custom_availability_strategy.md b/docs/pim/create_custom_availability_strategy.md index 153ac26593..c8b047401c 100644 --- a/docs/pim/create_custom_availability_strategy.md +++ b/docs/pim/create_custom_availability_strategy.md @@ -7,10 +7,10 @@ description: Implement custom availability strategies to handle different busine The product catalog uses an availability strategy to calculate [computed availability](products.md#availability-and-computed-availability) for a product, deciding whether the customers can order it. The default is based on the product availability and stock amount. -You can replace this logic with a custom strategy to handle specific business scenarios, for example pre-oders, minimum order quantities, or per-region availability. +You can replace this logic with a custom strategy to handle specific business scenarios, for example preorders, minimum order quantities, or per-region availability. The following example implements an availability strategy which allows buying products when they're set as available, without taking their stock into account. -You could use it for [virtual products](products.md#product-types) or in pre-order scenarios. +You could use it for [virtual products](products.md#product-types) or in preorder scenarios. ## Create a custom availability context From 4538d614c2be01ca1d16d39acc84358bd3c9062a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Fri, 8 May 2026 12:43:41 +0200 Subject: [PATCH 7/7] Selfreview --- docs/pim/create_custom_availability_strategy.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/pim/create_custom_availability_strategy.md b/docs/pim/create_custom_availability_strategy.md index c8b047401c..6a23d1b45d 100644 --- a/docs/pim/create_custom_availability_strategy.md +++ b/docs/pim/create_custom_availability_strategy.md @@ -12,16 +12,16 @@ You can replace this logic with a custom strategy to handle specific business sc The following example implements an availability strategy which allows buying products when they're set as available, without taking their stock into account. You could use it for [virtual products](products.md#product-types) or in preorder scenarios. -## Create a custom availability context +## Create custom availability context -An availability context carries the parameters needed by the strategy to evaluate computed availability. -Create a class implementing [`AvailabilityContextInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Availability-AvailabilityContextInterface.html): +Use an availability context to pass the parameters needed by the strategy to evaluate computed availability. +To do it, create a class implementing the [`AvailabilityContextInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-Values-Availability-AvailabilityContextInterface.html) interface: ``` php [[= include_file('code_samples/pim/availability/src/PurchasableWithoutStockAvailabilityContext.php') =]] ``` -## Create a custom availability strategy +## Create custom availability strategy Create a class implementing [`ProductAvailabilityStrategyInterface`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-ProductAvailabilityStrategyInterface.html): @@ -36,17 +36,17 @@ The strategy has two methods: When constructing the `AvailabilityInterface` object, provide the stock amount, the availability flag, and the result of your custom availability logic. -## Register the strategy as a service +## Register strategy as a service -Tag the strategy service with `ibexa.product_catalog.availability.strategy`: +If you're not using [autowiring]([[= symfony_doc =]]/service_container/autowiring.html), tag the strategy service with `ibexa.product_catalog.availability.strategy`: ``` yaml [[= include_file('code_samples/pim/availability/config/custom_services.yaml') =]] ``` -## Use the custom context +## Use custom context -Pass the custom context as the second argument to [`ProductAvailabilityServiceInterface::getAvailability()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-ProductAvailabilityServiceInterface.html): +To evaluate product availability using a custom strategy, pass the custom context as the second argument to [`ProductAvailabilityServiceInterface::getAvailability()`](/api/php_api/php_api_reference/classes/Ibexa-Contracts-ProductCatalog-ProductAvailabilityServiceInterface.html): ```php [[= include_code('code_samples/api/product_catalog/src/Command/ProductCommand.php', 122, 127, remove_indent=True) =]]