Skip to content

Fix www domain#195

Merged
superdav42 merged 6 commits intomainfrom
fix-www-domain
Sep 5, 2025
Merged

Fix www domain#195
superdav42 merged 6 commits intomainfrom
fix-www-domain

Conversation

@superdav42
Copy link
Copy Markdown
Collaborator

@superdav42 superdav42 commented Sep 5, 2025

add new option to not always create a www subdomain for every new domain

Summary by CodeRabbit

  • New Features

    • Option to control automatic creation of www subdomains (always, main-only, never).
    • Admin notice added when sunrise.php is not configured.
  • Improvements

    • Hosting integrations now honor the www-subdomain setting.
    • Async DNS verification runs earlier during domain mapping.
    • SSL verification in loopback checks now handles missing settings gracefully.
    • Adjusted lazy-load limits for better compatibility.
  • Bug Fixes

    • Fixed DNS verification when using a reverse proxy.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 5, 2025

Walkthrough

Adds a Domain_Manager UI setting and method to control automatic creation of www subdomains across host-provider integrations; updates host-provider integrations to consult that method; adds an early/async DNS verification invocation in the domain-mapping flow; updates changelog. One public method was added.

Changes

Cohort / File(s) Summary
Domain mapping async DNS check
inc/class-domain-mapping.php
Adds PHPDoc for verify_dns_mapping and invokes verify_dns_mapping($site, $domain, '/') at the start of check_domain_mapping to trigger an early/async DNS verification path; verify_dns_mapping behavior otherwise unchanged.
Conditional www handling via Domain_Manager
inc/integrations/host-providers/class-cloudflare-host-provider.php, inc/integrations/host-providers/class-cloudways-host-provider.php, inc/integrations/host-providers/class-runcloud-host-provider.php, inc/integrations/host-providers/class-serverpilot-host-provider.php, inc/integrations/host-providers/class-wpmudev-host-provider.php
Replace unconditional addition of www. domains with checks to \WP_Ultimo\Managers\Domain_Manager::get_instance()->should_create_www_subdomain(...), gating whether www. variants are included in provider payloads/lists. Minor formatting tweak in ServerPilot file.
Domain manager setting and helper
inc/managers/class-domain-manager.php
Adds UI setting auto_create_www_subdomain (always, main_only, never) and new public method should_create_www_subdomain($domain) with multi-part TLD heuristic and wu_multi_part_tlds filter; also guards SSL verify option with null-coalescing.
Documentation
readme.txt
Updates changelog for 2.4.4: DNS verification with reverse proxy, lazy load notes, sunrise.php admin notice, and new option to not always create www. subdomains.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Browser as Browser
  participant WP as WordPress
  participant DM as Domain_Mapping
  participant DNS as DNS_Verifier

  Browser->>WP: Request mapped domain
  WP->>DM: check_domain_mapping(site, domain)
  note right of DM: new early call: verify_dns_mapping(site, domain, "/")
  DM->>DNS: verify_dns_mapping (async path if nonce)
  alt async nonce present
    DNS-->>Browser: wp_send_json(status)
    note over DNS,Browser: Early async response (nonce-protected)
  else
    DM->>DM: continue existing mapping logic
  end
Loading
sequenceDiagram
  autonumber
  actor Admin as Admin/Automation
  participant HP as Host_Provider
  participant DMgr as Domain_Manager
  participant API as Hosting_API

  Admin->>HP: on_add_domain(domain)
  HP->>DMgr: should_create_www_subdomain(domain)
  alt returns true
    HP->>API: add domain + www.domain
  else returns false
    HP->>API: add domain only
  end
  API-->>HP: Success/Failure
  HP-->>Admin: Result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • Reverse proxy fix #191 — Modifies inc/class-domain-mapping.php to add/alter verify_dns_mapping startup/async DNS lookup; closely related to the domain-mapping changes here.

Poem

A rabbit hops through DNS and sites,
Choosing when "www." delights.
Providers listen, payloads adapt,
Early checks ping, responses wrapped.
Hop—config tidy, mapping mapped. 🐇🌐

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-www-domain

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (6)
readme.txt (1)

236-239: Polish changelog phrasing (grammar/clarity)

Minor wording tweaks for consistency and correctness.

- - Improved: Lazy load limitations for better performance and compatibility
- - New: Add Admin Notice if sunrise.php is not setup
- - New: Option to not always create www. subdomains with hosting integrations
+ - Improved: Lazy-load limitations for better performance and compatibility
+ - New: Add admin notice if sunrise.php is not set up
+ - New: Option to not always create www subdomains with hosting integrations
inc/class-domain-mapping.php (2)

