From dceac3c9f9c498abe03d18660a744ab7fea83de8 Mon Sep 17 00:00:00 2001
From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com>
Date: Mon, 9 Mar 2026 10:28:34 +0100
Subject: [PATCH 01/11] Add services.yaml and Mapper.php
---
.../collaboration/config/services.yaml | 40 +++++++++++++++++
.../Collaboration/Cart/Persistence/Mapper.php | 44 +++++++++++++++++++
2 files changed, 84 insertions(+)
create mode 100644 code_samples/collaboration/config/services.yaml
create mode 100644 code_samples/collaboration/src/Collaboration/Cart/Persistence/Mapper.php
diff --git a/code_samples/collaboration/config/services.yaml b/code_samples/collaboration/config/services.yaml
new file mode 100644
index 0000000000..4d60f1b59e
--- /dev/null
+++ b/code_samples/collaboration/config/services.yaml
@@ -0,0 +1,40 @@
+# This file is the entry point to configure your own services.
+# Files in the packages/ subdirectory configure your dependencies.
+
+# Put parameters here that don't need to change on each machine where the app is deployed
+# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
+parameters:
+
+services:
+ # default configuration for services in *this* file
+ _defaults:
+ autowire: true # Automatically injects dependencies in your services.
+ autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
+
+ # makes classes in src/ available to be used as services
+ # this creates a service per class whose id is the fully-qualified class name
+ App\:
+ resource: '../src/'
+
+ # add more service definitions when explicit configuration is needed
+ # please note that last definitions always *replace* previous ones
+
+ App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway:
+ tags:
+ - name: 'ibexa.collaboration.persistence.session.gateway'
+ discriminator: !php/const App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway::DISCRIMINATOR
+
+ App\Collaboration\Cart\Persistence\Mapper:
+ tags:
+ - name: 'ibexa.collaboration.persistence.session.mapper'
+ discriminator: !php/const App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway::DISCRIMINATOR
+
+ App\Collaboration\Cart\Mapper\CartSessionPersistenceMapper:
+ tags:
+ - name: 'ibexa.collaboration.service.session.persistence.mapper'
+ type: !php/const App\Collaboration\Cart\CartSessionType::IDENTIFIER
+
+ App\Collaboration\Cart\Mapper\CartSessionDomainMapper:
+ tags:
+ - name: 'ibexa.collaboration.service.session.domain.mapper'
+ type: App\Collaboration\Cart\Persistence\Values\CartSession
diff --git a/code_samples/collaboration/src/Collaboration/Cart/Persistence/Mapper.php b/code_samples/collaboration/src/Collaboration/Cart/Persistence/Mapper.php
new file mode 100644
index 0000000000..36cca970f4
--- /dev/null
+++ b/code_samples/collaboration/src/Collaboration/Cart/Persistence/Mapper.php
@@ -0,0 +1,44 @@
+
+ */
+final class Mapper implements MapperInterface
+{
+ public function extractFromRow(array $row): AbstractSession
+ {
+ return new CartSession(
+ $row['id'],
+ $row['cart_cart_identifier'],
+ $row['token'],
+ $row['owner_id'],
+ $row['is_active'],
+ $row['has_public_link'],
+ $row['created_at'],
+ $row['updated_at']
+ );
+ }
+}
From 64924a6449d1f80b7716e50a6230407ea6170adc Mon Sep 17 00:00:00 2001
From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com>
Date: Mon, 9 Mar 2026 10:30:53 +0100
Subject: [PATCH 02/11] Move SQL to files
---
.../ibexa_collaboration_cart.mysql.sql | 7 +++++++
.../ibexa_collaboration_cart.postgresql.sql | 7 +++++++
.../extend_collaborative_editing.md | 17 ++---------------
3 files changed, 16 insertions(+), 15 deletions(-)
create mode 100644 code_samples/collaboration/ibexa_collaboration_cart.mysql.sql
create mode 100644 code_samples/collaboration/ibexa_collaboration_cart.postgresql.sql
diff --git a/code_samples/collaboration/ibexa_collaboration_cart.mysql.sql b/code_samples/collaboration/ibexa_collaboration_cart.mysql.sql
new file mode 100644
index 0000000000..74b94b6a62
--- /dev/null
+++ b/code_samples/collaboration/ibexa_collaboration_cart.mysql.sql
@@ -0,0 +1,7 @@
+CREATE TABLE ibexa_collaboration_cart (
+ id INT NOT NULL PRIMARY KEY,
+ cart_identifier VARCHAR(255) NOT NULL,
+ CONSTRAINT ibexa_collaboration_cart_ibexa_collaboration_id_fk
+ FOREIGN KEY (id) REFERENCES ibexa_collaboration (id)
+ ON DELETE CASCADE
+) COLLATE = utf8mb4_general_ci;
diff --git a/code_samples/collaboration/ibexa_collaboration_cart.postgresql.sql b/code_samples/collaboration/ibexa_collaboration_cart.postgresql.sql
new file mode 100644
index 0000000000..a073132fca
--- /dev/null
+++ b/code_samples/collaboration/ibexa_collaboration_cart.postgresql.sql
@@ -0,0 +1,7 @@
+CREATE TABLE ibexa_collaboration_cart (
+ id INTEGER NOT NULL PRIMARY KEY,
+ cart_identifier VARCHAR(255) NOT NULL,
+ CONSTRAINT ibexa_collaboration_cart_ibexa_collaboration_id_fk
+ FOREIGN KEY (id) REFERENCES ibexa_collaboration (id)
+ ON DELETE CASCADE
+);
diff --git a/docs/content_management/collaborative_editing/extend_collaborative_editing.md b/docs/content_management/collaborative_editing/extend_collaborative_editing.md
index 4aea75b0e5..d6edb41f90 100644
--- a/docs/content_management/collaborative_editing/extend_collaborative_editing.md
+++ b/docs/content_management/collaborative_editing/extend_collaborative_editing.md
@@ -25,26 +25,13 @@ In this example, it represents the shopping Cart (identified by the Cart identif
=== "MySQL"
``` sql
- CREATE TABLE ibexa_collaboration_cart
- (
- id INT NOT NULL PRIMARY KEY,
- cart_identifier VARCHAR(255) NOT NULL,
- CONSTRAINT ibexa_collaboration_cart_ibexa_collaboration_id_fk
- FOREIGN KEY (id) REFERENCES ibexa_collaboration (id)
- ON DELETE CASCADE
- ) COLLATE = utf8mb4_general_ci;
+ [[= include_file('code_samples/collaboration/ibexa_collaboration_cart.mysql.sql', 0, None, ' ') =]]
```
=== "PostgreSQL"
``` sql
- CREATE TABLE ibexa_collaboration_cart (
- id INTEGER NOT NULL PRIMARY KEY,
- cart_identifier VARCHAR(255) NOT NULL,
- CONSTRAINT ibexa_collaboration_cart_ibexa_collaboration_id_fk
- FOREIGN KEY (id) REFERENCES ibexa_collaboration (id)
- ON DELETE CASCADE
- );
+ [[= include_file('code_samples/collaboration/ibexa_collaboration_cart.postgresql.sql', 0, None, ' ') =]]
```
## Set up the persistence layer
From d6312ad6659cd0d3fc381365e5d2b3b0266f5012 Mon Sep 17 00:00:00 2001
From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com>
Date: Mon, 9 Mar 2026 10:33:39 +0100
Subject: [PATCH 03/11] Remove copyright for sharability
---
.../src/Collaboration/Cart/CartResolverDecorator.php | 8 +-------
.../collaboration/src/Collaboration/Cart/CartSession.php | 8 +-------
.../src/Collaboration/Cart/CartSessionCreateStruct.php | 8 +-------
.../src/Collaboration/Cart/CartSessionType.php | 8 +-------
.../src/Collaboration/Cart/CartSessionUpdateStruct.php | 8 +-------
.../src/Collaboration/Cart/Mapper/CartProxyMapper.php | 8 +-------
.../Cart/Mapper/CartProxyMapperInterface.php | 8 +-------
.../Collaboration/Cart/Mapper/CartSessionDomainMapper.php | 8 +-------
.../Cart/Mapper/CartSessionPersistenceMapper.php | 8 +-------
.../Collaboration/Cart/PermissionResolverDecorator.php | 8 +-------
.../Cart/Persistence/Gateway/DatabaseGateway.php | 8 +-------
.../Cart/Persistence/Gateway/DatabaseSchema.php | 8 +-------
.../src/Collaboration/Cart/Persistence/Mapper.php | 8 +-------
.../Collaboration/Cart/Persistence/Values/CartSession.php | 8 +-------
.../Cart/Persistence/Values/CartSessionCreateStruct.php | 8 +-------
.../Cart/Persistence/Values/CartSessionUpdateStruct.php | 8 +-------
.../collaboration/src/Command/ManageSessionsCommand.php | 8 +-------
.../src/Controller/ShareCartCreateController.php | 8 +-------
.../src/Controller/ShareCartJoinController.php | 8 +-------
.../collaboration/src/Form/Data/ShareCartData.php | 8 +-------
.../collaboration/src/Form/Type/ShareCartType.php | 8 +-------
code_samples/collaboration/src/Query/Search.php | 3 +--
22 files changed, 22 insertions(+), 149 deletions(-)
diff --git a/code_samples/collaboration/src/Collaboration/Cart/CartResolverDecorator.php b/code_samples/collaboration/src/Collaboration/Cart/CartResolverDecorator.php
index 4d879c5dfc..e66a6496e2 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/CartResolverDecorator.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/CartResolverDecorator.php
@@ -1,10 +1,4 @@
-
Date: Mon, 9 Mar 2026 10:46:10 +0100
Subject: [PATCH 04/11] Rector
---
.../src/Collaboration/Cart/CartResolverDecorator.php | 4 ++--
.../src/Collaboration/Cart/CartSession.php | 6 +-----
.../src/Collaboration/Cart/CartSessionCreateStruct.php | 6 +-----
.../src/Collaboration/Cart/CartSessionType.php | 6 +++---
.../src/Collaboration/Cart/Mapper/CartProxyMapper.php | 2 +-
.../Cart/Mapper/CartSessionDomainMapper.php | 2 +-
.../Collaboration/Cart/PermissionResolverDecorator.php | 10 +++++-----
.../Cart/Persistence/Gateway/DatabaseGateway.php | 2 +-
.../Cart/Persistence/Gateway/DatabaseSchema.php | 6 +++---
.../Cart/Persistence/Values/CartSession.php | 6 +-----
.../Persistence/Values/CartSessionCreateStruct.php | 6 +-----
.../src/Controller/ShareCartCreateController.php | 6 +++---
.../src/Controller/ShareCartJoinController.php | 6 +++---
13 files changed, 26 insertions(+), 42 deletions(-)
diff --git a/code_samples/collaboration/src/Collaboration/Cart/CartResolverDecorator.php b/code_samples/collaboration/src/Collaboration/Cart/CartResolverDecorator.php
index e66a6496e2..9bf359e4a9 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/CartResolverDecorator.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/CartResolverDecorator.php
@@ -9,7 +9,7 @@
use Ibexa\Contracts\Core\Repository\Values\User\User;
use Symfony\Component\HttpFoundation\RequestStack;
-final class CartResolverDecorator implements CartResolverInterface
+final readonly class CartResolverDecorator implements CartResolverInterface
{
public function __construct(
private CartResolverInterface $innerCartResolver,
@@ -39,7 +39,7 @@ private function getSharedCart(): ?CartInterface
}
return $session->getCart();
- } catch (NotFoundException|\Ibexa\ProductCatalog\Exception\UnauthorizedException $e) {
+ } catch (NotFoundException|\Ibexa\ProductCatalog\Exception\UnauthorizedException) {
return null;
}
}
diff --git a/code_samples/collaboration/src/Collaboration/Cart/CartSession.php b/code_samples/collaboration/src/Collaboration/Cart/CartSession.php
index 3573889e3e..dcacef4130 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/CartSession.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/CartSession.php
@@ -10,11 +10,9 @@
final class CartSession extends AbstractSession
{
- private CartInterface $cart;
-
public function __construct(
int $id,
- CartInterface $cart,
+ private readonly CartInterface $cart,
string $token,
User $owner,
ParticipantCollectionInterface $participants,
@@ -24,8 +22,6 @@ public function __construct(
DateTimeInterface $updatedAt
) {
parent::__construct($id, $token, $owner, $participants, $isActive, $hasPublicLink, $createdAt, $updatedAt);
-
- $this->cart = $cart;
}
public function getCart(): CartInterface
diff --git a/code_samples/collaboration/src/Collaboration/Cart/CartSessionCreateStruct.php b/code_samples/collaboration/src/Collaboration/Cart/CartSessionCreateStruct.php
index aac0fac021..9594b61cd7 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/CartSessionCreateStruct.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/CartSessionCreateStruct.php
@@ -7,13 +7,9 @@
final class CartSessionCreateStruct extends AbstractSessionCreateStruct
{
- private CartInterface $cart;
-
- public function __construct(CartInterface $cart)
+ public function __construct(private CartInterface $cart)
{
parent::__construct();
-
- $this->cart = $cart;
}
public function getCart(): CartInterface
diff --git a/code_samples/collaboration/src/Collaboration/Cart/CartSessionType.php b/code_samples/collaboration/src/Collaboration/Cart/CartSessionType.php
index 99badde3f9..93c9ab3023 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/CartSessionType.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/CartSessionType.php
@@ -6,10 +6,10 @@
final class CartSessionType implements SessionScopeInterface
{
- public const SCOPE_VIEW = 'view';
- public const SCOPE_EDIT = 'edit';
+ public const string SCOPE_VIEW = 'view';
+ public const string SCOPE_EDIT = 'edit';
- public const IDENTIFIER = 'cart';
+ public const string IDENTIFIER = 'cart';
private function __construct()
{
diff --git a/code_samples/collaboration/src/Collaboration/Cart/Mapper/CartProxyMapper.php b/code_samples/collaboration/src/Collaboration/Cart/Mapper/CartProxyMapper.php
index 39783e80cd..8e719eba26 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/Mapper/CartProxyMapper.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/Mapper/CartProxyMapper.php
@@ -8,7 +8,7 @@
use Ibexa\Core\Repository\ProxyFactory\ProxyGeneratorInterface;
use ProxyManager\Proxy\LazyLoadingInterface;
-final class CartProxyMapper implements CartProxyMapperInterface
+final readonly class CartProxyMapper implements CartProxyMapperInterface
{
public function __construct(
private Repository $repository,
diff --git a/code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionDomainMapper.php b/code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionDomainMapper.php
index 2a4221c558..8f8a51ddb1 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionDomainMapper.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/Mapper/CartSessionDomainMapper.php
@@ -14,7 +14,7 @@
* \App\Collaboration\Cart\Persistence\Values\CartSession
* >
*/
-final class CartSessionDomainMapper implements SessionDomainMapperInterface
+final readonly class CartSessionDomainMapper implements SessionDomainMapperInterface
{
public function __construct(
private CartProxyMapperInterface $cartProxyMapper,
diff --git a/code_samples/collaboration/src/Collaboration/Cart/PermissionResolverDecorator.php b/code_samples/collaboration/src/Collaboration/Cart/PermissionResolverDecorator.php
index 8c086eb1ea..8aba2621ec 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/PermissionResolverDecorator.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/PermissionResolverDecorator.php
@@ -14,14 +14,14 @@
final class PermissionResolverDecorator implements PermissionResolverInterface
{
- public const COLLABORATION_SESSION_ID = 'collaboration_session';
+ public const string COLLABORATION_SESSION_ID = 'collaboration_session';
private bool $nested = false;
public function __construct(
- private PermissionResolverInterface $innerPermissionResolver,
- private SessionServiceInterface $sessionService,
- private RequestStack $requestStack,
+ private readonly PermissionResolverInterface $innerPermissionResolver,
+ private readonly SessionServiceInterface $sessionService,
+ private readonly RequestStack $requestStack,
) {
}
@@ -64,7 +64,7 @@ private function isSharedCart(?CartInterface $cart): bool
if ($session !== null) {
try {
return $cart->getId() === $session->getCart()->getId();
- } catch (NotFoundException $e) {
+ } catch (NotFoundException) {
}
}
} finally {
diff --git a/code_samples/collaboration/src/Collaboration/Cart/Persistence/Gateway/DatabaseGateway.php b/code_samples/collaboration/src/Collaboration/Cart/Persistence/Gateway/DatabaseGateway.php
index 63aaea9394..8ecca9a74b 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/Persistence/Gateway/DatabaseGateway.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/Persistence/Gateway/DatabaseGateway.php
@@ -24,7 +24,7 @@
*/
final class DatabaseGateway extends AbstractDoctrineDatabase implements GatewayInterface
{
- public const DISCRIMINATOR = 'cart';
+ public const string DISCRIMINATOR = 'cart';
protected function buildMetadata(): DoctrineSchemaMetadataInterface
{
diff --git a/code_samples/collaboration/src/Collaboration/Cart/Persistence/Gateway/DatabaseSchema.php b/code_samples/collaboration/src/Collaboration/Cart/Persistence/Gateway/DatabaseSchema.php
index 613510c745..87a556f269 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/Persistence/Gateway/DatabaseSchema.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/Persistence/Gateway/DatabaseSchema.php
@@ -4,10 +4,10 @@
final class DatabaseSchema
{
- public const TABLE_NAME = 'ibexa_collaboration_cart';
+ public const string TABLE_NAME = 'ibexa_collaboration_cart';
- public const COLUMN_ID = 'id';
- public const COLUMN_CART_IDENTIFIER = 'cart_identifier';
+ public const string COLUMN_ID = 'id';
+ public const string COLUMN_CART_IDENTIFIER = 'cart_identifier';
private function __construct()
{
diff --git a/code_samples/collaboration/src/Collaboration/Cart/Persistence/Values/CartSession.php b/code_samples/collaboration/src/Collaboration/Cart/Persistence/Values/CartSession.php
index 64e9a2e985..dd58482adf 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/Persistence/Values/CartSession.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/Persistence/Values/CartSession.php
@@ -7,11 +7,9 @@
final class CartSession extends AbstractSession
{
- private string $cartIdentifier;
-
public function __construct(
int $id,
- string $cartIdentifier,
+ private readonly string $cartIdentifier,
string $token,
int $userId,
bool $isActive,
@@ -20,8 +18,6 @@ public function __construct(
DateTimeImmutable $updatedAt
) {
parent::__construct($id, $token, $userId, $isActive, $hasPublicLink, $createdAt, $updatedAt);
-
- $this->cartIdentifier = $cartIdentifier;
}
public function getCartIdentifier(): string
diff --git a/code_samples/collaboration/src/Collaboration/Cart/Persistence/Values/CartSessionCreateStruct.php b/code_samples/collaboration/src/Collaboration/Cart/Persistence/Values/CartSessionCreateStruct.php
index bc460fb4df..875dc6a87a 100644
--- a/code_samples/collaboration/src/Collaboration/Cart/Persistence/Values/CartSessionCreateStruct.php
+++ b/code_samples/collaboration/src/Collaboration/Cart/Persistence/Values/CartSessionCreateStruct.php
@@ -8,11 +8,9 @@
final class CartSessionCreateStruct extends AbstractSessionCreateStruct
{
- private string $cartIdentifier;
-
public function __construct(
string $token,
- string $cartIdentifier,
+ private string $cartIdentifier,
int $ownerId,
bool $isActive,
bool $hasPublicLink,
@@ -20,8 +18,6 @@ public function __construct(
?DateTimeImmutable $updatedAt = null
) {
parent::__construct($token, $ownerId, $isActive, $hasPublicLink, $createdAt, $updatedAt);
-
- $this->cartIdentifier = $cartIdentifier;
}
public function getCartIdentifier(): string
diff --git a/code_samples/collaboration/src/Controller/ShareCartCreateController.php b/code_samples/collaboration/src/Controller/ShareCartCreateController.php
index 29a4df40b8..b0b612eba4 100644
--- a/code_samples/collaboration/src/Controller/ShareCartCreateController.php
+++ b/code_samples/collaboration/src/Controller/ShareCartCreateController.php
@@ -13,15 +13,15 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
-use Symfony\Component\Routing\Annotation\Route;
+use Symfony\Component\Routing\Attribute\Route;
#[AsController]
#[Route('/shared-cart/create', name: 'app.shared_cart.create')]
final class ShareCartCreateController extends AbstractController
{
public function __construct(
- private SessionServiceInterface $sessionService,
- private CartResolverInterface $cartResolver
+ private readonly SessionServiceInterface $sessionService,
+ private readonly CartResolverInterface $cartResolver
) {
}
diff --git a/code_samples/collaboration/src/Controller/ShareCartJoinController.php b/code_samples/collaboration/src/Controller/ShareCartJoinController.php
index feb7fc1c4e..4c9ecc209b 100644
--- a/code_samples/collaboration/src/Controller/ShareCartJoinController.php
+++ b/code_samples/collaboration/src/Controller/ShareCartJoinController.php
@@ -8,16 +8,16 @@
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Attribute\AsController;
-use Symfony\Component\Routing\Annotation\Route;
+use Symfony\Component\Routing\Attribute\Route;
#[AsController]
#[Route('/shared-cart/join/{token}', name: 'app.shared_cart.join')]
final class ShareCartJoinController extends AbstractController
{
- public const CURRENT_COLLABORATION_SESSION = 'collaboration_session';
+ public const string CURRENT_COLLABORATION_SESSION = 'collaboration_session';
public function __construct(
- private SessionServiceInterface $sessionService,
+ private readonly SessionServiceInterface $sessionService,
) {
}
From 0e9c16f134afc804f27b65a2d4e476606602e4a6 Mon Sep 17 00:00:00 2001
From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com>
Date: Mon, 9 Mar 2026 10:59:52 +0100
Subject: [PATCH 05/11] collaboration_search_reference: Fix highlights
---
.../collaboration_search_reference/collaboration_criteria.md | 2 +-
.../collaboration_sort_clauses.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/search/collaboration_search_reference/collaboration_criteria.md b/docs/search/collaboration_search_reference/collaboration_criteria.md
index b5b909674a..8ef1bed45a 100644
--- a/docs/search/collaboration_search_reference/collaboration_criteria.md
+++ b/docs/search/collaboration_search_reference/collaboration_criteria.md
@@ -50,7 +50,7 @@ Session Search Criteria are implementing the [CriterionInterface](/api/php_api/p
The following example shows how you can use the criteria to find all the currently active sessions:
-```php hl_lines="12-16"
+```php hl_lines="11-15"
[[= include_file('code_samples/collaboration/src/Query/Search.php') =]]
```
diff --git a/docs/search/collaboration_search_reference/collaboration_sort_clauses.md b/docs/search/collaboration_search_reference/collaboration_sort_clauses.md
index be985fb453..33b943f937 100644
--- a/docs/search/collaboration_search_reference/collaboration_sort_clauses.md
+++ b/docs/search/collaboration_search_reference/collaboration_sort_clauses.md
@@ -33,7 +33,7 @@ Session Search Sort Clauses are implementing the [SortClauseInterface](/api/php_
The following example shows how to use them to sort the searched sessions:
-```php hl_lines="18"
+```php hl_lines="17"
[[= include_file('code_samples/collaboration/src/Query/Search.php') =]]
```
From c8f904536e5637cf2282dc6c7d981fce14ddddcd Mon Sep 17 00:00:00 2001
From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com>
Date: Tue, 10 Mar 2026 10:06:20 +0100
Subject: [PATCH 06/11] collaboration/config/services.yaml: Fixes
---
code_samples/collaboration/config/services.yaml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/code_samples/collaboration/config/services.yaml b/code_samples/collaboration/config/services.yaml
index 4d60f1b59e..9fbf759a06 100644
--- a/code_samples/collaboration/config/services.yaml
+++ b/code_samples/collaboration/config/services.yaml
@@ -20,6 +20,8 @@ services:
# please note that last definitions always *replace* previous ones
App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway:
+ arguments:
+ $connection: '@ibexa.persistence.connection'
tags:
- name: 'ibexa.collaboration.persistence.session.gateway'
discriminator: !php/const App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway::DISCRIMINATOR
@@ -38,3 +40,9 @@ services:
tags:
- name: 'ibexa.collaboration.service.session.domain.mapper'
type: App\Collaboration\Cart\Persistence\Values\CartSession
+
+ App\Collaboration\Cart\PermissionResolverDecorator:
+ decorates: Ibexa\Contracts\ProductCatalog\PermissionResolverInterface
+
+ App\Collaboration\Cart\CartResolverDecorator:
+ decorates: Ibexa\Contracts\Cart\CartResolverInterface
From 407261ebea8444e995f9a245690558470cca4652 Mon Sep 17 00:00:00 2001
From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com>
Date: Tue, 10 Mar 2026 12:38:18 +0100
Subject: [PATCH 07/11] collaboration/config/services.yaml: Format
---
code_samples/collaboration/config/services.yaml | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/code_samples/collaboration/config/services.yaml b/code_samples/collaboration/config/services.yaml
index 9fbf759a06..c6d81568ae 100644
--- a/code_samples/collaboration/config/services.yaml
+++ b/code_samples/collaboration/config/services.yaml
@@ -23,24 +23,24 @@ services:
arguments:
$connection: '@ibexa.persistence.connection'
tags:
- - name: 'ibexa.collaboration.persistence.session.gateway'
- discriminator: !php/const App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway::DISCRIMINATOR
+ - name: 'ibexa.collaboration.persistence.session.gateway'
+ discriminator: !php/const App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway::DISCRIMINATOR
App\Collaboration\Cart\Persistence\Mapper:
tags:
- name: 'ibexa.collaboration.persistence.session.mapper'
discriminator: !php/const App\Collaboration\Cart\Persistence\Gateway\DatabaseGateway::DISCRIMINATOR
- App\Collaboration\Cart\Mapper\CartSessionPersistenceMapper:
- tags:
- - name: 'ibexa.collaboration.service.session.persistence.mapper'
- type: !php/const App\Collaboration\Cart\CartSessionType::IDENTIFIER
-
App\Collaboration\Cart\Mapper\CartSessionDomainMapper:
tags:
- name: 'ibexa.collaboration.service.session.domain.mapper'
type: App\Collaboration\Cart\Persistence\Values\CartSession
+ App\Collaboration\Cart\Mapper\CartSessionPersistenceMapper:
+ tags:
+ - name: 'ibexa.collaboration.service.session.persistence.mapper'
+ type: !php/const App\Collaboration\Cart\CartSessionType::IDENTIFIER
+
App\Collaboration\Cart\PermissionResolverDecorator:
decorates: Ibexa\Contracts\ProductCatalog\PermissionResolverInterface
From 46a334c8566c4887c873356715ee218d7e7bf9bb Mon Sep 17 00:00:00 2001
From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com>
Date: Tue, 10 Mar 2026 12:46:29 +0100
Subject: [PATCH 08/11] Move template to storefront theme
standard/cart/view.html.twig is always overridden by storefront/cart/view.html.twig from the bundle
As the template depends on and extends the storefront theme, they're part of it.
---
.../themes/{standard => storefront}/cart/share.html.twig | 0
.../{standard => storefront}/cart/share_result.html.twig | 0
.../themes/{standard => storefront}/cart/view.html.twig | 0
.../collaborative_editing/extend_collaborative_editing.md | 8 ++++----
4 files changed, 4 insertions(+), 4 deletions(-)
rename code_samples/collaboration/templates/themes/{standard => storefront}/cart/share.html.twig (100%)
rename code_samples/collaboration/templates/themes/{standard => storefront}/cart/share_result.html.twig (100%)
rename code_samples/collaboration/templates/themes/{standard => storefront}/cart/view.html.twig (100%)
diff --git a/code_samples/collaboration/templates/themes/standard/cart/share.html.twig b/code_samples/collaboration/templates/themes/storefront/cart/share.html.twig
similarity index 100%
rename from code_samples/collaboration/templates/themes/standard/cart/share.html.twig
rename to code_samples/collaboration/templates/themes/storefront/cart/share.html.twig
diff --git a/code_samples/collaboration/templates/themes/standard/cart/share_result.html.twig b/code_samples/collaboration/templates/themes/storefront/cart/share_result.html.twig
similarity index 100%
rename from code_samples/collaboration/templates/themes/standard/cart/share_result.html.twig
rename to code_samples/collaboration/templates/themes/storefront/cart/share_result.html.twig
diff --git a/code_samples/collaboration/templates/themes/standard/cart/view.html.twig b/code_samples/collaboration/templates/themes/storefront/cart/view.html.twig
similarity index 100%
rename from code_samples/collaboration/templates/themes/standard/cart/view.html.twig
rename to code_samples/collaboration/templates/themes/storefront/cart/view.html.twig
diff --git a/docs/content_management/collaborative_editing/extend_collaborative_editing.md b/docs/content_management/collaborative_editing/extend_collaborative_editing.md
index d6edb41f90..4abb2fbbf2 100644
--- a/docs/content_management/collaborative_editing/extend_collaborative_editing.md
+++ b/docs/content_management/collaborative_editing/extend_collaborative_editing.md
@@ -242,22 +242,22 @@ The form collects the email address of the user that you want to invite, and the
The last step is to integrate the new session type into your application by adding templates.
In this step, the view is rendered.
-You need to add following templates in the `templates/themes/standard/cart` folder:
+You need to add following templates in the `templates/themes/storefront/cart` folder:
- `share` - this Twig template defines the view for the Cart sharing form. It renders the form where a user can enter an email address to invite someone to collaborate on the Cart.
``` php
-[[= include_file('code_samples/collaboration/templates/themes/standard/cart/share.html.twig') =]]
+[[= include_file('code_samples/collaboration/templates/themes/storefront/cart/share.html.twig') =]]
```
- `share_result` - this Twig template renders the result page after a Cart has been shared. If the shared Cart exists in the system, the created session object is passed to the view and displayed. A message like "Cart has been shared…" is displayed, along with a link to access the session.
``` php
-[[= include_file('code_samples/collaboration/templates/themes/standard/cart/share_result.html.twig') =]]
+[[= include_file('code_samples/collaboration/templates/themes/storefront/cart/share_result.html.twig') =]]
```
- `view` - is the template that shows the Cart page. It displays the Cart content and includes the “Share Cart” button and other elements for Cart collaboration.
``` php
-[[= include_file('code_samples/collaboration/templates/themes/standard/cart/view.html.twig') =]]
+[[= include_file('code_samples/collaboration/templates/themes/storefront/cart/view.html.twig') =]]
```
From 50498ddf8d891851399fb51bf418d6de167fde90 Mon Sep 17 00:00:00 2001
From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com>
Date: Tue, 10 Mar 2026 13:15:21 +0100
Subject: [PATCH 09/11] Redesign share.html.twig for storefront
---
code_samples/collaboration/src/Form/Type/ShareCartType.php | 3 +++
.../templates/themes/storefront/cart/share.html.twig | 5 +++--
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/code_samples/collaboration/src/Form/Type/ShareCartType.php b/code_samples/collaboration/src/Form/Type/ShareCartType.php
index aa2009f7f9..86f2369bcb 100644
--- a/code_samples/collaboration/src/Form/Type/ShareCartType.php
+++ b/code_samples/collaboration/src/Form/Type/ShareCartType.php
@@ -5,6 +5,7 @@
use App\Form\Data\ShareCartData;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
+use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
@@ -17,6 +18,8 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder->add('email', EmailType::class, [
'label' => 'E-mail',
+ ])->add('submit', SubmitType::class, [
+ 'label' => 'Share',
]);
}
diff --git a/code_samples/collaboration/templates/themes/storefront/cart/share.html.twig b/code_samples/collaboration/templates/themes/storefront/cart/share.html.twig
index 14a2ed2388..f4ba2e2913 100644
--- a/code_samples/collaboration/templates/themes/storefront/cart/share.html.twig
+++ b/code_samples/collaboration/templates/themes/storefront/cart/share.html.twig
@@ -2,7 +2,8 @@
{% block content %}
{{ form_start(form) }}
- {{ form_widget(form) }}
-
+ {{ form_label(form.email, null, { 'label_attr': { 'class': 'ibexa-store-label' }}) }}
+ {{ form_widget(form.email, { 'attr': { 'class': 'ibexa-store-input' } }) }}
+ {{ form_widget(form.submit, { 'attr': { 'class': 'ibexa-store-btn ibexa-store-btn--primary' } }) }}
{{ form_end(form) }}
{% endblock %}
From 7e74373a49a88524135f1aee7e60360715514702 Mon Sep 17 00:00:00 2001
From: Adrien Dupuis <61695653+adriendupuis@users.noreply.github.com>
Date: Tue, 10 Mar 2026 13:15:53 +0100
Subject: [PATCH 10/11] Simplify cart/view.html.twig
---
.../themes/storefront/cart/view.html.twig | 51 +------------------
1 file changed, 1 insertion(+), 50 deletions(-)
diff --git a/code_samples/collaboration/templates/themes/storefront/cart/view.html.twig b/code_samples/collaboration/templates/themes/storefront/cart/view.html.twig
index e7900e130e..922e21be24 100644
--- a/code_samples/collaboration/templates/themes/storefront/cart/view.html.twig
+++ b/code_samples/collaboration/templates/themes/storefront/cart/view.html.twig
@@ -1,57 +1,8 @@
-{% extends '@ibexadesign/storefront/layout.html.twig' %}
-
-{% trans_default_domain 'ibexa_storefront' %}
-
-{% macro render_notice_messages(messages) %}
- {% for message in messages -%}
- {{ message }}{{ not loop.last ? '
' }}
- {%- endfor %}
-{% endmacro %}
+{% extends '@IbexaStorefront/themes/storefront/cart/view.html.twig' %}
{% block content %}
- Cart has been shared successfully! Link to session: + Cart has been shared successfully! Link to session: {{ url('app.shared_cart.join', { token: session.getToken() }) }}