From 6549884f471abca092358905780c1bb4d87ab7e2 Mon Sep 17 00:00:00 2001 From: David Grayston Date: Thu, 12 Sep 2024 15:57:33 +0100 Subject: [PATCH] Feature: Support notification settings pagination and active filter --- CHANGELOG.md | 2 + .../NotificationSettingsClient.php | 7 +- .../Operations/ListNotificationSettings.php | 27 ++++ .../NotificationSettingsClientTest.php | 94 +++++++++++++- .../_fixtures/response/list_default.json | 8 +- .../response/list_paginated_page_one.json | 115 ++++++++++++++++++ .../response/list_paginated_page_two.json | 115 ++++++++++++++++++ 7 files changed, 361 insertions(+), 7 deletions(-) create mode 100644 src/Resources/NotificationSettings/Operations/ListNotificationSettings.php create mode 100644 tests/Functional/Resources/NotificationSettings/_fixtures/response/list_paginated_page_one.json create mode 100644 tests/Functional/Resources/NotificationSettings/_fixtures/response/list_paginated_page_two.json diff --git a/CHANGELOG.md b/CHANGELOG.md index f33e6ea..ae53b7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ Check our main [developer changelog](https://developer.paddle.com/?utm_source=dx - Added `product` to `subscription.items[]`, see [related changelog](https://developer.paddle.com/changelog/2024/subscription-items-product?utm_source=dx&utm_medium=paddle-php-sdk) - Added `import_meta` to `transaction` - Support for `createdAt` and `updatedAt` on Subscription notification prices +- Support notification settings pagination, see [related changelog](https://developer.paddle.com/changelog/2024/notification-settings-pagination) +- Support notification settings `active` filter ## [1.1.2] - 2024-08-23 diff --git a/src/Resources/NotificationSettings/NotificationSettingsClient.php b/src/Resources/NotificationSettings/NotificationSettingsClient.php index ee1099e..e624bd3 100644 --- a/src/Resources/NotificationSettings/NotificationSettingsClient.php +++ b/src/Resources/NotificationSettings/NotificationSettingsClient.php @@ -13,10 +13,12 @@ use Paddle\SDK\Client; use Paddle\SDK\Entities\Collections\NotificationSettingCollection; +use Paddle\SDK\Entities\Collections\Paginator; use Paddle\SDK\Entities\NotificationSetting; use Paddle\SDK\Exceptions\ApiError; use Paddle\SDK\Exceptions\SdkExceptions\MalformedResponse; use Paddle\SDK\Resources\NotificationSettings\Operations\CreateNotificationSetting; +use Paddle\SDK\Resources\NotificationSettings\Operations\ListNotificationSettings; use Paddle\SDK\Resources\NotificationSettings\Operations\UpdateNotificationSetting; use Paddle\SDK\ResponseParser; @@ -31,14 +33,15 @@ public function __construct( * @throws ApiError On a generic API error * @throws MalformedResponse If the API response was not parsable */ - public function list(): NotificationSettingCollection + public function list(ListNotificationSettings $listOperation = new ListNotificationSettings()): NotificationSettingCollection { $parser = new ResponseParser( - $this->client->getRaw('notification-settings'), + $this->client->getRaw('notification-settings', $listOperation), ); return NotificationSettingCollection::from( $parser->getData(), + new Paginator($this->client, $parser->getPagination(), NotificationSettingCollection::class), ); } diff --git a/src/Resources/NotificationSettings/Operations/ListNotificationSettings.php b/src/Resources/NotificationSettings/Operations/ListNotificationSettings.php new file mode 100644 index 0000000..84c4bae --- /dev/null +++ b/src/Resources/NotificationSettings/Operations/ListNotificationSettings.php @@ -0,0 +1,27 @@ +pager?->getParameters() ?? [], + array_filter([ + 'active' => isset($this->active) ? ($this->active ? 'true' : 'false') : null, + ]), + ); + } +} diff --git a/tests/Functional/Resources/NotificationSettings/NotificationSettingsClientTest.php b/tests/Functional/Resources/NotificationSettings/NotificationSettingsClientTest.php index d1074a7..bbbc5b2 100644 --- a/tests/Functional/Resources/NotificationSettings/NotificationSettingsClientTest.php +++ b/tests/Functional/Resources/NotificationSettings/NotificationSettingsClientTest.php @@ -12,7 +12,10 @@ use Paddle\SDK\Environment; use Paddle\SDK\Options; use Paddle\SDK\Resources\NotificationSettings\Operations\CreateNotificationSetting; +use Paddle\SDK\Resources\NotificationSettings\Operations\ListNotificationSettings; use Paddle\SDK\Resources\NotificationSettings\Operations\UpdateNotificationSetting; +use Paddle\SDK\Resources\Shared\Operations\List\OrderBy; +use Paddle\SDK\Resources\Shared\Operations\List\Pager; use Paddle\SDK\Tests\Utils\ReadsFixtures; use PHPUnit\Framework\TestCase; use Psr\Http\Message\RequestInterface; @@ -173,11 +176,11 @@ public static function updateOperationsProvider(): \Generator * @dataProvider listOperationsProvider */ public function list_hits_expected_uri( - ResponseInterface $response, + ListNotificationSettings $listOperation, string $expectedUri, ): void { - $this->mockClient->addResponse($response); - $this->client->notificationSettings->list(); + $this->mockClient->addResponse(new Response(200, body: self::readRawJsonFixture('response/list_default'))); + $this->client->notificationSettings->list($listOperation); $request = $this->mockClient->getLastRequest(); self::assertInstanceOf(RequestInterface::class, $request); @@ -188,9 +191,92 @@ public function list_hits_expected_uri( public static function listOperationsProvider(): \Generator { yield 'Default' => [ - new Response(200, body: self::readRawJsonFixture('response/list_default')), + new ListNotificationSettings(), sprintf('%s/notification-settings', Environment::SANDBOX->baseUrl()), ]; + + yield 'With active filter true' => [ + new ListNotificationSettings(null, true), + sprintf('%s/notification-settings?active=true', Environment::SANDBOX->baseUrl()), + ]; + + yield 'With active filter false' => [ + new ListNotificationSettings(null, false), + sprintf('%s/notification-settings?active=false', Environment::SANDBOX->baseUrl()), + ]; + + yield 'With default pagination' => [ + new ListNotificationSettings( + new Pager(), + ), + sprintf('%s/notification-settings?order_by=id[asc]&per_page=50', Environment::SANDBOX->baseUrl()), + ]; + + yield 'With pagination after' => [ + new ListNotificationSettings( + new Pager('ntfset_01gkpjp8bkm3tm53kdgkx6sms7'), + ), + sprintf( + '%s/notification-settings?after=ntfset_01gkpjp8bkm3tm53kdgkx6sms7&order_by=id[asc]&per_page=50', + Environment::SANDBOX->baseUrl(), + ), + ]; + + yield 'With pagination after, order by ID asc' => [ + new ListNotificationSettings( + new Pager('ntfset_02gkpjp8bkm3tm53kdgkx6sms7', OrderBy::idAscending()), + ), + sprintf( + '%s/notification-settings?after=ntfset_02gkpjp8bkm3tm53kdgkx6sms7&order_by=id[asc]&per_page=50', + Environment::SANDBOX->baseUrl(), + ), + ]; + + yield 'With pagination after, order by ID desc' => [ + new ListNotificationSettings( + new Pager('ntfset_03gkpjp8bkm3tm53kdgkx6sms7', OrderBy::idDescending()), + ), + sprintf( + '%s/notification-settings?after=ntfset_03gkpjp8bkm3tm53kdgkx6sms7&order_by=id[desc]&per_page=50', + Environment::SANDBOX->baseUrl(), + ), + ]; + + yield 'With pagination after, order by ID asc, per page' => [ + new ListNotificationSettings( + new Pager('ntfset_04gkpjp8bkm3tm53kdgkx6sms7', OrderBy::idDescending(), 10), + ), + sprintf( + '%s/notification-settings?after=ntfset_04gkpjp8bkm3tm53kdgkx6sms7&order_by=id[desc]&per_page=10', + Environment::SANDBOX->baseUrl(), + ), + ]; + } + + /** @test */ + public function it_can_paginate(): void + { + $this->mockClient->addResponse(new Response(200, body: self::readRawJsonFixture('response/list_paginated_page_one'))); + $this->mockClient->addResponse(new Response(200, body: self::readRawJsonFixture('response/list_paginated_page_two'))); + + $collection = $this->client->notificationSettings->list(); + + $request = $this->mockClient->getLastRequest(); + + self::assertEquals( + Environment::SANDBOX->baseUrl() . '/notification-settings', + urldecode((string) $request->getUri()), + ); + + $allNotificationSettings = iterator_to_array($collection); + self::assertCount(2, $allNotificationSettings); + + $request = $this->mockClient->getLastRequest(); + + self::assertEquals( + Environment::SANDBOX->baseUrl() . '/notification-settings?after=ntfset_01gkpjp8bkm3tm53kdgkx6sms7', + urldecode((string) $request->getUri()), + ); } /** diff --git a/tests/Functional/Resources/NotificationSettings/_fixtures/response/list_default.json b/tests/Functional/Resources/NotificationSettings/_fixtures/response/list_default.json index 56b237e..9ecfc1f 100644 --- a/tests/Functional/Resources/NotificationSettings/_fixtures/response/list_default.json +++ b/tests/Functional/Resources/NotificationSettings/_fixtures/response/list_default.json @@ -206,6 +206,12 @@ } ], "meta": { - "request_id": "cf039cbb-6c2a-485d-b244-501894b797a6" + "request_id": "cf039cbb-6c2a-485d-b244-501894b797a6", + "pagination": { + "per_page": 5, + "next": "https://api.paddle.com/notification-settings?after=ntfset_01gkpop8bkm3tm53itgkx6klk7", + "has_more": false, + "estimated_total": 5 + } } } diff --git a/tests/Functional/Resources/NotificationSettings/_fixtures/response/list_paginated_page_one.json b/tests/Functional/Resources/NotificationSettings/_fixtures/response/list_paginated_page_one.json new file mode 100644 index 0000000..f5765ad --- /dev/null +++ b/tests/Functional/Resources/NotificationSettings/_fixtures/response/list_paginated_page_one.json @@ -0,0 +1,115 @@ +{ + "data": [ + { + "id": "ntfset_01gkpjp8bkm3tm53kdgkx6sms7", + "description": "Slack notifications", + "type": "url", + "destination": "https://hooks.slack.com/example", + "active": true, + "api_version": 1, + "include_sensitive_fields": false, + "subscribed_events": [ + { + "name": "transaction.billed", + "description": "Occurs when a transaction is billed.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.canceled", + "description": "Occurs when a transaction is canceled.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.completed", + "description": "Occurs when a transaction is completed.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.created", + "description": "Occurs when a transaction is created.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.payment_failed", + "description": "Occurs when a payment fails for a transaction.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.ready", + "description": "Occurs when a transaction is ready.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.updated", + "description": "Occurs when a transaction is updated.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "subscription.activated", + "description": "Occurs when a subscription is activated.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.canceled", + "description": "Occurs when a subscription is canceled.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.created", + "description": "Occurs when a subscription is created.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.past_due", + "description": "Occurs when a subscription is past due.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.paused", + "description": "Occurs when a subscription is paused.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.resumed", + "description": "Occurs when a subscription is resumed.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.trialing", + "description": "Occurs when a subscription is trialing.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.updated", + "description": "Occurs when a subscription is updated.", + "group": "Subscription", + "available_versions": [1] + } + ], + "endpoint_secret_key": "pdl_ntfset_01gkpjp8bkm3tm53kdgkx6sms7_6h3qd3uFSi9YCD3OLYAShQI90XTI5vEI" + } + ], + "meta": { + "request_id": "cf039cbb-6c2a-485d-b244-501894b797a6", + "pagination": { + "per_page": 1, + "next": "https://api.paddle.com/notification-settings?after=ntfset_01gkpjp8bkm3tm53kdgkx6sms7", + "has_more": true, + "estimated_total": 2 + } + } +} diff --git a/tests/Functional/Resources/NotificationSettings/_fixtures/response/list_paginated_page_two.json b/tests/Functional/Resources/NotificationSettings/_fixtures/response/list_paginated_page_two.json new file mode 100644 index 0000000..fb1e866 --- /dev/null +++ b/tests/Functional/Resources/NotificationSettings/_fixtures/response/list_paginated_page_two.json @@ -0,0 +1,115 @@ +{ + "data": [ + { + "id": "ntfset_01gkpop8bkm3tm53itgkx6klk7", + "description": "Discord notifications", + "type": "url", + "destination": "https://hooks.discord.com/example", + "active": true, + "api_version": 1, + "include_sensitive_fields": false, + "subscribed_events": [ + { + "name": "transaction.billed", + "description": "Occurs when a transaction is billed.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.canceled", + "description": "Occurs when a transaction is canceled.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.completed", + "description": "Occurs when a transaction is completed.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.created", + "description": "Occurs when a transaction is created.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.payment_failed", + "description": "Occurs when a payment fails for a transaction.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.ready", + "description": "Occurs when a transaction is ready.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "transaction.updated", + "description": "Occurs when a transaction is updated.", + "group": "Transaction", + "available_versions": [1] + }, + { + "name": "subscription.activated", + "description": "Occurs when a subscription is activated.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.canceled", + "description": "Occurs when a subscription is canceled.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.created", + "description": "Occurs when a subscription is created.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.past_due", + "description": "Occurs when a subscription is past due.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.paused", + "description": "Occurs when a subscription is paused.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.resumed", + "description": "Occurs when a subscription is resumed.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.trialing", + "description": "Occurs when a subscription is trialing.", + "group": "Subscription", + "available_versions": [1] + }, + { + "name": "subscription.updated", + "description": "Occurs when a subscription is updated.", + "group": "Subscription", + "available_versions": [1] + } + ], + "endpoint_secret_key": "ntfset_01gkpop8bkm3tm53itgkx6klk7_6h3qd3uFSi9YCD3OLYAShQI90XTI5vEI" + } + ], + "meta": { + "request_id": "cf039cbb-6c2a-485d-b244-501894b797a6", + "pagination": { + "per_page": 1, + "next": "https://api.paddle.com/notification-settings?after=ntfset_01gkpop8bkm3tm53itgkx6klk7", + "has_more": false, + "estimated_total": 2 + } + } +}