diff --git a/src/ConvertKit_API_Traits.php b/src/ConvertKit_API_Traits.php index 5cd57e4..b629c56 100644 --- a/src/ConvertKit_API_Traits.php +++ b/src/ConvertKit_API_Traits.php @@ -1103,6 +1103,41 @@ public function create_tags(array $tags, string $callback_url = '') ); } + /** + * Bulk delete tags. + * + * @param array $tag_ids Tag IDs. + * @param string $callback_url URL to notify for large batch size when async processing complete. + * + * @since 2.6.0 + * + * @see https://developers.kit.com/api-reference/tags/bulk-delete-tags + * + * @return false|mixed + */ + public function delete_tags(array $tag_ids, string $callback_url = '') + { + // Build parameters. + $options = [ + 'tags' => [], + ]; + foreach ($tag_ids as $i => $tag_id) { + $options['tags'][] = [ + 'id' => (int) $tag_id, + ]; + } + + if (!empty($callback_url)) { + $options['callback_url'] = $callback_url; + } + + // Send request. + return $this->delete( + 'bulk/tags', + $options + ); + } + /** * Updates the name of a tag. * @@ -1530,21 +1565,22 @@ public function create_subscribers(array $subscribers, string $callback_url = '' /** * Filter subscribers based on engagement. * - * @param array> $all Array of filter conditions where ALL must be met (AND logic). Each condition can have. - * - 'type' (string). - * - 'count_greater_than' (int|null). - * - 'count_less_than' (int|null). - * - 'after' (\DateTime|null). - * - 'before' (\DateTime|null). - * - 'states' (array). - * - 'any' (array|null). - * @param string $counting_mode Controls how engagement-filter count thresholds are tallied. - * - 'raw' (default) counts every event — five opens of the same email = five. - * - 'unique_email' counts distinct emails on which the action occurred. - * @param boolean $include_total_count To include the total count of records in the response, use true. - * @param string $after_cursor Return results after the given pagination cursor. - * @param string $before_cursor Return results before the given pagination cursor. - * @param integer $per_page Number of results to return. + * @param list> $all Array of filter conditions where ALL must be met (AND logic). Each condition can have. + * - 'type' (string). + * - 'count_greater_than' (int|null). + * - 'count_less_than' (int|null). + * - 'after' (\DateTime|null). + * - 'before' (\DateTime|null). + * - 'states' (array). + * - 'any' (array|null). + * @param string $counting_mode Controls how engagement-filter count thresholds are tallied. + * - 'raw' (default) counts every event — five opens of the same email = five. + * - 'unique_email' counts distinct emails on which the action occurred. + * @param list> $include Array of additional fields to embed on each subscriber row. + * @param boolean $include_total_count To include the total count of records in the response, use true. + * @param string $after_cursor Return results after the given pagination cursor. + * @param string $before_cursor Return results before the given pagination cursor. + * @param integer $per_page Number of results to return. * * @since 2.4.0 * @@ -1555,6 +1591,7 @@ public function create_subscribers(array $subscribers, string $callback_url = '' public function filter_subscribers( array $all = [], string $counting_mode = 'raw', + array $include = [], bool $include_total_count = false, string $after_cursor = '', string $before_cursor = '', @@ -1602,6 +1639,7 @@ public function filter_subscribers( [ 'all' => $options, 'counting_mode' => $counting_mode, + 'include' => $include, ], $include_total_count, $after_cursor, @@ -2688,8 +2726,8 @@ public function put(string $endpoint, array $args = []) /** * Performs a DELETE request to the API. * - * @param string $endpoint API Endpoint. - * @param array|string> $args Request arguments. + * @param string $endpoint API Endpoint. + * @param array|boolean|integer|float|string>> $args Request arguments. * * @return false|mixed */ diff --git a/tests/ConvertKitAPIKeyTest.php b/tests/ConvertKitAPIKeyTest.php index 28ec468..efa18ce 100644 --- a/tests/ConvertKitAPIKeyTest.php +++ b/tests/ConvertKitAPIKeyTest.php @@ -237,13 +237,19 @@ public function testRequestHeadersMethodWithTypeAndAuthDisabled() * * @return void */ - public function testCreateTags() + public function testCreateAndDeleteTags() { $this->expectException(ClientException::class); $result = $this->api->create_tags([ 'Tag Test ' . mt_rand(), 'Tag Test ' . mt_rand(), ]); + + $this->expectException(ClientException::class); + $result = $this->api->delete_tags([ + 12345, + 23456, + ]); } /** diff --git a/tests/ConvertKitAPITest.php b/tests/ConvertKitAPITest.php index 135b41b..e6ed190 100644 --- a/tests/ConvertKitAPITest.php +++ b/tests/ConvertKitAPITest.php @@ -2410,44 +2410,36 @@ public function testCreateTagThatExists() } /** - * Test that create_tags() returns the expected data. + * Test that create_tags() and delete_tags() returns the expected data. * * @since 1.1.0 * * @return void */ - public function testCreateTags() + public function testCreateAndDeleteTags() { $tagNames = [ 'Tag Test ' . mt_rand(), 'Tag Test ' . mt_rand(), ]; - // Add mock handler for this API request, as the API doesn't provide - // a method to delete tags to cleanup the test. - $this->api = $this->mockResponse( - api: $this->api, - responseBody: [ - 'tags' => [ - [ - 'id' => 12345, - 'name' => $tagNames[0], - 'created_at' => date('Y-m-d') . 'T' . date('H:i:s') . 'Z', - ], - [ - 'id' => 23456, - 'name' => $tagNames[1], - 'created_at' => date('Y-m-d') . 'T' . date('H:i:s') . 'Z', - ], - ], - 'failures' => [], - ] - ); - + // Create tags. $result = $this->api->create_tags($tagNames); // Assert no failures. $this->assertCount(0, $result->failures); + + // Build tag IDs array. + $ids = []; + foreach ($result->tags as $tag) { + $ids[] = $tag->id; + } + + // Delete tags. + $result = $this->api->delete_tags($ids); + + // Assert no failures. + $this->assertCount(0, $result->failures); } /** @@ -4609,6 +4601,44 @@ public function testFilterSubscribersWithCountingMode() $this->assertPaginationExists($result); } + /** + * Test that filter_subscribers() returns the expected data + * when the `include` parameter is specified. + * + * @since 2.6.0 + * + * @return void + */ + public function testFilterSubscribersWithInclude() + { + $result = $this->api->filter_subscribers( + all: [ + [ + 'type' => 'opens', + 'count_greater_than' => 0, + 'count_less_than' => 100, + 'after' => new \DateTime('2024-01-01'), + 'before' => new \DateTime('2029-01-01'), + 'states' => [ + 'active', + ], + ] + ], + include: [ + [ + 'type' => 'tags', + ], + ] + ); + + // Assert subscribers and pagination exist. + $this->assertDataExists($result, 'subscribers'); + $this->assertPaginationExists($result); + + // Assert tags are included. + $this->assertArrayHasKey('tags', get_object_vars($result->subscribers[0])); + } + /** * Test that filter_subscribers() returns the expected data * when no parameters are specified.