* SPDX-License-Identifier: AGPL-3.0-or-later */ namespace KTXM\PeopleProviderLocal\Providers\Shared; use KTXF\People\Collection\CollectionContent; use KTXF\People\Collection\CollectionPermissions; use KTXF\People\Collection\CollectionRoles; use KTXF\People\Collection\ICollectionMutable; use KTXM\PeopleProviderLocal\Store\Personal\CollectionEntry; use Override; class Collection implements ICollectionMutable { private ?string $userId = null; private ?int $collectionShareId = null; private ?string $collectionShareOwner = null; private ?int $collectionSharePermissions = null; private string $providerId = 'default'; private string $serviceId = 'shared'; private ?int $collectionId = null; private ?string $collectionUuid = null; private ?string $collectionLabel = null; private ?string $collectionDescription = null; private ?int $collectionPriority = null; private ?bool $collectionVisibility = null; private ?string $collectionColor = null; private bool $collectionEnabled = true; private ?string $collectionSignature = null; private array $collectionPermissions = []; private array $collectionAttributes = [ 'roles' => [ CollectionRoles::Individual->value => true, ], 'contents' => [ CollectionContent::Individual->value => true, CollectionContent::Organization->value => true, CollectionContent::Group->value => true, ], ]; public function jsonSerialize(): mixed { return [ self::JSON_PROPERTY_TYPE => self::JSON_TYPE, self::JSON_PROPERTY_PROVIDER => $this->providerId, self::JSON_PROPERTY_SERVICE => $this->serviceId, self::JSON_PROPERTY_IN => null, self::JSON_PROPERTY_ID => $this->collectionId, self::JSON_PROPERTY_UUID => $this->collectionUuid, self::JSON_PROPERTY_LABEL => $this->collectionLabel, self::JSON_PROPERTY_DESCRIPTION => $this->collectionDescription, self::JSON_PROPERTY_PRIORITY => $this->collectionPriority, self::JSON_PROPERTY_VISIBILITY => $this->collectionVisibility, self::JSON_PROPERTY_COLOR => $this->collectionColor, self::JSON_PROPERTY_ENABLED => $this->collectionEnabled, self::JSON_PROPERTY_SIGNATURE => $this->collectionSignature, self::JSON_PROPERTY_PERMISSIONS => [$this->userId => $this->collectionPermissions], self::JSON_PROPERTY_ROLES => $this->collectionAttributes['roles'] ?? [], self::JSON_PROPERTY_CONTENTS => $this->collectionAttributes['contents'] ?? [], ]; } public function jsonDeserialize(array $data): static { $this->collectionId = $data[self::JSON_PROPERTY_ID] ?? null; $this->collectionUuid = $data[self::JSON_PROPERTY_UUID] ?? null; $this->collectionLabel = $data[self::JSON_PROPERTY_LABEL] ?? null; $this->collectionDescription = $data[self::JSON_PROPERTY_DESCRIPTION] ?? null; $this->collectionPriority = $data[self::JSON_PROPERTY_PRIORITY] ?? null; $this->collectionVisibility = $data[self::JSON_PROPERTY_VISIBILITY] ?? null; $this->collectionColor = $data[self::JSON_PROPERTY_COLOR] ?? null; $this->collectionEnabled = $data[self::JSON_PROPERTY_ENABLED] ?? true; $this->collectionSignature = $data[self::JSON_PROPERTY_SIGNATURE] ?? null; return $this; } public function fromStore(CollectionEntry $data): self { $this->collectionShareOwner = $data->getUserId(); $this->collectionId = $data->getId(); $this->collectionUuid = $data->getUri(); $this->collectionLabel = $data->getDisplayname(); $this->collectionDescription = $data->getDescription(); $this->collectionSignature = $data->getSynctoken(); return $this; } public function toStore(): CollectionEntry { $data = new CollectionEntry(); if ($this->collectionId !== null) { $data->setId($this->collectionId); } $data->setUserId($this->userId); $data->setUri($this->collectionUuid); $data->setDisplayname($this->collectionLabel); $data->setDescription($this->collectionDescription); return $data; } public function fromShareStore(array $data): self { if (empty($data['principaluri']) || !str_starts_with($data['principaluri'], 'principals/users/')) { throw new \InvalidArgumentException('Share data must contain a principaluri'); } $this->userId = substr($data['principaluri'], 17); $this->collectionShareId = $data['id'] ?? null; $this->collectionSharePermissions = $data['access'] ?? 0; $this->collectionPermissions[CollectionPermissions::View->value] = true; if ($this->collectionSharePermissions === 2) { $this->collectionPermissions[CollectionPermissions::Create->value] = true; $this->collectionPermissions[CollectionPermissions::Modify->value] = true; $this->collectionPermissions[CollectionPermissions::Destroy->value] = true; } return $this; } /** * Unique identifier of the service this collection belongs to * * @since 2025.05.01 */ public function in(): null { return null; } /** * Unique arbitrary text string identifying this service (e.g. 1 or collection1 or anything else) * * @since 2025.05.01 */ public function id(): int { return $this->collectionShareId; } /** * Lists all supported attributes * * @since 2025.05.01 * * @return array */ public function attributes(): array { return $this->collectionAttributes; } /** * Unique universal identifier * * @since 2025.05.01 */ public function uuid(): string { return $this->collectionUuid; } /** * Gets the signature of this collection * * @since 2025.05.01 */ public function signature(): ?string { return $this->collectionSignature; } /** * Gets the roles of this collection * * @since 2025.05.01 * * @return array */ public function roles(): array { return $this->collectionAttributes['roles'] ?? []; } /** * Checks if this collection supports the given role * * @since 2025.05.01 */ public function role(CollectionRoles $role): bool { return $this->collectionAttributes['roles'][$role->value] ?? false; } /** * Gets the content types of this collection * * @since 2025.05.01 * * @return array */ public function contents(): array { return $this->collectionAttributes['content'] ?? []; } /** * Checks if this collection contains the given content type * * @since 2025.05.01 */ public function contains(CollectionContent $content): bool { return $this->collectionAttributes['content'][$content->value] ?? false; } /** * Gets the active status of this collection * * @since 2025.05.01 */ public function getEnabled(): bool { return (bool)$this->collectionEnabled; } /** * Sets the active status of this collection * * @since 2025.05.01 */ public function setEnabled(bool $value): self { $this->collectionEnabled = $value; return $this; } /** * Gets the active status of this collection * * @since 2025.05.01 */ public function getPermissions(): array { return [$this->userId => $this->collectionPermissions]; } /** * Checks if this collection supports the given attribute * * @since 2025.05.01 */ public function hasPermission(CollectionPermissions $permission): bool { return $this->collectionPermissions[$permission->value] ?? false; } /** * Gets the human friendly name of this collection (e.g. Personal Contacts) * * @since 2025.05.01 */ public function getLabel(): ?string { return $this->collectionLabel; } /** * Sets the human friendly name of this collection (e.g. Personal Contacts) * * @since 2025.05.01 */ public function setLabel(string $value): self { $this->collectionLabel = $value; return $this; } /** * Gets the human friendly description of this collection * * @since 2025.05.01 */ public function getDescription(): ?string { return $this->collectionDescription; } /** * Sets the human friendly description of this collection * * @since 2025.05.01 */ public function setDescription(?string $value): self { $this->collectionDescription = $value; return $this; } /** * Gets the priority of this collection * * @since 2025.05.01 */ public function getPriority(): ?int { return $this->collectionPriority; } /** * Sets the priority of this collection * * @since 2025.05.01 */ public function setPriority(?int $value): self { $this->collectionPriority = $value; return $this; } /** * Gets the visibility of this collection * * @since 2025.05.01 */ public function getVisibility(): ?bool { return $this->collectionVisibility; } /** * Sets the visibility of this collection * * @since 2025.05.01 */ public function setVisibility(?bool $value): self { $this->collectionVisibility = $value; return $this; } /** * Gets the color of this collection * * @since 2025.05.01 */ public function getColor(): ?string { return $this->collectionColor; } /** * Sets the color of this collection * * @since 2025.05.01 */ public function setColor(?string $value): self { $this->collectionColor = $value; return $this; } }