You are here

domain_user.module in Domain Access 5

Same filename and directory in other branches
  1. 6.2 domain_user/domain_user.module

Creates unique subdomains for registered users.

File

domain_user/domain_user.module
View source
<?php

/**
 * @defgroup domain_user Domain User: personal subdomains
 *
 * Creates unique subdomains for registered users.
 */

/**
 * @file
 * Creates unique subdomains for registered users.
 *
 * @ingroup domain_user
 */

/**
 * Implement hook_init()
 *
 * We have to do this because we cannot redirect on login.
 */
function domain_user_init() {
  if (isset($_SESSION['domain_user'])) {
    $domain = domain_user_lookup($_SESSION['domain_user']);
    unset($_SESSION['domain_user']);
    domain_goto($domain);
  }
}

/**
 * Implement hook_menu()
 */
function domain_user_menu($may_cache) {
  $items = array();
  if ($may_cache) {
    $items[] = array(
      'title' => t('User domains'),
      'path' => 'admin/build/domain/user',
      'type' => MENU_LOCAL_TASK,
      'access' => user_access('administer domains'),
      'callback' => 'drupal_get_form',
      'callback arguments' => array(
        'domain_user_configure_form',
      ),
    );
  }
  return $items;
}

/**
 * Implement hook_perm()
 */
function domain_user_perm() {
  return array(
    'create personal domain',
  );
}

/**
 * FormsAPI
 */
