From e48ee82530c725ef64c4d135855f5caff287a814 Mon Sep 17 00:00:00 2001 From: Sebastian Krupinski Date: Wed, 25 Feb 2026 00:13:51 -0500 Subject: [PATCH] refactor: people provider Signed-off-by: Sebastian Krupinski --- core/lib/Controllers/InitController.php | 2 +- .../Collection/CollectionBaseInterface.php | 4 +- .../Collection/CollectionBaseAbstract.php | 31 +++ .../Collection/CollectionBaseInterface.php | 30 +++ .../Collection/CollectionMutableAbstract.php | 50 ++++ .../Collection/CollectionMutableInterface.php | 32 +++ .../Collection/CollectionPermissions.php | 26 --- .../CollectionPropertiesBaseAbstract.php | 74 ++++++ .../CollectionPropertiesBaseInterface.php | 70 ++++++ .../CollectionPropertiesMutableAbstract.php | 72 ++++++ ... CollectionPropertiesMutableInterface.php} | 25 +- .../lib/People/Collection/CollectionRoles.php | 24 -- .../lib/People/Collection/ICollectionBase.php | 160 ------------- .../lib/People/Entity/EntityBaseAbstract.php | 31 +++ .../lib/People/Entity/EntityBaseInterface.php | 25 ++ .../People/Entity/EntityMutableAbstract.php | 47 ++++ .../People/Entity/EntityMutableInterface.php | 28 +++ .../lib/People/Entity/EntityPermissions.php | 25 -- .../Entity/EntityPropertiesBaseAbstract.php | 21 ++ .../Entity/EntityPropertiesBaseInterface.php | 21 ++ .../EntityPropertiesMutableAbstract.php | 30 +++ .../EntityPropertiesMutableInterface.php | 20 ++ shared/lib/People/Entity/IEntityBase.php | 94 -------- shared/lib/People/Entity/IEntityMutable.php | 52 ----- shared/lib/People/Provider/IProviderBase.php | 96 -------- .../Provider/IProviderServiceMutate.php | 69 ------ .../People/Provider/ProviderBaseInterface.php | 23 ++ .../ProviderServiceMutateInterface.php | 28 +++ .../Provider/ProviderServiceTestInterface.php | 45 ++++ shared/lib/People/Service/IServiceBase.php | 221 ------------------ .../Service/IServiceCollectionMutable.php | 79 ------- .../People/Service/IServiceEntityMutable.php | 82 ------- shared/lib/People/Service/IServiceMutable.php | 30 --- .../People/Service/ServiceBaseInterface.php | 199 ++++++++++++++++ .../ServiceCollectionMutableInterface.php | 75 ++++++ .../Service/ServiceConfigurableInterface.php | 23 ++ .../Service/ServiceEntityMutableInterface.php | 76 ++++++ .../Service/ServiceMutableInterface.php | 21 ++ ...ResourceProviderServiceMutateInterface.php | 2 +- .../ResourceServiceConfigureInterface.php | 5 +- .../ResourceServiceMutateInterface.php | 7 +- 41 files changed, 1091 insertions(+), 984 deletions(-) create mode 100644 shared/lib/People/Collection/CollectionBaseAbstract.php create mode 100644 shared/lib/People/Collection/CollectionBaseInterface.php create mode 100644 shared/lib/People/Collection/CollectionMutableAbstract.php create mode 100644 shared/lib/People/Collection/CollectionMutableInterface.php delete mode 100644 shared/lib/People/Collection/CollectionPermissions.php create mode 100644 shared/lib/People/Collection/CollectionPropertiesBaseAbstract.php create mode 100644 shared/lib/People/Collection/CollectionPropertiesBaseInterface.php create mode 100644 shared/lib/People/Collection/CollectionPropertiesMutableAbstract.php rename shared/lib/People/Collection/{ICollectionMutable.php => CollectionPropertiesMutableInterface.php} (55%) delete mode 100644 shared/lib/People/Collection/CollectionRoles.php delete mode 100644 shared/lib/People/Collection/ICollectionBase.php create mode 100644 shared/lib/People/Entity/EntityBaseAbstract.php create mode 100644 shared/lib/People/Entity/EntityBaseInterface.php create mode 100644 shared/lib/People/Entity/EntityMutableAbstract.php create mode 100644 shared/lib/People/Entity/EntityMutableInterface.php delete mode 100644 shared/lib/People/Entity/EntityPermissions.php create mode 100644 shared/lib/People/Entity/EntityPropertiesBaseAbstract.php create mode 100644 shared/lib/People/Entity/EntityPropertiesBaseInterface.php create mode 100644 shared/lib/People/Entity/EntityPropertiesMutableAbstract.php create mode 100644 shared/lib/People/Entity/EntityPropertiesMutableInterface.php delete mode 100644 shared/lib/People/Entity/IEntityBase.php delete mode 100644 shared/lib/People/Entity/IEntityMutable.php delete mode 100644 shared/lib/People/Provider/IProviderBase.php delete mode 100644 shared/lib/People/Provider/IProviderServiceMutate.php create mode 100644 shared/lib/People/Provider/ProviderBaseInterface.php create mode 100644 shared/lib/People/Provider/ProviderServiceMutateInterface.php create mode 100644 shared/lib/People/Provider/ProviderServiceTestInterface.php delete mode 100644 shared/lib/People/Service/IServiceBase.php delete mode 100644 shared/lib/People/Service/IServiceCollectionMutable.php delete mode 100644 shared/lib/People/Service/IServiceEntityMutable.php delete mode 100644 shared/lib/People/Service/IServiceMutable.php create mode 100644 shared/lib/People/Service/ServiceBaseInterface.php create mode 100644 shared/lib/People/Service/ServiceCollectionMutableInterface.php create mode 100644 shared/lib/People/Service/ServiceConfigurableInterface.php create mode 100644 shared/lib/People/Service/ServiceEntityMutableInterface.php create mode 100644 shared/lib/People/Service/ServiceMutableInterface.php diff --git a/core/lib/Controllers/InitController.php b/core/lib/Controllers/InitController.php index 1df5c07..7defcf3 100644 --- a/core/lib/Controllers/InitController.php +++ b/core/lib/Controllers/InitController.php @@ -29,7 +29,7 @@ class InitController extends ControllerAbstract // modules - filter by permissions $configuration['modules'] = []; - foreach ($this->moduleManager->list() as $module) { + foreach ($this->moduleManager->list(true, true) as $module) { // Check if user has permission to view this module // Allow access if user has: {module_handle}, {module_handle}.*, or * permission $handle = $module->handle(); diff --git a/shared/lib/Chrono/Collection/CollectionBaseInterface.php b/shared/lib/Chrono/Collection/CollectionBaseInterface.php index 5ceb6e8..848b5f7 100644 --- a/shared/lib/Chrono/Collection/CollectionBaseInterface.php +++ b/shared/lib/Chrono/Collection/CollectionBaseInterface.php @@ -12,9 +12,9 @@ namespace KTXF\Chrono\Collection; use KTXF\Resource\Provider\Node\NodeBaseInterface; /** - * Chrono Collection Base Interface + * Collection Base Interface * - * Interface represents a collection in a chrono service + * Interface represents a collection in a service * * @since 2025.05.01 */ diff --git a/shared/lib/People/Collection/CollectionBaseAbstract.php b/shared/lib/People/Collection/CollectionBaseAbstract.php new file mode 100644 index 0000000..d7ce0a6 --- /dev/null +++ b/shared/lib/People/Collection/CollectionBaseAbstract.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Collection; + +use KTXF\Resource\Provider\Node\NodeBaseAbstract; + +/** + * Abstract Collection Base Class + * + * Provides common implementation for collections + * + * @since 2025.05.01 + */ +abstract class CollectionBase extends NodeBaseAbstract implements CollectionBaseInterface { + + protected CollectionPropertiesBaseAbstract $properties; + + /** + * @inheritDoc + */ + public function getProperties(): CollectionPropertiesBaseInterface { + return $this->properties; + } +} diff --git a/shared/lib/People/Collection/CollectionBaseInterface.php b/shared/lib/People/Collection/CollectionBaseInterface.php new file mode 100644 index 0000000..de6287c --- /dev/null +++ b/shared/lib/People/Collection/CollectionBaseInterface.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Collection; + +use KTXF\Resource\Provider\Node\NodeBaseInterface; + +/** + * Collection Base Interface + * + * Interface represents a collection in a service + * + * @since 2025.05.01 + */ +interface CollectionBaseInterface extends NodeBaseInterface { + + /** + * Gets the collection properties + * + * @since 2025.05.01 + */ + public function getProperties(): CollectionPropertiesBaseInterface|CollectionPropertiesMutableInterface; + +} diff --git a/shared/lib/People/Collection/CollectionMutableAbstract.php b/shared/lib/People/Collection/CollectionMutableAbstract.php new file mode 100644 index 0000000..44d4a8a --- /dev/null +++ b/shared/lib/People/Collection/CollectionMutableAbstract.php @@ -0,0 +1,50 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Collection; + +use KTXF\Resource\Provider\Node\NodeMutableAbstract; +use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; + +/** + * Abstract Collection Mutable Class + * + * Provides common implementation for mutable collections + * + * @since 2025.05.01 + */ +abstract class CollectionMutableAbstract extends NodeMutableAbstract implements CollectionMutableInterface { + + protected CollectionPropertiesMutableAbstract $properties; + + /** + * @inheritDoc + */ + public function getProperties(): CollectionPropertiesMutableInterface { + return $this->properties; + } + + /** + * @inheritDoc + */ + public function setProperties(NodePropertiesMutableInterface $value): static { + if (!$value instanceof CollectionPropertiesMutableInterface) { + throw new \InvalidArgumentException('Properties must implement CollectionPropertiesMutableInterface'); + } + + // Copy all property values + $this->properties->setLabel($value->getLabel()); + $this->properties->setDescription($value->getDescription()); + $this->properties->setPriority($value->getPriority()); + $this->properties->setVisibility($value->getVisibility()); + $this->properties->setColor($value->getColor()); + + return $this; + } +} diff --git a/shared/lib/People/Collection/CollectionMutableInterface.php b/shared/lib/People/Collection/CollectionMutableInterface.php new file mode 100644 index 0000000..da064c1 --- /dev/null +++ b/shared/lib/People/Collection/CollectionMutableInterface.php @@ -0,0 +1,32 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Collection; + +use KTXF\Resource\Provider\Node\NodeMutableInterface; + +/** + * Collection Mutable Interface + * + * Interface for altering collection properties in a service + * + * @since 2025.05.01 + * + * @method static setProperties(CollectionPropertiesMutableInterface $value) + */ +interface CollectionMutableInterface extends CollectionBaseInterface, NodeMutableInterface { + + /** + * Gets the collection properties (mutable) + * + * @since 2025.05.01 + */ + public function getProperties(): CollectionPropertiesMutableInterface; + +} diff --git a/shared/lib/People/Collection/CollectionPermissions.php b/shared/lib/People/Collection/CollectionPermissions.php deleted file mode 100644 index 3136ca7..0000000 --- a/shared/lib/People/Collection/CollectionPermissions.php +++ /dev/null @@ -1,26 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Collection; - -use JsonSerializable; - -enum CollectionPermissions: string implements JsonSerializable { - - case View = 'view'; - case Create = 'create'; - case Modify = 'modify'; - case Destroy = 'destroy'; - case Share = 'share'; - - public function jsonSerialize(): string { - return $this->value; - } - -} \ No newline at end of file diff --git a/shared/lib/People/Collection/CollectionPropertiesBaseAbstract.php b/shared/lib/People/Collection/CollectionPropertiesBaseAbstract.php new file mode 100644 index 0000000..b8423b9 --- /dev/null +++ b/shared/lib/People/Collection/CollectionPropertiesBaseAbstract.php @@ -0,0 +1,74 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Collection; + +use KTXF\Resource\Provider\Node\NodePropertiesBaseAbstract; + +/** + * Abstract Collection Properties Base Class + * + * Provides common implementation for collection properties + * + * @since 2025.05.01 + */ +abstract class CollectionPropertiesBaseAbstract extends NodePropertiesBaseAbstract implements CollectionPropertiesBaseInterface { + + public const JSON_TYPE = CollectionPropertiesBaseInterface::JSON_TYPE; + + /** + * @inheritDoc + */ + public function content(): array { + $content = $this->data[self::JSON_PROPERTY_CONTENT] ?? null; + if (is_array($content)) { + return array_map(function ($item) { + return new CollectionContent($item); + }, $content); + } else { + return []; + } + } + + /** + * @inheritDoc + */ + public function getLabel(): string { + return $this->data[self::JSON_PROPERTY_LABEL] ?? ''; + } + + /** + * @inheritDoc + */ + public function getDescription(): ?string { + return $this->data[self::JSON_PROPERTY_DESCRIPTION] ?? null; + } + + /** + * @inheritDoc + */ + public function getPriority(): ?int { + return $this->data[self::JSON_PROPERTY_PRIORITY] ?? null; + } + + /** + * @inheritDoc + */ + public function getVisibility(): ?bool { + return $this->data[self::JSON_PROPERTY_VISIBILITY] ?? null; + } + + /** + * @inheritDoc + */ + public function getColor(): ?string { + return $this->data[self::JSON_PROPERTY_COLOR] ?? null; + } + +} diff --git a/shared/lib/People/Collection/CollectionPropertiesBaseInterface.php b/shared/lib/People/Collection/CollectionPropertiesBaseInterface.php new file mode 100644 index 0000000..70e6ccb --- /dev/null +++ b/shared/lib/People/Collection/CollectionPropertiesBaseInterface.php @@ -0,0 +1,70 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Collection; + +use KTXF\Resource\Provider\Node\NodePropertiesBaseInterface; +use PhpParser\Node\Expr\Array_; + +interface CollectionPropertiesBaseInterface extends NodePropertiesBaseInterface { + + public const JSON_TYPE = 'people:collection'; + public const JSON_PROPERTY_CONTENT = 'content'; + + public const JSON_PROPERTY_LABEL = 'label'; + public const JSON_PROPERTY_DESCRIPTION = 'description'; + public const JSON_PROPERTY_PRIORITY = 'priority'; + public const JSON_PROPERTY_VISIBILITY = 'visibility'; + public const JSON_PROPERTY_COLOR = 'color'; + + /** + * Gets the content type of this collection + * + * @since 2025.05.01 + * + * @return CollectionContent[] Returns an array of content types, a single content type, or null if not set + */ + public function content(): array; + + /** + * Gets the human friendly name of this collection (e.g. Personal Calendar) + * + * @since 2025.05.01 + */ + public function getLabel(): string; + + /** + * Gets the human friendly description of this collection + * + * @since 2025.05.01 + */ + public function getDescription(): ?string; + + /** + * Gets the priority of this collection + * + * @since 2025.05.01 + */ + public function getPriority(): ?int; + + /** + * Gets the visibility of this collection + * + * @since 2025.05.01 + */ + public function getVisibility(): ?bool; + + /** + * Gets the color of this collection + * + * @since 2025.05.01 + */ + public function getColor(): ?string; + +} diff --git a/shared/lib/People/Collection/CollectionPropertiesMutableAbstract.php b/shared/lib/People/Collection/CollectionPropertiesMutableAbstract.php new file mode 100644 index 0000000..1070cce --- /dev/null +++ b/shared/lib/People/Collection/CollectionPropertiesMutableAbstract.php @@ -0,0 +1,72 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Collection; + +/** + * Abstract Collection Properties Mutable Class + */ +abstract class CollectionPropertiesMutableAbstract extends CollectionPropertiesBaseAbstract implements CollectionPropertiesMutableInterface { + + public const JSON_TYPE = CollectionPropertiesBaseInterface::JSON_TYPE; + + /** + * @inheritDoc + */ + public function jsonDeserialize(array|string $data): static { + if (is_string($data)) { + $data = json_decode($data, true); + } + + $this->data = $data; + + return $this; + } + + /** + * @inheritDoc + */ + public function setLabel(string $value): static { + $this->data[self::JSON_PROPERTY_LABEL] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setDescription(?string $value): static { + $this->data[self::JSON_PROPERTY_DESCRIPTION] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setPriority(?int $value): static { + $this->data[self::JSON_PROPERTY_PRIORITY] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setVisibility(?bool $value): static { + $this->data[self::JSON_PROPERTY_VISIBILITY] = $value; + return $this; + } + + /** + * @inheritDoc + */ + public function setColor(?string $value): static { + $this->data[self::JSON_PROPERTY_COLOR] = $value; + return $this; + } + +} diff --git a/shared/lib/People/Collection/ICollectionMutable.php b/shared/lib/People/Collection/CollectionPropertiesMutableInterface.php similarity index 55% rename from shared/lib/People/Collection/ICollectionMutable.php rename to shared/lib/People/Collection/CollectionPropertiesMutableInterface.php index 610a48b..91f5e9e 100644 --- a/shared/lib/People/Collection/ICollectionMutable.php +++ b/shared/lib/People/Collection/CollectionPropertiesMutableInterface.php @@ -9,50 +9,45 @@ declare(strict_types=1); namespace KTXF\People\Collection; -use KTXF\Json\JsonDeserializable; +use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; -interface ICollectionMutable extends ICollectionBase, JsonDeserializable { +interface CollectionPropertiesMutableInterface extends NodePropertiesMutableInterface { + + public const JSON_TYPE = CollectionPropertiesBaseInterface::JSON_TYPE; /** - * Sets the active status of this collection + * Sets the human friendly name of this collection (e.g. Personal Calendar) * * @since 2025.05.01 */ - public function setEnabled(bool $value): self; - - /** - * Sets the human friendly name of this collection (e.g. Personal Contacts) - * - * @since 2025.05.01 - */ - public function setLabel(string $value): self; + public function setLabel(string $value): static; /** * Sets the human friendly description of this collection * * @since 2025.05.01 */ - public function setDescription(?string $value): self; + public function setDescription(?string $value): static; /** * Sets the priority of this collection * * @since 2025.05.01 */ - public function setPriority(?int $value): self; + public function setPriority(?int $value): static; /** * Sets the visibility of this collection * * @since 2025.05.01 */ - public function setVisibility(?bool $value): self; + public function setVisibility(?bool $value): static; /** * Sets the color of this collection * * @since 2025.05.01 */ - public function setColor(?string $value): self; + public function setColor(?string $value): static; } diff --git a/shared/lib/People/Collection/CollectionRoles.php b/shared/lib/People/Collection/CollectionRoles.php deleted file mode 100644 index 7a6bbbb..0000000 --- a/shared/lib/People/Collection/CollectionRoles.php +++ /dev/null @@ -1,24 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Collection; - -use JsonSerializable; - -enum CollectionRoles: string implements JsonSerializable { - - case System = 'system'; - case Individual = 'individual'; - case Recent = 'recent'; - - public function jsonSerialize(): string { - return $this->value; - } - -} \ No newline at end of file diff --git a/shared/lib/People/Collection/ICollectionBase.php b/shared/lib/People/Collection/ICollectionBase.php deleted file mode 100644 index cc1617e..0000000 --- a/shared/lib/People/Collection/ICollectionBase.php +++ /dev/null @@ -1,160 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Collection; - -use DateTimeImmutable; -use JsonSerializable; - -interface ICollectionBase extends JsonSerializable { - - public const JSON_TYPE = 'people.collection'; - public const JSON_PROPERTY_TYPE = '@type'; - public const JSON_PROPERTY_PROVIDER = 'provider'; - public const JSON_PROPERTY_SERVICE = 'service'; - public const JSON_PROPERTY_IN = 'in'; - public const JSON_PROPERTY_ID = 'id'; - public const JSON_PROPERTY_LABEL = 'label'; - public const JSON_PROPERTY_DESCRIPTION = 'description'; - public const JSON_PROPERTY_PRIORITY = 'priority'; - public const JSON_PROPERTY_VISIBILITY = 'visibility'; - public const JSON_PROPERTY_COLOR = 'color'; - public const JSON_PROPERTY_CREATED = 'created'; - public const JSON_PROPERTY_MODIFIED = 'modified'; - public const JSON_PROPERTY_ENABLED = 'enabled'; - public const JSON_PROPERTY_SIGNATURE = 'signature'; - public const JSON_PROPERTY_PERMISSIONS = 'permissions'; - public const JSON_PROPERTY_ROLES = 'roles'; - public const JSON_PROPERTY_CONTENTS = 'contents'; - - /** - * Unique identifier of the service this collection belongs to - * - * @since 2025.05.01 - */ - public function in(): string|int|null; - - /** - * Unique arbitrary text string identifying this service (e.g. 1 or collection1 or anything else) - * - * @since 2025.05.01 - */ - public function id(): string|int; - - /** - * Gets the creation date of this collection - */ - public function created(): ?DateTimeImmutable; - - /** - * Gets the modification date of this collection - */ - public function modified(): ?DateTimeImmutable; - - /** - * Lists all supported attributes - * - * @since 2025.05.01 - * - * @return array> - */ - public function attributes(): array; - - /** - * Gets the signature of this collection - * - * @since 2025.05.01 - */ - public function signature(): ?string; - - /** - * Gets the role(s) of this collection - * - * @since 2025.05.01 - */ - public function roles(): array; - - /** - * Checks if this collection supports the given role - * - * @since 2025.05.01 - */ - public function role(CollectionRoles $value): bool; - - /** - * Gets the content types of this collection - * - * @since 2025.05.01 - */ - public function contents(): array; - - /** - * Checks if this collection contains the given content type - * - * @since 2025.05.01 - */ - public function contains(CollectionContent $value): bool; - - /** - * Gets the active status of this collection - * - * @since 2025.05.01 - */ - public function getEnabled(): bool; - - /** - * Gets the active status of this collection - * - * @since 2025.05.01 - */ - public function getPermissions(): array; - - /** - * Checks if this collection has the given permission - * - * @since 2025.05.01 - */ - public function hasPermission(CollectionPermissions $permission): bool; - - /** - * Gets the human friendly name of this collection (e.g. Personal Contacts) - * - * @since 2025.05.01 - */ - public function getLabel(): ?string; - - /** - * Gets the human friendly description of this collection - * - * @since 2025.05.01 - */ - public function getDescription(): ?string; - - /** - * Gets the priority of this collection - * - * @since 2025.05.01 - */ - public function getPriority(): ?int; - - /** - * Gets the visibility of this collection - * - * @since 2025.05.01 - */ - public function getVisibility(): ?bool; - - /** - * Gets the color of this collection - * - * @since 2025.05.01 - */ - public function getColor(): ?string; - -} diff --git a/shared/lib/People/Entity/EntityBaseAbstract.php b/shared/lib/People/Entity/EntityBaseAbstract.php new file mode 100644 index 0000000..63885e7 --- /dev/null +++ b/shared/lib/People/Entity/EntityBaseAbstract.php @@ -0,0 +1,31 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Entity; + +use KTXF\Resource\Provider\Node\NodeBaseAbstract; + +/** + * Abstract Entity Base Class + * + * Provides common implementation for entities + * + * @since 2025.05.01 + */ +abstract class EntityBaseAbstract extends NodeBaseAbstract implements EntityBaseInterface { + + protected EntityPropertiesBaseAbstract $properties; + + /** + * @inheritDoc + */ + public function getProperties(): EntityPropertiesBaseInterface { + return $this->properties; + } +} diff --git a/shared/lib/People/Entity/EntityBaseInterface.php b/shared/lib/People/Entity/EntityBaseInterface.php new file mode 100644 index 0000000..f3b6a6b --- /dev/null +++ b/shared/lib/People/Entity/EntityBaseInterface.php @@ -0,0 +1,25 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Entity; + +use KTXF\Resource\Provider\Node\NodeBaseInterface; + +interface EntityBaseInterface extends NodeBaseInterface { + + public const JSON_TYPE = 'people:entity'; + + /** + * Gets the entity properties + * + * @since 2025.05.01 + */ + public function getProperties(): EntityPropertiesBaseInterface|EntityPropertiesMutableInterface; + +} diff --git a/shared/lib/People/Entity/EntityMutableAbstract.php b/shared/lib/People/Entity/EntityMutableAbstract.php new file mode 100644 index 0000000..1f0b289 --- /dev/null +++ b/shared/lib/People/Entity/EntityMutableAbstract.php @@ -0,0 +1,47 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Entity; + +use KTXF\Resource\Provider\Node\NodeMutableAbstract; +use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; + +/** + * Abstract Entity Mutable Class + * + * Provides common implementation for mutable entities + * + * @since 2025.05.01 + */ +abstract class EntityMutableAbstract extends NodeMutableAbstract implements EntityMutableInterface { + + public const JSON_TYPE = EntityMutableInterface::JSON_TYPE; + + protected EntityPropertiesMutableAbstract $properties; + + /** + * @inheritDoc + */ + public function getProperties(): EntityPropertiesMutableInterface { + return $this->properties; + } + + /** + * @inheritDoc + */ + public function setProperties(NodePropertiesMutableInterface $value): static { + if (!$value instanceof EntityPropertiesMutableInterface) { + throw new \InvalidArgumentException('Properties must implement EntityPropertiesMutableInterface'); + } + + $this->properties->setDataRaw($value->getDataRaw()); + + return $this; + } +} diff --git a/shared/lib/People/Entity/EntityMutableInterface.php b/shared/lib/People/Entity/EntityMutableInterface.php new file mode 100644 index 0000000..ab83678 --- /dev/null +++ b/shared/lib/People/Entity/EntityMutableInterface.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Entity; + +use KTXF\Resource\Provider\Node\NodeMutableInterface; + +/** + * @method static setProperties(EntityPropertiesMutableInterface $value) + */ +interface EntityMutableInterface extends EntityBaseInterface, NodeMutableInterface { + + public const JSON_TYPE = EntityBaseInterface::JSON_TYPE; + + /** + * Gets the entity properties (mutable) + * + * @since 2025.05.01 + */ + public function getProperties(): EntityPropertiesMutableInterface; + +} diff --git a/shared/lib/People/Entity/EntityPermissions.php b/shared/lib/People/Entity/EntityPermissions.php deleted file mode 100644 index 71a20a1..0000000 --- a/shared/lib/People/Entity/EntityPermissions.php +++ /dev/null @@ -1,25 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Entity; - -use JsonSerializable; - -enum EntityPermissions: string implements JsonSerializable { - - case View = 'view'; - case Modify = 'modify'; - case Delete = 'delete'; - case Share = 'share'; - - public function jsonSerialize(): string { - return $this->value; - } - -} \ No newline at end of file diff --git a/shared/lib/People/Entity/EntityPropertiesBaseAbstract.php b/shared/lib/People/Entity/EntityPropertiesBaseAbstract.php new file mode 100644 index 0000000..3c0c238 --- /dev/null +++ b/shared/lib/People/Entity/EntityPropertiesBaseAbstract.php @@ -0,0 +1,21 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Entity; + +use KTXF\Resource\Provider\Node\NodePropertiesBaseAbstract; + +abstract class EntityPropertiesBaseAbstract extends NodePropertiesBaseAbstract implements EntityPropertiesBaseInterface { + + public const JSON_TYPE = EntityPropertiesBaseInterface::JSON_TYPE; + + public function getDataRaw(): array|string|null { + return $this->data[self::JSON_PROPERTY_DATA] ?? null; + } +} diff --git a/shared/lib/People/Entity/EntityPropertiesBaseInterface.php b/shared/lib/People/Entity/EntityPropertiesBaseInterface.php new file mode 100644 index 0000000..e850f33 --- /dev/null +++ b/shared/lib/People/Entity/EntityPropertiesBaseInterface.php @@ -0,0 +1,21 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Entity; + +use KTXF\Resource\Provider\Node\NodePropertiesBaseInterface; + +interface EntityPropertiesBaseInterface extends NodePropertiesBaseInterface { + + public const JSON_TYPE = 'people:entity'; + public const JSON_PROPERTY_DATA = 'data'; + + public function getDataRaw(): array|string|null; + +} diff --git a/shared/lib/People/Entity/EntityPropertiesMutableAbstract.php b/shared/lib/People/Entity/EntityPropertiesMutableAbstract.php new file mode 100644 index 0000000..83ade23 --- /dev/null +++ b/shared/lib/People/Entity/EntityPropertiesMutableAbstract.php @@ -0,0 +1,30 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Entity; + +abstract class EntityPropertiesMutableAbstract extends EntityPropertiesBaseAbstract implements EntityPropertiesMutableInterface { + + public const JSON_TYPE = EntityPropertiesBaseInterface::JSON_TYPE; + + public function jsonDeserialize(array|string $data): static { + if (is_string($data)) { + $data = json_decode($data, true); + } + + $this->data = $data; + + return $this; + } + + public function setDataRaw(array|string|null $value): static { + $this->data[self::JSON_PROPERTY_DATA] = $value; + return $this; + } +} diff --git a/shared/lib/People/Entity/EntityPropertiesMutableInterface.php b/shared/lib/People/Entity/EntityPropertiesMutableInterface.php new file mode 100644 index 0000000..2a81e61 --- /dev/null +++ b/shared/lib/People/Entity/EntityPropertiesMutableInterface.php @@ -0,0 +1,20 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Entity; + +use KTXF\Resource\Provider\Node\NodePropertiesMutableInterface; + +interface EntityPropertiesMutableInterface extends EntityPropertiesBaseInterface, NodePropertiesMutableInterface { + + public const JSON_TYPE = EntityPropertiesBaseInterface::JSON_TYPE; + + public function setDataRaw(array|string|null $value): static; + +} diff --git a/shared/lib/People/Entity/IEntityBase.php b/shared/lib/People/Entity/IEntityBase.php deleted file mode 100644 index 88bdf47..0000000 --- a/shared/lib/People/Entity/IEntityBase.php +++ /dev/null @@ -1,94 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Entity; - -use DateTimeImmutable; -use KTXF\People\Entity\Individual\IndividualObject; - -interface IEntityBase extends \JsonSerializable { - - public const JSON_TYPE = 'people.entity'; - public const JSON_PROPERTY_TYPE = '@type'; - public const JSON_PROPERTY_IN = 'in'; - public const JSON_PROPERTY_ID = 'id'; - public const JSON_PROPERTY_DATA = 'data'; - public const JSON_PROPERTY_CREATED = 'created'; - public const JSON_PROPERTY_MODIFIED = 'modified'; - public const JSON_PROPERTY_SIGNATURE = 'signature'; - - /** - * Unique arbitrary text string identifying the collection this entity belongs to (e.g. 1 or Collection1 or anything else) - * - * @since 2025.05.01 - */ - public function in(): string|int; - - /** - * Unique arbitrary text string identifying this service (e.g. 1 or Entity or anything else) - * - * @since 2025.05.01 - */ - public function id(): string|int; - - /** - * Gets the creation date of this entity - */ - public function created(): ?DateTimeImmutable; - - /** - * Gets the modification date of this entity - */ - public function modified(): ?DateTimeImmutable; - - /** - * Gets the signature of this entity - * - * @since 2025.05.01 - */ - public function signature(): ?string; - - /** - * Gets the priority of this entity - * - * @since 2025.05.01 - */ - public function getPriority(): ?int; - - /** - * Gets the visibility of this entity - * - * @since 2025.05.01 - */ - public function getVisibility(): ?bool; - - /** - * Gets the color of this entity - * - * @since 2025.05.01 - */ - public function getColor(): ?string; - - /** - * Gets the object as a class instance. - * - * @since 2025.05.01 - */ - public function getDataObject(): IndividualObject|null; - - /** - * Gets the raw data as an associative array or JSON string. - * - * @since 2025.05.01 - * - * @return array|string|null - */ - public function getDataJson(): array|string|null; - -} diff --git a/shared/lib/People/Entity/IEntityMutable.php b/shared/lib/People/Entity/IEntityMutable.php deleted file mode 100644 index bd30af5..0000000 --- a/shared/lib/People/Entity/IEntityMutable.php +++ /dev/null @@ -1,52 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Entity; - -use KTXF\Json\JsonDeserializable; -use KTXF\People\Entity\Individual\IndividualObject; - -interface IEntityMutable extends IEntityBase, JsonDeserializable { - - /** - * Sets the priority of this entity - * - * @since 2025.05.01 - */ - public function setPriority(?int $value): static; - - /** - * Sets the visibility of this entity - * - * @since 2025.05.01 - */ - public function setVisibility(?bool $value): static; - - /** - * Sets the color of this entity - * - * @since 2025.05.01 - */ - public function setColor(?string $value): static; - - /** - * Sets the object as a class instance. - * - * @since 2025.05.01 - */ - public function setDataObject(IndividualObject $value): static; - - /** - * Sets the object data from a json string - * - * @since 2025.05.01 - */ - public function setDataJson(array|string $value): static; - -} diff --git a/shared/lib/People/Provider/IProviderBase.php b/shared/lib/People/Provider/IProviderBase.php deleted file mode 100644 index 5f778af..0000000 --- a/shared/lib/People/Provider/IProviderBase.php +++ /dev/null @@ -1,96 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Provider; - -use JsonSerializable; -use KTXF\People\Service\IServiceBase; - -interface IProviderBase extends JsonSerializable { - - public const CAPABILITY_SERVICE_LIST = 'ServiceList'; - public const CAPABILITY_SERVICE_FETCH = 'ServiceFetch'; - public const CAPABILITY_SERVICE_EXTANT = 'ServiceExtant'; - - public const JSON_TYPE = 'people.provider'; - public const JSON_PROPERTY_TYPE = '@type'; - public const JSON_PROPERTY_ID = 'id'; - public const JSON_PROPERTY_LABEL = 'label'; - public const JSON_PROPERTY_CAPABILITIES = 'capabilities'; - - /** - * Confirms if specific capability is supported (e.g. 'ServiceList') - * - * @since 2025.05.01 - */ - public function capable(string $value): bool; - - /** - * Lists all supported capabilities - * - * @since 2025.05.01 - * - * @return array - */ - public function capabilities(): array; - - /** - * An arbitrary unique text string identifying this provider (e.g. UUID or 'system' or anything else) - * - * @since 2025.05.01 - */ - public function id(): string; - - /** - * The localized human friendly name of this provider (e.g. System Contacts Provider) - * - * @since 2025.05.01 - */ - public function label(): string; - - /** - * Retrieve collection of services for a specific user - * - * @since 2025.05.01 - * - * @param string $tenantId tenant identifier - * @param string $userId user identifier - * @param array $filter filter criteria - * - * @return array collection of service objects - */ - public function serviceList(string $tenantId, string $userId, array $filter): array; - - /** - * Determine if any services are configured for a specific user - * - * @since 2025.05.01 - * - * @param string $tenantId tenant identifier - * @param string $userId user identifier - * @param int|string ...$identifiers variadic collection of service identifiers - * - * @return array collection of service identifiers with boolean values indicating if the service is available - */ - public function serviceExtant(string $tenantId, string $userId, int|string ...$identifiers): array; - - /** - * Retrieve a service with a specific identifier - * - * @since 2025.05.01 - * - * @param string $tenantId tenant identifier - * @param string $userId user identifier - * @param string|int $identifier service identifier - * - * @return IServiceBase|null returns service object or null if non found - */ - public function serviceFetch(string $tenantId, string $userId, string|int $identifier): ?IServiceBase; - -} diff --git a/shared/lib/People/Provider/IProviderServiceMutate.php b/shared/lib/People/Provider/IProviderServiceMutate.php deleted file mode 100644 index e128c96..0000000 --- a/shared/lib/People/Provider/IProviderServiceMutate.php +++ /dev/null @@ -1,69 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Provider; - -use KTXF\Json\JsonDeserializable; -use KTXF\People\Service\IServiceBase; - -interface IProviderServiceMutate extends JsonDeserializable { - - public const CAPABILITY_SERVICE_FRESH = 'ServiceFresh'; - public const CAPABILITY_SERVICE_CREATE = 'ServiceCreate'; - public const CAPABILITY_SERVICE_UPDATE = 'ServiceUpdate'; - public const CAPABILITY_SERVICE_DESTROY = 'ServiceDestroy'; - - /** - * construct and new blank service instance - * - * @since 2025.05.01 - * - * @param string $userId user identifier - * - * @return IServiceBase - */ - public function serviceFresh(string $userId = ''): IServiceBase; - - /** - * create a service configuration for a specific user - * - * @since 2025.05.01 - * - * @param string $userId user identifier - * @param IServiceBase $service service instance - * - * @return string - */ - public function serviceCreate(string $userId, IServiceBase $service): string; - - /** - * modify a service configuration for a specific user - * - * @since 2025.05.01 - * - * @param string $userId user identifier - * @param IServiceBase $service service instance - * - * @return string - */ - public function serviceModify(string $userId, IServiceBase $service): string; - - /** - * delete a service configuration for a specific user - * - * @since 2025.05.01 - * - * @param string $userId user identifier - * @param IServiceBase $service service instance - * - * @return bool - */ - public function serviceDestroy(string $userId, IServiceBase $service): bool; - -} diff --git a/shared/lib/People/Provider/ProviderBaseInterface.php b/shared/lib/People/Provider/ProviderBaseInterface.php new file mode 100644 index 0000000..aa66636 --- /dev/null +++ b/shared/lib/People/Provider/ProviderBaseInterface.php @@ -0,0 +1,23 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Provider; + +use KTXF\Resource\Provider\ResourceProviderBaseInterface; + +/** + * Provider Base Interface + * + * @since 2025.05.01 + */ +interface ProviderBaseInterface extends ResourceProviderBaseInterface{ + + public const JSON_TYPE = 'people:provider'; + +} diff --git a/shared/lib/People/Provider/ProviderServiceMutateInterface.php b/shared/lib/People/Provider/ProviderServiceMutateInterface.php new file mode 100644 index 0000000..4565c27 --- /dev/null +++ b/shared/lib/People/Provider/ProviderServiceMutateInterface.php @@ -0,0 +1,28 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Provider; + +use KTXF\Resource\Provider\ResourceProviderServiceMutateInterface; + +/** + * Provider Service Mutate Interface + * + * Optional interface for providers that support service CRUD operations. + * + * @since 2025.05.01 + * + * @method ServiceMutableInterface serviceFresh() Construct a new blank chrono service instance + * @method string serviceCreate(string $tenantId, ?string $userId, ServiceMutableInterface $service) Create a chrono service configuration + * @method string serviceModify(string $tenantId, ?string $userId, ServiceMutableInterface $service) Modify a chrono service configuration + * @method bool serviceDestroy(string $tenantId, ?string $userId, ServiceMutableInterface $service) Delete a chrono service configuration + */ +interface ProviderServiceMutateInterface extends ResourceProviderServiceMutateInterface { + +} diff --git a/shared/lib/People/Provider/ProviderServiceTestInterface.php b/shared/lib/People/Provider/ProviderServiceTestInterface.php new file mode 100644 index 0000000..358b657 --- /dev/null +++ b/shared/lib/People/Provider/ProviderServiceTestInterface.php @@ -0,0 +1,45 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Provider; + +use KTXF\Mail\Service\ServiceBaseInterface; + +/** + * Provider Service Test Interface + * + * Optional interface for providers that support testing service connections + * + * @since 2025.05.01 + */ +interface ProviderServiceTestInterface { + + /** + * Test a service connection + * + * Tests connectivity, authentication, and capabilities of a service + * + * @since 2025.05.01 + * + * @param ServiceBaseInterface $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) + * - 'test_send' => bool (attempt test send if capable, default: false) + * - 'test_receive' => bool (attempt mailbox access if capable, default: true) + * + * @return array Test results in the format: + * [ + * 'success' => bool, + * 'message' => 'Connection successful' | 'Error message' + * ] + */ + public function serviceTest(ServiceBaseInterface $service, array $options = []): array; + +} diff --git a/shared/lib/People/Service/IServiceBase.php b/shared/lib/People/Service/IServiceBase.php deleted file mode 100644 index fe8901d..0000000 --- a/shared/lib/People/Service/IServiceBase.php +++ /dev/null @@ -1,221 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Service; - -use JsonSerializable; -use KTXF\People\Collection\ICollectionBase; -use KTXF\Resource\Filter\IFilter; -use KTXF\Resource\Range\IRange; -use KTXF\Resource\Range\RangeType; -use KTXF\Resource\Sort\ISort; - -interface IServiceBase extends JsonSerializable { - - 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'; - - public const CAPABILITY_ENTITY_LIST = 'EntityList'; - public const CAPABILITY_ENTITY_LIST_FILTER = 'EntityListFilter'; - public const CAPABILITY_ENTITY_LIST_SORT = 'EntityListSort'; - public const CAPABILITY_ENTITY_LIST_RANGE = 'EntityListRange'; - public const CAPABILITY_ENTITY_DELTA = 'EntityDelta'; - public const CAPABILITY_ENTITY_EXTANT = 'EntityExtant'; - public const CAPABILITY_ENTITY_FETCH = 'EntityFetch'; - - public const JSON_TYPE = 'people.service'; - public const JSON_PROPERTY_TYPE = '@type'; - public const JSON_PROPERTY_PROVIDER = 'provider'; - public const JSON_PROPERTY_ID = 'id'; - public const JSON_PROPERTY_LABEL = 'label'; - public const JSON_PROPERTY_CAPABILITIES = 'capabilities'; - public const JSON_PROPERTY_ENABLED = 'enabled'; - - /** - * Confirms if specific capability is supported - * - * @since 2025.05.01 - * - * @param string $value required ability e.g. 'EntityList' - * - * @return bool - */ - public function capable(string $value): bool; - - /** - * Lists all supported capabilities - * - * @since 2025.05.01 - * - * @return array - */ - public function capabilities(): array; - - /** - * Unique identifier of the provider this service belongs to - * - * @since 2025.05.01 - */ - public function in(): string; - - /** - * Unique arbitrary text string identifying this service (e.g. 1 or service1 or anything else) - * - * @since 2025.05.01 - */ - public function id(): string|int; - - /** - * Gets the localized human friendly name of this service (e.g. ACME Company Mail Service) - * - * @since 2025.05.01 - */ - public function getLabel(): string; - - /** - * Gets the active status of this service - * - * @since 2025.05.01 - */ - public function getEnabled(): bool; - - /** - * List of accessible collection - * - * @since 2025.05.01 - * - * @return array - */ - public function collectionList(?IFilter $filter = null, ?ISort $sort = null): array; - - /** - * Fresh filter for collection list - * - * @since 2025.05.01 - * - * @return IFilter - */ - public function collectionListFilter(): IFilter; - - /** - * Fresh sort for collection list - * - * @since 2025.05.01 - * - * @return ISort - */ - public function collectionListSort(): ISort; - - /** - * Fetches details about a specific collection - * - * @since 2025.05.01 - * - * @param string|int $id collection identifier - */ - public function collectionExtant(string|int $identifier): bool; - - /** - * Fetches details about a specific collection - * - * @since 2025.05.01 - * - * @param string|int $identifier collection identifier - */ - public function collectionFetch(string|int $identifier): ?ICollectionBase; - - /** - * Lists all entities in a specific collection - * - * @since 2025.05.01 - * - * @param string|int $collection collection identifier - * - * @return array - */ - public function entityList(string|int $collection, ?IFilter $filter = null, ?ISort $sort = null, ?IRange $range = null, ?array $elements = null): array; - - /** - * Fresh filter for entity list - * - * @since 2025.05.01 - * - * @return Filter - */ - public function entityListFilter(): IFilter; - - /** - * Fresh sort for entity list - * - * @since 2025.05.01 - * - * @return ISort - */ - public function entityListSort(): ISort; - - /** - * Fresh range for entity list - * - * @since 2025.05.01 - * - * @param RangeType $type range type - * - * @return IRange - */ - public function entityListRange(RangeType $type): IRange; - - /** - * Lists of all changes from a specific token - * - * @since 2025.05.01 - * - * @param string|int $collection collection identifier - * @param string $signature token signature - * @param string $detail detail level ids | meta | full - * - * @return array - * - * [ - * 'added' => array, - * 'updated' => array, - * 'deleted' => array, - * 'signature' => string - * ] - * - */ - public function entityDelta(string|int $collection, string $signature, string $detail = 'ids'): array; - - /** - * Confirms if specific entity exists in a collection - * - * @since 2025.05.01 - * - * @param string|int $collection collection identifier - * @param string|int ...$identifiers list of entity identifiers - * - * @return array - */ - public function entityExtant(string|int $collection, string|int ...$identifiers): array; - - /** - * Fetches details about a specific entities in a collection - * - * @since 2025.05.01 - * - * @param string|int $collection collection identifier - * @param string|int ...$identifiers entity identifier - * - * @return array - */ - public function entityFetch(string|int $collection, string|int ...$identifiers): array; - -} diff --git a/shared/lib/People/Service/IServiceCollectionMutable.php b/shared/lib/People/Service/IServiceCollectionMutable.php deleted file mode 100644 index 84fe128..0000000 --- a/shared/lib/People/Service/IServiceCollectionMutable.php +++ /dev/null @@ -1,79 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Service; - -use KTXF\People\Collection\ICollectionBase; -use KTXF\People\Collection\ICollectionMutable; - -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 new, empty collection object - * - * @since 2025.05.01 - * - * @return ICollectionMutable - */ - public function collectionFresh(): ICollectionMutable; - - /** - * Creates a new collection at the specified location - * - * @since 2025.05.01 - * - * @param string|int $location The parent collection to create this collection in, or empty string for root - * @param ICollectionMutable $collection The collection to create - * @param array $options Additional options for the collection creation - * - * @return ICollectionBase - * - * @throws \KTXF\Resource\Exceptions\InvalidArgumentException - * @throws \KTXF\Resource\Exceptions\UnsupportedException - * @throws \KTXF\Resource\Exceptions\UnauthorizedException - */ - public function collectionCreate(string|int $location, ICollectionMutable $collection, array $options): ICollectionBase; - - /** - * Modifies an existing collection - * - * @since 2025.05.01 - * - * @param string|int $identifier The ID of the collection to modify - * @param ICollectionMutable $collection The collection with modifications - * - * @return ICollectionBase - * - * @throws \KTXF\Resource\Exceptions\InvalidArgumentException - * @throws \KTXF\Resource\Exceptions\UnsupportedException - * @throws \KTXF\Resource\Exceptions\UnauthorizedException - */ - public function collectionModify(string|int $identifier, ICollectionMutable $collection): ICollectionBase; - - /** - * Destroys an existing collection - * - * @since 2025.05.01 - * - * @param string|int $identifier The ID of the collection to destroy - * - * @return bool - * - * @throws \KTXF\Resource\Exceptions\InvalidArgumentException - * @throws \KTXF\Resource\Exceptions\UnsupportedException - * @throws \KTXF\Resource\Exceptions\UnauthorizedException - */ - public function collectionDestroy(string|int $identifier): bool; - -} diff --git a/shared/lib/People/Service/IServiceEntityMutable.php b/shared/lib/People/Service/IServiceEntityMutable.php deleted file mode 100644 index b80f840..0000000 --- a/shared/lib/People/Service/IServiceEntityMutable.php +++ /dev/null @@ -1,82 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Service; - -use KTXF\People\Entity\IEntityBase; -use KTXF\People\Entity\IEntityMutable; - -interface IServiceEntityMutable extends IServiceBase { - - 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 of the specified type - * - * @since 2025.05.01 - * - * @return IEntityMutable - */ - public function entityFresh(): IEntityMutable; - - /** - * Creates a new entity in the specified collection - * - * @since 2025.05.01 - * - * @param string|int $collection The collection to create this entity in - * @param IEntityMutable $entity The entity to create - * @param array $options Additional options for the entity creation - * - * @return IEntityMutable - * - * @throws \KTXF\Resource\Exceptions\InvalidArgumentException - * @throws \KTXF\Resource\Exceptions\UnsupportedException - * @throws \KTXF\Resource\Exceptions\UnauthorizedException - */ - public function entityCreate(string|int $collection, IEntityMutable $entity, array $options): IEntityMutable; - - /** - * Modifies an existing entity in the specified collection - * - * @since 2025.05.01 - * - * @param string|int $collection The collection containing the entity to modify - * @param string|int $identifier The ID of the entity to modify - * @param IEntityMutable $entity The entity with modifications - * - * @return IEntityMutable - * - * @throws \KTXF\Resource\Exceptions\InvalidArgumentException - * @throws \KTXF\Resource\Exceptions\UnsupportedException - * @throws \KTXF\Resource\Exceptions\UnauthorizedException - */ - public function entityModify(string|int $collection, string|int $identifier, IEntityMutable $entity): IEntityMutable; - - /** - * Destroys an existing entity in the specified collection - * - * @since 2025.05.01 - * - * @param string|int $collection The collection containing the entity to destroy - * @param string|int $identifier The ID of the entity to destroy - * - * @return bool - * - * @throws \KTXF\Resource\Exceptions\InvalidArgumentException - * @throws \KTXF\Resource\Exceptions\UnsupportedException - * @throws \KTXF\Resource\Exceptions\UnauthorizedException - */ - public function entityDestroy(string|int $collection, string|int $identifier): IEntityBase; - -} diff --git a/shared/lib/People/Service/IServiceMutable.php b/shared/lib/People/Service/IServiceMutable.php deleted file mode 100644 index f35c8a9..0000000 --- a/shared/lib/People/Service/IServiceMutable.php +++ /dev/null @@ -1,30 +0,0 @@ - - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -namespace KTXF\People\Service; - -use KTXF\Json\JsonDeserializable; - -interface IServiceMutable extends IServiceBase, JsonDeserializable { - - /** - * Sets the localized human friendly name of this service (e.g. ACME Company Mail Service) - * - * @since 2025.05.01 - */ - public function setLabel(string $value): self; - - /** - * Sets the active status of this service - * - * @since 2025.05.01 - */ - public function setEnabled(bool $value): self; - -} diff --git a/shared/lib/People/Service/ServiceBaseInterface.php b/shared/lib/People/Service/ServiceBaseInterface.php new file mode 100644 index 0000000..8ccadd6 --- /dev/null +++ b/shared/lib/People/Service/ServiceBaseInterface.php @@ -0,0 +1,199 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Service; + +use KTXF\People\Collection\CollectionBaseInterface; +use KTXF\Resource\Delta\Delta; +use KTXF\Resource\Filter\IFilter; +use KTXF\Resource\Provider\ResourceServiceBaseInterface; +use KTXF\Resource\Range\IRange; +use KTXF\Resource\Range\RangeType; +use KTXF\Resource\Sort\ISort; + +/** + * Service Base Interface + * + * Minimum interface for a service, providing read-only access to collections and entities. + * + * @since 2025.05.01 + */ +interface ServiceBaseInterface extends ResourceServiceBaseInterface { + + // 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'; + // Collection Filter + public const CAPABILITY_COLLECTION_FILTER_LABEL = 'label'; + public const CAPABILITY_COLLECTION_FILTER_CONTENTS = 'contents'; + // 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'; + public const CAPABILITY_ENTITY_LIST_RANGE = 'EntityListRange'; + public const CAPABILITY_ENTITY_DELTA = 'EntityDelta'; + public const CAPABILITY_ENTITY_EXTANT = 'EntityExtant'; + public const CAPABILITY_ENTITY_FETCH = 'EntityFetch'; + // Filter capabilities + public const CAPABILITY_ENTITY_FILTER_ALL = '*'; + public const CAPABILITY_ENTITY_FILTER_ID = 'id'; + public const CAPABILITY_ENTITY_FILTER_URID = 'urid'; + public const CAPABILITY_ENTITY_FILTER_LABEL = 'label'; + // Sort capabilities + public const CAPABILITY_ENTITY_SORT_ID = 'id'; + public const CAPABILITY_ENTITY_SORT_URID = 'urid'; + public const CAPABILITY_ENTITY_SORT_LABEL = 'label'; + public const CAPABILITY_ENTITY_SORT_PRIORITY = 'priority'; + // Range capabilities + public const CAPABILITY_ENTITY_RANGE_TALLY = 'tally'; + public const CAPABILITY_ENTITY_RANGE_TALLY_ABSOLUTE = 'absolute'; + public const CAPABILITY_ENTITY_RANGE_TALLY_RELATIVE = 'relative'; + + public const JSON_TYPE = 'people:service'; + + /** + * 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(string|int $location, ?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 $location, string|int ...$identifiers): array; + + /** + * Fetches a single collection + * + * @since 2025.05.01 + * + * @param string|int $identifier Collection ID + * + * @return CollectionBaseInterface|null Collection or null if not found + */ + public function collectionFetch(string|int $identifier): ?CollectionBaseInterface; + + /** + * 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 entityList(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 entityListFilter(): IFilter; + + /** + * Creates a sort builder for messages + * + * @since 2025.05.01 + * + * @return ISort + */ + public function entityListSort(): ISort; + + /** + * Creates a range builder for messages + * + * @since 2025.05.01 + * + * @param RangeType $type Range type (offset, cursor, etc.) + * + * @return IRange + */ + public function entityListRange(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 entityDelta(string|int $collection, string $signature, string $detail = 'ids'): Delta; + + /** + * 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 entityExtant(string|int $collection, string|int ...$identifiers): array; + + /** + * 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 Messages indexed by ID + */ + public function entityFetch(string|int $collection, string|int ...$identifiers): array; + +} diff --git a/shared/lib/People/Service/ServiceCollectionMutableInterface.php b/shared/lib/People/Service/ServiceCollectionMutableInterface.php new file mode 100644 index 0000000..d65cdcc --- /dev/null +++ b/shared/lib/People/Service/ServiceCollectionMutableInterface.php @@ -0,0 +1,75 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Service; + +use KTXF\People\Collection\CollectionBaseInterface; +use KTXF\People\Collection\CollectionMutableInterface; + +/** + * Service Collection Mutable Interface + * + * Optional interface for services that support collection CRUD operations. + * + * @since 2025.05.01 + */ +interface ServiceCollectionMutableInterface { + + public const CAPABILITY_COLLECTION_CREATE = 'CollectionCreate'; + public const CAPABILITY_COLLECTION_UPDATE = 'CollectionUpdate'; + public const CAPABILITY_COLLECTION_DELETE = 'CollectionDelete'; + + /** + * Creates a fresh collection instance for configuration + * + * @since 2025.05.01 + * + * @return CollectionMutableInterface Fresh collection object + */ + public function collectionFresh(): CollectionMutableInterface; + + /** + * Creates a new collection + * + * @since 2025.05.01 + * + * @param string|int|null $location Parent collection ID (null for root) + * @param CollectionMutableInterface $collection Collection to create + * @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; + + /** + * Updates an existing collection + * + * @since 2025.05.01 + * + * @param string|int $identifier Collection ID + * @param CollectionMutableInterface $collection Updated collection data + * + * @return CollectionBaseInterface Updated collection + */ + public function collectionUpdate(string|int $identifier, CollectionMutableInterface $collection): CollectionBaseInterface; + + /** + * Deletes a collection + * + * @since 2025.05.01 + * + * @param string|int $identifier Collection ID + * @param bool $force Force deletion even if not empty + * @param bool $recursive Recursively delete contents + * + * @return bool True if deleted + */ + public function collectionDelete(string|int $identifier, bool $force = false, bool $recursive = false): bool; + +} diff --git a/shared/lib/People/Service/ServiceConfigurableInterface.php b/shared/lib/People/Service/ServiceConfigurableInterface.php new file mode 100644 index 0000000..f5b6bcb --- /dev/null +++ b/shared/lib/People/Service/ServiceConfigurableInterface.php @@ -0,0 +1,23 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Service; + +use KTXF\Resource\Provider\ResourceServiceConfigureInterface; + +/** + * Service Configurable Interface + * + * Optional interface for services that require configuration + * + * @since 2025.05.01 + */ +interface ServiceConfigurableInterface extends ResourceServiceConfigureInterface { + +} diff --git a/shared/lib/People/Service/ServiceEntityMutableInterface.php b/shared/lib/People/Service/ServiceEntityMutableInterface.php new file mode 100644 index 0000000..8ba04f6 --- /dev/null +++ b/shared/lib/People/Service/ServiceEntityMutableInterface.php @@ -0,0 +1,76 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Service; + +use KTXF\People\Entity\EntityBaseInterface; +use KTXF\People\Entity\EntityMutableInterface; + +/** + * Service Entity Mutable Interface + * + * Optional interface for services that support entity CRUD operations. + * + * @since 2025.05.01 + */ +interface ServiceEntityMutableInterface { + + public const CAPABILITY_ENTITY_CREATE = 'EntityCreate'; + public const CAPABILITY_ENTITY_UPDATE = 'EntityUpdate'; + public const CAPABILITY_ENTITY_DELETE = 'EntityDelete'; + 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 entityUpdate(string|int $collection, string|int $identifier, EntityMutableInterface $entity): EntityBaseInterface; + /** + * Deletes an existing entity in the specified collection + * + * @since 2025.05.01 + * + * @param string|int $collection Collection identifier + * @param string|int $identifier Entity identifier to delete + * + * @return EntityBaseInterface Deleted entity + */ + public function entityDelete(string|int $collection, string|int $identifier): EntityBaseInterface; + +} diff --git a/shared/lib/People/Service/ServiceMutableInterface.php b/shared/lib/People/Service/ServiceMutableInterface.php new file mode 100644 index 0000000..2f9ada8 --- /dev/null +++ b/shared/lib/People/Service/ServiceMutableInterface.php @@ -0,0 +1,21 @@ + + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +namespace KTXF\People\Service; + +/** + * Service Mutable Interface + * + * Marker interface for services that support mutable operations + * + * @since 2025.05.01 + */ +interface ServiceMutableInterface { + +} diff --git a/shared/lib/Resource/Provider/ResourceProviderServiceMutateInterface.php b/shared/lib/Resource/Provider/ResourceProviderServiceMutateInterface.php index 4a22b71..c658698 100644 --- a/shared/lib/Resource/Provider/ResourceProviderServiceMutateInterface.php +++ b/shared/lib/Resource/Provider/ResourceProviderServiceMutateInterface.php @@ -11,7 +11,7 @@ namespace KTXF\Resource\Provider; use KTXF\Json\JsonDeserializable; -interface ResourceProviderServiceMutateInterface extends ResourceProviderBaseInterface, JsonDeserializable { +interface ResourceProviderServiceMutateInterface extends JsonDeserializable { /** * construct and new blank service instance diff --git a/shared/lib/Resource/Provider/ResourceServiceConfigureInterface.php b/shared/lib/Resource/Provider/ResourceServiceConfigureInterface.php index 563414a..eccfe1a 100644 --- a/shared/lib/Resource/Provider/ResourceServiceConfigureInterface.php +++ b/shared/lib/Resource/Provider/ResourceServiceConfigureInterface.php @@ -12,12 +12,11 @@ namespace KTXF\Resource\Provider; /** * Resource Service Configurable Interface * - * Extends base service interface with setter methods for mutable properties. - * Used for service configuration and updates. + * Optional interface for services that require configuration * * @since 2025.05.01 */ -interface ResourceServiceConfigureInterface extends ResourceServiceMutateInterface { +interface ResourceServiceConfigureInterface { /** * Sets the location/configuration of this service diff --git a/shared/lib/Resource/Provider/ResourceServiceMutateInterface.php b/shared/lib/Resource/Provider/ResourceServiceMutateInterface.php index 439fdd0..cca219a 100644 --- a/shared/lib/Resource/Provider/ResourceServiceMutateInterface.php +++ b/shared/lib/Resource/Provider/ResourceServiceMutateInterface.php @@ -12,14 +12,13 @@ namespace KTXF\Resource\Provider; use KTXF\Json\JsonDeserializable; /** - * Resource Service Configurable Interface + * Resource Service Mutate Interface * - * Extends base service interface with setter methods for mutable properties. - * Used for service configuration and updates. + * Optional interface for services that support mutable operations. * * @since 2025.05.01 */ -interface ResourceServiceMutateInterface extends ResourceServiceBaseInterface, JsonDeserializable { +interface ResourceServiceMutateInterface extends JsonDeserializable { /** * Sets the localized human-friendly name of this service (e.g. ACME Company Mail Service)