diff --git a/shared/lib/Mail/Collection/ICollectionMutable.php b/shared/lib/Mail/Collection/ICollectionMutable.php new file mode 100644 index 0000000..4ab8ae0 --- /dev/null +++ b/shared/lib/Mail/Collection/ICollectionMutable.php @@ -0,0 +1,98 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Mail\Collection; + +/** + * Mail Collection Mutable Interface + * + * Interface for creating and modifying mail collections with fluent setters. + * + * @since 2025.05.01 + */ +interface ICollectionMutable extends ICollectionBase { + + /** + * Sets the parent collection identifier + * + * @since 2025.05.01 + * + * @param string|int|null $in Parent collection ID or null for root + * + * @return self + */ + public function setIn(string|int|null $in): self; + + /** + * Sets the collection identifier + * + * @since 2025.05.01 + * + * @param string|int $id + * + * @return self + */ + public function setId(string|int $id): self; + + /** + * Sets the collection label/name + * + * @since 2025.05.01 + * + * @param string $label + * + * @return self + */ + public function setLabel(string $label): self; + + /** + * Sets the collection role + * + * @since 2025.05.01 + * + * @param CollectionRoles $role + * + * @return self + */ + public function setRole(CollectionRoles $role): self; + + /** + * Sets the total message count + * + * @since 2025.05.01 + * + * @param int|null $total + * + * @return self + */ + public function setTotal(?int $total): self; + + /** + * Sets the unread message count + * + * @since 2025.05.01 + * + * @param int|null $unread + * + * @return self + */ + public function setUnread(?int $unread): self; + + /** + * Sets the collection signature/sync token + * + * @since 2025.05.01 + * + * @param string|null $signature + * + * @return self + */ + public function setSignature(?string $signature): self; + +} diff --git a/shared/lib/Mail/Service/IServiceBase.php b/shared/lib/Mail/Service/IServiceBase.php index 8d7cdfb..bfc427b 100644 --- a/shared/lib/Mail/Service/IServiceBase.php +++ b/shared/lib/Mail/Service/IServiceBase.php @@ -10,17 +10,57 @@ declare(strict_types=1); namespace KTXF\Mail\Service; use JsonSerializable; +use KTXF\Mail\Collection\ICollectionBase; use KTXF\Mail\Entity\IAddress; +use KTXF\Mail\Entity\IMessageBase; +use KTXF\Resource\Filter\IFilter; +use KTXF\Resource\Range\IRange; +use KTXF\Resource\Range\RangeType; +use KTXF\Resource\Sort\ISort; /** * Mail Service Base Interface * - * Core interface for mail services providing identity, addressing, and capability information. + * Core interface for mail services with full protocol support (IMAP, JMAP, EWS, ActiveSync, Gmail API, etc.) + * Provides identity, addressing, capability information, and collection/message operations. * * @since 2025.05.01 */ interface IServiceBase extends JsonSerializable { + // Collection capabilities + public const CAPABILITY_COLLECTION_LIST = 'CollectionList'; + public const CAPABILITY_COLLECTION_LIST_FILTER = 'CollectionListFilter'; + public const CAPABILITY_COLLECTION_LIST_SORT = 'CollectionListSort'; + public const CAPABILITY_COLLECTION_EXTANT = 'CollectionExtant'; + public const CAPABILITY_COLLECTION_FETCH = 'CollectionFetch'; + + // Message capabilities + public const CAPABILITY_MESSAGE_LIST = 'MessageList'; + public const CAPABILITY_MESSAGE_LIST_FILTER = 'MessageListFilter'; + public const CAPABILITY_MESSAGE_LIST_SORT = 'MessageListSort'; + public const CAPABILITY_MESSAGE_LIST_RANGE = 'MessageListRange'; + public const CAPABILITY_MESSAGE_DELTA = 'MessageDelta'; + public const CAPABILITY_MESSAGE_EXTANT = 'MessageExtant'; + public const CAPABILITY_MESSAGE_FETCH = 'MessageFetch'; + public const CAPABILITY_MESSAGE_SEARCH = 'MessageSearch'; + + // Filter capabilities + public const CAPABILITY_FILTER_ID = 'FilterId'; + public const CAPABILITY_FILTER_SUBJECT = 'FilterSubject'; + public const CAPABILITY_FILTER_FROM = 'FilterFrom'; + public const CAPABILITY_FILTER_TO = 'FilterTo'; + public const CAPABILITY_FILTER_DATE = 'FilterDate'; + public const CAPABILITY_FILTER_FLAG = 'FilterFlag'; + public const CAPABILITY_FILTER_SIZE = 'FilterSize'; + public const CAPABILITY_FILTER_BODY = 'FilterBody'; + + // Sort capabilities + public const CAPABILITY_SORT_DATE = 'SortDate'; + public const CAPABILITY_SORT_SUBJECT = 'SortSubject'; + public const CAPABILITY_SORT_FROM = 'SortFrom'; + public const CAPABILITY_SORT_SIZE = 'SortSize'; + public const JSON_TYPE = 'mail.service'; public const JSON_PROPERTY_TYPE = '@type'; public const JSON_PROPERTY_PROVIDER = 'provider'; @@ -136,4 +176,152 @@ interface IServiceBase extends JsonSerializable { */ public function handlesAddress(string $address): bool; + /** + * Lists all collections in this service + * + * @since 2025.05.01 + * + * @param IFilter|null $filter Optional filter criteria + * @param ISort|null $sort Optional sort order + * + * @return array Collections indexed by ID + */ + public function collectionList(?IFilter $filter = null, ?ISort $sort = null): array; + + /** + * Creates a filter builder for collections + * + * @since 2025.05.01 + * + * @return IFilter + */ + public function collectionListFilter(): IFilter; + + /** + * Creates a sort builder for collections + * + * @since 2025.05.01 + * + * @return ISort + */ + public function collectionListSort(): ISort; + + /** + * Checks if collections exist + * + * @since 2025.05.01 + * + * @param string|int ...$identifiers Collection IDs to check + * + * @return array Map of ID => exists + */ + public function collectionExtant(string|int ...$identifiers): array; + + /** + * Fetches a single collection + * + * @since 2025.05.01 + * + * @param string|int $identifier Collection ID + * + * @return ICollectionBase|null Collection or null if not found + */ + public function collectionFetch(string|int $identifier): ?ICollectionBase; + + /** + * Lists messages in a collection + * + * @since 2025.05.01 + * + * @param string|int $collection Collection ID + * @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 + * + * @return array Messages indexed by ID + */ + public function messageList(string|int $collection, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null, ?array $properties = null): array; + + /** + * Creates a filter builder for messages + * + * @since 2025.05.01 + * + * @return IFilter + */ + public function messageListFilter(): IFilter; + + /** + * Creates a sort builder for messages + * + * @since 2025.05.01 + * + * @return ISort + */ + public function messageListSort(): ISort; + + /** + * Creates a range builder for messages + * + * @since 2025.05.01 + * + * @param RangeType $type Range type (offset, cursor, etc.) + * + * @return IRange + */ + public function messageListRange(RangeType $type): IRange; + + /** + * Gets incremental changes since last sync + * + * @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' + * + * @return array ['signature' => string, 'added' => array, 'modified' => array, 'removed' => array] + */ + public function messageDelta(string|int $collection, string $signature, string $detail = 'ids'): array; + + /** + * Checks if messages exist + * + * @since 2025.05.01 + * + * @param string|int $collection Collection ID + * @param string|int ...$identifiers Message IDs to check + * + * @return array Map of ID => exists + */ + public function messageExtant(string|int $collection, string|int ...$identifiers): array; + + /** + * Fetches one or more messages + * + * @since 2025.05.01 + * + * @param string|int $collection Collection ID + * @param string|int ...$identifiers Message IDs to fetch + * + * @return array Messages indexed by ID + */ + public function messageFetch(string|int $collection, string|int ...$identifiers): array; + + /** + * Searches messages across collections + * + * @since 2025.05.01 + * + * @param string $query Search query (syntax depends on protocol) + * @param array|null $collections Collection IDs to search (null = all) + * @param IFilter|null $filter Additional filter criteria + * @param ISort|null $sort Optional sort order + * @param IRange|null $range Optional pagination + * + * @return array Matching messages + */ + public function messageSearch(string $query, ?array $collections = null, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null): array; + } diff --git a/shared/lib/Mail/Service/IServiceCollectionMutable.php b/shared/lib/Mail/Service/IServiceCollectionMutable.php new file mode 100644 index 0000000..81cba39 --- /dev/null +++ b/shared/lib/Mail/Service/IServiceCollectionMutable.php @@ -0,0 +1,88 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Mail\Service; + +use KTXF\Mail\Collection\ICollectionBase; +use KTXF\Mail\Collection\ICollectionMutable; + +/** + * Mail Service Collection Mutable Interface + * + * Optional interface for services that support collection CRUD operations. + * Provides mailbox/folder creation, modification, deletion, and moving. + * + * @since 2025.05.01 + */ +interface IServiceCollectionMutable extends IServiceBase { + + public const CAPABILITY_COLLECTION_CREATE = 'CollectionCreate'; + public const CAPABILITY_COLLECTION_MODIFY = 'CollectionModify'; + public const CAPABILITY_COLLECTION_DESTROY = 'CollectionDestroy'; + public const CAPABILITY_COLLECTION_MOVE = 'CollectionMove'; + + /** + * Creates a fresh collection instance for configuration + * + * @since 2025.05.01 + * + * @return ICollectionMutable Fresh collection object + */ + public function collectionFresh(): ICollectionMutable; + + /** + * Creates a new collection + * + * @since 2025.05.01 + * + * @param string|int|null $location Parent collection ID (null for root) + * @param ICollectionMutable $collection Collection to create + * @param array $options Protocol-specific options + * + * @return ICollectionBase Created collection with assigned ID + */ + public function collectionCreate(string|int|null $location, ICollectionMutable $collection, array $options = []): ICollectionBase; + + /** + * Modifies an existing collection + * + * @since 2025.05.01 + * + * @param string|int $identifier Collection ID + * @param ICollectionMutable $collection Updated collection data + * + * @return ICollectionBase Modified collection + */ + public function collectionModify(string|int $identifier, ICollectionMutable $collection): ICollectionBase; + + /** + * Destroys a collection + * + * @since 2025.05.01 + * + * @param string|int $identifier Collection ID + * @param bool $recursive Destroy child collections too + * + * @return bool True if destroyed + */ + public function collectionDestroy(string|int $identifier, bool $recursive = false): bool; + + /** + * Moves a collection to a new parent + * + * @since 2025.05.01 + * + * @param string|int $identifier Collection ID + * @param string|int|null $targetLocation New parent ID (null for root) + * + * @return ICollectionBase Moved collection + */ + public function collectionMove(string|int $identifier, string|int|null $targetLocation): ICollectionBase; + +} diff --git a/shared/lib/Mail/Service/IServiceMessageMutable.php b/shared/lib/Mail/Service/IServiceMessageMutable.php new file mode 100644 index 0000000..87f6bee --- /dev/null +++ b/shared/lib/Mail/Service/IServiceMessageMutable.php @@ -0,0 +1,119 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\Mail\Service; + +use KTXF\Mail\Entity\IMessageBase; +use KTXF\Mail\Entity\IMessageMutable; + +/** + * Mail Service Message Mutable Interface + * + * Optional interface for services that support message CRUD operations. + * Provides message creation, modification, deletion, copying, moving, and flag management. + * + * @since 2025.05.01 + */ +interface IServiceMessageMutable extends IServiceBase { + + public const CAPABILITY_MESSAGE_CREATE = 'MessageCreate'; + public const CAPABILITY_MESSAGE_MODIFY = 'MessageModify'; + public const CAPABILITY_MESSAGE_DESTROY = 'MessageDestroy'; + public const CAPABILITY_MESSAGE_COPY = 'MessageCopy'; + public const CAPABILITY_MESSAGE_MOVE = 'MessageMove'; + public const CAPABILITY_MESSAGE_FLAG = 'MessageFlag'; + + /** + * Creates a fresh message instance for composition + * + * @since 2025.05.01 + * + * @return IMessageMutable Fresh message object + */ + public function messageFresh(): IMessageMutable; + + /** + * Creates/imports a message into a collection + * + * @since 2025.05.01 + * + * @param string|int $collection Target collection ID + * @param IMessageMutable $message Message to create + * @param array $options Protocol-specific options (e.g., flags, keywords) + * + * @return IMessageBase Created message with assigned ID + */ + public function messageCreate(string|int $collection, IMessageMutable $message, array $options = []): IMessageBase; + + /** + * Modifies an existing message + * + * @since 2025.05.01 + * + * @param string|int $collection Collection ID + * @param string|int $identifier Message ID + * @param IMessageMutable $message Updated message data + * + * @return IMessageBase Modified message + */ + public function messageModify(string|int $collection, string|int $identifier, IMessageMutable $message): IMessageBase; + + /** + * Destroys one or more messages + * + * @since 2025.05.01 + * + * @param string|int $collection Collection ID + * @param string|int ...$identifiers Message IDs to destroy + * + * @return array Map of ID => destroyed + */ + public function messageDestroy(string|int $collection, string|int ...$identifiers): array; + + /** + * Copies messages to another collection + * + * @since 2025.05.01 + * + * @param string|int $sourceCollection Source collection ID + * @param string|int $targetCollection Target collection ID + * @param string|int ...$identifiers Message IDs to copy + * + * @return array Map of source ID => new ID + */ + public function messageCopy(string|int $sourceCollection, string|int $targetCollection, string|int ...$identifiers): array; + + /** + * Moves messages to another collection + * + * @since 2025.05.01 + * + * @param string|int $sourceCollection Source collection ID + * @param string|int $targetCollection Target collection ID + * @param string|int ...$identifiers Message IDs to move + * + * @return array Map of ID => moved + */ + public function messageMove(string|int $sourceCollection, string|int $targetCollection, string|int ...$identifiers): array; + + /** + * Sets flags on messages + * + * @since 2025.05.01 + * + * @param string|int $collection Collection ID + * @param array $flags Flags to set (e.g., ['\Seen', '\Flagged']) + * @param bool $value True to add flags, false to remove + * @param string|int ...$identifiers Message IDs + * + * @return array Map of ID => success + */ + public function messageFlag(string|int $collection, array $flags, bool $value, string|int ...$identifiers): array; + +}