-
Notifications
You must be signed in to change notification settings - Fork 83
IBX-9737: Collaborative editing described in Developer Documentation - v4.6 #2721
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 5.0
Are you sure you want to change the base?
Changes from all commits
6a822f8
b52ac68
e22c0d9
d8203ca
3b4f1d5
3207ed3
e65c54b
c0a31b6
cc33bc5
13a094b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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. | ||
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 | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
|
||
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], | ||
]; | ||
``` | ||
|
||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
You can now restart you application and start [working with the Collaborative editing feature]([[= user_doc =]]/content_management/collaborative_editing/work_with_collaborative_editing/). |
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()); | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
``` | ||
|
||
## Read invitation | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
You can read an invitation with [`InvitationService::getInvitation`](../../api/php_api/php_api_reference/classes/Ibexa-Contracts-Core-Repository-InvitationService.html#method_deleteInvitation): | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
``` php | ||
$this->getInvitationService()->getInvitation(self::EXAMPLE_INVITATION_ID); | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
You can select the parameter that you can read from an invitaion: | ||
|
||
- Invitation ID: | ||
|
||
``` php | ||
self::assertEquals(self::EXAMPLE_INVITATION_ID, $invitation->getId()); | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
- Session ID: | ||
|
||
``` php | ||
self::assertEquals(self::EXAMPLE_SESSION_ID, $invitation->getSession()->getId()); | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
- Participant ID: | ||
|
||
``` php | ||
self::assertEquals(self::EXAMPLE_PARTICIPANT_ID, $invitation->getParticipant()->getId()); | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
- Invitation status: | ||
|
||
``` php | ||
self::assertEquals(InvitationStatus::STATUS_PENDING, $invitation->getStatus()); | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
## Find invitation | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here are Criteria which allows to find invitations: https://github.com/ibexa/collaboration/tree/4.6/src/contracts/Invitation/Query/Criterion |
||
|
||
## 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); | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
## 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); | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
julitafalcondusza marked this conversation as resolved.
Show resolved
Hide resolved
|
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); | ||
``` |
There was a problem hiding this comment.
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