You are here

domain_alias.module in Domain Access 7.3

Interface for advanced domain matching for Domain Access.

Original code by bforchhammer.- @link http://drupal.org/user/216396 @link http://drupal.org/node/284422

File

domain_alias/domain_alias.module
View source
<?php

/**
 * @defgroup domain_alias Domain Alias: Advanced domain matching
 *
 * Allows domain aliases and domain name patterns for domain
 * entries so multiple hostnames are matched on one single domain entry.
 */

/**
 * @file
 * Interface for advanced domain matching for Domain Access.
 *
 * Original code by bforchhammer.-
 * @link http://drupal.org/user/216396
 * @link http://drupal.org/node/284422
 *
 * @ingroup domain_alias
 */

/**
 * Implements hook_domain_bootstrap_lookup().
 *
 * Tries to match the given domain name against patterns in the {domain_alias}
 * table and, if successful, updates information in given parameter $domain.
 *
 * @param $domain
 *   An array containing current domain (host) name and
 *   the results of lookup against {domain} table.
 *
 * @see domain_resolve_name()
 *
 * @return
 *   An array containing at least a valid domain_id. Other values are:
 *   -- 'active_alias_id' => the currently active alias.
 *   -- 'redirect' => a boolean flag telling the module to redirect to the
 *   registered domain name if accessed from an alias.
 */
function domain_alias_domain_bootstrap_lookup($domain) {

  // If we had an exact match, then $domain['sitename'] is populated.
  // Otherwise, we must do an advanced check.
  if (isset($domain['sitename'])) {
    return;
  }
  $alias = domain_alias_lookup($domain['subdomain']);
  if ($alias != -1) {
    $domain['domain_id'] = $alias['domain_id'];
    $domain['active_alias_id'] = $alias['alias_id'];
    $domain['redirect'] = $alias['redirect'];
    return $domain;
  }
}

/**
 * Implements hook_init().
 *
 * If redirection is enabled for the active domain alias then we redirect to the
 * main domain.
 */
function domain_alias_init() {
  $_domain = domain_get_domain();

  // Redirect to main domain if active domain alias is set to redirect.
  // $_domain['redirect'] gets set in domain_alias_domain_bootstrap_lookup().
  if (isset($_domain['redirect']) && !empty($_domain['redirect'])) {
    $domain = domain_lookup($_domain['domain_id']);
    $response_code = $_domain['redirect'] < 300 ? 302 : $_domain['redirect'];
    drupal_goto(domain_get_uri($domain), array(), $response_code);
  }
}

/**
 * Implements hook_menu().
 */
