From 5ce7598dd1d88610014eac7767cd322762b90fec Mon Sep 17 00:00:00 2001 From: David Stone Date: Fri, 9 Jan 2026 01:14:43 -0700 Subject: [PATCH 1/2] Create new stage failed ssl to prevent domain without valid ssl certs from being active --- inc/apis/schemas/domain-create.php | 13 ++++--- inc/apis/schemas/domain-update.php | 13 ++++--- inc/class-faker.php | 8 ++-- inc/database/domains/class-domain-stage.php | 4 ++ inc/database/domains/class-domains-schema.php | 2 +- inc/database/domains/class-domains-table.php | 39 ++++++++++++++----- .../class-wpmudev-host-provider.php | 3 +- inc/managers/class-domain-manager.php | 16 ++++---- inc/models/class-domain.php | 11 +++--- 9 files changed, 72 insertions(+), 37 deletions(-) diff --git a/inc/apis/schemas/domain-create.php b/inc/apis/schemas/domain-create.php index 16762ae9f..4a55fa560 100644 --- a/inc/apis/schemas/domain-create.php +++ b/inc/apis/schemas/domain-create.php @@ -9,6 +9,8 @@ // Exit if accessed directly defined('ABSPATH') || exit; +use WP_Ultimo\Database\Domains\Domain_Stage; + /** * Schema for domain@create. * @@ -49,11 +51,12 @@ 'type' => 'string', 'required' => true, 'enum' => [ - 'checking-dns', - 'checking-ssl-cert', - 'done-without-ssl', - 'done', - 'failed', + Domain_Stage::CHECKING_DNS, + Domain_Stage::CHECKING_SSL, + Domain_Stage::DONE_WITHOUT_SSL, + Domain_Stage::DONE, + Domain_Stage::FAILED, + Domain_Stage::SSL_FAILED, ], ], 'date_created' => [ diff --git a/inc/apis/schemas/domain-update.php b/inc/apis/schemas/domain-update.php index 46e663a1a..1a5b9affe 100644 --- a/inc/apis/schemas/domain-update.php +++ b/inc/apis/schemas/domain-update.php @@ -9,6 +9,8 @@ // Exit if accessed directly defined('ABSPATH') || exit; +use WP_Ultimo\Database\Domains\Domain_Stage; + /** * Schema for domain@update. * @@ -49,11 +51,12 @@ 'type' => 'string', 'required' => false, 'enum' => [ - 'checking-dns', - 'checking-ssl-cert', - 'done-without-ssl', - 'done', - 'failed', + Domain_Stage::CHECKING_DNS, + Domain_Stage::CHECKING_SSL, + Domain_Stage::DONE_WITHOUT_SSL, + Domain_Stage::DONE, + Domain_Stage::FAILED, + Domain_Stage::SSL_FAILED, ], ], 'date_created' => [ diff --git a/inc/class-faker.php b/inc/class-faker.php index 65df3522e..0036a8b71 100644 --- a/inc/class-faker.php +++ b/inc/class-faker.php @@ -11,6 +11,7 @@ use Exception; use Faker as Lib_Faker; +use WP_Ultimo\Database\Domains\Domain_Stage; use WP_Ultimo\Models\Membership; use WP_Ultimo\Models\Product; @@ -184,6 +185,7 @@ private function get_random_data($model) { return false; } } + return false; } /** @@ -481,9 +483,9 @@ public function generate_fake_domain($number = 1): void { $faker = $this->get_faker(); $stage_options = [ - 'checking-dns', - 'checking-ssl-cert', - 'done', + Domain_Stage::CHECKING_DNS, + Domain_Stage::CHECKING_SSL, + Domain_Stage::DONE, ]; $stage_checking_dns = $stage_options[0]; diff --git a/inc/database/domains/class-domain-stage.php b/inc/database/domains/class-domain-stage.php index 88bf60ae4..558e2543f 100644 --- a/inc/database/domains/class-domain-stage.php +++ b/inc/database/domains/class-domain-stage.php @@ -28,6 +28,8 @@ class Domain_Stage extends Enum { const FAILED = 'failed'; + const SSL_FAILED = 'ssl-failed'; + const CHECKING_DNS = 'checking-dns'; const CHECKING_SSL = 'checking-ssl-cert'; @@ -46,6 +48,7 @@ protected function classes() { return [ static::FAILED => 'wu-bg-red-200 wu-text-red-700', + static::SSL_FAILED => 'wu-bg-red-200 wu-text-red-700', static::CHECKING_DNS => 'wu-bg-blue-200 wu-text-blue-700', static::CHECKING_SSL => 'wu-bg-yellow-200 wu-text-yellow-700', static::DONE => 'wu-bg-green-200 wu-text-green-700', @@ -63,6 +66,7 @@ protected function labels() { return [ static::FAILED => __('DNS Failed', 'ultimate-multisite'), + static::SSL_FAILED => __('SSL Failed', 'ultimate-multisite'), static::CHECKING_DNS => __('Checking DNS', 'ultimate-multisite'), static::CHECKING_SSL => __('Checking SSL', 'ultimate-multisite'), static::DONE => __('Ready', 'ultimate-multisite'), diff --git a/inc/database/domains/class-domains-schema.php b/inc/database/domains/class-domains-schema.php index 4d6b19de1..39bdcca3b 100644 --- a/inc/database/domains/class-domains-schema.php +++ b/inc/database/domains/class-domains-schema.php @@ -90,7 +90,7 @@ class Domains_Schema extends Schema { [ 'name' => 'stage', - 'type' => 'enum(\'checking-dns\', \'checking-ssl-cert\', \'done-without-ssl\', \'done\', \'failed\')', + 'type' => 'enum(\'' . Domain_Stage::CHECKING_DNS . '\', \'' . Domain_Stage::CHECKING_SSL . '\', \'' . Domain_Stage::DONE_WITHOUT_SSL . '\', \'' . Domain_Stage::DONE . '\', \'' . Domain_Stage::FAILED . '\', \'' . Domain_Stage::SSL_FAILED . '\')', 'default' => 'checking-dns', 'transition' => true, 'sortable' => true, diff --git a/inc/database/domains/class-domains-table.php b/inc/database/domains/class-domains-table.php index 33ebeb773..9e4b5f526 100644 --- a/inc/database/domains/class-domains-table.php +++ b/inc/database/domains/class-domains-table.php @@ -43,17 +43,18 @@ final class Domains_Table extends Table { * @since 2.0.0 * @var string */ - protected $version = '2.0.1-revision.20230601'; + protected $version = '2.0.1-revision.20260109'; /** - * List of table upgrades. - * - * @var array + * Use real callbacks. */ - protected $upgrades = [ - '2.0.1-revision.20230601' => 20_230_601, - ]; - + public function __construct() { + $this->upgrades = [ + '2.0.1-revision.20230601' => [$this, 'allow_nulls'], + '2.0.1-revision.20260109' => [$this, 'update_enum'], + ]; + parent::__construct(); + } /** * Set up the database schema @@ -70,7 +71,7 @@ protected function set_schema(): void { active tinyint(4) default 1, primary_domain tinyint(4) default 0, secure tinyint(4) default 0, - stage enum('checking-dns', 'checking-ssl-cert', 'done', 'failed', 'done-without-ssl') DEFAULT 'checking-dns', + stage enum('" . Domain_Stage::CHECKING_DNS . "', '" . Domain_Stage::CHECKING_SSL . "', '" . Domain_Stage::DONE_WITHOUT_SSL . "', '" . Domain_Stage::DONE . "', '" . Domain_Stage::FAILED . "', '" . Domain_Stage::SSL_FAILED . "')) DEFAULT '" . Domain_Stage::CHECKING_DNS . "', date_created datetime NULL, date_modified datetime NULL, PRIMARY KEY (id), @@ -83,7 +84,7 @@ protected function set_schema(): void { * * @since 2.1.2 */ - protected function __20230601(): bool { // phpcs:ignore PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.MethodDoubleUnderscore + protected function allow_nulls(): bool { $null_columns = [ 'date_created', @@ -102,4 +103,22 @@ protected function __20230601(): bool { // phpcs:ignore PHPCompatibility.Functio return true; } + + /** + * Adds the ssl-failed stage + * + * @since 2.4.10 + */ + protected function update_enum(): bool { // phpcs:ignore PHPCompatibility.FunctionNameRestrictions.ReservedFunctionNames.MethodDoubleUnderscore + + $query = "ALTER TABLE {$this->table_name} MODIFY COLUMN `stage` enum('" . Domain_Stage::CHECKING_DNS . "', '" . Domain_Stage::CHECKING_SSL . "', '" . Domain_Stage::DONE_WITHOUT_SSL . "', '" . Domain_Stage::DONE . "', '" . Domain_Stage::FAILED . "', '" . Domain_Stage::SSL_FAILED . "') DEFAULT '" . Domain_Stage::CHECKING_DNS . "';"; + + $result = $this->get_db()->query($query); + + if ( ! $this->is_success($result)) { + return false; + } + + return true; + } } diff --git a/inc/integrations/host-providers/class-wpmudev-host-provider.php b/inc/integrations/host-providers/class-wpmudev-host-provider.php index 50fd53d7c..1d4111c56 100644 --- a/inc/integrations/host-providers/class-wpmudev-host-provider.php +++ b/inc/integrations/host-providers/class-wpmudev-host-provider.php @@ -10,6 +10,7 @@ namespace WP_Ultimo\Integrations\Host_Providers; use Psr\Log\LogLevel; +use WP_Ultimo\Database\Domains\Domain_Stage; use WP_Ultimo\Integrations\Host_Providers\Base_Host_Provider; // Exit if accessed directly @@ -99,7 +100,7 @@ public function ssl_tries($max_tries, $domain) { return $max_tries; } - if ('checking-ssl-cert' === $domain->get_stage()) { + if (Domain_Stage::CHECKING_SSL === $domain->get_stage()) { $max_tries = 10; } diff --git a/inc/managers/class-domain-manager.php b/inc/managers/class-domain-manager.php index 3a1fde8c7..c3aeb54a8 100644 --- a/inc/managers/class-domain-manager.php +++ b/inc/managers/class-domain-manager.php @@ -13,6 +13,7 @@ namespace WP_Ultimo\Managers; use Psr\Log\LogLevel; +use WP_Ultimo\Database\Domains\Domain_Stage; use WP_Ultimo\Domain_Mapping\Helper; use WP_Ultimo\Models\Domain; @@ -664,9 +665,9 @@ public function async_process_domain_stage($domain_id, $tries = 0): void { // translators: %s is the domain name wu_log_add("domain-{$domain_url}", sprintf(__('Starting Check for %s', 'ultimate-multisite'), $domain_url)); - if ('checking-dns' === $stage) { + if (Domain_Stage::CHECKING_DNS === $stage) { if ($domain->has_correct_dns()) { - $domain->set_stage('checking-ssl-cert'); + $domain->set_stage(Domain_Stage::CHECKING_SSL); $domain->save(); @@ -692,7 +693,7 @@ public function async_process_domain_stage($domain_id, $tries = 0): void { * Max attempts */ if ($tries > $max_tries) { - $domain->set_stage('failed'); + $domain->set_stage(Domain_Stage::FAILED); $domain->save(); @@ -723,9 +724,9 @@ public function async_process_domain_stage($domain_id, $tries = 0): void { return; } - } elseif ('checking-ssl-cert' === $stage) { + } elseif (Domain_Stage::CHECKING_SSL === $stage) { if ($domain->has_valid_ssl_certificate()) { - $domain->set_stage('done'); + $domain->set_stage(Domain_Stage::DONE); $domain->set_secure(true); @@ -742,10 +743,11 @@ public function async_process_domain_stage($domain_id, $tries = 0): void { * Max attempts */ if ($tries > $max_tries) { - $domain->set_stage('done-without-ssl'); + // We use SSL FAILED instead of done-without-ssl since ssl is pretty much required + // and we don't want to redirect to a domain with certificate errors. + $domain->set_stage(Domain_Stage::SSL_FAILED); $domain->save(); - wu_log_add( "domain-{$domain_url}", // translators: %d is the number of minutes to try again. diff --git a/inc/models/class-domain.php b/inc/models/class-domain.php index c504e8026..d146f34f9 100644 --- a/inc/models/class-domain.php +++ b/inc/models/class-domain.php @@ -73,7 +73,7 @@ class Domain extends Base_Model { * @since 2.0.0 * @var string */ - protected $stage = 'checking-dns'; + protected $stage = Domain_Stage::CHECKING_DNS; /** * Date when this was created. @@ -90,9 +90,10 @@ class Domain extends Base_Model { * @var array */ const INACTIVE_STAGES = [ - 'checking-dns', - 'checking-ssl-cert', - 'failed', + Domain_Stage::CHECKING_DNS, + Domain_Stage::CHECKING_SSL, + Domain_Stage::FAILED, + Domain_Stage::SSL_FAILED, ]; /** @@ -127,7 +128,7 @@ public function validation_rules() { return [ 'blog_id' => 'required|integer', 'domain' => "required|domain|unique:\WP_Ultimo\Models\Domain,domain,{$id}", - 'stage' => 'required|in:checking-dns,checking-ssl-cert,done-without-ssl,done,failed|default:checking-dns', + 'stage' => 'required|in:checking-dns,checking-ssl-cert,done-without-ssl,done,failed,ssl-failed|default:checking-dns', 'active' => 'default:1', 'secure' => 'default:0', 'primary_domain' => 'default:0', From 682cf8da8049b4edf42195c231ff6c9f829d3698 Mon Sep 17 00:00:00 2001 From: David Stone Date: Fri, 9 Jan 2026 11:18:09 -0700 Subject: [PATCH 2/2] Update inc/database/domains/class-domains-table.php Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- inc/database/domains/class-domains-table.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/database/domains/class-domains-table.php b/inc/database/domains/class-domains-table.php index 9e4b5f526..1f1e2c574 100644 --- a/inc/database/domains/class-domains-table.php +++ b/inc/database/domains/class-domains-table.php @@ -71,7 +71,7 @@ protected function set_schema(): void { active tinyint(4) default 1, primary_domain tinyint(4) default 0, secure tinyint(4) default 0, - stage enum('" . Domain_Stage::CHECKING_DNS . "', '" . Domain_Stage::CHECKING_SSL . "', '" . Domain_Stage::DONE_WITHOUT_SSL . "', '" . Domain_Stage::DONE . "', '" . Domain_Stage::FAILED . "', '" . Domain_Stage::SSL_FAILED . "')) DEFAULT '" . Domain_Stage::CHECKING_DNS . "', + stage enum('" . Domain_Stage::CHECKING_DNS . "', '" . Domain_Stage::CHECKING_SSL . "', '" . Domain_Stage::DONE_WITHOUT_SSL . "', '" . Domain_Stage::DONE . "', '" . Domain_Stage::FAILED . "', '" . Domain_Stage::SSL_FAILED . "') DEFAULT '" . Domain_Stage::CHECKING_DNS . "', date_created datetime NULL, date_modified datetime NULL, PRIMARY KEY (id),