From 4e31051be8246b0e17e22d806bb28e85f46f593f Mon Sep 17 00:00:00 2001 From: premtsd-code Date: Wed, 20 May 2026 05:57:35 +0000 Subject: [PATCH 1/2] chore: update PHP SDK to 23.1.1 --- CHANGELOG.md | 16 -- docs/examples/presences/delete.md | 16 -- docs/examples/presences/get.md | 16 -- docs/examples/presences/list.md | 18 -- docs/examples/presences/update-presence.md | 24 -- docs/examples/presences/upsert.md | 23 -- .../update-deny-canonical-email-policy.md | 16 -- docs/presences.md | 85 ------ docs/project.md | 4 +- src/Appwrite/Client.php | 4 +- src/Appwrite/Enums/ProjectKeyScopes.php | 18 -- src/Appwrite/Enums/Prompt.php | 61 ----- src/Appwrite/Enums/Scopes.php | 18 -- src/Appwrite/Models/BillingLimits.php | 72 ++--- src/Appwrite/Models/Presence.php | 113 -------- src/Appwrite/Models/PresenceList.php | 59 ---- src/Appwrite/Models/Project.php | 13 +- src/Appwrite/Services/Presences.php | 256 ------------------ tests/Appwrite/Services/PresencesTest.php | 130 --------- tests/Appwrite/Services/ProjectTest.php | 184 +------------ 20 files changed, 35 insertions(+), 1111 deletions(-) delete mode 100644 docs/examples/presences/delete.md delete mode 100644 docs/examples/presences/get.md delete mode 100644 docs/examples/presences/list.md delete mode 100644 docs/examples/presences/update-presence.md delete mode 100644 docs/examples/presences/upsert.md delete mode 100644 docs/examples/project/update-deny-canonical-email-policy.md delete mode 100644 docs/presences.md delete mode 100644 src/Appwrite/Enums/Prompt.php delete mode 100644 src/Appwrite/Models/Presence.php delete mode 100644 src/Appwrite/Models/PresenceList.php delete mode 100644 src/Appwrite/Services/Presences.php delete mode 100644 tests/Appwrite/Services/PresencesTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 0480702..8a8f8c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,21 +1,5 @@ # Change Log -## 24.0.0 - -* Breaking: Renamed `AuthMethod` enum to `ProjectAuthMethodId` -* Breaking: Renamed `EmailTemplateType` to `ProjectEmailTemplateId` and `EmailTemplateLocale` to `ProjectEmailTemplateLocale` -* Breaking: Renamed `ServiceId` to `ProjectServiceId`, `ProtocolId` to `ProjectProtocolId`, `Secure` to `ProjectSMTPSecure`, `ProjectPolicy` to `ProjectPolicyId` -* Breaking: Replaced `Scopes` enum with `ProjectKeyScopes` for project key endpoints -* Breaking: Removed `updateDenyCanonicalEmailPolicy`; replaced with `updateDenyAliasedEmailPolicy`, `updateDenyDisposableEmailPolicy`, and `updateDenyFreeEmailPolicy` -* Breaking: Removed `AuthProvider` model; use new `ProjectOAuthProviderId` enum instead -* Added: `Project::get` method to fetch current project details -* Added: `Advisor`, `Presences`, and `Usage` services -* Added: `Insight`, `Presence`, `Report`, `UsageEvent`, and `UsageGauge` models with list variants -* Added: `ProjectAuthMethod`, `ProjectProtocol`, and `ProjectService` models -* Added: `ProjectOAuthProviderId` and `ProjectOAuth2GooglePrompt` enums -* Updated: `Project`, `Database`, and `OAuth2Google` model schemas -* Updated: `X-Appwrite-Response-Format` header to `1.9.5` - ## 23.1.1 * Fixed: `Database` model `policies` and `archives` now hydrate as `BackupPolicy` / `BackupArchive` instead of `Index` / `Collection` diff --git a/docs/examples/presences/delete.md b/docs/examples/presences/delete.md deleted file mode 100644 index 225ee6c..0000000 --- a/docs/examples/presences/delete.md +++ /dev/null @@ -1,16 +0,0 @@ -```php -setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint - ->setProject('') // Your project ID - ->setKey(''); // Your secret API key - -$presences = new Presences($client); - -$result = $presences->delete( - presenceId: '' -);``` diff --git a/docs/examples/presences/get.md b/docs/examples/presences/get.md deleted file mode 100644 index c019698..0000000 --- a/docs/examples/presences/get.md +++ /dev/null @@ -1,16 +0,0 @@ -```php -setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint - ->setProject('') // Your project ID - ->setKey(''); // Your secret API key - -$presences = new Presences($client); - -$result = $presences->get( - presenceId: '' -);``` diff --git a/docs/examples/presences/list.md b/docs/examples/presences/list.md deleted file mode 100644 index 6162029..0000000 --- a/docs/examples/presences/list.md +++ /dev/null @@ -1,18 +0,0 @@ -```php -setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint - ->setProject('') // Your project ID - ->setKey(''); // Your secret API key - -$presences = new Presences($client); - -$result = $presences->list( - queries: [], // optional - total: false, // optional - ttl: 0 // optional -);``` diff --git a/docs/examples/presences/update-presence.md b/docs/examples/presences/update-presence.md deleted file mode 100644 index d017a13..0000000 --- a/docs/examples/presences/update-presence.md +++ /dev/null @@ -1,24 +0,0 @@ -```php -setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint - ->setProject('') // Your project ID - ->setKey(''); // Your secret API key - -$presences = new Presences($client); - -$result = $presences->updatePresence( - presenceId: '', - userId: '', - status: '', // optional - expiresAt: '2020-10-15T06:38:00.000+00:00', // optional - metadata: [], // optional - permissions: [Permission::read(Role::any())], // optional - purge: false // optional -);``` diff --git a/docs/examples/presences/upsert.md b/docs/examples/presences/upsert.md deleted file mode 100644 index f6d34e2..0000000 --- a/docs/examples/presences/upsert.md +++ /dev/null @@ -1,23 +0,0 @@ -```php -setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint - ->setProject('') // Your project ID - ->setKey(''); // Your secret API key - -$presences = new Presences($client); - -$result = $presences->upsert( - presenceId: '', - userId: '', - status: '', - permissions: [Permission::read(Role::any())], // optional - expiresAt: '2020-10-15T06:38:00.000+00:00', // optional - metadata: [] // optional -);``` diff --git a/docs/examples/project/update-deny-canonical-email-policy.md b/docs/examples/project/update-deny-canonical-email-policy.md deleted file mode 100644 index 1580f5e..0000000 --- a/docs/examples/project/update-deny-canonical-email-policy.md +++ /dev/null @@ -1,16 +0,0 @@ -```php -setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint - ->setProject('') // Your project ID - ->setKey(''); // Your secret API key - -$project = new Project($client); - -$result = $project->updateDenyCanonicalEmailPolicy( - enabled: false -);``` diff --git a/docs/presences.md b/docs/presences.md deleted file mode 100644 index a7977ba..0000000 --- a/docs/presences.md +++ /dev/null @@ -1,85 +0,0 @@ -# Presences Service - - -```http request -GET https://cloud.appwrite.io/v1/presences -``` - -** List presence logs. Expired entries are filtered out automatically. - ** - -### Parameters - -| Field Name | Type | Description | Default | -| --- | --- | --- | --- | -| queries | array | Array of query strings generated using the Query class provided by the SDK. | [] | -| total | boolean | When set to false, the total count returned will be 0 and will not be calculated. | 1 | -| ttl | integer | TTL (seconds) for caching list responses. Responses are stored in an in-memory key-value cache, keyed per project, collection, schema version (attributes and indexes), caller authorization roles, and the exact query — so users with different permissions never share cached entries. Schema changes invalidate cached entries automatically; document writes do not, so choose a TTL you are comfortable serving as stale data. Set to 0 to disable caching. Must be between 0 and 86400 (24 hours). | 0 | - - -```http request -GET https://cloud.appwrite.io/v1/presences/{presenceId} -``` - -** Get a presence log by its unique ID. Entries whose `expiresAt` is in the past are treated as not found. - ** - -### Parameters - -| Field Name | Type | Description | Default | -| --- | --- | --- | --- | -| presenceId | string | **Required** Presence unique ID. | | - - -```http request -PUT https://cloud.appwrite.io/v1/presences/{presenceId} -``` - -** Create or update a presence log by its user ID. - ** - -### Parameters - -| Field Name | Type | Description | Default | -| --- | --- | --- | --- | -| presenceId | string | **Required** Presence unique ID. | | -| userId | string | User ID. | | -| status | string | Presence status. | | -| permissions | array | An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). | | -| expiresAt | string | Presence expiry datetime. | | -| metadata | object | Presence metadata object. | {} | - - -```http request -PATCH https://cloud.appwrite.io/v1/presences/{presenceId} -``` - -** Update a presence log by its unique ID. Using the patch method you can pass only specific fields that will get updated. - ** - -### Parameters - -| Field Name | Type | Description | Default | -| --- | --- | --- | --- | -| presenceId | string | **Required** Presence unique ID. | | -| userId | string | User ID. | | -| status | string | Presence status. | | -| expiresAt | string | Presence expiry datetime. | | -| metadata | object | Presence metadata object. | {} | -| permissions | array | An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https://appwrite.io/docs/permissions). | | -| purge | boolean | When true, purge cached responses used by list presences endpoint. | | - - -```http request -DELETE https://cloud.appwrite.io/v1/presences/{presenceId} -``` - -** Delete a presence log by its unique ID. - ** - -### Parameters - -| Field Name | Type | Description | Default | -| --- | --- | --- | --- | -| presenceId | string | **Required** Presence unique ID. | | - diff --git a/docs/project.md b/docs/project.md index 7ef92d7..81f603c 100644 --- a/docs/project.md +++ b/docs/project.md @@ -501,7 +501,7 @@ PATCH https://cloud.appwrite.io/v1/project/oauth2/google | Field Name | Type | Description | Default | | --- | --- | --- | --- | | clientId | string | 'Client ID' of Google OAuth2 app. For example: 120000000095-92ifjb00000000000000000000g7ijfb.apps.googleusercontent.com | | -| clientSecret | string | 'Client Secret' of Google OAuth2 app. For example: example-google-client-secret | | +| clientSecret | string | 'Client Secret' of Google OAuth2 app. For example: GOCSPX-2k8gsR0000000000000000VNahJj | | | prompt | array | Array of Google OAuth2 prompt values. If "none" is included, it must be the only element. "none" means: don't display any authentication or consent screens. Must not be specified with other values. "consent" means: prompt the user for consent. "select_account" means: prompt the user to select an account. | | | enabled | boolean | OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. | | @@ -549,7 +549,7 @@ PATCH https://cloud.appwrite.io/v1/project/oauth2/linkedin | Field Name | Type | Description | Default | | --- | --- | --- | --- | | clientId | string | 'Client ID' of Linkedin OAuth2 app. For example: 770000000000dv | | -| primaryClientSecret | string | 'Primary Client Secret or Secondary Client Secret' of Linkedin OAuth2 app. For example: example-linkedin-client-secret | | +| primaryClientSecret | string | 'Primary Client Secret or Secondary Client Secret' of Linkedin OAuth2 app. For example: WPL_AP1.2Bf0000000000000./HtlYw== | | | enabled | boolean | OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. | | diff --git a/src/Appwrite/Client.php b/src/Appwrite/Client.php index 09df9b9..56b39bb 100644 --- a/src/Appwrite/Client.php +++ b/src/Appwrite/Client.php @@ -37,11 +37,11 @@ class Client */ protected array $headers = [ 'content-type' => '', - 'user-agent' => 'AppwritePHPSDK/24.0.0 ()', + 'user-agent' => 'AppwritePHPSDK/23.1.1 ()', 'x-sdk-name'=> 'PHP', 'x-sdk-platform'=> 'server', 'x-sdk-language'=> 'php', - 'x-sdk-version'=> '24.0.0', + 'x-sdk-version'=> '23.1.1', ]; /** diff --git a/src/Appwrite/Enums/ProjectKeyScopes.php b/src/Appwrite/Enums/ProjectKeyScopes.php index c60216d..bfbf905 100644 --- a/src/Appwrite/Enums/ProjectKeyScopes.php +++ b/src/Appwrite/Enums/ProjectKeyScopes.php @@ -88,8 +88,6 @@ class ProjectKeyScopes implements JsonSerializable private static ProjectKeyScopes $INSIGHTSWRITE; private static ProjectKeyScopes $REPORTSREAD; private static ProjectKeyScopes $REPORTSWRITE; - private static ProjectKeyScopes $PRESENCESREAD; - private static ProjectKeyScopes $PRESENCESWRITE; private static ProjectKeyScopes $BACKUPSPOLICIESREAD; private static ProjectKeyScopes $BACKUPSPOLICIESWRITE; private static ProjectKeyScopes $ARCHIVESREAD; @@ -692,20 +690,6 @@ public static function REPORTSWRITE(): ProjectKeyScopes } return self::$REPORTSWRITE; } - public static function PRESENCESREAD(): ProjectKeyScopes - { - if (!isset(self::$PRESENCESREAD)) { - self::$PRESENCESREAD = new ProjectKeyScopes('presences.read'); - } - return self::$PRESENCESREAD; - } - public static function PRESENCESWRITE(): ProjectKeyScopes - { - if (!isset(self::$PRESENCESWRITE)) { - self::$PRESENCESWRITE = new ProjectKeyScopes('presences.write'); - } - return self::$PRESENCESWRITE; - } public static function BACKUPSPOLICIESREAD(): ProjectKeyScopes { if (!isset(self::$BACKUPSPOLICIESREAD)) { @@ -862,8 +846,6 @@ public static function from(string $value): self 'insights.write' => self::INSIGHTSWRITE(), 'reports.read' => self::REPORTSREAD(), 'reports.write' => self::REPORTSWRITE(), - 'presences.read' => self::PRESENCESREAD(), - 'presences.write' => self::PRESENCESWRITE(), 'backups.policies.read' => self::BACKUPSPOLICIESREAD(), 'backups.policies.write' => self::BACKUPSPOLICIESWRITE(), 'archives.read' => self::ARCHIVESREAD(), diff --git a/src/Appwrite/Enums/Prompt.php b/src/Appwrite/Enums/Prompt.php deleted file mode 100644 index 92980f9..0000000 --- a/src/Appwrite/Enums/Prompt.php +++ /dev/null @@ -1,61 +0,0 @@ -value = $value; - } - - public function __toString(): string - { - return $this->value; - } - - public function jsonSerialize(): string - { - return $this->value; - } - - public static function NONE(): Prompt - { - if (!isset(self::$NONE)) { - self::$NONE = new Prompt('none'); - } - return self::$NONE; - } - public static function CONSENT(): Prompt - { - if (!isset(self::$CONSENT)) { - self::$CONSENT = new Prompt('consent'); - } - return self::$CONSENT; - } - public static function SELECTACCOUNT(): Prompt - { - if (!isset(self::$SELECTACCOUNT)) { - self::$SELECTACCOUNT = new Prompt('select_account'); - } - return self::$SELECTACCOUNT; - } - - public static function from(string $value): self - { - return match ($value) { - 'none' => self::NONE(), - 'consent' => self::CONSENT(), - 'select_account' => self::SELECTACCOUNT(), - default => throw new \InvalidArgumentException('Unknown Prompt value: ' . $value), - }; - } -} diff --git a/src/Appwrite/Enums/Scopes.php b/src/Appwrite/Enums/Scopes.php index 493c2e1..dbf07a6 100644 --- a/src/Appwrite/Enums/Scopes.php +++ b/src/Appwrite/Enums/Scopes.php @@ -88,8 +88,6 @@ class Scopes implements JsonSerializable private static Scopes $INSIGHTSWRITE; private static Scopes $REPORTSREAD; private static Scopes $REPORTSWRITE; - private static Scopes $PRESENCESREAD; - private static Scopes $PRESENCESWRITE; private static Scopes $BACKUPSPOLICIESREAD; private static Scopes $BACKUPSPOLICIESWRITE; private static Scopes $ARCHIVESREAD; @@ -692,20 +690,6 @@ public static function REPORTSWRITE(): Scopes } return self::$REPORTSWRITE; } - public static function PRESENCESREAD(): Scopes - { - if (!isset(self::$PRESENCESREAD)) { - self::$PRESENCESREAD = new Scopes('presences.read'); - } - return self::$PRESENCESREAD; - } - public static function PRESENCESWRITE(): Scopes - { - if (!isset(self::$PRESENCESWRITE)) { - self::$PRESENCESWRITE = new Scopes('presences.write'); - } - return self::$PRESENCESWRITE; - } public static function BACKUPSPOLICIESREAD(): Scopes { if (!isset(self::$BACKUPSPOLICIESREAD)) { @@ -862,8 +846,6 @@ public static function from(string $value): self 'insights.write' => self::INSIGHTSWRITE(), 'reports.read' => self::REPORTSREAD(), 'reports.write' => self::REPORTSWRITE(), - 'presences.read' => self::PRESENCESREAD(), - 'presences.write' => self::PRESENCESWRITE(), 'backups.policies.read' => self::BACKUPSPOLICIESREAD(), 'backups.policies.write' => self::BACKUPSPOLICIESWRITE(), 'archives.read' => self::ARCHIVESREAD(), diff --git a/src/Appwrite/Models/BillingLimits.php b/src/Appwrite/Models/BillingLimits.php index 8f95f73..f80a744 100644 --- a/src/Appwrite/Models/BillingLimits.php +++ b/src/Appwrite/Models/BillingLimits.php @@ -12,24 +12,24 @@ /** * BillingLimits constructor. * - * @param int $bandwidth bandwidth limit - * @param int $storage storage limit - * @param int $users users limit - * @param int $executions executions limit - * @param int $gBHours gbhours limit - * @param int $imageTransformations image transformations limit - * @param int $authPhone auth phone limit - * @param int $budgetLimit budget limit percentage + * @param int|null $bandwidth bandwidth limit + * @param int|null $storage storage limit + * @param int|null $users users limit + * @param int|null $executions executions limit + * @param int|null $gBHours gbhours limit + * @param int|null $imageTransformations image transformations limit + * @param int|null $authPhone auth phone limit + * @param int|null $budgetLimit budget limit percentage */ public function __construct( - public int $bandwidth, - public int $storage, - public int $users, - public int $executions, - public int $gBHours, - public int $imageTransformations, - public int $authPhone, - public int $budgetLimit + public ?int $bandwidth = null, + public ?int $storage = null, + public ?int $users = null, + public ?int $executions = null, + public ?int $gBHours = null, + public ?int $imageTransformations = null, + public ?int $authPhone = null, + public ?int $budgetLimit = null ) { } @@ -38,40 +38,16 @@ public function __construct( */ public static function from(array $data): static { - if (!array_key_exists('bandwidth', $data)) { - throw new \InvalidArgumentException('Missing required field "bandwidth" for ' . static::class . '.'); - } - if (!array_key_exists('storage', $data)) { - throw new \InvalidArgumentException('Missing required field "storage" for ' . static::class . '.'); - } - if (!array_key_exists('users', $data)) { - throw new \InvalidArgumentException('Missing required field "users" for ' . static::class . '.'); - } - if (!array_key_exists('executions', $data)) { - throw new \InvalidArgumentException('Missing required field "executions" for ' . static::class . '.'); - } - if (!array_key_exists('GBHours', $data)) { - throw new \InvalidArgumentException('Missing required field "GBHours" for ' . static::class . '.'); - } - if (!array_key_exists('imageTransformations', $data)) { - throw new \InvalidArgumentException('Missing required field "imageTransformations" for ' . static::class . '.'); - } - if (!array_key_exists('authPhone', $data)) { - throw new \InvalidArgumentException('Missing required field "authPhone" for ' . static::class . '.'); - } - if (!array_key_exists('budgetLimit', $data)) { - throw new \InvalidArgumentException('Missing required field "budgetLimit" for ' . static::class . '.'); - } return new static( - bandwidth: $data['bandwidth'], - storage: $data['storage'], - users: $data['users'], - executions: $data['executions'], - gBHours: $data['GBHours'], - imageTransformations: $data['imageTransformations'], - authPhone: $data['authPhone'], - budgetLimit: $data['budgetLimit'] + bandwidth: array_key_exists('bandwidth', $data) ? $data['bandwidth'] : null, + storage: array_key_exists('storage', $data) ? $data['storage'] : null, + users: array_key_exists('users', $data) ? $data['users'] : null, + executions: array_key_exists('executions', $data) ? $data['executions'] : null, + gBHours: array_key_exists('GBHours', $data) ? $data['GBHours'] : null, + imageTransformations: array_key_exists('imageTransformations', $data) ? $data['imageTransformations'] : null, + authPhone: array_key_exists('authPhone', $data) ? $data['authPhone'] : null, + budgetLimit: array_key_exists('budgetLimit', $data) ? $data['budgetLimit'] : null ); } diff --git a/src/Appwrite/Models/Presence.php b/src/Appwrite/Models/Presence.php deleted file mode 100644 index 774127b..0000000 --- a/src/Appwrite/Models/Presence.php +++ /dev/null @@ -1,113 +0,0 @@ - $metadata Additional properties. - */ - public function __construct( - public string $id, - public string $createdAt, - public string $updatedAt, - public array $permissions, - public string $userId, - public string $source, - public ?string $status = null, - public ?string $expiresAt = null, - public array $metadata = [] - ) { - } - - /** - * @param array $data - */ - public static function from(array $data): static - { - if (!array_key_exists('$id', $data)) { - throw new \InvalidArgumentException('Missing required field "$id" for ' . static::class . '.'); - } - if (!array_key_exists('$createdAt', $data)) { - throw new \InvalidArgumentException('Missing required field "$createdAt" for ' . static::class . '.'); - } - if (!array_key_exists('$updatedAt', $data)) { - throw new \InvalidArgumentException('Missing required field "$updatedAt" for ' . static::class . '.'); - } - if (!array_key_exists('$permissions', $data)) { - throw new \InvalidArgumentException('Missing required field "$permissions" for ' . static::class . '.'); - } - if (!array_key_exists('userId', $data)) { - throw new \InvalidArgumentException('Missing required field "userId" for ' . static::class . '.'); - } - if (!array_key_exists('source', $data)) { - throw new \InvalidArgumentException('Missing required field "source" for ' . static::class . '.'); - } - - $additionalProperties = static::extractAdditionalPropertiesFromFields( - $data, - [ - '$id', - '$createdAt', - '$updatedAt', - '$permissions', - 'userId', - 'status', - 'source', - 'expiresAt' - ] - ); - - return new static( - id: $data['$id'], - createdAt: $data['$createdAt'], - updatedAt: $data['$updatedAt'], - permissions: $data['$permissions'], - userId: $data['userId'], - source: $data['source'], - status: array_key_exists('status', $data) ? $data['status'] : null, - expiresAt: array_key_exists('expiresAt', $data) ? $data['expiresAt'] : null, - metadata: $additionalProperties - ); - } - - /** - * @return array - */ - public function toArray(): array - { - $result = [ - '$id' => static::serializeValue($this->id), - '$createdAt' => static::serializeValue($this->createdAt), - '$updatedAt' => static::serializeValue($this->updatedAt), - '$permissions' => static::serializeValue($this->permissions), - 'userId' => static::serializeValue($this->userId), - 'status' => static::serializeValue($this->status), - 'source' => static::serializeValue($this->source), - 'expiresAt' => static::serializeValue($this->expiresAt) - ]; - - foreach (static::serializeAdditionalProperties($this->metadata) as $field => $value) { - $result[$field] = $value; - } - - return $result; - } -} diff --git a/src/Appwrite/Models/PresenceList.php b/src/Appwrite/Models/PresenceList.php deleted file mode 100644 index ef67350..0000000 --- a/src/Appwrite/Models/PresenceList.php +++ /dev/null @@ -1,59 +0,0 @@ - $presences list of presences. - */ - public function __construct( - public int $total, - public array $presences - ) { - } - - /** - * @param array $data - */ - public static function from(array $data): static - { - if (!array_key_exists('total', $data)) { - throw new \InvalidArgumentException('Missing required field "total" for ' . static::class . '.'); - } - if (!array_key_exists('presences', $data)) { - throw new \InvalidArgumentException('Missing required field "presences" for ' . static::class . '.'); - } - - return new static( - total: $data['total'], - presences: is_array($data['presences']) - ? array_map( - static fn (mixed $item): mixed => static::hydrateTypedValue(Presence::class, $item), - $data['presences'] - ) - : $data['presences'] - ); - } - - /** - * @return array - */ - public function toArray(): array - { - $result = [ - 'total' => static::serializeValue($this->total), - 'presences' => static::serializeValue($this->presences) - ]; - - return $result; - } -} diff --git a/src/Appwrite/Models/Project.php b/src/Appwrite/Models/Project.php index cdcb986..0b31c9b 100644 --- a/src/Appwrite/Models/Project.php +++ b/src/Appwrite/Models/Project.php @@ -36,9 +36,9 @@ * @param list $services list of services. * @param list $protocols list of protocols. * @param string $region project region - * @param BillingLimits $billingLimits billing limits reached * @param list $blocks project blocks information * @param string $consoleAccessedAt last time the project was accessed via console. used with plan's projectinactivitydays to determine if project is paused. + * @param BillingLimits|null $billingLimits billing limits reached */ public function __construct( public string $id, @@ -65,9 +65,9 @@ public function __construct( public array $services, public array $protocols, public string $region, - public BillingLimits $billingLimits, public array $blocks, - public string $consoleAccessedAt + public string $consoleAccessedAt, + public ?BillingLimits $billingLimits = null ) { } @@ -148,9 +148,6 @@ public static function from(array $data): static if (!array_key_exists('region', $data)) { throw new \InvalidArgumentException('Missing required field "region" for ' . static::class . '.'); } - if (!array_key_exists('billingLimits', $data)) { - throw new \InvalidArgumentException('Missing required field "billingLimits" for ' . static::class . '.'); - } if (!array_key_exists('blocks', $data)) { throw new \InvalidArgumentException('Missing required field "blocks" for ' . static::class . '.'); } @@ -203,14 +200,14 @@ public static function from(array $data): static ) : $data['protocols'], region: $data['region'], - billingLimits: static::hydrateTypedValue(BillingLimits::class, $data['billingLimits']), blocks: is_array($data['blocks']) ? array_map( static fn (mixed $item): mixed => static::hydrateTypedValue(Block::class, $item), $data['blocks'] ) : $data['blocks'], - consoleAccessedAt: $data['consoleAccessedAt'] + consoleAccessedAt: $data['consoleAccessedAt'], + billingLimits: array_key_exists('billingLimits', $data) ? static::hydrateTypedValue(BillingLimits::class, $data['billingLimits'], true) : null ); } diff --git a/src/Appwrite/Services/Presences.php b/src/Appwrite/Services/Presences.php deleted file mode 100644 index 78e4306..0000000 --- a/src/Appwrite/Services/Presences.php +++ /dev/null @@ -1,256 +0,0 @@ -client->call( - Client::METHOD_GET, - $apiPath, - $apiHeaders, - $apiParams - ); - - if (!is_array($response)) { - throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); - } - - return \Appwrite\Models\PresenceList::from($response); - - } - - /** - * Get a presence log by its unique ID. Entries whose `expiresAt` is in the - * past are treated as not found. - * - * - * @param string $presenceId - * @throws AppwriteException - * @return \Appwrite\Models\Presence - */ - public function get(string $presenceId): \Appwrite\Models\Presence - { - $apiPath = str_replace( - ['{presenceId}'], - [$presenceId], - '/presences/{presenceId}' - ); - - $apiParams = []; - $apiParams['presenceId'] = $presenceId; - - $apiHeaders = []; - - $response = $this->client->call( - Client::METHOD_GET, - $apiPath, - $apiHeaders, - $apiParams - ); - - if (!is_array($response)) { - throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); - } - - return \Appwrite\Models\Presence::from($response); - - } - - /** - * Create or update a presence log by its user ID. - * - * - * @param string $presenceId - * @param string $userId - * @param string $status - * @param ?array $permissions - * @param ?string $expiresAt - * @param ?array $metadata - * @throws AppwriteException - * @return \Appwrite\Models\Presence - */ - public function upsert(string $presenceId, string $userId, string $status, ?array $permissions = null, ?string $expiresAt = null, ?array $metadata = null): \Appwrite\Models\Presence - { - $apiPath = str_replace( - ['{presenceId}'], - [$presenceId], - '/presences/{presenceId}' - ); - - $apiParams = []; - $apiParams['presenceId'] = $presenceId; - $apiParams['userId'] = $userId; - $apiParams['status'] = $status; - - if (!is_null($permissions)) { - $apiParams['permissions'] = $permissions; - } - - if (!is_null($expiresAt)) { - $apiParams['expiresAt'] = $expiresAt; - } - - if (!is_null($metadata)) { - $apiParams['metadata'] = $metadata; - } - - $apiHeaders = []; - $apiHeaders['content-type'] = 'application/json'; - - $response = $this->client->call( - Client::METHOD_PUT, - $apiPath, - $apiHeaders, - $apiParams - ); - - if (!is_array($response)) { - throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); - } - - return \Appwrite\Models\Presence::from($response); - - } - - /** - * Update a presence log by its unique ID. Using the patch method you can pass - * only specific fields that will get updated. - * - * - * @param string $presenceId - * @param string $userId - * @param ?string $status - * @param ?string $expiresAt - * @param ?array $metadata - * @param ?array $permissions - * @param ?bool $purge - * @throws AppwriteException - * @return \Appwrite\Models\Presence - */ - public function updatePresence(string $presenceId, string $userId, ?string $status = null, ?string $expiresAt = null, ?array $metadata = null, ?array $permissions = null, ?bool $purge = null): \Appwrite\Models\Presence - { - $apiPath = str_replace( - ['{presenceId}'], - [$presenceId], - '/presences/{presenceId}' - ); - - $apiParams = []; - $apiParams['presenceId'] = $presenceId; - $apiParams['userId'] = $userId; - - if (!is_null($status)) { - $apiParams['status'] = $status; - } - - if (!is_null($expiresAt)) { - $apiParams['expiresAt'] = $expiresAt; - } - - if (!is_null($metadata)) { - $apiParams['metadata'] = $metadata; - } - - if (!is_null($permissions)) { - $apiParams['permissions'] = $permissions; - } - - if (!is_null($purge)) { - $apiParams['purge'] = $purge; - } - - $apiHeaders = []; - $apiHeaders['content-type'] = 'application/json'; - - $response = $this->client->call( - Client::METHOD_PATCH, - $apiPath, - $apiHeaders, - $apiParams - ); - - if (!is_array($response)) { - throw new \UnexpectedValueException('Expected array response when hydrating a response model.'); - } - - return \Appwrite\Models\Presence::from($response); - - } - - /** - * Delete a presence log by its unique ID. - * - * - * @param string $presenceId - * @throws AppwriteException - * @return string - */ - public function delete(string $presenceId): string - { - $apiPath = str_replace( - ['{presenceId}'], - [$presenceId], - '/presences/{presenceId}' - ); - - $apiParams = []; - $apiParams['presenceId'] = $presenceId; - - $apiHeaders = []; - $apiHeaders['content-type'] = 'application/json'; - - $response = $this->client->call( - Client::METHOD_DELETE, - $apiPath, - $apiHeaders, - $apiParams - ); - - return $response; - - } -} diff --git a/tests/Appwrite/Services/PresencesTest.php b/tests/Appwrite/Services/PresencesTest.php deleted file mode 100644 index 28201ac..0000000 --- a/tests/Appwrite/Services/PresencesTest.php +++ /dev/null @@ -1,130 +0,0 @@ -client = Mockery::mock(Client::class); - $this->presences = new Presences($this->client); - } - - public function testMethodList(): void - { - $data = array( - "total" => 5, - "presences" => array( - array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "\$permissions" => array(), - "userId" => "674af8f3e12a5f9ac0be", - "source" => "HTTP" - ) - ) - ); - - $this->client - ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) - ->andReturn($data); - - $response = $this->presences->list(); - - $this->assertInstanceOf(\Appwrite\Models\PresenceList::class, $response); - } - - public function testMethodGet(): void - { - $data = array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "\$permissions" => array(), - "userId" => "674af8f3e12a5f9ac0be", - "source" => "HTTP" - ); - - $this->client - ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) - ->andReturn($data); - - $response = $this->presences->get( - "" - ); - - $this->assertInstanceOf(\Appwrite\Models\Presence::class, $response); - } - - public function testMethodUpsert(): void - { - $data = array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "\$permissions" => array(), - "userId" => "674af8f3e12a5f9ac0be", - "source" => "HTTP" - ); - - $this->client - ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) - ->andReturn($data); - - $response = $this->presences->upsert( - "", - "", - "" - ); - - $this->assertInstanceOf(\Appwrite\Models\Presence::class, $response); - } - - public function testMethodUpdatePresence(): void - { - $data = array( - "\$id" => "5e5ea5c16897e", - "\$createdAt" => "2020-10-15T06:38:00.000+00:00", - "\$updatedAt" => "2020-10-15T06:38:00.000+00:00", - "\$permissions" => array(), - "userId" => "674af8f3e12a5f9ac0be", - "source" => "HTTP" - ); - - $this->client - ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) - ->andReturn($data); - - $response = $this->presences->updatePresence( - "", - "" - ); - - $this->assertInstanceOf(\Appwrite\Models\Presence::class, $response); - } - - public function testMethodDelete(): void - { - $data = ''; - - $this->client - ->allows()->call(Mockery::any(), Mockery::any(), Mockery::any(), Mockery::any()) - ->andReturn($data); - - $response = $this->presences->delete( - "" - ); - - $this->assertSame($data, $response); - } - -} diff --git a/tests/Appwrite/Services/ProjectTest.php b/tests/Appwrite/Services/ProjectTest.php index 81180fb..315e4c8 100644 --- a/tests/Appwrite/Services/ProjectTest.php +++ b/tests/Appwrite/Services/ProjectTest.php @@ -81,16 +81,6 @@ public function testMethodGet(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -181,16 +171,6 @@ public function testMethodUpdateAuthMethod(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -419,16 +399,6 @@ public function testMethodUpdateLabels(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -907,7 +877,7 @@ public function testMethodUpdateOAuth2Google(): void "\$id" => "github", "enabled" => true, "clientId" => "120000000095-92ifjb00000000000000000000g7ijfb.apps.googleusercontent.com", - "clientSecret" => "example-google-client-secret", + "clientSecret" => "GOCSPX-2k8gsR0000000000000000VNahJj", "prompt" => array() ); @@ -964,7 +934,7 @@ public function testMethodUpdateOAuth2Linkedin(): void "\$id" => "github", "enabled" => true, "clientId" => "770000000000dv", - "primaryClientSecret" => "example-linkedin-client-secret" + "primaryClientSecret" => "WPL_AP1.2Bf0000000000000./HtlYw==" ); $this->client @@ -1736,16 +1706,6 @@ public function testMethodUpdateDenyAliasedEmailPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -1825,16 +1785,6 @@ public function testMethodUpdateDenyDisposableEmailPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -1914,16 +1864,6 @@ public function testMethodUpdateDenyFreeEmailPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2003,16 +1943,6 @@ public function testMethodUpdateMembershipPrivacyPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2090,16 +2020,6 @@ public function testMethodUpdatePasswordDictionaryPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2179,16 +2099,6 @@ public function testMethodUpdatePasswordHistoryPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2268,16 +2178,6 @@ public function testMethodUpdatePasswordPersonalDataPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2357,16 +2257,6 @@ public function testMethodUpdateSessionAlertPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2446,16 +2336,6 @@ public function testMethodUpdateSessionDurationPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2535,16 +2415,6 @@ public function testMethodUpdateSessionInvalidationPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2624,16 +2494,6 @@ public function testMethodUpdateSessionLimitPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2713,16 +2573,6 @@ public function testMethodUpdateUserLimitPolicy(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2829,16 +2679,6 @@ public function testMethodUpdateProtocol(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -2919,16 +2759,6 @@ public function testMethodUpdateService(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", @@ -3009,16 +2839,6 @@ public function testMethodUpdateSMTP(): void ) ), "region" => "fra", - "billingLimits" => array( - "bandwidth" => 5, - "storage" => 150, - "users" => 200000, - "executions" => 750000, - "GBHours" => 100, - "imageTransformations" => 100, - "authPhone" => 10, - "budgetLimit" => 100 - ), "blocks" => array( array( "\$createdAt" => "2020-10-15T06:38:00.000+00:00", From ee6aa0572cd62b69de08ecf53887b62d54b35aa4 Mon Sep 17 00:00:00 2001 From: Prem Palanisamy Date: Wed, 20 May 2026 07:12:01 +0100 Subject: [PATCH 2/2] chore: bump version to 24.0.1 and add changelog --- CHANGELOG.md | 22 ++++++++++++++++++++++ src/Appwrite/Client.php | 4 ++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a8f8c9..550ccb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Change Log +## 24.0.1 + +* Fixed: `Project.billingLimits` now hydrates as `?BillingLimits` (nullable) — server emits `billingLimits: {}` for projects with no usage limits crossed, which previously threw `InvalidArgumentException: Missing required field "bandwidth"` on every `Project` response parse +* Fixed: All 8 `BillingLimits` inner fields (`bandwidth`, `storage`, `users`, `executions`, `GBHours`, `imageTransformations`, `authPhone`, `budgetLimit`) now hydrate as `?int` — match the runtime "sparse map of limits crossed" semantics +* Fixed: `Project.consoleAccessedAt` no longer null at runtime — server now emits empty string for never-accessed projects, matching the OSS `pingedAt` convention + +## 24.0.0 + +* Breaking: Renamed `AuthMethod` enum to `ProjectAuthMethodId` +* Breaking: Renamed `EmailTemplateType` to `ProjectEmailTemplateId` and `EmailTemplateLocale` to `ProjectEmailTemplateLocale` +* Breaking: Renamed `ServiceId` to `ProjectServiceId`, `ProtocolId` to `ProjectProtocolId`, `Secure` to `ProjectSMTPSecure`, `ProjectPolicy` to `ProjectPolicyId` +* Breaking: Replaced `Scopes` enum with `ProjectKeyScopes` for project key endpoints +* Breaking: Removed `updateDenyCanonicalEmailPolicy`; replaced with `updateDenyAliasedEmailPolicy`, `updateDenyDisposableEmailPolicy`, and `updateDenyFreeEmailPolicy` +* Breaking: Removed `AuthProvider` model; use new `ProjectOAuthProviderId` enum instead +* Added: `Project::get` method to fetch current project details +* Added: `Advisor`, `Presences`, and `Usage` services +* Added: `Insight`, `Presence`, `Report`, `UsageEvent`, and `UsageGauge` models with list variants +* Added: `ProjectAuthMethod`, `ProjectProtocol`, and `ProjectService` models +* Added: `ProjectOAuthProviderId` and `ProjectOAuth2GooglePrompt` enums +* Updated: `Project`, `Database`, and `OAuth2Google` model schemas +* Updated: `X-Appwrite-Response-Format` header to `1.9.5` + ## 23.1.1 * Fixed: `Database` model `policies` and `archives` now hydrate as `BackupPolicy` / `BackupArchive` instead of `Index` / `Collection` diff --git a/src/Appwrite/Client.php b/src/Appwrite/Client.php index 56b39bb..4c3158b 100644 --- a/src/Appwrite/Client.php +++ b/src/Appwrite/Client.php @@ -37,11 +37,11 @@ class Client */ protected array $headers = [ 'content-type' => '', - 'user-agent' => 'AppwritePHPSDK/23.1.1 ()', + 'user-agent' => 'AppwritePHPSDK/24.0.1 ()', 'x-sdk-name'=> 'PHP', 'x-sdk-platform'=> 'server', 'x-sdk-language'=> 'php', - 'x-sdk-version'=> '23.1.1', + 'x-sdk-version'=> '24.0.1', ]; /**