Skip to content

Doc for Quable#3085

Merged
mnocon merged 39 commits intorelease-5.0.7from
quable
Apr 14, 2026
Merged

Doc for Quable#3085
mnocon merged 39 commits intorelease-5.0.7from
quable

Conversation

@mnocon
Copy link
Copy Markdown
Contributor

@mnocon mnocon commented Mar 11, 2026

Documentation for the upcoming Quable connector.

Most important changes:

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 11, 2026

Preview of modified files

Preview of modified Markdown:

@mnocon mnocon changed the title [WIP] Doc for Quable Doc for Quable Mar 31, 2026
@mnocon mnocon marked this pull request as ready for review March 31, 2026 11:57
Comment thread code_samples/back_office/search/src/Query/UpdatedAtQuery.php Outdated
Comment thread composer.json Outdated
Copy link
Copy Markdown
Contributor

@adriendupuis adriendupuis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

month_change: true missing in several pages.

When moving from local to Quable:

  • Can I use the local and the Quable PIM at the same time?
  • How do I handle purchases without carts and orders?
  • What happens to taxonomy tree(s) precisely?
  • What are the product search criteria and sort clauses I'll have to stop using?

Some old pages could mention Quable

  • Product catalog configuration could mention quable as another possible value for type.
  • Product search references could indicate what is supported by Quable.

Comment on lines +2 to +3
description: Quable PIM connector configuration reference for Ibexa DXP
page_type: reference
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: Quable PIM connector configuration reference for Ibexa DXP
page_type: reference
description: Quable PIM connector configuration reference for Ibexa DXP
page_type: reference
month_change: true

@@ -0,0 +1,170 @@
---
description: Install and configure Quable PIM connector for Ibexa DXP
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: Install and configure Quable PIM connector for Ibexa DXP
description: Install and configure Quable PIM connector for Ibexa DXP
month_change: true

Comment on lines +2 to +3
description: Quable PIM integration with Ibexa DXP
page_type: landing_page
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: Quable PIM integration with Ibexa DXP
page_type: landing_page
description: Quable PIM integration with Ibexa DXP
page_type: landing_page
month_change: true

Comment on lines +2 to +3
description: The Quable product guide describes how you can use the product data from Quable in Ibexa DXP to create marketing campaigns built around your products.
month_change: false
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description: The Quable product guide describes how you can use the product data from Quable in Ibexa DXP to create marketing campaigns built around your products.
month_change: false
description: The Quable product guide describes how you can use the product data from Quable in Ibexa DXP to create marketing campaigns built around your products.
month_change: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is probably more missing month_change: truethan those abvious ones.


You can use [[= product_name =]] to manage product availability and pricing for [[= pim_product_name =]]'s products, including creating advanced pricing strategies with [discounts](discounts.md) combined with [regions](product_catalog_guide.md#regions) and [currencies](product_catalog_guide.md#currencies).

## Known limitations
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this isn't the place for this section as it get a bit too technical and detailed for a guide. But I see know better place.
As limitation to the capabilities, I would "hide" it a bit under this section.

Suggested change
## Known limitations
### Known limitations

Or even move it down after Use cases?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved down after use cases 👍

Comment on lines +64 to +67
|[ProductName](productname_sort_clause.md)|Product's name|


### Manage stock and pricing
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
|[ProductName](productname_sort_clause.md)|Product's name|
### Manage stock and pricing
|[ProductName](productname_sort_clause.md)|Product's name|
### Manage stock and pricing

