diff --git a/src/ConvertKit_API_Traits.php b/src/ConvertKit_API_Traits.php index 82f3302..a5ec402 100644 --- a/src/ConvertKit_API_Traits.php +++ b/src/ConvertKit_API_Traits.php @@ -818,21 +818,22 @@ public function get_sequence_email( } /** - * Updates a sequence - * - * @param integer $sequence_id Sequence ID. - * @param integer $email_id Sequence Email ID. - * @param string|null $subject Subject line of the email. - * @param integer|null $delay_value Number of days or hours to wait before sending this email after the previous one. - * @param string|null $delay_unit Unit for the send delay. Use `days` for schedule-aware delivery, `hours` for a fixed hourly delay. - * @param string|null $preview_text Preview text shown in email clients before the email is opened. - * @param string|null $content HTML body content of the email. - * @param integer|null $email_template_id ID of the email template to use for layout and styling. - * @param boolean|null $published Whether the email is active and will be sent to subscribers. - * @param array|null $send_days Days of the week this email may be sent. Defaults to all 7 days (inherits the sequence schedule). Pass a subset to restrict delivery, or null to reset to all days. - * @param integer|null $position Zero-based position of the email in the sequence. Assigned automatically after the last email if omitted. - * - * @see https://developers.kit.com/api-reference/sequences/create-a-sequence + * Updates a sequence email. + * + * @param integer $sequence_id Sequence ID. + * @param integer $email_id Sequence Email ID. + * @param string|null $subject Subject line of the email. + * @param integer|null $delay_value Number of days or hours to wait before sending this email after the previous one. + * @param string|null $delay_unit Unit for the send delay. Use `days` for schedule-aware delivery, `hours` for a fixed hourly delay. + * @param string|null $preview_text Preview text shown in email clients before the email is opened. + * @param string|null $content HTML body content of the email. + * @param integer|null $email_template_id ID of the email template to use for layout and styling. + * @param boolean|null $published Whether the email is active and will be sent to subscribers. + * @param array|null $send_days Days of the week this email may be sent. Defaults to all 7 days (inherits the sequence schedule). Pass a subset to restrict delivery, or null to reset to all days. + * @param integer|null $position Zero-based position of the email in the sequence. Assigned automatically after the last email if omitted. + * @param boolean $allow_content_loss Confirm changing $email_template_id without $content, when this would discard the email's existing content. + * + * @see https://developers.kit.com/api-reference/sequence-emails/update-a-sequence-email * * @return mixed|object */ @@ -848,6 +849,7 @@ public function update_sequence_email( bool|null $published = null, array|null $send_days = null, int|null $position = null, + bool $allow_content_loss = false, ) { // Build parameters. $options = ['send_days' => $send_days]; @@ -879,6 +881,9 @@ public function update_sequence_email( if (!is_null($position)) { $options['position'] = $position; } + if ($allow_content_loss) { + $options['allow_content_loss'] = true; + } // Send request. return $this->put( @@ -2137,26 +2142,27 @@ public function get_broadcasts_stats( /** * Update a broadcast. * - * @param integer $id Broadcast ID. - * @param string $subject The broadcast email's subject. - * @param string $content The broadcast's email HTML content. - * @param string $description An internal description of this broadcast. - * @param boolean $public Specifies whether or not this is a public post. - * @param \DateTime|null $published_at Specifies the time that this post was published (applicable - * only to public posts). - * @param \DateTime|null $send_at Time that this broadcast should be sent; leave blank to create - * a draft broadcast. If set to a future time, this is the time that - * the broadcast will be scheduled to send. - * @param string $email_address Sending email address; leave blank to use your account's - * default sending email address. - * @param string $email_template_id ID of the email template to use; leave blank to use your - * account's default email template. - * @param string $thumbnail_alt Specify the ALT attribute of the public thumbnail image - * (applicable only to public posts). - * @param string $thumbnail_url Specify the URL of the thumbnail image to accompany the broadcast - * post (applicable only to public posts). - * @param string $preview_text Specify the preview text of the email. - * @param array $subscriber_filter Filter subscriber(s) to send the email to. + * @param integer $id Broadcast ID. + * @param string $subject The broadcast email's subject. + * @param string $content The broadcast's email HTML content. + * @param string $description An internal description of this broadcast. + * @param boolean $public Specifies whether or not this is a public post. + * @param \DateTime|null $published_at Specifies the time that this post was published (applicable + * only to public posts). + * @param \DateTime|null $send_at Time that this broadcast should be sent; leave blank to create + * a draft broadcast. If set to a future time, this is the time that + * the broadcast will be scheduled to send. + * @param string $email_address Sending email address; leave blank to use your account's + * default sending email address. + * @param string $email_template_id ID of the email template to use; leave blank to use your + * account's default email template. + * @param string $thumbnail_alt Specify the ALT attribute of the public thumbnail image + * (applicable only to public posts). + * @param string $thumbnail_url Specify the URL of the thumbnail image to accompany the broadcast + * post (applicable only to public posts). + * @param string $preview_text Specify the preview text of the email. + * @param array $subscriber_filter Filter subscriber(s) to send the email to. + * @param boolean $allow_content_loss Confirm changing $email_template_id without $content, when this would discard the broadcast's existing content. * * @see https://developers.kit.com/api-reference/broadcasts/update-a-broadcast * @@ -2175,7 +2181,8 @@ public function update_broadcast( string $thumbnail_alt = '', string $thumbnail_url = '', string $preview_text = '', - array $subscriber_filter = [] + array $subscriber_filter = [], + bool $allow_content_loss = false ) { $options = [ 'email_template_id' => $email_template_id, @@ -2206,6 +2213,10 @@ public function update_broadcast( unset($options['published_at'], $options['thumbnail_alt'], $options['thumbnail_url']); } + if ($allow_content_loss) { + $options['allow_content_loss'] = true; + } + // Send request. return $this->put( sprintf('broadcasts/%s', $id), diff --git a/tests/TestsTrait.php b/tests/TestsTrait.php index 20bb2f0..ea41a53 100644 --- a/tests/TestsTrait.php +++ b/tests/TestsTrait.php @@ -1783,6 +1783,59 @@ public function testCreateGetUpdateAndDeleteSequenceEmail() $this->assertLastResponseStatusCode(204); } + /** + * Test that update_sequence_email() returns an error when changing the email template + * without content would discard the email's content, and changes the email template + * when allow_content_loss is specified. + * + * @since 2.9.0 + * + * @return void + */ + public function testUpdateSequenceEmailWithAllowContentLoss() + { + $emailTemplateID = $this->getStartingPointEmailTemplateID(); + if (!$emailTemplateID) { + $this->markTestSkipped('No Starting point email template exists on the Kit account.'); + } + + // Create a draft sequence email with content. + $result = $this->api->create_sequence_email( + sequence_id: (int) $_ENV['CONVERTKIT_API_SEQUENCE_ID'], + subject: 'Test Sequence Email', + delay_value: 1, + delay_unit: 'days', + content: 'Test Content', + email_template_id: (int) $_ENV['CONVERTKIT_API_EMAIL_TEMPLATE_ID'], + published: false + ); + $sequenceEmailID = $result->email->id; + + // Confirm changing to a Starting point template without content errors, as it would discard the content. + $this->assertApiError( + function () use ($sequenceEmailID, $emailTemplateID) { + return $this->api->update_sequence_email( + sequence_id: (int) $_ENV['CONVERTKIT_API_SEQUENCE_ID'], + email_id: $sequenceEmailID, + email_template_id: $emailTemplateID + ); + } + ); + + // Confirm the email template is changed when allow_content_loss is specified. + $result = $this->api->update_sequence_email( + sequence_id: (int) $_ENV['CONVERTKIT_API_SEQUENCE_ID'], + email_id: $sequenceEmailID, + email_template_id: $emailTemplateID, + allow_content_loss: true + ); + $this->assertEquals($emailTemplateID, $result->email->email_template_id); + + // Delete Sequence Email. + $this->api->delete_sequence_email((int) $_ENV['CONVERTKIT_API_SEQUENCE_ID'], $sequenceEmailID); + $this->assertLastResponseStatusCode(204); + } + /** * Test that get_sequence_email() returns the expected data. * @@ -5618,6 +5671,53 @@ public function testCreateAndUpdateDraftBroadcast() $this->assertLastResponseStatusCode(204); } + /** + * Test that update_broadcast() returns an error when changing the email template + * without content would discard the broadcast's content, and changes the email + * template when allow_content_loss is specified. + * + * @since 2.9.0 + * + * @return void + */ + public function testUpdateBroadcastWithAllowContentLoss() + { + $emailTemplateID = $this->getStartingPointEmailTemplateID(); + if (!$emailTemplateID) { + $this->markTestSkipped('No Starting point email template exists on the Kit account.'); + } + + // Create a broadcast with content. + $result = $this->api->create_broadcast( + subject: 'Test Subject', + content: 'Test Content', + description: 'Test Broadcast from PHP SDK', + email_template_id: $_ENV['CONVERTKIT_API_EMAIL_TEMPLATE_ID'] + ); + $broadcastID = $result->broadcast->id; + + // Set broadcast_ids to ensure broadcast is deleted after test. + $this->broadcast_ids[] = $broadcastID; + + // Confirm changing to a Starting point template without content errors, as it would discard the content. + $this->assertApiError( + function () use ($broadcastID, $emailTemplateID) { + return $this->api->update_broadcast( + id: $broadcastID, + email_template_id: (string) $emailTemplateID + ); + } + ); + + // Confirm the email template is changed when allow_content_loss is specified. + $result = $this->api->update_broadcast( + id: $broadcastID, + email_template_id: (string) $emailTemplateID, + allow_content_loss: true + ); + $this->assertEquals($emailTemplateID, $result->broadcast->email_template->id); + } + /** * Test that create_broadcast() works when specifying valid published_at and send_at values. * @@ -7795,6 +7895,32 @@ public function generateWebhookSignature($payload, $secret, $timestamp = null) ); } + /** + * Returns the ID of an email template in the Starting point category, excluding the + * email template defined in CONVERTKIT_API_EMAIL_TEMPLATE_ID. + * + * @since 2.9.0 + * + * @return integer|false + */ + public function getStartingPointEmailTemplateID() + { + $result = $this->api->get_email_templates(); + + foreach ($result->email_templates as $emailTemplate) { + if ($emailTemplate->category !== 'Starting point') { + continue; + } + if ($emailTemplate->id === (int) $_ENV['CONVERTKIT_API_EMAIL_TEMPLATE_ID']) { + continue; + } + + return $emailTemplate->id; + } + + return false; + } + /** * Checks if string is html. *