diff --git a/admin/class-convertkit-admin-refresh-resources.php b/admin/class-convertkit-admin-refresh-resources.php index 68e7c7ec8..57caddb80 100644 --- a/admin/class-convertkit-admin-refresh-resources.php +++ b/admin/class-convertkit-admin-refresh-resources.php @@ -22,8 +22,30 @@ class ConvertKit_Admin_Refresh_Resources { */ public function __construct() { - add_action( 'wp_ajax_convertkit_admin_refresh_resources', array( $this, 'refresh_resources' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + + } + + /** + * Register REST API routes. + * + * @since 3.1.0 + */ + public function register_routes() { + + // Register route to return all blocks registered by the Plugin. + register_rest_route( + 'kit/v1', + '/resources/refresh/(?P[a-zA-Z0-9-_]+)', + array( + 'methods' => WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'refresh_resources' ), + 'permission_callback' => function () { + return current_user_can( 'edit_posts' ); + }, + ) + ); } @@ -31,14 +53,14 @@ public function __construct() { * Refreshes resources (forms, landing pages or tags) from the API, returning them as a JSON string. * * @since 1.9.8.0 + * + * @param WP_REST_Request $request Request object. + * @return WP_REST_Response|WP_Error Response object. */ - public function refresh_resources() { - - // Check nonce. - check_ajax_referer( 'convertkit_admin_refresh_resources', 'nonce' ); + public function refresh_resources( $request ) { // Get resource type. - $resource = ( isset( $_REQUEST['resource'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['resource'] ) ) : '' ); + $resource = $request->get_param( 'resource' ); // Fetch resources. switch ( $resource ) { @@ -74,7 +96,7 @@ public function refresh_resources() { // Bail if an error occured. if ( is_wp_error( $results_tags ) ) { - wp_send_json_error( $results_tags->get_error_message() ); + return rest_ensure_response( $results_tags ); } // Fetch Products. @@ -83,17 +105,16 @@ public function refresh_resources() { // Bail if an error occured. if ( is_wp_error( $results_products ) ) { - wp_send_json_error( $results_products->get_error_message() ); + return rest_ensure_response( $results_products ); } // Return resources. - wp_send_json_success( + return rest_ensure_response( array( 'tags' => array_values( $results_tags ), 'products' => array_values( $results_products ), ) ); - // no break as wp_send_json_success terminates. default: $results = new WP_Error( @@ -108,11 +129,11 @@ public function refresh_resources() { // Bail if an error occured. if ( is_wp_error( $results ) ) { - wp_send_json_error( $results->get_error_message() ); + return rest_ensure_response( $results ); } // Return resources as a zero based sequential array, so that JS retains the order of resources. - wp_send_json_success( array_values( $results ) ); + return rest_ensure_response( array_values( $results ) ); } @@ -144,10 +165,9 @@ public function enqueue_scripts( $hook ) { 'convertkit-admin-refresh-resources', 'convertkit_admin_refresh_resources', array( - 'action' => 'convertkit_admin_refresh_resources', - 'ajaxurl' => admin_url( 'admin-ajax.php' ), + 'ajaxurl' => rest_url( 'kit/v1/resources/refresh/' ), 'debug' => $settings->debug_enabled(), - 'nonce' => wp_create_nonce( 'convertkit_admin_refresh_resources' ), + 'nonce' => wp_create_nonce( 'wp_rest' ), ) ); diff --git a/codeception.dist.yml b/codeception.dist.yml index 5660ac453..09ebaa6a1 100644 --- a/codeception.dist.yml +++ b/codeception.dist.yml @@ -14,6 +14,7 @@ extensions: - lucatume\WPBrowser\Command\RunOriginal - lucatume\WPBrowser\Command\RunAll - lucatume\WPBrowser\Command\GenerateWPUnit + - lucatume\WPBrowser\Command\GenerateWPRestApi - lucatume\WPBrowser\Command\DbExport - lucatume\WPBrowser\Command\DbImport - lucatume\WPBrowser\Command\MonkeyCachePath diff --git a/includes/blocks/class-convertkit-block-broadcasts.php b/includes/blocks/class-convertkit-block-broadcasts.php index 52aa0c174..8464a153b 100644 --- a/includes/blocks/class-convertkit-block-broadcasts.php +++ b/includes/blocks/class-convertkit-block-broadcasts.php @@ -272,8 +272,8 @@ public function get_supports() { */ public function get_fields() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } @@ -380,8 +380,8 @@ public function get_fields() { */ public function get_panels() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } diff --git a/includes/blocks/class-convertkit-block-content.php b/includes/blocks/class-convertkit-block-content.php index 2fe3f50d1..7f16f4b62 100644 --- a/includes/blocks/class-convertkit-block-content.php +++ b/includes/blocks/class-convertkit-block-content.php @@ -104,8 +104,8 @@ public function get_attributes() { */ public function get_fields() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } @@ -137,8 +137,8 @@ public function get_fields() { */ public function get_panels() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } diff --git a/includes/blocks/class-convertkit-block-form-builder-field-custom.php b/includes/blocks/class-convertkit-block-form-builder-field-custom.php index 19d271ea0..0df3c5472 100644 --- a/includes/blocks/class-convertkit-block-form-builder-field-custom.php +++ b/includes/blocks/class-convertkit-block-form-builder-field-custom.php @@ -101,8 +101,8 @@ public function get_attributes() { */ public function get_fields() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } @@ -150,8 +150,8 @@ public function get_fields() { */ public function get_panels() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } diff --git a/includes/blocks/class-convertkit-block-form-builder-field-email.php b/includes/blocks/class-convertkit-block-form-builder-field-email.php index 38016643c..71e02e8a7 100644 --- a/includes/blocks/class-convertkit-block-form-builder-field-email.php +++ b/includes/blocks/class-convertkit-block-form-builder-field-email.php @@ -120,8 +120,8 @@ public function get_attributes() { */ public function get_fields() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } diff --git a/includes/blocks/class-convertkit-block-form-builder-field.php b/includes/blocks/class-convertkit-block-form-builder-field.php index ebfecd65f..295fa480b 100644 --- a/includes/blocks/class-convertkit-block-form-builder-field.php +++ b/includes/blocks/class-convertkit-block-form-builder-field.php @@ -194,8 +194,8 @@ public function get_supports() { */ public function get_fields() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } @@ -223,8 +223,8 @@ public function get_fields() { */ public function get_panels() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } diff --git a/includes/blocks/class-convertkit-block-form-builder.php b/includes/blocks/class-convertkit-block-form-builder.php index 12556f808..4aa8b2a1b 100644 --- a/includes/blocks/class-convertkit-block-form-builder.php +++ b/includes/blocks/class-convertkit-block-form-builder.php @@ -475,8 +475,8 @@ public function get_supports() { */ public function get_fields() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } @@ -568,8 +568,8 @@ public function get_fields() { */ public function get_panels() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } diff --git a/includes/blocks/class-convertkit-block-form-trigger.php b/includes/blocks/class-convertkit-block-form-trigger.php index 967a57b13..5133b916f 100644 --- a/includes/blocks/class-convertkit-block-form-trigger.php +++ b/includes/blocks/class-convertkit-block-form-trigger.php @@ -212,8 +212,8 @@ public function get_supports() { */ public function get_fields() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } @@ -270,8 +270,8 @@ public function get_fields() { */ public function get_panels() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } diff --git a/includes/blocks/class-convertkit-block-form.php b/includes/blocks/class-convertkit-block-form.php index 3b1ae7154..b3e7c1615 100644 --- a/includes/blocks/class-convertkit-block-form.php +++ b/includes/blocks/class-convertkit-block-form.php @@ -240,8 +240,8 @@ public function get_supports() { */ public function get_fields() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } @@ -285,8 +285,8 @@ public function get_fields() { */ public function get_panels() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } diff --git a/includes/blocks/class-convertkit-block-product.php b/includes/blocks/class-convertkit-block-product.php index e0e779f34..ba847ab6d 100644 --- a/includes/blocks/class-convertkit-block-product.php +++ b/includes/blocks/class-convertkit-block-product.php @@ -245,8 +245,8 @@ public function get_supports() { */ public function get_fields() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } @@ -312,8 +312,8 @@ public function get_fields() { */ public function get_panels() { - // Bail if the request is not for the WordPress Administration or frontend editor. - if ( ! WP_ConvertKit()->is_admin_or_frontend_editor() ) { + // Bail if the request is not for the WordPress Administration, frontend editor or REST API request. + if ( ! $this->is_admin_frontend_editor_or_rest_request() ) { return false; } diff --git a/includes/blocks/class-convertkit-block.php b/includes/blocks/class-convertkit-block.php index fa8cf25a5..1b75ba135 100644 --- a/includes/blocks/class-convertkit-block.php +++ b/includes/blocks/class-convertkit-block.php @@ -395,6 +395,32 @@ public function get_atts_as_html_data_attributes( $atts ) { } + /** + * Determines if the request is a WordPress REST API request. + * + * @since 3.1.0 + * + * @return bool + */ + public function is_rest_request() { + + return defined( 'REST_REQUEST' ) && REST_REQUEST; + + } + + /** + * Determines if the request is for the WordPress Administration, frontend editor or REST API request. + * + * @since 3.1.0 + * + * @return bool + */ + public function is_admin_frontend_editor_or_rest_request() { + + return WP_ConvertKit()->is_admin_or_frontend_editor() || $this->is_rest_request(); + + } + /** * Determines if the request for the block is from the block editor or the frontend site. * @@ -405,10 +431,7 @@ public function get_atts_as_html_data_attributes( $atts ) { public function is_block_editor_request() { // Return false if not a WordPress REST API request, which Gutenberg uses. - if ( ! defined( 'REST_REQUEST' ) ) { - return false; - } - if ( REST_REQUEST !== true ) { + if ( ! $this->is_rest_request() ) { return false; } diff --git a/includes/class-convertkit-ajax.php b/includes/class-convertkit-ajax.php index b277b0d12..a6981f439 100644 --- a/includes/class-convertkit-ajax.php +++ b/includes/class-convertkit-ajax.php @@ -20,8 +20,6 @@ class ConvertKit_AJAX { */ public function __construct() { - add_action( 'wp_ajax_convertkit_get_blocks', array( $this, 'get_blocks' ) ); - add_action( 'wp_ajax_nopriv_convertkit_store_subscriber_id_in_cookie', array( $this, 'store_subscriber_id_in_cookie' ) ); add_action( 'wp_ajax_convertkit_store_subscriber_id_in_cookie', array( $this, 'store_subscriber_id_in_cookie' ) ); @@ -36,35 +34,6 @@ public function __construct() { } - /** - * Returns all ConvertKit registered blocks. - * - * Typically used when a refresh button in a block has been pressed when - * displayNoticeWithLink() is called, because either - * no Access Token is specified, or no resources exist in ConvertKit. - * - * @since 2.2.6 - */ - public function get_blocks() { - - // Check nonce. - check_ajax_referer( 'convertkit_get_blocks', 'nonce' ); - - // Refresh resources from the API, to reflect any changes. - $forms = new ConvertKit_Resource_Forms( 'block_edit' ); - $forms->refresh(); - - $posts = new ConvertKit_Resource_Posts( 'block_edit' ); - $posts->refresh(); - - $products = new ConvertKit_Resource_Products( 'block_edit' ); - $products->refresh(); - - // Return blocks. - wp_send_json_success( convertkit_get_blocks() ); - - } - /** * Stores the ConvertKit Subscriber's ID in a cookie. * diff --git a/includes/class-convertkit-gutenberg.php b/includes/class-convertkit-gutenberg.php index 7336b480e..0d787b43e 100644 --- a/includes/class-convertkit-gutenberg.php +++ b/includes/class-convertkit-gutenberg.php @@ -32,6 +32,47 @@ public function __construct() { // Register Gutenberg Blocks. add_action( 'init', array( $this, 'add_blocks' ) ); + // Register REST API routes. + add_action( 'rest_api_init', array( $this, 'register_routes' ) ); + + } + + /** + * Register REST API routes. + * + * @since 3.1.0 + */ + public function register_routes() { + + // Register route to return all blocks registered by the Plugin. + register_rest_route( + 'kit/v1', + '/blocks', + array( + 'methods' => WP_REST_Server::READABLE, + + // Refresh resources and return blocks. + 'callback' => function () { + // Refresh resources from the API, to reflect any changes. + $forms = new ConvertKit_Resource_Forms( 'block_edit' ); + $forms->refresh(); + + $posts = new ConvertKit_Resource_Posts( 'block_edit' ); + $posts->refresh(); + + $products = new ConvertKit_Resource_Products( 'block_edit' ); + $products->refresh(); + + // Return blocks. + return rest_ensure_response( convertkit_get_blocks() ); + }, + + 'permission_callback' => function () { + return current_user_can( 'edit_posts' ); + }, + ) + ); + } /** @@ -157,7 +198,8 @@ public function enqueue_scripts() { 'convertkit-gutenberg', 'convertkit_gutenberg', array( - 'get_blocks_nonce' => wp_create_nonce( 'convertkit_get_blocks' ), + 'ajaxurl' => rest_url( 'kit/v1/blocks' ), + 'get_blocks_nonce' => wp_create_nonce( 'wp_rest' ), ) ); diff --git a/includes/class-wp-convertkit.php b/includes/class-wp-convertkit.php index 135757263..f3ba41bfd 100644 --- a/includes/class-wp-convertkit.php +++ b/includes/class-wp-convertkit.php @@ -79,14 +79,14 @@ private function initialize_admin() { return; } - $this->classes['admin_bulk_edit'] = new ConvertKit_Admin_Bulk_Edit(); - $this->classes['admin_cache_plugins'] = new ConvertKit_Admin_Cache_Plugins(); - $this->classes['admin_category'] = new ConvertKit_Admin_Category(); - $this->classes['admin_landing_page'] = new ConvertKit_Admin_Landing_Page(); - $this->classes['admin_notices'] = new ConvertKit_Admin_Notices(); - $this->classes['admin_post'] = new ConvertKit_Admin_Post(); - $this->classes['admin_quick_edit'] = new ConvertKit_Admin_Quick_Edit(); - $this->classes['admin_refresh_resources'] = new ConvertKit_Admin_Refresh_Resources(); + $this->classes['admin_bulk_edit'] = new ConvertKit_Admin_Bulk_Edit(); + $this->classes['admin_cache_plugins'] = new ConvertKit_Admin_Cache_Plugins(); + $this->classes['admin_category'] = new ConvertKit_Admin_Category(); + $this->classes['admin_landing_page'] = new ConvertKit_Admin_Landing_Page(); + $this->classes['admin_notices'] = new ConvertKit_Admin_Notices(); + $this->classes['admin_post'] = new ConvertKit_Admin_Post(); + $this->classes['admin_quick_edit'] = new ConvertKit_Admin_Quick_Edit(); + $this->classes['admin_restrict_content'] = new ConvertKit_Admin_Restrict_Content(); $this->classes['admin_settings'] = new ConvertKit_Admin_Settings(); $this->classes['admin_setup_wizard_landing_page'] = new ConvertKit_Admin_Setup_Wizard_Landing_Page(); @@ -178,6 +178,7 @@ private function initialize_frontend() { */ private function initialize_global() { + $this->classes['admin_refresh_resources'] = new ConvertKit_Admin_Refresh_Resources(); $this->classes['ajax'] = new ConvertKit_AJAX(); $this->classes['blocks_convertkit_broadcasts'] = new ConvertKit_Block_Broadcasts(); $this->classes['blocks_convertkit_content'] = new ConvertKit_Block_Content(); diff --git a/resources/backend/js/gutenberg.js b/resources/backend/js/gutenberg.js index 349bc387b..5fd597d28 100644 --- a/resources/backend/js/gutenberg.js +++ b/resources/backend/js/gutenberg.js @@ -746,30 +746,43 @@ function convertKitGutenbergRegisterBlock(block) { * @param {Function} setButtonDisabled Function to enable or disable the refresh button. */ const refreshBlocksDefinitions = function (props, setButtonDisabled) { - // Define data for WordPress AJAX request. - const data = new FormData(); - data.append('action', 'convertkit_get_blocks'); - data.append('nonce', convertkit_gutenberg.get_blocks_nonce); - // Disable the button. if (typeof setButtonDisabled !== 'undefined') { setButtonDisabled(true); } // Send AJAX request. - fetch(ajaxurl, { - method: 'POST', - credentials: 'same-origin', - body: data, + fetch(convertkit_gutenberg.ajaxurl, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'X-WP-Nonce': convertkit_gutenberg.get_blocks_nonce, + }, }) .then(function (response) { // Convert response JSON string to object. return response.json(); }) .then(function (response) { + // If the response includes a code, show an error notice. + if (typeof response.code !== 'undefined') { + // Show an error in the Gutenberg editor. + wp.data + .dispatch('core/notices') + .createErrorNotice('Kit: ' + response.message, { + id: 'convertkit-error', + }); + + // Enable refresh button. + if (typeof setButtonDisabled !== 'undefined') { + setButtonDisabled(false); + } + return; + } + // Update global ConvertKit Blocks object, so that any updated resources // are reflected when adding new ConvertKit Blocks. - convertkit_blocks = response.data; + convertkit_blocks = response; // Update this block's properties, so that has_access_token, has_resources // and the resources properties are updated. @@ -790,12 +803,14 @@ function convertKitGutenbergRegisterBlock(block) { // Show an error in the Gutenberg editor. wp.data .dispatch('core/notices') - .createErrorNotice('ConvertKit: ' + error, { + .createErrorNotice('Kit: ' + error, { id: 'convertkit-error', }); // Enable refresh button. - setButtonDisabled(false); + if (typeof setButtonDisabled !== 'undefined') { + setButtonDisabled(false); + } }); }; diff --git a/resources/backend/js/refresh-resources.js b/resources/backend/js/refresh-resources.js index e46ad6380..fca71e8d4 100644 --- a/resources/backend/js/refresh-resources.js +++ b/resources/backend/js/refresh-resources.js @@ -49,16 +49,12 @@ function convertKitRefreshResources(button) { button.classList.add('is-refreshing'); // Perform AJAX request to refresh resource. - fetch(convertkit_admin_refresh_resources.ajaxurl, { + fetch(convertkit_admin_refresh_resources.ajaxurl + resource, { method: 'POST', headers: { - 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Type': 'application/json', + 'X-WP-Nonce': convertkit_admin_refresh_resources.nonce, }, - body: new URLSearchParams({ - action: 'convertkit_admin_refresh_resources', - nonce: convertkit_admin_refresh_resources.nonce, - resource, // e.g. forms, landing_pages, tags. - }), }) .then(function (response) { // Convert response JSON string to object. @@ -70,9 +66,9 @@ function convertKitRefreshResources(button) { } // Show an error if the request wasn't successful. - if (!response.success) { + if (typeof response.code !== 'undefined') { // Show error notice. - convertKitRefreshResourcesOutputErrorNotice(response.data); + convertKitRefreshResourcesOutputErrorNotice(response.message); // Enable button and remove is-refreshing class. button.disabled = false; @@ -102,7 +98,7 @@ function convertKitRefreshResources(button) { case 'restrict_content': // Populate select `optgroup`` from response data, which comprises of Tags and Products. // Tags. - response.data.tags.forEach(function (item) { + response.tags.forEach(function (item) { document .querySelector( field + ' optgroup[data-resource=tags]' @@ -118,7 +114,7 @@ function convertKitRefreshResources(button) { }); // Products. - response.data.products.forEach(function (item) { + response.products.forEach(function (item) { document .querySelector( field + ' optgroup[data-resource=products]' @@ -136,7 +132,7 @@ function convertKitRefreshResources(button) { default: // Populate select options from response data. - response.data.forEach(function (item) { + response.forEach(function (item) { // Define label. let label = ''; switch (resource) { diff --git a/tests/Integration/RESTAPITest.php b/tests/Integration/RESTAPITest.php new file mode 100644 index 000000000..6d30cbc72 --- /dev/null +++ b/tests/Integration/RESTAPITest.php @@ -0,0 +1,330 @@ +settings = new \ConvertKit_Settings(); + $this->settings->save( + array( + 'access_token' => $_ENV['CONVERTKIT_OAUTH_ACCESS_TOKEN'], + 'refresh_token' => $_ENV['CONVERTKIT_OAUTH_REFRESH_TOKEN'], + 'token_expires' => ( time() + 10000 ), + ) + ); + } + + /** + * Performs actions after each test. + * + * @since 3.1.0 + */ + public function tearDown(): void + { + // Delete Credentials from Plugin's settings. + $this->settings->delete_credentials(); + parent::tearDown(); + } + + /** + * Test that the /wp-json/kit/v1/blocks REST API route returns a 401 when the user is not authorized. + * + * @since 3.1.0 + */ + public function testGetBlocksWhenUnauthorized() + { + $request = new \WP_REST_Request( 'GET', '/kit/v1/blocks' ); + $response = rest_get_server()->dispatch( $request ); + $this->assertSame( 401, $response->get_status() ); + } + + /** + * Test that the /wp-json/kit/v1/blocks REST API route returns blocks when the user is authorized. + * + * @since 3.1.0 + */ + public function testGetBlocks() + { + // Create and become editor. + $this->actAsEditor(); + + // Send request. + $request = new \WP_REST_Request( 'GET', '/kit/v1/blocks' ); + $response = rest_get_server()->dispatch( $request ); + + // Assert response is successful. + $this->assertSame( 200, $response->get_status() ); + + // Assert response data has the expected keys. + $data = $response->get_data(); + $this->assertArrayHasKey( 'broadcasts', $data ); + $this->assertArrayHasKey( 'formtrigger', $data ); + $this->assertArrayHasKey( 'form', $data ); + $this->assertArrayHasKey( 'form-builder', $data ); + $this->assertArrayHasKey( 'form-builder-field-email', $data ); + $this->assertArrayHasKey( 'form-builder-field-name', $data ); + $this->assertArrayHasKey( 'form-builder-field-custom', $data ); + $this->assertArrayHasKey( 'product', $data ); + } + + /** + * Test that the /wp-json/kit/v1/resources/refresh REST API route returns a 401 when the user is not authorized. + * + * @since 3.1.0 + */ + public function testRefreshResourcesWhenUnauthorized() + { + // Make request. + $request = new \WP_REST_Request( 'POST', '/kit/v1/resources/refresh/forms' ); + $response = rest_get_server()->dispatch( $request ); + + // Assert response is unsuccessful. + $this->assertSame( 401, $response->get_status() ); + } + + /** + * Test that the /wp-json/kit/v1/resources/refresh REST API route returns a 404 when the user is authorized and no resource type is provided. + * + * @since 3.1.0 + */ + public function testRefreshResourcesWithNoResourceType() + { + // Create and become editor. + $this->actAsEditor(); + + // Send request. + $request = new \WP_REST_Request( 'POST', '/kit/v1/resources/refresh' ); + $response = rest_get_server()->dispatch( $request ); + + // Assert response is unsuccessful. + $this->assertSame( 404, $response->get_status() ); + } + + /** + * Test that the /wp-json/kit/v1/resources/refresh REST API route returns a 500 when the user is authorized and an invalid resource type is provided. + * + * @since 3.1.0 + */ + public function testRefreshResourcesWithInvalidResourceType() + { + // Create and become editor. + $this->actAsEditor(); + + // Send request. + $request = new \WP_REST_Request( 'POST', '/kit/v1/resources/refresh/invalid' ); + $response = rest_get_server()->dispatch( $request ); + + // Assert response is unsuccessful. + $this->assertSame( 500, $response->get_status() ); + } + + /** + * Test that the /wp-json/kit/v1/resources/refresh/forms REST API route refreshes and returns resources when the user is authorized. + * + * @since 3.1.0 + */ + public function testRefreshResourcesForms() + { + // Create and become editor. + $this->actAsEditor(); + + // Send request. + $request = new \WP_REST_Request( 'POST', '/kit/v1/resources/refresh/forms' ); + $response = rest_get_server()->dispatch( $request ); + + // Assert response is successful. + $this->assertSame( 200, $response->get_status() ); + + // Assert response data has the expected keys. + $data = $response->get_data(); + $this->assertIsArray( $data ); + $this->assertArrayHasKeys( $data[0], [ 'id', 'name', 'created_at', 'type', 'format', 'embed_js', 'embed_url', 'archived', 'uid' ] ); + } + + /** + * Test that the /wp-json/kit/v1/resources/refresh/landing_pages REST API route refreshes and returns resources when the user is authorized. + * + * @since 3.1.0 + */ + public function testRefreshResourcesLandingPages() + { + // Create and become editor. + $this->actAsEditor(); + + // Send request. + $request = new \WP_REST_Request( 'POST', '/kit/v1/resources/refresh/landing_pages' ); + $response = rest_get_server()->dispatch( $request ); + + // Assert response is successful. + $this->assertSame( 200, $response->get_status() ); + + // Assert response data has the expected keys. + $data = $response->get_data(); + $this->assertIsArray( $data ); + $this->assertArrayHasKeys( $data[0], [ 'id', 'name', 'created_at', 'type', 'format', 'embed_js', 'embed_url', 'archived', 'uid' ] ); + } + + /** + * Test that the /wp-json/kit/v1/resources/refresh/tags REST API route refreshes and returns resources when the user is authorized. + * + * @since 3.1.0 + */ + public function testRefreshResourcesTags() + { + // Create and become editor. + $this->actAsEditor(); + + // Send request. + $request = new \WP_REST_Request( 'POST', '/kit/v1/resources/refresh/tags' ); + $response = rest_get_server()->dispatch( $request ); + + // Assert response is successful. + $this->assertSame( 200, $response->get_status() ); + + // Assert response data has the expected keys. + $data = $response->get_data(); + $this->assertIsArray( $data ); + $this->assertArrayHasKeys( $data[0], [ 'id', 'name', 'created_at' ] ); + } + + /** + * Test that the /wp-json/kit/v1/resources/refresh/posts REST API route refreshes and returns resources when the user is authorized. + * + * @since 3.1.0 + */ + public function testRefreshResourcesPosts() + { + // Create and become editor. + $this->actAsEditor(); + + // Send request. + $request = new \WP_REST_Request( 'POST', '/kit/v1/resources/refresh/posts' ); + $response = rest_get_server()->dispatch( $request ); + + // Assert response is successful. + $this->assertSame( 200, $response->get_status() ); + + // Assert response data has the expected keys. + $data = $response->get_data(); + $this->assertIsArray( $data ); + $this->assertArrayHasKeys( $data[0], [ 'id', 'title', 'url', 'published_at', 'is_paid', 'description', 'thumbnail_alt', 'thumbnail_url' ] ); + } + + /** + * Test that the /wp-json/kit/v1/resources/refresh/products REST API route refreshes and returns resources when the user is authorized. + * + * @since 3.1.0 + */ + public function testRefreshResourcesProducts() + { + // Create and become editor. + $this->actAsEditor(); + + // Send request. + $request = new \WP_REST_Request( 'POST', '/kit/v1/resources/refresh/products' ); + $response = rest_get_server()->dispatch( $request ); + + // Assert response is successful. + $this->assertSame( 200, $response->get_status() ); + + // Assert response data has the expected keys. + $data = $response->get_data(); + $this->assertIsArray( $data ); + $this->assertArrayHasKeys( $data[0], [ 'id', 'name', 'url', 'published' ] ); + } + + /** + * Test that the /wp-json/kit/v1/resources/refresh/restrict_content REST API route refreshes and returns resources when the user is authorized. + * + * @since 3.1.0 + */ + public function testRefreshResourcesRestrictContent() + { + // Create and become editor. + $this->actAsEditor(); + + // Send request. + $request = new \WP_REST_Request( 'POST', '/kit/v1/resources/refresh/restrict_content' ); + $response = rest_get_server()->dispatch( $request ); + + // Assert response is successful. + $this->assertSame( 200, $response->get_status() ); + + // Assert response data has the expected keys. + $data = $response->get_data(); + $this->assertIsArray( $data ); + + // Assert tags response data has the expected keys. + $this->assertArrayHasKey( 'tags', $data ); + $this->assertIsArray( $data['tags'] ); + $this->assertArrayHasKeys( $data['tags'][0], [ 'id', 'name', 'created_at' ] ); + + // Assert products response data has the expected keys. + $this->assertArrayHasKey( 'products', $data ); + $this->assertIsArray( $data['products'] ); + $this->assertArrayHasKeys( $data['products'][0], [ 'id', 'name', 'url', 'published' ] ); + } + + /** + * Act as an editor user. + * + * @since 3.1.0 + */ + private function actAsEditor() + { + $editor_id = static::factory()->user->create( [ 'role' => 'editor' ] ); + wp_set_current_user( $editor_id ); + } + + /** + * Assert that an array has the expected keys. + * + * @since 3.1.0 + * + * @param array $arr The array to assert. + * @param array $keys The keys to assert. + * @return void + */ + private function assertArrayHasKeys( $arr, $keys ) + { + foreach ( $keys as $key ) { + $this->assertArrayHasKey( $key, $arr ); + } + } +}