Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
description: Collaborative editing enables multiple users to work on the same content simultaneously.
page_type: landing_page
month_change: true
---

# Collaborative editing

With Collaborative editing feature multiple users can work on the same content created in [[= product_name =]] simultaneously.
This feature allows multiple users to work together on the same content item in real time, streamlining the content creation and review process.

Users can invite both internal and external collaborators to a session, giving them access for editing or previewing.

Additionaly, they can collaborate using a Real-time collaboration premium feature to write and review content in a live mode thanks to CKEditor.
Real-time collaboration syncs changes instantly and shows user avatars and colored tags to indicate who is editing each part of the content.

This feature also introduces new dashboard tabs for managing shared drafts and joining collaboration sessions easily.

[[= cards([
"content_management/collaborative_editing/collaborative_editing",
"content_management/collaborative_editing/collaborative_editing_api",
"content_management/collaborative_editing/invitation_api",
"content_management/collaborative_editing/session_api",
"content_management/collaborative_editing/collaborative_editing_guide"
], columns=3) =]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
description: Use PHP API to manage invitations and sessions while using collaborative editing feature.
month_change: false
---

# Collaborative editing API

[[= product_name =]]'s Collaborative editing API provides two services for managing sessions and invitations, which differ in function:

- [`InvitationServiceInterface`](../api/php_api/php_api_reference/classes/Ibexa-Contracts-(?)-InvitationServiceInterface.html) is used to request product data
- [`SessionServiceInterface`](../api/php_api/php_api_reference/classes/Ibexa-Contracts-(?)-SessionServiceInterface.html) is used to modify products

``` php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Tests\Integration\Collaboration;

use DateTimeImmutable;
use Ibexa\Contracts\Collaboration\Invitation\InvitationCreateStruct;
use Ibexa\Contracts\Collaboration\Invitation\InvitationInterface;
use Ibexa\Contracts\Collaboration\Invitation\InvitationQuery;
use Ibexa\Contracts\Collaboration\Invitation\InvitationStatus;
use Ibexa\Contracts\Collaboration\Invitation\InvitationUpdateStruct;
use Ibexa\Contracts\Collaboration\Invitation\Query\Criterion;
use Ibexa\Contracts\Collaboration\Invitation\Query\SortClause;
use Ibexa\Contracts\Collaboration\InvitationServiceInterface;
use Ibexa\Contracts\Collaboration\SessionServiceInterface;
use Ibexa\Contracts\Core\Repository\Exceptions\InvalidArgumentException;
use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException;
use Ibexa\Contracts\Core\Test\IbexaKernelTestTrait;
use Ibexa\Contracts\CoreSearch\Values\Query\SortDirection;
use Ibexa\Contracts\Test\Core\IbexaKernelTestCase;

final class InvitationServiceTest extends IbexaKernelTestCase
{
use IbexaKernelTestTrait;

private const EXAMPLE_SESSION_ID = 1;
private const EXAMPLE_INVITATION_ID = 1;
private const EXAMPLE_PARTICIPANT_ID = 1;

private const EXAMPLE_INVITATION_A = 1;
private const EXAMPLE_INVITATION_B = 2;
private const EXAMPLE_INVITATION_C = 3;

protected function setUp(): void
{
self::bootKernel();
self::setAdministratorUser();
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
description: Install the Collaborative editing LTS update.
month_change: false
---

# Install Collaborative editing

Collaborative editing feature is available as an LTS update to [[= product_name =]] starting with version v5.0 or higher, regardless of its edition.

Choose a reason for hiding this comment

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

4.6 as opt-in, 5.0 build-in

To use this feature you must first install the packages and configure them.

## Install packages

Run the following commands to install the packages:

``` bash
composer require ibexa/collaboration
composer require ibexa/share
composer require ibexa/fieldtype-richtext-rte
```

Choose a reason for hiding this comment

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

composer require ibexa/share installs also ibexa/collaboration. The same situation for composer require ibexa/fieldtype-richtext-rte - installs also ibexa/ckeditor-premium.
Installing ibexa/collaboration does not include installing ibexa/share :)


This command adds the new real-time editing functionality to the Rich Text field type.
It also modifies the permission system to account for the new functionality.

## Configure Collaborative editing

Once the packages are installed, before you can start Collaborative editing feature, you must enable it by following these instructions.

### Add tables to the database

To add the tables to the database, run the following command:

``` bash
php bin/console ibexa:doctrine:schema:dump-sql vendor/ibexa/collaboration/src/bundle/Resources/config/schema.yaml | mysql -u <username> -p <password> <database_name>
php bin/console ibexa:doctrine:schema:dump-sql vendor/ibexa/share/src/bundle/Resources/config/schema.yaml | mysql -u <username> -p <password> <database_name>
```

### Modify the bundles file

Then, in the `config/bundles.php` file, add the following code:

``` php
<?php

return [
// A lot of bundles…
Ibexa\Bundle\Collaboration\IbexaCollaborationBundle::class => ['all' => true],
Ibexa\Bundle\Share\IbexaShareBundle::class => ['all' => true],
Ibexa\Bundle\FieldTypeRichTextRTE\IbexaFieldTypeRichTextRTEBundle::class => ['all' => true],
];
```

You can now restart you application and start [working with the Collaborative editing feature]([[= user_doc =]]/content_management/collaborative_editing/work_with_collaborative_editing/).
96 changes: 96 additions & 0 deletions docs/content_management/collaborative_editing/invitation_api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
description: You can use the PHP API to create new invitation, update existing one, read or delete it.
---

# Invitation API

[`InvitationService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-InvitationService.html) enables you to read, add, update, and remove invitation for collaborative editing session.

## Create invitation

