diff --git a/shared/lib/People/Entity/EntityBaseAbstract.php b/shared/lib/People/Entity/EntityBaseAbstract.php index 63885e7..d99eca4 100644 --- a/shared/lib/People/Entity/EntityBaseAbstract.php +++ b/shared/lib/People/Entity/EntityBaseAbstract.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace KTXF\People\Entity; +use KTXF\Resource\Identifier\EntityIdentifier; use KTXF\Resource\Provider\Node\NodeBaseAbstract; /** @@ -20,7 +21,12 @@ use KTXF\Resource\Provider\Node\NodeBaseAbstract; */ abstract class EntityBaseAbstract extends NodeBaseAbstract implements EntityBaseInterface { - protected EntityPropertiesBaseAbstract $properties; + protected string $type = 'people:entity'; + protected EntityPropertiesBaseInterface $properties; + + protected function nodeIdentifier(): EntityIdentifier { + return new EntityIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE], $this->data[static::PROPERTY_COLLECTION], $this->data[static::PROPERTY_IDENTIFIER]); + } /** * @inheritDoc diff --git a/shared/lib/People/Entity/EntityBaseInterface.php b/shared/lib/People/Entity/EntityBaseInterface.php index f3b6a6b..7f737b4 100644 --- a/shared/lib/People/Entity/EntityBaseInterface.php +++ b/shared/lib/People/Entity/EntityBaseInterface.php @@ -13,8 +13,6 @@ use KTXF\Resource\Provider\Node\NodeBaseInterface; interface EntityBaseInterface extends NodeBaseInterface { - public const JSON_TYPE = 'people:entity'; - /** * Gets the entity properties * diff --git a/shared/lib/People/Entity/EntityMutableAbstract.php b/shared/lib/People/Entity/EntityMutableAbstract.php index 1f0b289..5cd34a1 100644 --- a/shared/lib/People/Entity/EntityMutableAbstract.php +++ b/shared/lib/People/Entity/EntityMutableAbstract.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace KTXF\People\Entity; +use KTXF\Resource\Identifier\EntityIdentifier; use KTXF\Resource\Provider\Node\NodeMutableAbstract; use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; @@ -21,9 +22,12 @@ use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; */ abstract class EntityMutableAbstract extends NodeMutableAbstract implements EntityMutableInterface { - public const JSON_TYPE = EntityMutableInterface::JSON_TYPE; + protected string $type = 'people:entity'; + protected EntityPropertiesMutableInterface $properties; - protected EntityPropertiesMutableAbstract $properties; + protected function nodeIdentifier(): EntityIdentifier { + return new EntityIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE], (string) $this->data[static::PROPERTY_COLLECTION], (string) $this->data[static::PROPERTY_IDENTIFIER]); + } /** * @inheritDoc @@ -40,7 +44,7 @@ abstract class EntityMutableAbstract extends NodeMutableAbstract implements Enti throw new \InvalidArgumentException('Properties must implement EntityPropertiesMutableInterface'); } - $this->properties->setDataRaw($value->getDataRaw()); + $this->properties = $value; return $this; } diff --git a/shared/lib/People/Entity/EntityMutableInterface.php b/shared/lib/People/Entity/EntityMutableInterface.php index ab83678..d067a4c 100644 --- a/shared/lib/People/Entity/EntityMutableInterface.php +++ b/shared/lib/People/Entity/EntityMutableInterface.php @@ -16,8 +16,6 @@ use KTXF\Resource\Provider\Node\NodeMutableInterface; */ interface EntityMutableInterface extends EntityBaseInterface, NodeMutableInterface { - public const JSON_TYPE = EntityBaseInterface::JSON_TYPE; - /** * Gets the entity properties (mutable) * diff --git a/shared/lib/People/Entity/EntityPropertiesBaseAbstract.php b/shared/lib/People/Entity/EntityPropertiesBaseAbstract.php index 0b3c13c..e033a70 100644 --- a/shared/lib/People/Entity/EntityPropertiesBaseAbstract.php +++ b/shared/lib/People/Entity/EntityPropertiesBaseAbstract.php @@ -13,8 +13,9 @@ use KTXF\Resource\Provider\Node\NodePropertiesBaseAbstract; abstract class EntityPropertiesBaseAbstract extends NodePropertiesBaseAbstract implements EntityPropertiesBaseInterface { - public const JSON_TYPE = EntityPropertiesBaseInterface::JSON_TYPE; - + /** + * @inheritDoc + */ public function getDataRaw(): array|string|null { return $this->data[self::PROPERTY_DATA] ?? null; } diff --git a/shared/lib/People/Entity/EntityPropertiesMutableInterface.php b/shared/lib/People/Entity/EntityPropertiesMutableInterface.php index 2a81e61..66ec267 100644 --- a/shared/lib/People/Entity/EntityPropertiesMutableInterface.php +++ b/shared/lib/People/Entity/EntityPropertiesMutableInterface.php @@ -13,8 +13,6 @@ use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; interface EntityPropertiesMutableInterface extends EntityPropertiesBaseInterface, NodePropertiesMutableInterface { - public const JSON_TYPE = EntityPropertiesBaseInterface::JSON_TYPE; - public function setDataRaw(array|string|null $value): static; } diff --git a/shared/lib/People/Provider/ProviderServiceMutateInterface.php b/shared/lib/People/Provider/ProviderServiceMutateInterface.php index 4565c27..24117a8 100644 --- a/shared/lib/People/Provider/ProviderServiceMutateInterface.php +++ b/shared/lib/People/Provider/ProviderServiceMutateInterface.php @@ -14,7 +14,7 @@ use KTXF\Resource\Provider\ResourceProviderServiceMutateInterface; /** * Provider Service Mutate Interface * - * Optional interface for providers that support service CRUD operations. + * Optional interface for providers that support service CRUD operations * * @since 2025.05.01 * @@ -25,4 +25,6 @@ use KTXF\Resource\Provider\ResourceProviderServiceMutateInterface; */ interface ProviderServiceMutateInterface extends ResourceProviderServiceMutateInterface { + // Methods inherited from ResourceProviderServiceMutateInterface + } diff --git a/shared/lib/People/Provider/ProviderServiceTestInterface.php b/shared/lib/People/Provider/ProviderServiceTestInterface.php index 358b657..a0e76a2 100644 --- a/shared/lib/People/Provider/ProviderServiceTestInterface.php +++ b/shared/lib/People/Provider/ProviderServiceTestInterface.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace KTXF\People\Provider; +use KTXF\Chrono\Service\ServiceMutableInterface; use KTXF\Mail\Service\ServiceBaseInterface; /** @@ -20,6 +21,8 @@ use KTXF\Mail\Service\ServiceBaseInterface; */ interface ProviderServiceTestInterface { + public const CAPABILITY_SERVICE_TEST = 'ServiceTest'; + /** * Test a service connection * @@ -27,7 +30,7 @@ interface ProviderServiceTestInterface { * * @since 2025.05.01 * - * @param ServiceBaseInterface $service Service to test (can be fresh/unsaved or existing) + * @param ServiceBaseInterface|ServiceMutableInterface $service Service to test (can be fresh/unsaved or existing) * @param array $options Provider-specific test options: * - 'timeout' => int (seconds, default: 10) * - 'verify_ssl' => bool (default: true) @@ -36,10 +39,10 @@ interface ProviderServiceTestInterface { * * @return array Test results in the format: * [ - * 'success' => bool, - * 'message' => 'Connection successful' | 'Error message' + * 'disposition' => 'Success' | 'Failure' | 'Warning', + * 'message' => 'Connection successful' | 'Error message', * ] */ - public function serviceTest(ServiceBaseInterface $service, array $options = []): array; + public function serviceTest(ServiceBaseInterface|ServiceMutableInterface $service, array $options = []): array; } diff --git a/shared/lib/People/Service/ServiceBaseInterface.php b/shared/lib/People/Service/ServiceBaseInterface.php index 8ccadd6..7dcf2ae 100644 --- a/shared/lib/People/Service/ServiceBaseInterface.php +++ b/shared/lib/People/Service/ServiceBaseInterface.php @@ -9,16 +9,19 @@ declare(strict_types=1); namespace KTXF\People\Service; +use Generator; use KTXF\People\Collection\CollectionBaseInterface; +use KTXF\People\Entity\EntityBaseInterface; use KTXF\Resource\Delta\Delta; use KTXF\Resource\Filter\IFilter; +use KTXF\Resource\Identifier\EntityIdentifierInterface; use KTXF\Resource\Provider\ResourceServiceBaseInterface; use KTXF\Resource\Range\IRange; use KTXF\Resource\Range\RangeType; use KTXF\Resource\Sort\ISort; /** - * Service Base Interface + * People Service Base Interface * * Minimum interface for a service, providing read-only access to collections and entities. * @@ -71,7 +74,7 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface { * @param IFilter|null $filter Optional filter criteria * @param ISort|null $sort Optional sort order * - * @return array Collections indexed by ID + * @return array Collections indexed by identifier */ public function collectionList(string|int $location, ?IFilter $filter = null, ?ISort $sort = null): array; @@ -98,9 +101,9 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface { * * @since 2025.05.01 * - * @param string|int ...$identifiers Collection IDs to check + * @param string|int ...$identifiers Collection identifiers to check * - * @return array Map of ID => exists + * @return array Map of identifier => exists */ public function collectionExtant(string|int $location, string|int ...$identifiers): array; @@ -109,29 +112,44 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface { * * @since 2025.05.01 * - * @param string|int $identifier Collection ID + * @param string|int $identifier Collection identifier * * @return CollectionBaseInterface|null Collection or null if not found */ public function collectionFetch(string|int $identifier): ?CollectionBaseInterface; /** - * Lists messages in a collection + * Lists entities in a collection * * @since 2025.05.01 * - * @param string|int $collection Collection ID + * @param string|int $collection Collection identifier * @param IFilter|null $filter Optional filter criteria * @param ISort|null $sort Optional sort order * @param IRange|null $range Optional pagination - * @param array|null $properties Optional message properties to fetch + * @param array|null $properties Optional entity properties to fetch * - * @return array Messages indexed by ID + * @return array Entities indexed by Urn */ - public function entityList(string|int $collection, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null, ?array $properties = null): array; + public function entityListBulk(string|int $collection, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null, ?array $properties = null): array; /** - * Creates a filter builder for messages + * Lists entities in a collection + * + * @since 2025.05.01 + * + * @param string|int $collection Collection identifier + * @param IFilter|null $filter Optional filter criteria + * @param ISort|null $sort Optional sort order + * @param IRange|null $range Optional pagination + * @param array|null $properties Optional entity properties to fetch + * + * @return Generator Yields entities one by one as EntityBaseInterface + */ + public function entityListStream(string|int $collection, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null, ?array $properties = null): Generator; + + /** + * Creates a filter builder for entities * * @since 2025.05.01 * @@ -140,7 +158,7 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface { public function entityListFilter(): IFilter; /** - * Creates a sort builder for messages + * Creates a sort builder for entities * * @since 2025.05.01 * @@ -149,7 +167,7 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface { public function entityListSort(): ISort; /** - * Creates a range builder for messages + * Creates a range builder for entities * * @since 2025.05.01 * @@ -160,40 +178,49 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface { public function entityListRange(RangeType $type): IRange; /** - * Gets incremental changes since last sync + * Gets incremental changes since last signature * * @since 2025.05.01 * - * @param string|int $collection Collection ID - * @param string $signature Sync token from previous sync - * @param string $detail Detail level: 'ids', 'minimal', 'full' + * @param string|int $collection Collection identifier + * @param string $signature Token from previous delta * * @return array ['signature' => string, 'added' => array, 'modified' => array, 'removed' => array] */ - public function entityDelta(string|int $collection, string $signature, string $detail = 'ids'): Delta; + public function entityDelta(string|int $collection, string $signature): Delta; /** - * Checks if messages exist + * Checks if entities exist * * @since 2025.05.01 * - * @param string|int $collection Collection ID - * @param string|int ...$identifiers Message IDs to check + * @param string|int $collection Collection identifier + * @param string|int ...$identifiers Entity identifiers to check * - * @return array Map of ID => exists + * @return array Map of identifier => exists */ public function entityExtant(string|int $collection, string|int ...$identifiers): array; /** - * Fetches one or more entities + * Fetches one or more entities as an array * * @since 2025.05.01 * - * @param string|int $collection Collection ID - * @param string|int ...$identifiers Message IDs to fetch + * @param EntityIdentifierInterface ...$identifiers Entity identifiers to fetch * - * @return array Messages indexed by ID + * @return array Entities indexed by Urn */ - public function entityFetch(string|int $collection, string|int ...$identifiers): array; + public function entityFetchBulk(EntityIdentifierInterface ...$identifiers): array; + + /** + * Fetches one or more entities as a stream + * + * @since 2025.05.01 + * + * @param EntityIdentifierInterface ...$identifiers Entity identifiers to fetch + * + * @return Generator Yields entities one by one + */ + public function entityFetchStream(EntityIdentifierInterface ...$identifiers): Generator; } diff --git a/shared/lib/People/Service/ServiceCollectionMutableInterface.php b/shared/lib/People/Service/ServiceCollectionMutableInterface.php index d65cdcc..8eaaf6d 100644 --- a/shared/lib/People/Service/ServiceCollectionMutableInterface.php +++ b/shared/lib/People/Service/ServiceCollectionMutableInterface.php @@ -11,9 +11,11 @@ namespace KTXF\People\Service; use KTXF\People\Collection\CollectionBaseInterface; use KTXF\People\Collection\CollectionMutableInterface; +use KTXF\People\Collection\CollectionPropertiesBaseInterface; +use KTXF\Resource\Identifier\CollectionIdentifierInterface; /** - * Service Collection Mutable Interface + * People Service Collection Mutable Interface * * Optional interface for services that support collection CRUD operations. * @@ -39,37 +41,36 @@ interface ServiceCollectionMutableInterface { * * @since 2025.05.01 * - * @param string|int|null $location Parent collection ID (null for root) - * @param CollectionMutableInterface $collection Collection to create + * @param CollectionIdentifierInterface|null $target Target collection identifier (parent) + * @param CollectionPropertiesBaseInterface $properties Collection properties * @param array $options Protocol-specific options * * @return CollectionBaseInterface Created collection with assigned ID */ - public function collectionCreate(string|int|null $location, CollectionMutableInterface $collection, array $options = []): CollectionBaseInterface; + public function collectionCreate(CollectionIdentifierInterface|null $target, CollectionPropertiesBaseInterface $properties, array $options = []): CollectionBaseInterface; /** * Updates an existing collection * * @since 2025.05.01 * - * @param string|int $identifier Collection ID - * @param CollectionMutableInterface $collection Updated collection data + * @param CollectionIdentifierInterface $target Target collection identifier + * @param CollectionPropertiesBaseInterface $properties Updated collection data * * @return CollectionBaseInterface Updated collection */ - public function collectionUpdate(string|int $identifier, CollectionMutableInterface $collection): CollectionBaseInterface; + public function collectionUpdate(CollectionIdentifierInterface $target, CollectionPropertiesBaseInterface $properties): CollectionBaseInterface; /** * Deletes a collection * * @since 2025.05.01 * - * @param string|int $identifier Collection ID + * @param CollectionIdentifierInterface $target Target collection identifier * @param bool $force Force deletion even if not empty - * @param bool $recursive Recursively delete contents * - * @return bool True if deleted + * @return CollectionBaseInterface|true Collection object on soft delete, true on hard delete */ - public function collectionDelete(string|int $identifier, bool $force = false, bool $recursive = false): bool; + public function collectionDelete(CollectionIdentifierInterface $target, bool $force = false): CollectionBaseInterface | true; } diff --git a/shared/lib/People/Service/ServiceConfigurableInterface.php b/shared/lib/People/Service/ServiceConfigurableInterface.php index f5b6bcb..cbd04c2 100644 --- a/shared/lib/People/Service/ServiceConfigurableInterface.php +++ b/shared/lib/People/Service/ServiceConfigurableInterface.php @@ -14,7 +14,7 @@ use KTXF\Resource\Provider\ResourceServiceConfigureInterface; /** * Service Configurable Interface * - * Optional interface for services that require configuration + * Extends base service interface with setter methods for mutable properties * * @since 2025.05.01 */ diff --git a/shared/lib/People/Service/ServiceEntityMutableInterface.php b/shared/lib/People/Service/ServiceEntityMutableInterface.php index 8ba04f6..7feab5f 100644 --- a/shared/lib/People/Service/ServiceEntityMutableInterface.php +++ b/shared/lib/People/Service/ServiceEntityMutableInterface.php @@ -11,18 +11,21 @@ namespace KTXF\People\Service; use KTXF\People\Entity\EntityBaseInterface; use KTXF\People\Entity\EntityMutableInterface; +use KTXF\People\Entity\EntityPropertiesMutableInterface; +use KTXF\Resource\Identifier\CollectionIdentifierInterface; +use KTXF\Resource\Identifier\EntityIdentifierInterface; /** * Service Entity Mutable Interface * - * Optional interface for services that support entity CRUD operations. + * Optional interface for services that support entity CRUD operations * * @since 2025.05.01 */ interface ServiceEntityMutableInterface { public const CAPABILITY_ENTITY_CREATE = 'EntityCreate'; - public const CAPABILITY_ENTITY_UPDATE = 'EntityUpdate'; + public const CAPABILITY_ENTITY_MODIFY = 'EntityModify'; public const CAPABILITY_ENTITY_DELETE = 'EntityDelete'; public const CAPABILITY_ENTITY_COPY = 'EntityCopy'; public const CAPABILITY_ENTITY_MOVE = 'EntityMove'; @@ -41,36 +44,71 @@ interface ServiceEntityMutableInterface { * * @since 2025.05.01 * - * @param string|int $collection collection identifier - * @param EntityMutableInterface $entity Entity data - * @param array $options additional options + * @param CollectionIdentifierInterface $target Target collection identifier + * @param EntityPropertiesMutableInterface $properties Entity properties + * @param array $options Additional options * * @return EntityBaseInterface Created entity */ - public function entityCreate(string|int $collection, EntityMutableInterface $entity, array $options = []): EntityBaseInterface; + public function entityCreate(CollectionIdentifierInterface $target, EntityPropertiesMutableInterface $properties, array $options = []): EntityBaseInterface; /** * Modifies an existing entity * * @since 2025.05.01 * - * @param string|int $collection Collection identifier - * @param string|int $identifier Entity identifier - * @param EntityMutableInterface $entity Entity data + * @param EntityIdentifierInterface $target Target entity identifier + * @param EntityPropertiesMutableInterface $properties Entity properties to update * * @return EntityBaseInterface Modified entity */ - public function entityUpdate(string|int $collection, string|int $identifier, EntityMutableInterface $entity): EntityBaseInterface; + public function entityModify(EntityIdentifierInterface $target, EntityPropertiesMutableInterface $properties): EntityBaseInterface; + /** - * Deletes an existing entity in the specified collection + * Deletes entities + * + * @since 2026.04.01 + * + * @param EntityIdentifierInterface ...$targets Source entities to delete + * + * @return array Results keyed by source entity identifier + */ + public function entityDelete(EntityIdentifierInterface ...$targets): array; + + /** + * Moves entities to another collection + * + * @since 2025.05.01 + * + * @param CollectionIdentifierInterface $target Target collection identifier + * @param EntityIdentifierInterface ...$sources Source entities to move + * + * @return array Results keyed by source entity identifier + */ + public function entityMove(CollectionIdentifierInterface $target, EntityIdentifierInterface ...$sources): array; + + /** + * Copies entities to another collection * * @since 2025.05.01 * - * @param string|int $collection Collection identifier - * @param string|int $identifier Entity identifier to delete + * @param CollectionIdentifierInterface $target Target collection identifier + * @param EntityIdentifierInterface ...$sources Source entities to copy * - * @return EntityBaseInterface Deleted entity + * @return array Results keyed by source entity identifier */ - public function entityDelete(string|int $collection, string|int $identifier): EntityBaseInterface; + public function entityCopy(CollectionIdentifierInterface $target, EntityIdentifierInterface ...$sources): array; } diff --git a/shared/lib/People/Service/ServiceMutableInterface.php b/shared/lib/People/Service/ServiceMutableInterface.php index 2f9ada8..1c7e843 100644 --- a/shared/lib/People/Service/ServiceMutableInterface.php +++ b/shared/lib/People/Service/ServiceMutableInterface.php @@ -12,7 +12,7 @@ namespace KTXF\People\Service; /** * Service Mutable Interface * - * Marker interface for services that support mutable operations + * Extends base service interface with setter methods for mutable properties * * @since 2025.05.01 */