function domain_alias_menu() {
  $items = array();
  $items['admin/structure/domain/view/%domain/alias'] = array(
    'title' => 'Aliases',
    'access arguments' => array(
      'administer domains',
    ),
    'type' => MENU_LOCAL_TASK,
    'page callback' => 'domain_alias',
    'page arguments' => array(
      4,
    ),
    'file' => 'domain_alias.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_theme().
 */
function domain_alias_theme() {
  return array(
    'domain_alias_form' => array(
      'render element' => 'form',
      'file' => 'domain_alias.admin.inc',
    ),
    'domain_alias_block' => array(
      'variables' => array(
        'domains' => array(),
      ),
    ),
  );
}

/**
 * Implements hook_block_info().
 */
function domain_alias_block_info() {
  $blocks = array();
  $blocks['domain_alias'] = array(
    'info' => t('Domain alias switcher'),
  );
  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function domain_alias_block_view($delta = '') {
  $domains = domain_domains();
  $output = theme('domain_alias_block', array(
    'domains' => $domains,
  ));
  $blocks = array(
    'subject' => t('Domain alias switcher'),
    'content' => $output,
  );
  return $blocks;
}

/**
 * Implements hook_block().
 */
function domain_alias_block($op = 'list', $delta = 0, $edit = array()) {
  $blocks = array();
  switch ($op) {
    case 'list':
      $blocks['domain_alias'] = array(
        'info' => t('Domain alias switcher'),
        'cache' => BLOCK_CACHE_PER_ROLE,
      );
      break;
    case 'view':
      $domains = domain_domains();
      $output = 'Test';
      $output = theme('domain_alias_block', $domains);
      $blocks = array(
        'subject' => t('Domain alias switcher'),
        'content' => $output,
      );
      break;
  }
  return $blocks;
}

/**
 * Runs a lookup against the {domain_alias} table.  One of the two values must
 * be present. The database result is limited to one row.
 *
 * @param $subdomain
 *   The domain to match the patterns in the {domain_alias} table against. Optional.
 * @param $alias_id
 *   The alias_id taken from {domain_alias}. Optional
 * @param $reset
 *   A boolean flag to clear the static variable if necessary.
 *
 * @return
 *   An array containing the requested row from the {domain_alias} table.
 *   Returns -1 on failure.
 */
function domain_alias_lookup($subdomain = NULL, $alias_id = NULL, $reset = FALSE) {
  $aliases =& drupal_static(__FUNCTION__);

  // If both are NULL, no lookup can be run.
  if (is_null($subdomain) && is_null($alias_id)) {
    return -1;
  }

  // Create a unique key so we can static cache all requests.
  $key = $alias_id . '_' . $subdomain;

  // Run the lookup, if needed.
  if (!isset($aliases[$key]) || $reset) {
    if (is_string($subdomain)) {

      // First, look for an exact match.
      $alias = array();
      $alias = db_query("SELECT alias_id, domain_id, pattern, redirect FROM {domain_alias} WHERE pattern = :subdomain", array(
        ':subdomain' => $subdomain,
      ))
        ->fetchAssoc();

      // If that fails, find the closest pattern(s).
      if (empty($alias)) {
        $result = db_query("SELECT alias_id, domain_id, pattern, redirect FROM {domain_alias} WHERE :subdomain LIKE pattern", array(
          ':subdomain' => $subdomain,
        ), array(
          'fetch' => PDO::FETCH_ASSOC,
        ));

        // If we returned more than one match, we have to find the most appropriate one.
        $patterns = array();
        foreach ($result as $alias) {
          $patterns[] = $alias;
        }
        if (empty($patterns)) {
          $alias = array();
        }
        elseif (count($patterns) == 1) {
          $alias = current($patterns);
        }
        else {
          $alias = domain_alias_best_match($subdomain, $patterns);
        }
      }
    }
    elseif (intval($alias_id)) {
      $alias = db_query("SELECT alias_id, domain_id, pattern, redirect FROM {domain_alias} WHERE alias_id = :alias_id", array(
        ':alias_id' => $alias_id,
      ))
        ->fetchAssoc();
    }

    // If we found a match, prepare the readable version.
    if (isset($alias['alias_id'])) {
      $alias['pattern'] = _domain_alias_placeholders_from_sql($alias['pattern']);
      $aliases[$key] = $alias;
      $key2 = $alias['alias_id'] . '_';
      $aliases[$key2] =& $aliases[$key];
    }
    else {
      $aliases[$key] = -1;
    }
  }
  return $aliases[$key];
}

/**
 * Given multiple choices for an alias, find the best match.
 *
 * @param $subdomain
 *   The requested subdomain string.
 * @param $patterns
 *   An array of patterns and alias data that match the given subdomain string.
 *
 * @return
 *   The best match, as an $alias array.
 */
function domain_alias_best_match($subdomain, $patterns) {
  $alias = array();
  $test = -1;
  $request = explode('.', $subdomain);
  foreach ($patterns as $pattern) {
    $match = explode('.', $pattern['pattern']);
    $count = count(array_intersect($match, $request));
    if ($count > $test) {
      $test = $count;
      $alias = $pattern;
    }
  }
  return $alias;
}

/**
 * Replace placeholders * and ? with SQL placeholders % and _
 *
 * @param $subdomain
 *   String to work on.
 *
 * @return
 *   String with replaced values.
 */
function _domain_alias_placeholders_to_sql($subdomain, $reverse = FALSE) {
  $placeholders = array(
    '*' => '%',
    '?' => '_',
  );
  if ($reverse) {
    return str_replace($placeholders, array_keys($placeholders), $subdomain);
  }
  else {
    return str_replace(array_keys($placeholders), $placeholders, $subdomain);
  }
}

/**
 * Replace SQL placeholders % and _ by placeholders * and ?.
 * Opposite of _domain_alias_placeholder_to_sql().
 *
 * @param $subdomain
 *   String to work on.
 *
 * @return
 *   String with replaced values.
 */
function _domain_alias_placeholders_from_sql($subdomain) {
  return _domain_alias_placeholders_to_sql($subdomain, TRUE);
}

/**
 * Returns all aliases for one domain record (domain_id).
 *
 * @param $domain_id
 *   The domain_id taken from {domain}.
 * @param $reset
 *   A boolean flag indicating whether to reset the static array or not.
 *
 * @return
 *   An array of all aliases defined for given domain_id, indexed by alias_id
 */
function domain_alias_list($domain_id, $reset = FALSE) {
  $aliases =& drupal_static(__FUNCTION__ . '_aliases');
  $result =& drupal_static(__FUNCTION__ . '_result');

  // Query the db for aliases.
  if (!isset($result) || $reset) {
    $result = db_query("SELECT domain_id, alias_id, pattern, redirect FROM {domain_alias} ORDER BY domain_id, alias_id", array(), array(
      'fetch' => PDO::FETCH_ASSOC,
    ))
      ->FetchAll();
  }
  if (!isset($aliases[$domain_id]) || $reset) {
    $aliases[$domain_id] = array();
    foreach ($result as $data) {
      $data['pattern'] = _domain_alias_placeholders_from_sql($data['pattern']);
      $aliases[$data['domain_id']][$data['alias_id']] = $data;
    }
  }
  return $aliases[$domain_id];
}

/**
 * Theme element for the Domain Alias switcher block.
 *
 * @param $domains
 *   The array of active domains defined by domain_domains().
 *
 * @return
 *   HTML output.
 */
function theme_domain_alias_block($variables) {
  $_domain = domain_get_domain();
  $domains = $variables['domains'];
  $output = '';
  $items = array();
  $msg = FALSE;
  $i = 0;
  $active = NULL;
  foreach ($domains as $domain) {
    if ($domain['valid']) {
      $title = $domain['sitename'];
      $allow = TRUE;
    }
    else {
      $title = $domain['sitename'] . ' *';
      $allow = FALSE;
      if (user_access('access inactive domains')) {
        $msg = TRUE;
        $allow = TRUE;
      }
    }
    if ($allow) {
      if ($domain['domain_id'] == $_domain['domain_id']) {
        $title = '<strong>' . $title . '</strong>';
      }
      $items[$i]['data'] = l($title, domain_get_uri($domain), array(
        'absolute' => TRUE,
        'html' => TRUE,
      ));
      if (!empty($domain['aliases'])) {
        $request = array_reverse(explode('.', $_domain['subdomain']));
        if (isset($_domain['active_alias_id'])) {
          $active = $_domain['active_alias_id'];
        }
        foreach ($domain['aliases'] as $alias_id => $alias) {
          $items[$i]['children'][] = _domain_alias_link($alias, $domain, $request, $active);
        }
      }
      $i++;
    }
  }
  $output .= theme('item_list', array(
    'items' => $items,
  ));
  if ($msg) {
    $output .= t('<em>* Inactive domain.</em>');
  }
  return $output;
}

/**
 * Format links for the switcher block.
 *
 * @param $alias
 *   The alias array to check.
 * @param $domain
 *   The parent domain of the alias.
 * @param $request
 *   A reversed array of the HTTP_HOST request, used for replacement strings.
 * @param $active
 *   The active alias id, if present.
 *
 * @return
 *   A link or plain text representation of the alias.
 */
function _domain_alias_link($alias, $domain, $request, $active = 0) {

  // Search for wildcards.
  $wildcard = substr_count($alias['pattern'], '*');
  $character = substr_count($alias['pattern'], '?');
  $text = $alias['pattern'];
  if ($wildcard) {
    $bits = array_reverse(explode('.', $text));
    foreach ($bits as $key => $bit) {
      if ($bit == '*' && isset($request[$key])) {
        $bits[$key] = $request[$key];
      }
    }
    $text = implode('.', array_reverse($bits));
  }
  if ($character) {
    $request = strrev(implode('.', array_reverse($request)));
    $char = strpos(strrev($text), '?');
    $replace = substr($request, $char, 1);
    $text = str_replace('?', $replace, $text);
  }
  $wildcard = substr_count($text, '*');
  $output = $alias['pattern'];
  if ($alias['alias_id'] == $active) {
    $output = '<em>' . $alias['pattern'] . '</em>';
  }
  if (!$alias['redirect'] && !$wildcard) {
    $domain['subdomain'] = $text;
    $path = domain_get_uri($domain);
    $link = l($output, $path, array(
      'absolute' => TRUE,
      'html' => TRUE,
    ));
  }
  else {
    $link = check_markup($output);
  }
  return $link;
}

/**
 * Implements hook_features_api().
 */
function domain_alias_features_api() {
  $components = array(
    'domain_alias' => array(
      'name' => t('Domain aliases'),
      'default_hook' => 'domain_alias_default_aliases',
      'default_file' => FEATURES_DEFAULTS_CUSTOM,
      'default_filename' => 'domains',
      'feature_source' => TRUE,
      'file' => drupal_get_path('module', 'domain_alias') . '/domain_alias.features.inc',
    ),
  );
  return $components;
}

Related topics

Functions

Namesort descending Description
domain_alias_best_match Given multiple choices for an alias, find the best match.
domain_alias_block Implements hook_block().
domain_alias_block_info Implements hook_block_info().
domain_alias_block_view Implements hook_block_view().
domain_alias_domain_bootstrap_lookup Implements hook_domain_bootstrap_lookup().
domain_alias_features_api Implements hook_features_api().
domain_alias_init Implements hook_init().
domain_alias_list Returns all aliases for one domain record (domain_id).
domain_alias_lookup Runs a lookup against the {domain_alias} table. One of the two values must be present. The database result is limited to one row.
domain_alias_menu Implements hook_menu().
domain_alias_theme Implements hook_theme().
theme_domain_alias_block Theme element for the Domain Alias switcher block.
_domain_alias_link Format links for the switcher block.
_domain_alias_placeholders_from_sql Replace SQL placeholders % and _ by placeholders * and ?. Opposite of _domain_alias_placeholder_to_sql().
_domain_alias_placeholders_to_sql Replace placeholders * and ? with SQL placeholders % and _