feat: entity move
All checks were successful
Build Test / test (pull_request) Successful in 27s
JS Unit Tests / test (pull_request) Successful in 28s
PHP Unit Tests / test (pull_request) Successful in 50s

Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
2026-03-28 09:32:04 -04:00
parent 7322bb16da
commit 1c918ca55c
6 changed files with 216 additions and 6 deletions

View File

@@ -17,6 +17,10 @@ use KTXC\SessionIdentity;
use KTXC\SessionTenant;
use KTXF\Controller\ControllerAbstract;
use KTXF\Json\JsonSerializable;
use KTXF\Resource\Identifier\CollectionIdentifier;
use KTXF\Resource\Identifier\EntityIdentifier;
use KTXF\Resource\Identifier\ResourceIdentifier;
use KTXF\Resource\Identifier\ResourceIdentifiers;
use KTXF\Resource\Provider\ResourceServiceLocationInterface;
use KTXF\Resource\Selector\SourceSelector;
use KTXF\Routing\Attributes\AuthenticatedRoute;
@@ -38,6 +42,7 @@ class DefaultController extends ControllerAbstract {
private const ERR_MISSING_COLLECTION = 'Missing parameter: collection';
private const ERR_MISSING_DATA = 'Missing parameter: data';
private const ERR_MISSING_SOURCES = 'Missing parameter: sources';
private const ERR_MISSING_TARGET = 'Missing parameter: target';
private const ERR_MISSING_IDENTIFIERS = 'Missing parameter: identifiers';
private const ERR_INVALID_OPERATION = 'Invalid operation: ';
private const ERR_INVALID_PROVIDER = 'Invalid parameter: provider must be a string';
@@ -45,6 +50,7 @@ class DefaultController extends ControllerAbstract {
private const ERR_INVALID_IDENTIFIER = 'Invalid parameter: identifier must be a string';
private const ERR_INVALID_COLLECTION = 'Invalid parameter: collection must be a string or integer';
private const ERR_INVALID_SOURCES = 'Invalid parameter: sources must be an array';
private const ERR_INVALID_TARGET = 'Invalid parameter: target must be an array';
private const ERR_INVALID_IDENTIFIERS = 'Invalid parameter: identifiers must be an array';
private const ERR_INVALID_DATA = 'Invalid parameter: data must be an array';
@@ -157,7 +163,7 @@ class DefaultController extends ControllerAbstract {
'entity.delete' => throw new InvalidArgumentException('Operation not implemented: ' . $operation),
'entity.stream' => $this->entityStream($tenantId, $userId, $data, $version, $transaction),
'entity.delta' => $this->entityDelta($tenantId, $userId, $data),
'entity.move' => throw new InvalidArgumentException('Operation not implemented: ' . $operation),
'entity.move' => $this->entityMove($tenantId, $userId, $data),
'entity.copy' => throw new InvalidArgumentException('Operation not implemented: ' . $operation),
'entity.transmit' => $this->entityTransmit($tenantId, $userId, $data),
@@ -634,6 +640,35 @@ class DefaultController extends ControllerAbstract {
return $this->mailManager->entityDelta($tenantId, $userId, $sources);
}
private function entityMove(string $tenantId, string $userId, array $data): mixed {
if (!isset($data['target'])) {
throw new InvalidArgumentException(self::ERR_MISSING_TARGET);
}
if (!is_string($data['target'])) {
throw new InvalidArgumentException(self::ERR_INVALID_TARGET);
}
if (!isset($data['sources'])) {
throw new InvalidArgumentException(self::ERR_MISSING_SOURCES);
}
if (!is_array($data['sources'])) {
throw new InvalidArgumentException(self::ERR_INVALID_SOURCES);
}
$target = ResourceIdentifier::fromString($data['target']);
if (!$target instanceof CollectionIdentifier) {
throw new InvalidArgumentException('Invalid parameter: target must be provider:service:collection');
}
$sources = ResourceIdentifiers::fromArray($data['sources']);
foreach ($sources as $source) {
if (!$source instanceof EntityIdentifier) {
throw new InvalidArgumentException('Invalid parameter: sources must contain provider:service:collection:entity identifiers');
}
}
return $this->mailManager->entityMove($tenantId, $userId, $target, $sources);
}
private function entityTransmit(string $tenantId, string $userId, array $data): mixed {
if (!isset($data['provider'])) {
throw new InvalidArgumentException(self::ERR_MISSING_PROVIDER);
@@ -659,8 +694,6 @@ class DefaultController extends ControllerAbstract {
return ['jobId' => $jobId];
}
// ==================== Entity Stream ====================
private function entityStream(string $tenantId, string $userId, array $data, int $version, string $transaction): StreamedNdJsonResponse {
if (!isset($data['sources'])) {
throw new InvalidArgumentException(self::ERR_MISSING_SOURCES);