lots of improvements

This commit is contained in:
root
2026-02-10 17:47:48 -05:00
parent 6d0c5584bd
commit b87b5d9052
65 changed files with 3445 additions and 1577 deletions

View File

@@ -9,9 +9,9 @@ declare(strict_types=1);
namespace KTXF\Mail\Service;
use KTXF\Mail\Collection\ICollectionBase;
use KTXF\Mail\Entity\IAddress;
use KTXF\Mail\Entity\IMessageBase;
use KTXF\Mail\Collection\CollectionBaseInterface;
use KTXF\Mail\Object\AddressInterface;
use KTXF\Resource\Delta\Delta;
use KTXF\Resource\Filter\IFilter;
use KTXF\Resource\Provider\ResourceServiceBaseInterface;
use KTXF\Resource\Range\IRange;
@@ -34,7 +34,13 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
public const CAPABILITY_COLLECTION_LIST_SORT = 'CollectionListSort';
public const CAPABILITY_COLLECTION_EXTANT = 'CollectionExtant';
public const CAPABILITY_COLLECTION_FETCH = 'CollectionFetch';
// Message capabilities
// Collection Filter
public const CAPABILITY_COLLECTION_FILTER_LABEL = 'label';
public const CAPABILITY_COLLECTION_FILTER_ROLE = 'role';
// Collection Sort
public const CAPABILITY_COLLECTION_SORT_LABEL = 'label';
public const CAPABILITY_COLLECTION_SORT_RANK = 'rank';
// Entity capabilities
public const CAPABILITY_ENTITY_LIST = 'EntityList';
public const CAPABILITY_ENTITY_LIST_FILTER = 'EntityListFilter';
public const CAPABILITY_ENTITY_LIST_SORT = 'EntityListSort';
@@ -43,19 +49,24 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
public const CAPABILITY_ENTITY_EXTANT = 'EntityExtant';
public const CAPABILITY_ENTITY_FETCH = 'EntityFetch';
// Filter capabilities
public const CAPABILITY_FILTER_ID = 'id';
public const CAPABILITY_FILTER_SUBJECT = 'subject';
public const CAPABILITY_FILTER_FROM = 'from';
public const CAPABILITY_FILTER_TO = 'to';
public const CAPABILITY_FILTER_DATE = 'date';
public const CAPABILITY_FILTER_FLAG = 'flag';
public const CAPABILITY_FILTER_SIZE = 'size';
public const CAPABILITY_FILTER_BODY = 'body';
public const CAPABILITY_ENTITY_FILTER_ALL = '*';
public const CAPABILITY_ENTITY_FILTER_FROM = 'from';
public const CAPABILITY_ENTITY_FILTER_TO = 'to';
public const CAPABILITY_ENTITY_FILTER_CC = 'cc';
public const CAPABILITY_ENTITY_FILTER_BCC = 'bcc';
public const CAPABILITY_ENTITY_FILTER_SUBJECT = 'subject';
public const CAPABILITY_ENTITY_FILTER_BODY = 'body';
public const CAPABILITY_ENTITY_FILTER_DATE_BEFORE = 'before';
public const CAPABILITY_ENTITY_FILTER_DATE_AFTER = 'after';
public const CAPABILITY_ENTITY_FILTER_SIZE_MIN = 'min';
public const CAPABILITY_ENTITY_FILTER_SIZE_MAX = 'max';
// Sort capabilities
public const CAPABILITY_SORT_DATE = 'date';
public const CAPABILITY_SORT_SUBJECT = 'subject';
public const CAPABILITY_SORT_FROM = 'from';
public const CAPABILITY_SORT_SIZE = 'size';
public const CAPABILITY_ENTITY_SORT_FROM = 'from';
public const CAPABILITY_ENTITY_SORT_TO = 'to';
public const CAPABILITY_ENTITY_SORT_SUBJECT = 'subject';
public const CAPABILITY_ENTITY_SORT_DATE_RECEIVED = 'received';
public const CAPABILITY_ENTITY_SORT_DATE_SENT = 'sent';
public const CAPABILITY_ENTITY_SORT_SIZE = 'size';
public const JSON_TYPE = 'mail.service';
public const JSON_PROPERTY_PRIMARY_ADDRESS = 'primaryAddress';
@@ -66,16 +77,16 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
*
* @since 2025.05.01
*
* @return IAddress
* @return AddressInterface
*/
public function getPrimaryAddress(): IAddress;
public function getPrimaryAddress(): AddressInterface;
/**
* Gets the secondary mailing addresses (aliases) for this service
*
* @since 2025.05.01
*
* @return array<int, IAddress>
* @return array<int,AddressInterface>
*/
public function getSecondaryAddresses(): array;
@@ -88,7 +99,7 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
*
* @return bool True if address matches primary or any secondary address
*/
public function handlesAddress(string $address): bool;
public function hasAddress(string $address): bool;
/**
* Lists all collections in this service
@@ -98,9 +109,9 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
* @param IFilter|null $filter Optional filter criteria
* @param ISort|null $sort Optional sort order
*
* @return array<string|int,ICollectionBase> Collections indexed by ID
* @return array<string|int,CollectionBaseInterface> Collections indexed by ID
*/
public function collectionList(?IFilter $filter = null, ?ISort $sort = null): array;
public function collectionList(string|int $location, ?IFilter $filter = null, ?ISort $sort = null): array;
/**
* Creates a filter builder for collections
@@ -129,7 +140,7 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
*
* @return array<string|int,bool> Map of ID => exists
*/
public function collectionExtant(string|int ...$identifiers): array;
public function collectionExtant(string|int $location, string|int ...$identifiers): array;
/**
* Fetches a single collection
@@ -138,9 +149,9 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
*
* @param string|int $identifier Collection ID
*
* @return ICollectionBase|null Collection or null if not found
* @return CollectionBaseInterface|null Collection or null if not found
*/
public function collectionFetch(string|int $identifier): ?ICollectionBase;
public function collectionFetch(string|int $identifier): ?CollectionBaseInterface;
/**
* Lists messages in a collection
@@ -153,9 +164,9 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
* @param IRange|null $range Optional pagination
* @param array|null $properties Optional message properties to fetch
*
* @return array<string|int,IMessageBase> Messages indexed by ID
* @return array<string|int,EntityBaseInterface> Messages indexed by ID
*/
public function messageList(string|int $collection, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null, ?array $properties = null): array;
public function entityList(string|int $collection, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null, ?array $properties = null): array;
/**
* Creates a filter builder for messages
@@ -164,7 +175,7 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
*
* @return IFilter
*/
public function messageListFilter(): IFilter;
public function entityListFilter(): IFilter;
/**
* Creates a sort builder for messages
@@ -173,7 +184,7 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
*
* @return ISort
*/
public function messageListSort(): ISort;
public function entityListSort(): ISort;
/**
* Creates a range builder for messages
@@ -184,7 +195,7 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
*
* @return IRange
*/
public function messageListRange(RangeType $type): IRange;
public function entityListRange(RangeType $type): IRange;
/**
* Gets incremental changes since last sync
@@ -197,7 +208,7 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
*
* @return array ['signature' => string, 'added' => array, 'modified' => array, 'removed' => array]
*/
public function messageDelta(string|int $collection, string $signature, string $detail = 'ids'): array;
public function entityDelta(string|int $collection, string $signature, string $detail = 'ids'): Delta;
/**
* Checks if messages exist
@@ -209,18 +220,18 @@ interface ServiceBaseInterface extends ResourceServiceBaseInterface {
*
* @return array<string|int,bool> Map of ID => exists
*/
public function messageExtant(string|int $collection, string|int ...$identifiers): array;
public function entityExtant(string|int $collection, string|int ...$identifiers): array;
/**
* Fetches one or more messages
* Fetches one or more entities
*
* @since 2025.05.01
*
* @param string|int $collection Collection ID
* @param string|int ...$identifiers Message IDs to fetch
*
* @return array<string|int,IMessageBase> Messages indexed by ID
* @return array<string|int,EntityBaseInterface> Messages indexed by ID
*/
public function messageFetch(string|int $collection, string|int ...$identifiers): array;
public function entityFetch(string|int $collection, string|int ...$identifiers): array;
}

