You are here

hosting_site.module in Hosting 6.2

File

site/hosting_site.module
View source
<?php

/**
 * This site is deleted from the backend.
 */
define('HOSTING_SITE_DELETED', -2);

/**
 * This site is disabled.
 */
define('HOSTING_SITE_DISABLED', -1);

/**
 * This site is queued for creation.
 */
define('HOSTING_SITE_QUEUED', 0);

/**
 * This site is created and enabled in the backend.
 */
define('HOSTING_SITE_ENABLED', 1);
include_once 'hosting_site.nodeapi.inc';
include_once 'hosting_site.form.inc';
include_once 'hosting_site.backups.inc';

//Conditonally include site quotas
if (module_exists('hosting_quota')) {
  include_once 'hosting_site.quota.inc';
}

/**
 * Implementation of hook_menu()
 */
function hosting_site_menu() {
  $items = array();
  $items['hosting/sites/list'] = array(
    'title' => 'List',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -10,
  );
  $items['hosting/sites/add'] = array(
    'title' => 'Add site',
    'type' => MENU_LOCAL_TASK,
    'page callback' => 'drupal_goto',
    'page arguments' => array(
      'node/add/site',
    ),
    'access callback' => 'node_access',
    'access arguments' => array(
      'create',
      'site',
    ),
  );
  $items['node/%node/platform-add-site'] = array(
    'title' => 'Add site',
    'type' => MENU_LOCAL_TASK,
    'page callback' => 'hosting_site_add_by_platform',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'hosting_site_add_by_platform_access',
    'access arguments' => array(
      1,
    ),
  );
  $items['hosting/hosting_site_form_check'] = array(
    'page callback' => '_hosting_site_form_check',
    'type' => MENU_CALLBACK,
    'access arguments' => array(
      'access content',
    ),
  );
  $items['node/%hosting_site_node/goto_site'] = array(
    'page callback' => 'hosting_site_goto',
    'page arguments' => array(
      1,
    ),
    'access callback' => 'node_access',
    'access arguments' => array(
      'view',
      1,
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implements hook_theme().
 */
function hosting_site_theme() {
  $items = array();
  $items['hosting_site_profile'] = array(
    'arguments' => array(
      'profile' => NULL,
      'html' => FALSE,
    ),
  );
  $items['hosting_site_goto_link'] = array(
    'arguments' => array(
      'title' => NULL,
      'url' => NULL,
    ),
  );
  return $items;
}
function _hosting_site_form_check() {
  $platform = NULL;
  if (isset($_GET['platform'])) {
    $platform = $_GET['platform'];
  }
  $result = hosting_site_available_options($_POST, $platform);
  drupal_json($result);
  exit;
}

/**
 * Implementation of hook_load().
 *
 * @param arg
 *    Node's numeric nid
 */
function hosting_site_node_load($arg) {
  if (!is_numeric($arg)) {
    return FALSE;
  }
  if ($node = node_load($arg)) {
    if ($node->type == 'site') {
      return $node;
    }
  }
  return FALSE;
}

/**
 * Generate a link allowing the user to log into their new site, or simply
 * go to the site front page if the link has expired.
 */
function _hosting_site_goto_link($node) {
  $cache = cache_get("hosting:site:" . $node->nid . ":login_link");
  if (user_access('create login-reset task') && $cache && time() < $cache->data['expire']) {
    $title = t("Log in to !url", array(
      '!url' => $node->title,
    ));
  }
  else {
    $title = t("Go to !url", array(
      '!url' => $node->title,
    ));
  }
  $url = "node/" . $node->nid . "/goto_site";
  return theme('hosting_site_goto_link', $title, $url);
}

/**
 * Theme function for site link.
 */
function theme_hosting_site_goto_link($title, $url) {
  $options['attributes']['class'] = 'hosting-goto-site-link';
  $options['attributes']['target'] = '_blank';
  return l($title, $url, $options);
}

/**
 * Menu callback to go to your site.
 *
 * This needs to be a callback because the link is only going to work once, 
 * so this will remove the link from the cache and just redirect to the site
 * not the login page.
 */
function hosting_site_goto($node) {
  $cid = "hosting:site:" . $node->nid . ":login_link";
  $cache = cache_get($cid);
  if (user_access('create login-reset task') && !is_null($cache) && time() < $cache->data['expire']) {
    $theurl = $cache->data['link'];
    cache_clear_all($cid, 'cache');
  }
  else {
    $theurl = _hosting_site_url($node);
  }
  drupal_goto($theurl);
  exit;
}

/**
 * Retrieve the port the site will be available on, so we can redirect.
 */
function hosting_site_get_port($node) {
  $platform = node_load($node->platform);
  $server = node_load($platform->web_server);
  return $server->services['http']->port;
}

/**
 * Get site's URL.
 */
function _hosting_site_url($node) {
  $schema = 'http';
  $port = null;
  $url = strtolower(trim($node->title));
  $platform = node_load($node->platform);
  $server = node_load($platform->web_server);
  if ($server->services['http']
    ->has_port()) {
    $port = $server->services['http']->port;
    if ($port == 80) {
      $port = null;
    }
  }

  /**
   * This is part of the ssl feature, but is better to implement here.
   */
  if (isset($node->ssl_enabled) && $node->ssl_enabled == 2) {

    // this is a bit of a magic number, because we cant rely on the constant being available yet.
    // 2 == Only SSL is enabled.
    $schema = 'https';
    if ($server->services['http']
      ->has_port()) {
      $port = $server->services['http']->ssl_port;
      if ($port == 443) {
        $port = null;
      }
    }
  }
  if (is_numeric($port)) {
    return "{$schema}://{$url}:{$port}";
  }
  return "{$schema}://{$url}";
}

/**
 * Implementation of hook_hosting_tasks
 */
function hosting_site_hosting_tasks() {
  $tasks = array();
  $tasks['site']['backup'] = array(
    'title' => t('Backup'),
    'description' => t('Generate a backup of this site that can be restored to at any time'),
    'dialog' => TRUE,
  );
  $tasks['site']['restore'] = array(
    'title' => t('Restore'),
    'description' => t('Restore this site to a previous backup. A new backup will be created before this is attempted.'),
    'dialog' => TRUE,
  );
  $tasks['site']['verify'] = array(
    'title' => t('Verify'),
    'description' => t('Confirm that the site has been correctly installed and regenerate all configuration files to match the hosting front end.'),
    'provision_save' => TRUE,
  );
  $tasks['site']['disable'] = array(
    'title' => t('Disable'),
    'description' => t('Disabling this site will stop it from being accessible.
         It can be enabled again later.'),
    'dialog' => TRUE,
  );
  $tasks['site']['enable'] = array(
    'title' => t('Enable'),
    'description' => t('Enabling this site will allow it to be accesible again.
         It may be disabled again if needed.'),
  );
  $tasks['site']['delete'] = array(
    'title' => t('Delete'),
    'description' => t('Deleting this site will completely remove it from the hosting system,
        but will keep the last backup available. This process can not be undone.
        Are you really sure you want to delete this site?'),
    'dialog' => TRUE,
  );
  $tasks['site']['login-reset'] = array(
    'title' => t('Reset password'),
    'description' => t('Generate a one-time login reset url for this site.'),
  );
  $tasks['site']['backup-delete'] = array(
    'title' => t('Delete backups'),
    'description' => t('Delete one or more backup files of a site.'),
    'dialog' => TRUE,
  );
  $tasks['site']['install'] = array(
    'title' => t('Install'),
    'description' => t('Install a site'),
    'hidden' => TRUE,
    'provision_save' => TRUE,
  );
  $tasks['site']['import'] = array(
    'title' => t('Import'),
    'description' => t('Import an existing site into Aegir'),
    'hidden' => TRUE,
    'provision_save' => TRUE,
  );
  return $tasks;
}

/**
 * Implementation of hook_perm
 */
function hosting_site_perm() {
  return array(
    'create site',
    'view site',
    'edit site',
    'delete site',
    'administer sites',
  );
}

/**
 * Implementation of hook_access
 */
function hosting_site_access($op, $node, $account) {
  if ($op != 'create' && hosting_feature('client')) {

    // we rely on hosting_client_node_grants() instead of global configuration
    return NULL;
  }
  switch ($op) {
    case 'create':
      return user_access('create site', $account);
      break;
    case 'update':
      return user_access('edit site', $account);
      break;
    case 'delete':
      return user_access('delete site', $account);
      break;
    case 'view':
      return user_access('view site', $account);
      break;
  }
}

/**
 * Implements hook_node_operations().
 */
function hosting_site_node_operations() {
  $operations = array();
  $operations['hosting-site-backup'] = array(
    'label' => t('Site: Backup'),
    'callback' => 'hosting_site_op_backup',
  );
  $operations['hosting-site-verify'] = array(
    'label' => t('Site: Verify'),
    'callback' => 'hosting_site_op_verify',
  );
  $operations['hosting-site-disable'] = array(
    'label' => t('Site: Disable'),
    'callback' => 'hosting_site_op_disable',
  );
  $operations['hosting-site-enable'] = array(
    'label' => t('Site: Enable'),
    'callback' => 'hosting_site_op_enable',
  );
  $operations['hosting-site-delete'] = array(
    'label' => t('Site: Delete'),
    'callback' => 'hosting_site_op_delete',
  );
  $operations['hosting-site-login-reset'] = array(
    'label' => t('Site: Reset password'),
    'callback' => 'hosting_site_op_login_reset',
  );
  return $operations;
}

/**
 * Callback for site backup operation.
 */
function hosting_site_op_backup($nodes) {
  foreach ($nodes as $nid) {
    hosting_add_task($nid, 'backup');
  }
}

/**
 * Callback for site verify operation.
 */
function hosting_site_op_verify($nodes) {
  foreach ($nodes as $nid) {
    hosting_add_task($nid, 'verify');
  }
}

/**
 * Callback for site verify operation.
 */
function hosting_site_op_disable($nodes) {
  foreach ($nodes as $nid) {
    hosting_add_task($nid, 'disable');
  }
}

/**
 * Callback for site verify operation.
 */
function hosting_site_op_enable($nodes) {
  foreach ($nodes as $nid) {
    hosting_add_task($nid, 'enable');
  }
}

/**
 * Callback for site verify operation.
 */
function hosting_site_op_delete($nodes) {
  foreach ($nodes as $nid) {
    hosting_add_task($nid, 'delete');
  }
}

/**
 * Callback for site verify operation.
 */
function hosting_site_op_login_reset($nodes) {
  foreach ($nodes as $nid) {
    hosting_add_task($nid, 'login-reset');
  }
}

/**
 * Access callback for Site add by platform.
 */
function hosting_site_add_by_platform_access($node) {
  return $node->type == 'platform' && $node->platform_status == HOSTING_PLATFORM_ENABLED && node_access('create', 'site');
}

/**
 * Page callback for Site add by platform.
 */
function hosting_site_add_by_platform($node) {
  drupal_goto('node/add/site', "platform={$node->nid}");
}

/**
 * Returns a count of sites.
 *
 * This is used by cron and statistics to batch the number of sites that are
 * processed with each call. It is also used to generate the 'site count' per
 * platform at /hosting/platforms
 *
 * By default it only counts enabled sites.
 *
 * Optionally can include an array of site statuses by which to consider in the
 * count.
 *
 * @param $platform
 *   (optional) A platform nid to only count sites on that specific platform.
 * @param $statuses
 *   (optional) An array of site statuses (defined by their constants) by which
 *   to include such sites in the site count.
 *
 * @return
 *   The number of sites matching the specified criteria.
 */
function hosting_site_count($platform = NULL, $statuses = NULL) {
  if (is_null($statuses)) {
    $statuses = array(
      HOSTING_SITE_ENABLED,
    );
  }
  $args = array();
  $query = "SELECT count(nid) FROM {hosting_site}";
  $where = array();
  if (count($statuses)) {
    $where[] = '(status IN (' . db_placeholders($statuses) . '))';
    $args = array_merge($args, $statuses);
  }
  if (!is_null($platform)) {
    $where[] = "(platform = %d)";
    $args[] = $platform;
  }
  if (!empty($where)) {
    $query .= ' WHERE ' . implode(' AND ', $where);
  }
  return db_result(db_query($query, $args));
}

/**
 * Retrieve sites on a specific platform, with a specific status
 */
function hosting_get_sites_by_status($platform, $status) {
  $nodes = array();
  $result = db_query("SELECT nid FROM {hosting_site} WHERE platform=%d AND status = %d", $platform, $status);
  while ($nid = db_fetch_object($result)) {
    $nodes[$nid->nid] = node_load($nid->nid);
  }
  return $nodes;
}

/**
 * Retrieve a node based on the url
 */
function hosting_get_site_by_url($url) {

  // If the Aliases feature is enabled, try and get the site by its alias too
  if (hosting_feature('alias')) {
    $nid = db_result(db_query("SELECT n.nid FROM {node} n JOIN {hosting_site} h ON n.nid = h.nid LEFT JOIN {hosting_site_alias} ha ON h.vid = ha.vid WHERE (n.title = '%s' OR ha.alias = '%s') AND n.type = 'site' AND NOT (h.status = %d)", $url, $url, HOSTING_SITE_DELETED));
  }
  else {
    $nid = db_result(db_query("SELECT n.nid FROM {node} n JOIN {hosting_site} h ON n.nid = h.nid WHERE n.title='%s' AND n.type = 'site' AND NOT (h.status=%d)", $url, HOSTING_SITE_DELETED));
  }
  if ($nid) {
    return node_load($nid);
  }
  return false;
}

/**
 * Helper function to generate update a site node during import.
 *
 * @param $site_id
 *   The node ID of the existing site node to update.
 * @param $data
 *  An associative array of data to add to the site node. Keys should correspond
 *  to properties on the node object to overwrite.
 * @param $platform
 *   The node ID of the platform that the site is deployed on.
 */
function hosting_import_site($site_id, $data, $platform) {
  global $user;
  $client = node_load(HOSTING_DEFAULT_CLIENT);
  if ($data['client_name']) {
    $client = hosting_import_client($data['client_name']);
  }
  $site = node_load($site_id);
  $site->nid = $site_id;
  $site->uid = $client->uid;
  $site->status = 1;
  $site->site_status = 1;
  $site->platform = $platform;
  $site->no_verify = TRUE;
  $site->verified = time();
  $site->client = $client->nid ? $client->nid : HOSTING_DEFAULT_CLIENT;
  $site->cron_key = $data['cron_key'] ? $data['cron_key'] : '';
  $site->aliases = $data['aliases'] ? $data['aliases'] : array();
  $site->db_server = $site->db_server ? $site->db_server : HOSTING_DEFAULT_DB_SERVER;
  $site->site_language = $data['language'] ? $data['language'] : 'en';

  // Drupal 6 introduced a language field on nodes
  unset($data['language']);
  $profile = hosting_package_instance_load(array(
    'i.rid' => $platform,
    'p.short_name' => $data['profile'],
  ));
  if (!$profile) {
    $profile = hosting_package_instance_load(array(
      'i.rid' => $platform,
      'p.short_name' => 'default',
    ));
  }
  $site->profile = $profile->package_id;

  // cast site object to array, will be using various array_* functions on the data.
  $site = (array) $site;

  // Protect the fields already in the site object.
  foreach (array_keys($site) as $key) {
    unset($data[$key]);
  }

  // Load all the original node fields.
  $site = array_merge((array) node_load($site_id), $site);

  // Map the imported fields onto the node object.
  $site = array_merge($site, $data);

  // Cast back to object.
  $site = (object) $site;
  node_save($site);
}

/**
 * Define the status types of a site
 */
function _hosting_site_status($node) {
  $status = is_numeric($node) ? $node : $node->site_status;
  $labels = hosting_site_status_codes('label');
  return $labels[$status];
}

/**
 * Define the status type labels and classes.
 *
 * @param $type
 *   The type of status to return ('label' or 'class').
 */
function hosting_site_status_codes($type = NULL) {
  static $codes = array(
    HOSTING_SITE_QUEUED => array(
      'label' => 'Queued',
      'class' => 'hosting-queue',
    ),
    HOSTING_SITE_ENABLED => array(
      'label' => 'Enabled',
      'class' => 'hosting-success',
    ),
    HOSTING_SITE_DELETED => array(
      'label' => 'Deleted',
      'class' => 'hosting-error',
    ),
    HOSTING_SITE_DISABLED => array(
      'label' => 'Disabled',
      'class' => 'hosting-disable',
    ),
  );
  if (!is_null($type)) {

    // Return just the $type
    $return = array();
    foreach ($codes as $code => $types) {
      $return[$code] = $types[$type];
    }
    return $return;
  }
  else {

    // Return everything
    return $codes;
  }
}

/**
 * Implementation of hook_allow_domain().
 *
 * @see hosting_domain_allowed()
 */
function hosting_site_allow_domain($url, $params = array()) {
  $query = "SELECT COUNT(n.nid) FROM {node} n \n    JOIN {hosting_site} h ON n.nid = h.nid\n    WHERE type='site' AND title='%s' AND h.status <> %d ";
  $args[] = $url;
  $args[] = HOSTING_SITE_DELETED;
  if (isset($params['nid'])) {
    $query .= ' AND n.nid <> %d';
    $args[] = $params['nid'];
  }
  $result = !db_result(db_query($query, $args));
  return $result;
}
function hosting_site_task_status($nid) {
  return hosting_task_status_output('nid', $nid, 'install');
}

/**
 * Define the classes that correspond to the site status.
 * @see _hosting_site_status()
 */
function _hosting_site_list_class($node, $verified = null) {
  $status = is_numeric($node) ? $node : $node->site_status;
  $classes = hosting_site_status_codes('class');
  if ($status == HOSTING_SITE_ENABLED && !$verified) {
    return 'hosting-warning';
  }
  return $classes[$status];
}

/**
 * Views integration
 */
function hosting_site_views_api() {
  return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'hosting_site') . '/views',
  );
}

/**
 * Theme function for install profile item.
 */
function theme_hosting_site_profile($profile, $html = FALSE) {
  if ($html) {
    return "{$profile->title} <em>({$profile->short_name})</em>";
  }
  return "{$profile->title} ({$profile->short_name})";
}

/**
 * Control block visibility.
 */
function hosting_site_client_list_block_visibility() {
  global $user;
  $node = menu_get_object();
  $menu_item = menu_get_item();
  if (!empty($node) && $menu_item['number_parts'] == 2) {
    return $node->type == 'client' && !user_access('administer clients', $user);
  }
  return FALSE;
}

/**
 * Control block visibility.
 */
function hosting_site_client_admin_block_visibility() {
  global $user;
  $node = menu_get_object();
  $menu_item = menu_get_item();
  if (!empty($node) && $menu_item['number_parts'] == 2) {
    return $node->type == 'client' && user_access('administer clients', $user);
  }
  return FALSE;
}

/**
 * Control block visibility.
 */
function hosting_site_profile_block_visibility() {
  $node = menu_get_object();
  $menu_item = menu_get_item();
  if (!empty($node) && $menu_item['number_parts'] == 2) {
    return $node->type == 'package' && $node->package_type == 'profile';
  }
  return FALSE;
}

Functions

Namesort descending Description
hosting_get_sites_by_status Retrieve sites on a specific platform, with a specific status
hosting_get_site_by_url Retrieve a node based on the url
hosting_import_site Helper function to generate update a site node during import.
hosting_site_access Implementation of hook_access
hosting_site_add_by_platform Page callback for Site add by platform.
hosting_site_add_by_platform_access Access callback for Site add by platform.
hosting_site_allow_domain Implementation of hook_allow_domain().
hosting_site_client_admin_block_visibility Control block visibility.
hosting_site_client_list_block_visibility Control block visibility.
hosting_site_count Returns a count of sites.
hosting_site_get_port Retrieve the port the site will be available on, so we can redirect.
hosting_site_goto Menu callback to go to your site.
hosting_site_hosting_tasks Implementation of hook_hosting_tasks
hosting_site_menu Implementation of hook_menu()
hosting_site_node_load Implementation of hook_load().
hosting_site_node_operations Implements hook_node_operations().
hosting_site_op_backup Callback for site backup operation.
hosting_site_op_delete Callback for site verify operation.
hosting_site_op_disable Callback for site verify operation.
hosting_site_op_enable Callback for site verify operation.
hosting_site_op_login_reset Callback for site verify operation.
hosting_site_op_verify Callback for site verify operation.
hosting_site_perm Implementation of hook_perm
hosting_site_profile_block_visibility Control block visibility.
hosting_site_status_codes Define the status type labels and classes.
hosting_site_task_status
hosting_site_theme Implements hook_theme().
hosting_site_views_api Views integration
theme_hosting_site_goto_link Theme function for site link.
theme_hosting_site_profile Theme function for install profile item.
_hosting_site_form_check
_hosting_site_goto_link Generate a link allowing the user to log into their new site, or simply go to the site front page if the link has expired.
_hosting_site_list_class Define the classes that correspond to the site status.
_hosting_site_status Define the status types of a site
_hosting_site_url Get site's URL.

Constants

Namesort descending Description
HOSTING_SITE_DELETED This site is deleted from the backend.
HOSTING_SITE_DISABLED This site is disabled.
HOSTING_SITE_ENABLED This site is created and enabled in the backend.
HOSTING_SITE_QUEUED This site is queued for creation.