From 39943f2219006418a41118f97b1d28f9233f72f3 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Fri, 6 Mar 2026 15:46:46 +0100 Subject: [PATCH 1/3] docs: add migration guide for stream-chat-php --- README.md | 4 + .../01-setup-and-auth.md | 178 ++++++ .../02-users.md | 409 +++++++++++++ .../03-channels.md | 545 ++++++++++++++++++ .../04-messages-and-reactions.md | 397 +++++++++++++ .../05-moderation.md | 403 +++++++++++++ .../06-devices.md | 140 +++++ docs/migration-from-stream-chat-php/README.md | 91 +++ 8 files changed, 2167 insertions(+) create mode 100644 docs/migration-from-stream-chat-php/01-setup-and-auth.md create mode 100644 docs/migration-from-stream-chat-php/02-users.md create mode 100644 docs/migration-from-stream-chat-php/03-channels.md create mode 100644 docs/migration-from-stream-chat-php/04-messages-and-reactions.md create mode 100644 docs/migration-from-stream-chat-php/05-moderation.md create mode 100644 docs/migration-from-stream-chat-php/06-devices.md create mode 100644 docs/migration-from-stream-chat-php/README.md diff --git a/README.md b/README.md index 0bb52170..75522b27 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,10 @@ Install via Composer: composer require getstream/getstream-php ``` +## Migrating from stream-chat-php? + +If you are currently using [`stream-chat-php`](https://github.com/GetStream/stream-chat-php), we have a detailed migration guide with side-by-side code examples for common Chat use cases. See the [Migration Guide](docs/migration-from-stream-chat-php/README.md). + ## Configuration Copy `.env.example` to `.env` and configure: diff --git a/docs/migration-from-stream-chat-php/01-setup-and-auth.md b/docs/migration-from-stream-chat-php/01-setup-and-auth.md new file mode 100644 index 00000000..0c1f63de --- /dev/null +++ b/docs/migration-from-stream-chat-php/01-setup-and-auth.md @@ -0,0 +1,178 @@ +# Setup and Authentication + +This guide covers migrating client setup, configuration, and token generation from `stream-chat-php` to `getstream-php`. + +## Installation + +**Before (stream-chat-php):** + +```bash +composer require get-stream/stream-chat +``` + +**After (getstream-php):** + +```bash +composer require getstream/getstream-php +``` + +## Client Instantiation + +### Direct Constructor + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// With optional timeout (seconds) +$client = new Client("", "", timeout: 5.0); +``` + +**After (getstream-php):** + +```php +use GetStream\Client; + +$client = new Client( + apiKey: "", + apiSecret: "", +); + +// With optional base URL or custom HTTP client +$client = new Client( + apiKey: "", + apiSecret: "", + baseUrl: "https://chat.stream-io-api.com", +); +``` + +### ClientBuilder (New) + +The new SDK introduces a `ClientBuilder` with a fluent interface. This pattern has no equivalent in the old SDK. + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +// Build from environment variables (STREAM_API_KEY, STREAM_API_SECRET, STREAM_BASE_URL) +$client = ClientBuilder::fromEnv()->build(); + +// Build from a custom .env file path +$client = ClientBuilder::fromEnv('/path/to/.env')->build(); + +// Mix environment and explicit values +$client = ClientBuilder::fromEnv() + ->apiKey("") + ->apiSecret("") + ->baseUrl("") + ->build(); + +// Skip .env file loading entirely +$client = ClientBuilder::fromEnv() + ->skipEnvLoad() + ->apiKey("") + ->apiSecret("") + ->build(); +``` + +### Environment Variables + +The environment variable names have changed: + +| Purpose | stream-chat-php | getstream-php | +|---------|-----------------|---------------| +| API Key | `STREAM_KEY` | `STREAM_API_KEY` | +| API Secret | `STREAM_SECRET` | `STREAM_API_SECRET` | +| Base URL | `STREAM_CHAT_URL`, `STREAM_BASE_CHAT_URL`, or `STREAM_BASE_URL` | `STREAM_BASE_URL` | +| Timeout | `STREAM_CHAT_TIMEOUT` | _(configure via HTTP client)_ | + +## Namespace Changes + +Update your `use` statements: + +| Purpose | stream-chat-php | getstream-php | +|---------|-----------------|---------------| +| Client | `GetStream\StreamChat\Client` | `GetStream\Client` | +| Chat Client | _(same class)_ | `GetStream\ChatClient` | +| Builder | _(none)_ | `GetStream\ClientBuilder` | + +`ChatClient` extends `Client` and adds all chat-specific methods via `ChatTrait`. For chat operations, you can use either `Client` or `ChatClient` directly. + +## User Token Generation + +### Token Without Expiration + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); +$token = $client->createToken("user-id-123"); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +$client = ClientBuilder::fromEnv()->build(); +$token = $client->createUserToken("user-id-123"); +``` + +### Token With Expiration + +The expiration parameter changed from an absolute Unix timestamp to a relative duration in seconds. + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// Expiration is an absolute Unix timestamp +$expiration = time() + 3600; // 1 hour from now +$token = $client->createToken("user-id-123", $expiration); + +// With both expiration and issued-at +$issuedAt = time(); +$expiration = $issuedAt + 3600; +$token = $client->createToken("user-id-123", $expiration, $issuedAt); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +$client = ClientBuilder::fromEnv()->build(); + +// Expiration is a duration in seconds (relative, not absolute) +$token = $client->createUserToken( + userId: "user-id-123", + expiration: 3600, // expires 1 hour from now +); + +// With additional custom claims +$token = $client->createUserToken( + userId: "user-id-123", + claims: ['role' => 'admin'], + expiration: 3600, +); +``` + +> **Important:** In `stream-chat-php`, `createToken()` expects an absolute Unix timestamp for expiration. In `getstream-php`, `createUserToken()` expects a duration in seconds. If you are computing `time() + 3600` in your old code, simply pass `3600` to the new SDK. + +## Summary of Method Changes + +| Operation | stream-chat-php | getstream-php | +|-----------|-----------------|---------------| +| Create client | `new Client($key, $secret)` | `new Client(apiKey: $key, apiSecret: $secret)` or `ClientBuilder::fromEnv()->build()` | +| Generate user token | `$client->createToken($userId)` | `$client->createUserToken($userId)` | +| Token with expiry | `$client->createToken($userId, time() + 3600)` | `$client->createUserToken($userId, expiration: 3600)` | +| Token with claims | _(not supported)_ | `$client->createUserToken($userId, claims: [...])` | diff --git a/docs/migration-from-stream-chat-php/02-users.md b/docs/migration-from-stream-chat-php/02-users.md new file mode 100644 index 00000000..5d779ea1 --- /dev/null +++ b/docs/migration-from-stream-chat-php/02-users.md @@ -0,0 +1,409 @@ +# Users + +This guide covers migrating user management operations from `stream-chat-php` to `getstream-php`. + +> All `getstream-php` examples assume the client is already instantiated. See [01-setup-and-auth.md](./01-setup-and-auth.md) for client setup. + +## Upsert a Single User + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->upsertUser([ + 'id' => 'user-123', + 'name' => 'John Doe', + 'role' => 'admin', + 'custom_field' => 'value', +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateUsers(new GeneratedModels\UpdateUsersRequest( + users: [ + 'user-123' => new GeneratedModels\UserRequest( + id: 'user-123', + name: 'John Doe', + role: 'admin', + custom: (object) ['custom_field' => 'value'], + ), + ], +)); + +$user = $response->getData()->users['user-123']; +``` + +**Key differences:** + +- The old SDK accepts a flat associative array. The new SDK uses typed `UserRequest` model objects. +- Custom fields are placed in the `custom` property (cast to `object`) instead of being mixed into the top-level array. +- The `users` parameter is keyed by user ID. +- There is no dedicated `upsertUser()` method in the new SDK. Use `updateUsers()` with a single entry. + +## Batch Upsert Users + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->upsertUsers([ + ['id' => 'user-1', 'name' => 'Alice'], + ['id' => 'user-2', 'name' => 'Bob'], +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateUsers(new GeneratedModels\UpdateUsersRequest( + users: [ + 'user-1' => new GeneratedModels\UserRequest( + id: 'user-1', + name: 'Alice', + ), + 'user-2' => new GeneratedModels\UserRequest( + id: 'user-2', + name: 'Bob', + ), + ], +)); + +$users = $response->getData()->users; +``` + +**Key differences:** + +- The old SDK takes a plain array of user arrays and indexes them by ID internally. The new SDK requires you to key the array by user ID yourself. + +## Query Users + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// Query by ID +$response = $client->queryUsers( + ['id' => ['$in' => ['user-1', 'user-2']]], +); + +// With sort and pagination +$response = $client->queryUsers( + ['role' => 'admin'], + ['last_active' => -1], // sort descending + ['limit' => 10, 'offset' => 0], +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +// Query by ID +$response = $client->queryUsers(new GeneratedModels\QueryUsersPayload( + filterConditions: (object) [ + 'id' => (object) ['$in' => ['user-1', 'user-2']], + ], +)); + +// With sort and pagination +$response = $client->queryUsers(new GeneratedModels\QueryUsersPayload( + filterConditions: (object) ['role' => (object) ['$eq' => 'admin']], + sort: [ + new GeneratedModels\SortParamRequest( + field: 'last_active', + direction: -1, + ), + ], + limit: 10, + offset: 0, +)); + +$users = $response->getData()->users; +``` + +**Key differences:** + +- Filter conditions must be cast to `(object)`. The old SDK accepts plain associative arrays. +- Sort is now an array of `SortParamRequest` objects instead of an associative array. +- Pagination options (`limit`, `offset`) are named parameters on the payload instead of a separate `$options` array. +- To include deactivated users, pass `includeDeactivatedUsers: true` on the payload. + +## Partial Update Users + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// Set and unset fields +$response = $client->partialUpdateUser([ + 'id' => 'user-123', + 'set' => ['name' => 'Jane Doe', 'country' => 'NL'], + 'unset' => ['custom_field'], +]); + +// Batch partial update +$response = $client->partialUpdateUsers([ + [ + 'id' => 'user-1', + 'set' => ['role' => 'admin'], + ], + [ + 'id' => 'user-2', + 'set' => ['role' => 'user'], + ], +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +// Set and unset fields +$response = $client->updateUsersPartial(new GeneratedModels\UpdateUsersPartialRequest( + users: [ + new GeneratedModels\UpdateUserPartialRequest( + id: 'user-123', + set: (object) ['name' => 'Jane Doe', 'country' => 'NL'], + unset: ['custom_field'], + ), + ], +)); + +// Batch partial update +$response = $client->updateUsersPartial(new GeneratedModels\UpdateUsersPartialRequest( + users: [ + new GeneratedModels\UpdateUserPartialRequest( + id: 'user-1', + set: (object) ['role' => 'admin'], + ), + new GeneratedModels\UpdateUserPartialRequest( + id: 'user-2', + set: (object) ['role' => 'user'], + ), + ], +)); +``` + +**Key differences:** + +- Method renamed from `partialUpdateUser()` / `partialUpdateUsers()` to `updateUsersPartial()`. +- The `set` property must be cast to `(object)`. +- Both single and batch updates use the same `updateUsersPartial()` method with an array of `UpdateUserPartialRequest` objects. + +## Deactivate and Reactivate Users + +### Single User + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// Deactivate +$response = $client->deactivateUser('user-123', [ + 'mark_messages_deleted' => true, + 'created_by_id' => 'admin-user', +]); + +// Reactivate +$response = $client->reactivateUser('user-123', [ + 'restore_messages' => true, + 'created_by_id' => 'admin-user', +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +// Deactivate +$response = $client->deactivateUser('user-123', new GeneratedModels\DeactivateUserRequest( + markMessagesDeleted: true, + createdByID: 'admin-user', +)); + +// Reactivate +$response = $client->reactivateUser('user-123', new GeneratedModels\ReactivateUserRequest( + restoreMessages: true, + createdByID: 'admin-user', +)); +``` + +### Batch (Async) + +Both SDKs support batch deactivation/reactivation as asynchronous operations that return a task ID. + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// Batch deactivate +$response = $client->deactivateUsers(['user-1', 'user-2'], [ + 'mark_messages_deleted' => true, + 'created_by_id' => 'admin-user', +]); + +// Batch reactivate +$response = $client->reactivateUsers(['user-1', 'user-2'], [ + 'restore_messages' => true, + 'created_by_id' => 'admin-user', +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +// Batch deactivate +$response = $client->deactivateUsers(new GeneratedModels\DeactivateUsersRequest( + userIds: ['user-1', 'user-2'], + markMessagesDeleted: true, + createdByID: 'admin-user', +)); +$taskId = $response->getData()->taskID; + +// Batch reactivate +$response = $client->reactivateUsers(new GeneratedModels\ReactivateUsersRequest( + userIds: ['user-1', 'user-2'], + restoreMessages: true, + createdByID: 'admin-user', +)); +$taskId = $response->getData()->taskID; +``` + +**Key differences:** + +- Option keys changed from snake_case strings to camelCase named arguments (e.g. `mark_messages_deleted` becomes `markMessagesDeleted`). +- Options are passed as typed request objects instead of associative arrays. +- The method signatures are otherwise very similar between the two SDKs. + +## Delete Users + +### Single User (Sync) + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->deleteUser('user-123', [ + 'mark_messages_deleted' => true, +]); +``` + +**After (getstream-php):** + +The new SDK does not have a synchronous single-user delete. Use `deleteUsers()` with a single user ID instead: + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->deleteUsers(new GeneratedModels\DeleteUsersRequest( + userIds: ['user-123'], + user: 'soft', + messages: 'soft', +)); +$taskId = $response->getData()->taskID; +``` + +### Batch Delete (Async) + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->deleteUsers(['user-1', 'user-2'], [ + 'user' => 'hard', + 'messages' => 'hard', + 'conversations' => 'hard', +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->deleteUsers(new GeneratedModels\DeleteUsersRequest( + userIds: ['user-1', 'user-2'], + user: 'hard', + messages: 'hard', + conversations: 'hard', +)); +$taskId = $response->getData()->taskID; +``` + +**Key differences:** + +- The old SDK has both `deleteUser()` (sync, single user) and `deleteUsers()` (async, batch). The new SDK only has `deleteUsers()`, which is always async. +- Options are passed as named arguments on a typed request object instead of an associative array. + +## Summary of Method Changes + +| Operation | stream-chat-php | getstream-php | +|-----------|-----------------|---------------| +| Upsert user(s) | `$client->upsertUser($user)` / `$client->upsertUsers($users)` | `$client->updateUsers(new UpdateUsersRequest(...))` | +| Query users | `$client->queryUsers($filter, $sort, $options)` | `$client->queryUsers(new QueryUsersPayload(...))` | +| Partial update | `$client->partialUpdateUser($update)` / `$client->partialUpdateUsers($updates)` | `$client->updateUsersPartial(new UpdateUsersPartialRequest(...))` | +| Deactivate (single) | `$client->deactivateUser($id, $opts)` | `$client->deactivateUser($id, new DeactivateUserRequest(...))` | +| Deactivate (batch) | `$client->deactivateUsers($ids, $opts)` | `$client->deactivateUsers(new DeactivateUsersRequest(...))` | +| Reactivate (single) | `$client->reactivateUser($id, $opts)` | `$client->reactivateUser($id, new ReactivateUserRequest(...))` | +| Reactivate (batch) | `$client->reactivateUsers($ids, $opts)` | `$client->reactivateUsers(new ReactivateUsersRequest(...))` | +| Delete (single, sync) | `$client->deleteUser($id, $opts)` | _(use `deleteUsers()` with one ID)_ | +| Delete (batch, async) | `$client->deleteUsers($ids, $opts)` | `$client->deleteUsers(new DeleteUsersRequest(...))` | diff --git a/docs/migration-from-stream-chat-php/03-channels.md b/docs/migration-from-stream-chat-php/03-channels.md new file mode 100644 index 00000000..cab810f8 --- /dev/null +++ b/docs/migration-from-stream-chat-php/03-channels.md @@ -0,0 +1,545 @@ +# Channels + +This guide covers migrating channel operations from `stream-chat-php` to `getstream-php`. + +> All `getstream-php` examples assume the client is already instantiated. See [01-setup-and-auth.md](./01-setup-and-auth.md) for client setup. + +## Channel Type Creation + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->createChannelType([ + 'name' => 'support', + 'typing_events' => true, + 'read_events' => true, + 'connect_events' => true, + 'search' => true, + 'reactions' => true, + 'replies' => true, + 'mutes' => true, + 'commands' => ['all'], +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->createChannelType(new GeneratedModels\CreateChannelTypeRequest( + name: 'support', + typingEvents: true, + readEvents: true, + connectEvents: true, + search: true, + reactions: true, + replies: true, + mutes: true, + commands: ['all'], +)); +``` + +**Key differences:** + +- The old SDK accepts a flat associative array. The new SDK uses a typed `CreateChannelTypeRequest` with named arguments. +- Option keys change from snake_case strings to camelCase named arguments. +- The old SDK defaults `commands` to `['all']` if not provided. The new SDK does not auto-set this. + +## Listing Channel Types + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->listChannelTypes(); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->listChannelTypes(); +``` + +**Key differences:** + +- The method name and signature are identical. No changes needed. + +## Getting a Channel Type + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->getChannelType('support'); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->getChannelType('support'); +``` + +**Key differences:** + +- The method name and signature are identical. No changes needed. + +## Updating a Channel Type + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->updateChannelType('support', [ + 'typing_events' => false, + 'read_events' => true, + 'replies' => false, +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateChannelType('support', new GeneratedModels\UpdateChannelTypeRequest( + typingEvents: false, + readEvents: true, + replies: false, +)); +``` + +**Key differences:** + +- Settings change from a flat associative array to a typed `UpdateChannelTypeRequest` with named arguments. + +## Deleting a Channel Type + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->deleteChannelType('support'); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->deleteChannelType('support'); +``` + +**Key differences:** + +- The method name and signature are identical. No changes needed. + +## Creating a Channel with Members + +In the old SDK, you create a `Channel` object on the client and then call `create()` on it. In the new SDK, you call `getOrCreateChannel()` directly on the client. + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->create('admin-user', ['user-1', 'user-2']); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->getOrCreateChannel('messaging', 'general', new GeneratedModels\ChannelGetOrCreateRequest( + data: new GeneratedModels\ChannelInput( + createdByID: 'admin-user', + members: [ + new GeneratedModels\ChannelMemberRequest(userID: 'user-1'), + new GeneratedModels\ChannelMemberRequest(userID: 'user-2'), + ], + ), +)); +``` + +**Key differences:** + +- The old SDK uses a two-step pattern: `$client->Channel()` returns a `Channel` object, then `$channel->create()` creates it. The new SDK uses a single `getOrCreateChannel()` call. +- Members are `ChannelMemberRequest` objects (with optional `channelRole` and `custom` properties) instead of plain user ID strings. +- The creating user is specified via `createdByID` on `ChannelInput` rather than as the first argument to `create()`. + +### Creating a Distinct Channel (Without an ID) + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// Pass null as the channel ID to create a distinct channel based on members +$channel = $client->Channel('messaging', null, ['members' => ['user-1', 'user-2']]); +$response = $channel->create('user-1'); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +// Use getOrCreateDistinctChannel (no channel ID needed) +$response = $client->getOrCreateDistinctChannel('messaging', new GeneratedModels\ChannelGetOrCreateRequest( + data: new GeneratedModels\ChannelInput( + createdByID: 'user-1', + members: [ + new GeneratedModels\ChannelMemberRequest(userID: 'user-1'), + new GeneratedModels\ChannelMemberRequest(userID: 'user-2'), + ], + ), +)); +``` + +**Key differences:** + +- The old SDK passes `null` as the channel ID and includes members in the data array. The new SDK has a dedicated `getOrCreateDistinctChannel()` method that omits the channel ID parameter entirely. + +## Adding Members + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->addMembers(['user-3', 'user-4']); + +// With options (e.g. hide history) +$response = $channel->addMembers(['user-5'], [ + 'hide_history' => true, +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( + addMembers: [ + new GeneratedModels\ChannelMemberRequest(userID: 'user-3'), + new GeneratedModels\ChannelMemberRequest(userID: 'user-4'), + ], +)); + +// With options (e.g. hide history) +$response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( + addMembers: [ + new GeneratedModels\ChannelMemberRequest(userID: 'user-5'), + ], + hideHistory: true, +)); +``` + +**Key differences:** + +- The old SDK calls `addMembers()` on a `Channel` object with an array of user ID strings. The new SDK calls `updateChannel()` on the client with `addMembers` containing `ChannelMemberRequest` objects. +- Options like `hide_history` become named arguments on the `UpdateChannelRequest`. + +## Removing Members + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->removeMembers(['user-3', 'user-4']); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( + removeMembers: ['user-3', 'user-4'], +)); +``` + +**Key differences:** + +- The old SDK calls `removeMembers()` on a `Channel` object. The new SDK passes `removeMembers` as a named argument to `updateChannel()`. +- Unlike `addMembers`, `removeMembers` takes plain user ID strings in both SDKs. + +## Querying Channels + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// Basic query +$response = $client->queryChannels( + ['type' => 'messaging', 'members' => ['$in' => ['user-1']]], +); + +// With sort and pagination +$response = $client->queryChannels( + ['type' => 'messaging'], + ['last_message_at' => -1], + ['limit' => 10, 'offset' => 0], +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +// Basic query +$response = $client->queryChannels(new GeneratedModels\QueryChannelsRequest( + filterConditions: (object) [ + 'type' => 'messaging', + 'members' => (object) ['$in' => ['user-1']], + ], +)); + +// With sort and pagination +$response = $client->queryChannels(new GeneratedModels\QueryChannelsRequest( + filterConditions: (object) ['type' => 'messaging'], + sort: [ + new GeneratedModels\SortParamRequest( + field: 'last_message_at', + direction: -1, + ), + ], + limit: 10, + offset: 0, +)); + +$channels = $response->getData()->channels; +``` + +**Key differences:** + +- Filter conditions must be cast to `(object)`. The old SDK accepts plain associative arrays. +- Sort is now an array of `SortParamRequest` objects instead of an associative array. +- Pagination options (`limit`, `offset`) are named parameters on the request instead of a separate `$options` array. +- The old SDK auto-sets `state`, `watch`, and `presence` defaults. The new SDK leaves them as null unless explicitly provided. + +## Updating a Channel + +### Full Update + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->update( + ['name' => 'General Chat', 'image' => 'https://example.com/img.png'], + ['text' => 'Channel updated', 'user_id' => 'admin-user'], +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( + message: new GeneratedModels\MessageRequest( + text: 'Channel updated', + userID: 'admin-user', + ), +)); +``` + +> **Note:** In the new SDK, channel data fields like `name` and `image` are not set via `updateChannel()`. Use `updateChannelPartial()` (see below) to update individual channel properties, or pass a `data` parameter with a `ChannelInput` if a full overwrite is needed. + +### Partial Update + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->updatePartial( + ['name' => 'Updated Name', 'color' => 'blue'], // set + ['old_field'], // unset +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateChannelPartial('messaging', 'general', new GeneratedModels\UpdateChannelPartialRequest( + set: (object) ['name' => 'Updated Name', 'color' => 'blue'], + unset: ['old_field'], +)); +``` + +**Key differences:** + +- The old SDK calls `updatePartial()` on a `Channel` object with positional `$set` and `$unset` arrays. The new SDK calls `updateChannelPartial()` on the client with a typed request object. +- The `set` property must be cast to `(object)`. + +## Deleting Channels + +### Single Channel + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->delete(); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->deleteChannel('messaging', 'general', hardDelete: false); +``` + +**Key differences:** + +- The old SDK calls `delete()` on a `Channel` object. The new SDK calls `deleteChannel()` on the client with the channel type and ID as arguments. +- The new SDK requires an explicit `hardDelete` boolean parameter. + +### Batch Delete + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->deleteChannels(['messaging:general', 'messaging:support']); + +// Hard delete +$response = $client->deleteChannels( + ['messaging:general', 'messaging:support'], + ['hard_delete' => true], +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->deleteChannels(new GeneratedModels\DeleteChannelsRequest( + cids: ['messaging:general', 'messaging:support'], +)); + +// Hard delete +$response = $client->deleteChannels(new GeneratedModels\DeleteChannelsRequest( + cids: ['messaging:general', 'messaging:support'], + hardDelete: true, +)); +``` + +**Key differences:** + +- The old SDK takes a plain array of CIDs and an optional options array. The new SDK uses a typed `DeleteChannelsRequest` with named arguments. + +## Summary of Method Changes + +| Operation | stream-chat-php | getstream-php | +|-----------|-----------------|---------------| +| Create channel type | `$client->createChannelType($data)` | `$client->createChannelType(new CreateChannelTypeRequest(...))` | +| List channel types | `$client->listChannelTypes()` | `$client->listChannelTypes()` | +| Get channel type | `$client->getChannelType($name)` | `$client->getChannelType($name)` | +| Update channel type | `$client->updateChannelType($name, $settings)` | `$client->updateChannelType($name, new UpdateChannelTypeRequest(...))` | +| Delete channel type | `$client->deleteChannelType($name)` | `$client->deleteChannelType($name)` | +| Create channel | `$client->Channel($type, $id)->create($userId, $members)` | `$client->getOrCreateChannel($type, $id, new ChannelGetOrCreateRequest(...))` | +| Create distinct channel | `$client->Channel($type, null, $data)->create($userId)` | `$client->getOrCreateDistinctChannel($type, new ChannelGetOrCreateRequest(...))` | +| Add members | `$channel->addMembers($userIds)` | `$client->updateChannel($type, $id, new UpdateChannelRequest(addMembers: [...]))` | +| Remove members | `$channel->removeMembers($userIds)` | `$client->updateChannel($type, $id, new UpdateChannelRequest(removeMembers: [...]))` | +| Query channels | `$client->queryChannels($filter, $sort, $opts)` | `$client->queryChannels(new QueryChannelsRequest(...))` | +| Update channel | `$channel->update($data, $message)` | `$client->updateChannel($type, $id, new UpdateChannelRequest(...))` | +| Partial update channel | `$channel->updatePartial($set, $unset)` | `$client->updateChannelPartial($type, $id, new UpdateChannelPartialRequest(...))` | +| Delete channel | `$channel->delete()` | `$client->deleteChannel($type, $id, hardDelete: false)` | +| Batch delete channels | `$client->deleteChannels($cids, $opts)` | `$client->deleteChannels(new DeleteChannelsRequest(...))` | diff --git a/docs/migration-from-stream-chat-php/04-messages-and-reactions.md b/docs/migration-from-stream-chat-php/04-messages-and-reactions.md new file mode 100644 index 00000000..acb82c48 --- /dev/null +++ b/docs/migration-from-stream-chat-php/04-messages-and-reactions.md @@ -0,0 +1,397 @@ +# Messages and Reactions + +This guide covers migrating messaging and reaction operations from `stream-chat-php` to `getstream-php`. + +> All `getstream-php` examples assume the client is already instantiated. See [01-setup-and-auth.md](./01-setup-and-auth.md) for client setup. + +## Sending a Message + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->sendMessage( + ['text' => 'Hello, world!'], + 'user-1', +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->sendMessage('messaging', 'general', new GeneratedModels\SendMessageRequest( + message: new GeneratedModels\MessageRequest( + text: 'Hello, world!', + userID: 'user-1', + ), +)); +``` + +**Key differences:** + +- The old SDK calls `sendMessage()` on a `Channel` object, passing the user ID as a separate argument. The new SDK calls `sendMessage()` on the client with channel type and ID, wrapping the message in a typed `SendMessageRequest`. +- The user ID moves from a standalone parameter into the `MessageRequest` as `userID`. +- Message properties change from snake_case array keys to camelCase named arguments. + +## Sending a Message with Options + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->sendMessage( + [ + 'text' => 'Hello!', + 'custom_field' => 'value', + ], + 'user-1', + null, // parentId + ['skip_push' => true], +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->sendMessage('messaging', 'general', new GeneratedModels\SendMessageRequest( + message: new GeneratedModels\MessageRequest( + text: 'Hello!', + userID: 'user-1', + custom: (object) ['custom_field' => 'value'], + ), + skipPush: true, +)); +``` + +**Key differences:** + +- Options like `skip_push` become named arguments on `SendMessageRequest` instead of a separate options array. +- Custom fields go into the `custom` property (cast to `(object)`) on `MessageRequest`, rather than being mixed in with the top-level message array. + +## Replying to a Message (Threads) + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); + +// Reply in a thread +$response = $channel->sendMessage( + ['text' => 'This is a thread reply'], + 'user-1', + 'parent-message-id', +); + +// Reply in a thread and show in channel +$response = $channel->sendMessage( + ['text' => 'This reply also appears in the channel', 'show_in_channel' => true], + 'user-1', + 'parent-message-id', +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +// Reply in a thread +$response = $client->sendMessage('messaging', 'general', new GeneratedModels\SendMessageRequest( + message: new GeneratedModels\MessageRequest( + text: 'This is a thread reply', + userID: 'user-1', + parentID: 'parent-message-id', + ), +)); + +// Reply in a thread and show in channel +$response = $client->sendMessage('messaging', 'general', new GeneratedModels\SendMessageRequest( + message: new GeneratedModels\MessageRequest( + text: 'This reply also appears in the channel', + userID: 'user-1', + parentID: 'parent-message-id', + showInChannel: true, + ), +)); +``` + +**Key differences:** + +- The old SDK passes `parentId` as a separate third argument to `sendMessage()`. The new SDK sets `parentID` directly on the `MessageRequest`. +- `show_in_channel` moves from the message array into the typed `showInChannel` named argument on `MessageRequest`. + +## Getting a Message + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->getMessage('message-id-123'); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->getMessage('message-id-123', showDeletedMessage: false); +``` + +**Key differences:** + +- Both SDKs call `getMessage()` on the client. The new SDK adds a required `showDeletedMessage` boolean parameter. + +## Updating a Message + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->updateMessage([ + 'id' => 'message-id-123', + 'text' => 'Updated message text', + 'user_id' => 'user-1', +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateMessage('message-id-123', new GeneratedModels\UpdateMessageRequest( + message: new GeneratedModels\MessageRequest( + text: 'Updated message text', + userID: 'user-1', + ), +)); +``` + +**Key differences:** + +- The old SDK passes a flat array with the message `id` included in it. The new SDK passes the message ID as the first argument and the update data as a typed `UpdateMessageRequest`. +- The message ID is no longer part of the message body; it is a separate parameter. + +### Partial Update + +The new SDK also supports partial message updates, which the old SDK does not have as a dedicated method. + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateMessagePartial('message-id-123', new GeneratedModels\UpdateMessagePartialRequest( + set: (object) ['text' => 'Partially updated text', 'color' => 'blue'], + unset: ['old_field'], + userID: 'user-1', +)); +``` + +## Deleting a Message + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// Soft delete +$response = $client->deleteMessage('message-id-123'); + +// Hard delete +$response = $client->deleteMessage('message-id-123', ['hard' => true]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +$client = ClientBuilder::fromEnv()->build(); + +// Soft delete +$response = $client->deleteMessage('message-id-123', hard: false, deletedBy: '', deleteForMe: false); + +// Hard delete +$response = $client->deleteMessage('message-id-123', hard: true, deletedBy: '', deleteForMe: false); +``` + +**Key differences:** + +- The old SDK accepts an optional options array for `hard` delete. The new SDK uses explicit named parameters: `hard`, `deletedBy`, and `deleteForMe`. +- The new SDK adds `deletedBy` (to attribute deletion to a specific user) and `deleteForMe` (to delete only for the requesting user), which were not available in the old SDK. + +## Sending a Reaction + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->sendReaction( + 'message-id-123', + ['type' => 'like'], + 'user-1', +); + +// With a score +$response = $channel->sendReaction( + 'message-id-123', + ['type' => 'like', 'score' => 5], + 'user-1', +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->sendReaction('message-id-123', new GeneratedModels\SendReactionRequest( + reaction: new GeneratedModels\ReactionRequest( + type: 'like', + userID: 'user-1', + ), +)); + +// With a score +$response = $client->sendReaction('message-id-123', new GeneratedModels\SendReactionRequest( + reaction: new GeneratedModels\ReactionRequest( + type: 'like', + score: 5, + userID: 'user-1', + ), +)); +``` + +**Key differences:** + +- The old SDK calls `sendReaction()` on a `Channel` object with the reaction as a flat array and user ID as a separate argument. The new SDK calls `sendReaction()` on the client with a typed `SendReactionRequest` wrapping a `ReactionRequest`. +- The user ID moves from a standalone parameter into the `ReactionRequest` as `userID`. +- The new SDK adds `enforceUnique` on `SendReactionRequest` to replace all existing reactions by the user, and `skipPush` to suppress push notifications. + +## Listing Reactions + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); + +// Get reactions for a message +$response = $channel->getReactions('message-id-123'); + +// With pagination +$response = $channel->getReactions('message-id-123', ['limit' => 10, 'offset' => 0]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +$client = ClientBuilder::fromEnv()->build(); + +// Get reactions for a message +$response = $client->getReactions('message-id-123', limit: 25, offset: 0); + +// With pagination +$response = $client->getReactions('message-id-123', limit: 10, offset: 0); +``` + +**Key differences:** + +- The old SDK calls `getReactions()` on a `Channel` object with an optional options array. The new SDK calls `getReactions()` on the client with explicit `limit` and `offset` named parameters. +- Pagination parameters are no longer bundled in an associative array. + +## Deleting a Reaction + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->deleteReaction('message-id-123', 'like', 'user-1'); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->deleteReaction('message-id-123', type: 'like', userID: 'user-1'); +``` + +**Key differences:** + +- The old SDK calls `deleteReaction()` on a `Channel` object. The new SDK calls it on the client directly. +- The parameters are the same (message ID, reaction type, user ID), but the new SDK uses named arguments. + +## Summary of Method Changes + +| Operation | stream-chat-php | getstream-php | +|-----------|-----------------|---------------| +| Send message | `$channel->sendMessage($msg, $userId)` | `$client->sendMessage($type, $id, new SendMessageRequest(...))` | +| Send thread reply | `$channel->sendMessage($msg, $userId, $parentId)` | `$client->sendMessage($type, $id, new SendMessageRequest(message: new MessageRequest(parentID: ...)))` | +| Get message | `$client->getMessage($id)` | `$client->getMessage($id, showDeletedMessage: false)` | +| Update message | `$client->updateMessage($msg)` | `$client->updateMessage($id, new UpdateMessageRequest(...))` | +| Partial update message | _(not available)_ | `$client->updateMessagePartial($id, new UpdateMessagePartialRequest(...))` | +| Delete message | `$client->deleteMessage($id, $opts)` | `$client->deleteMessage($id, hard: false, deletedBy: '', deleteForMe: false)` | +| Send reaction | `$channel->sendReaction($msgId, $reaction, $userId)` | `$client->sendReaction($msgId, new SendReactionRequest(...))` | +| List reactions | `$channel->getReactions($msgId, $opts)` | `$client->getReactions($msgId, limit: 25, offset: 0)` | +| Delete reaction | `$channel->deleteReaction($msgId, $type, $userId)` | `$client->deleteReaction($msgId, type: $type, userID: $userId)` | diff --git a/docs/migration-from-stream-chat-php/05-moderation.md b/docs/migration-from-stream-chat-php/05-moderation.md new file mode 100644 index 00000000..ff752783 --- /dev/null +++ b/docs/migration-from-stream-chat-php/05-moderation.md @@ -0,0 +1,403 @@ +# Moderation + +This guide covers migrating moderation operations from `stream-chat-php` to `getstream-php`. + +> All `getstream-php` examples assume the client is already instantiated. See [01-setup-and-auth.md](./01-setup-and-auth.md) for client setup. + +## Adding and Removing Moderators + +### Adding Moderators to a Channel + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->addModerators(['user-1', 'user-2']); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( + addModerators: ['user-1', 'user-2'], +)); +``` + +**Key differences:** +- Old SDK uses a dedicated `addModerators()` method on the Channel object +- New SDK uses `updateChannel()` with the `addModerators` parameter on `UpdateChannelRequest` +- No separate Channel object in the new SDK; channel type and ID are passed directly + +### Demoting Moderators + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->demoteModerators(['user-1', 'user-2']); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( + demoteModerators: ['user-1', 'user-2'], +)); +``` + +**Key differences:** +- Same pattern as adding moderators: old SDK has `demoteModerators()` on Channel, new SDK uses `updateChannel()` with `demoteModerators` parameter + +## Banning and Unbanning Users + +### App-level Ban + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// Ban a user app-wide +$response = $client->banUser('bad-user', [ + 'user_id' => 'admin-user', + 'reason' => 'Spamming', + 'timeout' => 60, // minutes +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +// Ban a user app-wide +$response = $client->ban(new GeneratedModels\BanRequest( + targetUserID: 'bad-user', + bannedByID: 'admin-user', + reason: 'Spamming', + timeout: 60, // minutes +)); +``` + +**Key differences:** +- Old SDK: `banUser($targetId, $options)` with flat associative array options +- New SDK: `ban(BanRequest)` with typed named arguments +- `user_id` in old SDK becomes `bannedByID` in new SDK +- The new SDK method lives on the moderation trait (`$client->ban()`), not under a `banUser` name + +### Channel-level Ban + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->banUser('bad-user', [ + 'user_id' => 'admin-user', + 'reason' => 'Off-topic messages', +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->ban(new GeneratedModels\BanRequest( + targetUserID: 'bad-user', + bannedByID: 'admin-user', + reason: 'Off-topic messages', + channelCid: 'messaging:general', +)); +``` + +**Key differences:** +- Old SDK: `$channel->banUser()` automatically includes channel type/ID from the Channel object +- New SDK: use the same `ban()` method but pass `channelCid` (format: `type:id`) to scope the ban to a channel + +### Unbanning a User (App-level) + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->unbanUser('bad-user'); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->unban( + targetUserID: 'bad-user', + channelCid: '', + createdBy: 'admin-user', + requestData: new GeneratedModels\UnbanRequest(), +); +``` + +**Key differences:** +- Old SDK: `unbanUser($targetId)` with optional options array +- New SDK: `unban()` requires `targetUserID`, `channelCid` (empty string for app-level), `createdBy`, and an `UnbanRequest` object +- The new SDK requires explicitly specifying who is performing the unban (`createdBy`) + +### Unbanning a User (Channel-level) + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->unbanUser('bad-user'); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->unban( + targetUserID: 'bad-user', + channelCid: 'messaging:general', + createdBy: 'admin-user', + requestData: new GeneratedModels\UnbanRequest(), +); +``` + +**Key differences:** +- Old SDK: `$channel->unbanUser()` scopes the unban to the channel automatically +- New SDK: pass `channelCid` as `type:id` to scope the unban to a channel + +### Shadow Banning + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +// Shadow ban (app-level) +$response = $client->shadowBan('bad-user', [ + 'user_id' => 'admin-user', +]); + +// Remove shadow ban +$response = $client->removeShadowBan('bad-user', [ + 'user_id' => 'admin-user', +]); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +// Shadow ban (app-level) +$response = $client->ban(new GeneratedModels\BanRequest( + targetUserID: 'bad-user', + bannedByID: 'admin-user', + shadow: true, +)); + +// Remove shadow ban +$response = $client->unban( + targetUserID: 'bad-user', + channelCid: '', + createdBy: 'admin-user', + requestData: new GeneratedModels\UnbanRequest(), +); +``` + +**Key differences:** +- Old SDK has dedicated `shadowBan()` and `removeShadowBan()` methods +- New SDK uses the same `ban()` method with `shadow: true` +- Removing a shadow ban uses the same `unban()` method (no separate method needed) + +### Querying Banned Users + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->queryBannedUsers( + ['channel_cid' => 'messaging:general'], + ['limit' => 10, 'offset' => 0], +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->queryBannedUsers(new GeneratedModels\QueryBannedUsersPayload( + filterConditions: (object) ['channel_cid' => 'messaging:general'], + limit: 10, + offset: 0, +)); +``` + +**Key differences:** +- Old SDK: filter conditions and options are separate array arguments +- New SDK: everything goes into a single `QueryBannedUsersPayload` object with named arguments +- Filter conditions must be cast to `(object)` in the new SDK + +## Muting and Unmuting Users + +### Muting a User + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->muteUser('target-user', 'requesting-user'); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->mute(new GeneratedModels\MuteRequest( + targetIds: ['target-user'], + userID: 'requesting-user', +)); +``` + +**Key differences:** +- Old SDK: `muteUser($targetId, $userId)` takes two string arguments +- New SDK: `mute(MuteRequest)` takes a typed request object +- New SDK accepts an array of `targetIds`, allowing you to mute multiple users in one call +- New SDK supports an optional `timeout` parameter (duration in minutes) + +### Muting a User with Timeout + +**Before (stream-chat-php):** + +```php +// The old SDK does not support mute timeouts directly. +// You would need to handle expiration on your own. +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->mute(new GeneratedModels\MuteRequest( + targetIds: ['target-user'], + userID: 'requesting-user', + timeout: 60, // mute for 60 minutes +)); +``` + +**Key differences:** +- Mute timeout is a new capability in `getstream-php` that was not available in the old SDK + +### Unmuting a User + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$response = $client->unmuteUser('target-user', 'requesting-user'); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->unmute(new GeneratedModels\UnmuteRequest( + targetIds: ['target-user'], + userID: 'requesting-user', +)); +``` + +**Key differences:** +- Old SDK: `unmuteUser($targetId, $userId)` takes two string arguments +- New SDK: `unmute(UnmuteRequest)` takes a typed request object +- New SDK accepts an array of `targetIds`, allowing you to unmute multiple users in one call + +## Summary of Method Mapping + +| Operation | stream-chat-php | getstream-php | +|---|---|---| +| Add moderators | `$channel->addModerators($userIds)` | `$client->updateChannel($type, $id, new UpdateChannelRequest(addModerators: [...]))` | +| Demote moderators | `$channel->demoteModerators($userIds)` | `$client->updateChannel($type, $id, new UpdateChannelRequest(demoteModerators: [...]))` | +| Ban user (app) | `$client->banUser($targetId, $opts)` | `$client->ban(new BanRequest(targetUserID: ..., ...))` | +| Ban user (channel) | `$channel->banUser($targetId, $opts)` | `$client->ban(new BanRequest(targetUserID: ..., channelCid: ..., ...))` | +| Unban user (app) | `$client->unbanUser($targetId)` | `$client->unban($targetUserID, '', $createdBy, new UnbanRequest())` | +| Unban user (channel) | `$channel->unbanUser($targetId)` | `$client->unban($targetUserID, $channelCid, $createdBy, new UnbanRequest())` | +| Shadow ban | `$client->shadowBan($targetId, $opts)` | `$client->ban(new BanRequest(targetUserID: ..., shadow: true, ...))` | +| Remove shadow ban | `$client->removeShadowBan($targetId, $opts)` | `$client->unban($targetUserID, '', $createdBy, new UnbanRequest())` | +| Query banned users | `$client->queryBannedUsers($filter, $opts)` | `$client->queryBannedUsers(new QueryBannedUsersPayload(...))` | +| Mute user | `$client->muteUser($targetId, $userId)` | `$client->mute(new MuteRequest(targetIds: [...], userID: ...))` | +| Unmute user | `$client->unmuteUser($targetId, $userId)` | `$client->unmute(new UnmuteRequest(targetIds: [...], userID: ...))` | diff --git a/docs/migration-from-stream-chat-php/06-devices.md b/docs/migration-from-stream-chat-php/06-devices.md new file mode 100644 index 00000000..fd9d79b8 --- /dev/null +++ b/docs/migration-from-stream-chat-php/06-devices.md @@ -0,0 +1,140 @@ +# Devices + +This guide covers migrating device management operations (push notification setup) from `stream-chat-php` to `getstream-php`. + +## Adding a Device + +### APN (Apple Push Notifications) + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$client->addDevice("device-token-abc", "apn", "user-123"); + +// With a named push provider configuration +$client->addDevice("device-token-abc", "apn", "user-123", "my-apn-provider"); +``` + +**After (getstream-php):** + +```php +use GetStream\ChatClient; +use GetStream\GeneratedModels\CreateDeviceRequest; + +$client = new ChatClient("", ""); + +$client->createDevice(new CreateDeviceRequest( + id: 'device-token-abc', + pushProvider: 'apn', + userID: 'user-123', +)); + +// With a named push provider configuration +$client->createDevice(new CreateDeviceRequest( + id: 'device-token-abc', + pushProvider: 'apn', + userID: 'user-123', + pushProviderName: 'my-apn-provider', +)); +``` + +> **Key differences:** +> - Method renamed from `addDevice()` to `createDevice()` +> - Uses a `CreateDeviceRequest` object with named arguments instead of positional string parameters +> - Push provider and user ID are properties on the request object + +### Firebase (Android Push Notifications) + +**Before (stream-chat-php):** + +```php +$client->addDevice("fcm-token-xyz", "firebase", "user-123"); + +// With a named push provider configuration +$client->addDevice("fcm-token-xyz", "firebase", "user-123", "my-firebase-provider"); +``` + +**After (getstream-php):** + +```php +use GetStream\GeneratedModels\CreateDeviceRequest; + +$client->createDevice(new CreateDeviceRequest( + id: 'fcm-token-xyz', + pushProvider: 'firebase', + userID: 'user-123', +)); + +// With a named push provider configuration +$client->createDevice(new CreateDeviceRequest( + id: 'fcm-token-xyz', + pushProvider: 'firebase', + userID: 'user-123', + pushProviderName: 'my-firebase-provider', +)); +``` + +### VoIP Token (Apple) + +The new SDK adds support for registering Apple VoIP push tokens, which was not available as a dedicated option in the old SDK. + +**After (getstream-php):** + +```php +use GetStream\GeneratedModels\CreateDeviceRequest; + +$client->createDevice(new CreateDeviceRequest( + id: 'voip-token-abc', + pushProvider: 'apn', + userID: 'user-123', + voipToken: true, +)); +``` + +## Listing Devices for a User + +**Before (stream-chat-php):** + +```php +$response = $client->getDevices("user-123"); +``` + +**After (getstream-php):** + +```php +$response = $client->listDevices('user-123'); +``` + +> **Key differences:** +> - Method renamed from `getDevices()` to `listDevices()` +> - Response is typed as `ListDevicesResponse` instead of a generic `StreamResponse` + +## Deleting a Device + +**Before (stream-chat-php):** + +```php +$client->deleteDevice("device-token-abc", "user-123"); +``` + +**After (getstream-php):** + +```php +$client->deleteDevice('device-token-abc', 'user-123'); +``` + +> **Key differences:** +> - The method signature is the same: `deleteDevice(string $id, string $userID)` +> - Parameter names changed from `$deviceId` to `$id` and `$userId` to `$userID`, but since both are positional strings this has no practical impact + +## Method Mapping Summary + +| Operation | stream-chat-php | getstream-php | +|-----------|----------------|---------------| +| Add device | `$client->addDevice($deviceId, $provider, $userId, $providerName)` | `$client->createDevice(new CreateDeviceRequest(...))` | +| List devices | `$client->getDevices($userId)` | `$client->listDevices($userID)` | +| Delete device | `$client->deleteDevice($deviceId, $userId)` | `$client->deleteDevice($id, $userID)` | diff --git a/docs/migration-from-stream-chat-php/README.md b/docs/migration-from-stream-chat-php/README.md new file mode 100644 index 00000000..2337478e --- /dev/null +++ b/docs/migration-from-stream-chat-php/README.md @@ -0,0 +1,91 @@ +# Migrating from stream-chat-php to getstream-php + +## Why Migrate? + +Stream has released **[getstream-php](https://github.com/GetStream/getstream-php)**, a new full-product PHP SDK that covers Chat, Video, Moderation, and Feeds in a single package. It is generated from OpenAPI specs, which means it stays up to date with the latest API features automatically. + +**getstream-php** is the long-term-supported SDK going forward. **stream-chat-php** will enter maintenance mode and continue receiving critical bug fixes, but new features and API coverage will only be added to getstream-php. + +If you are starting a new project, use **getstream-php**. If you have an existing project using stream-chat-php, we encourage you to migrate at your convenience. There is no rush, as stream-chat-php is not going away, but migrating gives you access to the latest features and the best developer experience. + +## Key Differences + +| | **stream-chat-php** | **getstream-php** | +|---|---|---| +| **Package** | `get-stream/stream-chat` | `getstream/getstream-php` | +| **Namespace** | `GetStream\StreamChat\Client` | `GetStream\Client` / `GetStream\ChatClient` | +| **Client init** | `new Client($apiKey, $apiSecret)` | `ClientBuilder::fromEnv()->build()` or `new Client(apiKey: ..., apiSecret: ...)` | +| **API style** | Associative arrays for everything | Typed model classes with named arguments | +| **Channel operations** | `$client->Channel($type, $id)->method()` | `$client->methodName($type, $id, ...)` | +| **Custom fields** | Top-level array keys | `custom: (object) [...]` property | +| **Filters / Sort** | Associative arrays | `(object)` casts and `SortParamRequest` objects | +| **Response types** | Associative arrays | Typed response objects | +| **Autoloading** | PSR-0 | PSR-4 | +| **Product coverage** | Chat only | Chat, Video, Moderation, Feeds | + +## Quick Before/After Example + +The most common operation (initialize client and send a message): + +**Before (stream-chat-php):** + +```php +use GetStream\StreamChat\Client; + +$client = new Client("", ""); + +$channel = $client->Channel('messaging', 'general'); +$response = $channel->sendMessage( + ['text' => 'Hello, world!'], + 'user-1', +); +``` + +**After (getstream-php):** + +```php +use GetStream\ClientBuilder; +use GetStream\GeneratedModels; + +$client = ClientBuilder::fromEnv()->build(); + +$response = $client->sendMessage( + 'messaging', + 'general', + new GeneratedModels\SendMessageRequest( + message: new GeneratedModels\MessageRequest( + text: 'Hello, world!', + userID: 'user-1', + ), + ), +); +``` + +## Migration Guides by Topic + +| # | Topic | Guide | +|---|-------|-------| +| 1 | Setup and Authentication | [01-setup-and-auth.md](./01-setup-and-auth.md) | +| 2 | Users | [02-users.md](./02-users.md) | +| 3 | Channels | [03-channels.md](./03-channels.md) | +| 4 | Messages and Reactions | [04-messages-and-reactions.md](./04-messages-and-reactions.md) | +| 5 | Moderation | [05-moderation.md](./05-moderation.md) | +| 6 | Devices | [06-devices.md](./06-devices.md) | + +Each guide provides side-by-side "Before" and "After" code examples for every operation, along with notes on key differences. + +## Continued Support for stream-chat-php + +stream-chat-php is not being removed or abandoned. It will continue to receive: + +- Critical bug fixes +- Security patches +- Requested features on a case-by-case basis + +However, all new API features, generated model types, and multi-product support will only be available in getstream-php. We recommend migrating when it makes sense for your project timeline. + +## Resources + +- [getstream-php on GitHub](https://github.com/GetStream/getstream-php) +- [getstream-php on Packagist](https://packagist.org/packages/getstream/getstream-php) +- [Stream Chat documentation](https://getstream.io/chat/docs/) From e864eec404117c5da67a7d09ebabfb24f9a31d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=90=99=20Yun=20Wang?= Date: Wed, 11 Mar 2026 10:18:39 +0100 Subject: [PATCH 2/3] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- docs/migration-from-stream-chat-php/01-setup-and-auth.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/migration-from-stream-chat-php/01-setup-and-auth.md b/docs/migration-from-stream-chat-php/01-setup-and-auth.md index 0c1f63de..68ad0949 100644 --- a/docs/migration-from-stream-chat-php/01-setup-and-auth.md +++ b/docs/migration-from-stream-chat-php/01-setup-and-auth.md @@ -100,7 +100,7 @@ Update your `use` statements: | Chat Client | _(same class)_ | `GetStream\ChatClient` | | Builder | _(none)_ | `GetStream\ClientBuilder` | -`ChatClient` extends `Client` and adds all chat-specific methods via `ChatTrait`. For chat operations, you can use either `Client` or `ChatClient` directly. +`ChatClient` extends `Client` and adds all chat-specific methods via `ChatTrait`. For chat operations, you must use `ChatClient`; the base `Client` does not include chat-specific methods. ## User Token Generation From 6baf5446c31832d9b117118351cf2f23f9006e77 Mon Sep 17 00:00:00 2001 From: Yun Wang Date: Wed, 11 Mar 2026 10:39:42 +0100 Subject: [PATCH 3/3] feat: expose chat and video clients --- .../01-setup-and-auth.md | 30 +++++++++---- .../03-channels.md | 28 ++++++------ .../04-messages-and-reactions.md | 20 ++++----- .../05-moderation.md | 22 +++++----- .../06-devices.md | 4 +- docs/migration-from-stream-chat-php/README.md | 4 +- src/ClientBuilder.php | 20 +++++++++ tests/ClientBuilderTest.php | 44 +++++++++++++++++++ 8 files changed, 125 insertions(+), 47 deletions(-) diff --git a/docs/migration-from-stream-chat-php/01-setup-and-auth.md b/docs/migration-from-stream-chat-php/01-setup-and-auth.md index 68ad0949..b4f3286a 100644 --- a/docs/migration-from-stream-chat-php/01-setup-and-auth.md +++ b/docs/migration-from-stream-chat-php/01-setup-and-auth.md @@ -51,32 +51,44 @@ $client = new Client( ### ClientBuilder (New) -The new SDK introduces a `ClientBuilder` with a fluent interface. This pattern has no equivalent in the old SDK. +The new SDK introduces a `ClientBuilder` with a fluent interface. This pattern has no equivalent in the old SDK. The builder has specialized build methods for each product area: + +- `build()` returns a base `Client` (common operations: users, devices, tokens) +- `buildChatClient()` returns a `ChatClient` (all common + chat operations: channels, messages, reactions) +- `buildModerationClient()` returns a `ModerationClient` (all common + moderation operations: ban, mute) +- `buildVideoClient()` returns a `VideoClient` (all common + video operations) +- `buildFeedsClient()` returns a `FeedsV3Client` (all common + feeds operations) **After (getstream-php):** ```php use GetStream\ClientBuilder; -// Build from environment variables (STREAM_API_KEY, STREAM_API_SECRET, STREAM_BASE_URL) -$client = ClientBuilder::fromEnv()->build(); +// Build a ChatClient from environment variables (STREAM_API_KEY, STREAM_API_SECRET, STREAM_BASE_URL) +$client = ClientBuilder::fromEnv()->buildChatClient(); // Build from a custom .env file path -$client = ClientBuilder::fromEnv('/path/to/.env')->build(); +$client = ClientBuilder::fromEnv('/path/to/.env')->buildChatClient(); // Mix environment and explicit values $client = ClientBuilder::fromEnv() ->apiKey("") ->apiSecret("") ->baseUrl("") - ->build(); + ->buildChatClient(); // Skip .env file loading entirely $client = ClientBuilder::fromEnv() ->skipEnvLoad() ->apiKey("") ->apiSecret("") - ->build(); + ->buildChatClient(); + +// Build a base Client for common operations (users, devices, tokens) +$client = ClientBuilder::fromEnv()->build(); + +// Build a ModerationClient for moderation operations (ban, mute, etc.) +$client = ClientBuilder::fromEnv()->buildModerationClient(); ``` ### Environment Variables @@ -96,8 +108,10 @@ Update your `use` statements: | Purpose | stream-chat-php | getstream-php | |---------|-----------------|---------------| -| Client | `GetStream\StreamChat\Client` | `GetStream\Client` | +| Base Client | `GetStream\StreamChat\Client` | `GetStream\Client` | | Chat Client | _(same class)_ | `GetStream\ChatClient` | +| Moderation Client | _(none)_ | `GetStream\ModerationClient` | +| Video Client | _(none)_ | `GetStream\VideoClient` | | Builder | _(none)_ | `GetStream\ClientBuilder` | `ChatClient` extends `Client` and adds all chat-specific methods via `ChatTrait`. For chat operations, you must use `ChatClient`; the base `Client` does not include chat-specific methods. @@ -172,7 +186,7 @@ $token = $client->createUserToken( | Operation | stream-chat-php | getstream-php | |-----------|-----------------|---------------| -| Create client | `new Client($key, $secret)` | `new Client(apiKey: $key, apiSecret: $secret)` or `ClientBuilder::fromEnv()->build()` | +| Create client | `new Client($key, $secret)` | `new ChatClient(apiKey: $key, apiSecret: $secret)` or `ClientBuilder::fromEnv()->buildChatClient()` | | Generate user token | `$client->createToken($userId)` | `$client->createUserToken($userId)` | | Token with expiry | `$client->createToken($userId, time() + 3600)` | `$client->createUserToken($userId, expiration: 3600)` | | Token with claims | _(not supported)_ | `$client->createUserToken($userId, claims: [...])` | diff --git a/docs/migration-from-stream-chat-php/03-channels.md b/docs/migration-from-stream-chat-php/03-channels.md index cab810f8..5544f755 100644 --- a/docs/migration-from-stream-chat-php/03-channels.md +++ b/docs/migration-from-stream-chat-php/03-channels.md @@ -32,7 +32,7 @@ $response = $client->createChannelType([ use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->createChannelType(new GeneratedModels\CreateChannelTypeRequest( name: 'support', @@ -70,7 +70,7 @@ $response = $client->listChannelTypes(); ```php use GetStream\ClientBuilder; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->listChannelTypes(); ``` @@ -96,7 +96,7 @@ $response = $client->getChannelType('support'); ```php use GetStream\ClientBuilder; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->getChannelType('support'); ``` @@ -127,7 +127,7 @@ $response = $client->updateChannelType('support', [ use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->updateChannelType('support', new GeneratedModels\UpdateChannelTypeRequest( typingEvents: false, @@ -157,7 +157,7 @@ $response = $client->deleteChannelType('support'); ```php use GetStream\ClientBuilder; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->deleteChannelType('support'); ``` @@ -187,7 +187,7 @@ $response = $channel->create('admin-user', ['user-1', 'user-2']); use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->getOrCreateChannel('messaging', 'general', new GeneratedModels\ChannelGetOrCreateRequest( data: new GeneratedModels\ChannelInput( @@ -226,7 +226,7 @@ $response = $channel->create('user-1'); use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); // Use getOrCreateDistinctChannel (no channel ID needed) $response = $client->getOrCreateDistinctChannel('messaging', new GeneratedModels\ChannelGetOrCreateRequest( @@ -268,7 +268,7 @@ $response = $channel->addMembers(['user-5'], [ use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( addMembers: [ @@ -310,7 +310,7 @@ $response = $channel->removeMembers(['user-3', 'user-4']); use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( removeMembers: ['user-3', 'user-4'], @@ -350,7 +350,7 @@ $response = $client->queryChannels( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); // Basic query $response = $client->queryChannels(new GeneratedModels\QueryChannelsRequest( @@ -407,7 +407,7 @@ $response = $channel->update( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( message: new GeneratedModels\MessageRequest( @@ -441,7 +441,7 @@ $response = $channel->updatePartial( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->updateChannelPartial('messaging', 'general', new GeneratedModels\UpdateChannelPartialRequest( set: (object) ['name' => 'Updated Name', 'color' => 'blue'], @@ -474,7 +474,7 @@ $response = $channel->delete(); ```php use GetStream\ClientBuilder; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->deleteChannel('messaging', 'general', hardDelete: false); ``` @@ -508,7 +508,7 @@ $response = $client->deleteChannels( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->deleteChannels(new GeneratedModels\DeleteChannelsRequest( cids: ['messaging:general', 'messaging:support'], diff --git a/docs/migration-from-stream-chat-php/04-messages-and-reactions.md b/docs/migration-from-stream-chat-php/04-messages-and-reactions.md index acb82c48..a8b2b265 100644 --- a/docs/migration-from-stream-chat-php/04-messages-and-reactions.md +++ b/docs/migration-from-stream-chat-php/04-messages-and-reactions.md @@ -26,7 +26,7 @@ $response = $channel->sendMessage( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->sendMessage('messaging', 'general', new GeneratedModels\SendMessageRequest( message: new GeneratedModels\MessageRequest( @@ -69,7 +69,7 @@ $response = $channel->sendMessage( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->sendMessage('messaging', 'general', new GeneratedModels\SendMessageRequest( message: new GeneratedModels\MessageRequest( @@ -118,7 +118,7 @@ $response = $channel->sendMessage( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); // Reply in a thread $response = $client->sendMessage('messaging', 'general', new GeneratedModels\SendMessageRequest( @@ -162,7 +162,7 @@ $response = $client->getMessage('message-id-123'); ```php use GetStream\ClientBuilder; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->getMessage('message-id-123', showDeletedMessage: false); ``` @@ -193,7 +193,7 @@ $response = $client->updateMessage([ use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->updateMessage('message-id-123', new GeneratedModels\UpdateMessageRequest( message: new GeneratedModels\MessageRequest( @@ -218,7 +218,7 @@ The new SDK also supports partial message updates, which the old SDK does not ha use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->updateMessagePartial('message-id-123', new GeneratedModels\UpdateMessagePartialRequest( set: (object) ['text' => 'Partially updated text', 'color' => 'blue'], @@ -248,7 +248,7 @@ $response = $client->deleteMessage('message-id-123', ['hard' => true]); ```php use GetStream\ClientBuilder; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); // Soft delete $response = $client->deleteMessage('message-id-123', hard: false, deletedBy: '', deleteForMe: false); @@ -292,7 +292,7 @@ $response = $channel->sendReaction( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->sendReaction('message-id-123', new GeneratedModels\SendReactionRequest( reaction: new GeneratedModels\ReactionRequest( @@ -340,7 +340,7 @@ $response = $channel->getReactions('message-id-123', ['limit' => 10, 'offset' => ```php use GetStream\ClientBuilder; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); // Get reactions for a message $response = $client->getReactions('message-id-123', limit: 25, offset: 0); @@ -372,7 +372,7 @@ $response = $channel->deleteReaction('message-id-123', 'like', 'user-1'); ```php use GetStream\ClientBuilder; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->deleteReaction('message-id-123', type: 'like', userID: 'user-1'); ``` diff --git a/docs/migration-from-stream-chat-php/05-moderation.md b/docs/migration-from-stream-chat-php/05-moderation.md index ff752783..8fbcb395 100644 --- a/docs/migration-from-stream-chat-php/05-moderation.md +++ b/docs/migration-from-stream-chat-php/05-moderation.md @@ -25,7 +25,7 @@ $response = $channel->addModerators(['user-1', 'user-2']); use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( addModerators: ['user-1', 'user-2'], @@ -56,7 +56,7 @@ $response = $channel->demoteModerators(['user-1', 'user-2']); use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->updateChannel('messaging', 'general', new GeneratedModels\UpdateChannelRequest( demoteModerators: ['user-1', 'user-2'], @@ -91,7 +91,7 @@ $response = $client->banUser('bad-user', [ use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildModerationClient(); // Ban a user app-wide $response = $client->ban(new GeneratedModels\BanRequest( @@ -130,7 +130,7 @@ $response = $channel->banUser('bad-user', [ use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildModerationClient(); $response = $client->ban(new GeneratedModels\BanRequest( targetUserID: 'bad-user', @@ -162,7 +162,7 @@ $response = $client->unbanUser('bad-user'); use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildModerationClient(); $response = $client->unban( targetUserID: 'bad-user', @@ -196,7 +196,7 @@ $response = $channel->unbanUser('bad-user'); use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildModerationClient(); $response = $client->unban( targetUserID: 'bad-user', @@ -236,7 +236,7 @@ $response = $client->removeShadowBan('bad-user', [ use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildModerationClient(); // Shadow ban (app-level) $response = $client->ban(new GeneratedModels\BanRequest( @@ -280,7 +280,7 @@ $response = $client->queryBannedUsers( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->queryBannedUsers(new GeneratedModels\QueryBannedUsersPayload( filterConditions: (object) ['channel_cid' => 'messaging:general'], @@ -314,7 +314,7 @@ $response = $client->muteUser('target-user', 'requesting-user'); use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildModerationClient(); $response = $client->mute(new GeneratedModels\MuteRequest( targetIds: ['target-user'], @@ -343,7 +343,7 @@ $response = $client->mute(new GeneratedModels\MuteRequest( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildModerationClient(); $response = $client->mute(new GeneratedModels\MuteRequest( targetIds: ['target-user'], @@ -373,7 +373,7 @@ $response = $client->unmuteUser('target-user', 'requesting-user'); use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildModerationClient(); $response = $client->unmute(new GeneratedModels\UnmuteRequest( targetIds: ['target-user'], diff --git a/docs/migration-from-stream-chat-php/06-devices.md b/docs/migration-from-stream-chat-php/06-devices.md index fd9d79b8..efae74f2 100644 --- a/docs/migration-from-stream-chat-php/06-devices.md +++ b/docs/migration-from-stream-chat-php/06-devices.md @@ -22,10 +22,10 @@ $client->addDevice("device-token-abc", "apn", "user-123", "my-apn-provider"); **After (getstream-php):** ```php -use GetStream\ChatClient; +use GetStream\ClientBuilder; use GetStream\GeneratedModels\CreateDeviceRequest; -$client = new ChatClient("", ""); +$client = ClientBuilder::fromEnv()->build(); $client->createDevice(new CreateDeviceRequest( id: 'device-token-abc', diff --git a/docs/migration-from-stream-chat-php/README.md b/docs/migration-from-stream-chat-php/README.md index 2337478e..a824eee2 100644 --- a/docs/migration-from-stream-chat-php/README.md +++ b/docs/migration-from-stream-chat-php/README.md @@ -14,7 +14,7 @@ If you are starting a new project, use **getstream-php**. If you have an existin |---|---|---| | **Package** | `get-stream/stream-chat` | `getstream/getstream-php` | | **Namespace** | `GetStream\StreamChat\Client` | `GetStream\Client` / `GetStream\ChatClient` | -| **Client init** | `new Client($apiKey, $apiSecret)` | `ClientBuilder::fromEnv()->build()` or `new Client(apiKey: ..., apiSecret: ...)` | +| **Client init** | `new Client($apiKey, $apiSecret)` | `ClientBuilder::fromEnv()->buildChatClient()` or `new ChatClient(apiKey: ..., apiSecret: ...)` | | **API style** | Associative arrays for everything | Typed model classes with named arguments | | **Channel operations** | `$client->Channel($type, $id)->method()` | `$client->methodName($type, $id, ...)` | | **Custom fields** | Top-level array keys | `custom: (object) [...]` property | @@ -47,7 +47,7 @@ $response = $channel->sendMessage( use GetStream\ClientBuilder; use GetStream\GeneratedModels; -$client = ClientBuilder::fromEnv()->build(); +$client = ClientBuilder::fromEnv()->buildChatClient(); $response = $client->sendMessage( 'messaging', diff --git a/src/ClientBuilder.php b/src/ClientBuilder.php index 774a417d..312206d3 100644 --- a/src/ClientBuilder.php +++ b/src/ClientBuilder.php @@ -115,6 +115,26 @@ public function buildFeedsClient(): FeedsV3Client return new FeedsV3Client($this->apiKey, $this->apiSecret, $this->baseUrl, $this->httpClient); } + /** + * @throws StreamException + */ + public function buildChatClient(): ChatClient + { + $this->loadCreds(); + + return new ChatClient($this->apiKey, $this->apiSecret, $this->baseUrl, $this->httpClient); + } + + /** + * @throws StreamException + */ + public function buildVideoClient(): VideoClient + { + $this->loadCreds(); + + return new VideoClient($this->apiKey, $this->apiSecret, $this->baseUrl, $this->httpClient); + } + /** * @throws StreamException */ diff --git a/tests/ClientBuilderTest.php b/tests/ClientBuilderTest.php index ce7b6835..b2bfc827 100644 --- a/tests/ClientBuilderTest.php +++ b/tests/ClientBuilderTest.php @@ -4,9 +4,11 @@ namespace GetStream\Tests; +use GetStream\ChatClient; use GetStream\Client; use GetStream\ClientBuilder; use GetStream\Http\HttpClientInterface; +use GetStream\VideoClient; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; @@ -175,6 +177,48 @@ public function environmentBaseUrlOverridesDefault(): void self::assertSame('https://custom-env.api.com', $client->getBaseUrl()); } + /** + * @test + */ + public function buildChatClient(): void + { + $client = (new ClientBuilder()) + ->apiKey('test-key') + ->apiSecret('test-secret') + ->baseUrl('https://custom.api.com') + ->httpClient($this->mockHttpClient) + ->skipEnvLoad() + ->buildChatClient(); + + self::assertInstanceOf(ChatClient::class, $client); + self::assertInstanceOf(Client::class, $client); + self::assertSame('test-key', $client->getApiKey()); + self::assertSame('test-secret', $client->getApiSecret()); + self::assertSame('https://custom.api.com', $client->getBaseUrl()); + self::assertSame($this->mockHttpClient, $client->getHttpClient()); + } + + /** + * @test + */ + public function buildVideoClient(): void + { + $client = (new ClientBuilder()) + ->apiKey('test-key') + ->apiSecret('test-secret') + ->baseUrl('https://custom.api.com') + ->httpClient($this->mockHttpClient) + ->skipEnvLoad() + ->buildVideoClient(); + + self::assertInstanceOf(VideoClient::class, $client); + self::assertInstanceOf(Client::class, $client); + self::assertSame('test-key', $client->getApiKey()); + self::assertSame('test-secret', $client->getApiSecret()); + self::assertSame('https://custom.api.com', $client->getBaseUrl()); + self::assertSame($this->mockHttpClient, $client->getHttpClient()); + } + /** * @test */