Documentation >
Content management >
Collaborative editing >
Install and configure Collaborative editing
Install Collaborative editing
Collaborative editing feature is available as an LTS update to Ibexa DXP starting with version v4.6.24 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:
composer require ibexa/collaboration
composer require ibexa/share
If you have an arrangements with Ibexa to use Real-time editing feature, you also need to install following package:
composer require ibexa/fieldtype-richtext-rte
This command instals also ibexa/ckeditor-premium
package and 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.
Add tables to the database
Add the tables to the database:
Create the ibexa_share.sql
file that contains the following code:
MySQL PostgreSQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95 CREATE TABLE ibexa_collaboration
(
id INT AUTO_INCREMENT NOT NULL ,
owner_id INT NOT NULL ,
token VARCHAR ( 160 ) NOT NULL ,
discriminator VARCHAR ( 190 ) NOT NULL ,
is_active TINYINT ( 1 ) NOT NULL ,
has_public_link TINYINT ( 1 ) NOT NULL ,
created_at DATETIME NOT NULL COMMENT '(DC2Type:datetimetz_immutable)' ,
updated_at DATETIME NOT NULL COMMENT '(DC2Type:datetimetz_immutable)' ,
UNIQUE INDEX ibexa_collaboration_token_idx ( token ),
INDEX ibexa_collaboration_owner_idx ( owner_id ),
UNIQUE INDEX ibexa_collaboration_token_uc ( token ),
PRIMARY KEY ( id )
) DEFAULT CHARACTER SET utf8mb4
COLLATE ` utf8mb4_unicode_520_ci `
ENGINE = InnoDB ;
CREATE TABLE ibexa_collaboration_participant
(
id INT AUTO_INCREMENT NOT NULL ,
session_id INT NOT NULL ,
discriminator VARCHAR ( 190 ) NOT NULL ,
scope VARCHAR ( 255 ) DEFAULT NULL ,
token VARCHAR ( 255 ) DEFAULT NULL ,
created_at DATETIME NOT NULL COMMENT '(DC2Type:datetimetz_immutable)' ,
updated_at DATETIME NOT NULL COMMENT '(DC2Type:datetimetz_immutable)' ,
INDEX IDX_9C5C6401613FECDF ( session_id ),
UNIQUE INDEX ibexa_collaboration_participant_token_idx ( token ),
PRIMARY KEY ( id )
) DEFAULT CHARACTER SET utf8mb4
COLLATE ` utf8mb4_unicode_520_ci `
ENGINE = InnoDB ;
CREATE TABLE ibexa_collaboration_participant_internal
(
id INT NOT NULL ,
user_id INT NOT NULL ,
INDEX IDX_E838B79AA76ED395 ( user_id ),
PRIMARY KEY ( id )
) DEFAULT CHARACTER SET utf8mb4
COLLATE ` utf8mb4_unicode_520_ci `
ENGINE = InnoDB ;
CREATE TABLE ibexa_collaboration_participant_external
(
id INT NOT NULL ,
email VARCHAR ( 255 ) NOT NULL ,
PRIMARY KEY ( id )
) DEFAULT CHARACTER SET utf8mb4
COLLATE ` utf8mb4_unicode_520_ci `
ENGINE = InnoDB ;
CREATE TABLE ibexa_collaboration_invitation
(
id INT AUTO_INCREMENT NOT NULL ,
session_id INT NOT NULL ,
participant_id INT NOT NULL ,
sender_id INT NOT NULL ,
status VARCHAR ( 64 ) NOT NULL ,
context LONGTEXT DEFAULT NULL COMMENT '(DC2Type:json)' ,
created_at DATETIME NOT NULL COMMENT '(DC2Type:datetimetz_immutable)' ,
updated_at DATETIME NOT NULL COMMENT '(DC2Type:datetimetz_immutable)' ,
INDEX IDX_36C63687613FECDF ( session_id ),
INDEX IDX_36C636879D1C3019 ( participant_id ),
INDEX IDX_36C63687F624B39D ( sender_id ),
PRIMARY KEY ( id )
) DEFAULT CHARACTER SET utf8mb4
COLLATE ` utf8mb4_unicode_520_ci `
ENGINE = InnoDB ;
ALTER TABLE ibexa_collaboration
ADD CONSTRAINT ibexa_collaboration_owner_id_fk FOREIGN KEY ( owner_id ) REFERENCES ezuser ( contentobject_id ) ON DELETE RESTRICT ;
ALTER TABLE ibexa_collaboration_participant
ADD CONSTRAINT ibexa_collaboration_participant_session_id_fk FOREIGN KEY ( session_id ) REFERENCES ibexa_collaboration ( id ) ON UPDATE CASCADE ON DELETE CASCADE ;
ALTER TABLE ibexa_collaboration_participant_internal
ADD CONSTRAINT ibexa_collaboration_participant_internal_pk FOREIGN KEY ( id ) REFERENCES ibexa_collaboration_participant ( id ) ON UPDATE CASCADE ON DELETE CASCADE ;
ALTER TABLE ibexa_collaboration_participant_internal
ADD CONSTRAINT ibexa_collaboration_participant_internal_user_id_fk FOREIGN KEY ( user_id ) REFERENCES ezuser ( contentobject_id ) ON DELETE RESTRICT ;
ALTER TABLE ibexa_collaboration_participant_external
ADD CONSTRAINT ibexa_collaboration_participant_external_pk FOREIGN KEY ( id ) REFERENCES ibexa_collaboration_participant ( id ) ON UPDATE CASCADE ON DELETE CASCADE ;
ALTER TABLE ibexa_collaboration_invitation
ADD CONSTRAINT ibexa_collaboration_invitation_session_id_fk FOREIGN KEY ( session_id ) REFERENCES ibexa_collaboration ( id ) ON UPDATE CASCADE ON DELETE CASCADE ;
ALTER TABLE ibexa_collaboration_invitation
ADD CONSTRAINT ibexa_collaboration_invitation_participant_id_fk FOREIGN KEY ( participant_id ) REFERENCES ibexa_collaboration_participant ( id ) ON UPDATE CASCADE ON DELETE CASCADE ;
ALTER TABLE ibexa_collaboration_invitation
ADD CONSTRAINT ibexa_collaboration_invitation_sender_id_fk FOREIGN KEY ( sender_id ) REFERENCES ezuser ( contentobject_id ) ON DELETE RESTRICT ;
CREATE TABLE ibexa_collaboration_content
(
id INT NOT NULL ,
content_id INT NOT NULL ,
version_no INT NOT NULL ,
language_id BIGINT NOT NULL ,
INDEX ibexa_collaboration_session_content_version_language_idx ( content_id , version_no , language_id ),
PRIMARY KEY ( id )
) DEFAULT CHARACTER SET utf8 COLLATE ` utf8mb4_unicode_520_ci ` ENGINE = InnoDB ;
ALTER TABLE
ibexa_collaboration_content
ADD
CONSTRAINT ibexa_collaboration_content_pk FOREIGN KEY ( id ) REFERENCES ibexa_collaboration ( id ) ON UPDATE CASCADE ON DELETE CASCADE ;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 CREATE TABLE ibexa_collaboration
(
id SERIAL NOT NULL ,
owner_id INT NOT NULL ,
token VARCHAR ( 160 ) NOT NULL ,
discriminator VARCHAR ( 190 ) NOT NULL ,
is_active BOOLEAN NOT NULL ,
has_public_link BOOLEAN NOT NULL ,
created_at TIMESTAMP ( 0 ) WITH TIME ZONE NOT NULL ,
updated_at TIMESTAMP ( 0 ) WITH TIME ZONE NOT NULL ,
PRIMARY KEY ( id )
);
CREATE UNIQUE INDEX ibexa_collaboration_token_idx ON ibexa_collaboration ( token );
CREATE INDEX ibexa_collaboration_owner_idx ON ibexa_collaboration ( owner_id );
CREATE UNIQUE INDEX ibexa_collaboration_token_uc ON ibexa_collaboration ( token );
COMMENT
ON COLUMN ibexa_collaboration . created_at IS '(DC2Type:datetimetz_immutable)' ;
COMMENT
ON COLUMN ibexa_collaboration . updated_at IS '(DC2Type:datetimetz_immutable)' ;
CREATE TABLE ibexa_collaboration_participant
(
id SERIAL NOT NULL ,
session_id INT NOT NULL ,
discriminator VARCHAR ( 190 ) NOT NULL ,
scope VARCHAR ( 255 ) DEFAULT NULL ,
token VARCHAR ( 255 ) DEFAULT NULL ,
created_at TIMESTAMP ( 0 ) WITH TIME ZONE NOT NULL ,
updated_at TIMESTAMP ( 0 ) WITH TIME ZONE NOT NULL ,
PRIMARY KEY ( id )
);
CREATE INDEX ibexa_collaboration_participant_idx ON ibexa_collaboration_participant ( session_id );
CREATE UNIQUE INDEX ibexa_collaboration_participant_token_idx ON ibexa_collaboration_participant ( token );
COMMENT
ON COLUMN ibexa_collaboration_participant . created_at IS '(DC2Type:datetimetz_immutable)' ;
COMMENT
ON COLUMN ibexa_collaboration_participant . updated_at IS '(DC2Type:datetimetz_immutable)' ;
CREATE TABLE ibexa_collaboration_participant_internal
(
id INT NOT NULL ,
user_id INT NOT NULL ,
PRIMARY KEY ( id )
);
CREATE INDEX ibexa_collaboration_participant_internal_idx ON ibexa_collaboration_participant_internal ( user_id );
CREATE TABLE ibexa_collaboration_participant_external
(
id INT NOT NULL ,
email VARCHAR ( 255 ) NOT NULL ,
PRIMARY KEY ( id )
);
CREATE TABLE ibexa_collaboration_invitation
(
id SERIAL NOT NULL ,
session_id INT NOT NULL ,
participant_id INT NOT NULL ,
sender_id INT NOT NULL ,
status VARCHAR ( 64 ) NOT NULL ,
context JSON DEFAULT NULL ,
created_at TIMESTAMP ( 0 ) WITH TIME ZONE NOT NULL ,
updated_at TIMESTAMP ( 0 ) WITH TIME ZONE NOT NULL ,
PRIMARY KEY ( id )
);
CREATE INDEX ibexa_collaboration_invitation_idx ON ibexa_collaboration_invitation ( session_id );
CREATE INDEX ibexa_collaboration_invitation_idx ON ibexa_collaboration_invitation ( participant_id );
CREATE INDEX ibexa_collaboration_invitation_idx ON ibexa_collaboration_invitation ( sender_id );
COMMENT
ON COLUMN ibexa_collaboration_invitation . created_at IS '(DC2Type:datetimetz_immutable)' ;
COMMENT
ON COLUMN ibexa_collaboration_invitation . updated_at IS '(DC2Type:datetimetz_immutable)' ;
ALTER TABLE ibexa_collaboration
ADD CONSTRAINT ibexa_collaboration_owner_id_fk FOREIGN KEY ( owner_id ) REFERENCES ezuser ( contentobject_id ) ON DELETE RESTRICT NOT DEFERRABLE INITIALLY IMMEDIATE ;
ALTER TABLE ibexa_collaboration_participant
ADD CONSTRAINT ibexa_collaboration_participant_session_id_fk FOREIGN KEY ( session_id ) REFERENCES ibexa_collaboration ( id ) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ;
ALTER TABLE ibexa_collaboration_participant_internal
ADD CONSTRAINT ibexa_collaboration_participant_internal_pk FOREIGN KEY ( id ) REFERENCES ibexa_collaboration_participant ( id ) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ;
ALTER TABLE ibexa_collaboration_participant_internal
ADD CONSTRAINT ibexa_collaboration_participant_internal_user_id_fk FOREIGN KEY ( user_id ) REFERENCES ezuser ( contentobject_id ) ON DELETE RESTRICT NOT DEFERRABLE INITIALLY IMMEDIATE ;
ALTER TABLE ibexa_collaboration_participant_external
ADD CONSTRAINT ibexa_collaboration_participant_external_pk FOREIGN KEY ( id ) REFERENCES ibexa_collaboration_participant ( id ) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ;
ALTER TABLE ibexa_collaboration_invitation
ADD CONSTRAINT ibexa_collaboration_invitation_session_id_fk FOREIGN KEY ( session_id ) REFERENCES ibexa_collaboration ( id ) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ;
ALTER TABLE ibexa_collaboration_invitation
ADD CONSTRAINT ibexa_collaboration_invitation_participant_id_fk FOREIGN KEY ( participant_id ) REFERENCES ibexa_collaboration_participant ( id ) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ;
ALTER TABLE ibexa_collaboration_invitation
ADD CONSTRAINT ibexa_collaboration_invitation_sender_id_fk FOREIGN KEY ( sender_id ) REFERENCES ezuser ( contentobject_id ) ON DELETE RESTRICT NOT DEFERRABLE INITIALLY IMMEDIATE ;
CREATE TABLE ibexa_collaboration_content
(
id INT NOT NULL ,
content_id INT NOT NULL ,
version_no INT NOT NULL ,
language_id BIGINT NOT NULL ,
PRIMARY KEY ( id )
);
CREATE INDEX ibexa_collaboration_session_content_version_language_idx ON ibexa_collaboration_content ( content_id , version_no , language_id );
ALTER TABLE ibexa_collaboration_content
ADD CONSTRAINT ibexa_collaboration_content_pk FOREIGN KEY ( id ) REFERENCES ibexa_collaboration ( id ) ON UPDATE CASCADE ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE ;
Then, run the following command, where <database_name>
is the same name that you defined when you installed Ibexa DXP:
This command modifies the existing database schema by adding database configuration required for using Collaborative editing.
Modify the bundles file
Then, if not using Symfony Flex, add the following code to the config/bundles.php
file:
<? 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 ],
Ibexa\Bundle\CkeditorPremium\IbexaCkeditorPremiumBundle :: class => [ 'all' => true ],
];
Add migration file and execute migration
Last step is to add migration file and execute migration with the following commands:
php bin/console ibexa:migrations:import vendor/ibexa/collaboration/src/bundle/Resources/migrations/2025_08_26_10_14_shareable_user.yaml
php bin/console ibexa:migrations:migrate --file= 2025_08_26_10_14_shareable_user.yaml
Once the packages are installed, before you can start Collaborative editing feature, you must enable it by following these instructions.
Security configuration
After an installation process is finished, go to config/packages/security.yaml
and make following changes:
uncomment following lines with shared
user provider under the providers
key:
security :
providers :
# ...
shared :
id : Ibexa\Collaboration\Security\User\ShareableLinkUserProvider
uncomment following lines under the ibexa_shareable_link
key:
security :
# ...
ibexa_shareable_link :
request_matcher : Ibexa\Collaboration\Security\RequestMatcher\ShareableLinkRequestMatcher
pattern : ^/
provider : shared
stateless : true
user_checker : Ibexa\Core\MVC\Symfony\Security\UserChecker
guard :
authenticator : Ibexa\Collaboration\Security\Authenticator\ShareableLinkAuthenticator
Configuration
You can configure Collaborative editing per Repository .
Under ibexa.repositories.<repository_name>.collaboration
configuration key , indicate the settings for collaboration:
ibexa :
repositories :
<repository_name> :
collaboration :
participants :
allowed_types :
- internal
- external
auto_invite : <value>
session :
public_link_enabled : <value>
The following settings are available:
participants:
allowed_types
- defines allowed user types, values: internal
, external
, you can set one or both of the values
auto_invite
- determines whether invitations should be sent automatically when inviting someone to a session, default value: true
, available values: true
, false
session:
public_link_enabled
- determines whether the public link is available, default value: false
, available values: true
, false
ibexa/share
configuration
To share content model, you need to configure the ibexa/share
package.
Under ibexa.system
configuration key , indicate the settings:
ibexa :
system :
admin_group :
share :
content_type_groups :
- 'Content'
excluded_content_types :
- 'tag'
- 'product_category_tag'
The following setting is available:
content_type_groups
– defines groups of content types for which the Share button is displayed (it can still be disabled for specific content types within these groups)
In the example confugiration above, the Share button is displayed for any content that belongs to the Content
group, except for tag
and product_category_tag
content types.
You can now restart you application and start working with the Collaborative editing feature .