From 0e6b9838881a50f18a4882971589f05f1cf897be Mon Sep 17 00:00:00 2001 From: David Stone Date: Tue, 30 Dec 2025 00:51:58 -0700 Subject: [PATCH 1/3] Fix enhance api requests --- .../class-base-host-provider.php | 20 +++++++------- .../class-closte-host-provider.php | 18 ++++++------- .../class-enhance-host-provider.php | 27 +++++++++---------- .../class-gridpane-host-provider.php | 3 +++ .../class-wpengine-host-provider.php | 10 ++++++- 5 files changed, 43 insertions(+), 35 deletions(-) diff --git a/inc/integrations/host-providers/class-base-host-provider.php b/inc/integrations/host-providers/class-base-host-provider.php index 51616542..c730e590 100644 --- a/inc/integrations/host-providers/class-base-host-provider.php +++ b/inc/integrations/host-providers/class-base-host-provider.php @@ -100,17 +100,17 @@ public function init(): void { // avoid text domain loaded at the wrong time. add_action('init', [$this, 'alert_provider_not_setup']); } - } - - /* - * Load the dependencies. - */ - $this->load_dependencies(); + } else { + /* + * Load the dependencies. + */ + $this->load_dependencies(); - /* - * Initialize the hooks. - */ - $this->register_hooks(); + /* + * Initialize the hooks. + */ + $this->register_hooks(); + } } add_filter('wu_domain_manager_get_integrations', [$this, 'self_register']); diff --git a/inc/integrations/host-providers/class-closte-host-provider.php b/inc/integrations/host-providers/class-closte-host-provider.php index 8397f04e..81aa6699 100644 --- a/inc/integrations/host-providers/class-closte-host-provider.php +++ b/inc/integrations/host-providers/class-closte-host-provider.php @@ -105,7 +105,7 @@ public function on_add_domain($domain, $site_id): void { if (wu_get_isset($domain_response, 'success', false)) { wu_log_add('integration-closte', sprintf('Domain %s added successfully, requesting SSL certificate', $domain)); $this->request_ssl_certificate($domain); - } elseif (isset($domain_response['error']) && $domain_response['error'] === 'Invalid or empty domain: ' . $domain) { + } elseif (isset($domain_response['error']) && 'Invalid or empty domain: ' . $domain === $domain_response['error']) { wu_log_add('integration-closte', sprintf('Domain %s rejected by Closte API as invalid. This may be expected for Closte subdomains or internal domains.', $domain)); } else { wu_log_add('integration-closte', sprintf('Failed to add domain %s. Response: %s', $domain, wp_json_encode($domain_response))); @@ -180,8 +180,6 @@ private function request_ssl_certificate($domain) { '/certificate/install', ]; - $ssl_response = null; - foreach ($ssl_endpoints as $endpoint) { wu_log_add('integration-closte', sprintf('Trying SSL endpoint: %s', $endpoint)); @@ -217,7 +215,7 @@ private function request_ssl_certificate($domain) { * * @since 2.0.0 * @param string $domain The domain to check SSL status for. - * @return array|object + * @return array */ public function check_ssl_status($domain) { @@ -264,13 +262,13 @@ public function test_connection(): void { * @since 1.7.3 * @param string $endpoint Endpoint to send the call to. * @param array $data Array containing the params to the call. - * @return object + * @return array */ public function send_closte_api_request($endpoint, $data) { if (defined('CLOSTE_CLIENT_API_KEY') === false) { wu_log_add('integration-closte', 'CLOSTE_CLIENT_API_KEY constant not defined'); - return (object) [ + return [ 'success' => false, 'error' => 'Closte API Key not found.', ]; @@ -278,7 +276,7 @@ public function send_closte_api_request($endpoint, $data) { if (empty(CLOSTE_CLIENT_API_KEY)) { wu_log_add('integration-closte', 'CLOSTE_CLIENT_API_KEY is empty'); - return (object) [ + return [ 'success' => false, 'error' => 'Closte API Key is empty.', ]; @@ -324,7 +322,7 @@ public function send_closte_api_request($endpoint, $data) { // Check for HTTP errors if ($response_code >= 400) { wu_log_add('integration-closte', sprintf('HTTP error %d for endpoint %s', $response_code, $endpoint)); - return (object) [ + return [ 'success' => false, 'error' => sprintf('HTTP %d error', $response_code), 'response_body' => $response_body, @@ -346,7 +344,7 @@ public function send_closte_api_request($endpoint, $data) { } wu_log_add('integration-closte', sprintf('JSON decode error: %s', json_last_error_msg())); - return (object) [ + return [ 'success' => false, 'error' => 'Invalid JSON response', 'json_error' => json_last_error_msg(), @@ -354,7 +352,7 @@ public function send_closte_api_request($endpoint, $data) { } wu_log_add('integration-closte', 'Empty response body'); - return (object) [ + return [ 'success' => false, 'error' => 'Empty response', ]; diff --git a/inc/integrations/host-providers/class-enhance-host-provider.php b/inc/integrations/host-providers/class-enhance-host-provider.php index 06981e09..a276e992 100644 --- a/inc/integrations/host-providers/class-enhance-host-provider.php +++ b/inc/integrations/host-providers/class-enhance-host-provider.php @@ -100,6 +100,7 @@ public function get_fields() { return [ 'WU_ENHANCE_API_TOKEN' => [ 'type' => 'password', + 'html_attr' => ['autocomplete' => 'new-password'], 'title' => __('Enhance API Token', 'ultimate-multisite'), 'placeholder' => __('Your bearer token', 'ultimate-multisite'), ], @@ -137,13 +138,11 @@ public function on_add_domain($domain, $site_id): void { $domain_response = $this->send_enhance_api_request( '/servers/' . $server_id . '/domains', 'POST', - [ - 'domain' => $domain, - ] + $domain ); // Check if domain was added successfully - if (wu_get_isset($domain_response, 'id')) { + if (wu_get_isset($domain_response, 'domainid')) { wu_log_add('integration-enhance', sprintf('Domain %s added successfully. SSL will be automatically provisioned via LetsEncrypt when DNS resolves.', $domain)); } elseif (isset($domain_response['error'])) { wu_log_add('integration-enhance', sprintf('Failed to add domain %s. Error: %s', $domain, wp_json_encode($domain_response))); @@ -179,10 +178,10 @@ public function on_remove_domain($domain, $site_id): void { $domain_id = null; - if (isset($domains_list['items']) && is_array($domains_list['items'])) { - foreach ($domains_list['items'] as $item) { - if (isset($item['domain']) && $item['domain'] === $domain) { - $domain_id = $item['id']; + if (isset($domains_list['domains']) && is_array($domains_list['domains'])) { + foreach ($domains_list['domains'] as $item) { + if (isset($item['domainName']) && $item['domainName'] === $domain) { + $domain_id = $item['domainId']; break; } } @@ -250,8 +249,7 @@ public function test_connection(): void { // Test by attempting to list domains $response = $this->send_enhance_api_request( - '/servers/' . $server_id . '/domains', - 'GET' + '/servers/' . $server_id ); if (isset($response['items']) || isset($response['id'])) { @@ -261,7 +259,8 @@ public function test_connection(): void { ] ); } else { - $error = new \WP_Error('connection-failed', __('Failed to connect to Enhance API', 'ultimate-multisite')); + // Translators: %s the full error message. + $error = new \WP_Error('connection-failed', sprintf(__('Failed to connect to Enhance API: %s', 'ultimate-multisite'), $response['error'] ?? 'Unknown error')); wp_send_json_error($error); } } @@ -270,9 +269,9 @@ public function test_connection(): void { * Sends a request to the Enhance API with the configured bearer token. * * @since 2.0.0 - * @param string $endpoint API endpoint (relative to base URL). - * @param string $method HTTP method (GET, POST, DELETE, etc.). - * @param array $data Request body data (for POST/PUT/PATCH). + * @param string $endpoint API endpoint (relative to base URL). + * @param string $method HTTP method (GET, POST, DELETE, etc.). + * @param array|string $data Request body data (for POST/PUT/PATCH). * @return array|object */ public function send_enhance_api_request($endpoint, $method = 'GET', $data = []) { diff --git a/inc/integrations/host-providers/class-gridpane-host-provider.php b/inc/integrations/host-providers/class-gridpane-host-provider.php index 8cb375dc..599dea6e 100644 --- a/inc/integrations/host-providers/class-gridpane-host-provider.php +++ b/inc/integrations/host-providers/class-gridpane-host-provider.php @@ -62,6 +62,9 @@ class Gridpane_Host_Provider extends Base_Host_Provider { */ protected $constants = [ 'WU_GRIDPANE', + 'WU_GRIDPANE_API_KEY', + 'WU_GRIDPANE_APP_ID', + 'WU_GRIDPANE_SERVER_ID', ]; /** diff --git a/inc/integrations/host-providers/class-wpengine-host-provider.php b/inc/integrations/host-providers/class-wpengine-host-provider.php index 4416ebc7..599765ec 100644 --- a/inc/integrations/host-providers/class-wpengine-host-provider.php +++ b/inc/integrations/host-providers/class-wpengine-host-provider.php @@ -105,7 +105,9 @@ public function load_dependencies(): void { * @return void */ public function on_add_domain($domain, $site_id): void { - + if (! class_exists('WPE_API')) { + return; + } $api = new \WPE_API(); $api->set_arg('method', 'domain'); @@ -124,6 +126,9 @@ public function on_add_domain($domain, $site_id): void { * @return void */ public function on_remove_domain($domain, $site_id): void { + if (! class_exists('WPE_API')) { + return; + } $api = new \WPE_API(); @@ -197,6 +202,9 @@ public function get_logo() { * @return void */ public function test_connection(): void { + if (! class_exists('WPE_API')) { + wp_send_json_error(__('Class WPE_API is not installed.', 'ultimate-multisite')); + } $api = new \WPE_API(); From e10e0126a5338274b07b0112305d426e6c4f2cc0 Mon Sep 17 00:00:00 2001 From: David Stone Date: Fri, 9 Jan 2026 18:15:14 -0700 Subject: [PATCH 2/3] Use the correct website id --- .../class-enhance-host-provider.php | 91 +++++++++++++------ 1 file changed, 61 insertions(+), 30 deletions(-) diff --git a/inc/integrations/host-providers/class-enhance-host-provider.php b/inc/integrations/host-providers/class-enhance-host-provider.php index a276e992..95aae8e1 100644 --- a/inc/integrations/host-providers/class-enhance-host-provider.php +++ b/inc/integrations/host-providers/class-enhance-host-provider.php @@ -65,7 +65,8 @@ class Enhance_Host_Provider extends Base_Host_Provider { protected $constants = [ 'WU_ENHANCE_API_TOKEN', 'WU_ENHANCE_API_URL', - 'WU_ENHANCE_SERVER_ID', + 'WU_ENHANCE_ORG_ID', + 'WU_ENHANCE_WEBSITE_ID', ]; /** @@ -98,19 +99,23 @@ public function detect(): bool { public function get_fields() { return [ - 'WU_ENHANCE_API_TOKEN' => [ + 'WU_ENHANCE_API_TOKEN' => [ 'type' => 'password', 'html_attr' => ['autocomplete' => 'new-password'], 'title' => __('Enhance API Token', 'ultimate-multisite'), 'placeholder' => __('Your bearer token', 'ultimate-multisite'), ], - 'WU_ENHANCE_API_URL' => [ + 'WU_ENHANCE_API_URL' => [ 'title' => __('Enhance API URL', 'ultimate-multisite'), 'placeholder' => __('e.g. https://your-enhance-server.com', 'ultimate-multisite'), ], - 'WU_ENHANCE_SERVER_ID' => [ - 'title' => __('Server ID', 'ultimate-multisite'), - 'placeholder' => __('UUID of your server', 'ultimate-multisite'), + 'WU_ENHANCE_ORG_ID' => [ + 'title' => __('Organization ID', 'ultimate-multisite'), + 'placeholder' => __('UUID of your organization', 'ultimate-multisite'), + ], + 'WU_ENHANCE_WEBSITE_ID' => [ + 'title' => __('Website ID', 'ultimate-multisite'), + 'placeholder' => __('UUID of your website', 'ultimate-multisite'), ], ]; } @@ -127,22 +132,33 @@ public function on_add_domain($domain, $site_id): void { wu_log_add('integration-enhance', sprintf('Adding domain: %s for site ID: %d', $domain, $site_id)); - $server_id = defined('WU_ENHANCE_SERVER_ID') ? WU_ENHANCE_SERVER_ID : ''; + $org_id = defined('WU_ENHANCE_ORG_ID') ? WU_ENHANCE_ORG_ID : ''; + $website_id = defined('WU_ENHANCE_WEBSITE_ID') ? WU_ENHANCE_WEBSITE_ID : ''; + + if (empty($org_id)) { + wu_log_add('integration-enhance', 'Organization ID not configured'); + return; + } - if (empty($server_id)) { - wu_log_add('integration-enhance', 'Server ID not configured'); + if (empty($website_id)) { + wu_log_add('integration-enhance', 'Website ID not configured'); return; } - // Add the domain to the server + // Add the domain to the website + // POST /orgs/{org_id}/websites/{website_id}/domains + $domain_data = [ + 'domain' => $domain, + ]; + $domain_response = $this->send_enhance_api_request( - '/servers/' . $server_id . '/domains', + '/orgs/' . $org_id . '/websites/' . $website_id . '/domains', 'POST', - $domain + $domain_data ); // Check if domain was added successfully - if (wu_get_isset($domain_response, 'domainid')) { + if (wu_get_isset($domain_response, 'id') || (isset($domain_response['success']) && $domain_response['success'])) { wu_log_add('integration-enhance', sprintf('Domain %s added successfully. SSL will be automatically provisioned via LetsEncrypt when DNS resolves.', $domain)); } elseif (isset($domain_response['error'])) { wu_log_add('integration-enhance', sprintf('Failed to add domain %s. Error: %s', $domain, wp_json_encode($domain_response))); @@ -163,25 +179,31 @@ public function on_remove_domain($domain, $site_id): void { wu_log_add('integration-enhance', sprintf('Removing domain: %s for site ID: %d', $domain, $site_id)); - $server_id = defined('WU_ENHANCE_SERVER_ID') ? WU_ENHANCE_SERVER_ID : ''; + $org_id = defined('WU_ENHANCE_ORG_ID') ? WU_ENHANCE_ORG_ID : ''; + $website_id = defined('WU_ENHANCE_WEBSITE_ID') ? WU_ENHANCE_WEBSITE_ID : ''; - if (empty($server_id)) { - wu_log_add('integration-enhance', 'Server ID not configured'); + if (empty($org_id)) { + wu_log_add('integration-enhance', 'Organization ID not configured'); + return; + } + + if (empty($website_id)) { + wu_log_add('integration-enhance', 'Website ID not configured'); return; } // First, get the domain ID by listing domains and finding a match + // GET /orgs/{org_id}/websites/{website_id}/domains $domains_list = $this->send_enhance_api_request( - '/servers/' . $server_id . '/domains', - 'GET' + '/orgs/' . $org_id . '/websites/' . $website_id . '/domains' ); $domain_id = null; - if (isset($domains_list['domains']) && is_array($domains_list['domains'])) { - foreach ($domains_list['domains'] as $item) { - if (isset($item['domainName']) && $item['domainName'] === $domain) { - $domain_id = $item['domainId']; + if (isset($domains_list['items']) && is_array($domains_list['items'])) { + foreach ($domains_list['items'] as $item) { + if (isset($item['domain']) && $item['domain'] === $domain) { + $domain_id = $item['id']; break; } } @@ -193,8 +215,9 @@ public function on_remove_domain($domain, $site_id): void { } // Delete the domain - $delete_response = $this->send_enhance_api_request( - '/servers/' . $server_id . '/domains/' . $domain_id, + // DELETE /orgs/{org_id}/websites/{website_id}/domains/{domain_id} + $this->send_enhance_api_request( + '/orgs/' . $org_id . '/websites/' . $website_id . '/domains/' . $domain_id, 'DELETE' ); @@ -239,20 +262,28 @@ public function on_remove_subdomain($subdomain, $site_id): void { */ public function test_connection(): void { - $server_id = defined('WU_ENHANCE_SERVER_ID') ? WU_ENHANCE_SERVER_ID : ''; + $org_id = defined('WU_ENHANCE_ORG_ID') ? WU_ENHANCE_ORG_ID : ''; + $website_id = defined('WU_ENHANCE_WEBSITE_ID') ? WU_ENHANCE_WEBSITE_ID : ''; + + if (empty($org_id)) { + $error = new \WP_Error('no-org-id', __('Organization ID is not configured', 'ultimate-multisite')); + wp_send_json_error($error); + return; + } - if (empty($server_id)) { - $error = new \WP_Error('no-server-id', __('Server ID is not configured', 'ultimate-multisite')); + if (empty($website_id)) { + $error = new \WP_Error('no-website-id', __('Website ID is not configured', 'ultimate-multisite')); wp_send_json_error($error); return; } - // Test by attempting to list domains + // Test by attempting to get website info. + // GET /orgs/{org_id}/websites/{website_id} $response = $this->send_enhance_api_request( - '/servers/' . $server_id + '/orgs/' . $org_id . '/websites/' . $website_id ); - if (isset($response['items']) || isset($response['id'])) { + if (isset($response['id'])) { wp_send_json_success( [ 'message' => __('Connection successful', 'ultimate-multisite'), From 9445358fd7dc2e94a9c5f0fd63f6f46302e7f571 Mon Sep 17 00:00:00 2001 From: David Stone Date: Fri, 9 Jan 2026 19:24:26 -0700 Subject: [PATCH 3/3] Add descriptions --- .../class-enhance-host-provider.php | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/inc/integrations/host-providers/class-enhance-host-provider.php b/inc/integrations/host-providers/class-enhance-host-provider.php index 95aae8e1..e8fb7ed2 100644 --- a/inc/integrations/host-providers/class-enhance-host-provider.php +++ b/inc/integrations/host-providers/class-enhance-host-provider.php @@ -103,19 +103,33 @@ public function get_fields() { 'type' => 'password', 'html_attr' => ['autocomplete' => 'new-password'], 'title' => __('Enhance API Token', 'ultimate-multisite'), + 'desc' => sprintf( + /* translators: %s is the link to the API token documentation */ + __('Generate an API token in your Enhance Control Panel under Settings → API Tokens. Learn more', 'ultimate-multisite'), + 'https://apidocs.enhance.com/#section/Authentication' + ), 'placeholder' => __('Your bearer token', 'ultimate-multisite'), ], 'WU_ENHANCE_API_URL' => [ 'title' => __('Enhance API URL', 'ultimate-multisite'), - 'placeholder' => __('e.g. https://your-enhance-server.com', 'ultimate-multisite'), + 'desc' => __('The API URL of your Enhance Control Panel (e.g., https://your-enhance-server.com/api).', 'ultimate-multisite'), + 'placeholder' => __('e.g. https://your-enhance-server.com/api', 'ultimate-multisite'), + 'html_attr' => [ + 'id' => 'wu_enhance_api_url', + ], ], 'WU_ENHANCE_ORG_ID' => [ 'title' => __('Organization ID', 'ultimate-multisite'), - 'placeholder' => __('UUID of your organization', 'ultimate-multisite'), + 'desc' => __('The UUID of your organization. You can find this in your Enhance Control Panel URL when viewing the organization (e.g., /org/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).', 'ultimate-multisite'), + 'placeholder' => __('e.g. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 'ultimate-multisite'), + 'html_attr' => [ + 'id' => 'wu_enhance_org_id', + ], ], 'WU_ENHANCE_WEBSITE_ID' => [ 'title' => __('Website ID', 'ultimate-multisite'), - 'placeholder' => __('UUID of your website', 'ultimate-multisite'), + 'placeholder' => __('e.g. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 'ultimate-multisite'), + 'desc' => __('The UUID of the website where domains should be added. You can find this in your Enhance Control Panel URL when viewing a website (e.g., /websites/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).', 'ultimate-multisite'), ], ]; }