View File

@@ -9,8 +9,8 @@ declare(strict_types=1);
namespace KTXF\Mail\Service;
use KTXF\Mail\Collection\ICollectionBase;
use KTXF\Mail\Collection\ICollectionMutable;
use KTXF\Mail\Collection\CollectionBaseInterface;
use KTXF\Mail\Collection\CollectionMutableInterface;
/**
* Mail Service Collection Mutable Interface
@@ -32,9 +32,9 @@ interface ServiceCollectionMutableInterface extends ServiceBaseInterface {
*
* @since 2025.05.01
*
* @return ICollectionMutable Fresh collection object
* @return CollectionMutableInterface Fresh collection object
*/
public function collectionFresh(): ICollectionMutable;
public function collectionFresh(): CollectionMutableInterface;
/**
* Creates a new collection
@@ -42,12 +42,12 @@ interface ServiceCollectionMutableInterface extends ServiceBaseInterface {
* @since 2025.05.01
*
* @param string|int|null $location Parent collection ID (null for root)
* @param ICollectionMutable $collection Collection to create
* @param CollectionMutableInterface $collection Collection to create
* @param array $options Protocol-specific options
*
* @return ICollectionBase Created collection with assigned ID
* @return CollectionBaseInterface Created collection with assigned ID
*/
public function collectionCreate(string|int|null $location, ICollectionMutable $collection, array $options = []): ICollectionBase;
public function collectionCreate(string|int|null $location, CollectionMutableInterface $collection, array $options = []): CollectionBaseInterface;
/**
* Modifies an existing collection
@@ -55,11 +55,11 @@ interface ServiceCollectionMutableInterface extends ServiceBaseInterface {
* @since 2025.05.01
*
* @param string|int $identifier Collection ID
* @param ICollectionMutable $collection Updated collection data
* @param CollectionMutableInterface $collection Updated collection data
*
* @return ICollectionBase Modified collection
* @return CollectionBaseInterface Modified collection
*/
public function collectionModify(string|int $identifier, ICollectionMutable $collection): ICollectionBase;
public function collectionModify(string|int $identifier, CollectionMutableInterface $collection): CollectionBaseInterface;
/**
* Destroys a collection
@@ -67,11 +67,12 @@ interface ServiceCollectionMutableInterface extends ServiceBaseInterface {
* @since 2025.05.01
*
* @param string|int $identifier Collection ID
* @param bool $recursive Destroy child collections too
* @param bool $force Force destruction even if not empty
* @param bool $recursive Recursively destroy contents
*
* @return bool True if destroyed
*/
public function collectionDestroy(string|int $identifier, bool $recursive = false): bool;
public function collectionDestroy(string|int $identifier, bool $force = false, bool $recursive = false): bool;
/**
* Moves a collection to a new parent
@@ -81,8 +82,8 @@ interface ServiceCollectionMutableInterface extends ServiceBaseInterface {
* @param string|int $identifier Collection ID
* @param string|int|null $targetLocation New parent ID (null for root)
*
* @return ICollectionBase Moved collection
* @return CollectionBaseInterface Moved collection
*/
public function collectionMove(string|int $identifier, string|int|null $targetLocation): ICollectionBase;
public function collectionMove(string|int $identifier, string|int|null $targetLocation): CollectionBaseInterface;
}

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace KTXF\Mail\Service;
use KTXF\Resource\Provider\ResourceServiceConfigureInterface;
/**
* Mail Service Mutable Interface
*
* Extends base service interface with setter methods for mutable properties.
* Used for service configuration and updates.
*
* @since 2025.05.01
*/
interface ServiceConfigurableInterface extends ServiceMutableInterface, ResourceServiceConfigureInterface {
public const JSON_TYPE = ServiceBaseInterface::JSON_TYPE;
}

