You are here

hosting_quota.module in Hostmaster (Aegir) 6

Implement quota's for the resource used by client.

File

modules/hosting/quota/hosting_quota.module
View source
<?php

/**
 * @file Implement quota's for the resource used by client.
 */

/**
 * Implements hook_perm().
 */
function hosting_quota_perm() {
  return array(
    'edit all quotas',
    'view all quotas',
    'view own quota',
  );
}

/**
 * Implements hook_menu
 */
function hosting_quota_menu() {
  $items = array();
  $items['admin/hosting/quotas'] = array(
    'title' => t('Quotas'),
    'description' => t('Aegir client quotas'),
    'page callback' => 'hosting_quota_admin_client_list',
    'access arguments' => array(
      'view all quotas',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'hosting_quota.admin.inc',
  );
  $items['admin/hosting/quotas/list'] = array(
    'title' => t('List Client Quotas'),
    'description' => t('Listing of all client quotas'),
    'access arguments' => array(
      'view all quotas',
    ),
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'file' => 'hosting_quota.admin.inc',
  );
  $items['admin/hosting/quotas/defaults'] = array(
    'title' => t('Default Client Quotas'),
    'description' => t('Set defaults for client quotas'),
    'access arguments' => array(
      'edit all quotas',
    ),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'hosting_quota_admin_defaults_form',
    ),
    'type' => MENU_LOCAL_TASK,
    'file' => 'hosting_quota.admin.inc',
  );
  return $items;
}

/**
 * Get info about hosting quotas
 *
 * We call here every declaration of hook_hosting_quota_resource
 *
 * @param $resource string
 *   The name of the requested resource
 * @return
 *   A multidimensional array containing the resource, or false if the provided resource does not validate
 */
function hosting_quota_get($resource) {
  $all_resources = module_invoke_all('hosting_quota_resource');
  if (in_array($resource, array_keys($all_resources))) {
    return $all_resources[$resource];
  }
  else {

    // $resource is not valid, so generate an error
    watchdog('hosting_quota', 'Invalid resource called', array(), WATCHDOG_ERROR);
    return FALSE;
  }
}

/**
 * Get the usage for the specified resource
 *
 * This function does not always return a human readable value - in some
 * cases the value may be in bits or bytes, and needs the appropriate
 * hook_hosting_quota_render_resource function to be called in order to 
 * be readable.
 *
 * @param $client int
 *   The nid of the client node
 * @param $resource string
 *   The machine name of the resource, or a resource as returned by hosting_quota_get
 * @param $start string
 *   Optional start date of the checking perios, defaults to 1st of last month
 * @param $end string
 *   Optional end date of the checked period, defaults to 1st of this month
 * @return
 *   An integer representing the quota usage
 */
function hosting_quota_get_usage($client, $resource, $start = NULL, $end = NULL) {
  $quota_usage = 0;

  // Set up some default dates for the last month if necessary
  if (!$start || !$end) {
    $end = date('Y-m-d', mktime(0, 0, 0, date("m"), 1, date("Y")));
    $start = date('Y-m-d', mktime(0, 0, 0, date("m") - 1, 1, date("Y")));
  }

  // Get the resource info if necessary
  if (!is_array($resource)) {
    $resource = hosting_quota_get($resource);
  }
  $resource_name = key($resource);
  $resource = $resource[$resource_name];

  // We're finally ready to fetch the usage info!
  if ($resource['module']) {
    $quota_usage = module_invoke($resource['module'], 'hosting_quota_get_usage', $client, $resource_name, $start, $end);
  }
  return $quota_usage;
}

/**
 * Rendering function for quotas
 *
 * @param $resource
 *   Either a resource retrieved via hosting_quota_get or the machine name of a resource
 * @param $usage int
 *   The usage as returned by hosting_quota_get_usage
 * @return
 *   The rendered usage string
 */
function hosting_quota_resource_render($resource, $usage) {
  $rendered_usage = '';
  if (!is_array($resource)) {
    $resource = hosting_quota_get($resource);
  }
  $resource_name = key($resource);
  $resource = $resource[$resource_name];
  if ($resource['module']) {
    $rendered_usage = module_invoke($resource['module'], 'hosting_quota_resource_render', $resource_name, $usage);
  }
  return $rendered_usage;
}

/**
 * Set the hosting quota for a given resource.
 *
 * @param $client
 *   The nid of the client node.
 * @param $resource
 *   The machine name of the resource.
 * @param $value
 *   The new value for the resource.
 */
