feat: listen to user life cycle events

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-08-08 21:51:07 -04:00
parent c0f154eddb
commit 25c3043b82
5 changed files with 216 additions and 3 deletions
+58
View File
@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace KTXM\ProviderLocalPeople\Listeners;
use KTXC\User\Event\UserCreatedEvent;
use KTXC\User\Event\UserDeletingEvent;
use KTXF\Resource\Identifier\CollectionIdentifier;
use KTXM\ProviderLocalPeople\Providers\Personal\PersonalService;
use KTXM\ProviderLocalPeople\Store\Personal\Store;
final class UserEventListener
{
private const PERSONAL_ADDRESS_BOOK_LABEL = 'Personal Address Book';
public function __construct(
private readonly Store $store,
private readonly PersonalService $service,
) {
}
public function onUserCreated(UserCreatedEvent $event): void
{
$tenantId = $event->tenantIdentifier();
$userId = $event->userIdentifier();
// A replayed lifecycle event must not create another default collection.
if ($this->store->collectionList($tenantId, $userId) !== []) {
return;
}
$collection = $this->store->collectionFresh()->setEnabled(true);
$collection->getProperties()
->setLabel(self::PERSONAL_ADDRESS_BOOK_LABEL)
->setVisibility(true);
$this->store->collectionCreate($tenantId, $userId, $collection);
}
public function onUserDeleting(UserDeletingEvent $event): void
{
$service = $this->service->initialize($event->tenantIdentifier(), $event->userIdentifier());
foreach ($service->collectionList(null) as $collection) {
$identifier = $collection->identifier();
if ($identifier === null) {
continue;
}
$service->collectionDelete(new CollectionIdentifier(
$collection->provider(),
(string) $collection->service(),
(string) $identifier,
), true);
}
}
}
+10
View File
@@ -3,9 +3,14 @@
namespace KTXM\ProviderLocalPeople;
use KTXC\Resource\ProviderManager;
use KTXC\User\Event\UserCreatedEvent;
use KTXC\User\Event\UserDeletingEvent;
use KTXF\Event\DeliveryMode;
use KTXF\Event\EventListenerRegistrarInterface;
use KTXF\Module\ModuleBrowserInterface;
use KTXF\Module\ModuleInstanceAbstract;
use KTXF\Resource\Provider\ProviderInterface;
use KTXM\ProviderLocalPeople\Listeners\UserEventListener;
use KTXM\ProviderLocalPeople\Providers\Provider;
/**
@@ -15,6 +20,7 @@ class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
{
public function __construct(
private readonly ProviderManager $providerManager,
private readonly EventListenerRegistrarInterface $events,
) {}
public function handle(): string
@@ -55,6 +61,10 @@ class Module extends ModuleInstanceAbstract implements ModuleBrowserInterface
public function boot(): void
{
// Register listeners
$this->events->listen($this->handle(), UserCreatedEvent::class, UserEventListener::class, 'onUserCreated', DeliveryMode::Deferred);
$this->events->listen($this->handle(), UserDeletingEvent::class, UserEventListener::class, 'onUserDeleting', DeliveryMode::Deferred);
// Register providers
$this->providerManager->register(ProviderInterface::TYPE_PEOPLE, 'default', Provider::class);
}
+5 -1
View File
@@ -279,7 +279,11 @@ class PersonalService implements ServiceBaseInterface, ServiceCollectionMutableI
throw new InvalidParameterException("Invalid: Collection identifier '$id' does not exist or does not belong to user '{$this->serviceUserId}'");
}
// destroy collection in store
$this->store->collectionDestroyById($this->serviceTenantId, $this->serviceUserId, $id);
$collection = $this->store->collectionFetch($this->serviceTenantId, $this->serviceUserId, $id);
if ($collection === null) {
throw new InvalidParameterException("Invalid: Collection identifier '$id' could not be retrieved");
}
$this->store->collectionDestroy($this->serviceTenantId, $this->serviceUserId, $collection);
unset($this->serviceCollectionCache[$id]);
return true;
}
+25 -2
View File
@@ -183,6 +183,7 @@ class Store {
return $list;
}
/**
* confirm if collections exist in data store
*
@@ -306,7 +307,12 @@ class Store {
if ($identifier === null) {
return $entity;
}
return $this->collectionDestroyById($tenantId, $userId, (string) $identifier) ? $entity : $entity;
$this->entityDestroyByCollectionId($tenantId, $userId, [(string) $identifier]);
$this->chronicleExpungeByCollectionId($tenantId, [(string) $identifier]);
$this->collectionDestroyById($tenantId, $userId, (string) $identifier);
return $entity;
}
/**
@@ -591,6 +597,21 @@ class Store {
return false;
}
/**
* Delete entities belonging to specific collections from the data store.
*
* @param string $tenantId tenant identifier
* @param string $userId user identifier
* @param array $identifiers collection identifiers
*/
private function entityDestroyByCollectionId(string $tenantId, string $userId, array $identifiers): void {
$this->_store->selectCollection($this->_EntityTable)->deleteMany([
'tid' => $tenantId,
'uid' => $userId,
'cid' => ['$in' => $identifiers],
]);
}
/**
* chronicle a operation to an entity to the data store
*
@@ -758,10 +779,12 @@ class Store {
* @since Release 1.0.0
*
* @param array $identifiers collection of identifiers
* @param string $tenantId tenant identifier
*/
private function chronicleExpungeByCollectionId(array $identifiers): void {
private function chronicleExpungeByCollectionId(string $tenantId, array $identifiers): void {
// Delete chronicle entries for the specified collection identifiers
$this->_store->selectCollection($this->_ChronicleTable)->deleteMany([
'tid' => $tenantId,
'cid' => ['$in' => $identifiers]
]);
}