Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions code_samples/collaborative_editing/collaboration_event_listener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?php

declare(strict_types=1);

namespace App\EventListener;

use Ibexa\Contracts\Collaboration\Session\Event\JoinSessionEvent;
use Ibexa\Contracts\Collaboration\Session\Event\SessionPublicPreviewEvent;
use Ibexa\Contracts\Core\Repository\ContentService;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class CollaborationEventListener implements EventSubscriberInterface
{
public function __construct(
private ContentService $contentService,
private LoggerInterface $logger
) {
}

public static function getSubscribedEvents(): array
{
return [
JoinSessionEvent::class => 'onJoinSession',
SessionPublicPreviewEvent::class => 'onSessionPublicPreview',
];
}

/**
* Handle user joining a collaboration session
*/
public function onJoinSession(JoinSessionEvent $event): void
{
$session = $event->getSession();
$user = $event->getUser();

$this->logger->info('User joined collaboration session', [
'user_id' => $user->getId(),
'user_name' => $user->getName(),
'session_id' => $session->getId(),
'content_id' => $session->getContentId(),
]);

// Custom logic: Send notification to other participants
$this->notifyOtherParticipants($session, $user);

// Custom logic: Update user activity metrics
$this->updateUserActivityMetrics($user->getId(), 'session_join');
}

/**
* Handle public preview access for collaboration session
*/
public function onSessionPublicPreview(SessionPublicPreviewEvent $event): void
{
$session = $event->getSession();
$content = $this->contentService->loadContent($session->getContentId());

$this->logger->info('Public preview accessed for collaboration session', [
'session_id' => $session->getId(),
'content_id' => $session->getContentId(),
'content_name' => $content->getName(),
'preview_url' => $event->getPreviewUrl(),
]);

// Custom logic: Track public preview usage
$this->trackPublicPreviewAccess($session, $event->getPreviewUrl());
}

/**
* Notify other participants when someone joins the session
*/
private function notifyOtherParticipants($session, $user): void
{
// Implementation would send real-time notifications
// to other active participants in the session
$this->logger->debug('Notifying other participants of new joiner', [
'session_id' => $session->getId(),
'new_participant' => $user->getName(),
]);
}

/**
* Update user activity metrics for analytics
*/
private function updateUserActivityMetrics(int $userId, string $action): void
{
// Implementation would update user activity statistics
// for collaboration analytics and reporting
$this->logger->debug('Updated user activity metrics', [
'user_id' => $userId,
'action' => $action,
'timestamp' => new \DateTime(),
]);
}

/**
* Track public preview access for analytics
*/
private function trackPublicPreviewAccess($session, string $previewUrl): void
{
// Implementation would track public preview usage
// for collaboration session analytics
$this->logger->debug('Tracked public preview access', [
'session_id' => $session->getId(),
'preview_url' => $previewUrl,
'access_time' => new \DateTime(),
]);
}
}
60 changes: 60 additions & 0 deletions code_samples/collaborative_editing/create_invitation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

declare(strict_types=1);

namespace App\Collaboration;

use Ibexa\Contracts\Collaboration\Invitation\InvitationServiceInterface;
use Ibexa\Contracts\Collaboration\Values\Invitation\InvitationCreateStruct;
use Ibexa\Contracts\Core\Repository\ContentService;
use Ibexa\Contracts\Core\Repository\UserService;

class InvitationManager
{
public function __construct(
private InvitationServiceInterface $invitationService,
private ContentService $contentService,
private UserService $userService
) {
}

/**
* Create a collaboration invitation for a content item
*/
public function createInvitation(int $contentId, int $userId, string $message = ''): void
{
$content = $this->contentService->loadContent($contentId);
$user = $this->userService->loadUser($userId);

$invitationCreateStruct = new InvitationCreateStruct();
$invitationCreateStruct->contentId = $contentId;
$invitationCreateStruct->userId = $userId;
$invitationCreateStruct->message = $message;
$invitationCreateStruct->permissions = ['edit', 'comment'];

$invitation = $this->invitationService->createInvitation($invitationCreateStruct);

// Send notification to invited user
// This would typically trigger email notifications
echo "Invitation created for user {$user->getName()} to collaborate on '{$content->getName()}'";
}

/**
* Create invitation for external user by email
*/
public function createExternalInvitation(int $contentId, string $email, string $message = ''): void
{
$content = $this->contentService->loadContent($contentId);

$invitationCreateStruct = new InvitationCreateStruct();
$invitationCreateStruct->contentId = $contentId;
$invitationCreateStruct->email = $email;
$invitationCreateStruct->message = $message;
$invitationCreateStruct->permissions = ['comment']; // Limited permissions for external users
$invitationCreateStruct->expirationDate = new \DateTime('+7 days'); // Expires in 7 days

$invitation = $this->invitationService->createInvitation($invitationCreateStruct);

echo "External invitation created for {$email} to collaborate on '{$content->getName()}'";
}
}
98 changes: 98 additions & 0 deletions code_samples/collaborative_editing/session_management.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

declare(strict_types=1);

namespace App\Collaboration;

use Ibexa\Contracts\Collaboration\Session\SessionServiceInterface;
use Ibexa\Contracts\Collaboration\Values\Session\SessionCreateStruct;
use Ibexa\Contracts\Collaboration\Values\Session\SessionQuery;
use Ibexa\Contracts\Collaboration\Session\Query\Criterion;
use Ibexa\Contracts\Collaboration\Session\Query\SortClause;

class CollaborationSessionManager
{
public function __construct(
private SessionServiceInterface $sessionService
) {
}

/**
* Create a new collaboration session
*/
public function createSession(int $contentId, array $participants = []): void
{
$sessionCreateStruct = new SessionCreateStruct();
$sessionCreateStruct->contentId = $contentId;
$sessionCreateStruct->participants = $participants;
$sessionCreateStruct->settings = [
'realTimeEnabled' => true,
'allowExternalUsers' => false,
'maxParticipants' => 10,
'autoSave' => true,
];

$session = $this->sessionService->createSession($sessionCreateStruct);

echo "Collaboration session created with ID: {$session->getId()}";
}

/**
* Find active collaboration sessions for a user
*/
public function findUserSessions(int $userId): array
{
$query = new SessionQuery();
$query->filter = new Criterion\ParticipantId($userId);
$query->sortClauses = [
new SortClause\UpdatedAt('DESC'),
];
$query->limit = 50;

$searchResult = $this->sessionService->findSessions($query);

return $searchResult->sessions;
}

/**
* Join an existing collaboration session
*/
public function joinSession(int $sessionId, int $userId): void
{
$session = $this->sessionService->loadSession($sessionId);

// Add user as participant
$this->sessionService->addParticipant($sessionId, $userId);

echo "User {$userId} joined collaboration session {$sessionId}";
}

/**
* Leave a collaboration session
*/
public function leaveSession(int $sessionId, int $userId): void
{
$this->sessionService->removeParticipant($sessionId, $userId);

echo "User {$userId} left collaboration session {$sessionId}";
}

/**
* Get session statistics
*/
public function getSessionStats(int $sessionId): array
{
$session = $this->sessionService->loadSession($sessionId);
$participants = $this->sessionService->getSessionParticipants($sessionId);

return [
'session_id' => $session->getId(),
'content_id' => $session->getContentId(),
'created_at' => $session->getCreatedAt(),
'updated_at' => $session->getUpdatedAt(),
'participant_count' => count($participants),
'active_participants' => array_filter($participants, fn($p) => $p->isActive()),
'real_time_enabled' => $session->getSetting('realTimeEnabled', false),
];
}
}
Loading