View File

@@ -0,0 +1,103 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace KTXF\Mail\Service;
use KTXF\Mail\Entity\EntityBaseInterface;
use KTXF\Mail\Entity\EntityMutableInterface;
/**
* Mail Service Entity Mutable Interface
*
* Optional interface for services that support entity CRUD operations.
* Provides entity creation, modification, deletion, copying, moving, and flag management.
*
* @since 2025.05.01
*/
interface ServiceEntityMutableInterface extends ServiceBaseInterface {
public const CAPABILITY_ENTITY_CREATE = 'EntityCreate';
public const CAPABILITY_ENTITY_MODIFY = 'EntityModify';
public const CAPABILITY_ENTITY_DESTROY = 'EntityDestroy';
public const CAPABILITY_ENTITY_COPY = 'EntityCopy';
public const CAPABILITY_ENTITY_MOVE = 'EntityMove';
/**
* Creates a fresh entity instance for composition
*
* @since 2025.05.01
*
* @return EntityMutableInterface Fresh entity object
*/
public function entityFresh(): EntityMutableInterface;
/**
* Creates/imports an entity into a collection
*
* @since 2025.05.01
*
* @param string|int $collection collection identifier
* @param EntityMutableInterface $entity Entity data
* @param array $options additional options
*
* @return EntityBaseInterface Created entity
*/
public function entityCreate(string|int $collection, EntityMutableInterface $entity, 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
*
* @return EntityBaseInterface Modified entity
*/
public function entityModify(string|int $collection, string|int $identifier, EntityMutableInterface $entity): EntityBaseInterface;
/**
* Destroys one or more entities
*
* @since 2025.05.01
*
* @param string|int $collection Collection identifier
* @param string|int ...$identifiers Entity identifiers to destroy
*
* @return array<string|int,bool> List of destroyed entity identifiers
*/
public function entityDestroy(string|int $collection, string|int ...$identifiers): array;
/**
* Copies entities to another collection
*
* @since 2025.05.01
*
* @param string|int $sourceCollection Source collection identifier
* @param string|int $targetCollection Target collection identifier
* @param string|int ...$identifiers Entity identifiers to copy
*
* @return array<string|int,string|int> Map of source identifier => new identifier
*/
public function entityCopy(string|int $sourceCollection, string|int $targetCollection, string|int ...$identifiers): array;
/**
* Moves entities to another collection
*
* @since 2025.05.01
*
* @param string|int $sourceCollection Source collection identifier
* @param string|int $targetCollection Target collection identifier
* @param string|int ...$identifiers Entity identifiers to move
*
* @return array<string|int,bool> List of moved entity identifiers
*/
public function entityMove(string|int $sourceCollection, string|int $targetCollection, string|int ...$identifiers): array;
}

View File

@@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace KTXF\Mail\Service;
use KTXF\Mail\Entity\EntityMutableInterface;
use KTXF\Mail\Exception\SendException;
/**
* Mail Service Transmit Interface
*
* Interface for mail services capable of transmitting outbound entities.
*
* @since 2025.05.01
*/
interface ServiceEntityTransmitInterface extends ServiceBaseInterface {
public const CAPABILITY_ENTITY_TRANSMIT = 'EntityTransmit';
/**
* Creates a fresh entity instance for composition
*
* @since 2025.05.01
*
* @return EntityMutableInterface Fresh entity object
*/
public function entityFresh(): EntityMutableInterface;
/**
* Transmits an outbound entity
*
* @since 2025.05.01
*
* @param EntityMutableInterface $entity Entity to transmit
*
* @return string Entity identifier assigned by the transport
*
* @throws SendException On delivery failure
*/
public function entitySend(EntityMutableInterface $entity): string;
}

View File

@@ -1,119 +0,0 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
* 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 ServiceMessageMutableInterface extends ServiceBaseInterface {
public const CAPABILITY_ENTITY_CREATE = 'EntityCreate';
public const CAPABILITY_ENTITY_MODIFY = 'EntityModify';
public const CAPABILITY_ENTITY_DESTROY = 'EntityDestroy';
public const CAPABILITY_ENTITY_COPY = 'EntityCopy';
public const CAPABILITY_ENTITY_MOVE = 'EntityMove';
public const CAPABILITY_ENTITY_FLAG = 'EntityFlag';
/**
* 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<string|int,bool> 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<string|int,string|int> 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<string|int,bool> 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<string|int,bool> Map of ID => success
*/
public function messageFlag(string|int $collection, array $flags, bool $value, string|int ...$identifiers): array;
}

View File

@@ -1,49 +0,0 @@
<?php
declare(strict_types=1);
/**
* SPDX-FileCopyrightText: Sebastian Krupinski <krupinski01@gmail.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
namespace KTXF\Mail\Service;
use KTXF\Mail\Entity\IMessageMutable;
use KTXF\Mail\Exception\SendException;
/**
* Mail Service Send Interface
*
* Interface for mail services capable of sending outbound messages.
* This is the minimum capability for an outbound-only mail service.
*
* @since 2025.05.01
*/
interface ServiceMessageSendInterface extends ServiceBaseInterface {
public const CAPABILITY_SEND = 'Send';
/**
* Creates a new fresh message object
*
* @since 2025.05.01
*
* @return IMessageMutable Fresh message object for composing
*/
public function messageFresh(): IMessageMutable;
/**
* Sends an outbound message
*
* @since 2025.05.01
*
* @param IMessageMutable $message Message to send
*
* @return string Message ID assigned by the transport
*
* @throws SendException On delivery failure
*/
public function messageSend(IMessageMutable $message): string;
}

View File

@@ -9,7 +9,7 @@ declare(strict_types=1);
namespace KTXF\Mail\Service;
use KTXF\Mail\Entity\IAddress;
use KTXF\Mail\Object\AddressInterface;
/**
* Mail Service Mutable Interface
@@ -26,21 +26,21 @@ interface ServiceMutableInterface extends ServiceBaseInterface {
*
* @since 2025.05.01
*
* @param IAddress $value Primary email address
* @param AddressInterface $value Primary email address
*
* @return self
* @return static
*/
public function setPrimaryAddress(IAddress $value): self;
public function setPrimaryAddress(AddressInterface $value): static;
/**
* Sets the secondary mailing addresses (aliases) for this service
*
* @since 2025.05.01
*
* @param array<int, IAddress> $value Array of secondary addresses
* @param array<int,AddressInterface> $value Array of secondary addresses
*
* @return self
* @return static
*/
public function setSecondaryAddresses(array $value): self;
public function setSecondaryAddresses(array $value): static;
}