diff --git a/.env.dist.testing b/.env.dist.testing index f61980a..3acd54e 100644 --- a/.env.dist.testing +++ b/.env.dist.testing @@ -12,3 +12,4 @@ CONVERTKIT_API_TAG_NAME_2="gravityforms-tag-1" CONVERTKIT_API_TAG_ID_2="2907192" CONVERTKIT_API_SUBSCRIBER_EMAIL="optin@n7studios.com" CONVERTKIT_API_SUBSCRIBER_ID="1579118532" +CONVERTKIT_API_EMAIL_TEMPLATE_ID="2201089" diff --git a/phpcs.xml b/phpcs.xml index 3b059b2..9a763a5 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -72,7 +72,7 @@ - + diff --git a/src/ConvertKit_API_Traits.php b/src/ConvertKit_API_Traits.php index 92c8abd..b1131f8 100644 --- a/src/ConvertKit_API_Traits.php +++ b/src/ConvertKit_API_Traits.php @@ -415,6 +415,156 @@ public function get_sequences( ); } + /** + * Create a sequence + * + * @param string $name The name of the sequence. + * @param string $email_address The sending email address to use. Uses the account's sending email address if not provided. + * @param integer $email_template_id Id of the email template to use. + * @param array $send_days The days of the week to send the sequence on. Must be one of: `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, `saturday`, `sunday`. + * @param integer $send_hour The hour of the day to send the sequence at. Must be an integer between 0 and 23. + * @param string $time_zone The timezone to use for the sequence. Must be a valid IANA timezone string. + * @param boolean $active Use `true` to activate the sequence, `false` to deactivate it. + * @param boolean $repeat When `true`, subscribers can restart the sequence multiple times. + * @param boolean $hold When `true`, subscribers added via Visual Automations stay in the sequence after receiving the last email. + * @param array> $exclude_subscriber_sources The subscriber sources to exclude from the sequence. Uses the account's default exclude subscriber sources if not provided. + * + * @see https://developers.kit.com/api-reference/sequences/create-a-sequence + * + * @return mixed|object + */ + public function create_sequence( + string $name, + string $email_address = '', + int $email_template_id = 0, + array $send_days = [], + int $send_hour = 0, + string $time_zone = '', + bool $active = true, + bool $repeat = false, + bool $hold = false, + array $exclude_subscriber_sources = [] + ) { + $options = [ + 'name' => $name, + 'email_address' => $email_address, + 'email_template_id' => $email_template_id, + 'send_hour' => $send_hour, + 'time_zone' => $time_zone, + 'active' => $active, + 'repeat' => $repeat, + 'hold' => $hold, + ]; + if (count($send_days)) { + $options['send_days'] = $send_days; + } + if (count($exclude_subscriber_sources)) { + $options['exclude_subscriber_sources'] = $exclude_subscriber_sources; + } + + // Iterate through options, removing blank entries. + foreach ($options as $key => $value) { + if (is_string($value) && strlen($value) === 0) { + unset($options[$key]); + } + } + + // Send request. + return $this->post( + 'sequences', + $options + ); + } + + /** + * Get a sequence. + * + * @param integer $id Sequence ID. + * + * @see https://developers.kit.com/api-reference/sequences/get-a-sequence + * + * @return mixed|object + */ + public function get_sequence(int $id) + { + return $this->get(sprintf('sequences/%s', $id)); + } + + /** + * Updates a sequence + * + * @param integer $sequence_id Sequence ID. + * @param string $name The name of the sequence. + * @param string $email_address The sending email address to use. Uses the account's sending email address if not provided. + * @param integer $email_template_id Id of the email template to use. + * @param array $send_days The days of the week to send the sequence on. Must be one of: `monday`, `tuesday`, `wednesday`, `thursday`, `friday`, `saturday`, `sunday`. + * @param integer $send_hour The hour of the day to send the sequence at. Must be an integer between 0 and 23. + * @param string $time_zone The timezone to use for the sequence. Must be a valid IANA timezone string. + * @param boolean $active Use `true` to activate the sequence, `false` to deactivate it. + * @param boolean $repeat When `true`, subscribers can restart the sequence multiple times. + * @param boolean $hold When `true`, subscribers added via Visual Automations stay in the sequence after receiving the last email. + * @param array> $exclude_subscriber_sources The subscriber sources to exclude from the sequence. Uses the account's default exclude subscriber sources if not provided. + * + * @see https://developers.kit.com/api-reference/sequences/create-a-sequence + * + * @return mixed|object + */ + public function update_sequence( + int $sequence_id, + string $name = '', + string $email_address = '', + int $email_template_id = 0, + array $send_days = [], + int $send_hour = 0, + string $time_zone = '', + bool $active = true, + bool $repeat = false, + bool $hold = false, + array $exclude_subscriber_sources = [] + ) { + $options = [ + 'name' => $name, + 'email_address' => $email_address, + 'email_template_id' => $email_template_id, + 'send_days' => $send_days, + 'send_hour' => $send_hour, + 'time_zone' => $time_zone, + 'active' => $active, + 'repeat' => $repeat, + 'hold' => $hold, + ]; + if (count($exclude_subscriber_sources)) { + $options['exclude_subscriber_sources'] = $exclude_subscriber_sources; + } + + // Iterate through options, removing blank entries. + foreach ($options as $key => $value) { + if (is_string($value) && strlen($value) === 0) { + unset($options[$key]); + } + } + + // Send request. + return $this->put( + sprintf('sequences/%s', $sequence_id), + $options + ); + } + + /** + * Deletes a sequence. + * + * @param integer $id Sequence ID. + * + * @see https://developers.kit.com/api-reference/sequences/delete-a-sequence + * + * @return mixed|object + */ + public function delete_sequence(int $id) + { + return $this->delete(sprintf('sequences/%s', $id)); + } + /** * Adds subscriber to sequence by email address * @@ -2067,8 +2217,8 @@ public function post(string $endpoint, array $args = []) /** * Performs a PUT 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/ConvertKitAPITest.php b/tests/ConvertKitAPITest.php index 8259adc..0fa5e42 100644 --- a/tests/ConvertKitAPITest.php +++ b/tests/ConvertKitAPITest.php @@ -1059,6 +1059,135 @@ public function testGetSequencesPagination() $this->assertCount(1, $result->sequences); } + /** + * Test that create_sequence(), update_sequence() and delete_sequence() works. + * + * We do all tests in a single function, so we don't end up with unnecessary + * Sequences remaining on the Kit account when running tests, which might impact + * other tests that expect (or do not expect) specific Sequences. + * + * @since 2.5.0 + * + * @return void + */ + public function testCreateUpdateAndDeleteSequence() + { + // Create a sequence. + $result = $this->api->create_sequence( + name: 'Test Sequence', + email_address: 'wordpress@convertkit.com', + email_template_id: (int) $_ENV['CONVERTKIT_API_EMAIL_TEMPLATE_ID'], + send_days: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], + send_hour: 12, + time_zone: 'America/Los_Angeles', + active: false, + repeat: false, + hold: false + ); + $sequenceID = $result->sequence->id; + + // Confirm the Sequence saved. + $result = get_object_vars($result->sequence); + $this->assertArrayHasKey('id', $result); + $this->assertEquals('Test Sequence', $result['name']); + $this->assertEquals('wordpress@convertkit.com', $result['email_address']); + $this->assertEquals((int) $_ENV['CONVERTKIT_API_EMAIL_TEMPLATE_ID'], $result['email_template_id']); + $this->assertEquals(['monday', 'tuesday', 'wednesday', 'thursday', 'friday'], $result['send_days']); + $this->assertEquals(12, $result['send_hour']); + $this->assertEquals('America/Los_Angeles', $result['time_zone']); + $this->assertEquals(false, $result['active']); + $this->assertEquals(false, $result['repeat']); + $this->assertEquals(false, $result['hold']); + + // Update the existing sequence. + $result = $this->api->update_sequence( + sequence_id: $sequenceID, + name: 'Edited Test Sequence', + email_address: 'wordpress@convertkit.com', + email_template_id: (int) $_ENV['CONVERTKIT_API_EMAIL_TEMPLATE_ID'], + send_days: ['saturday', 'sunday'], + send_hour: 13, + time_zone: 'America/New_York', + active: true, + repeat: true, + hold: true + ); + + // Confirm the changes saved. + $result = get_object_vars($result->sequence); + $this->assertArrayHasKey('id', $result); + $this->assertEquals('Edited Test Sequence', $result['name']); + $this->assertEquals('wordpress@convertkit.com', $result['email_address']); + $this->assertEquals((int) $_ENV['CONVERTKIT_API_EMAIL_TEMPLATE_ID'], $result['email_template_id']); + $this->assertEquals(['saturday', 'sunday'], $result['send_days']); + $this->assertEquals(13, $result['send_hour']); + $this->assertEquals('America/New_York', $result['time_zone']); + $this->assertEquals(true, $result['active']); + $this->assertEquals(true, $result['repeat']); + $this->assertEquals(true, $result['hold']); + + // Delete Sequence. + $this->api->delete_sequence($sequenceID); + $this->assertEquals(204, $this->api->getResponseInterface()->getStatusCode()); + } + + /** + * Test that get_sequence() returns the expected data. + * + * @since 2.5.0 + * + * @return void + */ + public function testGetSequence() + { + $result = $this->api->get_sequence((int) $_ENV['CONVERTKIT_API_SEQUENCE_ID']); + $this->assertInstanceOf('stdClass', $result); + $this->assertArrayHasKey('sequence', get_object_vars($result)); + $this->assertArrayHasKey('id', get_object_vars($result->sequence)); + } + + /** + * Test that get_sequence() throws a ClientException when an invalid + * sequence ID is specified. + * + * @since 2.5.0 + * + * @return void + */ + public function testGetSequenceWithInvalidSequenceID() + { + $this->expectException(ClientException::class); + $this->api->get_sequence(12345); + } + + /** + * Test that update_sequence() throws a ClientException when an invalid + * sequence ID is specified. + * + * @since 2.5.0 + * + * @return void + */ + public function testUpdateSequenceWithInvalidSequenceID() + { + $this->expectException(ClientException::class); + $this->api->update_sequence(12345); + } + + /** + * Test that delete_sequence() throws a ClientException when an invalid + * sequence ID is specified. + * + * @since 2.5.0 + * + * @return void + */ + public function testDeleteSequenceWithInvalidSequenceID() + { + $this->expectException(ClientException::class); + $this->api->delete_sequence(12345); + } + /** * Test that add_subscriber_to_sequence_by_email() returns the expected data. *