function domain_user_configure_form() {
  drupal_set_title(t('User domain settings'));
  $form = array();
  $form['domain_user'] = array(
    '#type' => 'radios',
    '#title' => t('Module behavior'),
    '#options' => array(
      0 => t('Do not create domains for users'),
      1 => t('Automatically create domains for new users'),
      2 => t('Ask users if they would like to create a domain'),
    ),
    '#description' => t('Should subdomains be created when users register?'),
    '#default_value' => variable_get('domain_user', 0),
  );
  $form['domain_user_root'] = array(
    '#type' => 'textfield',
    '#title' => t('Root domain name'),
    '#size' => 40,
    '#maxlength' => 80,
    '#required' => TRUE,
    '#default_value' => variable_get('domain_user_root', variable_get('domain_root', '')),
    '#description' => t('The root domain to use for creating user domains, typically <em>example.com</em>.  No http or slashes.
      <br /> When users create domains, their username will be added to the root domain to create a custom domain.
      <br /> For example, <em>user1.example.com</em> or <em>administrator.example.com</em>.'),
  );
  $form['domain_user_scheme'] = array(
    '#type' => 'radios',
    '#title' => t('User Domain URL scheme'),
    '#options' => array(
      'http' => 'http://',
      'https' => 'https://',
    ),
    '#default_value' => variable_get('domain_user_scheme', 'http'),
    '#description' => t('The URL scheme for accessing user domains.'),
  );
  $form['domain_user_login'] = array(
    '#type' => 'radios',
    '#title' => t('User login behavior'),
    '#options' => array(
      1 => t('On login, go to personal domain'),
      0 => t('Do not go to personal domain on login'),
    ),
    '#default_value' => variable_get('domain_user_login', 1),
    '#description' => t('The domain users should go to when they login to the site.'),
  );
  if (module_exists('domain_prefix')) {
    $form['domain_user_prefixing'] = array(
      '#type' => 'radios',
      '#title' => t('Domain table prefixing'),
      '#options' => array(
        0 => t('Never create prefixed tabled for user domains'),
        1 => t('Obey the settings in Domain Prefix'),
      ),
      '#description' => t('Should user domains have detabase talbes created?'),
      '#default_value' => variable_get('domain_user_prefixing', 0),
    );
  }

  // Show the rules for username restrictions
  $rules = domain_user_rules();
  if (!empty($rules)) {
    $output = '<ul>';
    foreach ($rules as $rule) {
      $output .= '<li>' . $rule . '</li>';
    }
    $output .= '</ul>';
  }
  $form['rules'] = array(
    '#type' => 'markup',
    '#weight' => 20,
    '#value' => '<br /><br />' . t('<h3>Reserved Usernames</h3><p>The following usernames cannot be registered, since they are used as unique subdomains:</p>') . $output,
  );
  return system_settings_form($form);
}

/**
 * Checks for existing domains to create rules
 *
 * @param $generate
 *  A boolean flag indicating whether to generate {access} table entries based on
 *  the current domain set.  Default to TRUE.
 * @return
 *  An array of reserved name strings or an empty array.
 */
function domain_user_rules($generate = TRUE) {

  // Find domains that are not user domains.  These are blacklisted in user rules.
  // We set the $reset flag to TRUE, to be sure we catch all changes.
  $domains = domain_domains(TRUE);
  $reserved = array();

  // Get the root user domain.
  $root = variable_get('domain_user_root', variable_get('domain_root', ''));
  foreach ($domains as $domain) {
    if ($domain['domain_id'] > 0 && !$domain['uid'] && !empty($root)) {

      // Chop the name of domains to find the username equivalent.
      $string = str_replace('.' . $root, '', $domain['subdomain']);

      // In this case, we do strip port protocols, since they make no sense as usernames.
      $str = explode(':', $string);
      $name_string = $str[0];
      $reserved[] = $name_string;
      if ($generate && !empty($name_string)) {
        $check = db_result(db_query("SELECT aid FROM {access} WHERE mask = '%s'", $name_string));
        if (!$check) {
          db_query("INSERT INTO {access} (mask, type, status) VALUES ('%s', '%s', %d)", $name_string, 'user', 0);
        }
      }
    }
  }
  return $reserved;
}

/**
 * Implement hook_enable()
 *
 * When the module is enabled, create the rules for existing domains.
 */
function domain_user_enable() {
  domain_user_rules();
}

/**
 * Implement hook_disable()
 *
 * Deletes our user access masks.
 */
function domain_user_disable() {
  $rules = domain_user_rules(FALSE);
  foreach ($rules as $rule) {
    db_query("DELETE FROM {access} WHERE mask = '%s'", $rule);
  }
}

/**
 * Implement hook_domainload()
 */
function domain_user_domainload(&$domain) {

  // Zero is the default domain, and we don't want to invalidate it.
  if ($domain['domain_id'] > 0) {
    $data = db_fetch_array(db_query("SELECT du.uid, u.status FROM {domain_user} du INNER JOIN {users} u ON du.uid = u.uid WHERE du.domain_id = %d", $domain['domain_id']));
    if ($data['uid']) {
      $domain['uid'] = $data['uid'];
    }
  }
}

/**
 * Implement hook_user()
 */
function domain_user_user($op, &$edit, &$account, $category = NULL) {
  switch ($op) {
    case 'view':
      $domain = domain_user_lookup($account->uid);
      if ($domain != -1) {
        $items['domain'] = array(
          'title' => t(''),
          'value' => l($domain['path'], $domain['path']),
          'class' => '',
        );
        return array(
          t('Personal web site') => $items,
        );
      }
      break;
    case 'register':
    case 'form':

      // This function will return -1 if no domain exists. If no user exists yet, assume -1.
      $domain = -1;
      if (isset($account->uid)) {
        $domain = domain_user_lookup($account->uid);
      }

      // New users throw E_ALL errors.
      $name = t('username');
      if (isset($account->name)) {

        // Sanitize the username according to the host RFC.
        $name = domain_user_strip_chars($account->name);
      }
      $default = domain_default();
      $root = variable_get('domain_user_root', $default['subdomain']);

      // If the user name is on the ban list, we do not create a domain.
      // TODO: Maybe we should set a message here.
      if ($domain == -1 && domain_lookup(NULL, $name . '.' . $root) == -1) {
        $create_domain = variable_get('domain_user', 0);
        if (user_access('create personal domain')) {
          if ($create_domain == 1 && !empty($root)) {
            $form['domain_user_domain']['domain_create_user'] = array(
              '#type' => 'value',
              '#value' => 1,
            );
          }
          else {
            if ($create_domain == 2 && !empty($root)) {
              $form['domain_user_domain'] = array(
                '#type' => 'fieldset',
                '#title' => t('Personal web site'),
                '#collapsible' => TRUE,
                '#collapsed' => FALSE,
                '#weight' => 1,
              );
              $form['domain_user_domain']['domain_create_user'] = array(
                '#type' => 'checkbox',
                '#return_value' => 1,
                '#title' => t('Yes, I want to create my own site at <b>!user.!site</b>', array(
                  '!user' => $name,
                  '!site' => $root,
                )),
              );
            }
          }
          return $form;
        }
      }
      break;
    case 'insert':
    case 'update':

      // If we did not come from our expected form, do nothing.
      if (!isset($edit['domain_create_user'])) {
        return;
      }
      if (!empty($edit['domain_create_user']) && user_access('create personal domain', $account)) {
        $user_root = variable_get('domain_user_root', variable_get('domain_root', ''));
        $name = domain_user_strip_chars($account->name);
        $form_values['sitename'] = $account->name;
        $form_values['subdomain'] = $name . '.' . $user_root;
        $form_values['valid'] = $account->status;
        $form_values['user_submitted'] = TRUE;

        // This function will return -1 if no domain exists.
        $domain = domain_user_lookup($account->uid);
        if ($domain == -1) {

          // Set arguments to be passed to the form
          $arguments = array(
            'user_submitted' => TRUE,
          );

          // Include the form file.
          include_once drupal_get_path('module', 'domain') . '/domain_admin.inc';

          // Set the scheme as needed.
          $form_values['domain_scheme'] = variable_get('domain_user_scheme', 'http');
          drupal_execute('domain_create_form', $form_values, $arguments);
          $domain = domain_lookup(NULL, $form_values['subdomain'], TRUE);
          if ($domain['domain_id']) {
            db_query("INSERT INTO {domain_user} VALUES (%d, %d)", $domain['domain_id'], $account->uid);
            $edit['domains'][] = $domain['domain_id'];
            drupal_set_message(t('Your personal URL is <a href="!url">!url</a>.', array(
              '!url' => url($domain['path']),
            )));
          }
          else {
            drupal_set_message(t('Your personal URL could not be created.'));
          }
        }

        // Set the user's default domain to their subdomain.
        if ($domain['domain_id']) {

          // If the user cannot assign domain editors, only allow their unique domain.
          if (!user_access('assign domain editors')) {
            $edit['domain_user'] = array();
          }
          $edit['domain_user'][$domain['domain_id']] = $domain['domain_id'];

          // If the user account is blocked, set the domain to invalid.
          if ($account->status == 0) {
            db_query("UPDATE {domain} SET valid = 0 WHERE domain_id = %d", $domain['domain_id']);
          }
        }
      }
      if ($edit['domain_create_user'] && !user_access('create personal domain', $account)) {
        drupal_set_message(t('Your personal URL could not be created.'));
      }

      // Throw away what we do not need.
      $edit['domain_create_user'] = NULL;
      $edit['domains'] = NULL;

      // Special case if the username has changed.
      if ($op == 'update' && $edit['name'] != $account->name) {
        $domain = domain_user_lookup($account->uid, TRUE);
        if ($domain != -1) {
          $user_root = variable_get('domain_user_root', variable_get('domain_root', ''));
          $name = domain_user_strip_chars($edit['name']);
          $string = $name . '.' . $user_root;
          db_query("UPDATE {domain} SET subdomain = '%s', sitename = '%s' WHERE domain_id = %d", $string, $edit['name'], $domain['domain_id']);
        }
      }
      break;
    case 'login':

      // If the user has a personal domain, take them there.
      $domain = domain_user_lookup($account->uid);
      if (variable_get('domain_user_login', 1) && $domain != -1) {

        // We cannot do a redirect on login, which forces us to use a $_SESSION variable.
        // Only store the uid here, no need to store extra data where it can get hijacked.
        $_SESSION['domain_user'] = $account->uid;
      }
      break;
    case 'delete':

      // Delete the record
      // Run the lookup before we delete the row!
      $domain = domain_user_lookup($account->uid);
      if ($domain != -1) {
        db_query("DELETE FROM {domain} WHERE domain_id = %d", $domain['domain_id']);

        // Let other modules act.
        module_invoke_all('domainupdate', 'delete', $domain);
      }
      break;
  }
}

/**
 * Turn a user name into a domain-safe string.
 *
 * @param $name
 * The user name to process.
 * @return
 * A string with only alphanumeric characters and dashes.
 */
function domain_user_strip_chars($name) {

  // Only alphanumeric characters are allowed.
  $pattern = '/[^a-zA-Z0-9]/';
  $name = preg_replace($pattern, '-', $name);
  return strtolower($name);
}

/**
 * Implement hook_domainupdate()
 */
function domain_user_domainupdate($op, $domain = array(), $edit = array()) {
  $root = variable_get('domain_user_root', variable_get('domain_root', ''));
  switch ($op) {
    case 'update':

      // If these are different, then we must delete a row from {access}.
      if ($domain['subdomain'] != $edit['subdomain']) {
        $mask = str_replace('.' . $root, '', $domain['subdomain']);
        db_query("DELETE FROM {access} WHERE mask = '%s'", $mask);
      }
      domain_user_rules();
      break;
    case 'delete':

      // Delete from {domain_user}
      db_query("DELETE FROM {domain_user} WHERE domain_id = %d", $domain['domain_id']);

      // Delete from the access rules.
      $user_root = variable_get('domain_user_root', variable_get('domain_root', ''));
      $mask = str_replace('.' . $user_root, '', $domain['subdomain']);
      db_query("DELETE FROM {access} WHERE mask = '%s'", $mask);
      break;
  }
}

/**
 * Check to see if a user has created a domain record
 *
 * @param $uid
 *  The user id of the domain to be checked. Optional.
 * @param $name
 *  The username of the domain to be checked. Optional.
 * @param $domain_id
 *  The domain_id taken from {domain}. Optional.
 * @param $clear
 *  A boolean flag to clear the static variable if necessary. Not used.  Here for consistency.
 */
function domain_user_lookup($uid = NULL, $name = NULL, $domain_id = NULL, $clear = FALSE) {
  if ($uid) {
    $id = db_result(db_query("SELECT domain_id FROM {domain_user} WHERE uid = %d", $uid));
  }
  else {
    if ($name) {
      $id = db_result(db_query("SELECT du.domain_id FROM {domain_user} du INNER JOIN {users} u ON du.uid = u.uid WHERE u.name = '%s'", $name));
    }
    else {
      if ($domain_id) {
        $id = db_result(db_query("SELECT domain_id FROM {domain_user} WHERE domain_id = %d", $domain_id));
      }
    }
  }
  if ($id) {
    $return = domain_lookup($id);
  }
  else {
    $return = -1;
  }
  return $return;
}

/**
 * Implement hook_domainview()
 */
function domain_user_domainview($op, $domain = array()) {
  switch ($op) {
    case 'header':
      return array(
        array(
          'data' => t('User'),
          'field' => 'du.uid',
        ),
      );
      break;
    case 'select':
      return 'du.uid';
    case 'join':
      return "LEFT JOIN {domain_user} du ON du.domain_id = d.domain_id";
      break;
    case 'data':
      if ($domain['uid']) {
        $account = user_load(array(
          'uid' => $domain['uid'],
        ));
        return l($account->name, 'user/' . $account->uid);
      }
      break;
  }
}

Related topics

Functions

Namesort descending Description
domain_user_configure_form FormsAPI
domain_user_disable Implement hook_disable()
domain_user_domainload Implement hook_domainload()
domain_user_domainupdate Implement hook_domainupdate()
domain_user_domainview Implement hook_domainview()
domain_user_enable Implement hook_enable()
domain_user_init Implement hook_init()
domain_user_lookup Check to see if a user has created a domain record
domain_user_menu Implement hook_menu()
domain_user_perm Implement hook_perm()
domain_user_rules Checks for existing domains to create rules
domain_user_strip_chars Turn a user name into a domain-safe string.
domain_user_user Implement hook_user()