From 79743dacc25668432aa18836b505dfde87536825 Mon Sep 17 00:00:00 2001 From: David Stone Date: Sun, 31 Aug 2025 16:38:00 -0600 Subject: [PATCH 1/6] ensure new roles are not lost --- inc/limits/class-customer-user-role-limits.php | 6 +++++- inc/models/class-site.php | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/inc/limits/class-customer-user-role-limits.php b/inc/limits/class-customer-user-role-limits.php index b0621c796..6ac4c9f25 100644 --- a/inc/limits/class-customer-user-role-limits.php +++ b/inc/limits/class-customer-user-role-limits.php @@ -135,7 +135,11 @@ public function update_site_user_roles($membership_id): void { $role = $membership->get_limitations()->customer_user_role->get_limit(); foreach ($sites as $site) { - add_user_to_blog($site->get_id(), $customer->get_user_id(), $role); + // only add user to blog if they are not already a member, or we are downgrading their role. + // Without this check the user could lose additional roles added manually or with hooks. + if ('administrator' !== $role || ! is_user_member_of_blog($customer->get_user_id(), $site->get_id())) { + add_user_to_blog($site->get_id(), $customer->get_user_id(), $role); + } } } } diff --git a/inc/models/class-site.php b/inc/models/class-site.php index cfae4f8f1..07cdf41c8 100644 --- a/inc/models/class-site.php +++ b/inc/models/class-site.php @@ -1679,7 +1679,11 @@ public function save() { $user_id = $customer->get_user_id(); - add_user_to_blog($this->get_id(), $user_id, $role); + // only add user to blog if they are not already a member, or we are downgrading their role. + // Without this check the user could lose additional roles added manually or with hooks. + if ('administrator' !== $role || ! is_user_member_of_blog($user_id, $this->get_id())) { + add_user_to_blog($this->get_id(), $user_id, $role); + } } elseif ($this->get_type() !== Site_Type::CUSTOMER_OWNED && $original_customer_id) { $user_id = wu_get_customer($original_customer_id)->get_user_id(); From 416dc27719bbf868276a24243cd31d0fed83ade0 Mon Sep 17 00:00:00 2001 From: David Stone Date: Sun, 31 Aug 2025 16:39:25 -0600 Subject: [PATCH 2/6] lazy load limitations and keep data merged correctly --- inc/objects/class-limitations.php | 41 ++++++-------------- tests/WP_Ultimo/Objects/Limitations_Test.php | 10 ++--- 2 files changed, 16 insertions(+), 35 deletions(-) diff --git a/inc/objects/class-limitations.php b/inc/objects/class-limitations.php index b9cb33138..7bcf4bbd1 100644 --- a/inc/objects/class-limitations.php +++ b/inc/objects/class-limitations.php @@ -67,7 +67,7 @@ class Limitations { */ public function __construct($modules_data = []) { - $this->build_modules($modules_data); + $this->raw_module_data = $modules_data; } /** @@ -83,16 +83,10 @@ public function __get($name) { $module = wu_get_isset($this->modules, $name, false); if (false === $module) { - $repo = self::repository(); - - $class_name = wu_get_isset($repo, $name, false); - - if (class_exists($class_name)) { - $module = new $class_name($this->raw_module_data[ $name ] ?? []); - + $module = self::build($this->raw_module_data[ $name ] ?? [], $name); + if ($module) { $this->modules[ $name ] = $module; - - return $module; + return $this->modules[ $name ]; } } @@ -121,7 +115,7 @@ public function __serialize() { * @return void */ public function __unserialize($modules_data) { - $this->build_modules($modules_data); + $this->raw_module_data = $modules_data; } /** @@ -136,14 +130,6 @@ public function build_modules($modules_data) { $this->raw_module_data = $modules_data; - foreach ($modules_data as $type => $data) { - $module = self::build($data, $type); - - if ($module) { - $this->modules[ $type ] = $module; - } - } - return $this; } @@ -181,7 +167,7 @@ public static function build($data, $module_name) { */ public function exists($module) { - return wu_get_isset($this->modules, $module, false); + return (bool) wu_get_isset($this->raw_module_data, $module, false); } /** @@ -192,15 +178,13 @@ public function exists($module) { */ public function has_limitations() { - $has_limitations = false; - - foreach ($this->modules as $module) { - if ($module->is_enabled()) { + foreach ($this->raw_module_data as $module) { + if ($module['enabled']) { return true; } } - return $has_limitations; + return false; } /** @@ -213,9 +197,7 @@ public function has_limitations() { */ public function is_module_enabled($module_name) { - $module = $this->{$module_name}; - - return $module ? $module->is_enabled() : false; + return $this->raw_module_data[ $module_name ]['enabled'] ?? false; } /** @@ -374,8 +356,7 @@ protected function merge_recursive(array &$array1, array &$array2, $should_sum = * @since 2.0.0 */ public function to_array(): array { - - return array_map(fn($module) => method_exists($module, 'to_array') ? $module->to_array() : (array) $module, $this->modules); + return $this->raw_module_data; } /** diff --git a/tests/WP_Ultimo/Objects/Limitations_Test.php b/tests/WP_Ultimo/Objects/Limitations_Test.php index a35f796f4..aee1815eb 100644 --- a/tests/WP_Ultimo/Objects/Limitations_Test.php +++ b/tests/WP_Ultimo/Objects/Limitations_Test.php @@ -78,7 +78,7 @@ public function test_constructor(array $modules_data, int $expected_modules_coun // Use reflection to access protected modules property $reflection = new \ReflectionClass($limitations); - $modules_property = $reflection->getProperty('modules'); + $modules_property = $reflection->getProperty('raw_module_data'); $modules_property->setAccessible(true); $modules = $modules_property->getValue($limitations); @@ -199,11 +199,11 @@ public function test_build_modules(array $modules_data, int $expected_count): vo // Use reflection to access protected modules property $reflection = new \ReflectionClass($limitations); - $modules_property = $reflection->getProperty('modules'); + $modules_property = $reflection->getProperty('raw_module_data'); $modules_property->setAccessible(true); $modules = $modules_property->getValue($limitations); - $this->assertCount($expected_count, $modules); + $this->assertEquals($modules_data, $modules); } /** @@ -284,11 +284,11 @@ public function existsMethodDataProvider(): array { */ public function test_exists_method(array $modules_data, string $module_name, bool $should_exist): void { $limitations = new Limitations($modules_data); - $result = $limitations->exists($module_name); + $result = $limitations->exists($module_name); if ($should_exist) { $this->assertNotFalse($result); - $this->assertIsObject($result); + $this->assertTrue($result); } else { $this->assertFalse($result); } From 8abce99a5edee7f1389d8074aa06a9fb2fbf329e Mon Sep 17 00:00:00 2001 From: David Stone Date: Sun, 31 Aug 2025 16:42:31 -0600 Subject: [PATCH 3/6] allow some html in notices --- views/admin-notices.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/views/admin-notices.php b/views/admin-notices.php index fc6b48cbd..c1570bbcb 100644 --- a/views/admin-notices.php +++ b/views/admin-notices.php @@ -18,7 +18,7 @@ -

+

From 1624b2ec0e9775f08258bbd464cc402e88fcbd7f Mon Sep 17 00:00:00 2001 From: David Stone Date: Mon, 1 Sep 2025 11:27:10 -0600 Subject: [PATCH 4/6] Add method to verify dns when reverse proxy is used --- README.md | 2 +- inc/managers/class-domain-manager.php | 150 ++++++++++++++++++++++++++ inc/models/class-domain.php | 12 +++ views/domain/dns-table.php | 5 + 4 files changed, 168 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ba72ed61f..da275ddf4 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@

Unit & Integration Tests E2E Tests - E2E Tests + Code Rabbit

## 🌟 Overview diff --git a/inc/managers/class-domain-manager.php b/inc/managers/class-domain-manager.php index 9f00b1892..d3f95668d 100644 --- a/inc/managers/class-domain-manager.php +++ b/inc/managers/class-domain-manager.php @@ -904,4 +904,154 @@ public function load_integrations(): void { */ do_action('wp_ultimo_host_providers_load'); } + + /** + * Register the domain verification endpoint. + * + * @since 2.0.0 + * @return void + */ + public function register_domain_verification_endpoint(): void { + + register_rest_route( + 'wu/v1', + '/domain-verification/(?P[a-zA-Z0-9.-]+)', + array( + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array($this, 'domain_verification_endpoint'), + 'permission_callback' => '__return_true', + 'args' => array( + 'domain' => array( + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field', + ), + ), + ) + ); + } + + /** + * Domain verification endpoint that returns a shared secret. + * + * @since 2.0.0 + * + * @param \WP_REST_Request $request The request object. + * @return \WP_REST_Response|\WP_Error + */ + public function domain_verification_endpoint($request) { + + $domain = $request->get_param('domain'); + + if ( empty($domain) ) { + return new \WP_Error('missing_domain', __('Domain parameter is required.', 'multisite-ultimate'), array('status' => 400)); + } + + $secret = $this->get_domain_verification_secret($domain); + + return rest_ensure_response( + array( + 'domain' => $domain, + 'secret' => $secret, + ) + ); + } + + /** + * Generate and store a verification secret for a domain. + * + * @since 2.0.0 + * + * @param string $domain The domain to generate a secret for. + * @return string The generated secret. + */ + private function generate_domain_verification_secret($domain) { + + $secret = wp_generate_password(32, false); + + set_site_transient("wu_domain_verification_{$domain}", $secret, 5 * MINUTE_IN_SECONDS); + + return $secret; + } + + /** + * Get the verification secret for a domain. + * + * @since 2.0.0 + * + * @param string $domain The domain to get the secret for. + * @return string The verification secret. + */ + private function get_domain_verification_secret($domain) { + + $secret = get_site_transient("wu_domain_verification_{$domain}"); + + if ( false === $secret ) { + $secret = $this->generate_domain_verification_secret($domain); + } + + return $secret; + } + + /** + * Verify domain ownership using the secret-based method. + * + * @since 2.0.0 + * + * @param string $domain The domain to verify. + * @return bool True if verification succeeds, false otherwise. + */ + public function verify_domain_with_secret($domain) { + + $expected_secret = $this->generate_domain_verification_secret($domain); + + $verification_url = "https://{$domain}/wp-json/wu/v1/domain-verification/{$domain}"; + + $response = wp_remote_get( + $verification_url, + array( + 'timeout' => 10, + 'sslverify' => false, + ) + ); + + if ( is_wp_error($response) ) { + wu_log_add( + "domain-verification-{$domain}", + // translators: %s url of the endpoint. + sprintf(__('Failed to connect to verification endpoint: %s', 'multisite-ultimate'), $response->get_error_message()), + LogLevel::WARNING + ); + return false; + } + + $body = wp_remote_retrieve_body($response); + $data = json_decode($body, true); + + if ( ! isset($data['secret']) ) { + wu_log_add( + "domain-verification-{$domain}", + __('Verification endpoint did not return a secret.', 'multisite-ultimate'), + LogLevel::WARNING + ); + return false; + } + + $received_secret = $data['secret']; + + if ( hash_equals($expected_secret, $received_secret) ) { + wu_log_add( + "domain-verification-{$domain}", + __('Domain verification successful using secret method.', 'multisite-ultimate') + ); + return true; + } + + wu_log_add( + "domain-verification-{$domain}", + __('Domain verification failed: secrets do not match.', 'multisite-ultimate'), + LogLevel::WARNING + ); + + return false; + } } diff --git a/inc/models/class-domain.php b/inc/models/class-domain.php index c6bdb0c14..78b5f6882 100644 --- a/inc/models/class-domain.php +++ b/inc/models/class-domain.php @@ -397,6 +397,18 @@ public function has_correct_dns() { $domain_url = $this->get_domain(); + $domain_manager = \WP_Ultimo\Managers\Domain_Manager::get_instance(); + + $secret_verification_enabled = apply_filters('wu_enable_secret_domain_verification', true, $this); + + if ( $secret_verification_enabled ) { + $secret_result = $domain_manager->verify_domain_with_secret($domain_url); + + if ( $secret_result ) { + return true; + } + } + $network_ip_address = Helper::get_network_public_ip(); $results = \WP_Ultimo\Managers\Domain_Manager::dns_get_record($domain_url); diff --git a/views/domain/dns-table.php b/views/domain/dns-table.php index 5d424cda3..4f3ad4a3d 100644 --- a/views/domain/dns-table.php +++ b/views/domain/dns-table.php @@ -75,6 +75,11 @@ {{ results.network_ip }} + + + {{ results.has_correct_dns }} + + From 0ece38c131e57018a2ac1d2efea123a0d1cd5d67 Mon Sep 17 00:00:00 2001 From: David Stone Date: Tue, 2 Sep 2025 22:42:49 -0600 Subject: [PATCH 5/6] esc the html in the logs --- assets/js/domain-logs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/js/domain-logs.js b/assets/js/domain-logs.js index 2de45d517..a853a4003 100644 --- a/assets/js/domain-logs.js +++ b/assets/js/domain-logs.js @@ -12,7 +12,7 @@ return_ascii: 'no', }, success(response) { - $('#content').html(response.data.contents); + $('#content').text(response.data.contents); if (typeof callback !== 'undefined') { callback(); From 287f62092da8131d1be99996b418a3613823679a Mon Sep 17 00:00:00 2001 From: David Stone Date: Tue, 2 Sep 2025 22:50:01 -0600 Subject: [PATCH 6/6] Use loopback request instead of api because domain mapping will not work for api when the domain is not yet active. --- inc/class-domain-mapping.php | 20 +++ inc/managers/class-domain-manager.php | 235 +++++++++++++------------- inc/models/class-domain.php | 14 +- views/domain/dns-table.php | 5 - 4 files changed, 138 insertions(+), 136 deletions(-) diff --git a/inc/class-domain-mapping.php b/inc/class-domain-mapping.php index 84a70efde..f00dac6c5 100644 --- a/inc/class-domain-mapping.php +++ b/inc/class-domain-mapping.php @@ -122,6 +122,8 @@ public function startup(): void { */ add_filter('pre_get_site_by_path', [$this, 'check_domain_mapping'], 10, 2); + add_action('ms_site_not_found', [$this, 'verify_dns_mapping'], 5, 3); + /* * When a site gets delete, clean up the mapped domains */ @@ -240,6 +242,24 @@ public function get_www_and_nowww_versions($domain) { return [$nowww, $www]; } + public function verify_dns_mapping($current_site, $domain, $path) { + + // Nonce functions are unavailable and the wp_hash is basically the same. + if (isset($_REQUEST['async_check_dns_nonce'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended + // This is very early in the request we need these to use wp_hash. + require_once ABSPATH . WPINC . '/l10n.php'; + require_once ABSPATH . WPINC . '/pluggable.php'; + if (hash_equals(wp_hash($domain), $_REQUEST['async_check_dns_nonce'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash + $domains = $this->get_www_and_nowww_versions($domain); + + $mapping = Domain::get_by_domain($domains); + if ($mapping) { + wp_send_json($mapping->to_array()); + } + } + } + } + /** * Checks if we have a site associated with the domain being accessed * diff --git a/inc/managers/class-domain-manager.php b/inc/managers/class-domain-manager.php index d3f95668d..bedf40d6f 100644 --- a/inc/managers/class-domain-manager.php +++ b/inc/managers/class-domain-manager.php @@ -14,6 +14,7 @@ use Psr\Log\LogLevel; use WP_Ultimo\Domain_Mapping\Helper; +use WP_Ultimo\Models\Domain; // Exit if accessed directly defined('ABSPATH') || exit; @@ -906,150 +907,142 @@ public function load_integrations(): void { } /** - * Register the domain verification endpoint. + * Verify domain ownership using a loopback request. * - * @since 2.0.0 - * @return void - */ - public function register_domain_verification_endpoint(): void { - - register_rest_route( - 'wu/v1', - '/domain-verification/(?P[a-zA-Z0-9.-]+)', - array( - 'methods' => \WP_REST_Server::READABLE, - 'callback' => array($this, 'domain_verification_endpoint'), - 'permission_callback' => '__return_true', - 'args' => array( - 'domain' => array( - 'required' => true, - 'sanitize_callback' => 'sanitize_text_field', - ), - ), - ) - ); - } - - /** - * Domain verification endpoint that returns a shared secret. - * - * @since 2.0.0 - * - * @param \WP_REST_Request $request The request object. - * @return \WP_REST_Response|\WP_Error - */ - public function domain_verification_endpoint($request) { - - $domain = $request->get_param('domain'); - - if ( empty($domain) ) { - return new \WP_Error('missing_domain', __('Domain parameter is required.', 'multisite-ultimate'), array('status' => 400)); - } - - $secret = $this->get_domain_verification_secret($domain); - - return rest_ensure_response( - array( - 'domain' => $domain, - 'secret' => $secret, - ) - ); - } - - /** - * Generate and store a verification secret for a domain. + * This method attempts to verify a domain by making an loopback request with a + * a specific parameter that is used by Domain_Mapper::verify_dns_mapping(). * - * @since 2.0.0 + * @since 2.4.4 * - * @param string $domain The domain to generate a secret for. - * @return string The generated secret. + * @param Domain $domain The domain object to verify. + * @return bool True if verification succeeds, false otherwise. */ - private function generate_domain_verification_secret($domain) { - - $secret = wp_generate_password(32, false); + public function verify_domain_with_loopback_request(Domain $domain): bool { - set_site_transient("wu_domain_verification_{$domain}", $secret, 5 * MINUTE_IN_SECONDS); + $domain_url = $domain->get_domain(); + $domain_id = $domain->get_id(); - return $secret; - } + $endpoint_path = '/'; - /** - * Get the verification secret for a domain. - * - * @since 2.0.0 - * - * @param string $domain The domain to get the secret for. - * @return string The verification secret. - */ - private function get_domain_verification_secret($domain) { + // Test protocols in order of preference: HTTPS with SSL verify, HTTPS without SSL verify, HTTP + $protocols_to_test = [ + [ + 'url' => "https://{$domain_url}{$endpoint_path}", + /** This filter is documented in wp-includes/class-wp-http-streams.php */ + 'sslverify' => apply_filters('https_local_ssl_verify', false), + 'label' => 'HTTPS with SSL verification', + ], + [ + 'url' => "http://{$domain_url}{$endpoint_path}", + 'label' => 'HTTP', + ], + ]; - $secret = get_site_transient("wu_domain_verification_{$domain}"); + foreach ($protocols_to_test as $protocol_config) { + wu_log_add( + "domain-{$domain_url}", + sprintf( + /* translators: %1$s: Protocol label (HTTPS with SSL verification, HTTPS without SSL verification, HTTP), %2$s: URL being tested */ + __('Testing domain verification via Loopback using %1$s: %2$s', 'multisite-ultimate'), + $protocol_config['label'], + $protocol_config['url'] + ) + ); - if ( false === $secret ) { - $secret = $this->generate_domain_verification_secret($domain); - } + // Make API request with basic auth + $response = wp_remote_get( + $protocol_config['url'], + [ + 'timeout' => 10, + 'redirection' => 0, + 'sslverify' => $protocol_config['sslverify'], + 'body' => ['async_check_dns_nonce' => wp_hash($domain_url)], + ] + ); - return $secret; - } + // Check for connection errors + if (is_wp_error($response)) { + wu_log_add( + "domain-{$domain_url}", + sprintf( + /* translators: %1$s: Protocol label (HTTPS with SSL verification, HTTPS without SSL verification, HTTP), %2$s: Error Message */ + __('Failed to connect via %1$s: %2$s', 'multisite-ultimate'), + $protocol_config['label'], + $response->get_error_message() + ), + LogLevel::WARNING + ); + continue; + } - /** - * Verify domain ownership using the secret-based method. - * - * @since 2.0.0 - * - * @param string $domain The domain to verify. - * @return bool True if verification succeeds, false otherwise. - */ - public function verify_domain_with_secret($domain) { + $response_code = wp_remote_retrieve_response_code($response); + $body = wp_remote_retrieve_body($response); - $expected_secret = $this->generate_domain_verification_secret($domain); + // Check HTTP status + if (200 !== $response_code) { + wu_log_add( + "domain-{$domain_url}", + sprintf( + /* translators: %1$s: Protocol label (HTTPS with SSL verification, HTTPS without SSL verification, HTTP), %2$s: HTTP Response Code */ + __('Loopback request via %1$s returned HTTP %2$d', 'multisite-ultimate'), + $protocol_config['label'], + $response_code + ), + LogLevel::WARNING + ); + continue; + } - $verification_url = "https://{$domain}/wp-json/wu/v1/domain-verification/{$domain}"; + // Try to decode JSON response + $data = json_decode($body, true); - $response = wp_remote_get( - $verification_url, - array( - 'timeout' => 10, - 'sslverify' => false, - ) - ); + if (json_last_error() !== JSON_ERROR_NONE) { + wu_log_add( + "domain-{$domain_url}", + sprintf( + /* translators: %1$s: Protocol label (HTTPS with SSL verification, HTTPS without SSL verification, HTTP), %2$s: Json error, %3$s part of the response */ + __('Loopback response via %1$s is not valid JSON: %2$s : %3$s', 'multisite-ultimate'), + $protocol_config['label'], + json_last_error_msg(), + substr($body, 0, 100) + ), + LogLevel::WARNING + ); + continue; + } - if ( is_wp_error($response) ) { - wu_log_add( - "domain-verification-{$domain}", - // translators: %s url of the endpoint. - sprintf(__('Failed to connect to verification endpoint: %s', 'multisite-ultimate'), $response->get_error_message()), - LogLevel::WARNING - ); - return false; - } + // Check if we got a valid domain object back + if (isset($data['id']) && (int) $data['id'] === $domain_id) { + wu_log_add( + "domain-{$domain_url}", + sprintf( + /* translators: %1$s: Protocol label (HTTPS with SSL verification, HTTPS without SSL verification, HTTP), %2$s: Domain ID number */ + __('Domain verification successful via Loopback using %1$s. Domain ID %2$d confirmed.', 'multisite-ultimate'), + $protocol_config['label'], + $domain_id + ) + ); - $body = wp_remote_retrieve_body($response); - $data = json_decode($body, true); + return true; + } - if ( ! isset($data['secret']) ) { wu_log_add( - "domain-verification-{$domain}", - __('Verification endpoint did not return a secret.', 'multisite-ultimate'), + "domain-{$domain_url}", + sprintf( + /* translators: %1$s: Protocol label (HTTPS with SSL verification, HTTPS without SSL verification, HTTP), %2$s: Domain ID number, %3$s Domain ID number */ + __('Loopback response via %1$s did not contain expected domain ID. Expected: %2$d, Got: %3$s', 'multisite-ultimate'), + $protocol_config['label'], + $domain_id, + isset($data['id']) ? $data['id'] : 'null' + ), LogLevel::WARNING ); - return false; - } - - $received_secret = $data['secret']; - - if ( hash_equals($expected_secret, $received_secret) ) { - wu_log_add( - "domain-verification-{$domain}", - __('Domain verification successful using secret method.', 'multisite-ultimate') - ); - return true; } wu_log_add( - "domain-verification-{$domain}", - __('Domain verification failed: secrets do not match.', 'multisite-ultimate'), - LogLevel::WARNING + "domain-{$domain_url}", + __('Domain verification failed via loopback on all protocols (HTTPS with SSL, HTTPS without SSL, HTTP).', 'multisite-ultimate'), + LogLevel::ERROR ); return false; diff --git a/inc/models/class-domain.php b/inc/models/class-domain.php index 78b5f6882..b5dfaff71 100644 --- a/inc/models/class-domain.php +++ b/inc/models/class-domain.php @@ -399,14 +399,8 @@ public function has_correct_dns() { $domain_manager = \WP_Ultimo\Managers\Domain_Manager::get_instance(); - $secret_verification_enabled = apply_filters('wu_enable_secret_domain_verification', true, $this); - - if ( $secret_verification_enabled ) { - $secret_result = $domain_manager->verify_domain_with_secret($domain_url); - - if ( $secret_result ) { - return true; - } + if ($domain_manager->verify_domain_with_loopback_request($this)) { + return true; } $network_ip_address = Helper::get_network_public_ip(); @@ -612,7 +606,7 @@ public static function get_by_site($site) { * @since 2.0.0 * * @param array|string $domains Domain names to search for. - * @return object + * @return static */ public static function get_by_domain($domains) { @@ -645,7 +639,7 @@ public static function get_by_domain($domains) { $placeholders_in = implode(',', $placeholders); // Prepare the query - $query = "SELECT * FROM {$wpdb->wu_dmtable} WHERE domain IN ($placeholders_in) AND active = 1 ORDER BY primary_domain DESC, active DESC, secure DESC LIMIT 1"; + $query = "SELECT * FROM {$wpdb->wu_dmtable} WHERE domain IN ($placeholders_in) ORDER BY primary_domain DESC, active DESC, secure DESC LIMIT 1"; $query = $wpdb->prepare($query, $domains); // phpcs:ignore diff --git a/views/domain/dns-table.php b/views/domain/dns-table.php index 4f3ad4a3d..5d424cda3 100644 --- a/views/domain/dns-table.php +++ b/views/domain/dns-table.php @@ -75,11 +75,6 @@ {{ results.network_ip }} - - - {{ results.has_correct_dns }} - -