Files
2026-07-19 07:08:48 -04:00

159 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace KTXM\ProviderMailSystem\Stores;
use KTXC\Db\DataStore;
use KTXF\Utile\UUID;
use KTXM\ProviderMailSystem\Providers\Service;
/**
* System Mail Route Store
*
* Persists system mail routes (one MongoDB document per route) in the
* collection `provider_system_mail_services`. Routes are tenant scoped —
* they carry no user association and contain no transport credentials,
* only the mapping from a "@system" address to a backing provider/service.
*
* @since 2026.07.01
*/
class ServiceStore
{
protected const COLLECTION_NAME = 'provider_system_mail_services';
public function __construct(
protected readonly DataStore $dataStore,
) {}
/**
* List routes for a tenant, optionally filtered by route IDs
*/
public function list(string $tenantId, ?array $filter = null): array
{
$filterCondition = [
'tid' => $tenantId,
];
if (!empty($filter)) {
$filterCondition['sid'] = ['$in' => array_map('strval', $filter)];
}
$cursor = $this->dataStore->selectCollection(self::COLLECTION_NAME)->find($filterCondition);
$list = [];
foreach ($cursor as $entry) {
$list[$entry['sid']] = $entry;
}
return $list;
}
/**
* Check existence of routes by IDs for a tenant
*/
public function extant(string $tenantId, array $identifiers): array
{
if (empty($identifiers)) {
return [];
}
$cursor = $this->dataStore->selectCollection(self::COLLECTION_NAME)->find(
[
'tid' => $tenantId,
'sid' => ['$in' => array_map('strval', $identifiers)]
],
['projection' => ['sid' => 1]]
);
$existingIds = [];
foreach ($cursor as $document) {
$existingIds[] = $document['sid'];
}
$result = [];
foreach ($identifiers as $id) {
$result[(string)$id] = in_array((string)$id, $existingIds, true);
}
return $result;
}
/**
* Retrieve a single route by ID
*/
public function fetch(string $tenantId, string|int $serviceId): ?array
{
$document = $this->dataStore->selectCollection(self::COLLECTION_NAME)->findOne([
'tid' => $tenantId,
'sid' => (string)$serviceId,
]);
if (!$document) {
return null;
}
return $document;
}
/**
* Create a new route
*/
public function create(string $tenantId, Service $service): array
{
$document = $service->toStore();
$document['tid'] = $tenantId;
$document['sid'] = UUID::v4();
$document['createdOn'] = new \MongoDB\BSON\UTCDateTime();
$document['modifiedOn'] = new \MongoDB\BSON\UTCDateTime();
$this->dataStore->selectCollection(self::COLLECTION_NAME)->insertOne($document);
return $document;
}
/**
* Modify an existing route
*/
public function modify(string $tenantId, Service $service): array
{
$serviceId = (string)$service->identifier();
if ($serviceId === '') {
throw new \InvalidArgumentException('Service ID is required for update');
}
$document = $service->toStore();
$document['modifiedOn'] = new \MongoDB\BSON\UTCDateTime();
unset($document['sid'], $document['tid'], $document['createdOn']);
$this->dataStore->selectCollection(self::COLLECTION_NAME)->updateOne(
[
'tid' => $tenantId,
'sid' => $serviceId,
],
['$set' => $document]
);
return $document;
}
/**
* Delete a route
*/
public function delete(string $tenantId, string|int $serviceId): bool
{
$result = $this->dataStore->selectCollection(self::COLLECTION_NAME)->deleteOne([
'tid' => $tenantId,
'sid' => (string)$serviceId,
]);
return $result->getDeletedCount() > 0;
}
}