Skip to content

Commit

Permalink
Plugin: Add API health checks (#189)
Browse files Browse the repository at this point in the history
* add client test staus endpoint

* show API connection health messages

* show client ip range

* add admin js and ignore build directories from the repo

* update npm build commands

* get api connection status to the browser

* enqueue admin js

* make sure the backend data is available in the site editor

* cleanup status check

* cleanup script
  • Loading branch information
jhnstn authored Aug 27, 2024
1 parent 8801689 commit b64a2b6
Show file tree
Hide file tree
Showing 11 changed files with 230 additions and 60 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ node_modules/
*.zip

/vendor/
/build/
21 changes: 21 additions & 0 deletions plugin/admin/assets/js/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

(function ( { wp, wpcloud } ) {
if (!wp || !wpcloud ) {
return;
}
if (!wpcloud.apiConnected) {
wp.data.dispatch('core/notices').createNotice(
'error',
'You are not connected to the WP Cloud API. Station requires a valid API connection to function properly.', // Text string to display.
{
isDismissible: false,
actions: [
{
url: '/wp-admin/admin.php?page=wpcloud_admin_settings',
label: 'WP Cloud Settings',
},
],
}
);
}
})( window );
64 changes: 43 additions & 21 deletions plugin/admin/init.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
declare( strict_types = 1 );

require_once 'includes/wpcloud-headstart.php';
$wpcloud_request_api_status = wpcloud_client_test_status();
$wpcloud_api_healthy = is_wp_error( $wpcloud_request_api_status ) ? false : true;

/**
* Get the available themes.
Expand Down Expand Up @@ -67,6 +69,8 @@ function wpcloud_settings_sanitize( $input ) {
* @return void
*/
function wpcloud_settings_init(): void {
global $wpcloud_api_healthy;

register_setting( 'wpcloud', 'wpcloud_settings', 'wpcloud_settings_sanitize' );

add_settings_section(
Expand Down Expand Up @@ -113,6 +117,7 @@ function wpcloud_settings_init(): void {
'wpcloud_custom_data' => 'custom',
'default' => '',
'description' => __( 'The default domain to use for new sites. Each site will use this root domain with the site name as the subdomain. If left empty a unique subdomain will be generated for each site.' ),
'disabled' => ! $wpcloud_api_healthy,
)
);

Expand All @@ -127,6 +132,7 @@ function wpcloud_settings_init(): void {
'class' => 'wpcloud_row',
'description' => __( 'The URL to send site creation events to. This can be used to trigger actions on site creation.' ),
'client_meta_key' => 'webhook_url',
'disabled' => ! $wpcloud_api_healthy,
)
);

Expand Down Expand Up @@ -161,6 +167,7 @@ function wpcloud_settings_init(): void {
'description' => __( 'The default theme to install on new sites.' ),
'items' => $themes,
'default' => array_keys( $themes )[0],
'disabled' => ! $wpcloud_api_healthy,
)
);

Expand All @@ -176,6 +183,7 @@ function wpcloud_settings_init(): void {
'wpcloud_custom_data' => 'custom',
'description' => __( 'Plugins available to install or activate with new installs. ' ),
'items' => wpcloud_admin_get_available_plugins(),
'disabled' => ! $wpcloud_api_healthy,
)
);

Expand All @@ -191,7 +199,8 @@ function wpcloud_settings_init(): void {
'wpcloud_custom_data' => 'custom',
'description' => __( 'Enable caching of common client requests to reduce the number of requests to the WP Cloud API and speed up page loads. The cache is stored in memory per request.' ),
'type' => 'checkbox',
'checked' => get_option( 'wpcloud_settings', array() )['client_cache'] ?? false,
'checked' => get_option( 'wpcloud_settings', array() )['client_cache'] ?? true,
'disabled' => ! $wpcloud_api_healthy,
)
);

