fix: #3588169 Validator: do not count the port wildcard against the host wildcard limit
Summary
Two related fixes in the alias pattern validator, plus the cleanup work that surfaced from the audit:
-
Validator counted host and port wildcards together.
DomainAliasValidatorandDomainAliasPatternConstraintValidatorsummedsubstr_count($pattern, '*')across host and port portions when enforcing the "one wildcard" rule. The port wildcard:*means "any port for this host" — conceptually distinct from a host wildcard — and the rest of the alias pipeline already treats it that way (buildPortPatterns(),DomainAliasPatternResolver, the priority model docs added in #3588155). Co-counting blocked patterns the README documents as supported (e.g.example.*:*,*.com:*).Fix: split the port suffix off the pattern before counting wildcards. Apply the existing single-wildcard limit to host stars only.
-
Inert
?wildcard handling dropped. Audit found?was half-treated as a wildcard:- The validators counted
substr_count($pattern, '?')toward the wildcard limit. DomainAliasFormtranslated\?to[^.:]in its "pattern shadows a canonical hostname" warning regex.
But the matching pipeline never honors
?:DomainAliasPatternResolver::patternToRegex()only replaces*,buildPatterns()only inserts*,loadByPattern()does an exact-string DB lookup. The README only documents*as the wildcard. A pattern likefoo?.example.comwas capped (or warned about) as if it had a wildcard, but at runtime would only ever match the literal hostnamefoo?.example.com.Fix: drop the
?counting in both validators and the?-to-regex translation in the form.Historical context:
?was a real single-character wildcard in Domain 6.x/7.x (see_domain_alias_link()on the 7.x-3.x branch). The 8.x-1.x port silently dropped the matcher logic but kept the validator. Sites migrated from D7 with?patterns have had silently inert aliases ever since. - The validators counted
-
Deprecation pathway for 4.0.0.
?stays in the character allowlist for backwards compatibility (existing config with?still loads), but a newhook_ENTITY_TYPE_presave('domain_alias')fires@trigger_error(... E_USER_DEPRECATED)when an alias pattern contains?. Catches every save path (UI form, Drush, config import). Five@todo Remove in domain:4.0.0markers across the validators and the hook make a future cleanup-grep find every related code path with no orphans.
Issue: #3588169.
What ships in this MR
| File | Change |
|---|---|
DomainAliasValidator.php |
Host/port split, ? no longer counted, @todos for 4.0.0. |
DomainAliasPatternConstraintValidator.php |
Same on the entity-constraint side. |
DomainAliasForm.php |
? removed from the canonical-shadow warning regex. Pattern field #description now spells out the host-wildcard / port-suffix combination rules. |
DomainAliasHooks.php |
New #[Hook('domain_alias_presave')] firing the ? deprecation. @todo Remove this entire method in domain:4.0.0. |
domain_alias/README.md |
"Alias Patterns" rewritten with the patterns the validator actually accepts. New "Constraints" subsection. ? flagged as deprecated and removed in 4.0.0. |
DomainAliasValidatorTest.php |
Positive cases: example.com:*, *.example.com:*, example.*:*, example.*:8080. |
DomainAliasConstraintTest.php |
testValidPatterns extended with the same combinations. |
Behavior changes
- Patterns previously rejected for combining host wildcard with port suffix (e.g.
example.*:*,*.example.com:*,example.*:8080) now save successfully. Strict superset; no patterns previously valid are now rejected. - Patterns containing
?save with a deprecation notice. No matching change —?was never honored as a wildcard at request time.
Test plan
-
DomainAliasValidatorTest::testDomainAliasValidator— 25 assertions, OK locally (Drupal 11.x + MySQL). -
DomainAliasConstraintTestfull file — 16 tests, 28 assertions, OK locally. - PHPCS / PHPStan / cspell / eslint / stylelint clean.
- CI phpunit (D11) green; phpunit (previous major / D10) running.
- Spot-check on a multi-alias setup that registering
example.*:*succeeds and resolves correctly on incoming requests.
Out of scope (separate issues)
- Raising the host-wildcard limit to match the README's "max 3" claim.
DomainAliasPatternResolver::replaceWildcards()substitution hardening (prerequisite for raising the cap).- 4.0.0 cleanup itself: drop
?from the allowlist, delete the deprecation hook, simplify the validator comments. The@todo Remove in domain:4.0.0markers in this MR will surface every related code path.
Coordination
No hard dependencies. Independent of !371 (merged) (#3588168 buildPatterns completeness) — different functions, different test methods. !370 (merged) (#3588155 sort + priority) already merged.
Release notes
The
domain_aliaspattern validator no longer counts the port wildcard:*against the host-wildcard limit. Patterns combining a single host wildcard with a port suffix (e.g.example.*:*,*.example.com:8080) now save successfully — these patterns were always documented as supported and handled by the matching pipeline; only the validator blocked them.Patterns containing
?are now flagged with a deprecation notice on save.?was a single-character wildcard in Domain 6.x/7.x, but has not been honored as a wildcard since the 8.x-1.x port. The character will be removed from the alias pattern allowlist entirely indomain:4.0.0. Sites with?patterns should clean them up before upgrading to 4.0.0.