You can create new invitation for the collaborative session using the [`InvitationService::createInvitation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-InvitationService.html#method_createInvitation) method:

``` php
{
$session = self::getSessionService()->getSession(self::EXAMPLE_SESSION_ID);
$participant = $session->getParticipants()->getById(self::EXAMPLE_PARTICIPANT_ID);

$createStruct = new InvitationCreateStruct($session, $participant);
$createStruct->setContext([
'message' => 'Hello, would you like to join my session?',
]);

$invitation = $this->getInvitationService()->createInvitation($createStruct);

self::assertEquals(InvitationStatus::STATUS_PENDING, $invitation->getStatus());
self::assertEquals([
'message' => 'Hello, would you like to join my session?',
], $invitation->getContext());
}
```

## Read invitation

You can read an invitation with [`InvitationService::getInvitation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-InvitationService.html#method_deleteInvitation):

``` php
$this->getInvitationService()->getInvitation(self::EXAMPLE_INVITATION_ID);
```

You can select the parameter that you can read from an invitaion:

- Invitation ID:

``` php
self::assertEquals(self::EXAMPLE_INVITATION_ID, $invitation->getId());
```

- Session ID:

``` php
self::assertEquals(self::EXAMPLE_SESSION_ID, $invitation->getSession()->getId());
```

- Participant ID:

``` php
self::assertEquals(self::EXAMPLE_PARTICIPANT_ID, $invitation->getParticipant()->getId());
```

- Invitation status:

``` php
self::assertEquals(InvitationStatus::STATUS_PENDING, $invitation->getStatus());
```

## Find invitation

You can find an invitation with [`InvitationService::findInvitation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-InvitationService.html#method_deleteInvitation) by:

- Invitation ID:

``` php
[[= include_file('code_samples/api/public_php_api/src/Command/(?).php', , ) =]]
```

- Session ID:

- Participant ID:

- Invitation status:
Comment on lines +70 to +80
Copy link
Contributor

Choose a reason for hiding this comment

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


## Update invitation

You can update existing invitation with [`InvitationService::deleteInvitation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-InvitationService.html#method_deleteInvitation):

``` php
$invitation = $this->getInvitationService()->getInvitation(self::EXAMPLE_INVITATION_ID);
```

## Delete invitation

You can delete an invitation with [`InvitationService::deleteInvitation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-InvitationService.html#method_deleteInvitation):

``` php
$this->getInvitationService()->deleteInvitation($invitation);
```
93 changes: 93 additions & 0 deletions docs/content_management/collaborative_editing/session_api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
---
description: You can use the PHP API to create new session, update existing one, find or delete it, and add or remove participants.
---

# Session API

[`SessionService`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SessionService.html) enables you work with the collaborative session, for example, create a new one, update or delete existing one, and add or remove new participants to join collaborative session.

## Create session

You can create new collaboration session with given id with [`SessionService::createSession`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SessionService.html#method_createSession):

``` php
$this->innerService->createSession($createStruct);
```
## Get session

You can return existing collaboration session with [`SessionService::getSession`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SessionService.html#method_getSession):

- using given id:

``` php
$this->innerService->getSession($id);
```

- using given token:

``` php
$this->innerService->getSessionByToken($token);
```

- matching the given query:

``` php
$this->innerService->findSessions($query);
```

## Find session

You can find an existing session with [`SessionService::findSession`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SessionService.html#method_findSession) by:

``` php
$this->innerService->findSessions($query);
```

## Update session

You can update existing invitation with [`SessionService::updateSession`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SessionService.html#method_updateSession):

``` php
$this->innerService->updateSession($session, $updateStruct);
```

## Delete session

You can delete session with [`SessionService::deleteSession`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SessionService.html#method_deleteSession):

``` php
$this->innerService->deleteSession($session);
```

# Participant API

## Add participant

You can add participant to the collaboration session with [`SessionService::addParticipant`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SessionService.html#method_addParticipant):

``` php
$this->innerService->addParticipant($session, $createStruct);
```

## Update participant

You can update participant added to the collaboration session with [`SessionService::updateParticipant`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SessionService.html#method_updateParticipant):

``` php
$this->innerService->updateParticipant($session, $participant, $updateStruct);
```
## Remove participant

You can remove participant from the collaboration session with [`SessionService::removeParticipant`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SessionService.html#method_removeParticipant):

``` php
$this->innerService->removeParticipant($session, $participant);
```

## Check session Owner

You can check the Owner of the collaboration session with [`SessionService::removeParticipant`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-SessionService.html#method_removeParticipant):

``` php
$this->innerService->isSessionOwner($session, $user);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
description: CreatedAt Search Criterion
---

# CreatedAt Search Criterion

The `CreatedAt` Search Criterion searches for invitations based on the date they were created.

## Arguments

- `value` - date to be matched, provided as a DateTimeInterface object
- `operator` - optional operator string (EQ, GT, GTE, LT, LTE)

## Example

```php
$criteria = new \Ibexa\Contracts\Collaboration\Invitation\Query\Criterion\CreatedAt(
new DateTime('2025-05-01 14:07:02'),
'GTE'
);

$query = new InvitationQuery($criteria);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
description: CreatedAt Sort Clause
---

# CreatedAt Sort Clause

The `CreatedAt` Sort Clause sorts search results by the date and time of the creation of invitation.

## Arguments

- (optional) `direction` - SortDirection constant, either SortDirection::ASC or SortDirection::DESC.

## Example

```php
$sortClause = [new \Ibexa\Contracts\Collaboration\Invitation\Query\SortClause\CreatedAt(SortDirection::DESC)]);

$query = new InvitationQuery($criteria, sortClause);
```
Loading