From 4383fe4569c693c5431393d3ff582b1ec707383e Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 29 Oct 2024 10:31:36 +0800 Subject: [PATCH 1/6] Broadcasts Importer: Refactor functions --- .../class-convertkit-broadcasts-importer.php | 286 +++++++++++------- 1 file changed, 184 insertions(+), 102 deletions(-) diff --git a/includes/class-convertkit-broadcasts-importer.php b/includes/class-convertkit-broadcasts-importer.php index ede6f41b..08b16cd3 100644 --- a/includes/class-convertkit-broadcasts-importer.php +++ b/includes/class-convertkit-broadcasts-importer.php @@ -14,6 +14,15 @@ */ class ConvertKit_Broadcasts_Importer { + /** + * Holds the API class. + * + * @since 2.6.4 + * + * @var bool|ConvertKit_API_V4 + */ + private $api = false; + /** * Holds the Broadcasts Settings class. * @@ -32,6 +41,24 @@ class ConvertKit_Broadcasts_Importer { */ private $media_library = false; + /** + * Holds the Settings class. + * + * @since 2.6.4 + * + * @var bool|ConvertKit_Settings + */ + private $settings = false; + + /** + * Holds the Logging class. + * + * @since 2.6.4 + * + * @var bool|ConvertKit_Log + */ + private $log = false; + /** * Constructor. Registers actions and filters to output ConvertKit Forms and Landing Pages * on the frontend web site. @@ -40,6 +67,12 @@ class ConvertKit_Broadcasts_Importer { */ public function __construct() { + // Initialize required classes. + $this->broadcasts_settings = new ConvertKit_Settings_Broadcasts(); + $this->media_library = new ConvertKit_Media_Library(); + $this->settings = new ConvertKit_Settings(); + $this->log = new ConvertKit_Log( CONVERTKIT_PLUGIN_PATH ); + // Create WordPress Posts when the ConvertKit Posts Resource is refreshed. add_action( 'convertkit_resource_refreshed_posts', array( $this, 'refresh' ) ); @@ -57,12 +90,6 @@ public function __construct() { */ public function refresh( $broadcasts ) { - // Initialize required classes. - $this->broadcasts_settings = new ConvertKit_Settings_Broadcasts(); - $this->media_library = new ConvertKit_Media_Library(); - $settings = new ConvertKit_Settings(); - $log = new ConvertKit_Log( CONVERTKIT_PLUGIN_PATH ); - // Bail if Broadcasts to Posts are disabled. if ( ! $this->broadcasts_settings->enabled() ) { return; @@ -74,142 +101,188 @@ public function refresh( $broadcasts ) { } // Bail if the Plugin Access Token has not been configured. - if ( ! $settings->has_access_and_refresh_token() ) { + if ( ! $this->settings->has_access_and_refresh_token() ) { return; } // Initialize the API. - $api = new ConvertKit_API_V4( + $this->api = new ConvertKit_API_V4( CONVERTKIT_OAUTH_CLIENT_ID, CONVERTKIT_OAUTH_CLIENT_REDIRECT_URI, - $settings->get_access_token(), - $settings->get_refresh_token(), - $settings->debug_enabled(), + $this->settings->get_access_token(), + $this->settings->get_refresh_token(), + $this->settings->debug_enabled(), 'broadcasts_importer' ); // Check that we're using the ConvertKit WordPress Libraries 1.3.8 or higher. // If another ConvertKit Plugin is active and out of date, its libraries might // be loaded that don't have this method. - if ( ! method_exists( $api, 'get_post' ) ) { + if ( ! method_exists( $this->api, 'get_post' ) ) { return; } foreach ( $broadcasts as $broadcast_id => $broadcast ) { // If a WordPress Post exists for this Broadcast ID, we previously imported it - skip it. if ( $this->broadcast_exists_as_post( $broadcast_id ) ) { - if ( $settings->debug_enabled() ) { - $log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . ' already exists as a WordPress Post. Skipping...' ); - } - continue; - } - - // Fetch Broadcast's content. - // We need to query wordpress/posts/{id} to fetch the full Broadcast information and content. - $broadcast = $api->get_post( $broadcast_id ); - - // Skip if an error occured fetching the Broadcast. - if ( is_wp_error( $broadcast ) ) { - if ( $settings->debug_enabled() ) { - $log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error fetching from API: ' . $broadcast->get_error_message() ); + if ( $this->settings->debug_enabled() ) { + $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . ' already exists as a WordPress Post. Skipping...' ); } continue; } // Skip if the published_at date is older than the 'Earliest Date' setting. if ( strtotime( $broadcast['published_at'] ) < strtotime( $this->broadcasts_settings->published_at_min_date() ) ) { - if ( $settings->debug_enabled() ) { - $log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . ' published_at date is before ' . $this->broadcasts_settings->published_at_min_date() . '. Skipping...' ); + if ( $this->settings->debug_enabled() ) { + $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . ' published_at date is before ' . $this->broadcasts_settings->published_at_min_date() . '. Skipping...' ); } continue; } - // Create Post as a draft, without content or a Featured Image. - // This gives us a Post ID we can then use if we need to import - // the Featured Image and/or Broadcast images to the Media Library, - // storing them against the Post ID just created. - $post_id = wp_insert_post( - $this->build_post_args( - $broadcast, - $this->broadcasts_settings->author_id(), - $this->broadcasts_settings->category_id() - ), - true + // Import the broadcast. + $this->import_broadcast( + $broadcast_id, + $this->broadcasts_settings->post_status(), + $this->broadcasts_settings->author_id(), + $this->broadcasts_settings->category_id(), + $this->broadcasts_settings->import_thumbnail(), + $this->broadcasts_settings->import_images(), + $this->broadcasts_settings->no_styles() ); + } - // Skip if an error occured. - if ( is_wp_error( $post_id ) ) { - if ( $settings->debug_enabled() ) { - $log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_insert_post(): ' . $post_id->get_error_message() ); - } - continue; + } + + /** + * Imports the given Kit Broadcast ID to a new WordPress Post. + * + * @since 2.6.4 + * + * @param int $broadcast_id Broadcast ID. + * @param string $post_status WordPress Post Status to save Post as (publish,draft etc). + * @param int $author_id WordPress User ID to assign as the author of the Post. + * @param bool|int $category_id WordPress Category to assign to the Post. + * @param bool $import_thumbnail Store Broadcast's thumbnail as the WordPress Post's Featured Image. + * @param bool $import_images Store Broadcast's inline images in the Media Library. + * @param bool $disable_styles Remove CSS styles and layout elements from the Broadcast content. + * + * @return WP_Error|int + */ + public function import_broadcast( $broadcast_id, $post_status = 'publish', $author_id = 1, $category_id = false, $import_thumbnail = false, $import_images = false, $disable_styles = false ) { + + // Fetch Broadcast's content. + // We need to query wordpress/posts/{id} to fetch the full Broadcast information and content. + $broadcast = $this->api->get_post( $broadcast_id ); + + // Bail if an error occured fetching the Broadcast. + if ( is_wp_error( $broadcast ) ) { + if ( $this->settings->debug_enabled() ) { + $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error fetching from API: ' . $broadcast->get_error_message() ); } - // Parse the Broadcast's content, storing it in the Post. - $post_id = wp_update_post( - array( - 'ID' => $post_id, - 'post_content' => $this->parse_broadcast_content( $broadcast['content'], $post_id ), + return $broadcast; + } + + // Create Post as a draft, without content or a Featured Image. + // This gives us a Post ID we can then use if we need to import + // the Featured Image and/or Broadcast images to the Media Library, + // storing them against the Post ID just created. + $post_id = wp_insert_post( + $this->build_post_args( + $broadcast, + $author_id, + $category_id + ), + true + ); + + // Bail if an error occured. + if ( is_wp_error( $post_id ) ) { + if ( $this->settings->debug_enabled() ) { + $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_insert_post(): ' . $post_id->get_error_message() ); + } + + return $post_id; + } + + // Parse the Broadcast's content, storing it in the Post. + $post_id = wp_update_post( + array( + 'ID' => $post_id, + 'post_content' => $this->parse_broadcast_content( + $post_id, + $broadcast['content'], + $broadcast['title'], + $import_images, + $disable_styles ), - true - ); + ), + true + ); - // Skip if an error occured. - if ( is_wp_error( $post_id ) ) { - if ( $settings->debug_enabled() ) { - $log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_update_post() when adding Broadcast content: ' . $post_id->get_error_message() ); - } - continue; + // Bail if an error occured updating the Post. + if ( is_wp_error( $post_id ) ) { + if ( $this->settings->debug_enabled() ) { + $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_update_post() when adding Broadcast content: ' . $post_id->get_error_message() ); } - // If a Product is specified, apply it as the Restrict Content setting. - if ( $broadcast['is_paid'] && $broadcast['product_id'] ) { - // Fetch Post's settings. - $convertkit_post = new ConvertKit_Post( $post_id ); - $meta = $convertkit_post->get(); + return $post_id; + } + + // If a Product is specified, apply it as the Restrict Content setting. + if ( $broadcast['is_paid'] && $broadcast['product_id'] ) { + // Fetch Post's settings. + $convertkit_post = new ConvertKit_Post( $post_id ); + $meta = $convertkit_post->get(); - // Define Restrict Content setting. - $meta['restrict_content'] = 'product_' . $broadcast['product_id']; + // Define Restrict Content setting. + $meta['restrict_content'] = 'product_' . $broadcast['product_id']; - // Save Post's settings. - $convertkit_post->save( $meta ); + // Save Post's settings. + $convertkit_post->save( $meta ); - if ( $settings->debug_enabled() ) { - $log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Set Restrict Content = ' . $broadcast['product_id'] ); - } + if ( $this->settings->debug_enabled() ) { + $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Set Restrict Content = ' . $broadcast['product_id'] ); } + } - // If the Import Thumbnail setting is enabled, and the Broadcast has an image, save it to the Media Library and link it to the Post. - if ( $this->broadcasts_settings->import_thumbnail() ) { - $result = $this->add_broadcast_image_to_post( $broadcast, $post_id ); + // If the Import Thumbnail setting is enabled, and the Broadcast has an image, save it to the Media Library and link it to the Post. + if ( $import_thumbnail ) { + $result = $this->add_broadcast_image_to_post( $broadcast, $post_id ); - if ( is_wp_error( $result ) && $settings->debug_enabled() ) { - $log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on add_broadcast_image_to_post(): ' . $result->get_error_message() ); - } - } elseif ( $settings->debug_enabled() ) { - $log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Skipping thumbnail.' ); + if ( is_wp_error( $result ) && $this->settings->debug_enabled() ) { + $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on add_broadcast_image_to_post(): ' . $result->get_error_message() ); } + } elseif ( $this->settings->debug_enabled() ) { + $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Skipping thumbnail.' ); + } - // Transition the Post to the defined Post Status in the settings, now that the image has been added to it. - $post_id = wp_update_post( - array( - 'ID' => $post_id, - 'post_status' => $this->broadcasts_settings->post_status(), - ), - true - ); + // Transition the Post to the defined Post Status in the settings, now that the image has been added to it. + $post_id = wp_update_post( + array( + 'ID' => $post_id, + 'post_status' => $post_status, + ), + true + ); - // Maybe log if an error occured updating the Post to the publish status. - if ( is_wp_error( $post_id ) ) { - if ( $settings->debug_enabled() ) { - $log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_update_post() when transitioning post status from draft to publish: ' . $post_id->get_error_message() ); - } - } - if ( $settings->debug_enabled() ) { - $log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Added as Post ID #' . $post_id ); + // Maybe log if an error occured updating the Post to the publish status. + if ( is_wp_error( $post_id ) ) { + if ( $this->settings->debug_enabled() ) { + $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_update_post() when transitioning post status from draft to publish: ' . $post_id->get_error_message() ); } + + return $post_id; + } + + // Import successful. + // Maybe log success. + if ( $this->settings->debug_enabled() ) { + $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Added as Post ID #' . $post_id ); } + return $post_id; + } /** @@ -269,7 +342,9 @@ private function build_post_args( $broadcast, $author_id, $category_id = false ) ); // If a Category was supplied, assign the Post to the given Category ID when created. - $post_args['post_category'] = array( $category_id ); + if ( $category_id ) { + $post_args['post_category'] = array( $category_id ); + } /** * Define the wp_insert_post() compatible arguments for importing a ConvertKit Broadcast @@ -306,11 +381,14 @@ private function build_post_args( $broadcast, $author_id, $category_id = false ) * * @since 2.2.9 * - * @param string $broadcast_content Broadcast Content. * @param int $post_id WordPress Post ID. + * @param string $broadcast_content Broadcast Content. + * @param string $broadcast_title Broadcast Title. + * @param bool $import_images Import images to Media Library. + * @param bool $disable_styles Disable CSS styles in content. * @return string Parsed Content. */ - private function parse_broadcast_content( $broadcast_content, $post_id ) { + private function parse_broadcast_content( $post_id, $broadcast_content, $broadcast_title = '', $import_images = false, $disable_styles = false ) { $content = $broadcast_content; @@ -359,7 +437,7 @@ private function parse_broadcast_content( $broadcast_content, $post_id ) { // If the Import Images setting is enabled, iterate through all images within the Broadcast, importing them and changing their // URLs to the WordPress Media Library hosted versions. - if ( $this->broadcasts_settings->import_images() ) { + if ( $import_images ) { foreach ( $xpath->query( '//img' ) as $node ) { $image = array( @@ -400,17 +478,21 @@ private function parse_broadcast_content( $broadcast_content, $post_id ) { $content = $html->saveHTML(); // Return content with permitted HTML tags and inline styles included/excluded, depending on the setting. - $content = $this->get_permitted_html( $content, $this->broadcasts_settings->no_styles() ); + $content = $this->get_permitted_html( $content, $disable_styles ); /** * Parses the given Broadcast's content, removing unnecessary HTML tags and styles. * * @since 2.2.9 * - * @param string $content Parsed Content. - * @param string $broadcast_content Original Broadcast's Content. + * @param string $content Parsed Content. + * @param int $post_id WordPress Post ID. + * @param string $broadcast_content Broadcast Content. + * @param string $broadcast_title Broadcast Title. + * @param bool $import_images Import images to Media Library. + * @param bool $disable_styles Disable CSS styles in content. */ - $content = apply_filters( 'convertkit_broadcasts_parse_broadcast_content', $content, $broadcast_content ); + $content = apply_filters( 'convertkit_broadcasts_parse_broadcast_content', $content, $post_id, $broadcast_content, $broadcast_title, $import_images, $disable_styles ); return $content; From 5ef7cfdd66ac70763c20258cb0f91e3942d1414a Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 29 Oct 2024 10:44:55 +0800 Subject: [PATCH 2/6] Stubbed unit tests --- .env.dist.testing | 1 + .env.example | 1 + tests/wpunit/BroadcastsImportTest.php | 133 ++++++++++++++++++++++++++ 3 files changed, 135 insertions(+) create mode 100644 tests/wpunit/BroadcastsImportTest.php diff --git a/.env.dist.testing b/.env.dist.testing index c693b76d..a034bbb3 100644 --- a/.env.dist.testing +++ b/.env.dist.testing @@ -52,6 +52,7 @@ CONVERTKIT_API_SUBSCRIBER_ID="1579118532" CONVERTKIT_API_THIRD_PARTY_INTEGRATIONS_FORM_NAME="Third Party Integrations Form [inline]" CONVERTKIT_API_THIRD_PARTY_INTEGRATIONS_FORM_ID="3003590" CONVERTKIT_API_COMMERCE_JS_URL="https://cheerful-architect-3237.ck.page/commerce.js" +CONVERTKIT_API_BROADCAST_ID=3175837 CONVERTKIT_API_BROADCAST_FIRST_URL="https://cheerful-architect-3237.ck.page/posts/html-template-test" CONVERTKIT_API_BROADCAST_FIRST_TITLE="HTML Template Test" CONVERTKIT_API_BROADCAST_FIRST_DATE="2023-08-02T16:34:51.000Z" diff --git a/.env.example b/.env.example index 64dff1e6..afe9f350 100644 --- a/.env.example +++ b/.env.example @@ -58,6 +58,7 @@ CONVERTKIT_API_SUBSCRIBER_ID="1579118532" CONVERTKIT_API_THIRD_PARTY_INTEGRATIONS_FORM_NAME="Third Party Integrations Form [inline]" CONVERTKIT_API_THIRD_PARTY_INTEGRATIONS_FORM_ID="3003590" CONVERTKIT_API_COMMERCE_JS_URL="https://cheerful-architect-3237.ck.page/commerce.js" +CONVERTKIT_API_BROADCAST_ID=3175837 CONVERTKIT_API_BROADCAST_FIRST_URL="https://cheerful-architect-3237.ck.page/posts/html-template-test" CONVERTKIT_API_BROADCAST_FIRST_TITLE="HTML Template Test" CONVERTKIT_API_BROADCAST_FIRST_DATE="2023-08-02T16:34:51.000Z" diff --git a/tests/wpunit/BroadcastsImportTest.php b/tests/wpunit/BroadcastsImportTest.php new file mode 100644 index 00000000..7ae23831 --- /dev/null +++ b/tests/wpunit/BroadcastsImportTest.php @@ -0,0 +1,133 @@ +importer = new ConvertKit_Broadcasts_Importer(); + + // Confirm initialization didn't result in an error. + $this->assertNotInstanceOf(WP_Error::class, $this->importer); + } + + /** + * Performs actions after each test. + * + * @since 2.4.2 + */ + public function tearDown(): void + { + // Destroy the class we tested. + unset($this->importer); + + // Deactivate Plugin. + deactivate_plugins('convertkit/wp-convertkit.php'); + + parent::tearDown(); + } + + /** + * Test that the import_broadcast() method works. + * + * @since 2.6.4 + */ + public function testImportBroadcast() + { + // Import broadcast. + $result = $this->importer->import_broadcast($_ENV['CONVERTKIT_API_BROADCAST_ID']); + + // @TODO Inspect created Post to run assertions. + var_dump($result); + die(); + + } + + /** + * Test that the import_broadcast() method works when + * a Post Status is defined. + * + * @since 2.6.4 + */ + public function testImportBroadcastWithPostStatus() + { + + } + + /** + * Test that the import_broadcast() method works when + * a WordPress User ID is defined as the author. + * + * @since 2.6.4 + */ + public function testImportBroadcastWithAuthorID() + { + + } + + /** + * Test that the import_broadcast() method works when + * a Category ID is defined. + * + * @since 2.6.4 + */ + public function testImportBroadcastWithCategoryID() + { + + } + + /** + * Test that the import_broadcast() method works when + * importing the Broadcast's thumbnail as the Post's + * Featured Image is enabled. + * + * @since 2.6.4 + */ + public function testImportBroadcastWithImportThumbnailEnabled() + { + + } + + /** + * Test that the import_broadcast() method works when + * importing images to the Media Library is enabled. + * + * @since 2.6.4 + */ + public function testImportBroadcastWithImportImagesEnabled() + { + + } + + /** + * Test that the import_broadcast() method works when + * disabling styles is enabled. + * + * @since 2.6.4 + */ + public function testImportBroadcastWithDisableStylesEnabled() + { + + } +} From c2ef287dd9c0218ca6327736c401165236979ff5 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 29 Oct 2024 12:42:59 +0800 Subject: [PATCH 3/6] Started work on unit tests for broadcast importer --- .../class-convertkit-broadcasts-importer.php | 131 +++++----- tests/wpunit/BroadcastsImportTest.php | 242 +++++++++++++++++- 2 files changed, 300 insertions(+), 73 deletions(-) diff --git a/includes/class-convertkit-broadcasts-importer.php b/includes/class-convertkit-broadcasts-importer.php index 08b16cd3..405bb1e4 100644 --- a/includes/class-convertkit-broadcasts-importer.php +++ b/includes/class-convertkit-broadcasts-importer.php @@ -14,15 +14,6 @@ */ class ConvertKit_Broadcasts_Importer { - /** - * Holds the API class. - * - * @since 2.6.4 - * - * @var bool|ConvertKit_API_V4 - */ - private $api = false; - /** * Holds the Broadcasts Settings class. * @@ -69,10 +60,10 @@ public function __construct() { // Initialize required classes. $this->broadcasts_settings = new ConvertKit_Settings_Broadcasts(); + $this->log = new ConvertKit_Log( CONVERTKIT_PLUGIN_PATH ); $this->media_library = new ConvertKit_Media_Library(); $this->settings = new ConvertKit_Settings(); - $this->log = new ConvertKit_Log( CONVERTKIT_PLUGIN_PATH ); - + // Create WordPress Posts when the ConvertKit Posts Resource is refreshed. add_action( 'convertkit_resource_refreshed_posts', array( $this, 'refresh' ) ); @@ -100,42 +91,16 @@ public function refresh( $broadcasts ) { return; } - // Bail if the Plugin Access Token has not been configured. - if ( ! $this->settings->has_access_and_refresh_token() ) { - return; - } - - // Initialize the API. - $this->api = new ConvertKit_API_V4( - CONVERTKIT_OAUTH_CLIENT_ID, - CONVERTKIT_OAUTH_CLIENT_REDIRECT_URI, - $this->settings->get_access_token(), - $this->settings->get_refresh_token(), - $this->settings->debug_enabled(), - 'broadcasts_importer' - ); - - // Check that we're using the ConvertKit WordPress Libraries 1.3.8 or higher. - // If another ConvertKit Plugin is active and out of date, its libraries might - // be loaded that don't have this method. - if ( ! method_exists( $this->api, 'get_post' ) ) { - return; - } - foreach ( $broadcasts as $broadcast_id => $broadcast ) { // If a WordPress Post exists for this Broadcast ID, we previously imported it - skip it. if ( $this->broadcast_exists_as_post( $broadcast_id ) ) { - if ( $this->settings->debug_enabled() ) { - $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . ' already exists as a WordPress Post. Skipping...' ); - } + $this->maybe_log( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . ' already exists as a WordPress Post. Skipping...' ); continue; } // Skip if the published_at date is older than the 'Earliest Date' setting. if ( strtotime( $broadcast['published_at'] ) < strtotime( $this->broadcasts_settings->published_at_min_date() ) ) { - if ( $this->settings->debug_enabled() ) { - $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . ' published_at date is before ' . $this->broadcasts_settings->published_at_min_date() . '. Skipping...' ); - } + $this->maybe_log( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . ' published_at date is before ' . $this->broadcasts_settings->published_at_min_date() . '. Skipping...' ); continue; } @@ -153,6 +118,8 @@ public function refresh( $broadcasts ) { } + + /** * Imports the given Kit Broadcast ID to a new WordPress Post. * @@ -170,16 +137,41 @@ public function refresh( $broadcasts ) { */ public function import_broadcast( $broadcast_id, $post_status = 'publish', $author_id = 1, $category_id = false, $import_thumbnail = false, $import_images = false, $disable_styles = false ) { + // Bail if the Plugin Access Token has not been configured. + if ( ! $this->settings->has_access_and_refresh_token() ) { + return new WP_Error( + 'convertkit_broadcasts_importer_error', + __( 'No Access Token specified in Plugin Settings', 'convertkit' ) + ); + } + + // Initialize the API. + $api = new ConvertKit_API_V4( + CONVERTKIT_OAUTH_CLIENT_ID, + CONVERTKIT_OAUTH_CLIENT_REDIRECT_URI, + $this->settings->get_access_token(), + $this->settings->get_refresh_token(), + $this->settings->debug_enabled(), + 'broadcasts_importer' + ); + + // Check that we're using the ConvertKit WordPress Libraries 1.3.8 or higher. + // If another ConvertKit Plugin is active and out of date, its libraries might + // be loaded that don't have this method. + if ( ! method_exists( $api, 'get_post' ) ) { + return; + } + // Fetch Broadcast's content. // We need to query wordpress/posts/{id} to fetch the full Broadcast information and content. - $broadcast = $this->api->get_post( $broadcast_id ); + $broadcast = $api->get_post( $broadcast_id ); + + // Unset API class. + unset( $api ); // Bail if an error occured fetching the Broadcast. if ( is_wp_error( $broadcast ) ) { - if ( $this->settings->debug_enabled() ) { - $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error fetching from API: ' . $broadcast->get_error_message() ); - } - + $this->maybe_log( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error fetching from API: ' . $broadcast->get_error_message() ); return $broadcast; } @@ -198,10 +190,7 @@ public function import_broadcast( $broadcast_id, $post_status = 'publish', $auth // Bail if an error occured. if ( is_wp_error( $post_id ) ) { - if ( $this->settings->debug_enabled() ) { - $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_insert_post(): ' . $post_id->get_error_message() ); - } - + $this->maybe_log( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_insert_post(): ' . $post_id->get_error_message() ); return $post_id; } @@ -222,10 +211,7 @@ public function import_broadcast( $broadcast_id, $post_status = 'publish', $auth // Bail if an error occured updating the Post. if ( is_wp_error( $post_id ) ) { - if ( $this->settings->debug_enabled() ) { - $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_update_post() when adding Broadcast content: ' . $post_id->get_error_message() ); - } - + $this->maybe_log( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_update_post() when adding Broadcast content: ' . $post_id->get_error_message() ); return $post_id; } @@ -240,21 +226,18 @@ public function import_broadcast( $broadcast_id, $post_status = 'publish', $auth // Save Post's settings. $convertkit_post->save( $meta ); - - if ( $this->settings->debug_enabled() ) { - $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Set Restrict Content = ' . $broadcast['product_id'] ); - } + $this->maybe_log( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Set Restrict Content = ' . $broadcast['product_id'] ); } // If the Import Thumbnail setting is enabled, and the Broadcast has an image, save it to the Media Library and link it to the Post. if ( $import_thumbnail ) { $result = $this->add_broadcast_image_to_post( $broadcast, $post_id ); - if ( is_wp_error( $result ) && $this->settings->debug_enabled() ) { - $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on add_broadcast_image_to_post(): ' . $result->get_error_message() ); + if ( is_wp_error( $result ) ) { + $this->maybe_log( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on add_broadcast_image_to_post(): ' . $result->get_error_message() ); } - } elseif ( $this->settings->debug_enabled() ) { - $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Skipping thumbnail.' ); + } else { + $this->maybe_log( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Skipping thumbnail.' ); } // Transition the Post to the defined Post Status in the settings, now that the image has been added to it. @@ -268,20 +251,32 @@ public function import_broadcast( $broadcast_id, $post_status = 'publish', $auth // Maybe log if an error occured updating the Post to the publish status. if ( is_wp_error( $post_id ) ) { - if ( $this->settings->debug_enabled() ) { - $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_update_post() when transitioning post status from draft to publish: ' . $post_id->get_error_message() ); - } - + $this->maybe_log( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Error on wp_update_post() when transitioning post status from draft to publish: ' . $post_id->get_error_message() ); return $post_id; } // Import successful. - // Maybe log success. - if ( $this->settings->debug_enabled() ) { - $this->log->add( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Added as Post ID #' . $post_id ); + $this->maybe_log( 'ConvertKit_Broadcasts_Importer::refresh(): Broadcast #' . $broadcast_id . '. Added as Post ID #' . $post_id ); + return $post_id; + + } + + /** + * Logs the given message if debug logging is enabled + * in the Plugin's settings. + * + * @since 2.6.4 + * + * @param string $message Log message. + */ + private function maybe_log( $message ) { + + // Don't log if debugging is not enabled. + if ( ! $this->settings->debug_enabled() ) { + return; } - return $post_id; + $this->log->add( $message ); } diff --git a/tests/wpunit/BroadcastsImportTest.php b/tests/wpunit/BroadcastsImportTest.php index 7ae23831..de431321 100644 --- a/tests/wpunit/BroadcastsImportTest.php +++ b/tests/wpunit/BroadcastsImportTest.php @@ -25,6 +25,13 @@ public function setUp(): void // Activate Plugin. activate_plugins('convertkit/wp-convertkit.php'); + // Configure access and refresh token in Plugin settings. + $this->settings = new ConvertKit_Settings(); + $this->settings->save( [ + 'access_token' => $_ENV['CONVERTKIT_OAUTH_ACCESS_TOKEN'], + 'refresh_token' => $_ENV['CONVERTKIT_OAUTH_REFRESH_TOKEN'], + ] ); + // Initialize the class we want to test. $this->importer = new ConvertKit_Broadcasts_Importer(); @@ -48,20 +55,48 @@ public function tearDown(): void parent::tearDown(); } + /** + * Test that the import_broadcast() method returns a WP_Error + * when no access token is specified in the Plugin's settings. + * + * @since 2.6.4 + */ + public function testImportBroadcastWithNoAccessToken() + { + // Delete access and refresh token from Plugin settings. + $this->settings->delete_credentials(); + + // Re-initialize the class we want to test. + $this->importer = new ConvertKit_Broadcasts_Importer(); + + // Assert a WP_Error is returned when attempting to import a Broadcast. + $this->assertInstanceOf(WP_Error::class, $this->importer->import_broadcast($_ENV['CONVERTKIT_API_BROADCAST_ID'])); + } + /** * Test that the import_broadcast() method works. * * @since 2.6.4 */ - public function testImportBroadcast() + public function testImportBroadcastWithDefaultSettings() { // Import broadcast. $result = $this->importer->import_broadcast($_ENV['CONVERTKIT_API_BROADCAST_ID']); - // @TODO Inspect created Post to run assertions. - var_dump($result); - die(); + // Assert a Post ID was returned. + $this->assertNotInstanceOf(WP_Error::class, $result); + $this->assertIsInt($result); + // Fetch Post from database. + $post = get_post($result); + + // Assert the imported Broadcast is correct. + $this->assertImportValid($post); + $this->assertInlineStylesExist($post); + $this->assertFeaturedImageDoesNotExist($post); + $this->assertImagesNotImported($post); + $this->assertPostStatusEquals('publish', $post); + $this->assertPostAuthorIDEquals(1, $post); } /** @@ -70,9 +105,28 @@ public function testImportBroadcast() * * @since 2.6.4 */ - public function testImportBroadcastWithPostStatus() + public function testImportBroadcastWithDraftPostStatus() { + // Import broadcast. + $result = $this->importer->import_broadcast( + $_ENV['CONVERTKIT_API_BROADCAST_ID'], + 'draft' + ); + + // Assert a Post ID was returned. + $this->assertNotInstanceOf(WP_Error::class, $result); + $this->assertIsInt($result); + + // Fetch Post from database. + $post = get_post($result); + // Assert the imported Broadcast is correct. + $this->assertImportValid($post); + $this->assertInlineStylesExist($post); + $this->assertFeaturedImageDoesNotExist($post); + $this->assertImagesNotImported($post); + $this->assertPostStatusEquals('draft', $post); + $this->assertPostAuthorIDEquals(1, $post); } /** @@ -83,7 +137,27 @@ public function testImportBroadcastWithPostStatus() */ public function testImportBroadcastWithAuthorID() { + // Import broadcast. + $result = $this->importer->import_broadcast( + $_ENV['CONVERTKIT_API_BROADCAST_ID'], + 'publish', + 10 + ); + + // Assert a Post ID was returned. + $this->assertNotInstanceOf(WP_Error::class, $result); + $this->assertIsInt($result); + // Fetch Post from database. + $post = get_post($result); + + // Assert the imported Broadcast is correct. + $this->assertImportValid($post); + $this->assertInlineStylesExist($post); + $this->assertFeaturedImageDoesNotExist($post); + $this->assertImagesNotImported($post); + $this->assertPostStatusEquals('publish', $post); + $this->assertPostAuthorIDEquals(10, $post); } /** @@ -94,7 +168,32 @@ public function testImportBroadcastWithAuthorID() */ public function testImportBroadcastWithCategoryID() { + // Create category. + $termID = wp_create_category('Newsletter'); + + // Import broadcast. + $result = $this->importer->import_broadcast( + $_ENV['CONVERTKIT_API_BROADCAST_ID'], + 'publish', + 1, + $termID + ); + + // Assert a Post ID was returned. + $this->assertNotInstanceOf(WP_Error::class, $result); + $this->assertIsInt($result); + + // Fetch Post from database. + $post = get_post($result); + // Assert the imported Broadcast is correct. + $this->assertImportValid($post); + $this->assertInlineStylesExist($post); + $this->assertFeaturedImageDoesNotExist($post); + $this->assertImagesNotImported($post); + $this->assertPostStatusEquals('publish', $post); + $this->assertPostAuthorIDEquals(1, $post); + $this->assertPostHasCategory($termID, $post); } /** @@ -106,7 +205,29 @@ public function testImportBroadcastWithCategoryID() */ public function testImportBroadcastWithImportThumbnailEnabled() { + // Import broadcast. + $result = $this->importer->import_broadcast( + $_ENV['CONVERTKIT_API_BROADCAST_ID'], + 'publish', + 1, + false, + true + ); + + // Assert a Post ID was returned. + $this->assertNotInstanceOf(WP_Error::class, $result); + $this->assertIsInt($result); + // Fetch Post from database. + $post = get_post($result); + + // Assert the imported Broadcast is correct. + $this->assertImportValid($post); + $this->assertInlineStylesExist($post); + $this->assertFeaturedImageExists($post); + $this->assertImagesNotImported($post); + $this->assertPostStatusEquals('publish', $post); + $this->assertPostAuthorIDEquals(1, $post); } /** @@ -117,7 +238,30 @@ public function testImportBroadcastWithImportThumbnailEnabled() */ public function testImportBroadcastWithImportImagesEnabled() { + // Import broadcast. + $result = $this->importer->import_broadcast( + $_ENV['CONVERTKIT_API_BROADCAST_ID'], + 'publish', + 1, + false, + false, + true + ); + + // Assert a Post ID was returned. + $this->assertNotInstanceOf(WP_Error::class, $result); + $this->assertIsInt($result); + + // Fetch Post from database. + $post = get_post($result); + // Assert the imported Broadcast is correct. + $this->assertImportValid($post); + $this->assertInlineStylesExist($post); + $this->assertFeaturedImageDoesNotExist($post); + $this->assertImagesImported($post); + $this->assertPostStatusEquals('publish', $post); + $this->assertPostAuthorIDEquals(1, $post); } /** @@ -128,6 +272,94 @@ public function testImportBroadcastWithImportImagesEnabled() */ public function testImportBroadcastWithDisableStylesEnabled() { + // Import broadcast. + $result = $this->importer->import_broadcast( + $_ENV['CONVERTKIT_API_BROADCAST_ID'], + 'publish', + 1, + false, + false, + true + ); + + // Assert a Post ID was returned. + $this->assertNotInstanceOf(WP_Error::class, $result); + $this->assertIsInt($result); + // Fetch Post from database. + $post = get_post($result); + + // Assert the imported Broadcast is correct. + $this->assertImportValid($post); + $this->assertInlineStylesDoNotExist($post); + $this->assertFeaturedImageDoesNotExist($post); + $this->assertImagesNotImported($post); + $this->assertPostStatusEquals('publish', $post); + $this->assertPostAuthorIDEquals(1, $post); + } + + private function assertImportValid($post) + { + // Confirm title correct. + $this->assertEquals($_ENV['CONVERTKIT_API_BROADCAST_FIRST_TITLE'], $post->post_title); + + // Confirm tracking image has been removed. + $this->assertStringNotContainsString('', $post->post_content); + + // Confirm unsubscribe link section has been removed. + $this->assertStringNotContainsString('
post_content); + + // Confirm poll block has been removed. + $this->assertStringNotContainsString('post_content); + } + + private function assertInlineStylesDoNotExist($post) + { + $this->assertStringNotContainsString('
post_content); + } + + private function assertFeaturedImageExists($post) + { + $this->assertGreaterThan(0, (int) get_post_meta($post->ID, '_thumbnail_id', true)); + } + + private function assertFeaturedImageDoesNotExist($post) + { + $this->assertNull(get_post_meta($post->ID, '_thumbnail_id', true)); + } + + private function assertImagesImported($post) + { + + } + + private function assertImagesNotImported($post) + { + + } + + private function assertPostAuthorIDEquals($id, $post) + { + $this->assertEquals($id, (int) $post->post_author); + } + + private function assertPostHasCategory($id, $post) + { + $this->assertTrue(has_category($id, $post)); } } From 6c7295e94dd24645dc93cd8f4edb2ace092e48f3 Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 29 Oct 2024 13:02:23 +0800 Subject: [PATCH 4/6] Completed unit tests --- tests/wpunit/BroadcastsImportTest.php | 110 ++++++++++++++++++++++---- 1 file changed, 96 insertions(+), 14 deletions(-) diff --git a/tests/wpunit/BroadcastsImportTest.php b/tests/wpunit/BroadcastsImportTest.php index de431321..f3ae9026 100644 --- a/tests/wpunit/BroadcastsImportTest.php +++ b/tests/wpunit/BroadcastsImportTest.php @@ -27,10 +27,12 @@ public function setUp(): void // Configure access and refresh token in Plugin settings. $this->settings = new ConvertKit_Settings(); - $this->settings->save( [ - 'access_token' => $_ENV['CONVERTKIT_OAUTH_ACCESS_TOKEN'], - 'refresh_token' => $_ENV['CONVERTKIT_OAUTH_REFRESH_TOKEN'], - ] ); + $this->settings->save( + [ + 'access_token' => $_ENV['CONVERTKIT_OAUTH_ACCESS_TOKEN'], + 'refresh_token' => $_ENV['CONVERTKIT_OAUTH_REFRESH_TOKEN'], + ] + ); // Initialize the class we want to test. $this->importer = new ConvertKit_Broadcasts_Importer(); @@ -82,7 +84,7 @@ public function testImportBroadcastWithDefaultSettings() { // Import broadcast. $result = $this->importer->import_broadcast($_ENV['CONVERTKIT_API_BROADCAST_ID']); - + // Assert a Post ID was returned. $this->assertNotInstanceOf(WP_Error::class, $result); $this->assertIsInt($result); @@ -112,7 +114,7 @@ public function testImportBroadcastWithDraftPostStatus() $_ENV['CONVERTKIT_API_BROADCAST_ID'], 'draft' ); - + // Assert a Post ID was returned. $this->assertNotInstanceOf(WP_Error::class, $result); $this->assertIsInt($result); @@ -143,7 +145,7 @@ public function testImportBroadcastWithAuthorID() 'publish', 10 ); - + // Assert a Post ID was returned. $this->assertNotInstanceOf(WP_Error::class, $result); $this->assertIsInt($result); @@ -178,7 +180,7 @@ public function testImportBroadcastWithCategoryID() 1, $termID ); - + // Assert a Post ID was returned. $this->assertNotInstanceOf(WP_Error::class, $result); $this->assertIsInt($result); @@ -213,7 +215,7 @@ public function testImportBroadcastWithImportThumbnailEnabled() false, true ); - + // Assert a Post ID was returned. $this->assertNotInstanceOf(WP_Error::class, $result); $this->assertIsInt($result); @@ -247,7 +249,7 @@ public function testImportBroadcastWithImportImagesEnabled() false, true ); - + // Assert a Post ID was returned. $this->assertNotInstanceOf(WP_Error::class, $result); $this->assertIsInt($result); @@ -279,9 +281,10 @@ public function testImportBroadcastWithDisableStylesEnabled() 1, false, false, + false, true ); - + // Assert a Post ID was returned. $this->assertNotInstanceOf(WP_Error::class, $result); $this->assertIsInt($result); @@ -298,6 +301,13 @@ public function testImportBroadcastWithDisableStylesEnabled() $this->assertPostAuthorIDEquals(1, $post); } + /** + * Assert that the created Post's content is valid. + * + * @since 2.6.4 + * + * @param WP_Post $post WordPress Post. + */ private function assertImportValid($post) { // Confirm title correct. @@ -317,47 +327,119 @@ private function assertImportValid($post) $this->assertEquals($date, $post->post_date_gmt); } + /** + * Assert that the created Post's post status matches the expected status. + * + * @since 2.6.4 + * + * @param string $status Expected Post Status. + * @param WP_Post $post WordPress Post. + */ private function assertPostStatusEquals($status, $post) { $this->assertEquals($status, $post->post_status); } + /** + * Assert that the created Post's inline styles exist. + * + * @since 2.6.4 + * + * @param WP_Post $post WordPress Post. + */ private function assertInlineStylesExist($post) { $this->assertStringContainsString('
post_content); $this->assertStringNotContainsString('style="', $post->post_content); } + /** + * Assert that the created Post has a Featured Image. + * + * @since 2.6.4 + * + * @param WP_Post $post WordPress Post. + */ private function assertFeaturedImageExists($post) { $this->assertGreaterThan(0, (int) get_post_meta($post->ID, '_thumbnail_id', true)); } + /** + * Assert that the created Post does not have a Featured Image. + * + * @since 2.6.4 + * + * @param WP_Post $post WordPress Post. + */ private function assertFeaturedImageDoesNotExist($post) { - $this->assertNull(get_post_meta($post->ID, '_thumbnail_id', true)); + $this->assertEmpty(get_post_meta($post->ID, '_thumbnail_id', true)); } + /** + * Assert that the created Post's images were imported from Kit + * and saved in the Media Library. + * + * @since 2.6.4 + * + * @param WP_Post $post WordPress Post. + */ private function assertImagesImported($post) { - + $this->assertStringNotContainsString('embed.filekitcdn.com', $post->post_content); + $this->assertStringContainsString($_ENV['TEST_SITE_WP_URL'] . '/wp-content/uploads/2023/08', $post->post_content); } + /** + * Assert that the created Post's images were not imported from Kit + * and saved in the Media Library. + * + * @since 2.6.4 + * + * @param WP_Post $post WordPress Post. + */ private function assertImagesNotImported($post) { - + $this->assertStringContainsString('embed.filekitcdn.com', $post->post_content); + $this->assertStringNotContainsString($_ENV['TEST_SITE_WP_URL'] . '/wp-content/uploads/2023/08', $post->post_content); } + /** + * Assert that the created Post's author matches the expected + * WordPress User ID. + * + * @since 2.6.4 + * + * @param int $id WordPress User ID. + * @param WP_Post $post WordPress Post. + */ private function assertPostAuthorIDEquals($id, $post) { $this->assertEquals($id, (int) $post->post_author); } + /** + * Assert that the created Post has the expected + * WordPress Category assigned to it. + * + * @since 2.6.4 + * + * @param int $id WordPress Category ID. + * @param WP_Post $post WordPress Post. + */ private function assertPostHasCategory($id, $post) { $this->assertTrue(has_category($id, $post)); From 0b0124d06735b9fbf5c36cf03978fc52eb81b5eb Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Tue, 29 Oct 2024 15:07:44 +0800 Subject: [PATCH 5/6] Coding standards --- includes/class-convertkit-broadcasts-importer.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/includes/class-convertkit-broadcasts-importer.php b/includes/class-convertkit-broadcasts-importer.php index 405bb1e4..0c675335 100644 --- a/includes/class-convertkit-broadcasts-importer.php +++ b/includes/class-convertkit-broadcasts-importer.php @@ -63,7 +63,7 @@ public function __construct() { $this->log = new ConvertKit_Log( CONVERTKIT_PLUGIN_PATH ); $this->media_library = new ConvertKit_Media_Library(); $this->settings = new ConvertKit_Settings(); - + // Create WordPress Posts when the ConvertKit Posts Resource is refreshed. add_action( 'convertkit_resource_refreshed_posts', array( $this, 'refresh' ) ); @@ -264,10 +264,10 @@ public function import_broadcast( $broadcast_id, $post_status = 'publish', $auth /** * Logs the given message if debug logging is enabled * in the Plugin's settings. - * - * @since 2.6.4 - * - * @param string $message Log message. + * + * @since 2.6.4 + * + * @param string $message Log message. */ private function maybe_log( $message ) { From 6c1d2153be20de340330d7d2d6d34c34b3bc9eee Mon Sep 17 00:00:00 2001 From: Tim Carr Date: Wed, 30 Oct 2024 11:09:07 +0800 Subject: [PATCH 6/6] PHPStan compat. --- includes/class-convertkit-broadcasts-importer.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/includes/class-convertkit-broadcasts-importer.php b/includes/class-convertkit-broadcasts-importer.php index 0c675335..a52cdd34 100644 --- a/includes/class-convertkit-broadcasts-importer.php +++ b/includes/class-convertkit-broadcasts-importer.php @@ -60,7 +60,6 @@ public function __construct() { // Initialize required classes. $this->broadcasts_settings = new ConvertKit_Settings_Broadcasts(); - $this->log = new ConvertKit_Log( CONVERTKIT_PLUGIN_PATH ); $this->media_library = new ConvertKit_Media_Library(); $this->settings = new ConvertKit_Settings(); @@ -159,7 +158,10 @@ public function import_broadcast( $broadcast_id, $post_status = 'publish', $auth // If another ConvertKit Plugin is active and out of date, its libraries might // be loaded that don't have this method. if ( ! method_exists( $api, 'get_post' ) ) { - return; + return new WP_Error( + 'convertkit_broadcasts_importer_error', + __( 'Kit WordPress Libraries 1.3.7 or older detected, missing the `get_post` method.', 'convertkit' ) + ); } // Fetch Broadcast's content. @@ -276,6 +278,11 @@ private function maybe_log( $message ) { return; } + // Initialize logging class, if not yet initialized. + if ( ! $this->log ) { + $this->log = new ConvertKit_Log( CONVERTKIT_PLUGIN_PATH ); + } + $this->log->add( $message ); }