diff --git a/.env.dist.testing b/.env.dist.testing index 48cc810..ca3522d 100644 --- a/.env.dist.testing +++ b/.env.dist.testing @@ -1,5 +1,6 @@ CONVERTKIT_API_BROADCAST_ID="8697158" CONVERTKIT_API_FORM_ID="2765139" +CONVERTKIT_API_FORM_ID_2="2780977" CONVERTKIT_API_LEGACY_FORM_URL="https://app.convertkit.com/landing_pages/470099" CONVERTKIT_API_LANDING_PAGE_URL="https://cheerful-architect-3237.ck.page/cc5eb21744" CONVERTKIT_API_LEGACY_LANDING_PAGE_URL="https://app.convertkit.com/landing_pages/470103" diff --git a/.env.example b/.env.example index 83d8a88..c138bea 100644 --- a/.env.example +++ b/.env.example @@ -7,6 +7,7 @@ CONVERTKIT_OAUTH_CLIENT_SECRET= CONVERTKIT_OAUTH_REDIRECT_URI="https://convertkit-github.local/wp-admin/options-general.php?page=_wp_convertkit_settings" CONVERTKIT_API_BROADCAST_ID="8697158" CONVERTKIT_API_FORM_ID="2765139" +CONVERTKIT_API_FORM_ID_2="2780977" CONVERTKIT_API_LEGACY_FORM_URL="https://app.convertkit.com/landing_pages/470099" CONVERTKIT_API_LANDING_PAGE_URL="https://cheerful-architect-3237.ck.page/cc5eb21744" CONVERTKIT_API_LEGACY_LANDING_PAGE_URL="https://app.convertkit.com/landing_pages/470103" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 43d8299..4894c77 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -42,7 +42,7 @@ jobs: # Make sure your committed .env.dist.testing file ends with a newline. # The formatting of the contents to include a blank newline is deliberate. - name: Define GitHub Secrets in .env.dist.testing - uses: DamianReeves/write-file-action@v1.1 + uses: DamianReeves/write-file-action@v1.3 with: path: .env.dist.testing contents: | @@ -68,6 +68,11 @@ jobs: - name: Build PHP Autoloader run: composer dump-autoload + # Run PHPStan for static analysis. + - name: Run PHPStan Static Analysis + working-directory: ${{ env.PLUGIN_DIR }} + run: php vendor/bin/phpstan analyse --memory-limit=1250M + # Run Coding Standards. - name: Run Coding Standards run: php vendor/bin/phpcs --standard=phpcs.xml diff --git a/composer.json b/composer.json index e2c5048..9b46196 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "vlucas/phpdotenv": "^5.5", "phpunit/phpunit": "^5.7 || ^9.0", "squizlabs/php_codesniffer": "^3.3", - "phpstan/phpstan": "^1.2" + "phpstan/phpstan": "^2.0" }, "autoload": { "psr-4": { diff --git a/phpstan.neon.dist b/phpstan.neon.dist index c3bd077..77033b3 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -6,4 +6,4 @@ parameters: # Should not need to edit anything below here # Rule Level: https://phpstan.org/user-guide/rule-levels - level: 8 \ No newline at end of file + level: 10 \ No newline at end of file diff --git a/src/ConvertKit_API.php b/src/ConvertKit_API.php index 86b1888..6fcd9d3 100644 --- a/src/ConvertKit_API.php +++ b/src/ConvertKit_API.php @@ -142,6 +142,7 @@ private function create_log(string $message) // Mask email addresses that may be contained within the message. $message = preg_replace_callback( '^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})^', + // @phpstan-ignore-next-line - see https://github.com/phpstan/phpstan/issues/10396 function ($matches) { return preg_replace('/\B[^@.]/', '*', $matches[0]); }, @@ -176,7 +177,7 @@ public function get_oauth_url(string $redirectURI) * @param string $authCode Authorization Code, returned from get_oauth_url() flow. * @param string $redirectURI Redirect URI. * - * @return array API response + * @return mixed|array API response */ public function get_access_token(string $authCode, string $redirectURI) { @@ -214,7 +215,7 @@ public function get_access_token(string $authCode, string $redirectURI) * @param string $refreshToken Refresh Token. * @param string $redirectURI Redirect URI. * - * @return array API response + * @return mixed|array API response */ public function refresh_token(string $refreshToken, string $redirectURI) { @@ -337,7 +338,7 @@ public function get_resource(string $url) * * @throws \Exception If JSON encoding arguments failed. * - * @return false|mixed + * @return mixed|object */ public function request(string $endpoint, string $method, array $args = []) { diff --git a/src/ConvertKit_API_Traits.php b/src/ConvertKit_API_Traits.php index b5fc993..fb54712 100644 --- a/src/ConvertKit_API_Traits.php +++ b/src/ConvertKit_API_Traits.php @@ -161,7 +161,7 @@ public function get_growth_stats(\DateTime $starting = null, \DateTime $ending = * * @see https://developers.convertkit.com/v4.html#convertkit-api-forms * - * @return false|array + * @return mixed|array */ public function get_forms( string $status = 'active', @@ -198,7 +198,7 @@ public function get_forms( * * @see https://developers.convertkit.com/v4.html#convertkit-api-forms * - * @return false|array + * @return mixed|array */ public function get_landing_pages( string $status = 'active', @@ -222,21 +222,57 @@ public function get_landing_pages( ); } + /** + * Adds subscribers to forms in bulk. + * + * @param array> $forms_subscribers_ids Array of arrays comprising of `form_id`, `subscriber_id` and optional `referrer` URL. + * @param string $callback_url URL to notify for large batch size when async processing complete. + * + * @since 2.1.0 + * + * @see https://developers.kit.com/v4.html#bulk-add-subscribers-to-forms + * + * @return false|object + */ + public function add_subscribers_to_forms(array $forms_subscribers_ids, string $callback_url = '') + { + // Build parameters. + $options = ['additions' => $forms_subscribers_ids]; + if (!empty($callback_url)) { + $options['callback_url'] = $callback_url; + } + + // Send request. + return $this->post( + 'bulk/forms/subscribers', + $options + ); + } + /** * Adds a subscriber to a form by email address * * @param integer $form_id Form ID. * @param string $email_address Email Address. + * @param string $referrer Referrer. * * @see https://developers.convertkit.com/v4.html#add-subscriber-to-form-by-email-address * * @return false|mixed */ - public function add_subscriber_to_form_by_email(int $form_id, string $email_address) + public function add_subscriber_to_form_by_email(int $form_id, string $email_address, string $referrer = '') { + // Build parameters. + $options = ['email_address' => $email_address]; + + if (!empty($referrer)) { + $options['referrer'] = $referrer; + } + + // Send request. return $this->post( sprintf('forms/%s/subscribers', $form_id), - ['email_address' => $email_address] + $options ); } @@ -245,6 +281,7 @@ public function add_subscriber_to_form_by_email(int $form_id, string $email_addr * * @param integer $form_id Form ID. * @param integer $subscriber_id Subscriber ID. + * @param string $referrer Referrer URL. * * @see https://developers.convertkit.com/v4.html#add-subscriber-to-form * @@ -252,9 +289,20 @@ public function add_subscriber_to_form_by_email(int $form_id, string $email_addr * * @return false|mixed */ - public function add_subscriber_to_form(int $form_id, int $subscriber_id) + public function add_subscriber_to_form(int $form_id, int $subscriber_id, string $referrer = '') { - return $this->post(sprintf('forms/%s/subscribers/%s', $form_id, $subscriber_id)); + // Build parameters. + $options = []; + + if (!empty($referrer)) { + $options['referrer'] = $referrer; + } + + // Send request. + return $this->post( + sprintf('forms/%s/subscribers/%s', $form_id, $subscriber_id), + $options + ); } /** @@ -456,7 +504,7 @@ public function get_sequence_subscriptions( * * @see https://developers.convertkit.com/v4.html#list-tags * - * @return false|array + * @return mixed|array */ public function get_tags( bool $include_total_count = false, @@ -863,10 +911,26 @@ public function get_subscriber_id(string $email_address) ['email_address' => $email_address] ); + if (!$subscribers instanceof \stdClass) { + return false; + } + + if (!is_array($subscribers->subscribers)) { + return false; + } + if (!count($subscribers->subscribers)) { return false; } + if (!$subscribers->subscribers[0] instanceof \stdClass) { + return false; + } + + if (!is_int($subscribers->subscribers[0]->id)) { + return false; + } + // Return the subscriber's ID. return $subscribers->subscribers[0]->id; } @@ -878,7 +942,7 @@ public function get_subscriber_id(string $email_address) * * @see https://developers.convertkit.com/v4.html#get-a-subscriber * - * @return false|integer + * @return mixed|integer */ public function get_subscriber(int $subscriber_id) { @@ -895,7 +959,7 @@ public function get_subscriber(int $subscriber_id) * * @see https://developers.convertkit.com/v4.html#update-a-subscriber * - * @return false|mixed + * @return mixed */ public function update_subscriber( int $subscriber_id, @@ -930,7 +994,7 @@ public function update_subscriber( * * @see https://developers.convertkit.com/v4.html#unsubscribe-subscriber * - * @return false|object + * @return mixed|object */ public function unsubscribe_by_email(string $email_address) { @@ -949,7 +1013,7 @@ public function unsubscribe_by_email(string $email_address) * * @see https://developers.convertkit.com/v4.html#unsubscribe-subscriber * - * @return false|object + * @return mixed|object */ public function unsubscribe(int $subscriber_id) { @@ -967,7 +1031,7 @@ public function unsubscribe(int $subscriber_id) * * @see https://developers.convertkit.com/v4.html#list-tags-for-a-subscriber * - * @return false|array + * @return mixed|array */ public function get_subscriber_tags( int $subscriber_id, @@ -1044,7 +1108,7 @@ public function get_broadcasts( * * @see https://developers.convertkit.com/v4.html#create-a-broadcast * - * @return false|object + * @return mixed|object */ public function create_broadcast( string $subject = '', @@ -1103,7 +1167,7 @@ public function create_broadcast( * * @see https://developers.convertkit.com/v4.html#get-a-broadcast * - * @return false|object + * @return mixed|object */ public function get_broadcast(int $id) { @@ -1118,7 +1182,7 @@ public function get_broadcast(int $id) * * @see https://developers.convertkit.com/v4.html#get-stats * - * @return false|object + * @return mixed|object */ public function get_broadcast_stats(int $id) { @@ -1151,7 +1215,7 @@ public function get_broadcast_stats(int $id) * * @see https://developers.convertkit.com/#create-a-broadcast * - * @return false|object + * @return mixed|object */ public function update_broadcast( int $id, @@ -1213,7 +1277,7 @@ public function update_broadcast( * * @see https://developers.convertkit.com/v4.html#delete-a-broadcast * - * @return false|object + * @return mixed|object */ public function delete_broadcast(int $id) { @@ -1266,7 +1330,7 @@ public function get_webhooks( * * @throws \InvalidArgumentException If the event is not supported. * - * @return false|object + * @return mixed|object */ public function create_webhook(string $url, string $event, string $parameter = '') { @@ -1340,7 +1404,7 @@ public function create_webhook(string $url, string $event, string $parameter = ' * * @see https://developers.convertkit.com/v4.html#delete-a-webhook * - * @return false|object + * @return mixed|object */ public function delete_webhook(int $id) { @@ -1389,7 +1453,7 @@ public function get_custom_fields( * * @see https://developers.convertkit.com/v4.html#create-a-custom-field * - * @return false|object + * @return mixed|object */ public function create_custom_field(string $label) { @@ -1409,7 +1473,7 @@ public function create_custom_field(string $label) * * @see https://developers.convertkit.com/v4.html#bulk-create-custom-fields * - * @return false|object + * @return mixed|object */ public function create_custom_fields(array $labels, string $callback_url = '') { @@ -1444,7 +1508,7 @@ public function create_custom_fields(array $labels, string $callback_url = '') * * @see https://developers.convertkit.com/v4.html#update-a-custom-field * - * @return false|object + * @return mixed|object */ public function update_custom_field(int $id, string $label) { @@ -1463,7 +1527,7 @@ public function update_custom_field(int $id, string $label) * * @see https://developers.convertkit.com/#destroy-field * - * @return false|object + * @return mixed|object */ public function delete_custom_field(int $id) { @@ -1510,7 +1574,7 @@ public function get_purchases( * * @see https://developers.convertkit.com/v4.html#get-a-purchase * - * @return false|object + * @return mixed|object */ public function get_purchase(int $purchase_id) { @@ -1535,7 +1599,7 @@ public function get_purchase(int $purchase_id) * * @see https://developers.convertkit.com/v4.html#create-a-purchase * - * @return false|object + * @return mixed|object */ public function create_purchase( string $email_address, diff --git a/tests/ConvertKitAPITest.php b/tests/ConvertKitAPITest.php index b6839a3..9de4f49 100644 --- a/tests/ConvertKitAPITest.php +++ b/tests/ConvertKitAPITest.php @@ -95,6 +95,9 @@ protected function setUp(): void clientSecret: $_ENV['CONVERTKIT_OAUTH_CLIENT_SECRET'], accessToken: $_ENV['CONVERTKIT_OAUTH_ACCESS_TOKEN'] ); + + // Wait a second to avoid hitting a 429 rate limit. + sleep(1); } /** @@ -762,8 +765,8 @@ public function testGetGrowthStatsWithStartDate() $this->assertArrayHasKey('ending', $stats); // Assert start and end dates were honored. - $this->assertEquals($stats['starting'], $starting->format('Y-m-d') . 'T00:00:00-04:00'); - $this->assertEquals($stats['ending'], $ending->format('Y-m-d') . 'T23:59:59-04:00'); + $this->assertEquals($stats['starting'], $starting->format('Y-m-d') . 'T00:00:00-05:00'); + $this->assertEquals($stats['ending'], $ending->format('Y-m-d') . 'T23:59:59-05:00'); } /** @@ -799,8 +802,8 @@ public function testGetGrowthStatsWithEndDate() $this->assertArrayHasKey('ending', $stats); // Assert start and end dates were honored. - $this->assertEquals($stats['starting'], $starting->format('Y-m-d') . 'T00:00:00-04:00'); - $this->assertEquals($stats['ending'], $ending->format('Y-m-d') . 'T23:59:59-04:00'); + $this->assertEquals($stats['starting'], $starting->format('Y-m-d') . 'T00:00:00-05:00'); + $this->assertEquals($stats['ending'], $ending->format('Y-m-d') . 'T23:59:59-05:00'); } /** @@ -2699,6 +2702,261 @@ public function testGetTagSubscriptionsWithInvalidTagID() $result = $this->api->get_tag_subscriptions(12345); } + /** + * Test that add_subscribers_to_forms() returns the expected data. + * + * @since 2.1.0 + * + * @return void + */ + public function testAddSubscribersToForms() + { + // Create subscriber. + $emailAddress = $this->generateEmailAddress(); + $subscriber = $this->api->create_subscriber( + email_address: $emailAddress + ); + + // Set subscriber_id to ensure subscriber is unsubscribed after test. + $this->subscriber_ids[] = $subscriber->subscriber->id; + + // Add subscribers to forms. + $result = $this->api->add_subscribers_to_forms( + forms_subscribers_ids: [ + [ + 'form_id' => (int) $_ENV['CONVERTKIT_API_FORM_ID'], + 'subscriber_id' => $subscriber->subscriber->id, + ], + [ + 'form_id' => (int) $_ENV['CONVERTKIT_API_FORM_ID_2'], + 'subscriber_id' => $subscriber->subscriber->id, + ], + ] + ); + + // Assert no failures. + $this->assertCount(0, $result->failures); + + // Confirm result is an array comprising of each subscriber that was created. + $this->assertIsArray($result->subscribers); + } + + /** + * Test that add_subscribers_to_forms() returns the expected data + * when a referrer URL is specified. + * + * @since 2.1.0 + * + * @return void + */ + public function testAddSubscribersToFormsWithReferrer() + { + // Create subscriber. + $emailAddress = $this->generateEmailAddress(); + $subscriber = $this->api->create_subscriber( + email_address: $emailAddress + ); + + // Set subscriber_id to ensure subscriber is unsubscribed after test. + $this->subscriber_ids[] = $subscriber->subscriber->id; + + // Add subscribers to forms. + $result = $this->api->add_subscribers_to_forms( + forms_subscribers_ids: [ + [ + 'form_id' => (int) $_ENV['CONVERTKIT_API_FORM_ID'], + 'subscriber_id' => $subscriber->subscriber->id, + 'referrer' => 'https://mywebsite.com/bfpromo/', + ], + [ + 'form_id' => (int) $_ENV['CONVERTKIT_API_FORM_ID_2'], + 'subscriber_id' => $subscriber->subscriber->id, + 'referrer' => 'https://mywebsite.com/bfpromo/', + ], + ] + ); + + // Assert no failures. + $this->assertCount(0, $result->failures); + + // Confirm result is an array comprising of each subscriber that was created. + $this->assertIsArray($result->subscribers); + + // Assert referrer data set for subscribers. + foreach ($result->subscribers as $subscriber) { + $this->assertEquals( + $subscriber->referrer, + 'https://mywebsite.com/bfpromo/' + ); + } + } + + /** + * Test that add_subscribers_to_forms() returns the expected data + * when a referrer URL with UTM parameters is specified. + * + * @since 2.1.0 + * + * @return void + */ + public function testAddSubscribersToFormsWithReferrerUTMParams() + { + // Define referrer. + $referrerUTMParams = [ + 'utm_source' => 'facebook', + 'utm_medium' => 'cpc', + 'utm_campaign' => 'black_friday', + 'utm_term' => 'car_owners', + 'utm_content' => 'get_10_off', + ]; + $referrer = 'https://mywebsite.com/bfpromo/?' . http_build_query($referrerUTMParams); + + // Create subscriber. + $emailAddress = $this->generateEmailAddress(); + $subscriber = $this->api->create_subscriber( + email_address: $emailAddress + ); + + // Set subscriber_id to ensure subscriber is unsubscribed after test. + $this->subscriber_ids[] = $subscriber->subscriber->id; + + // Add subscribers to forms. + $result = $this->api->add_subscribers_to_forms( + forms_subscribers_ids: [ + [ + 'form_id' => (int) $_ENV['CONVERTKIT_API_FORM_ID'], + 'subscriber_id' => $subscriber->subscriber->id, + 'referrer' => $referrer, + ], + [ + 'form_id' => (int) $_ENV['CONVERTKIT_API_FORM_ID_2'], + 'subscriber_id' => $subscriber->subscriber->id, + 'referrer' => $referrer, + ], + ] + ); + + // Assert no failures. + $this->assertCount(0, $result->failures); + + // Confirm result is an array comprising of each subscriber that was created. + $this->assertIsArray($result->subscribers); + + // Assert referrer data set for subscribers. + foreach ($result->subscribers as $subscriber) { + $this->assertEquals( + $subscriber->referrer, + $referrer + ); + $this->assertEquals( + $subscriber->referrer_utm_parameters->source, + $referrerUTMParams['utm_source'] + ); + $this->assertEquals( + $subscriber->referrer_utm_parameters->medium, + $referrerUTMParams['utm_medium'] + ); + $this->assertEquals( + $subscriber->referrer_utm_parameters->campaign, + $referrerUTMParams['utm_campaign'] + ); + $this->assertEquals( + $subscriber->referrer_utm_parameters->term, + $referrerUTMParams['utm_term'] + ); + $this->assertEquals( + $subscriber->referrer_utm_parameters->content, + $referrerUTMParams['utm_content'] + ); + } + } + + /** + * Test that add_subscribers_to_forms() returns the expected errors + * when invalid Form IDs are specified. + * + * @since 2.1.0 + * + * @return void + */ + public function testAddSubscribersToFormsWithInvalidFormIDs() + { + // Create subscriber. + $emailAddress = $this->generateEmailAddress(); + $subscriber = $this->api->create_subscriber( + email_address: $emailAddress + ); + + // Set subscriber_id to ensure subscriber is unsubscribed after test. + $this->subscriber_ids[] = $subscriber->subscriber->id; + + // Add subscribers to forms. + $result = $this->api->add_subscribers_to_forms( + forms_subscribers_ids: [ + [ + 'form_id' => 9999999, + 'subscriber_id' => $subscriber->subscriber->id, + ], + [ + 'form_id' => 9999999, + 'subscriber_id' => $subscriber->subscriber->id, + ], + ] + ); + + // Assert failures. + $this->assertCount(2, $result->failures); + foreach ($result->failures as $failure) { + $this->assertEquals( + $failure->errors[0], + 'Form does not exist' + ); + } + } + + /** + * Test that add_subscribers_to_forms() returns the expected errors + * when invalid Subscriber IDs are specified. + * + * @since 2.1.0 + * + * @return void + */ + public function testAddSubscribersToFormsWithInvalidSubscriberIDs() + { + // Create subscriber. + $emailAddress = $this->generateEmailAddress(); + $subscriber = $this->api->create_subscriber( + email_address: $emailAddress + ); + + // Set subscriber_id to ensure subscriber is unsubscribed after test. + $this->subscriber_ids[] = $subscriber->subscriber->id; + + // Add subscribers to forms. + $result = $this->api->add_subscribers_to_forms( + forms_subscribers_ids: [ + [ + 'form_id' => (int) $_ENV['CONVERTKIT_API_FORM_ID'], + 'subscriber_id' => 999999, + ], + [ + 'form_id' => (int) $_ENV['CONVERTKIT_API_FORM_ID_2'], + 'subscriber_id' => 999999, + ], + ] + ); + + // Assert failures. + $this->assertCount(2, $result->failures); + foreach ($result->failures as $failure) { + $this->assertEquals( + $failure->errors[0], + 'Subscriber does not exist' + ); + } + } + /** * Test that add_subscriber_to_form_by_email() returns the expected data. * @@ -2731,6 +2989,118 @@ public function testAddSubscriberToFormByEmail() ); } + /** + * Test that add_subscriber_to_form_by_email() returns the expected data + * when a referrer is specified. + * + * @since 2.1.0 + * + * @return void + */ + public function testAddSubscriberToFormByEmailWithReferrer() + { + // Create subscriber. + $emailAddress = $this->generateEmailAddress(); + $subscriber = $this->api->create_subscriber( + email_address: $emailAddress, + ); + + // Set subscriber_id to ensure subscriber is unsubscribed after test. + $this->subscriber_ids[] = $subscriber->subscriber->id; + + // Add subscriber to form. + $result = $this->api->add_subscriber_to_form_by_email( + form_id: (int) $_ENV['CONVERTKIT_API_FORM_ID'], + email_address: $emailAddress, + referrer: 'https://mywebsite.com/bfpromo/', + ); + + $this->assertInstanceOf('stdClass', $result); + $this->assertArrayHasKey('subscriber', get_object_vars($result)); + $this->assertArrayHasKey('id', get_object_vars($result->subscriber)); + $this->assertEquals( + get_object_vars($result->subscriber)['email_address'], + $emailAddress + ); + + // Assert referrer data set for form subscriber. + $this->assertEquals( + $result->subscriber->referrer, + 'https://mywebsite.com/bfpromo/' + ); + } + + /** + * Test that add_subscriber_to_form_by_email() returns the expected data + * when a referrer is specified that includes UTM parameters. + * + * @since 2.1.0 + * + * @return void + */ + public function testAddSubscriberToFormByEmailWithReferrerUTMParams() + { + // Define referrer. + $referrerUTMParams = [ + 'utm_source' => 'facebook', + 'utm_medium' => 'cpc', + 'utm_campaign' => 'black_friday', + 'utm_term' => 'car_owners', + 'utm_content' => 'get_10_off', + ]; + $referrer = 'https://mywebsite.com/bfpromo/?' . http_build_query($referrerUTMParams); + + // Create subscriber. + $emailAddress = $this->generateEmailAddress(); + $subscriber = $this->api->create_subscriber( + email_address: $emailAddress, + ); + + // Set subscriber_id to ensure subscriber is unsubscribed after test. + $this->subscriber_ids[] = $subscriber->subscriber->id; + + // Add subscriber to form. + $result = $this->api->add_subscriber_to_form_by_email( + form_id: (int) $_ENV['CONVERTKIT_API_FORM_ID'], + email_address: $emailAddress, + referrer: $referrer, + ); + + $this->assertInstanceOf('stdClass', $result); + $this->assertArrayHasKey('subscriber', get_object_vars($result)); + $this->assertArrayHasKey('id', get_object_vars($result->subscriber)); + $this->assertEquals( + get_object_vars($result->subscriber)['email_address'], + $emailAddress + ); + + // Assert referrer data set for form subscriber. + $this->assertEquals( + $result->subscriber->referrer, + $referrer + ); + $this->assertEquals( + $result->subscriber->referrer_utm_parameters->source, + $referrerUTMParams['utm_source'] + ); + $this->assertEquals( + $result->subscriber->referrer_utm_parameters->medium, + $referrerUTMParams['utm_medium'] + ); + $this->assertEquals( + $result->subscriber->referrer_utm_parameters->campaign, + $referrerUTMParams['utm_campaign'] + ); + $this->assertEquals( + $result->subscriber->referrer_utm_parameters->term, + $referrerUTMParams['utm_term'] + ); + $this->assertEquals( + $result->subscriber->referrer_utm_parameters->content, + $referrerUTMParams['utm_content'] + ); + } + /** * Test that add_subscriber_to_form_by_email() throws a ClientException when an invalid * form ID is specified. @@ -2792,6 +3162,110 @@ public function testAddSubscriberToForm() $this->assertEquals(get_object_vars($result->subscriber)['id'], $subscriber->subscriber->id); } + /** + * Test that add_subscriber_to_form() returns the expected data + * when a referrer is specified. + * + * @since 2.1.0 + * + * @return void + */ + public function testAddSubscriberToFormWithReferrer() + { + // Create subscriber. + $subscriber = $this->api->create_subscriber( + email_address: $this->generateEmailAddress() + ); + + // Set subscriber_id to ensure subscriber is unsubscribed after test. + $this->subscriber_ids[] = $subscriber->subscriber->id; + + // Add subscriber to form. + $result = $this->api->add_subscriber_to_form( + form_id: (int) $_ENV['CONVERTKIT_API_FORM_ID'], + subscriber_id: $subscriber->subscriber->id, + referrer: 'https://mywebsite.com/bfpromo/', + ); + + $this->assertInstanceOf('stdClass', $result); + $this->assertArrayHasKey('subscriber', get_object_vars($result)); + $this->assertArrayHasKey('id', get_object_vars($result->subscriber)); + $this->assertEquals(get_object_vars($result->subscriber)['id'], $subscriber->subscriber->id); + + // Assert referrer data set for form subscriber. + $this->assertEquals( + $result->subscriber->referrer, + 'https://mywebsite.com/bfpromo/' + ); + } + + /** + * Test that add_subscriber_to_form() returns the expected data + * when a referrer is specified that includes UTM parameters. + * + * @since 2.1.0 + * + * @return void + */ + public function testAddSubscriberToFormWithReferrerUTMParams() + { + // Define referrer. + $referrerUTMParams = [ + 'utm_source' => 'facebook', + 'utm_medium' => 'cpc', + 'utm_campaign' => 'black_friday', + 'utm_term' => 'car_owners', + 'utm_content' => 'get_10_off', + ]; + $referrer = 'https://mywebsite.com/bfpromo/?' . http_build_query($referrerUTMParams); + + // Create subscriber. + $subscriber = $this->api->create_subscriber( + email_address: $this->generateEmailAddress() + ); + + // Set subscriber_id to ensure subscriber is unsubscribed after test. + $this->subscriber_ids[] = $subscriber->subscriber->id; + + // Add subscriber to form. + $result = $this->api->add_subscriber_to_form( + form_id: (int) $_ENV['CONVERTKIT_API_FORM_ID'], + subscriber_id: $subscriber->subscriber->id, + referrer: $referrer, + ); + + $this->assertInstanceOf('stdClass', $result); + $this->assertArrayHasKey('subscriber', get_object_vars($result)); + $this->assertArrayHasKey('id', get_object_vars($result->subscriber)); + $this->assertEquals(get_object_vars($result->subscriber)['id'], $subscriber->subscriber->id); + + // Assert referrer data set for form subscriber. + $this->assertEquals( + $result->subscriber->referrer, + $referrer + ); + $this->assertEquals( + $result->subscriber->referrer_utm_parameters->source, + $referrerUTMParams['utm_source'] + ); + $this->assertEquals( + $result->subscriber->referrer_utm_parameters->medium, + $referrerUTMParams['utm_medium'] + ); + $this->assertEquals( + $result->subscriber->referrer_utm_parameters->campaign, + $referrerUTMParams['utm_campaign'] + ); + $this->assertEquals( + $result->subscriber->referrer_utm_parameters->term, + $referrerUTMParams['utm_term'] + ); + $this->assertEquals( + $result->subscriber->referrer_utm_parameters->content, + $referrerUTMParams['utm_content'] + ); + } + /** * Test that add_subscriber_to_form() throws a ClientException when an invalid * form ID is specified. @@ -5086,11 +5560,11 @@ private function callPrivateMethod($obj, $name, array $args) * * @since 1.0.0 * - * @param string $domain Domain (default: convertkit.com). + * @param string $domain Domain (default: kit.com). * * @return string */ - private function generateEmailAddress($domain = 'convertkit.com') + private function generateEmailAddress($domain = 'kit.com') { return 'php-sdk-' . date('Y-m-d-H-i-s') . '-php-' . PHP_VERSION_ID . '@' . $domain; }