Expand All @@ -207,6 +216,7 @@ function wpcloud_settings_init(): void {
'type' => 'checkbox',
'wpcloud_custom_data' => 'custom',
'description' => __( 'Run the headstart script to setup the demo site. The script will not delete or overwrite any existing pages or settings so it\'s safe to run multiple times.' ),
'disabled' => ! $wpcloud_api_healthy,
)
);
}
Expand Down Expand Up @@ -279,7 +289,7 @@ function wpcloud_field_input_cb( array $args ): void {
if ( 'checkbox' === $type ) {
$value = '1';
}
$disabled = $args['disabled'] ?? false;
$disabled = $args['disabled'] ?? false ? ' disabled ' : '';
?>
<input
type="<?php echo esc_attr( $type ); ?>"
Expand All @@ -290,13 +300,10 @@ function wpcloud_field_input_cb( array $args ): void {
if ( 'checkbox' === $type && $checked ) {
echo ' checked '; }
?>
<?php
if ( $disabled ) {
echo ' disabled '; }
?>
<?php echo esc_attr( $disabled ); ?>
>
<?php if ( isset( $args['description'] ) ) { ?>
<p class="description"><?php echo esc_html( $args['description'] ); ?></p>
<p class="description <?php echo esc_attr( $disabled ); ?>"><?php echo esc_html( $args['description'] ); ?></p>
<?php
}
if ( isset( $args['error'] ) ) {
Expand All @@ -313,16 +320,13 @@ function wpcloud_field_input_cb( array $args ): void {
* @return void.
*/
function wpcloud_client_meta_field_input_cb( array $args ): void {
$meta_key = $args['client_meta_key'] ?? '';
$request = wpcloud_client_get_client_meta( $meta_key );
if ( is_wp_error( $request ) ) {
// Let's ignore 404s.
if ( ! str_contains( $request->get_error_message(), 'Resource not found' ) ) {
$args['error'] = 'Warning: There was a issue retrieving the setting: ' . $request->get_error_message();
$disabled = $args['{disabled'] ?? false;
if ( ! $disabled ) {
$meta_key = $args['client_meta_key'] ?? '';
$request = wpcloud_client_get_client_meta( $meta_key );
if ( ! is_wp_error( $request ) ) {
$args['value'] = $request->$meta_key;
}
error_log( $request->get_error_message() ); // phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_error_log
} else {
$args['value'] = $request->$meta_key;
}

wpcloud_field_input_cb( $args );
Expand Down Expand Up @@ -363,10 +367,11 @@ function wpcloud_field_select_cb( array $args ): void {
$default = $args['default'] ?? '';
$value = esc_attr( $options[ $label_for ] ?? $default );
$items = $args['items'];
$disabled = $args['disabled'] ?? false ? ' disabled ' : '';

// output the field.
?>
<select name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $label_for ); ?>">
<select name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $label_for ); ?>" <?php echo esc_attr( $disabled ); ?> >
<option value=''></option>
<?php
foreach ( $items as $item_value => $item_label ) {
Expand All @@ -376,7 +381,7 @@ function wpcloud_field_select_cb( array $args ): void {
?>
</select>
<?php if ( isset( $args['description'] ) ) { ?>
<p class="description"><?php echo esc_html( $args['description'] ); ?></p>
<p class="description <?php echo esc_attr( $disabled ); ?>"><?php echo esc_html( $args['description'] ); ?></p>
<?php
}
}
Expand All @@ -391,6 +396,7 @@ function wpcloud_field_software_cb( array $args ): void {
$options = get_option( 'wpcloud_settings' );
$label_for = esc_attr( $args['label_for'] );
$items = $args['items'];
$disabled = $args['disabled'] ?? false ? ' disabled ' : '';

// output the field.
echo '<table>';
Expand All @@ -400,10 +406,12 @@ function wpcloud_field_software_cb( array $args ): void {
?>
<tr>
<td style="padding: 5px;">
<label><?php echo esc_html( $item_label ); ?></label>
<label class="<?php echo esc_attr( $disabled ); ?>"><?php echo esc_html( $item_label ); ?></label>
</td>
<td style="padding: 5px;">
<select name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $name ); ?>">
<select name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $name ); ?>"
<?php echo esc_attr( $disabled ); ?>
>
<option value=""></option>
<option value="install" <?php echo ( 'install' === $value ) ? 'selected' : ''; ?>>Install</option>
<option value="activate" <?php echo ( 'activate' === $value ) ? 'selected' : ''; ?>>Activate</option>
Expand All @@ -415,7 +423,7 @@ function wpcloud_field_software_cb( array $args ): void {
echo '</table>';
if ( isset( $args['description'] ) ) {
?>
<p class="description"><?php echo esc_html( $args['description'] ); ?></p>
<p class="description <?php echo esc_attr( $disabled ); ?>"><?php echo esc_html( $args['description'] ); ?></p>
<?php
}
}
Expand Down Expand Up @@ -533,3 +541,17 @@ function cc_mime_types( $mimes ) {
return $mimes;
}
add_filter( 'upload_mimes', 'cc_mime_types' );


/**
* Enqueue the admin styles
*
* @return void
*/
add_action(
'admin_enqueue_scripts',
function () {
$config = require_once plugin_dir_path( __FILE__ ) . 'assets/js/build/index.asset.php';
wp_enqueue_script( 'wpcloud-admin', plugin_dir_url( __FILE__ ) . 'assets/js/build/index.js', $config['dependencies'], $config['version'], true );
}
);
121 changes: 97 additions & 24 deletions plugin/admin/options.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,45 +10,118 @@
}
$client_ips = null;
$server_ip = filter_var( wp_unslash( $_SERVER['SERVER_ADDR'] ?? '' ), FILTER_VALIDATE_IP );
$ip_error = false;

global $wpcloud_request_api_status;
global $wpcloud_api_healthy;

$wpcloud_api_error = '';

if ( ! $wpcloud_api_healthy ) {
$wpcloud_api_error = $wpcloud_request_api_status->get_error_message();
$ip_error = str_contains( $wpcloud_api_error, 'not allowed' );
} else {
$client_ips_request = wpcloud_client_domain_ip_addresses( null );
if ( is_wp_error( $client_ips_request ) ) {
$client_ips = $client_ips_request;
} else {
$client_ips = ( (array) $client_ips_request )['ips'] ?? array();
}
}

?>
<style>
.wp-cloud-settings {
.description {
width: 400px;
}
.disabled {
opacity: 0.5;
}
.warning {
font-weight: bold;
}
ul {
list-style: disc;
padding-left: 40px;
}
}
</style>
<div class="wrap wp-cloud-settings">
<h1>WP Cloud</h1>
<?php if ( ! $wpcloud_api_healthy ) : ?>
</div>
<div class="notice notice-error" >
<h3>WP Cloud API is not healthy</h3>
<p>
<?php esc_attr_e( 'Your site is unable to connect to the WP Cloud API' ); ?>
<br />
<strong><?php esc_attr_e( 'Please check the following:' ); ?></strong>
</p>

<ul>
<?php if ( defined( 'IS_ATOMIC' ) && IS_ATOMIC ) : ?>
<li>
<p>
<?php esc_attr_e( 'It appears you are trying to run Station on a WP Cloud site. For security reasons, WP Cloud sites are unable to connect to the WP Cloud API directly. ' ); ?>
</p>
<p>
<strong><?php esc_attr_e( 'Please install Station on a different platform.' ); ?></strong>
</p>
</li>
<?php else : ?>
<?php if ( $ip_error ) : ?>
<li>
<p>
<?php esc_attr_e( 'The WP Cloud API limits access by IP address.' ); ?>
<br/>
<?php esc_attr_e( 'The server IP address appears to be:' ); ?>
</p>
<ul><li><strong><?php echo esc_attr( $server_ip ); ?></strong></li></ul>
<p>
<?php esc_attr_e( 'Please verify and update the server IP address with your WP Cloud representative.' ); ?>
<?php else : ?>
<li>
<p>
<?php echo esc_attr( $wpcloud_api_error ); ?>
</p>
</li>
<?php endif; ?>
<?php endif; ?>
</ul>
<p>
<?php esc_html_e( 'Return back to this page after correcting the API issues to continue configuring Station.' ); ?>
</p>
</div>
<?php else : ?>
<h2>Details</h2>
<table class="form-table" role="presentation">
<tbody>
<?php if ( $client_ips ) : ?>
<tr class="wpcloud_row">
<th scope="row">
<label for="wpcloud_api_key">WP Cloud IP Address Range</label>
</th>
<td>
<?php if ( is_wp_error( $client_ips ) ) : ?>
<?php echo esc_html( $client_ips->get_error_message() ); ?>
<?php else : ?>
<?php foreach ( $client_ips as $ip ) : ?>
<?php echo esc_html( $ip ); ?>
<?php endforeach; ?>
<?php endif; ?>
</td>
</tr>
<?php endif; ?>
</tbody>
</table>
<?php endif; ?>


<form action="options.php" method="post">
<?php
settings_fields( 'wpcloud' );
do_settings_sections( 'wpcloud' );
submit_button( 'Save Settings' );
?>
</form>
<h2>Details</h2>
<table class="form-table" role="presentation">
<tbody>
<?php if ( $client_ips ) : ?>
<tr class="wpcloud_row">
<th scope="row">
<label for="wpcloud_api_key">WP Cloud IP Address Range</label>
</th>
<td>
<?php foreach ( $client_ips as $ip ) : ?>
<?php echo esc_html( $ip ); ?>
<?php endforeach; ?>
</td>
</tr>
<?php endif; ?>
<tr class="wpcloud_row">
<th scope="row">
<label for="wpcloud_api_key">Server IP Address</label>
</th>
<td>
<?php echo esc_html( $server_ip ); ?>
</td>
</tr>
</tbody></table>
1 change: 0 additions & 1 deletion plugin/assets/js/build/index.asset.php

This file was deleted.

1 change: 0 additions & 1 deletion plugin/assets/js/build/index.js

This file was deleted.

16 changes: 11 additions & 5 deletions plugin/blocks/init.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,17 @@ function wpcloud_block_available_wp_versions(): array {
}

/**
* Enqueue the admin scripts.
* Enqueue the block admin scripts in the editor.
*
* @param WP_Screen $current_screen The current screen.
*
* @return void
*/
function wpcloud_block_admin_enqueue_scripts(): void {
if ( ! wp_doing_ajax() ) {
function wpcloud_block_admin_enqueue_scripts( $current_screen ): void {
if ( ! $current_screen instanceof WP_Screen ) {
return;
}
if ( $current_screen->is_block_editor() || 'site-editor' === $current_screen->base ) {
wp_register_script( 'wpcloud-blocks-site-form', '', array(), '1.0.0', true );
wp_enqueue_script( 'wpcloud-blocks-site-form' );
wp_add_inline_script(
Expand All @@ -114,8 +119,9 @@ function wpcloud_block_admin_enqueue_scripts(): void {
'wpcloud.dataCenters=' . wp_json_encode( wpcloud_block_available_datacenters_options() ) . ';' .
'wpcloud.linkableSiteDetails=' . wp_json_encode( WPCloud_Site::get_linkable_detail_options() ) . ';' .
'wpcloud.siteMutableOptions=' . wp_json_encode( WPCloud_Site::get_mutable_options() ) . ';' .
'wpcloud.siteMutableFields=' . wp_json_encode( WPCloud_Site::get_mutable_fields() ) . ';'
'wpcloud.siteMutableFields=' . wp_json_encode( WPCloud_Site::get_mutable_fields() ) . ';' .
'wpcloud.apiConnected=' . wp_json_encode( WPCloud_Site::is_api_connected() ) . ';'
);
}
}
add_action( 'admin_init', 'wpcloud_block_admin_enqueue_scripts' );
add_action( 'current_screen', 'wpcloud_block_admin_enqueue_scripts' );
Loading

0 comments on commit b64a2b6

Please sign in to comment.