From f3c882454d0ffea804879a0cb7d01a78bc596ea0 Mon Sep 17 00:00:00 2001 From: Sebastian Krupinski Date: Thu, 14 May 2026 22:54:51 -0400 Subject: [PATCH] refactor: mail interfaces Signed-off-by: Sebastian Krupinski --- .../Collection/CollectionBaseAbstract.php | 6 + .../Collection/CollectionMutableAbstract.php | 5 + .../CollectionPropertiesBaseAbstract.php | 18 +- .../CollectionPropertiesBaseInterface.php | 13 +- .../CollectionPropertiesMutableAbstract.php | 10 +- .../CollectionPropertiesMutableInterface.php | 2 - shared/lib/Mail/Entity/EntityBaseAbstract.php | 6 + .../lib/Mail/Entity/EntityBaseInterface.php | 2 - .../lib/Mail/Entity/EntityMutableAbstract.php | 8 +- .../Mail/Entity/EntityMutableInterface.php | 2 - .../Object/MessagePropertiesBaseAbstract.php | 361 +++------- .../Object/MessagePropertiesBaseInterface.php | 119 ++-- .../MessagePropertiesMutableAbstract.php | 626 ++++++------------ .../MessagePropertiesMutableInterface.php | 87 +-- .../ProviderServiceDiscoverInterface.php | 2 +- .../ProviderServiceMutateInterface.php | 4 +- .../Provider/ProviderServiceTestInterface.php | 7 +- .../ServiceCollectionMutableInterface.php | 24 +- .../Provider/Node/NodeBaseAbstract.php | 155 +++-- .../Provider/Node/NodeBaseInterface.php | 18 +- .../Provider/Node/NodeMutableAbstract.php | 46 +- .../Node/NodePropertiesBaseAbstract.php | 13 +- .../Node/NodePropertiesBaseInterface.php | 7 +- .../Node/NodePropertiesMutableInterface.php | 4 +- 24 files changed, 583 insertions(+), 962 deletions(-) diff --git a/shared/lib/Mail/Collection/CollectionBaseAbstract.php b/shared/lib/Mail/Collection/CollectionBaseAbstract.php index 17959f9..79044df 100644 --- a/shared/lib/Mail/Collection/CollectionBaseAbstract.php +++ b/shared/lib/Mail/Collection/CollectionBaseAbstract.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace KTXF\Mail\Collection; +use KTXF\Resource\Identifier\CollectionIdentifier; use KTXF\Resource\Provider\Node\NodeBaseAbstract; /** @@ -20,8 +21,13 @@ use KTXF\Resource\Provider\Node\NodeBaseAbstract; */ abstract class CollectionBase extends NodeBaseAbstract implements CollectionBaseInterface { + protected string $type = 'mail.collection'; protected CollectionPropertiesBaseAbstract $properties; + protected function nodeIdentifier(): CollectionIdentifier { + return new CollectionIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE], (string) $this->data[static::PROPERTY_IDENTIFIER]); + } + /** * @inheritDoc */ diff --git a/shared/lib/Mail/Collection/CollectionMutableAbstract.php b/shared/lib/Mail/Collection/CollectionMutableAbstract.php index 3dae2c8..fe7068f 100644 --- a/shared/lib/Mail/Collection/CollectionMutableAbstract.php +++ b/shared/lib/Mail/Collection/CollectionMutableAbstract.php @@ -9,6 +9,7 @@ declare(strict_types=1); namespace KTXF\Mail\Collection; +use KTXF\Resource\Identifier\CollectionIdentifier; use KTXF\Resource\Provider\Node\NodeMutableAbstract; use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; @@ -23,6 +24,10 @@ abstract class CollectionMutableAbstract extends NodeMutableAbstract implements protected CollectionPropertiesMutableAbstract $properties; + protected function nodeIdentifier(): CollectionIdentifier { + return new CollectionIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE], $this->data[static::PROPERTY_IDENTIFIER]); + } + /** * @inheritDoc */ diff --git a/shared/lib/Mail/Collection/CollectionPropertiesBaseAbstract.php b/shared/lib/Mail/Collection/CollectionPropertiesBaseAbstract.php index 7cf60b5..f9a37a7 100644 --- a/shared/lib/Mail/Collection/CollectionPropertiesBaseAbstract.php +++ b/shared/lib/Mail/Collection/CollectionPropertiesBaseAbstract.php @@ -20,49 +20,47 @@ use KTXF\Resource\Provider\Node\NodePropertiesBaseAbstract; */ abstract class CollectionPropertiesBaseAbstract extends NodePropertiesBaseAbstract implements CollectionPropertiesBaseInterface { - public const JSON_TYPE = CollectionPropertiesBaseInterface::JSON_TYPE; - /** * @inheritDoc */ public function total(): int { - return $this->data['total'] ?? 0; + return $this->data[static::PROPERTY_TOTAL] ?? 0; } /** * @inheritDoc */ public function unread(): int { - return $this->data['unread'] ?? 0; + return $this->data[static::PROPERTY_UNREAD] ?? 0; } /** * @inheritDoc */ public function getLabel(): string { - return $this->data['label'] ?? ''; + return $this->data[static::PROPERTY_LABEL] ?? ''; } /** * @inheritDoc */ public function getRole(): CollectionRoles { - return isset($this->data['role']) - ? ($this->data['role'] instanceof CollectionRoles ? $this->data['role'] : CollectionRoles::from($this->data['role'])) - : CollectionRoles::Custom; + return isset($this->data[static::PROPERTY_ROLE]) + ? ($this->data[static::PROPERTY_ROLE] instanceof CollectionRoles ? $this->data[static::PROPERTY_ROLE] : CollectionRoles::from($this->data[static::PROPERTY_ROLE])) + : CollectionRoles::None; } /** * @inheritDoc */ public function getRank(): int { - return $this->data['rank'] ?? 0; + return $this->data[static::PROPERTY_RANK] ?? 0; } /** * @inheritDoc */ public function getSubscription(): bool { - return $this->data['subscribed'] ?? false; + return $this->data[static::PROPERTY_SUBSCRIPTION] ?? false; } } diff --git a/shared/lib/Mail/Collection/CollectionPropertiesBaseInterface.php b/shared/lib/Mail/Collection/CollectionPropertiesBaseInterface.php index a6197c0..372a5f7 100644 --- a/shared/lib/Mail/Collection/CollectionPropertiesBaseInterface.php +++ b/shared/lib/Mail/Collection/CollectionPropertiesBaseInterface.php @@ -13,13 +13,12 @@ use KTXF\Resource\Provider\Node\NodePropertiesBaseInterface; interface CollectionPropertiesBaseInterface extends NodePropertiesBaseInterface { - public const JSON_TYPE = 'mail.collection'; - public const JSON_PROPERTY_TOTAL = 'total'; - public const JSON_PROPERTY_UNREAD = 'unread'; - public const JSON_PROPERTY_LABEL = 'label'; - public const JSON_PROPERTY_ROLE = 'role'; - public const JSON_PROPERTY_RANK = 'rank'; - public const JSON_PROPERTY_SUBSCRIPTION = 'subscription'; + public const PROPERTY_TOTAL = 'total'; + public const PROPERTY_UNREAD = 'unread'; + public const PROPERTY_LABEL = 'label'; + public const PROPERTY_ROLE = 'role'; + public const PROPERTY_RANK = 'rank'; + public const PROPERTY_SUBSCRIPTION = 'subscription'; public function total(): int; diff --git a/shared/lib/Mail/Collection/CollectionPropertiesMutableAbstract.php b/shared/lib/Mail/Collection/CollectionPropertiesMutableAbstract.php index edc820b..f05af9c 100644 --- a/shared/lib/Mail/Collection/CollectionPropertiesMutableAbstract.php +++ b/shared/lib/Mail/Collection/CollectionPropertiesMutableAbstract.php @@ -16,8 +16,6 @@ use KTXF\Resource\Provider\Node\NodePropertiesMutableAbstract; */ abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesBaseAbstract implements CollectionPropertiesMutableInterface { - public const JSON_TYPE = CollectionPropertiesBaseInterface::JSON_TYPE; - /** * @inheritDoc */ @@ -35,7 +33,7 @@ abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesB * @inheritDoc */ public function setLabel(string $value): static { - $this->data['label'] = $value; + $this->data[self::PROPERTY_LABEL] = $value; return $this; } @@ -43,7 +41,7 @@ abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesB * @inheritDoc */ public function setRole(CollectionRoles $value): static { - $this->data['role'] = $value; + $this->data[self::PROPERTY_ROLE] = $value; return $this; } @@ -51,7 +49,7 @@ abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesB * @inheritDoc */ public function setRank(int $value): static { - $this->data['rank'] = $value; + $this->data[self::PROPERTY_RANK] = $value; return $this; } @@ -59,7 +57,7 @@ abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesB * @inheritDoc */ public function setSubscription(bool $value): static { - $this->data['subscription'] = $value; + $this->data[self::PROPERTY_SUBSCRIPTION] = $value; return $this; } } diff --git a/shared/lib/Mail/Collection/CollectionPropertiesMutableInterface.php b/shared/lib/Mail/Collection/CollectionPropertiesMutableInterface.php index a16557c..e4a978c 100644 --- a/shared/lib/Mail/Collection/CollectionPropertiesMutableInterface.php +++ b/shared/lib/Mail/Collection/CollectionPropertiesMutableInterface.php @@ -13,8 +13,6 @@ use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; interface CollectionPropertiesMutableInterface extends CollectionPropertiesBaseInterface, NodePropertiesMutableInterface { - public const JSON_TYPE = CollectionPropertiesBaseInterface::JSON_TYPE; - public function setLabel(string $value); public function setRole(CollectionRoles $value): static; diff --git a/shared/lib/Mail/Entity/EntityBaseAbstract.php b/shared/lib/Mail/Entity/EntityBaseAbstract.php index a88fcb8..ec46240 100644 --- a/shared/lib/Mail/Entity/EntityBaseAbstract.php +++ b/shared/lib/Mail/Entity/EntityBaseAbstract.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace KTXF\Mail\Entity; use KTXF\Mail\Object\MessagePropertiesBaseInterface; +use KTXF\Resource\Identifier\EntityIdentifier; use KTXF\Resource\Provider\Node\NodeBaseAbstract; /** @@ -21,8 +22,13 @@ use KTXF\Resource\Provider\Node\NodeBaseAbstract; */ abstract class EntityBaseAbstract extends NodeBaseAbstract implements EntityBaseInterface { + protected string $type = 'mail.entity'; protected MessagePropertiesBaseInterface $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/Mail/Entity/EntityBaseInterface.php b/shared/lib/Mail/Entity/EntityBaseInterface.php index 3a7b054..25f8c61 100644 --- a/shared/lib/Mail/Entity/EntityBaseInterface.php +++ b/shared/lib/Mail/Entity/EntityBaseInterface.php @@ -15,8 +15,6 @@ use KTXF\Resource\Provider\Node\NodeBaseInterface; interface EntityBaseInterface extends NodeBaseInterface { - public const JSON_TYPE = 'mail.entity'; - /** * Gets the entity properties * diff --git a/shared/lib/Mail/Entity/EntityMutableAbstract.php b/shared/lib/Mail/Entity/EntityMutableAbstract.php index 1148120..204f638 100644 --- a/shared/lib/Mail/Entity/EntityMutableAbstract.php +++ b/shared/lib/Mail/Entity/EntityMutableAbstract.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace KTXF\Mail\Entity; use KTXF\Mail\Object\MessagePropertiesMutableInterface; +use KTXF\Resource\Identifier\EntityIdentifier; use KTXF\Resource\Provider\Node\NodeMutableAbstract; use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; @@ -22,10 +23,13 @@ use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; */ abstract class EntityMutableAbstract extends NodeMutableAbstract implements EntityMutableInterface { - public const JSON_TYPE = EntityMutableInterface::JSON_TYPE; - + protected string $type = 'mail.entity'; protected MessagePropertiesMutableInterface $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 */ diff --git a/shared/lib/Mail/Entity/EntityMutableInterface.php b/shared/lib/Mail/Entity/EntityMutableInterface.php index 88bb136..368eab7 100644 --- a/shared/lib/Mail/Entity/EntityMutableInterface.php +++ b/shared/lib/Mail/Entity/EntityMutableInterface.php @@ -17,8 +17,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/Mail/Object/MessagePropertiesBaseAbstract.php b/shared/lib/Mail/Object/MessagePropertiesBaseAbstract.php index 6dcd267..fac63d1 100644 --- a/shared/lib/Mail/Object/MessagePropertiesBaseAbstract.php +++ b/shared/lib/Mail/Object/MessagePropertiesBaseAbstract.php @@ -21,188 +21,161 @@ use KTXF\Resource\Provider\Node\NodePropertiesBaseAbstract; */ abstract class MessagePropertiesBaseAbstract extends NodePropertiesBaseAbstract implements MessagePropertiesBaseInterface { - public const JSON_TYPE = MessagePropertiesBaseInterface::JSON_TYPE; + protected string $type = 'mail.message'; /** * @inheritDoc */ - public function getHeaders(): array { - return $this->data['headers'] ?? []; - } - - /** - * @inheritDoc - */ - public function getHeader(string $name): string|array|null { - return $this->data['headers'][$name] ?? null; - } - - /** - * @inheritDoc - */ - public function getUrid(): ?string { - return $this->data['urid'] ?? null; - } - - /** - * @inheritDoc - */ - public function getCreated(): ?DateTimeImmutable { - return $this->data['created'] ?? null; - } - - /** - * @inheritDoc - */ - public function getModified(): ?DateTimeImmutable { - return $this->data['modified'] ?? null; - } - - /** - * @inheritDoc - */ - public function getDate(): ?DateTimeImmutable { - return $this->data['date'] ?? null; - } - - /** - * @inheritDoc - */ - public function getReceived(): ?DateTimeImmutable { - return $this->data['received'] ?? null; + public function jsonSerialize(): array { + return $this->data; } /** * @inheritDoc */ public function getSize(): ?int { - return $this->data['size'] ?? null; + return $this->data[static::PROPERTY_SIZE] ?? null; } /** * @inheritDoc */ - public function getSender(): ?AddressInterface { - return $this->data['sender'] ?? null; + public function getHeaders(): array { + return $this->data[static::PROPERTY_HEADERS] ?? []; } /** * @inheritDoc */ - public function getFrom(): ?AddressInterface { - return $this->data['from'] ?? null; + public function getHeader(string $name): string|array|null { + return $this->data[static::PROPERTY_HEADERS][$name] ?? null; } /** * @inheritDoc */ - public function getReplyTo(): array { - return $this->data['replyTo'] ?? []; - } - - /** - * @inheritDoc - */ - public function getTo(): array { - return $this->data['to'] ?? []; - } - - /** - * @inheritDoc - */ - public function getCc(): array { - return $this->data['cc'] ?? []; - } - - /** - * @inheritDoc - */ - public function getBcc(): array { - return $this->data['bcc'] ?? []; + public function getUrid(): ?string { + return $this->data[static::PROPERTY_URID] ?? null; } /** * @inheritDoc */ public function getInReplyTo(): ?string { - return $this->data['inReplyTo'] ?? null; + return $this->data[static::PROPERTY_IN_REPLY_TO] ?? null; } /** * @inheritDoc */ public function getReferences(): array { - return $this->data['references'] ?? []; + return $this->data[static::PROPERTY_REFERENCES] ?? []; + } + + /** + * @inheritDoc + */ + public function getReceived(): ?DateTimeImmutable { + return $this->data[static::PROPERTY_RECEIVED] ?? null; + } + + /** + * @inheritDoc + */ + public function getSent(): ?DateTimeImmutable { + return $this->data[static::PROPERTY_SENT] ?? null; + } + + /** + * @inheritDoc + */ + public function getSender(): ?AddressInterface { + return $this->data[static::PROPERTY_SENDER] ?? null; + } + + /** + * @inheritDoc + */ + public function getFrom(): ?AddressInterface { + return $this->data[static::PROPERTY_FROM] ?? null; + } + + /** + * @inheritDoc + */ + public function getReplyTo(): array { + return $this->data[static::PROPERTY_REPLY_TO] ?? []; + } + + /** + * @inheritDoc + */ + public function getTo(): array { + return $this->data[static::PROPERTY_TO] ?? []; + } + + /** + * @inheritDoc + */ + public function getCc(): array { + return $this->data[static::PROPERTY_CC] ?? []; + } + + /** + * @inheritDoc + */ + public function getBcc(): array { + return $this->data[static::PROPERTY_BCC] ?? []; } /** * @inheritDoc */ public function getSubject(): string { - return $this->data['subject'] ?? ''; + return $this->data[static::PROPERTY_SUBJECT] ?? ''; } /** * @inheritDoc */ - public function getSnippet(): ?string { - return $this->data['snippet'] ?? null; + public function getBody(): ?MessagePartInterface { + return $this->data[static::PROPERTY_BODY] ?? null; } /** * @inheritDoc */ - public function getBodyText(): ?string { - return $this->data['bodyText'] ?? null; + public function hasBody(): bool { + return ($this->data[static::PROPERTY_BODY_TEXT_PLAIN] !== null && $this->data[static::PROPERTY_BODY_TEXT_PLAIN] !== '') + || ($this->data[static::PROPERTY_BODY_TEXT_HTML] !== null && $this->data[static::PROPERTY_BODY_TEXT_HTML] !== ''); } /** * @inheritDoc */ - public function getBodyTextCharset(): ?string { - return $this->data['bodyTextCharset'] ?? null; + public function getBodyTextPlain(): ?string { + return $this->data[static::PROPERTY_BODY_TEXT_PLAIN] ?? null; } /** * @inheritDoc */ - public function getBodyTextSize(): ?int { - return $this->data['bodyTextSize'] ?? null; - } - - /** - * @inheritDoc - */ - public function getBodyHtml(): ?string { - return $this->data['bodyHtml'] ?? null; - } - - /** - * @inheritDoc - */ - public function getBodyHtmlCharset(): ?string { - return $this->data['bodyHtmlCharset'] ?? null; - } - - /** - * @inheritDoc - */ - public function getBodyHtmlSize(): ?int { - return $this->data['bodyHtmlSize'] ?? null; + public function getBodyTextHtml(): ?string { + return $this->data[static::PROPERTY_BODY_TEXT_HTML] ?? null; } /** * @inheritDoc */ public function getAttachments(): array { - return $this->data['attachments'] ?? []; + return $this->data[static::PROPERTY_ATTACHMENTS] ?? []; } /** * @inheritDoc */ public function getFlags(): array { - return $this->data['flags'] ?? [ + return $this->data[static::PROPERTY_FLAGS] ?? [ 'read' => false, 'starred' => false, 'important' => false, @@ -218,179 +191,7 @@ abstract class MessagePropertiesBaseAbstract extends NodePropertiesBaseAbstract * @inheritDoc */ public function getFlag(string $name): bool { - return $this->data['flags'][$name] ?? false; + return $this->data[static::PROPERTY_FLAGS][$name] ?? false; } - /** - * Gets message labels - * - * @since 2025.05.01 - * - * @return array - */ - public function getLabels(): array { - return $this->data['labels'] ?? []; - } - - /** - * Gets message tags - * - * @since 2025.05.01 - * - * @return array - */ - public function getTags(): array { - return $this->data['tags'] ?? []; - } - - /** - * Gets message priority - * - * @since 2025.05.01 - * - * @return string - */ - public function getPriority(): string { - return $this->data['priority'] ?? 'normal'; - } - - /** - * Gets message sensitivity - * - * @since 2025.05.01 - * - * @return string - */ - public function getSensitivity(): string { - return $this->data['sensitivity'] ?? 'normal'; - } - - /** - * Gets encryption information - * - * @since 2025.05.01 - * - * @return array{method: string|null, signed: bool, encrypted: bool} - */ - public function getEncryption(): array { - return $this->data['encryption'] ?? [ - 'method' => null, - 'signed' => false, - 'encrypted' => false, - ]; - } - - /** - * Checks if delivery receipt is requested - * - * @since 2025.05.01 - * - * @return bool - */ - public function isDeliveryReceipt(): bool { - return $this->data['deliveryReceipt'] ?? false; - } - - /** - * Checks if read receipt is requested - * - * @since 2025.05.01 - * - * @return bool - */ - public function isReadReceipt(): bool { - return $this->data['readReceipt'] ?? false; - } - - /** - * @inheritDoc - */ - public function hasRecipients(): bool { - return !empty($this->data['to']) || !empty($this->data['cc']) || !empty($this->data['bcc']); - } - - /** - * @inheritDoc - */ - public function hasBody(): bool { - return ($this->data['bodyText'] !== null && $this->data['bodyText'] !== '') - || ($this->data['bodyHtml'] !== null && $this->data['bodyHtml'] !== ''); - } - - /** - * @inheritDoc - */ - public function getBody(): ?MessagePartInterface { - return $this->data['body'] ?? null; - } - - /** - * @inheritDoc - */ - public function jsonSerialize(): array { - $data = [ - self::JSON_PROPERTY_TYPE => self::JSON_TYPE, - self::JSON_PROPERTY_SCHEMA => $this->data['schema'] ?? 1, - ]; - - if (!empty($this->data['headers'])) { - $data[self::JSON_PROPERTY_HEADERS] = $this->data['headers']; - } - if (isset($this->data['urid']) && $this->data['urid'] !== null) { - $data[self::JSON_PROPERTY_URID] = $this->data['urid']; - } - if (isset($this->data['date']) && $this->data['date'] !== null) { - $data[self::JSON_PROPERTY_DATE] = $this->data['date'] instanceof DateTimeImmutable - ? $this->data['date']->format('c') - : $this->data['date']; - } - if (isset($this->data['received']) && $this->data['received'] !== null) { - $data[self::JSON_PROPERTY_RECEIVED] = $this->data['received'] instanceof DateTimeImmutable - ? $this->data['received']->format('c') - : $this->data['received']; - } - if (isset($this->data['size']) && $this->data['size'] !== null) { - $data[self::JSON_PROPERTY_SIZE] = $this->data['size']; - } - if (isset($this->data['sender']) && $this->data['sender'] !== null) { - $data[self::JSON_PROPERTY_SENDER] = $this->data['sender']; - } - if (isset($this->data['from']) && $this->data['from'] !== null) { - $data[self::JSON_PROPERTY_FROM] = $this->data['from']; - } - if (!empty($this->data['replyTo'])) { - $data[self::JSON_PROPERTY_REPLY_TO] = $this->data['replyTo']; - } - if (!empty($this->data['to'])) { - $data[self::JSON_PROPERTY_TO] = $this->data['to']; - } - if (!empty($this->data['cc'])) { - $data[self::JSON_PROPERTY_CC] = $this->data['cc']; - } - if (!empty($this->data['bcc'])) { - $data[self::JSON_PROPERTY_BCC] = $this->data['bcc']; - } - if (isset($this->data['inReplyTo']) && $this->data['inReplyTo'] !== null) { - $data[self::JSON_PROPERTY_IN_REPLY_TO] = $this->data['inReplyTo']; - } - if (!empty($this->data['references'])) { - $data[self::JSON_PROPERTY_REFERENCES] = $this->data['references']; - } - - if (isset($this->data['snippet']) && $this->data['snippet'] !== null) { - $data[self::JSON_PROPERTY_SNIPPET] = $this->data['snippet']; - } - - if (!empty($this->data['attachments'])) { - $data[self::JSON_PROPERTY_ATTACHMENTS] = $this->data['attachments']; - } - if (!empty($this->data['flags'])) { - $data[self::JSON_PROPERTY_FLAGS] = $this->data['flags']; - } - - $data[self::JSON_PROPERTY_SUBJECT] = $this->data['subject'] ?? null; - $data[self::JSON_PROPERTY_BODY] = $this->data['body'] ?? null; - - return $data; - } } diff --git a/shared/lib/Mail/Object/MessagePropertiesBaseInterface.php b/shared/lib/Mail/Object/MessagePropertiesBaseInterface.php index b3c92ef..6436c46 100644 --- a/shared/lib/Mail/Object/MessagePropertiesBaseInterface.php +++ b/shared/lib/Mail/Object/MessagePropertiesBaseInterface.php @@ -19,26 +19,35 @@ use KTXF\Resource\Provider\Node\NodePropertiesBaseInterface; */ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface { - public const JSON_TYPE = 'mail.message'; - public const JSON_PROPERTY_HEADERS = 'headers'; - public const JSON_PROPERTY_URID = 'urid'; - public const JSON_PROPERTY_DATE = 'date'; - public const JSON_PROPERTY_RECEIVED = 'received'; - public const JSON_PROPERTY_SIZE = 'size'; - public const JSON_PROPERTY_SENDER = 'sender'; - public const JSON_PROPERTY_FROM = 'from'; - public const JSON_PROPERTY_REPLY_TO = 'replyTo'; - public const JSON_PROPERTY_TO = 'to'; - public const JSON_PROPERTY_CC = 'cc'; - public const JSON_PROPERTY_BCC = 'bcc'; - public const JSON_PROPERTY_IN_REPLY_TO = 'inReplyTo'; - public const JSON_PROPERTY_REFERENCES = 'references'; - public const JSON_PROPERTY_SUBJECT = 'subject'; - public const JSON_PROPERTY_SNIPPET = 'snippet'; - public const JSON_PROPERTY_BODY = 'body'; - public const JSON_PROPERTY_ATTACHMENTS = 'attachments'; - public const JSON_PROPERTY_FLAGS = 'flags'; - public const JSON_PROPERTY_TAGS = 'tags'; + public const PROPERTY_SIZE = 'size'; + public const PROPERTY_HEADERS = 'headers'; + public const PROPERTY_URID = 'urid'; // mime message ID or similar unique identifier + public const PROPERTY_IN_REPLY_TO = 'inReplyTo'; + public const PROPERTY_REFERENCES = 'references'; + public const PROPERTY_RECEIVED = 'received'; + public const PROPERTY_SENT = 'sent'; + public const PROPERTY_SENDER = 'sender'; + public const PROPERTY_REPLY_TO = 'replyTo'; + public const PROPERTY_FROM = 'from'; + public const PROPERTY_TO = 'to'; + public const PROPERTY_CC = 'cc'; + public const PROPERTY_BCC = 'bcc'; + public const PROPERTY_SUBJECT = 'subject'; + public const PROPERTY_BODY = 'body'; + public const PROPERTY_BODY_TEXT_PLAIN = 'bodyTextPlain'; + public const PROPERTY_BODY_TEXT_HTML = 'bodyTextHtml'; + public const PROPERTY_ATTACHMENTS = 'attachments'; + public const PROPERTY_FLAGS = 'flags'; + public const PROPERTY_TAGS = 'tags'; + + /** + * Gets the message size in bytes + * + * @since 2025.05.01 + * + * @return int|null + */ + public function getSize(): ?int; /** * Gets custom headers @@ -70,13 +79,22 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface { public function getUrid(): ?string; /** - * Gets the message date + * Gets the message ID this is replying to * * @since 2025.05.01 * - * @return DateTimeImmutable|null + * @return string|null */ - public function getDate(): ?DateTimeImmutable; + public function getInReplyTo(): ?string; + + /** + * Gets the references (message IDs in thread) + * + * @since 2025.05.01 + * + * @return array + */ + public function getReferences(): array; /** * Gets the received date @@ -88,13 +106,13 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface { public function getReceived(): ?DateTimeImmutable; /** - * Gets the message size in bytes + * Gets the sent date * * @since 2025.05.01 * - * @return int|null + * @return DateTimeImmutable|null */ - public function getSize(): ?int; + public function getSent(): ?DateTimeImmutable; /** * Gets the sender address (actual sender, may differ from From) @@ -149,24 +167,6 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface { */ public function getBcc(): array; - /** - * Gets the message ID this is replying to - * - * @since 2025.05.01 - * - * @return string|null - */ - public function getInReplyTo(): ?string; - - /** - * Gets the references (message IDs in thread) - * - * @since 2025.05.01 - * - * @return array - */ - public function getReferences(): array; - /** * Gets the message subject * @@ -176,24 +176,6 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface { */ public function getSubject(): string; - /** - * Gets the message snippet/preview - * - * @since 2025.05.01 - * - * @return string|null - */ - public function getSnippet(): ?string; - - /** - * Checks if the message has any body content - * - * @since 2025.05.01 - * - * @return bool True if text or HTML body is set - */ - public function hasBody(): bool; - /** * Gets the message body structure * @@ -203,6 +185,15 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface { */ public function getBody(): ?MessagePartInterface; + /** + * Checks if the message has any body content + * + * @since 2025.05.01 + * + * @return bool True if text or HTML body is set + */ + public function hasBody(): bool; + /** * Gets the plain text body content * @@ -210,7 +201,7 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface { * * @return string|null */ - public function getBodyText(): ?string; + public function getBodyTextPlain(): ?string; /** * Gets the HTML body content @@ -219,7 +210,7 @@ interface MessagePropertiesBaseInterface extends NodePropertiesBaseInterface { * * @return string|null */ - public function getBodyHtml(): ?string; + public function getBodyTextHtml(): ?string; /** * Gets the attachments diff --git a/shared/lib/Mail/Object/MessagePropertiesMutableAbstract.php b/shared/lib/Mail/Object/MessagePropertiesMutableAbstract.php index 5c13540..62a79d6 100644 --- a/shared/lib/Mail/Object/MessagePropertiesMutableAbstract.php +++ b/shared/lib/Mail/Object/MessagePropertiesMutableAbstract.php @@ -19,422 +19,9 @@ use DateTimeImmutable; * @since 2025.05.01 */ abstract class MessagePropertiesMutableAbstract extends MessagePropertiesBaseAbstract implements MessagePropertiesMutableInterface { - - public const JSON_TYPE = MessagePropertiesBaseInterface::JSON_TYPE; - /** - * @inheritDoc - */ - public function setHeaders(array $value): static { - $this->data['headers'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setHeader(string $name, string|array $value): static { - $this->data['headers'][$name] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setUrid(?string $value): static { - $this->data['urid'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setCreated(DateTimeImmutable $value): static { - $this->data['created'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setModified(DateTimeImmutable $value): static { - $this->data['modified'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setDate(DateTimeImmutable $value): static { - $this->data['date'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setReceived(?DateTimeImmutable $value): static { - $this->data['received'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setSize(?int $value): static { - $this->data['size'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setSender(?AddressInterface $value): static { - $this->data['sender'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setFrom(AddressInterface $value): static { - $this->data['from'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setReplyTo(AddressInterface ...$value): static { - $this->data['replyTo'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setTo(AddressInterface ...$value): static { - $this->data['to'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setCc(AddressInterface ...$value): static { - $this->data['cc'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setBcc(AddressInterface ...$value): static { - $this->data['bcc'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setInReplyTo(?string $value): static { - $this->data['inReplyTo'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setReferences(string ...$value): static { - $this->data['references'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setSubject(string $value): static { - $this->data['subject'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setSnippet(?string $value): static { - $this->data['snippet'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setBodyText(?string $value): static { - $this->data['bodyText'] = $value; - return $this; - } - - /** - * Sets the plain text body charset - * - * @since 2025.05.01 - * - * @param string $value - * - * @return static - */ - public function setBodyTextCharset(string $value): static { - $this->data['bodyTextCharset'] = $value; - return $this; - } - - /** - * Sets the plain text body size - * - * @since 2025.05.01 - * - * @param int $value - * - * @return static - */ - public function setBodyTextSize(int $value): static { - $this->data['bodyTextSize'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setBodyHtml(?string $value): static { - $this->data['bodyHtml'] = $value; - return $this; - } - - /** - * Sets the HTML body charset - * - * @since 2025.05.01 - * - * @param string $value - * - * @return static - */ - public function setBodyHtmlCharset(string $value): static { - $this->data['bodyHtmlCharset'] = $value; - return $this; - } - - /** - * Sets the HTML body size - * - * @since 2025.05.01 - * - * @param int $value - * - * @return static - */ - public function setBodyHtmlSize(int $value): static { - $this->data['bodyHtmlSize'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function setAttachments(AttachmentInterface ...$value): static { - $this->data['attachments'] = $value; - return $this; - } - - /** - * @inheritDoc - */ - public function addAttachment(AttachmentInterface $value): static { - $this->data['attachments'][] = $value; - return $this; - } - - /** - * Sets message flags - * - * @since 2025.05.01 - * - * @param array $value - * - * @return static - */ - public function setFlags(array $value): static { - if (!isset($this->data['flags'])) { - $this->data['flags'] = [ - 'read' => false, - 'starred' => false, - 'important' => false, - 'answered' => false, - 'forwarded' => false, - 'draft' => false, - 'deleted' => false, - 'flagged' => false, - ]; - } - $this->data['flags'] = array_merge($this->data['flags'], $value); - return $this; - } - - /** - * @inheritDoc - */ - public function setFlag(string $name, bool $value): static { - if (!isset($this->data['flags'])) { - $this->data['flags'] = [ - 'read' => false, - 'starred' => false, - 'important' => false, - 'answered' => false, - 'forwarded' => false, - 'draft' => false, - 'deleted' => false, - 'flagged' => false, - ]; - } - if (array_key_exists($name, $this->data['flags'])) { - $this->data['flags'][$name] = $value; - } - return $this; - } - - /** - * Sets message labels - * - * @since 2025.05.01 - * - * @param string ...$value - * - * @return static - */ - public function setLabels(string ...$value): static { - $this->data['labels'] = $value; - return $this; - } - - /** - * Adds a message label - * - * @since 2025.05.01 - * - * @param string $value - * - * @return static - */ - public function addLabel(string $value): static { - $this->data['labels'][] = $value; - return $this; - } - - /** - * Sets message tags - * - * @since 2025.05.01 - * - * @param string ...$value - * - * @return static - */ - public function setTags(string ...$value): static { - $this->data['tags'] = $value; - return $this; - } - - /** - * Adds a message tag - * - * @since 2025.05.01 - * - * @param string $value - * - * @return static - */ - public function addTag(string $value): static { - $this->data['tags'][] = $value; - return $this; - } - - /** - * Sets message priority - * - * @since 2025.05.01 - * - * @param string $value - * - * @return static - */ - public function setPriority(string $value): static { - $this->data['priority'] = $value; - return $this; - } - - /** - * Sets message sensitivity - * - * @since 2025.05.01 - * - * @param string $value - * - * @return static - */ - public function setSensitivity(string $value): static { - $this->data['sensitivity'] = $value; - return $this; - } - - /** - * Sets encryption information - * - * @since 2025.05.01 - * - * @param array $value - * - * @return static - */ - public function setEncryption(array $value): static { - if (!isset($this->data['encryption'])) { - $this->data['encryption'] = [ - 'method' => null, - 'signed' => false, - 'encrypted' => false, - ]; - } - $this->data['encryption'] = array_merge($this->data['encryption'], $value); - return $this; - } - - /** - * Sets delivery receipt flag - * - * @since 2025.05.01 - * - * @param bool $value - * - * @return static - */ - public function setDeliveryReceipt(bool $value): static { - $this->data['deliveryReceipt'] = $value; - return $this; - } - - /** - * Sets read receipt flag - * - * @since 2025.05.01 - * - * @param bool $value - * - * @return static - */ - public function setReadReceipt(bool $value): static { - $this->data['readReceipt'] = $value; - return $this; - } - + protected string $type = 'mail.message'; + /** * @inheritDoc */ @@ -452,4 +39,213 @@ abstract class MessagePropertiesMutableAbstract extends MessagePropertiesBaseAbs return $this; } + + /** + * @inheritDoc + */ + public function setSize(?int $value): static { + $this->data[static::PROPERTY_SIZE] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setHeaders(array $value): static { + $this->data[static::PROPERTY_HEADERS] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setHeader(string $name, string|array $value): static { + $this->data[static::PROPERTY_HEADERS][$name] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setUrid(?string $value): static { + $this->data[static::PROPERTY_URID] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setInReplyTo(?string $value): static { + $this->data[static::PROPERTY_IN_REPLY_TO] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setReferences(string ...$value): static { + $this->data[static::PROPERTY_REFERENCES] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setReceived(?DateTimeImmutable $value): static { + $this->data[static::PROPERTY_RECEIVED] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setSent(DateTimeImmutable $value): static { + $this->data[static::PROPERTY_SENT] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setSender(?AddressInterface $value): static { + $this->data[static::PROPERTY_SENDER] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setFrom(AddressInterface $value): static { + $this->data[static::PROPERTY_FROM] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setReplyTo(AddressInterface ...$value): static { + $this->data[static::PROPERTY_REPLY_TO] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setTo(AddressInterface ...$value): static { + $this->data[static::PROPERTY_TO] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setCc(AddressInterface ...$value): static { + $this->data[static::PROPERTY_CC] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setBcc(AddressInterface ...$value): static { + $this->data[static::PROPERTY_BCC] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setSubject(string $value): static { + $this->data[static::PROPERTY_SUBJECT] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setBody(?MessagePartInterface $value): static { + $this->data[static::PROPERTY_BODY] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setBodyTextPlain(?string $value): static { + $this->data[static::PROPERTY_BODY_TEXT_PLAIN] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setBodyTextHtml(?string $value): static { + $this->data[static::PROPERTY_BODY_TEXT_HTML] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setAttachments(AttachmentInterface ...$value): static { + $this->data[static::PROPERTY_ATTACHMENTS] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function addAttachment(AttachmentInterface $value): static { + $this->data[static::PROPERTY_ATTACHMENTS][] = $value; + return $this; + } + + /** + * Sets message flags + * + * @since 2025.05.01 + * + * @param array $value + * + * @return static + */ + public function setFlags(array $value): static { + if (!isset($this->data[static::PROPERTY_FLAGS])) { + $this->data[static::PROPERTY_FLAGS] = [ + 'read' => false, + 'starred' => false, + 'important' => false, + 'answered' => false, + 'forwarded' => false, + 'draft' => false, + 'deleted' => false, + 'flagged' => false, + ]; + } + $this->data[static::PROPERTY_FLAGS] = array_merge($this->data[static::PROPERTY_FLAGS], $value); + return $this; + } + + /** + * @inheritDoc + */ + public function setFlag(string $name, bool $value): static { + if (!isset($this->data[static::PROPERTY_FLAGS])) { + $this->data[static::PROPERTY_FLAGS] = [ + 'read' => false, + 'starred' => false, + 'important' => false, + 'answered' => false, + 'forwarded' => false, + 'draft' => false, + 'deleted' => false, + 'flagged' => false, + ]; + } + if (array_key_exists($name, $this->data[static::PROPERTY_FLAGS])) { + $this->data[static::PROPERTY_FLAGS][$name] = $value; + } + return $this; + } + } diff --git a/shared/lib/Mail/Object/MessagePropertiesMutableInterface.php b/shared/lib/Mail/Object/MessagePropertiesMutableInterface.php index 831bb63..4e880ce 100644 --- a/shared/lib/Mail/Object/MessagePropertiesMutableInterface.php +++ b/shared/lib/Mail/Object/MessagePropertiesMutableInterface.php @@ -18,9 +18,18 @@ use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; * @since 2025.05.01 */ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterface, NodePropertiesMutableInterface { - - public const JSON_TYPE = MessagePropertiesBaseInterface::JSON_TYPE; + /** + * Sets the message size in bytes + * + * @since 2025.05.01 + * + * @param int|null $value + * + * @return self + */ + public function setSize(?int $value): static; + /** * Sets custom headers * @@ -56,15 +65,26 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa public function setUrid(?string $value): static; /** - * Sets the message date + * Sets the message ID this is replying to * * @since 2025.05.01 * - * @param DateTimeImmutable $value + * @param string|null $value * * @return self */ - public function setDate(DateTimeImmutable $value): static; + public function setInReplyTo(?string $value): static; + + /** + * Sets the references (message IDs in thread) + * + * @since 2025.05.01 + * + * @param string ...$value + * + * @return self + */ + public function setReferences(string ...$value): static; /** * Sets the received date @@ -77,16 +97,16 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa */ public function setReceived(?DateTimeImmutable $value): static; - /** - * Sets the message size in bytes + /** + * Sets the message date * * @since 2025.05.01 * - * @param int|null $value + * @param DateTimeImmutable $value * * @return self */ - public function setSize(?int $value): static; + public function setSent(DateTimeImmutable $value): static; /** * Sets the sender address (actual sender, may differ from From) @@ -154,28 +174,6 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa */ public function setBcc(AddressInterface ...$value): static; - /** - * Sets the message ID this is replying to - * - * @since 2025.05.01 - * - * @param string|null $value - * - * @return self - */ - public function setInReplyTo(?string $value): static; - - /** - * Sets the references (message IDs in thread) - * - * @since 2025.05.01 - * - * @param string ...$value - * - * @return self - */ - public function setReferences(string ...$value): static; - /** * Sets the message subject * @@ -188,15 +186,15 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa public function setSubject(string $value): static; /** - * Sets the message snippet/preview + * Sets the message body * * @since 2025.05.01 * - * @param string|null $value + * @param MessagePartInterface|null $value * * @return self */ - public function setSnippet(?string $value): static; + public function setBody(?MessagePartInterface $value): static; /** * Sets the plain text body content @@ -207,7 +205,7 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa * * @return self */ - public function setBodyText(?string $value): static; + public function setBodyTextPlain(?string $value): static; /** * Sets the HTML body content @@ -218,7 +216,7 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa * * @return self */ - public function setBodyHtml(?string $value): static; + public function setBodyTextHtml(?string $value): static; /** * Sets the attachments @@ -241,15 +239,28 @@ interface MessagePropertiesMutableInterface extends MessagePropertiesBaseInterfa * @return self */ public function addAttachment(AttachmentInterface $value): static; + /** - * Sets message tags + * Sets message flags * * @since 2025.05.01 * - * @param array{read: bool, starred: bool, important: bool, answered: bool, forwarded: bool, draft: bool, deleted: bool, flagged: bool} $value + * @param array $value * * @return self */ + public function setFlags(array $value): static; + + /** + * Sets message flags + * + * @since 2025.05.01 + * + * @param string $label + * @param bool $value + * + * @return self + */ public function setFlag(string $label, bool $value): static; } diff --git a/shared/lib/Mail/Provider/ProviderServiceDiscoverInterface.php b/shared/lib/Mail/Provider/ProviderServiceDiscoverInterface.php index 603f5ed..82f6adc 100644 --- a/shared/lib/Mail/Provider/ProviderServiceDiscoverInterface.php +++ b/shared/lib/Mail/Provider/ProviderServiceDiscoverInterface.php @@ -26,7 +26,7 @@ use KTXF\Resource\Provider\ResourceServiceLocationInterface; * * @since 2025.05.01 */ -interface ProviderServiceDiscoverInterface extends ProviderBaseInterface { +interface ProviderServiceDiscoverInterface { /** * Attempts to discover service configuration using provider-specific methods. diff --git a/shared/lib/Mail/Provider/ProviderServiceMutateInterface.php b/shared/lib/Mail/Provider/ProviderServiceMutateInterface.php index 7bf5e92..ac0c426 100644 --- a/shared/lib/Mail/Provider/ProviderServiceMutateInterface.php +++ b/shared/lib/Mail/Provider/ProviderServiceMutateInterface.php @@ -25,9 +25,7 @@ use KTXF\Resource\Provider\ResourceProviderServiceMutateInterface; * @method string serviceModify(string $tenantId, ?string $userId, ServiceMutableInterface $service) Modify a mail service configuration * @method bool serviceDestroy(string $tenantId, ?string $userId, ServiceMutableInterface $service) Delete a mail service configuration */ -interface ProviderServiceMutateInterface extends ProviderBaseInterface, ResourceProviderServiceMutateInterface { - - public const JSON_TYPE = ProviderBaseInterface::JSON_TYPE; +interface ProviderServiceMutateInterface extends ResourceProviderServiceMutateInterface { // Methods inherited from ResourceProviderServiceMutateInterface // Implementations should return/accept ServiceMutableInterface instances diff --git a/shared/lib/Mail/Provider/ProviderServiceTestInterface.php b/shared/lib/Mail/Provider/ProviderServiceTestInterface.php index 82196b9..72ee119 100644 --- a/shared/lib/Mail/Provider/ProviderServiceTestInterface.php +++ b/shared/lib/Mail/Provider/ProviderServiceTestInterface.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace KTXF\Mail\Provider; use KTXF\Mail\Service\ServiceBaseInterface; +use KTXF\Mail\Service\ServiceMutableInterface; /** * Mail Provider Service Test Interface @@ -25,7 +26,7 @@ use KTXF\Mail\Service\ServiceBaseInterface; * * @since 2025.05.01 */ -interface ProviderServiceTestInterface extends ProviderBaseInterface { +interface ProviderServiceTestInterface { /** * Test a service connection @@ -39,7 +40,7 @@ interface ProviderServiceTestInterface extends ProviderBaseInterface { * * @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) @@ -72,6 +73,6 @@ interface ProviderServiceTestInterface extends ProviderBaseInterface { * ] * ] */ - public function serviceTest(ServiceBaseInterface $service, array $options = []): array; + public function serviceTest(ServiceBaseInterface|ServiceMutableInterface $service, array $options = []): array; } diff --git a/shared/lib/Mail/Service/ServiceCollectionMutableInterface.php b/shared/lib/Mail/Service/ServiceCollectionMutableInterface.php index 1eb16dc..f17b45c 100644 --- a/shared/lib/Mail/Service/ServiceCollectionMutableInterface.php +++ b/shared/lib/Mail/Service/ServiceCollectionMutableInterface.php @@ -11,6 +11,8 @@ namespace KTXF\Mail\Service; use KTXF\Mail\Collection\CollectionBaseInterface; use KTXF\Mail\Collection\CollectionMutableInterface; +use KTXF\Mail\Collection\CollectionPropertiesBaseInterface; +use KTXF\Resource\Identifier\CollectionIdentifier; /** * Mail Service Collection Mutable Interface @@ -41,48 +43,48 @@ interface ServiceCollectionMutableInterface { * * @since 2025.05.01 * - * @param string|int|null $location Parent collection ID (null for root) - * @param CollectionMutableInterface $collection Collection to create + * @param CollectionIdentifier $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(CollectionIdentifier|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 CollectionIdentifier $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(CollectionIdentifier $target, CollectionPropertiesBaseInterface $properties): CollectionBaseInterface; /** * Deletes a collection * * @since 2025.05.01 * - * @param string|int $identifier Collection ID + * @param CollectionIdentifier $target Target collection identifier * @param bool $force Force deletion even if not empty * * @return CollectionBaseInterface|true Collection object on soft delete, true on hard delete */ - public function collectionDelete(string|int $identifier, bool $force = false): CollectionBaseInterface | true; + public function collectionDelete(CollectionIdentifier $target, bool $force = false): CollectionBaseInterface | true; /** * 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) + * @param CollectionIdentifier $source Source collection identifier + * @param CollectionIdentifier $target Target collection identifier * * @return CollectionBaseInterface Moved collection */ - public function collectionMove(string|int $identifier, string|int|null $targetLocation): CollectionBaseInterface; + public function collectionMove(CollectionIdentifier $target, CollectionIdentifier $source): CollectionBaseInterface; } diff --git a/shared/lib/Resource/Provider/Node/NodeBaseAbstract.php b/shared/lib/Resource/Provider/Node/NodeBaseAbstract.php index d6460da..9c8fb74 100644 --- a/shared/lib/Resource/Provider/Node/NodeBaseAbstract.php +++ b/shared/lib/Resource/Provider/Node/NodeBaseAbstract.php @@ -10,6 +10,11 @@ declare(strict_types=1); namespace KTXF\Resource\Provider\Node; use DateTimeImmutable; +use KTXF\Resource\Identifier\CollectionIdentifier; +use KTXF\Resource\Identifier\CollectionIdentifierInterface; +use KTXF\Resource\Identifier\EntityIdentifierInterface; +use KTXF\Resource\Identifier\ResourceIdentifier; +use KTXF\Resource\Identifier\ServiceIdentifier; /** * Abstract Node Base Class @@ -23,6 +28,7 @@ abstract class NodeBaseAbstract implements NodeBaseInterface { /** * Internal data storage */ + protected string $type = 'resource.node'; protected array $data = []; public function __construct( @@ -30,87 +36,96 @@ abstract class NodeBaseAbstract implements NodeBaseInterface { protected readonly string|int $service, ) { $this->data = [ - static::JSON_PROPERTY_PROVIDER => $this->provider, - static::JSON_PROPERTY_SERVICE => $this->service, - static::JSON_PROPERTY_COLLECTION => null, - static::JSON_PROPERTY_IDENTIFIER => null, - static::JSON_PROPERTY_SIGNATURE => null, - static::JSON_PROPERTY_CREATED => null, - static::JSON_PROPERTY_MODIFIED => null, + static::PROPERTY_TYPE => $this->type, + static::PROPERTY_PROVIDER => $this->provider, + static::PROPERTY_SERVICE => $this->service, + static::PROPERTY_COLLECTION => null, + static::PROPERTY_IDENTIFIER => null, + static::PROPERTY_SIGNATURE => null, + static::PROPERTY_CREATED => null, + static::PROPERTY_MODIFIED => null, ]; } - /** - * @inheritDoc - */ - public function type(): string { - return static::RESOURCE_TYPE; - } - - /** - * @inheritDoc - */ - public function provider(): string { - return $this->data[static::JSON_PROPERTY_PROVIDER]; - } - - /** - * @inheritDoc - */ - public function service(): string|int { - return $this->data[static::JSON_PROPERTY_SERVICE]; - } - - /** - * @inheritDoc - */ - public function collection(): string|int|null { - return $this->data[static::JSON_PROPERTY_COLLECTION] ?? null; - } - - /** - * @inheritDoc - */ - public function identifier(): string|int|null { - return $this->data[static::JSON_PROPERTY_IDENTIFIER] ?? null; - } - - /** - * @inheritDoc - */ - public function signature(): string|null { - return isset($this->data[static::JSON_PROPERTY_SIGNATURE]) - ? (string)$this->data[static::JSON_PROPERTY_SIGNATURE] - : null; - } - - /** - * @inheritDoc - */ - public function created(): DateTimeImmutable|null { - return isset($this->data[static::JSON_PROPERTY_CREATED]) - ? new DateTimeImmutable($this->data[static::JSON_PROPERTY_CREATED]) - : null; - } - - /** - * @inheritDoc - */ - public function modified(): DateTimeImmutable|null { - return isset($this->data[static::JSON_PROPERTY_MODIFIED]) - ? new DateTimeImmutable($this->data[static::JSON_PROPERTY_MODIFIED]) - : null; - } - /** * @inheritDoc */ public function jsonSerialize(): array { $data = $this->data; - $data[static::JSON_PROPERTY_PROPERTIES] = $this->getProperties()->jsonSerialize(); + $data['provider'] = new ResourceIdentifier($this->data[static::PROPERTY_PROVIDER]); + $data['service'] = new ServiceIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE]); + $data['collection'] = isset($this->data[static::PROPERTY_COLLECTION]) + ? new CollectionIdentifier($this->data[static::PROPERTY_PROVIDER], $this->data[static::PROPERTY_SERVICE], $this->data[static::PROPERTY_COLLECTION]) + : null; + $data['identifier'] = $this->nodeIdentifier(); + $data[static::PROPERTY_PROPERTIES] = $this->getProperties()->jsonSerialize(); return $data; } + abstract protected function nodeIdentifier(): CollectionIdentifierInterface|EntityIdentifierInterface|null; + + /** + * @inheritDoc + */ + public function type(): string { + return $this->data[static::PROPERTY_TYPE]; + } + + /** + * @inheritDoc + */ + public function provider(): string { + return $this->data[static::PROPERTY_PROVIDER]; + } + + /** + * @inheritDoc + */ + public function service(): string|int { + return $this->data[static::PROPERTY_SERVICE]; + } + + /** + * @inheritDoc + */ + public function collection(): string|int|null { + return $this->data[static::PROPERTY_COLLECTION] ?? null; + } + + /** + * @inheritDoc + */ + public function identifier(): string|int|null { + return $this->data[static::PROPERTY_IDENTIFIER] ?? null; + } + + /** + * @inheritDoc + */ + public function signature(): string|null { + return isset($this->data[static::PROPERTY_SIGNATURE]) + ? (string)$this->data[static::PROPERTY_SIGNATURE] + : null; + } + + /** + * @inheritDoc + */ + public function created(): DateTimeImmutable|null { + return isset($this->data[static::PROPERTY_CREATED]) + ? new DateTimeImmutable($this->data[static::PROPERTY_CREATED]) + : null; + } + + /** + * @inheritDoc + */ + public function modified(): DateTimeImmutable|null { + return isset($this->data[static::PROPERTY_MODIFIED]) + ? new DateTimeImmutable($this->data[static::PROPERTY_MODIFIED]) + : null; + } + /** * @inheritDoc */ diff --git a/shared/lib/Resource/Provider/Node/NodeBaseInterface.php b/shared/lib/Resource/Provider/Node/NodeBaseInterface.php index 6137d60..fee2e11 100644 --- a/shared/lib/Resource/Provider/Node/NodeBaseInterface.php +++ b/shared/lib/Resource/Provider/Node/NodeBaseInterface.php @@ -19,15 +19,15 @@ use KTXF\Json\JsonSerializable; */ interface NodeBaseInterface extends JsonSerializable { - public const RESOURCE_TYPE = 'resource.node'; - public const JSON_PROPERTY_PROVIDER = 'provider'; - public const JSON_PROPERTY_SERVICE = 'service'; - public const JSON_PROPERTY_COLLECTION = 'collection'; - public const JSON_PROPERTY_IDENTIFIER = 'identifier'; - public const JSON_PROPERTY_SIGNATURE = 'signature'; - public const JSON_PROPERTY_CREATED = 'created'; - public const JSON_PROPERTY_MODIFIED = 'modified'; - public const JSON_PROPERTY_PROPERTIES = 'properties'; + public const PROPERTY_TYPE = 'resource.node'; + public const PROPERTY_PROVIDER = 'provider'; + public const PROPERTY_SERVICE = 'service'; + public const PROPERTY_COLLECTION = 'collection'; + public const PROPERTY_IDENTIFIER = 'identifier'; + public const PROPERTY_SIGNATURE = 'signature'; + public const PROPERTY_CREATED = 'created'; + public const PROPERTY_MODIFIED = 'modified'; + public const PROPERTY_PROPERTIES = 'properties'; /** * Node type diff --git a/shared/lib/Resource/Provider/Node/NodeMutableAbstract.php b/shared/lib/Resource/Provider/Node/NodeMutableAbstract.php index 25fdcc5..7634d53 100644 --- a/shared/lib/Resource/Provider/Node/NodeMutableAbstract.php +++ b/shared/lib/Resource/Provider/Node/NodeMutableAbstract.php @@ -28,56 +28,56 @@ abstract class NodeMutableAbstract extends NodeBaseAbstract implements NodeMutab $this->data = []; - if (isset($data[static::JSON_PROPERTY_COLLECTION])) { - if (!is_string($data[static::JSON_PROPERTY_COLLECTION]) && !is_int($data[static::JSON_PROPERTY_COLLECTION])) { + if (isset($data[static::PROPERTY_COLLECTION])) { + if (!is_string($data[static::PROPERTY_COLLECTION]) && !is_int($data[static::PROPERTY_COLLECTION])) { throw new \InvalidArgumentException("Collection must be a string or integer"); } - $this->data[static::JSON_PROPERTY_COLLECTION] = $data[static::JSON_PROPERTY_COLLECTION]; + $this->data[static::PROPERTY_COLLECTION] = $data[static::PROPERTY_COLLECTION]; } else { - $this->data[static::JSON_PROPERTY_COLLECTION] = null; + $this->data[static::PROPERTY_COLLECTION] = null; } - if (isset($data[static::JSON_PROPERTY_IDENTIFIER])) { - if (!is_string($data[static::JSON_PROPERTY_IDENTIFIER]) && !is_int($data[static::JSON_PROPERTY_IDENTIFIER])) { + if (isset($data[static::PROPERTY_IDENTIFIER])) { + if (!is_string($data[static::PROPERTY_IDENTIFIER]) && !is_int($data[static::PROPERTY_IDENTIFIER])) { throw new \InvalidArgumentException("Identifier must be a string or integer"); } - $this->data[static::JSON_PROPERTY_IDENTIFIER] = $data[static::JSON_PROPERTY_IDENTIFIER]; + $this->data[static::PROPERTY_IDENTIFIER] = $data[static::PROPERTY_IDENTIFIER]; } else { - $this->data[static::JSON_PROPERTY_IDENTIFIER] = null; + $this->data[static::PROPERTY_IDENTIFIER] = null; } - if (isset($data[static::JSON_PROPERTY_SIGNATURE])) { - if (!is_string($data[static::JSON_PROPERTY_SIGNATURE]) && !is_int($data[static::JSON_PROPERTY_SIGNATURE])) { + if (isset($data[static::PROPERTY_SIGNATURE])) { + if (!is_string($data[static::PROPERTY_SIGNATURE]) && !is_int($data[static::PROPERTY_SIGNATURE])) { throw new \InvalidArgumentException("Signature must be a string or integer"); } - $this->data[static::JSON_PROPERTY_SIGNATURE] = $data[static::JSON_PROPERTY_SIGNATURE]; + $this->data[static::PROPERTY_SIGNATURE] = $data[static::PROPERTY_SIGNATURE]; } else { - $this->data[static::JSON_PROPERTY_SIGNATURE] = null; + $this->data[static::PROPERTY_SIGNATURE] = null; } - if (isset($data[static::JSON_PROPERTY_CREATED])) { - if (!is_string($data[static::JSON_PROPERTY_CREATED])) { + if (isset($data[static::PROPERTY_CREATED])) { + if (!is_string($data[static::PROPERTY_CREATED])) { throw new \InvalidArgumentException("Created date must be a string in ISO 8601 format"); } - $this->data[static::JSON_PROPERTY_CREATED] = $data[static::JSON_PROPERTY_CREATED]; + $this->data[static::PROPERTY_CREATED] = $data[static::PROPERTY_CREATED]; } else { - $this->data[static::JSON_PROPERTY_CREATED] = null; + $this->data[static::PROPERTY_CREATED] = null; } - if (isset($data[static::JSON_PROPERTY_MODIFIED])) { - if (!is_string($data[static::JSON_PROPERTY_MODIFIED])) { + if (isset($data[static::PROPERTY_MODIFIED])) { + if (!is_string($data[static::PROPERTY_MODIFIED])) { throw new \InvalidArgumentException("Modified date must be a string in ISO 8601 format"); } - $this->data[static::JSON_PROPERTY_MODIFIED] = $data[static::JSON_PROPERTY_MODIFIED]; + $this->data[static::PROPERTY_MODIFIED] = $data[static::PROPERTY_MODIFIED]; } else { - $this->data[static::JSON_PROPERTY_MODIFIED] = null; + $this->data[static::PROPERTY_MODIFIED] = null; } - if (isset($data[static::JSON_PROPERTY_PROPERTIES])) { - if (!is_array($data[static::JSON_PROPERTY_PROPERTIES])) { + if (isset($data[static::PROPERTY_PROPERTIES])) { + if (!is_array($data[static::PROPERTY_PROPERTIES])) { throw new \InvalidArgumentException("Properties must be an array"); } - $this->getProperties()->jsonDeserialize($data[static::JSON_PROPERTY_PROPERTIES]); + $this->getProperties()->jsonDeserialize($data[static::PROPERTY_PROPERTIES]); } return $this; diff --git a/shared/lib/Resource/Provider/Node/NodePropertiesBaseAbstract.php b/shared/lib/Resource/Provider/Node/NodePropertiesBaseAbstract.php index ccc3677..7eb7bfb 100644 --- a/shared/lib/Resource/Provider/Node/NodePropertiesBaseAbstract.php +++ b/shared/lib/Resource/Provider/Node/NodePropertiesBaseAbstract.php @@ -18,16 +18,17 @@ namespace KTXF\Resource\Provider\Node; */ abstract class NodePropertiesBaseAbstract implements NodePropertiesBaseInterface { + protected string $type = 'resource.data'; protected array $data = []; public function __construct(array $data) { - if (!isset($data[static::JSON_PROPERTY_TYPE])) { - $data[static::JSON_PROPERTY_TYPE] = static::JSON_TYPE; + if (!isset($data[static::PROPERTY_TYPE])) { + $data[static::PROPERTY_TYPE] = $this->type; } - if (!isset($data[static::JSON_PROPERTY_SCHEMA])) { - $data[static::JSON_PROPERTY_SCHEMA] = 1; + if (!isset($data[static::PROPERTY_SCHEMA])) { + $data[static::PROPERTY_SCHEMA] = 1; } $this->data = $data; @@ -44,14 +45,14 @@ abstract class NodePropertiesBaseAbstract implements NodePropertiesBaseInterface * @inheritDoc */ public function type(): string { - return $this->data[static::JSON_PROPERTY_TYPE]; + return $this->data[static::PROPERTY_TYPE]; } /** * @inheritDoc */ public function schema(): int { - return $this->data[static::JSON_PROPERTY_SCHEMA]; + return $this->data[static::PROPERTY_SCHEMA]; } } diff --git a/shared/lib/Resource/Provider/Node/NodePropertiesBaseInterface.php b/shared/lib/Resource/Provider/Node/NodePropertiesBaseInterface.php index 551c0f3..562c9da 100644 --- a/shared/lib/Resource/Provider/Node/NodePropertiesBaseInterface.php +++ b/shared/lib/Resource/Provider/Node/NodePropertiesBaseInterface.php @@ -18,11 +18,8 @@ use JsonSerializable; */ interface NodePropertiesBaseInterface extends JsonSerializable { - public const RESOURCE_TYPE = 'resource.data'; - - public const JSON_TYPE = 'resource.data'; - public const JSON_PROPERTY_TYPE = '@type'; - public const JSON_PROPERTY_SCHEMA = 'schema'; + public const PROPERTY_TYPE = '@type'; + public const PROPERTY_SCHEMA = 'schema'; /** * Get resource node properties type diff --git a/shared/lib/Resource/Provider/Node/NodePropertiesMutableInterface.php b/shared/lib/Resource/Provider/Node/NodePropertiesMutableInterface.php index d38d319..341d6cc 100644 --- a/shared/lib/Resource/Provider/Node/NodePropertiesMutableInterface.php +++ b/shared/lib/Resource/Provider/Node/NodePropertiesMutableInterface.php @@ -16,6 +16,4 @@ use KTXF\Json\JsonDeserializable; * * @since 2025.05.01 */ -interface NodePropertiesMutableInterface extends NodePropertiesBaseInterface, JsonDeserializable { - -} +interface NodePropertiesMutableInterface extends NodePropertiesBaseInterface, JsonDeserializable {}