diff --git a/assets/js/ctct-plugin-admin/ajax.js b/assets/js/ctct-plugin-admin/ajax.js index fbf44d8b..ed471082 100644 --- a/assets/js/ctct-plugin-admin/ajax.js +++ b/assets/js/ctct-plugin-admin/ajax.js @@ -12,6 +12,7 @@ window.CTCTAJAX = {}; // Trigger any field modifications we need to do. that.handleReviewAJAX(); + that.handleAPITest(); }; // Handle saving the decision regarding the review prompt admin notice. @@ -50,5 +51,40 @@ window.CTCTAJAX = {}; } }; + that.handleAPITest = () => { + const apitestlink = document.querySelector('#ctct-test-api'); + if (apitestlink) { + apitestlink.addEventListener('click', (e) => { + e.preventDefault(); + + const data = new FormData(); + data.append('action', 'constant_contact_test_api_ajax_handler'); + + const params = new URLSearchParams(e.target.href); + + if (params.get('ctct-test-connection')) { + data.append('ctct-test-connection-nonce', params.get('ctct-test-connection')); + } + + fetch(window.ajaxurl, options = { + method: 'POST', body: data, + }) + .then((response) => response.json()) + .then((response) => { + const successDOM = document.querySelector('#ctct-test-api-result'); + successDOM.innerHTML = response.data.is_connected; + successDOM.setAttribute('class', ''); + if (response.success) { + successDOM.classList.add('success'); + } else { + successDOM.classList.add('no-success'); + } + }).catch((error) => { + console.log(error); + }); + }); + } + }; + that.init(); }(window, window.CTCTAJAX)); diff --git a/assets/sass/_admin-connect.scss b/assets/sass/_admin-connect.scss index 8ad0a098..7fc7040d 100644 --- a/assets/sass/_admin-connect.scss +++ b/assets/sass/_admin-connect.scss @@ -316,8 +316,7 @@ } // Connection Details -.ctct-connected-wrap{ - +.ctct-connected-wrap { .ctct-connection-details{ display: flex; text-align: left; @@ -343,15 +342,23 @@ } p{ - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - &.ctct-label{ justify-content: flex-end; } } } + + #ctct-test-api-result { + font-weight: bold; + margin-left: 10px; + &.success { + color: variables.$color-success-dark; + } + + &.no-success { + color: variables.$color-error-dark; + } + } } // Getting Started/ Next Steps diff --git a/assets/sass/_variables.scss b/assets/sass/_variables.scss index 43545af6..944d6dda 100644 --- a/assets/sass/_variables.scss +++ b/assets/sass/_variables.scss @@ -23,7 +23,9 @@ $color-black-translucent: rgba(0,0,0, 0.5); // Theming $color-error: $color-red; +$color-error-dark: #a90b00; $color-success: $color-green; +$color-success-dark: #1c7727; // constant contact colors $color-sky-blue: #88c5e2; diff --git a/includes/class-client.php b/includes/class-client.php index ccd48c91..2d3213c9 100644 --- a/includes/class-client.php +++ b/includes/class-client.php @@ -273,6 +273,10 @@ public function get_updated_lists_ids( $old_ids_string ) { return $this->get( "contact_lists/list_id_xrefs?sequence_ids={$old_ids_string}", $this->base_args ); } + public function test_connection() { + return $this->test( $this->base_args ); + } + /** * GET method for API requests. * @@ -434,4 +438,41 @@ private function delete( string $endpoint, array $args = [] ) : array { return json_decode( $response['body'], true ); } + + /** + * Method to do a basic API request test, to check on current credentials. + * + * @since 2.22.0 + * + * @param array $args + * @return bool + */ + private function test( array $args = [] ): bool { + + $url = $this->base_url . '/account/user/privileges'; + + $options = [ + /** + * Sets the HTTP timeout, in seconds, for the request. + * + * @since 2.22.0 + * + * @param int $value The timeout limit, in seconds. Defaults to 30. + * @param string $request_url The request URL. + * + * @return int + */ + 'timeout' => apply_filters( 'http_request_timeout', 30, $url ), + 'headers' => $args, + ]; + + $response = wp_safe_remote_get( $url, $options ); + if ( is_wp_error( $response ) ) { + return false; + } + + $code = wp_remote_retrieve_response_code( $response ); + + return 200 === $code; + } } diff --git a/includes/class-connect.php b/includes/class-connect.php index be1bd056..d8303d5c 100644 --- a/includes/class-connect.php +++ b/includes/class-connect.php @@ -157,7 +157,7 @@ public function admin_page_display() { if ( constant_contact_get_needs_manual_reconnect() ) { $heading = esc_html__( 'Manual reconnection required', 'constant-contact-forms' ); $description = esc_html__( 'Issues with reauthentication for tokens occurred and a manual disconnect and reconnect is needed. Use the status button to start the re-authentication process.', 'constant-contact-forms' ); - $btn_value = esc_attr__( 'Disconnected', 'constant-contact-forms' ); + $btn_value = esc_attr__( 'Force disconnect', 'constant-contact-forms' ); } $times = constant_contact_get_issued_expired_access_token_times(); ?> @@ -228,7 +228,15 @@ public function admin_page_display() {

- + +

+

+ +

+
+
+

+

diff --git a/includes/helper-functions.php b/includes/helper-functions.php index e1e12bfd..f1a1a456 100644 --- a/includes/helper-functions.php +++ b/includes/helper-functions.php @@ -841,7 +841,7 @@ function constant_contact_get_date_field_order( $format = '' ) { /** * Return an array of timestamps for issued, current, and expected expiration time for current access token. * - * @since NEXT + * @since 2.21.0 * * @return array|null * @throws Exception @@ -861,3 +861,31 @@ function constant_contact_get_issued_expired_access_token_times() { 'expires' => $obj->format( 'Y-m-d, H:i' ), ]; }; + +/** + * Make a test API request to a general endpoint. + * + * Meant to just verify access tokens are still valid. + * + * @since 2.22.0 + * + * @return bool + */ +function constant_contact_test_api_ajax_handler(): bool { + + if ( ! current_user_can( 'manage_options' ) ) { + exit(); + } + + if ( ! wp_verify_nonce( $_REQUEST['ctct-test-connection-nonce'], 'ctct-test-connection' ) ) { + wp_send_json_error( [ 'nonce-result' => 'failed' ] ); + exit(); + } + + $is_connected = constant_contact()->get_api()->cc()->test_connection(); + $is_connected ? + wp_send_json_success( [ 'is_connected' => 'did connect' ], 200 ) : + wp_send_json_error( [ 'is_connected' => 'did not connect' ], 200 ); + exit(); +} +add_action( 'wp_ajax_constant_contact_test_api_ajax_handler', 'constant_contact_test_api_ajax_handler' );