domain_alias.module in Domain Access 8
Same filename and directory in other branches
Maps multiple host requests to a single domain record.
File
domain_alias/domain_alias.moduleView source
<?php
/**
* @file
* Maps multiple host requests to a single domain record.
*/
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;
use Drupal\Core\Session\AccountInterface;
use Drupal\domain\DomainInterface;
use Drupal\domain\DomainNegotiatorInterface;
/**
* Implements hook_domain_request_alter().
*
* The logic in this function gives us the following matches for a request to
* foo.example.com.
*
* 'foo.*'
* '*.example.com'
* 'foo.*.com'
* 'foo.example.*'
* '*.foo.example.com'
* 'foo.example.com.*'
*
* These patterns should be sufficient for most conditions.
*/
function domain_alias_domain_request_alter(DomainInterface &$domain) {
// During the installation the entity definition is not yet added when this
// hook is invoked, so skip if not present.
$has_definition = \Drupal::entityTypeManager()
->hasDefinition('domain_alias');
// If an exact match has loaded, do nothing.
if ($domain
->getMatchType() === DomainNegotiatorInterface::DOMAIN_MATCHED_EXACT || !$has_definition) {
return;
}
// If no exact match, then run the alias load routine.
$hostname = $domain
->getHostname();
$alias_storage = \Drupal::entityTypeManager()
->getStorage('domain_alias');
$domain_storage = \Drupal::entityTypeManager()
->getStorage('domain');
/** @var \Drupal\domain_alias\Entity\DomainAlias $alias */
if ($alias = $alias_storage
->loadByHostname($hostname)) {
/** @var \Drupal\domain\Entity\Domain $domain */
if ($domain = $domain_storage
->load($alias
->getDomainId())) {
$domain
->addProperty('alias', $alias);
$domain
->setMatchType(DomainNegotiatorInterface::DOMAIN_MATCHED_ALIAS);
$redirect = $alias
->getRedirect();
if (!empty($redirect)) {
$domain
->setRedirect($redirect);
}
}
else {
// If the domain did not load, report an error.
\Drupal::logger('domain_alias')
->error('Found matching alias %alias for host request %hostname, but failed to load matching domain with id %id.', [
'%alias' => $alias
->getPattern(),
'%hostname' => $hostname,
'%id' => $alias
->getDomainId(),
]);
}
}
}
/**
* Implements hook_domain_operations().
*/
function domain_alias_domain_operations(DomainInterface $domain, AccountInterface $account) {
$operations = [];
// Check permissions. The user must be a super-admin or assigned to the
// domain.
$is_domain_admin = $domain
->access('update', $account);
if ($account
->hasPermission('administer domain aliases') || $is_domain_admin && $account
->hasPermission('view domain aliases')) {
// Add aliases to the list of operations.
$operations['domain_alias'] = [
'title' => t('Aliases'),
'url' => Url::fromRoute('domain_alias.admin', [
'domain' => $domain
->id(),
]),
'weight' => 60,
];
}
return $operations;
}
/**
* Implements hook_ENTITY_TYPE_load().
*/
function domain_alias_domain_load($entities) {
static $enabled;
// We can only perform meaningful actions if url.site is a cache context.
// Otherwise, the render process ignores our changes.
if (!isset($enabled)) {
$required_cache_contexts = \Drupal::getContainer()
->getParameter('renderer.config')['required_cache_contexts'];
if (!in_array('url.site', $required_cache_contexts) && !in_array('url', $required_cache_contexts)) {
$enabled = FALSE;
return;
}
$enabled = TRUE;
}
// We cannot run before the negotiator service has fired.
$negotiator = \Drupal::service('domain.negotiator');
$active = $negotiator
->getActiveDomain();
// Do nothing if no domain is active.
if (empty($active)) {
return;
}
// Load and rewrite environment-specific aliases.
$alias_storage = \Drupal::entityTypeManager()
->getStorage('domain_alias');
if (isset($active->alias) && $active->alias
->getEnvironment() != 'default') {
foreach ($entities as $id => $domain) {
if ($environment_aliases = $alias_storage
->loadByEnvironmentMatch($domain, $active->alias
->getEnvironment())) {
foreach ($environment_aliases as $environment_alias) {
$pattern = $environment_alias
->getPattern();
// Add a canonical property.
$domain
->setCanonical();
// Override the domain hostname and path. We always prefer a string
// match.
if (substr_count($pattern, '*') < 1) {
$domain
->setHostname($pattern);
$domain
->setPath();
$domain
->setUrl();
break;
}
else {
// Do a wildcard replacement based on the current request.
$request = $negotiator
->negotiateActiveHostname();
// First, check for a wildcard port.
if (substr_count($pattern, ':*') > 0) {
// Do not replace ports unless they are nonstandard. See
// \Symfony\Component\HttpFoundation\Request\getHttpHost().
if (substr_count($request, ':') > 0) {
$search = explode(':', $pattern);
$replace = explode(':', $request);
if (!empty($search[1]) && !empty($replace[1])) {
$pattern = str_replace(':' . $search[1], ':' . $replace[1], $pattern);
}
}
else {
$pattern = str_replace(':*', '', $pattern);
}
}
$replacements = [
'.' => '\\.',
'*' => '(.+?)',
];
$regex = '/^' . strtr($active->alias
->getPattern(), $replacements) . '$/';
if (preg_match($regex, $request, $matches) && isset($matches[1])) {
$pattern = str_replace('*', $matches[1], $pattern);
}
// Do not let the domain loop back on itself.
if ($pattern != $domain
->getCanonical()) {
$domain
->setHostname($pattern);
$domain
->setPath();
$domain
->setUrl();
}
}
}
}
}
}
}
/**
* Implements hook_ENTITY_TYPE_delete().
*/
function domain_alias_domain_delete(EntityInterface $entity) {
$alias_storage = \Drupal::entityTypeManager()
->getStorage('domain_alias');
$properties = [
'domain_id' => $entity
->id(),
];
foreach ($alias_storage
->loadByProperties($properties) as $alias) {
$alias
->delete();
}
}
Functions
Name | Description |
---|---|
domain_alias_domain_delete | Implements hook_ENTITY_TYPE_delete(). |
domain_alias_domain_load | Implements hook_ENTITY_TYPE_load(). |
domain_alias_domain_operations | Implements hook_domain_operations(). |
domain_alias_domain_request_alter | Implements hook_domain_request_alter(). |