task: #3588246 Extract DomainAccessManager static helpers to DomainAccessFields
Summary
Moves the 5 public statics on Drupal\domain_access\DomainAccessManager (getAccessValues, getAllValue, getDefaultValue, clearStaticCache, userCanAccessDomain) to a new Drupal\domain_access\Utility\DomainAccessFields class. The originals become @deprecated wrappers with @trigger_error() that delegate to the new class.
Issue: #3588246. Mirrors the precedent set by !358 for DomainStorage::createMachineName() -> Drupal\domain\Utility\MachineName::fromString().
Why
DomainAccessManager is a service whose 5 statics are de-facto public API in the ecosystem (domain_path, domain_shorturl, domain_extras/domain_access_linkit). Marking the class @internal in #3584261 surfaced the conflict — the service is internal, its statics are public. Splitting them clears the way for DomainAccessManager to become @internal in 4.0.0 with no remaining public surface.
The new statics are pure entity-field readers with no instance state or DI requirements. They naturally belong on a utility class, not a service.
Internal callers migrated
DomainAccessManager itself (its instance methods checkEntityAccess, hasDomainPermissions, getContentUrls now call the new utility), DomainAccessNodeHooks, DomainAccessEntityHooks (incl. the setDefaultValueCallback() in entityBundleFieldInfoAlter), DomainAccessDomainHooks, DomainAccessFormHooks, DomainAccessAdd, DomainAccessRemove, DomainContentHooks, DomainSourceSet, plus 7 functional test classes (DomainAccessAllAffiliatesTest, DomainAccessDefaultValueTest, DomainAccessElementTest, DomainAccessEntityReferenceTest, DomainAccessLanguageSaveTest, DomainAccessPermissionsTest, DomainAccessSaveTest).
Behavior changes
None. Strict superset:
- The new class implements identical behavior to the originals (function bodies copied verbatim except for trivial type tightening — see "Type tightening" below).
- Static cache stays in one place — moved into
DomainAccessFields::$staticCache. The deprecatedDomainAccessManagerwrappers delegate, so external callers still hit the same (and only) cache. The oldDomainAccessManager::$staticCacheproperty is removed. getDefaultValueis set as a field default callback at runtime viasetDefaultValueCallback()inhook_entity_bundle_field_info_alter, NOT stored in config — so changing the callback location does not require a config migration. The callback fires fresh on everyentity_bundle_field_info_alterinvocation.
Type tightening (in DomainAccessFields only — wrappers preserve original signatures)
getAccessValues($entity, string $field_name = ...): array(was untyped$field_name, no return type)getAllValue($entity): bool(was no return type)getDefaultValue($entity, $definition): array(was no return type)clearStaticCache(string|int|null $entity_id, ?string $entity_type_id): void(was untyped)userCanAccessDomain($account, string|int $domain_id): UserDomainAccess(was untyped$domain_id; return type already present)
The deprecated wrappers on DomainAccessManager keep the original loose signatures, so the public BC surface is unchanged.
Out of scope (separate sweeps)
- Migrating the actual ecosystem callers:
domain_path(3 files, 11 call sites),domain_shorturl(1 site),domain_extras/domain_access_linkit(1 site). They keep working through the deprecated path. - Restoring
@internalonDomainAccessManager— that goes in 4.0.0 once the wrappers are removed.
Test plan
- PHPCS clean on changed files.
- PHPStan level 2 clean on full module.
- CI lint stage (cspell/eslint/stylelint/phpstan/phpcs/composer) green.
- CI phpunit (D11 + previous-major D10) — pipeline running.