function hosting_quota_set_limit($client, $resource, $value) {
  if (db_result(db_query("SELECT COUNT(*) FROM {hosting_client_quota} WHERE client = %d AND resource = '%s'", $client, $resource))) {
    db_query("UPDATE {hosting_client_quota} SET value = '%s' WHERE client = %d AND resource = '%s'", $value, $client, $resource);
  }
  else {
    db_query("INSERT INTO {hosting_client_quota} (client, resource, value) VALUES (%d, '%s', '%s')", $client, $resource, $value);
  }
}

/**
 * Quickly check if a given quota has been exceeded
 *
 * @param $client int
 *   The nid of the client node
 * @param $resource string
 *   The machine name of the resource, or a resource as returned by hosting_quota_get
 * @param $start string
 *   Optional start date of the checking perios, defaults to 1st of last month
 * @param $end string
 *   Optional end date of the checked period, defaults to 1st of this month
 * @return
 *   True if the limit is higher than usage, false otherwise, or null if the resource could not be checked
 */
function hosting_quota_check($client, $resource, $start = NULL, $end = NULL) {

  // Set up some default dates for the last month if necessary
  if (!$start || !$end) {
    $end = date('Y-m-d', mktime(0, 0, 0, date("m"), 1, date("Y")));
    $start = date('Y-m-d', mktime(0, 0, 0, date("m") - 1, 1, date("Y")));
  }

  // Get info about the resource if necessary
  if (!is_array($resource)) {
    $resource = hosting_quota_get($resource);
  }
  $resource_name = key($resource);
  $resource = $resource[$resource_name];

  // Get usage and limit for the selected resource
  if ($resource['module']) {
    $resource_usage = module_invoke($resource['module'], 'hosting_quota_get_usage');
    $resource_limit = db_result(db_query('SELECT value FROM {hosting_client_quota} WHERE client = %d AND resource = "%s"', $client, $resource_name));

    // Return the appropriate values
    if ($resource_limit > $resource_usage) {
      return TRUE;
    }
    else {
      return FALSE;
    }
  }
  return NULL;
}

/**
 * Get the rendered usage and info for all resources
 *
 * @param $client int
 *   The nid of the client node
 * @param $start string
 *   Optional start date of the checking perios, defaults to 1st of last month
 * @param $end string
 *   Optional end date of the checked period, defaults to 1st of this month
 * @return
 *   An array of info about the clients quotas
 */
function hosting_quota_get_all_info($client, $start = NULL, $end = NULL) {
  static $quota_info;
  if (!isset($quota_info)) {
    $quota_info = array();

    // Set up some default dates for the last month if necessary
    if (!$start || !$end) {
      $end = date('Y-m-d', mktime(0, 0, 0, date("m"), 1, date("Y")));
      $start = date('Y-m-d', mktime(0, 0, 0, date("m") - 1, 1, date("Y")));
    }
    $all_resources = module_invoke_all('hosting_quota_resource');
    foreach ($all_resources as $resource_name => $resource_data) {

      // First read in the info from the resource
      $quota_info[$resource_name] = $resource_data;

      // We have to format this way to to dependencies in quota imps
      $resource = array(
        $resource_name => $resource_data,
      );

      // Get usage info
      $quota_info[$resource_name]['usage'] = hosting_quota_get_usage($client, $resource, $start, $end);

      // Fetch info about the quota limit directly from the db
      $quota_info[$resource_name]['limit'] = db_result(db_query('SELECT value FROM {hosting_client_quota} WHERE client = %d AND resource = "%s"', $client, $resource_name));

      // Render both limits and usage
      $quota_info[$resource_name]['rendered usage'] = hosting_quota_resource_render($resource, $quota_info[$resource_name]['usage']);
      $quota_info[$resource_name]['rendered limit'] = hosting_quota_resource_render($resource, $quota_info[$resource_name]['limit']);
    }
  }
  return $quota_info;
}

/**
 * Implements hook_nodeapi().
 */
function hosting_quota_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  global $user;
  if ($node->type == 'client') {
    switch ($op) {
      case 'insert':
      case 'update':
        if (user_access('edit all quotas')) {
          foreach ($node as $field => $value) {
            if (substr($field, 0, 6) == 'quota-') {
              $quota = substr($field, 6);

              // If no value was entered use the default value for this resource
              if (!$value) {
                $value = variable_get("hosting_quota_default_{$quota}", 0);
              }
              hosting_quota_set_limit($node->nid, $quota, $value);
            }
          }
        }
        break;
      case 'load':
        $node->quota = hosting_quota_get_all_info($node->nid);
        break;
      case 'view':
        $allowed_clients = array_keys(hosting_get_client_from_user($user->uid));
        if (user_access('view all quotas') || in_array($node->nid, $allowed_clients) && user_access('view own quota')) {
          $node->content['info']['quota'] = array(
            '#type' => 'item',
            '#title' => 'Quota',
            '#value' => theme('hosting_quota_client', $node),
            '#weight' => 5,
          );
        }
        break;
    }
  }
}

