diff options
| author | Daniel Weipert <git@mail.dweipert.de> | 2025-09-25 13:38:24 +0200 |
|---|---|---|
| committer | Daniel Weipert <git@mail.dweipert.de> | 2025-09-25 13:38:24 +0200 |
| commit | b19a8f63ad727a3633885d3f2b81edf8181a53b9 (patch) | |
| tree | 6b5fd70224a125a16010a291e5fd0df834e9436f | |
| parent | b08047ba485f86038f33175162943c0a9878ab1a (diff) | |
matrix-specification split work in progress
57 files changed, 1284 insertions, 92 deletions
diff --git a/composer.json b/composer.json index 14c1b94..49923a9 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,8 @@ "psr/log": "^3.0", "symfony/dotenv": "^7.3", "symfony/http-foundation": "^7.3", - "symfony/routing": "^7.3" + "symfony/routing": "^7.3", + "psr/http-message": "^2.0" }, "require-dev": { "guzzlehttp/guzzle": "^7.9", diff --git a/composer.lock b/composer.lock index c80924c..398e061 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,62 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b8c9f3de980f8dc287642ead631cec2e", + "content-hash": "1e6280a905a847ca703c88bbef0521b2", "packages": [ { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { "name": "psr/log", "version": "3.0.2", "source": { @@ -1636,59 +1689,6 @@ "time": "2024-04-15T12:06:14+00:00" }, { - "name": "psr/http-message", - "version": "2.0", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "support": { - "source": "https://github.com/php-fig/http-message/tree/2.0" - }, - "time": "2023-04-04T09:54:51+00:00" - }, - { "name": "ralouphie/getallheaders", "version": "3.0.3", "source": { diff --git a/matrix-specification/AccountData.php b/matrix-specification/AccountData.php deleted file mode 100644 index b29e7fe..0000000 --- a/matrix-specification/AccountData.php +++ /dev/null @@ -1,16 +0,0 @@ -<?php - -namespace Matrix; - -use Matrix\Events\Event; - -class AccountData -{ - /** - * @param Event[] $events - */ - public function __construct( - private array $events - ) - {} -} diff --git a/matrix-specification/Data/AccountData.php b/matrix-specification/Data/AccountData.php new file mode 100644 index 0000000..fa3e4a3 --- /dev/null +++ b/matrix-specification/Data/AccountData.php @@ -0,0 +1,23 @@ +<?php + +namespace Matrix\Data; + +use Matrix\Events\Event; + +class AccountData implements \JsonSerializable +{ + /** + * @param Event[] $events + */ + public function __construct( + private array $events + ) + {} + + public function jsonSerialize(): array + { + return [ + "events" => $this->events, + ]; + } +} diff --git a/matrix-specification/Data/Contact.php b/matrix-specification/Data/Contact.php new file mode 100644 index 0000000..9eeefe5 --- /dev/null +++ b/matrix-specification/Data/Contact.php @@ -0,0 +1,28 @@ +<?php + +namespace Matrix\Data; + +use Matrix\Enums\Role; + +class Contact implements \JsonSerializable +{ + public function __construct( + private Role|string $role, + private ?string $emailAddress = null, + private ?string $matrixId = null, + ) + { + if (is_null($emailAddress) && is_null($matrixId)) { + throw new \InvalidArgumentException("at least one of emailAddress or matrixId is required"); + } + } + + public function jsonSerialize(): array + { + return array_filter([ + "email_address" => $this->emailAddress, + "matrix_id" => $this->matrixId, + "role" => $this->role, + ], "is_null"); + } +} diff --git a/matrix-specification/Data/DeviceKeys.php b/matrix-specification/Data/DeviceKeys.php new file mode 100644 index 0000000..034263e --- /dev/null +++ b/matrix-specification/Data/DeviceKeys.php @@ -0,0 +1,31 @@ +<?php + +namespace Matrix\Data; + +class DeviceKeys implements \JsonSerializable +{ + /** + * @param string[] $algorithms + * @param array<string, string> $keys + * @param array<string, array<string, string>> $signatures + */ + public function __construct( + private array $algorithms, + private string $deviceId, + private array $keys, + private array $signatures, + private string $userId, + ) + {} + + public function jsonSerialize(): array + { + return [ + "algorithms" => $this->algorithms, + "device_id" => $this->deviceId, + "keys" => $this->keys, + "signatures" => $this->signatures, + "user_id" => $this->userId, + ]; + } +} diff --git a/matrix-specification/Data/DeviceLists.php b/matrix-specification/Data/DeviceLists.php new file mode 100644 index 0000000..33d9459 --- /dev/null +++ b/matrix-specification/Data/DeviceLists.php @@ -0,0 +1,24 @@ +<?php + +namespace Matrix\Data; + +class DeviceLists implements \JsonSerializable +{ + /** + * @param string[] $changed + * @param string[] $left + */ + public function __construct( + private array $changed = [], + private array $left = [], + ) + {} + + public function jsonSerialize(): array + { + return [ + "changed" => $this->events, + "left" => $this->events, + ]; + } +} diff --git a/matrix-specification/Data/DiscoveryInformation.php b/matrix-specification/Data/DiscoveryInformation.php new file mode 100644 index 0000000..42a3dc2 --- /dev/null +++ b/matrix-specification/Data/DiscoveryInformation.php @@ -0,0 +1,30 @@ +<?php + +namespace Matrix\Data; + +class DiscoveryInformation implements \JsonSerializable +{ + /** + * @param array<string, array<mixed, mixed>> $otherProperties + */ + public function __construct( + private HomeServerInformation $homeServerInformation, + private IdentityServerInformation $identityServerInformation, + private ?array $otherProperties = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter( + array_merge( + [ + "m.homeserver" => $this->homeServerInformation, + "m.identity_server" => $this->identityServerInformation, + ], + $this->otherProperties ?? [], + ), + "is_null" + ); + } +} diff --git a/matrix-specification/Data/Filters/EventFilter.php b/matrix-specification/Data/Filters/EventFilter.php new file mode 100644 index 0000000..98788ad --- /dev/null +++ b/matrix-specification/Data/Filters/EventFilter.php @@ -0,0 +1,36 @@ +<?php + +namespace Matrix\Data\Filters; + +class EventFilter implements \JsonSerializable +{ + /** + * @param string[] $notSenders + * @param string[] $notTypes + * @param string[] $senders + * @param string[] $types + */ + public function __construct( + private ?int $limit = null, + private ?array $notSenders = null, + private ?array $notTypes = null, + private ?array $senders = null, + private ?array $types = null, + ) + { + if (! is_null($limit) && $limit <= 0) { + throw new \InvalidArgumentException("limit must be an integer greater than 0"); + } + } + + public function jsonSerialize(): array + { + return array_filter([ + "limit" => $this->limit, + "not_senders" => $this->notSenders, + "not_types" => $this->notTypes, + "senders" => $this->senders, + "types" => $this->types, + ], "is_null"); + } +} diff --git a/matrix-specification/Data/Filters/RoomEventFilter.php b/matrix-specification/Data/Filters/RoomEventFilter.php new file mode 100644 index 0000000..915c9a0 --- /dev/null +++ b/matrix-specification/Data/Filters/RoomEventFilter.php @@ -0,0 +1,50 @@ +<?php + +namespace Matrix\Data\Filters; + +class RoomEventFilter extends EventFilter +{ + /** + * @param string[] $notRooms + * @param string[] $notSenders + * @param string[] $notTypes + * @param string[] $rooms + * @param string[] $senders + * @param string[] $types + */ + public function __construct( + private ?bool $containsUrl = null, + private ?bool $includeRedundantMembers = null, + private ?bool $lazyLoadMembers = null, + ?int $limit = null, + private ?array $notRooms = null, + ?array $notSenders = null, + ?array $notTypes = null, + private ?array $rooms = null, + ?array $senders = null, + ?array $types = null, + private ?bool $unreadThreadNotifications = null, + ) + { + parent::__construct($limit, $notSenders, $notTypes, $senders, $types); + } + + public function setDefaults(): void + { + $this->includeRedundantMembers ??= false; + $this->lazyLoadMembers ??= false; + $this->unreadThreadNotifications ??= false; + } + + public function jsonSerialize(): array + { + return parent::jsonSerialize() + array_filter([ + "contains_url" => $this->containsUrl, + "include_redundant_members" => $this->includeRedundantMembers, + "lazy_load_members" => $this->lazyLoadMembers, + "not_rooms" => $this->notRooms, + "rooms" => $this->rooms, + "unread_thread_notifications" => $this->unreadThreadNotifications, + ], "is_null"); + } +} diff --git a/matrix-specification/Data/Filters/RoomFilter.php b/matrix-specification/Data/Filters/RoomFilter.php new file mode 100644 index 0000000..dd110bd --- /dev/null +++ b/matrix-specification/Data/Filters/RoomFilter.php @@ -0,0 +1,39 @@ +<?php + +namespace Matrix\Data\Filters; + +class RoomFilter +{ + /** + * @param string[] $notRooms + * @param string[] $rooms + */ + public function __construct( + private ?RoomEventFilter $accountData = null, + private ?RoomEventFilter $ephemeral = null, + private ?bool $includeLeave = null, + private ?array $notRooms = null, + private ?array $rooms = null, + private ?RoomEventFilter $state = null, + private ?RoomEventFilter $timeline = null, + ) + {} + + public function setDefaults(): void + { + $this->includeLeave ??= false; + } + + public function jsonSerialize(): array + { + return array_filter([ + "account_data" => $this->accountData, + "ephemeral" => $this->ephemeral, + "include_leave" => $this->includeLeave, + "not_rooms" => $this->notRooms, + "rooms" => $this->rooms, + "state" => $this->state, + "timeline" => $this->timeline, + ], "is_null"); + } +} diff --git a/matrix-specification/Data/HomeServerInformation.php b/matrix-specification/Data/HomeServerInformation.php new file mode 100644 index 0000000..15c9f10 --- /dev/null +++ b/matrix-specification/Data/HomeServerInformation.php @@ -0,0 +1,18 @@ +<?php + +namespace Matrix\Data; + +class HomeServerInformation implements \JsonSerializable +{ + public function __construct( + private string $baseUrl, + ) + {} + + public function jsonSerialize(): array + { + return [ + "base_url" => $this->baseUrl, + ]; + } +} diff --git a/matrix-specification/Data/IdentityServerInformation.php b/matrix-specification/Data/IdentityServerInformation.php new file mode 100644 index 0000000..bed8323 --- /dev/null +++ b/matrix-specification/Data/IdentityServerInformation.php @@ -0,0 +1,18 @@ +<?php + +namespace Matrix\Data; + +class IdentityServerInformation implements \JsonSerializable +{ + public function __construct( + private string $baseUrl, + ) + {} + + public function jsonSerialize(): array + { + return [ + "base_url" => $this->baseUrl, + ]; + } +} diff --git a/matrix-specification/Data/KeyObject.php b/matrix-specification/Data/KeyObject.php new file mode 100644 index 0000000..120350c --- /dev/null +++ b/matrix-specification/Data/KeyObject.php @@ -0,0 +1,32 @@ +<?php + +namespace Matrix\Data; + +class KeyObject implements \JsonSerializable +{ + /** + * @param array<string, array> $signatures + */ + public function __construct( + private string $key, + private array $signatures, + private bool $isFallback = false, + ) + {} + + public function jsonSerialize(): array + { + $keyObject = [ + "key" => $this->key, + "signatures" => $this->signatures, + ]; + + if ($this->isFallback) { + $keyObject += [ + "fallback" => true, + ]; + } + + return $keyObject; + } +} diff --git a/matrix-specification/Responses/LoginFlow.php b/matrix-specification/Data/LoginFlow.php index 6ddb703..6874aad 100644 --- a/matrix-specification/Responses/LoginFlow.php +++ b/matrix-specification/Data/LoginFlow.php @@ -1,6 +1,6 @@ <?php -namespace Matrix\Responses; +namespace Matrix\Data; use Matrix\Enums\LoginType; diff --git a/matrix-specification/Data/Presence.php b/matrix-specification/Data/Presence.php new file mode 100644 index 0000000..971343f --- /dev/null +++ b/matrix-specification/Data/Presence.php @@ -0,0 +1,23 @@ +<?php + +namespace Matrix\Data; + +use Matrix\Events\PresenceEvent; + +class Presence implements \JsonSerializable +{ + /** + * @param PresenceEvent[] $events + */ + public function __construct( + private array $events + ) + {} + + public function jsonSerialize(): array + { + return [ + "events" => $this->events, + ]; + } +} diff --git a/matrix-specification/Data/Room/Ephemeral.php b/matrix-specification/Data/Room/Ephemeral.php new file mode 100644 index 0000000..bcaf22f --- /dev/null +++ b/matrix-specification/Data/Room/Ephemeral.php @@ -0,0 +1,21 @@ +<?php + +namespace Matrix\Data\Room; + +class Ephemeral implements \JsonSerializable +{ + /** + * @param Event[] $events + */ + public function __construct( + private array $events, + ) + {} + + public function jsonSerialize(): array + { + return [ + "events" => $this->events, + ]; + } +} diff --git a/matrix-specification/Data/Room/InviteState.php b/matrix-specification/Data/Room/InviteState.php new file mode 100644 index 0000000..ca468ee --- /dev/null +++ b/matrix-specification/Data/Room/InviteState.php @@ -0,0 +1,23 @@ +<?php + +namespace Matrix\Data\Room; + +use Matrix\Events\StrippedStateEvent; + +class InviteState implements \JsonSerializable +{ + /** + * @param StrippedStateEvent[] $events + */ + public function __construct( + private array $events, + ) + {} + + public function jsonSerialize(): array + { + return [ + "events" => $this->events, + ]; + } +} diff --git a/matrix-specification/Data/Room/InvitedRoom.php b/matrix-specification/Data/Room/InvitedRoom.php new file mode 100644 index 0000000..f081861 --- /dev/null +++ b/matrix-specification/Data/Room/InvitedRoom.php @@ -0,0 +1,18 @@ +<?php + +namespace Matrix\Data\Room; + +class InvitedRoom implements \JsonSerializable +{ + public function __construct( + private InviteState $inviteState, + ) + {} + + public function jsonSerialize(): array + { + return [ + "invite_state" => $this->inviteState, + ]; + } +} diff --git a/matrix-specification/Data/Room/JoinedRoom.php b/matrix-specification/Data/Room/JoinedRoom.php new file mode 100644 index 0000000..89f64b9 --- /dev/null +++ b/matrix-specification/Data/Room/JoinedRoom.php @@ -0,0 +1,37 @@ +<?php + +namespace Matrix\Data\Room; + +use Matrix\Data\AccountData; + +class JoinedRoom implements \JsonSerializable +{ + /** + * @param array<string, ThreadNotificationCounts> + */ + public function __construct( + private ?AccountData $accountData = null, + private ?Ephemeral $ephemeral = null, + private ?State $state = null, + private ?State $stateAfter = null, + private ?RoomSummary $summary = null, + private ?Timeline $timeline = null, + private ?UnreadNotificationCounts $unreadNotifications = null, + private ?array $unreadThreadNotifications = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "account_data" => $this->inviteState, + "ephemeral" => $this->ephemeral, + "state" => $this->state, + "state_after" => $this->stateAfter, + "summary" => $this->summary, + "timeline" => $this->timeline, + "unread_notifications" => $this->unreadNotifications, + "unreadThreadNotifications" => $this->unreadThreadNotifications, + ], "is_null"); + } +} diff --git a/matrix-specification/Data/Room/KnockState.php b/matrix-specification/Data/Room/KnockState.php new file mode 100644 index 0000000..e294da8 --- /dev/null +++ b/matrix-specification/Data/Room/KnockState.php @@ -0,0 +1,23 @@ +<?php + +namespace Matrix\Data\Room; + +use Matrix\Events\StrippedStateEvent; + +class KnockState implements \JsonSerializable +{ + /** + * @param StrippedStateEvent[] $events + */ + public function __construct( + private array $events, + ) + {} + + public function jsonSerialize(): array + { + return [ + "events" => $this->events, + ]; + } +} diff --git a/matrix-specification/Data/Room/KnockedRoom.php b/matrix-specification/Data/Room/KnockedRoom.php new file mode 100644 index 0000000..cbea19f --- /dev/null +++ b/matrix-specification/Data/Room/KnockedRoom.php @@ -0,0 +1,18 @@ +<?php + +namespace Matrix\Data\Room; + +class KnockedRoom implements \JsonSerializable +{ + public function __construct( + private KnockState $knockState, + ) + {} + + public function jsonSerialize(): array + { + return [ + "knock_state" => $this->knockState, + ]; + } +} diff --git a/matrix-specification/Data/Room/LeftRoom.php b/matrix-specification/Data/Room/LeftRoom.php new file mode 100644 index 0000000..18e97b5 --- /dev/null +++ b/matrix-specification/Data/Room/LeftRoom.php @@ -0,0 +1,30 @@ +<?php + +namespace Matrix\Data\Room; + +use Matrix\Data\AccountData; + +/** + * @see https://spec.matrix.org/v1.16/client-server-api/#get_matrixclientv3sync_response-200_left-room + * TODO: validate against request. add ValidatesAgainstRequest interface? and MatrixRequest base class? + */ +class LeftRoom implements \JsonSerializable +{ + public function __construct( + private ?AccountData $accountData = null, + private ?State $state = null, + private ?State $stateAfter = null, + private ?Timeline $timeline = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "account_data" => $this->inviteState, + "state" => $this->state, + "state_after" => $this->stateAfter, + "timeline" => $this->timeline, + ], "is_null"); + } +} diff --git a/matrix-specification/Data/Room/RoomSummary.php b/matrix-specification/Data/Room/RoomSummary.php new file mode 100644 index 0000000..91d170f --- /dev/null +++ b/matrix-specification/Data/Room/RoomSummary.php @@ -0,0 +1,25 @@ +<?php + +namespace Matrix\Data\Room; + +class RoomSummary implements \JsonSerializable +{ + /** + * @param string[] $heroes + */ + public function __construct( + private ?array $heroes = null, + private ?int $invitedMemberCount = null, + private ?int $joinedMemberCount = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "m.heroes" => $this->heroes, + "m.invited_member_count" => $this->invitedMemberCount, + "m.joined_member_count" => $this->joinedMemberCount, + ], "is_null"); + } +} diff --git a/matrix-specification/Data/Room/Rooms.php b/matrix-specification/Data/Room/Rooms.php new file mode 100644 index 0000000..1a84608 --- /dev/null +++ b/matrix-specification/Data/Room/Rooms.php @@ -0,0 +1,62 @@ +<?php + +namespace Matrix\Data\Room; + +class Rooms implements \JsonSerializable +{ + /** + * @param array<string, InvitedRoom> $invite + * @param array<string, JoinedRoom> $join + * @param array<string, KnockedRoom> $knock + * @param array<string, LeftRoom> $leave + */ + public function __construct( + private ?array $invite = null, + private ?array $join = null, + private ?array $knock = null, + private ?array $leave = null, + ) + {} + + public function jsonSerialize(): array + { + return [ + "invite" => $this->invite ?? new \stdClass(), + "join" => $this->join ?? new \stdClass(), + "knock" => $this->knock ?? new \stdClass(), + "leave" => $this->leave ?? new \stdClass(), + ]; + } + + /** + * @return InvitedRoom[] + */ + public function getInvite(): ?array + { + return $this->invite; + } + + /** + * @return JoinedRoom[] + */ + public function getJoined(): ?array + { + return $this->join; + } + + /** + * @return KnockedRoom[] + */ + public function getKnocked(): ?array + { + return $this->knock; + } + + /** + * @return LeftRoom[] + */ + public function getLeft(): ?array + { + return $this->leave; + } +} diff --git a/matrix-specification/Data/Room/State.php b/matrix-specification/Data/Room/State.php new file mode 100644 index 0000000..be9f0ef --- /dev/null +++ b/matrix-specification/Data/Room/State.php @@ -0,0 +1,23 @@ +<?php + +namespace Matrix\Data\Room; + +use Matrix\Events\ClientEventWithoutRoomId; + +class State implements \JsonSerializable +{ + /** + * @param ClientEventWithoutRoomId[] $events + */ + public function __construct( + private array $events, + ) + {} + + public function jsonSerialize(): array + { + return [ + "events" => $this->events, + ]; + } +} diff --git a/matrix-specification/Data/Room/ThreadNotificationCounts.php b/matrix-specification/Data/Room/ThreadNotificationCounts.php new file mode 100644 index 0000000..346aeb3 --- /dev/null +++ b/matrix-specification/Data/Room/ThreadNotificationCounts.php @@ -0,0 +1,20 @@ +<?php + +namespace Matrix\Data\Room; + +class ThreadNotificationCounts implements \JsonSerializable +{ + public function __construct( + private ?int $highlightCount = null, + private ?int $notificationCount = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "highlight_count" => $this->highlightCount, + "notification_count" => $this->notificationCount, + ], "is_null"); + } +} diff --git a/matrix-specification/Data/Room/Timeline.php b/matrix-specification/Data/Room/Timeline.php new file mode 100644 index 0000000..cc88472 --- /dev/null +++ b/matrix-specification/Data/Room/Timeline.php @@ -0,0 +1,27 @@ +<?php + +namespace Matrix\Data\Room; + +use Matrix\Events\ClientEventWithoutRoomId; + +class Timeline implements \JsonSerializable +{ + /** + * @param ClientEventWithoutRoomId[] $events + */ + public function __construct( + private array $events, + private ?bool $limited = null, + private ?string $previousBatch = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "events" => $this->events, + "limited" => $this->limited, + "prev_batch" => $this->previousBatch, + ], "is_null"); + } +} diff --git a/matrix-specification/Data/Room/UnreadNotificationCounts.php b/matrix-specification/Data/Room/UnreadNotificationCounts.php new file mode 100644 index 0000000..d2600e6 --- /dev/null +++ b/matrix-specification/Data/Room/UnreadNotificationCounts.php @@ -0,0 +1,20 @@ +<?php + +namespace Matrix\Data\Room; + +class UnreadNotificationCounts implements \JsonSerializable +{ + public function __construct( + private ?int $highlightCount = null, + private ?int $notificationCount = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "highlight_count" => $this->highlightCount, + "notification_count" => $this->notificationCount, + ], "is_null"); + } +} diff --git a/matrix-specification/Data/ToDevice.php b/matrix-specification/Data/ToDevice.php new file mode 100644 index 0000000..362ce06 --- /dev/null +++ b/matrix-specification/Data/ToDevice.php @@ -0,0 +1,23 @@ +<?php + +namespace Matrix\Data; + +use Matrix\Events\SenderEvent; + +class ToDevice implements \JsonSerializable +{ + /** + * @param SenderEvent[] $events + */ + public function __construct( + private array $events + ) + {} + + public function jsonSerialize(): array + { + return [ + "events" => $this->events, + ]; + } +} diff --git a/matrix-specification/Data/UserId.php b/matrix-specification/Data/UserId.php new file mode 100644 index 0000000..01a5e9e --- /dev/null +++ b/matrix-specification/Data/UserId.php @@ -0,0 +1,17 @@ +<?php + +namespace Matrix\Data; + +class UserId +{ + public static function validate(): bool + {} + + public static function parse(): array + {} + + public static function build(string $username, string $serverName): string + { + return "@$username:$serverName"; + } +} diff --git a/matrix-specification/UserIdentifier.php b/matrix-specification/Data/UserIdentifier.php index 63f939a..8fcdae0 100644 --- a/matrix-specification/UserIdentifier.php +++ b/matrix-specification/Data/UserIdentifier.php @@ -1,6 +1,6 @@ <?php -namespace Matrix; +namespace Matrix\Data; use Matrix\Enums\UserIdentifierType; diff --git a/matrix-specification/Enums/ApiPathVersion.php b/matrix-specification/Enums/ApiPathVersion.php new file mode 100644 index 0000000..5664688 --- /dev/null +++ b/matrix-specification/Enums/ApiPathVersion.php @@ -0,0 +1,11 @@ +<?php + +namespace Matrix\Enums; + +enum ApiPathVersion: string +{ + case R0 = "r0"; + case V1 = "v1"; + case V2 = "v2"; + case V3 = "v3"; +} diff --git a/matrix-specification/Enums/EventType.php b/matrix-specification/Enums/EventType.php index bf805b2..da199dd 100644 --- a/matrix-specification/Enums/EventType.php +++ b/matrix-specification/Enums/EventType.php @@ -5,11 +5,15 @@ namespace Matrix\Enums; enum EventType: string implements \JsonSerializable { case PRESENCE = "m.presence"; + case RECEIPT = "m.receipt"; case ROOM_MEMBER = "m.room.member"; case ROOM_MESSAGE = "m.room.message"; case ROOM_NAME = "m.room.name"; + case TAG = "m.tag"; + case TYPING = "m.typing"; + public function jsonSerialize(): string { return $this->value; diff --git a/matrix-specification/Enums/Role.php b/matrix-specification/Enums/Role.php new file mode 100644 index 0000000..f2abf9b --- /dev/null +++ b/matrix-specification/Enums/Role.php @@ -0,0 +1,14 @@ +<?php + +namespace Matrix\Enums; + +enum Role: string implements \JsonSerializable +{ + case ADMIN = "m.role.admin"; + case SECURITY = "m.role.security"; + + public function jsonSerialize(): string + { + return $this->value; + } +} diff --git a/matrix-specification/Events/PresenceEvent.php b/matrix-specification/Events/PresenceEvent.php index f71d4bd..c8c2023 100644 --- a/matrix-specification/Events/PresenceEvent.php +++ b/matrix-specification/Events/PresenceEvent.php @@ -10,22 +10,22 @@ class PresenceEvent extends SenderEvent public function __construct( string $sender, PresenceState $presence, - string $avatarUrl = "", - bool $currentlyActive = false, - string $displayName = "", - int $lastActiveAgo = 0, - string $statusMessage = "", + ?string $avatarUrl = null, + ?bool $currentlyActive = null, + ?string $displayName = null, + ?int $lastActiveAgo = null, + ?string $statusMessage = null, ) { parent::__construct( - [ + array_filter([ "avatar_url" => $avatarUrl, "currently_active" => $currentlyActive, "display_name" => $displayName, "last_active_ago" => $lastActiveAgo, "presence" => $presence, "status_msg" => $statusMessage, - ], + ], "is_null"), $sender, EventType::PRESENCE ); diff --git a/matrix-specification/Events/StrippedStateEvent.php b/matrix-specification/Events/StrippedStateEvent.php new file mode 100644 index 0000000..6e8aea6 --- /dev/null +++ b/matrix-specification/Events/StrippedStateEvent.php @@ -0,0 +1,31 @@ +<?php + +namespace Matrix\Events; + +use Matrix\Enums\EventType; + +class StrippedStateEvent extends SenderEvent +{ + /** + * @param array<string, mixed> $content + */ + public function __construct( + array $content, + string $sender, + private string $stateKey, + EventType $type, + ) + { + parent::__construct($content, $sender, $type); + } + + public function jsonSerialize(): array + { + return [ + "content" => $this->content, + "sender" => $this->sender, + "state_key" => $this->stateKey, + "type" => $this->type, + ]; + } +} diff --git a/matrix-specification/Request.php b/matrix-specification/Request.php new file mode 100644 index 0000000..c9f315f --- /dev/null +++ b/matrix-specification/Request.php @@ -0,0 +1,26 @@ +<?php + +namespace Matrix; + +use Matrix\Enums\ApiPathVersion; +use Psr\Http\Message\RequestInterface; + +abstract class Request implements RequestInterface, \JsonSerializable +{ + abstract public function getUri(string $serverName, ApiPathVersion $version): string; + + /** + * @return array<string, string> + */ + abstract public function getQueryParameters(): array; + + /** + * @return array<string, string> + */ + abstract public function getBody(): array; + + public function jsonSerialize(): array + { + return $this->getBody(); + } +} diff --git a/matrix-specification/Requests/ClientDirectoryRoomAliasGetRequest.php b/matrix-specification/Requests/ClientDirectoryRoomAliasGetRequest.php new file mode 100644 index 0000000..174a5c2 --- /dev/null +++ b/matrix-specification/Requests/ClientDirectoryRoomAliasGetRequest.php @@ -0,0 +1,29 @@ +<?php + +namespace Matrix\Requests; + +use Matrix\Enums\ApiPathVersion; +use Matrix\Request; + +class ClientDirectoryRoomAliasGetRequest extends Request +{ + public function __construct( + private string $roomAlias, + ) + {} + + public function getUri(string $serverName, ApiPathVersion $version): string + { + return "https://$serverName/_matrix/client/{$version}/directory/room/{$this->roomAlias}"; + } + + public function getQueryParameters(): array + { + return []; + } + + public function getBody(): array + { + return []; + } +} diff --git a/matrix-specification/Requests/ClientKeysUploadPostRequest.php b/matrix-specification/Requests/ClientKeysUploadPostRequest.php new file mode 100644 index 0000000..40d9eae --- /dev/null +++ b/matrix-specification/Requests/ClientKeysUploadPostRequest.php @@ -0,0 +1,29 @@ +<?php + +namespace Matrix\Requests; + +use Matrix\Data\DeviceKeys; +use Matrix\Data\KeyObject; + +class ClientKeysUploadPostRequest implements RateLimited, RequiresAuthentication, \JsonSerializable +{ + /** + * @param array<string, string|KeyObject> $fallbackKeys + * @param array<string, string|KeyObject> $oneTimeKeys + */ + public function __construct( + private ?DeviceKeys $deviceKeys = null, + private ?array $fallbackKeys = null, + private ?array $oneTimeKeys = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "device_keys" => $this->deviceKeys, + "fallback_keys" => $this->fallbackKeys, + "one_time_keys" => $this->oneTimeKeys, + ], "is_null"); + } +} diff --git a/matrix-specification/Requests/ClientLoginGetRequest.php b/matrix-specification/Requests/ClientLoginGetRequest.php deleted file mode 100644 index 73cc24c..0000000 --- a/matrix-specification/Requests/ClientLoginGetRequest.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php - -namespace Matrix\Requests; - -class ClientLoginGetRequest implements RateLimited -{} diff --git a/matrix-specification/Requests/ClientLoginPostRequest.php b/matrix-specification/Requests/ClientLoginPostRequest.php index d17c558..44497e7 100644 --- a/matrix-specification/Requests/ClientLoginPostRequest.php +++ b/matrix-specification/Requests/ClientLoginPostRequest.php @@ -2,8 +2,8 @@ namespace Matrix\Requests; +use Matrix\Data\UserIdentifier; use Matrix\Enums\LoginType; -use Matrix\UserIdentifier; class ClientLoginPostRequest implements RateLimited, \JsonSerializable { diff --git a/matrix-specification/Requests/ClientRefreshPostRequest.php b/matrix-specification/Requests/ClientRefreshPostRequest.php new file mode 100644 index 0000000..733ca75 --- /dev/null +++ b/matrix-specification/Requests/ClientRefreshPostRequest.php @@ -0,0 +1,18 @@ +<?php + +namespace Matrix\Requests; + +class ClientRefreshPostRequest implements RateLimited, \JsonSerializable +{ + public function __construct( + private string $refreshToken, + ) + {} + + public function jsonSerialize(): array + { + return [ + "refresh_token" => $this->refreshToken, + ]; + } +} diff --git a/matrix-specification/Requests/ClientSyncGetRequest.php b/matrix-specification/Requests/ClientSyncGetRequest.php index 2921fcf..2ab7d9e 100644 --- a/matrix-specification/Requests/ClientSyncGetRequest.php +++ b/matrix-specification/Requests/ClientSyncGetRequest.php @@ -2,7 +2,37 @@ namespace Matrix\Requests; -class ClientSyncGetRequest +use Matrix\Enums\PresenceState; + +class ClientSyncGetRequest implements RequiresAuthentication { - # TODO + public function __construct( + private ?string $filter = null, + private ?bool $fullState = null, + private ?PresenceState $setPresence = null, + private ?string $since = null, + private ?int $timeout = null, + private ?bool $useStateAfter = null, + ) + {} + + public function setDefaults(): void + { + $this->fullState ??= false; + $this->setPresence ??= PresenceState::ONLINE; + $this->timeout ??= 0; + $this->useStateAfter ??= false; + } + + public function getQueryParameters(): array + { + return array_filter([ + "filter" => $this->filter, + "full_state" => $this->fullState, + "set_presence" => $this->setPresence, + "since" => $this->since, + "timeout" => $this->timeout, + "use_state_after" => $this->useStateAfter, + ], "is_null"); + } } diff --git a/matrix-specification/Requests/ClientUserIdFilterPostRequest.php b/matrix-specification/Requests/ClientUserIdFilterPostRequest.php new file mode 100644 index 0000000..2edc4c5 --- /dev/null +++ b/matrix-specification/Requests/ClientUserIdFilterPostRequest.php @@ -0,0 +1,34 @@ +<?php + +namespace Matrix\Requests; + +use Matrix\Data\Filters\EventFilter; +use Matrix\Data\Filters\RoomFilter; + + # ClientUserUserIdFilterPostRequest? +class ClientUserIdFilterPostRequest implements RequiresAuthentication, \JsonSerializable +{ + /** + * @param string[] $eventFields + */ + public function __construct( + private string $userId, + private ?EventFilter $accountData = null, + private ?array $eventFields = null, + private ?string $eventFormat = null, + private ?EventFilter $presence = null, + private ?RoomFilter $room = null, + ) + {} + + public function jsonSerialize(): array + { + return [ + "account_data" => $this->accountData, + "event_fields" => $this->eventFields, + "event_format" => $this->eventFormat, + "presence" => $this->presence, + "room" => $this->room, + ]; + } +} diff --git a/matrix-specification/Requests/RequiresAuthentication.php b/matrix-specification/Requests/RequiresAuthentication.php index c494f13..a762405 100644 --- a/matrix-specification/Requests/RequiresAuthentication.php +++ b/matrix-specification/Requests/RequiresAuthentication.php @@ -4,5 +4,5 @@ namespace Matrix\Requests; interface RequiresAuthentication { - public function authenticateUser(): bool; + //public function authenticateUser(): bool; } diff --git a/matrix-specification/Responses/ClientAccountWhoamiGetResponse.php b/matrix-specification/Responses/ClientAccountWhoamiGetResponse.php new file mode 100644 index 0000000..48fbbde --- /dev/null +++ b/matrix-specification/Responses/ClientAccountWhoamiGetResponse.php @@ -0,0 +1,22 @@ +<?php + +namespace Matrix\Responses; + +class ClientAccountWhoamiGetResponse implements \JsonSerializable +{ + public function __construct( + private string $userId, + private ?string $deviceId = null, + private ?bool $isGuest = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "device_id" => $this->deviceId, + "is_guest" => $this->isGuest, + "user_id" => $this->userId, + ], "is_null"); + } +} diff --git a/matrix-specification/Responses/ClientDirectoryRoomAliasGetResponse.php b/matrix-specification/Responses/ClientDirectoryRoomAliasGetResponse.php new file mode 100644 index 0000000..a2a6346 --- /dev/null +++ b/matrix-specification/Responses/ClientDirectoryRoomAliasGetResponse.php @@ -0,0 +1,23 @@ +<?php + +namespace Matrix\Responses; + +class ClientDirectoryRoomAliasGetResponse implements \JsonSerializable +{ + /** + * @param string[] $servers + */ + public function __construct( + private string $roomId, + private array $servers, + ) + {} + + public function jsonSerialize(): array + { + return [ + "room_id" => $this->roomId, + "servers" => $this->servers, + ]; + } +} diff --git a/matrix-specification/Responses/ClientKeysUploadPostResponse.php b/matrix-specification/Responses/ClientKeysUploadPostResponse.php new file mode 100644 index 0000000..ff81734 --- /dev/null +++ b/matrix-specification/Responses/ClientKeysUploadPostResponse.php @@ -0,0 +1,21 @@ +<?php + +namespace Matrix\Responses; + +class ClientKeysUploadPostResponse implements \JsonSerializable +{ + /** + * @param array<string, integer> $oneTimeKeyCounts + */ + public function __construct( + private array $oneTimeKeyCounts, + ) + {} + + public function jsonSerialize(): array + { + return [ + "one_time_keys_counts" => $this->oneTimeKeyCounts, + ]; + } +} diff --git a/matrix-specification/Responses/ClientLoginGetResponse.php b/matrix-specification/Responses/ClientLoginGetResponse.php index e0ccc26..b3b65c3 100644 --- a/matrix-specification/Responses/ClientLoginGetResponse.php +++ b/matrix-specification/Responses/ClientLoginGetResponse.php @@ -2,6 +2,8 @@ namespace Matrix\Responses; +use Matrix\Data\LoginFlow; + class ClientLoginGetResponse implements \JsonSerializable { /** diff --git a/matrix-specification/Responses/ClientLoginPostResponse.php b/matrix-specification/Responses/ClientLoginPostResponse.php new file mode 100644 index 0000000..4bb893d --- /dev/null +++ b/matrix-specification/Responses/ClientLoginPostResponse.php @@ -0,0 +1,30 @@ +<?php + +namespace Matrix\Responses; + +use Matrix\Data\DiscoveryInformation; + +class ClientLoginPostResponse implements \JsonSerializable +{ + public function __construct( + private string $accessToken, + private string $deviceId, + private string $userId, + private ?int $expiresInMilliseconds = null, + private ?string $refreshToken = null, + private ?DiscoveryInformation $wellKnown = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "access_token" => $this->accessToken, + "device_id" => $this->deviceId, + "expires_in_ms" => $this->expiresInMilliseconds, + "refresh_token" => $this->refreshToken, + "user_id" => $this->userId, + "well_known" => $this->wellKnown, + ], "is_null"); + } +} diff --git a/matrix-specification/Responses/ClientRefreshPostResponse.php b/matrix-specification/Responses/ClientRefreshPostResponse.php new file mode 100644 index 0000000..b1e1154 --- /dev/null +++ b/matrix-specification/Responses/ClientRefreshPostResponse.php @@ -0,0 +1,22 @@ +<?php + +namespace Matrix\Responses; + +class ClientRefreshPostResponse implements \JsonSerializable +{ + public function __construct( + private string $accessToken, + private ?int $expiresInMilliseconds = null, + private ?string $refreshToken = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "access_token" => $this->accessToken, + "expires_in_ms" => $this->expiresInMilliseconds, + "refresh_token" => $this->refreshToken, + ], "is_null"); + } +} diff --git a/matrix-specification/Responses/ClientSyncGetResponse.php b/matrix-specification/Responses/ClientSyncGetResponse.php index 27464c1..ccdc5e6 100644 --- a/matrix-specification/Responses/ClientSyncGetResponse.php +++ b/matrix-specification/Responses/ClientSyncGetResponse.php @@ -2,7 +2,38 @@ namespace Matrix\Responses; -class ClientSyncGetResponse +use Matrix\Data\AccountData; +use Matrix\Data\DeviceLists; +use Matrix\Data\Presence; +use Matrix\Data\Room\Rooms; +use Matrix\Data\ToDevice; + +class ClientSyncGetResponse implements \JsonSerializable { - # TODO + /** + * @param array<string, int> $deviceOneTimeKeysCount + */ + public function __construct( + private string $nextBatch, + private ?AccountData $accountData = null, + private ?DeviceLists $deviceLists = null, + private ?array $deviceOneTimeKeysCount = null, + private ?Presence $presence = null, + private ?Rooms $rooms = null, + private ?ToDevice $toDevice = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "account_data" => $this->accountData, + "device_lists" => $this->deviceLists, + "device_one_time_keys_count" => $this->deviceOneTimeKeysCount, + "next_batch" => $this->nextBatch, + "presence" => $this->presence, + "rooms" => $this->rooms, + "to_device" => $this->toDevice, + ], "is_null"); + } } diff --git a/matrix-specification/Responses/ClientUserIdFilterPostResponse.php b/matrix-specification/Responses/ClientUserIdFilterPostResponse.php new file mode 100644 index 0000000..ed7ba37 --- /dev/null +++ b/matrix-specification/Responses/ClientUserIdFilterPostResponse.php @@ -0,0 +1,22 @@ +<?php + +namespace Matrix\Responses; + +class ClientUserIdFilterPostResponse implements \JsonSerializable +{ + public function __construct( + private string $filterId, + ) + { + if (str_starts_with($filterId, "{")) { + throw new \InvalidArgumentException("filterId cannot start with a { as this character is used to determine if the filter provided is inline JSON or a previously declared filter by homeservers on some APIs"); + } + } + + public function jsonSerialize(): array + { + return [ + "filter_id" => $this->filterId, + ]; + } +} diff --git a/matrix-specification/Responses/ClientVersionsGetResponse.php b/matrix-specification/Responses/ClientVersionsGetResponse.php new file mode 100644 index 0000000..9ec701d --- /dev/null +++ b/matrix-specification/Responses/ClientVersionsGetResponse.php @@ -0,0 +1,24 @@ +<?php + +namespace Matrix\Responses; + +class ClientVersionsGetResponse implements \JsonSerializable +{ + /** + * @param string[] $versions + * @param array<string, bool> $unstableFeatures + */ + public function __construct( + private array $versions, + private ?array $unstableFeatures = null, + ) + {} + + public function jsonSerialize(): array + { + return array_filter([ + "unstable_features" => $this->unstableFeatures, + "versions" => $this->versions, + ], "is_null"); + } +} diff --git a/matrix-specification/Responses/WellKnownMatrixClientGetResponse.php b/matrix-specification/Responses/WellKnownMatrixClientGetResponse.php new file mode 100644 index 0000000..769268f --- /dev/null +++ b/matrix-specification/Responses/WellKnownMatrixClientGetResponse.php @@ -0,0 +1,18 @@ +<?php + +namespace Matrix\Responses; + +use Matrix\Data\DiscoveryInformation; + +class WellKnownMatrixClientGetResponse implements \JsonSerializable +{ + public function __construct( + private DiscoveryInformation $discoveryInformation, + ) + {} + + public function jsonSerialize(): array + { + return $this->discoveryInformation; + } +} diff --git a/matrix-specification/Responses/WellKnownMatrixSupportGetResponse.php b/matrix-specification/Responses/WellKnownMatrixSupportGetResponse.php new file mode 100644 index 0000000..f38e2b0 --- /dev/null +++ b/matrix-specification/Responses/WellKnownMatrixSupportGetResponse.php @@ -0,0 +1,33 @@ +<?php + +namespace Matrix\Responses; + +use Matrix\Data\Contact; + +class WellKnownMatrixSupportGetResponse implements \JsonSerializable +{ + /** + * @param Contact[] $contacts + */ + public function __construct( + private ?array $contacts = null, + private ?string $supportPage = null, + ) + { + if (is_null($contacts) && is_null($supportPage)) { + throw new \InvalidArgumentException("at least one of contacts or supportPage is required"); + } + + if (! is_null($contacts) && is_null($supportPage) && empty($contacts)) { + throw new \InvalidArgumentException("if only contacts is set, it must contain at least one item"); + } + } + + public function jsonSerialize(): array + { + return array_filter([ + "contacts" => $this->contacts, + "support_page" => $this->supportPage, + ], "is_null"); + } +} |
