You are here

hosting_package.module in Hostmaster (Aegir) 6

File

modules/hosting/package/hosting_package.module
View source
<?php

/**
 * @file
 *   Defines package node types
 *
 * Packages are somewhat analogous to Drupal.org projects. i.e.: components that
 * can be installed onto Drupal sites.
 */
require_once 'hosting_package.instance.inc';
function _hosting_package_types() {
  return array(
    'profile' => t('Installation Profiles'),
    'module' => t('Modules'),
    'theme' => t('Themes'),
  );
}

/**
 * Implementation of hook_node_info().
 */
function hosting_package_node_info() {

  #package management
  $types["package"] = array(
    "type" => 'package',
    "name" => 'Package',
    "module" => 'hosting_package',
    "has_title" => FALSE,
    "title_label" => '',
    "description" => hosting_node_help("package"),
    "has_body" => 0,
    "body_label" => '',
    "min_word_count" => 0,
  );
  return $types;
}

/**
 * Implementation of hook_menu().
 */
function hosting_package_menu() {
  $items = array();
  $items['node/%hosting_package_node/packages'] = array(
    'title' => 'Packages',
    'description' => 'List of packages available for this platform',
    'page callback' => 'hosting_package_list',
    'page arguments' => array(
      1,
    ),
    'type' => MENU_LOCAL_TASK,
    'access arguments' => array(
      'view package',
    ),
    'weight' => 1,
  );
  $items['node/%hosting_package_node/packages/all'] = array(
    'title' => 'All packages',
    'description' => 'List of all packages',
    'page callback' => 'hosting_package_list',
    'page arguments' => array(
      1,
    ),
    'access arguments' => array(
      'view package',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -1,
  );
  $x = 0;
  foreach (_hosting_package_types() as $type => $description) {
    $items['node/%hosting_package_node/packages/' . $type] = array(
      'title' => $description,
      'description' => $description,
      'page callback' => 'hosting_package_list',
      'page arguments' => array(
        1,
        $type,
      ),
      'access arguments' => array(
        'view package',
      ),
      'type' => MENU_LOCAL_TASK,
      'weight' => $x++,
    );
  }
  return $items;
}
function hosting_package_node_load($arg) {
  if (!is_numeric($arg)) {
    return FALSE;
  }
  if ($node = node_load($arg)) {
    if (in_array($node->type, array(
      'site',
      'platform',
    ))) {
      return $node;
    }
  }
  return FALSE;
}

/**
 * Implementation of hook_perm().
 */
function hosting_package_perm() {
  return array(
    'create package',
    'view package',
    'edit package',
    'delete package',
  );
}

/**
 * Implementation of hook_access().
 */
function hosting_package_access($op, $node, $account) {
  if (hosting_feature('client')) {

    // we rely on hosting_node_grants() instead of global configuration
    return NULL;
  }
  switch ($op) {
    case 'create':
      return user_access('create package', $account);
      break;
    case 'view':
      return user_access('view package', $account);
      break;
    case 'update':
      return user_access('edit package', $account);
      break;
    case 'delete':
      return user_access('delete package', $account);
      break;
    default:
      break;
  }
}
function hosting_get_profiles($platform = NULL, $field = 'title') {
  $profiles = array();
  if (!is_null($platform)) {
    $instances = hosting_package_instances_load(array(
      'i.rid' => $platform,
      'p.package_type' => 'profile',
      'n.status' => 1,
    ));
    foreach ($instances as $iid => $instance) {
      $profiles[$instance->package_id] = $instance->{$field};
    }
  }
  else {
    $instances = hosting_package_instances_load(array(
      'p.package_type' => 'profile',
      'n.status' => 1,
      'r.type' => 'platform',
    ));
    foreach ($instances as $iid => $instance) {
      $profiles[$instance->package_id] = $instance->{$field};
    }
  }
  return $profiles;
}
function hosting_get_profile_platforms($profile, $check_old_short_name = FALSE) {
  $defaults = array(
    'default',
    'standard',
    'minimal',
  );
  $platforms = array();
  $instances = hosting_package_instances_load(array(
    'i.package_id' => $profile,
    'n.status' => 1,
    'r.status' => 1,
    'r.type' => 'platform',
  ));
  if ($check_old_short_name) {
    $instances = array_merge($instances, hosting_package_instances_load(array(
      'p.old_short_name' => $instances[key($instances)]->short_name,
      'n.status' => 1,
      'r.status' => 1,
      'r.type' => 'platform',
    )));
  }
  foreach ($instances as $iid => $instance) {
    $platform = node_load($instance->rid);

    // this is one of the default profiles
    if (in_array($instance->short_name, $defaults) && sizeof(array_diff(array_values($platform->profiles), $defaults)) && variable_get('hosting_ignore_default_profiles', FALSE)) {

      // there are other profiles available on this platform. skip this.
      continue;
    }
    if ($platform->platform_status != HOSTING_PLATFORM_DELETED) {
      $platforms[$instance->rid] = $platform->title;
    }
  }
  return $platforms;
}
function hosting_get_profile_languages($profile = NULL, $platform = NULL) {
  $languages['en'] = _hosting_language_name('en');
  if ($profile && $platform) {
    $instance = hosting_package_instance_load(array(
      'i.rid' => $platform,
      'i.package_id' => $profile,
    ));
    $languages = array_merge($languages, $instance->languages);
  }
  else {
    $result = db_query("SELECT DISTINCT language FROM {hosting_package_languages}");
    while ($lang = db_fetch_object($result)) {
      $languages[$lang->language] = _hosting_language_name($lang->language);
    }
  }
  return $languages;
}

/**
 * A generic method for finding whichever packages you are looking for.
 *
 * This works similarly to node_load's implementation, but it will only look
 * for fields related to packages.
 *
 * @param
 *    An associated array containing the following properties
 *    - name => A string containing the friendly name of the package
 *    - short_name => The name of the drupal package in the system table
 *    - old_short_name => The name that a package used to be called, for
 *      migration purposes.
 *    - package_type => The type of package. (theme|module|profile|engine)
 */
function _hosting_package_load($param) {

  // Turn the conditions into a query.
  foreach ($param as $key => $value) {
    $cond[] = 'p.' . db_escape_table($key) . " = '%s'";
    $arguments[] = $value;
  }
  $cond = implode(' AND ', $cond);
  $result = db_query('SELECT n.nid FROM {node} n left join {hosting_package} p on n.nid = p.nid WHERE ' . $cond, $arguments);
  while ($nid = db_fetch_object($result)) {
    $return[$nid->nid] = node_load(array(
      'nid' => $nid->nid,
    ));
  }
  if (sizeof($return)) {
    return $return;
  }
  return null;
}
function hosting_get_packages_by_type($type) {
  $result = db_query("SELECT nid FROM {hosting_package} WHERE package_type = '%s'", $type);
  if ($nid = db_result($result)) {
    return node_load($nid);
  }
  return false;
}
function hosting_get_default_profile($default = null) {
  if ($p = hosting_get_package(variable_get('hosting_default_profile', 'default'))) {
    return $p->nid;
  }
  elseif ($p = hosting_get_package('standard')) {
    return $p->nid;
  }
  return $default;
}
function hosting_get_package($short_name) {
  $result = db_query("SELECT nid FROM {hosting_package} WHERE short_name = '%s'", $short_name);
  if ($nid = db_result($result)) {
    return node_load($nid);
  }
  return false;
}

/**
 * Implementation of hook_insert().
 */
function hosting_package_insert($node) {
  db_query("INSERT INTO {hosting_package} (vid, nid, package_type, short_name, old_short_name, description ) VALUES (%d, %d, '%s', '%s', '%s', '%s')", $node->vid, $node->nid, $node->package_type, $node->short_name, $node->old_short_name, $node->description);
}

/**
 * Implementation of hook_update().
 *
 * As an existing node is being updated in the database, we need to do our own
 * database updates.
 */
function hosting_package_update($node) {

  // if this is a new node or we're adding a new revision,
  if (!empty($node->revision)) {
    hosting_package_insert($node);
  }
  else {
    db_query("UPDATE {hosting_package} SET package_type = '%s', short_name = '%s', old_short_name = '%s', description = '%s' WHERE nid=%d", $node->package_type, $node->short_name, $node->old_short_name, $node->description, $node->nid);
  }
}
function hosting_nodeapi_package_delete_revision(&$node) {
  db_query('DELETE FROM {hosting_package} WHERE vid = %d', $node->vid);
}

/**
 * Implementation of hook_delete().
 */
function hosting_package_delete($node) {
  db_query('DELETE FROM {hosting_package} WHERE nid = %d', $node->nid);
}

/**
 * Implementation of hook_load().
 */
function hosting_package_load($node) {
  $additions = db_fetch_object(db_query('SELECT package_type, short_name, old_short_name, description FROM {hosting_package} WHERE vid = %d', $node->vid));
  return $additions;
}

/**
 * Implementation of hook_view().
 */
function hosting_package_view($node, $teaser = FALSE, $page = FALSE) {
  hosting_set_breadcrumb($node);
  $node->content['info']['#prefix'] = '<div id="hosting-package-info">';
  $node->content['info']['package_type'] = array(
    '#type' => 'item',
    '#title' => t('Package Type'),
    '#value' => filter_xss($node->package_type),
  );
  $node->content['info']['short_name'] = array(
    '#type' => 'item',
    '#title' => t('Project Name'),
    '#value' => filter_xss($node->short_name),
  );
  if (!empty($node->old_short_name)) {
    $node->content['info']['old_short_name'] = array(
      '#type' => 'item',
      '#title' => t('Previous Project Name'),
      '#value' => filter_xss($node->old_short_name),
    );
  }
  $node->content['info']['#suffix'] = '</div>';
  if ($node->package_type == 'profile') {
    $node->content['sites_view'] = array(
      '#type' => 'item',
      '#value' => drupal_get_form('hosting_site_list_form', 'profile', $node->nid),
      '#prefix' => '<div id="hosting-site-list">',
      '#suffix' => '</div>',
      '#weight' => 10,
    );
  }
  return $node;
}

/**
 * Return names of the languages available
 */
function _hosting_language_names($languages) {
  foreach ($languages as $language) {

    // Try to use verbose language name
    $return[$language] = _hosting_language_name($language);
  }
  return $return;
}
function _hosting_language_name($language) {
  include_once './includes/locale.inc';
  $locales = _locale_get_predefined_list();
  return $locales[$language][0] . (isset($locales[$language][1]) ? ' ' . t('(@language)', array(
    '@language' => $locales[$language][1],
  )) : '');
}
function _hosting_package_plural_map($key = null) {
  static $plural_map = array(
    'modules' => 'module',
    'themes' => 'theme',
    'profiles' => 'profile',
    'engines' => 'engine',
    'platforms' => 'platform',
  );
  if (is_null($key)) {
    return $plural_map;
  }
  return array_key_exists($key, $plural_map) ? $plural_map[$key] : $key;
}

/**
 * Sync the package and package release nodes with the information
 * retrieved from the verify task
 *
 * @todo Make this prettier.
 */
function hosting_package_sync(&$data) {
  foreach ($data as $plural => $packages) {
    $type = _hosting_package_plural_map($plural);
    foreach ($packages as $short_name => $file) {
      $name = isset($file['info']['name']) ? $file['info']['name'] : $short_name;
      if (!($package = hosting_get_package($short_name))) {

        // Create a new package.
        $package = new stdClass();
        $package->type = 'package';
        $package->uid = 1;
        $package->package_type = $type;
        $package->short_name = $short_name;
        $package->old_short_name = isset($file['info']['old_short_name']) ? $file['info']['old_short_name'] : '';
        $package->status = 1;
      }

      // we only call node save when the title, description changes
      // or when it's a new package.
      if (!isset($package->nid) || isset($package->title) && $package->title != $name || isset($file['info']['description']) && $package->description != $file['info']['description'] || isset($file['info']['old_short_name']) && $package->old_short_name != $file['info']['old_short_name']) {
        $package->title = $name;
        $package->description = isset($file['info']['description']) ? $file['info']['description'] : '';
        $package->old_short_name = isset($file['info']['old_short_name']) ? $file['info']['old_short_name'] : '';
        node_save($package);
      }
      $data[$plural][$short_name]['package_id'] = $package->nid;
    }
  }
}

/**
 * Display a list of packages associated to a node
 * @TODO Add ability to filter by additional fields
 * @TODO Add paging.
 */
function hosting_package_list($ref, $type = null) {
  drupal_set_title(t('Packages on @reference', array(
    '@reference' => $ref->title,
  )));
  $header = array(
    array(
      'data' => t('Status'),
      'field' => 'status',
      'sort' => 'DESC',
    ),
    array(
      'data' => t('Package'),
      'field' => 'short_name',
    ),
    array(
      'data' => t('Release'),
      'field' => 'version',
    ),
    array(
      'data' => t('Package type'),
      'field' => 'package_type',
    ),
  );
  $args[] = $ref->nid;
  if (!is_null($type)) {
    $cond = " AND h.package_type = '%s'";
    $args[] = $type;
  }
  $sql = "SELECT h.nid as 'package', i.status, h.short_name, i.version, h.package_type, i.status FROM {hosting_package} h\n    LEFT JOIN {hosting_package_instance} i ON i.package_id=h.nid WHERE i.rid=%d" . $cond;
  $sql .= tablesort_sql($header);

  // @TODO hide deleted sites
  $result = pager_query(db_rewrite_sql($sql, 'h'), 25, 2, null, $args);
  $view_package_perm = user_access('view package');
  if (!$result) {
    return t('No packages are associated with @reference', array(
      '@reference' => $ref->title,
    ));
  }
  $rows = array();
  while ($package = db_fetch_object($result)) {
    $row_class = $package->status == 1 ? 'hosting-success' : 'hosting-info';
    $row = array();
    $row[] = array(
      'data' => $package->status ? t('Enabled') : t('Available'),
      'class' => 'hosting-status',
    );
    $row[] = $view_package_perm ? l(filter_xss($package->short_name), 'node/' . $package->package) : $package->short_name;
    $row[] = $package->version;
    $row[] = filter_xss($package->package_type);
    $rows[] = array(
      'data' => $row,
      'class' => $row_class,
    );
  }
  return theme('table', $header, $rows, array(
    'class' => 'hosting-table',
  )) . theme('pager', null, 25, 2);
}

/**
 * Implementation of hook_views_api().
 */
function hosting_package_views_api() {
  return array(
    'api' => 2,
    'path' => drupal_get_path('module', 'hosting_package'),
  );
}

Functions

Namesort descending Description
hosting_get_default_profile
hosting_get_package
hosting_get_packages_by_type
hosting_get_profiles
hosting_get_profile_languages
hosting_get_profile_platforms
hosting_nodeapi_package_delete_revision
hosting_package_access Implementation of hook_access().
hosting_package_delete Implementation of hook_delete().
hosting_package_insert Implementation of hook_insert().
hosting_package_list Display a list of packages associated to a node @TODO Add ability to filter by additional fields @TODO Add paging.
hosting_package_load Implementation of hook_load().
hosting_package_menu Implementation of hook_menu().
hosting_package_node_info Implementation of hook_node_info().
hosting_package_node_load
hosting_package_perm Implementation of hook_perm().
hosting_package_sync Sync the package and package release nodes with the information retrieved from the verify task
hosting_package_update Implementation of hook_update().
hosting_package_view Implementation of hook_view().
hosting_package_views_api Implementation of hook_views_api().
_hosting_language_name
_hosting_language_names Return names of the languages available
_hosting_package_load A generic method for finding whichever packages you are looking for.
_hosting_package_plural_map
_hosting_package_types