/**
 * Insert edit controls for the hosting quotas into the client edit form
 */
function hosting_quota_form_alter(&$form, $form_state, $form_id) {
  if (user_access('edit all quotas') && isset($form['type']) && isset($form['#node']) && 'client_node_form' == $form_id) {
    $node = $form['#node'];
    if (!($quota_info = $node->quota)) {
      $quota_info = module_invoke_all('hosting_quota_resource');
    }
    $form['quota'] = array(
      '#type' => 'fieldset',
      '#title' => t('Client quota settings'),
      '#access' => user_access('edit all quotas'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    foreach ($quota_info as $resource => $quota) {
      if (!$quota['limit']) {
        $quota['limit'] = variable_get("hosting_quota_default_{$resource}", 0);
      }
      $form['quota']['quota-' . $resource] = array(
        '#title' => $quota['title'],
        '#description' => $quota['description'],
        '#type' => 'textfield',
        '#default_value' => $quota ? $quota['limit'] : 0,
      );

      // Validate that a number was submitted for the quota
      $form['#validate'][] = 'hosting_quota_numeric_value';
    }
  }
}

/**
 * Validate that quota values are numeric
 */
function hosting_quota_numeric_value($form, $form_state) {
  foreach ($form_state['values'] as $key => $value) {
    if (substr($key, 0, 5) == 'quota' && !is_numeric($value)) {
      form_set_error($key, 'You must set a number as a quota value!');
    }
  }
}

/**
 * Implements hook_theme().
 */
function hosting_quota_theme($existing, $resource, $theme, $path) {
  return array(
    'hosting_quota_client' => array(
      'arguments' => array(
        'node' => NULL,
      ),
    ),
    'hosting_quota_admin_list' => array(
      'arguments' => array(
        'client_quotas' => array(),
        'resources' => array(),
        'items_per_page' => 25,
      ),
    ),
  );
}

/**
 * Theme the admin list of client quotas
 *
 * @param $client_quotas array
 *   The client_quotas provided by hosting_quota_admin_client_list
 * @param $resources array
 *   The array of info about resources
 */
function theme_hosting_quota_admin_list($client_quotas, $resources, $items_per_page = 25) {
  $header = array(
    t('Client'),
  );
  $rows = array();
  foreach ($resources as $resource) {
    $header[] = t('@resource (Used / Limit)', array(
      '@resource' => $resource['title'],
    ));
  }
  foreach ($client_quotas as $client_nid => $quotas) {
    $row = array();
    $row[] = l($quotas['name'], "node/{$client_nid}");
    foreach ($resources as $resource => $resource_info) {

      // Provide a visual indication if the usage is over the limit
      if ($quotas[$resource]['usage'] > $quotas[$resource]['limit']) {
        $row[] = array(
          'data' => "{$quotas[$resource]['rendered usage']} / {$quotas[$resource]['rendered limit']}",
          'class' => 'warning',
        );
      }
      else {
        $row[] = "{$quotas[$resource]['rendered usage']} / {$quotas[$resource]['rendered limit']}";
      }
    }
    $rows[] = $row;
  }
  return '<p>' . t('Usage information for the last month.') . '</p>' . theme('table', $header, $rows) . theme('pager', array(), $items_per_page);
}

/**
 * Theme the client quota information.
 *
 * @param $node
 *   The client node object being themed.
 */
function theme_hosting_quota_client($node) {
  if (!empty($node->quota)) {
    $header = array(
      t('Resource'),
      t('Used'),
      t('Quota'),
    );
    foreach ($node->quota as $resource => $value) {
      $row = array();
      $row[] = $value['title'];
      $row[] = $value['rendered usage'];
      $row[] = $value['rendered limit'];
      $rows[] = $row;
    }
    return theme('table', $header, $rows);
  }
  return '';
}

Functions

Namesort descending Description
hosting_quota_check Quickly check if a given quota has been exceeded
hosting_quota_form_alter Insert edit controls for the hosting quotas into the client edit form
hosting_quota_get Get info about hosting quotas
hosting_quota_get_all_info Get the rendered usage and info for all resources
hosting_quota_get_usage Get the usage for the specified resource
hosting_quota_menu Implements hook_menu
hosting_quota_nodeapi Implements hook_nodeapi().
hosting_quota_numeric_value Validate that quota values are numeric
hosting_quota_perm Implements hook_perm().
hosting_quota_resource_render Rendering function for quotas
hosting_quota_set_limit Set the hosting quota for a given resource.
hosting_quota_theme Implements hook_theme().
theme_hosting_quota_admin_list Theme the admin list of client quotas
theme_hosting_quota_client Theme the client quota information.