Comment on lines +2 to +3
description: Ibexa DXP provides product catalog capabilities for managing products, product types, variants, attributes, pricing, and catalogs.
page_type: landing_page
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduction to the total revamp of what was PIM (https://doc.ibexa.co/en/5.0/pim/pim/) worth being labeled as new.

Suggested change
description: Ibexa DXP provides product catalog capabilities for managing products, product types, variants, attributes, pricing, and catalogs.
page_type: landing_page
description: Ibexa DXP provides product catalog capabilities for managing products, product types, variants, attributes, pricing, and catalogs.
page_type: landing_page
month_change: true

I like this new https://ez-systems-developer-documentation--3085.com.readthedocs.build/en/3085/product_catalog/product_catalog/ by the way.

Comment thread docs/product_catalog/product_catalog.md Outdated
Comment thread docs/index.md
Comment thread mkdocs.yml
Comment thread docs/content_management/rich_text/online_editor_guide.md Outdated
Comment thread docs/content_management/rich_text/online_editor_guide.md Outdated
Comment thread docs/permissions/limitation_reference.md
Comment thread docs/product_catalog/quable/configure_quable_connector.md
Comment thread docs/product_catalog/quable/configure_quable_connector.md Outdated
Comment thread docs/search/sort_clause_reference/product_sort_clauses.md Outdated
### `ibexa_format_product_attribute`

The `ibexa_format_product_attribute` filter formats the attribute value to a readable, translated form.
Rendering is performed using a configurable list of Twig templates with named blocks.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Rendering is performed using a configurable list of Twig templates with named blocks.
Rendering is performed by using a configurable list of Twig templates with named blocks.

"Rendering is performed by using a configurable list of templates..." or rather "Rendering is performed by using templates from a configurable list..." ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to:

Rendering is performed by using Twig templates with named blocks, defined in a configurable list.

Comment thread docs/templating/twig_function_reference/quable_twig_functions.md Outdated
Comment thread docs/templating/twig_function_reference/quable_twig_functions.md Outdated
Comment thread docs/index.md
<li><a href="pim/catalogs/">Catalogs</a></li>
<li><a href="pim/prices/">Prices</a></li>
<li><a href="product_catalog/product_catalog_configuration/">Product catalog configuration</a></li>
<li><a href="product_catalog/quable_integration/">Quable PIM Integration</a></li>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<li><a href="product_catalog/quable_integration/">Quable PIM Integration</a></li>
<li><a href="product_catalog/quable_integration/">Quable PIM Integration add-on</a></li>

Will we add Raptor to the index page as well?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's discuss this after the release - it's a good idea

@mnocon mnocon requested a review from adriendupuis April 14, 2026 08:00
Co-authored-by: Tomasz Dąbrowski <64841871+dabrt@users.noreply.github.com>
mnocon and others added 5 commits April 14, 2026 10:41
Co-authored-by: Tomasz Dąbrowski <64841871+dabrt@users.noreply.github.com>
Co-authored-by: Tomasz Dąbrowski <64841871+dabrt@users.noreply.github.com>
Co-authored-by: Tomasz Dąbrowski <64841871+dabrt@users.noreply.github.com>
@mnocon mnocon requested a review from dabrt April 14, 2026 09:26
| `webhook_secret` | string | Secret expected in the [webhook](https://docs.quable.com/v5-EN/docs/webhook) authorization header. |
| <nobr>`throw_on_invalid_criteria`</nobr> | <nobr>`%kernel.debug%`</nobr> | Controls behavior for unsupported search criteria: `true` throws an exception, `false` only logs unsupported criteria. |
| <nobr>`throw_on_invalid_mapping`</nobr> | <nobr>`%kernel.debug%`</nobr> | 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`, cache decorators use only [in-memory cache](persistence_cache.md#in-memory-cache-configuration). |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| `cache.enabled` | `true` | Global cache switch for the connector. When set to `false`, cache decorators use only [in-memory cache](persistence_cache.md#in-memory-cache-configuration). |
| `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. |

Also, I'd like to note that we are using cache.app.taggable (so indirectly cache.app) to create caching services, which means we are using the cache that is declared for Symfony framework. See https://symfony.com/doc/current/cache.html#system-cache-and-application-cache

cache.app is a general-purpose data cache for application and bundle code. Data in this pool does not need to be flushed on deployment. It defaults to cache.adapter.filesystem, but configuring a faster adapter like Redis is recommended when available (this ensures cached data survives deployments and is shared across multiple instances in a multi-server setup).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added as:

When set to true, [Symfony's cache.app cache pool]([[= symfony_doc =]]/cache.html#system-cache-and-application-cache) is used.

linking to https://symfony.com/doc/current/cache.html#system-cache-and-application-cache

Comment thread docs/product_catalog/quable/install_quable.md Outdated
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 =]].
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Siteaccess cannot use both at the same time. Two repositories would be needed. It is one-or-the-other.

Comment thread docs/product_catalog/quable/install_quable.md Outdated
Comment thread docs/product_catalog/quable/quable_api.md Outdated
- [Catalogs](product_catalog_guide.md#catalogs) can't be created from [[= pim_product_name =]] products.
- Product assets are not fully synchronized. Only the main asset thumbnail URL from [[= pim_product_name =]] is used.
- [Product-level access restrictions](policies.md#products) based on product type are not supported.
- Products with unsupported identifiers (containing `/` or exceeding 64 characters) are not synchronized.
Copy link
Copy Markdown
Contributor

@Steveb-p Steveb-p Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not exactly true.

If product contains / or it's identifier is longer than 64 characters, then certain "attachments" (availability, price management) won't work for it due to our arbitrary limitations (which might / are likely to be changed in upcoming versions).

Suggested change
- Products with unsupported identifiers (containing `/` or exceeding 64 characters) are not synchronized.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to:

  • You can't define prices and availability for products with product codes exceeding 64 characters.
    As discussed on Slack

mnocon and others added 3 commits April 14, 2026 11:45
Co-authored-by: Paweł Niedzielski <pawel.tadeusz.niedzielski@gmail.com>
* Added doc for language configuration

* Apply suggestion from @mnocon
@mnocon mnocon changed the base branch from 5.0 to release-5.0.7 April 14, 2026 11:41
@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown

code_samples/ change report

Before (on target branch)After (in current PR)

code_samples/back_office/search/src/Query/ProductCategorySubtreeQuery.php


code_samples/back_office/search/src/Query/ProductCategorySubtreeQuery.php

docs/search/criteria_reference/productcategorysubtree_criterion.md@20:``` php
docs/search/criteria_reference/productcategorysubtree_criterion.md@21:[[= include_file('code_samples/back_office/search/src/Query/ProductCategorySubtreeQuery.php') =]]
docs/search/criteria_reference/productcategorysubtree_criterion.md@22:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery;
004⫶use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\ProductCategorySubtree;
005⫶
006⫶$taxonomyEntryId = 42;
007⫶$criteria = new ProductCategorySubtree($taxonomyEntryId);
008⫶
009⫶/** @var \Ibexa\Contracts\ProductCatalog\ProductServiceInterface $productService */
010⫶$productQuery = new ProductQuery();
011⫶$productQuery->setQuery($criteria);
012⫶$results = $productService->findProducts($productQuery);


code_samples/back_office/search/src/Query/UpdatedAtQuery.php


code_samples/back_office/search/src/Query/UpdatedAtQuery.php

docs/search/criteria_reference/updated_at_criterion.md@29:``` php
docs/search/criteria_reference/updated_at_criterion.md@30:[[= include_file('code_samples/back_office/search/src/Query/UpdatedAtQuery.php') =]]
docs/search/criteria_reference/updated_at_criterion.md@31:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶use DateTimeImmutable;
004⫶use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery;
005⫶use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\Operator;
006⫶use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\UpdatedAt;
007⫶
008⫶$criteria = new UpdatedAt(
009⫶ new DateTimeImmutable('2023-03-01'),
010⫶ Operator::GTE,
011⫶);
012⫶
013⫶/** @var \Ibexa\Contracts\ProductCatalog\ProductServiceInterface $productService */
014⫶$productQuery = new ProductQuery();
015⫶$productQuery->setQuery($criteria);
016⫶$results = $productService->findProducts($productQuery);


code_samples/back_office/search/src/Query/UpdatedAtRangeQuery.php


code_samples/back_office/search/src/Query/UpdatedAtRangeQuery.php

docs/search/criteria_reference/updated_at_range_criterion.md@21:``` php
docs/search/criteria_reference/updated_at_range_criterion.md@22:[[= include_file('code_samples/back_office/search/src/Query/UpdatedAtRangeQuery.php') =]]
docs/search/criteria_reference/updated_at_range_criterion.md@23:```


code_samples/product_catalog/Symbol/Format/Checksum/LuhnChecksum.php
001⫶<?php declare(strict_types=1);
002⫶
003⫶use DateTimeImmutable;
004⫶use Ibexa\Contracts\ProductCatalog\Values\Product\ProductQuery;
005⫶use Ibexa\Contracts\ProductCatalog\Values\Product\Query\Criterion\UpdatedAtRange;
006⫶
007⫶$criteria = new UpdatedAtRange(
008⫶ new DateTimeImmutable('2020-07-10T00:00:00+00:00'),
009⫶ new DateTimeImmutable('2023-07-12T00:00:00+00:00'),
010⫶);
011⫶
012⫶/** @var \Ibexa\Contracts\ProductCatalog\ProductServiceInterface $productService */
013⫶$productQuery = new ProductQuery();
014⫶$productQuery->setQuery($criteria);
015⫶$results = $productService->findProducts($productQuery);




code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php
code_samples/product_catalog/Symbol/Format/Checksum/LuhnChecksum.php


docs/pim/attributes/symbol_attribute_type.md@68:``` php
docs/pim/attributes/symbol_attribute_type.md@69:[[= include_file('code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php') =]]
docs/pim/attributes/symbol_attribute_type.md@70:```
docs/product_catalog/attributes/symbol_attribute_type.md@68:``` php
docs/product_catalog/attributes/symbol_attribute_type.md@69:[[= include_file('code_samples/product_catalog/Symbol/Format/Checksum/LuhnChecksum.php') =]]
docs/product_catalog/attributes/symbol_attribute_type.md@70:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\PIM\Symbol\Format\Checksum;
006⫶
007⫶use Ibexa\Contracts\ProductCatalog\Values\AttributeDefinitionInterface;
008⫶use Ibexa\Contracts\ProductCatalogSymbolAttribute\Value\ChecksumInterface;
009⫶
010⫶final class LuhnChecksum implements ChecksumInterface
011⫶{
012⫶ public function validate(AttributeDefinitionInterface $attributeDefinition, string $value): bool
013⫶ {
014⫶ $digits = $this->getDigits($value);
015⫶
016⫶ $count = count($digits);
017⫶ $total = 0;
018⫶ for ($i = $count - 2; $i >= 0; $i -= 2) {
019⫶ $digit = $digits[$i];
020⫶ if ($i % 2 === 0) {
021⫶ $digit *= 2;
022⫶ }
023⫶
024⫶ $total += $digit > 9 ? $digit - 9 : $digit;
025⫶ }
026⫶
027⫶ $checksum = $digits[$count - 1];
028⫶
029⫶ return $total + $checksum === 0;
030⫶ }
031⫶
032⫶ /**
033⫶ * Returns an array of digits from the given value (skipping any formatting characters).
034⫶ *
035⫶ * @return int[]
036⫶ */
037⫶ private function getDigits(string $value): array
038⫶ {
039⫶ $chars = array_filter(
040⫶ str_split($value),
041⫶ static fn (string $char): bool => $char !== '-'
042⫶ );
043⫶
044⫶ return array_map(intval(...), array_values($chars));
045⫶ }
046⫶}



001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\PIM\Symbol\Format\Checksum;
006⫶
007⫶use Ibexa\Contracts\ProductCatalog\Values\AttributeDefinitionInterface;
008⫶use Ibexa\Contracts\ProductCatalogSymbolAttribute\Value\ChecksumInterface;
009⫶
010⫶final class LuhnChecksum implements ChecksumInterface
011⫶{
012⫶ public function validate(AttributeDefinitionInterface $attributeDefinition, string $value): bool
013⫶ {
014⫶ $digits = $this->getDigits($value);
015⫶
016⫶ $count = count($digits);
017⫶ $total = 0;
018⫶ for ($i = $count - 2; $i >= 0; $i -= 2) {
019⫶ $digit = $digits[$i];
020⫶ if ($i % 2 === 0) {
021⫶ $digit *= 2;
022⫶ }
023⫶
024⫶ $total += $digit > 9 ? $digit - 9 : $digit;
025⫶ }
026⫶
027⫶ $checksum = $digits[$count - 1];
028⫶
029⫶ return $total + $checksum === 0;
030⫶ }
031⫶
032⫶ /**
033⫶ * Returns an array of digits from the given value (skipping any formatting characters).
034⫶ *
035⫶ * @return int[]
036⫶ */
037⫶ private function getDigits(string $value): array
038⫶ {
039⫶ $chars = array_filter(
040⫶ str_split($value),
041⫶ static fn (string $char): bool => $char !== '-'
042⫶ );
043⫶
044⫶ return array_map(intval(...), array_values($chars));
045⫶ }
046⫶}


code_samples/pim/Symbol/Format/Checksum/LuhnChecksum.php


code_samples/product_catalog/src/EventSubscriber/MyAttributeRenderSubscriber.php

code_samples/product_catalog/src/EventSubscriber/MyAttributeRenderSubscriber.php

docs/product_catalog/customize_product_attribute_templates.md@91:``` php
docs/product_catalog/customize_product_attribute_templates.md@92:[[= include_file('code_samples/product_catalog/src/EventSubscriber/MyAttributeRenderSubscriber.php') =]]
docs/product_catalog/customize_product_attribute_templates.md@93:```

001⫶<?php declare(strict_types=1);
002⫶
003⫶namespace App\EventSubscriber;
004⫶
005⫶use Ibexa\Contracts\ProductCatalog\Events\ProductAttributeRenderEvent;
006⫶use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
007⫶
008⫶final readonly class MyAttributeRenderSubscriber
009⫶{
010⫶ #[AsEventListener]
011⫶ public function onAttributeRender(ProductAttributeRenderEvent $event): void
012⫶ {
013⫶ $event->addTemplateBefore(
014⫶ 'templates/product/attributes/integer_attribute.html.twig',
015⫶ '@ibexadesign/product_catalog/product/attributes/attribute_blocks.html.twig',
016⫶ );
017⫶ }
018⫶}

Download colorized diff

@mnocon mnocon merged commit ee48945 into release-5.0.7 Apr 14, 2026
10 checks passed
@mnocon mnocon deleted the quable branch April 14, 2026 11:57
@mnocon mnocon mentioned this pull request Apr 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs DEV review Needs DOC review Wait with merge PRs that shouldn't be merged instantly

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants