* SPDX-License-Identifier: AGPL-3.0-or-later */ namespace KTXM\PeopleProviderLocal\Providers\Personal; use KTXF\People\Collection\CollectionContent; use KTXF\People\Collection\CollectionPermissions; use KTXF\People\Collection\CollectionRoles; use KTXF\People\Collection\ICollectionMutable; class Collection implements ICollectionMutable { private ?string $userId = null; private string $providerId = 'default'; private string $serviceId = 'personal'; private ?string $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 ?string $collectionCreatedOn = null; private ?string $collectionModifiedOn = null; private bool $collectionEnabled = true; private ?string $collectionSignature = null; private array $collectionPermissions = [ CollectionPermissions::View->value => true, CollectionPermissions::Create->value => true, CollectionPermissions::Modify->value => true, CollectionPermissions::Destroy->value => true, CollectionPermissions::Share->value => true, ]; 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_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_CREATED => $this->collectionCreatedOn, self::JSON_PROPERTY_MODIFIED => $this->collectionModifiedOn, 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|string $data): static { if (is_string($data)) { $data = json_decode($data, true); } $this->collectionId = $data[self::JSON_PROPERTY_ID] ?? 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->collectionCreatedOn = $data[self::JSON_PROPERTY_CREATED] ?? null; $this->collectionModifiedOn = $data[self::JSON_PROPERTY_MODIFIED] ?? null; $this->collectionEnabled = $data[self::JSON_PROPERTY_ENABLED] ?? true; $this->collectionSignature = $data[self::JSON_PROPERTY_SIGNATURE] ?? null; return $this; } public function fromStore(array|object $data): self { // Convert object to array if needed if (is_object($data)) { $data = (array) $data; } // extract properties if (isset($data['cid'])) { $this->collectionId = $data['cid']; } elseif (isset($data['_id'])) { if (is_object($data['_id']) && method_exists($data['_id'], '__toString')) { $this->collectionId = (string) $data['_id']; } elseif (is_array($data['_id']) && isset($data['_id']['$oid'])) { $this->collectionId = $data['_id']['$oid']; } else { $this->collectionId = (string) $data['_id']; } } $this->userId = $data['uid'] ?? null; $this->collectionLabel = $data['label'] ?? null; $this->collectionDescription = $data['description'] ?? null; $this->collectionColor = $data['color'] ?? null; $this->collectionCreatedOn = $data['created'] ?? null; $this->collectionModifiedOn = $data['modified'] ?? null; $this->collectionEnabled = $data['enabled'] ?? true; $this->collectionSignature = isset($data['signature']) ? md5((string)$data['signature']) : null; // Handle BSON array if present if (isset($data['tags'])) { if (is_object($data['tags']) && method_exists($data['tags'], 'bsonSerialize')) { $tags = $data['tags']->bsonSerialize(); } else { $tags = $data['tags'] ?? []; } } return $this; } public function toStore(): array { $data = [ 'uid' => $this->userId, 'uuid' => $this->collectionUuid, 'label' => $this->collectionLabel, 'description' => $this->collectionDescription, 'color' => $this->collectionColor, 'created' => $this->collectionCreatedOn, 'modified' => $this->collectionModifiedOn, 'signature' => $this->collectionSignature, 'enabled' => $this->collectionEnabled, ]; // Only include _id if it exists (for updates) if ($this->collectionId !== null) { $data['_id'] = $this->collectionId; } return $data; } public function in(): null { return null; } public function id(): string { return $this->collectionId; } public function created(): ?\DateTimeImmutable { return $this->collectionCreatedOn ? new \DateTimeImmutable($this->collectionCreatedOn) : null; } public function modified(): ?\DateTimeImmutable { return $this->collectionModifiedOn ? new \DateTimeImmutable($this->collectionModifiedOn) : null; } public function attributes(): array { return $this->collectionAttributes; } public function uuid(): string { return $this->collectionUuid; } public function signature(): ?string { return $this->collectionSignature; } public function roles(): array { return $this->collectionAttributes['roles'] ?? []; } public function role(CollectionRoles $role): bool { return $this->collectionAttributes['roles'][$role->value] ?? false; } public function contents(): array { return $this->collectionAttributes['content'] ?? []; } public function contains(CollectionContent $content): bool { return $this->collectionAttributes['content'][$content->value] ?? false; } public function getEnabled(): bool { return (bool)$this->collectionEnabled; } public function setEnabled(bool $value): self { $this->collectionEnabled = $value; return $this; } public function getPermissions(): array { return [$this->userId => $this->collectionPermissions]; } public function hasPermission(CollectionPermissions $permission): bool { return $this->collectionPermissions[$permission->value] ?? false; } public function getLabel(): ?string { return $this->collectionLabel; } public function setLabel(string $value): self { $this->collectionLabel = $value; return $this; } public function getDescription(): ?string { return $this->collectionDescription; } public function setDescription(?string $value): self { $this->collectionDescription = $value; return $this; } public function getPriority(): ?int { return $this->collectionPriority; } public function setPriority(?int $value): self { $this->collectionPriority = $value; return $this; } public function getVisibility(): ?bool { return $this->collectionVisibility; } public function setVisibility(?bool $value): self { $this->collectionVisibility = $value; return $this; } public function getColor(): ?string { return $this->collectionColor; } public function setColor(?string $value): self { $this->collectionColor = $value; return $this; } }