245-253: Docblock: note the side effect

This method can send JSON and terminate the request; make that explicit in the doc.

  /**
   * Check if this is a special loopback request.
   *
   * @param null|false|\WP_Site $current_site Current Site.
   * @param string              $domain Current domain.
   * @param string              $path   Current Path.
   *
+  * Side effect: When the nonce is valid and a mapping is found, this sends JSON and terminates.
   * @return void
   */

284-287: Gate the loopback handler to avoid an extra function call on normal requests

Saves a call on every request and makes the intent explicit.

-        $this->verify_dns_mapping($site, $domain, '/');
+        if (isset($_REQUEST['async_check_dns_nonce'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+            $this->verify_dns_mapping($site, $domain, '/');
+        }
inc/managers/class-domain-manager.php (1)

399-418: Setting label tweak

Pluralize for consistency with description.

-                'title'   => __('Create www Subdomain Automatically?', 'multisite-ultimate'),
+                'title'   => __('Create www Subdomains Automatically?', 'multisite-ultimate'),
inc/integrations/host-providers/class-serverpilot-host-provider.php (1)

121-127: Avoid duplicates when merging domains

ServerPilot updates the entire list; send a de-duplicated array to prevent redundant entries.

-            $this->send_server_pilot_api_request(
+            $this->send_server_pilot_api_request(
                 '',
                 [
-                    'domains' => array_merge($current_domain_list, $domains_to_add),
+                    'domains' => array_values(array_unique(array_merge($current_domain_list, $domains_to_add))),
                 ]
             );

Also applies to: 131-132

inc/integrations/host-providers/class-cloudways-host-provider.php (1)

294-296: Don’t mutate the iterated array; collect and merge after the loop

Appending to $domain_list while iterating it is surprising and version-dependent. Gather additions separately, then merge.

-        foreach ($domain_list as $naked_domain) {
-            if (! str_starts_with((string) $naked_domain, 'www.') && ! str_starts_with((string) $naked_domain, '*.') && \WP_Ultimo\Managers\Domain_Manager::get_instance()->should_create_www_subdomain($naked_domain)) {
-                $domain_list[] = 'www.' . $naked_domain;
-            }
-        }
+        $to_append = [];
+        foreach ($domain_list as $naked_domain) {
+            if (
+                ! str_starts_with((string) $naked_domain, 'www.')
+                && ! str_starts_with((string) $naked_domain, '*.')
+                && \WP_Ultimo\Managers\Domain_Manager::get_instance()->should_create_www_subdomain($naked_domain)
+            ) {
+                $to_append[] = 'www.' . $naked_domain;
+            }
+        }
+        if ($to_append) {
+            $domain_list = array_merge($domain_list, $to_append);
+        }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6c0edfb and bf47b10.

⛔ Files ignored due to path filters (1)
  • assets/js/domain-logs.min.js is excluded by !**/*.min.js
📒 Files selected for processing (8)
  • inc/class-domain-mapping.php (2 hunks)
  • inc/integrations/host-providers/class-cloudflare-host-provider.php (1 hunks)
  • inc/integrations/host-providers/class-cloudways-host-provider.php (2 hunks)
  • inc/integrations/host-providers/class-runcloud-host-provider.php (1 hunks)
  • inc/integrations/host-providers/class-serverpilot-host-provider.php (2 hunks)
  • inc/integrations/host-providers/class-wpmudev-host-provider.php (1 hunks)
  • inc/managers/class-domain-manager.php (1 hunks)
  • readme.txt (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
inc/integrations/host-providers/class-runcloud-host-provider.php (1)
inc/managers/class-domain-manager.php (1)
  • should_create_www_subdomain (427-462)
inc/managers/class-domain-manager.php (1)
inc/functions/settings.php (2)
  • wu_register_settings_field (89-92)
  • wu_get_setting (39-42)
inc/integrations/host-providers/class-serverpilot-host-provider.php (2)
inc/managers/class-domain-manager.php (1)
  • should_create_www_subdomain (427-462)
inc/traits/trait-singleton.php (1)
  • get_instance (31-40)
inc/integrations/host-providers/class-cloudflare-host-provider.php (1)
inc/managers/class-domain-manager.php (1)
  • should_create_www_subdomain (427-462)
inc/integrations/host-providers/class-wpmudev-host-provider.php (1)
inc/managers/class-domain-manager.php (1)
  • should_create_www_subdomain (427-462)
inc/integrations/host-providers/class-cloudways-host-provider.php (2)
inc/managers/class-domain-manager.php (1)
  • should_create_www_subdomain (427-462)
inc/traits/trait-singleton.php (1)
  • get_instance (31-40)
🪛 LanguageTool
readme.txt

[grammar] ~236-~236: There might be a mistake here.
Context: ... DNS settings when using a reverse proxy - Improved: Lazy load limitations for bett...

(QB_NEW_EN)


[grammar] ~237-~237: There might be a mistake here.
Context: ...for better performance and compatibility - New: Add Admin Notice if sunrise.php is ...

(QB_NEW_EN)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: PHP 7.4
  • GitHub Check: PHP 8.1
  • GitHub Check: PHP 8.2
  • GitHub Check: PHP 8.3
  • GitHub Check: cypress (8.0, firefox)
  • GitHub Check: cypress (8.1, firefox)
  • GitHub Check: cypress (8.2, chrome)
  • GitHub Check: cypress (8.4, chrome)
  • GitHub Check: cypress (8.3, firefox)
  • GitHub Check: cypress (8.2, firefox)
  • GitHub Check: cypress (8.4, firefox)
  • GitHub Check: cypress (8.3, chrome)
  • GitHub Check: cypress (8.0, chrome)
  • GitHub Check: cypress (8.1, chrome)
  • GitHub Check: cypress (7.4, chrome)
  • GitHub Check: cypress (7.4, firefox)
🔇 Additional comments (2)
inc/integrations/host-providers/class-wpmudev-host-provider.php (1)

138-140: Conditional www subdomain addition — LGTM

Matches the new Domain_Manager gating and preserves existing behavior otherwise.

inc/integrations/host-providers/class-cloudways-host-provider.php (1)

381-383: Mirrored gating for mapped domains — LGTM

Consistent with get_domains() and the new setting.

superdav42 and others added 2 commits September 4, 2025 21:08
….php

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
inc/integrations/host-providers/class-cloudflare-host-provider.php (1)

255-262: Expose $full_domain to the filter for better context (BC-safe).

Provide the FQDN as an extra arg so callbacks can make informed overrides without recomputing it. This does not break existing hooks (WordPress will pass only what callbacks accept).

Apply:

-        $should_add_www = apply_filters(
-            'wu_cloudflare_should_add_www',
-            \WP_Ultimo\Managers\Domain_Manager::get_instance()->should_create_www_subdomain($full_domain),
-            $subdomain,
-            $site_id
-        );
+        $should_add_www = apply_filters(
+            'wu_cloudflare_should_add_www',
+            \WP_Ultimo\Managers\Domain_Manager::get_instance()->should_create_www_subdomain($full_domain),
+            $subdomain,
+            $site_id,
+            $full_domain
+        );
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bf47b10 and d5010cc.

📒 Files selected for processing (1)
  • inc/integrations/host-providers/class-cloudflare-host-provider.php (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
inc/integrations/host-providers/class-cloudflare-host-provider.php (1)
inc/managers/class-domain-manager.php (1)
  • should_create_www_subdomain (427-462)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: PHP 8.3
  • GitHub Check: PHP 8.2
  • GitHub Check: PHP 7.4
  • GitHub Check: PHP 8.4
  • GitHub Check: PHP 8.1
  • GitHub Check: PHP 8.0
  • GitHub Check: cypress (8.4, firefox)
  • GitHub Check: cypress (8.3, chrome)
  • GitHub Check: cypress (8.0, chrome)
  • GitHub Check: cypress (7.4, firefox)
  • GitHub Check: cypress (8.2, firefox)
  • GitHub Check: cypress (8.3, firefox)
  • GitHub Check: cypress (8.0, firefox)
  • GitHub Check: cypress (8.4, chrome)
  • GitHub Check: cypress (8.1, firefox)
  • GitHub Check: cypress (7.4, chrome)
  • GitHub Check: cypress (8.1, chrome)
  • GitHub Check: cypress (8.2, chrome)
🔇 Additional comments (1)
inc/integrations/host-providers/class-cloudflare-host-provider.php (1)

255-262: Good fix: using FQDN for the decision source.

Passing $full_domain to Domain_Manager aligns with its contract and resolves the prior “main_only” misclassification risk. Looks correct.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
inc/managers/class-domain-manager.php (1)

1001-1011: Undefined index ‘sslverify’ and mislabeled HTTPS branch.

  • You read $protocol_config['sslverify'] even for the HTTP case where it isn’t set (PHP notice).
  • The “HTTPS with SSL verification” branch currently uses apply_filters('https_local_ssl_verify', false) which is commonly false → not actually verifying.
-		$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',
-			],
-		];
+		$protocols_to_test = [
+			[
+				'url'       => "https://{$domain_url}{$endpoint_path}",
+				'sslverify' => true,
+				'label'     => 'HTTPS with SSL verification',
+			],
+			[
+				'url'       => "https://{$domain_url}{$endpoint_path}",
+				'sslverify' => false,
+				'label'     => 'HTTPS without SSL verification',
+			],
+			[
+				'url'   => "http://{$domain_url}{$endpoint_path}",
+				'label' => 'HTTP',
+			],
+		];
@@
-					'sslverify'   => $protocol_config['sslverify'],
+					'sslverify'   => $protocol_config['sslverify'] ?? false,

Also applies to: 1024-1033

🧹 Nitpick comments (3)
inc/managers/class-domain-manager.php (3)

399-417: Scope UI to custom domains as well (optional).

This control only matters when custom domains are enabled. Consider requiring custom_domains too.

  'require' => [
     'enable_domain_mapping' => true,
+    'custom_domains'        => true,
  ],

420-470: Harden domain parsing and make decision filterable.

  • Don’t treat single-label inputs (e.g., “localhost”) as mains.
  • Normalize trailing dots.
  • Expose a final decision filter so site owners can override per-domain.
-	 * @since 2.0.0
+	 * @since 2.4.4
@@
-	public function should_create_www_subdomain($domain) {
+	public function should_create_www_subdomain($domain) {
@@
-		$domain = trim(strtolower($domain));
+		$domain = rtrim(trim(strtolower($domain)), '.');
@@
-		if (strpos($domain, 'www.') === 0) {
-			return false;
-		}
+		if (strpos($domain, 'www.') === 0) {
+			return (bool) apply_filters('wu_should_create_www_subdomain', false, $domain, null);
+		}
@@
-			case 'never':
-				return false;
+			case 'never':
+				return (bool) apply_filters('wu_should_create_www_subdomain', false, $domain, $setting);
@@
-				if (count($parts) <= 2) {
-					return true; // e.g., example.com
-				}
+				if (count($parts) === 2) {
+					return (bool) apply_filters('wu_should_create_www_subdomain', true, $domain, $setting); // e.g., example.com
+				}
+				if (count($parts) < 2) {
+					return (bool) apply_filters('wu_should_create_www_subdomain', false, $domain, $setting);
+				}
@@
-				if (count($parts) === 3 && in_array($last_two_parts, $known_multi_part_tlds, true)) {
-					return true; // e.g., example.co.uk
-				}
+				if (count($parts) === 3 && in_array($last_two_parts, $known_multi_part_tlds, true)) {
+					return (bool) apply_filters('wu_should_create_www_subdomain', true, $domain, $setting); // e.g., example.co.uk
+				}
@@
-				return false;
+				return (bool) apply_filters('wu_should_create_www_subdomain', false, $domain, $setting);
@@
-			default:
-				return true;
+			default:
+				return (bool) apply_filters('wu_should_create_www_subdomain', true, $domain, $setting);

423-424: Confirm @SInCE version.

This method appears newly introduced here; @since 2.0.0 is misleading. Please set to the release you’ll ship (looks like 2.4.4 per nearby annotations).

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 442c2a9 and 8f1f0c0.

📒 Files selected for processing (1)
  • inc/managers/class-domain-manager.php (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
inc/managers/class-domain-manager.php (1)
inc/functions/settings.php (2)
  • wu_register_settings_field (89-92)
  • wu_get_setting (39-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: cypress (8.4, firefox)
  • GitHub Check: cypress (8.4, chrome)
  • GitHub Check: cypress (8.3, chrome)
  • GitHub Check: cypress (8.3, firefox)
  • GitHub Check: cypress (8.0, chrome)
  • GitHub Check: cypress (8.0, firefox)
  • GitHub Check: cypress (8.2, firefox)
  • GitHub Check: cypress (8.1, chrome)
  • GitHub Check: cypress (8.1, firefox)
  • GitHub Check: cypress (8.2, chrome)
  • GitHub Check: cypress (7.4, firefox)
  • GitHub Check: cypress (7.4, chrome)

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
inc/managers/class-domain-manager.php (1)

999-1031: Make HTTPS fallback explicit and fix label/behavior mismatch

Comment says you test HTTPS with and without verification, but array defines only one HTTPS variant; the label claims “with SSL verification” while the default of https_local_ssl_verify is typically false. Define both HTTPS attempts explicitly and default to https_ssl_verify for remote hosts.

-		// 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',
-			],
-		];
+		// Test protocols in order of preference: HTTPS (verify), HTTPS (no verify), HTTP
+		$protocols_to_test = [
+			[
+				'url'       => "https://{$domain_url}{$endpoint_path}",
+				// Remote host verification (default true); allow overrides.
+				'sslverify' => apply_filters('https_ssl_verify', true),
+				'label'     => 'HTTPS (verify SSL)',
+			],
+			[
+				'url'       => "https://{$domain_url}{$endpoint_path}",
+				'sslverify' => false,
+				'label'     => 'HTTPS (no SSL verification)',
+			],
+			[
+				'url'   => "http://{$domain_url}{$endpoint_path}",
+				'label' => 'HTTP',
+			],
+		];
@@
-					'sslverify'   => $protocol_config['sslverify'] ?? false,
+					'sslverify'   => $protocol_config['sslverify'] ?? false,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 8f1f0c0 and 1e4eeaa.

📒 Files selected for processing (1)
  • inc/managers/class-domain-manager.php (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
inc/managers/class-domain-manager.php (1)
inc/functions/settings.php (2)
  • wu_register_settings_field (89-92)
  • wu_get_setting (39-42)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: cypress (8.3, firefox)
  • GitHub Check: cypress (8.4, chrome)
  • GitHub Check: cypress (8.4, firefox)
  • GitHub Check: cypress (8.1, chrome)
  • GitHub Check: cypress (8.3, chrome)
  • GitHub Check: cypress (8.2, firefox)
  • GitHub Check: cypress (8.2, chrome)
  • GitHub Check: cypress (8.1, firefox)
  • GitHub Check: cypress (8.0, chrome)
  • GitHub Check: cypress (7.4, firefox)
  • GitHub Check: cypress (8.0, firefox)
  • GitHub Check: cypress (7.4, chrome)
  • GitHub Check: PHP 8.2
  • GitHub Check: PHP 8.4
  • GitHub Check: PHP 8.3
  • GitHub Check: PHP 8.0
  • GitHub Check: PHP 7.4
  • GitHub Check: PHP 8.1
🔇 Additional comments (1)
inc/managers/class-domain-manager.php (1)

398-417: LGTM: new “www” setting wiring looks correct

Field registration, defaults, options, and require-gating are consistent with adjacent settings.

Comment on lines +420 to 470
/**
* Check if a www subdomain should be created for the given domain.
*
* @since 2.0.0
* @param string $domain The domain to check.
* @return bool True if www subdomain should be created, false otherwise.
*/
public function should_create_www_subdomain($domain) {

// Normalize incoming domain
$domain = trim(strtolower($domain));

// Guard against double-prefixing - return false if already starts with www.
if (strpos($domain, 'www.') === 0) {
return false;
}

$setting = wu_get_setting('auto_create_www_subdomain', 'always');

switch ($setting) {
case 'never':
return false;

case 'main_only':
// Check if this is a main domain (no subdomain parts)
// A main domain has only 2 parts when split by dots (e.g., example.com)
// or 3 parts if it's a known TLD structure (e.g., example.co.uk)
$parts = explode('.', $domain);

// Simple heuristic: if domain has only 2 parts, it's definitely a main domain
if (count($parts) <= 2) {
return true; // e.g., example.com
}

// For 3+ parts, check if it's a main domain with multi-part TLD
$known_multi_part_tlds = apply_filters('wu_multi_part_tlds', ['.co.uk', '.com.au', '.co.nz', '.com.br', '.co.in']);
$last_two_parts = '.' . $parts[ count($parts) - 2 ] . '.' . $parts[ count($parts) - 1 ];

// If it has exactly 3 parts and matches a known multi-part TLD, it's a main domain
if (count($parts) === 3 && in_array($last_two_parts, $known_multi_part_tlds, true)) {
return true; // e.g., example.co.uk
}

// Otherwise, it's a subdomain
return false;

case 'always':
default:
return true;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Harden domain normalization and avoid fatal on unexpected input; fix @SInCE

Cast to string before strtolower/trim and strip scheme/port/trailing dot to cover common edge cases (URLs passed in, ports, trailing dot). Also align the docblock @SInCE to the version introducing this method.

Apply:

-	 * @since 2.0.0
+	 * @since 2.4.4
@@
-	public function should_create_www_subdomain($domain) {
+	public function should_create_www_subdomain($domain) {
@@
-		// Normalize incoming domain
-		$domain = trim(strtolower($domain));
+		// Normalize incoming domain
+		$domain = strtolower(trim((string) $domain));
+		// If a URL sneaks in, extract host
+		if (strpos($domain, '://') !== false) {
+			$parsed = wp_parse_url($domain);
+			if (!empty($parsed['host'])) {
+				$domain = $parsed['host'];
+			}
+		}
+		// Drop trailing dot and any port suffix
+	$domain = rtrim($domain, '.');
+	$domain = preg_replace('/:\d+$/', '', $domain);

Optional: add a return type for consistency with this class’ other methods.

-	public function should_create_www_subdomain($domain) {
+	public function should_create_www_subdomain($domain): bool {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Check if a www subdomain should be created for the given domain.
*
* @since 2.0.0
* @param string $domain The domain to check.
* @return bool True if www subdomain should be created, false otherwise.
*/
public function should_create_www_subdomain($domain) {
// Normalize incoming domain
$domain = trim(strtolower($domain));
// Guard against double-prefixing - return false if already starts with www.
if (strpos($domain, 'www.') === 0) {
return false;
}
$setting = wu_get_setting('auto_create_www_subdomain', 'always');
switch ($setting) {
case 'never':
return false;
case 'main_only':
// Check if this is a main domain (no subdomain parts)
// A main domain has only 2 parts when split by dots (e.g., example.com)
// or 3 parts if it's a known TLD structure (e.g., example.co.uk)
$parts = explode('.', $domain);
// Simple heuristic: if domain has only 2 parts, it's definitely a main domain
if (count($parts) <= 2) {
return true; // e.g., example.com
}
// For 3+ parts, check if it's a main domain with multi-part TLD
$known_multi_part_tlds = apply_filters('wu_multi_part_tlds', ['.co.uk', '.com.au', '.co.nz', '.com.br', '.co.in']);
$last_two_parts = '.' . $parts[ count($parts) - 2 ] . '.' . $parts[ count($parts) - 1 ];
// If it has exactly 3 parts and matches a known multi-part TLD, it's a main domain
if (count($parts) === 3 && in_array($last_two_parts, $known_multi_part_tlds, true)) {
return true; // e.g., example.co.uk
}
// Otherwise, it's a subdomain
return false;
case 'always':
default:
return true;
}
}
/**
* Check if a www subdomain should be created for the given domain.
*
* @since 2.4.4
* @param string $domain The domain to check.
* @return bool True if www subdomain should be created, false otherwise.
*/
public function should_create_www_subdomain($domain) {
// Normalize incoming domain
$domain = strtolower(trim((string) $domain));
// If a URL sneaks in, extract host
if (strpos($domain, '://') !== false) {
$parsed = wp_parse_url($domain);
if (! empty( $parsed['host'] )) {
$domain = $parsed['host'];
}
}
// Drop trailing dot and any port suffix
$domain = rtrim($domain, '.');
$domain = preg_replace('/:\d+$/', '', $domain);
// Guard against double-prefixing - return false if already starts with www.
if (strpos($domain, 'www.') === 0) {
return false;
}
$setting = wu_get_setting('auto_create_www_subdomain', 'always');
switch ($setting) {
case 'never':
return false;
case 'main_only':
// ...existing logic...
🤖 Prompt for AI Agents
In inc/managers/class-domain-manager.php around lines 420 to 470, the domain
normalization can raise a fatal on non-string input and the docblock @since is
inaccurate; cast the incoming $domain to string before using strtolower/trim,
then strip URL scheme (http:// or https://), remove any trailing port (":1234")
and trailing dot to normalize inputs like full URLs or hostnames with ports,
then continue the existing www-prefix check; update the @since tag to the actual
version that introduced this method (replace 2.0.0 with the correct version),
and optionally add a bool return type to the method signature for consistency
(e.g., public function should_create_www_subdomain($domain): bool).

@superdav42 superdav42 merged commit 74ab99a into main Sep 5, 2025
14 of 25 checks passed
@superdav42 superdav42 deleted the fix-www-domain branch September 23, 2025 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant