You are here

hosting_quota.module in Hosting 7.4

Same filename and directory in other branches
  1. 6.2 quota/hosting_quota.module
  2. 7.3 quota/hosting_quota.module

Implement quota's for the resource used by client.

File

quota/hosting_quota.module
View source
<?php

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

/**
 * Implements hook_permission().
 */
function hosting_quota_permission() {
  $permissions = array(
    'edit all quotas' => array(
      'title' => t('edit all quotas'),
    ),
    'view all quotas' => array(
      'title' => t('view all quotas'),
    ),
    'view own quota' => array(
      'title' => t('view own quota'),
    ),
    'bypass all quotas' => array(
      'title' => t('bypass all quotas'),
    ),
  );
  $all_resources = module_invoke_all('hosting_quota_resource');
  foreach ($all_resources as $resource => $data) {
    $permissions["bypass resource {$resource} limit"] = array(
      'title' => t('bypass resource !resource limit', array(
        '!resource' => $resource,
      )),
    );
  }
  return $permissions;
}

/**
 * Implements hook_menu().
 */
function hosting_quota_menu() {
  $items = array();
  $items['admin/hosting/quotas'] = array(
    'title' => 'Quotas',
    'description' => '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' => 'List Client Quotas',
    'description' => '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' => 'Default Client Quotas',
    'description' => '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 array|bool
 *   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
 */

/**
 * @todo Please document this function.
 * @see http://drupal.org/node/1354
 */
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 array|string
 *   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 mixed
 *   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_query("SELECT COUNT(*) FROM {hosting_client_quota} WHERE client = :client AND resource = :resource", array(
    ':client' => $client,
    ':resource' => $resource,
  ))
    ->fetchField()) {
    $id = db_update('hosting_client_quota')
      ->fields(array(
      'value' => $value,
    ))
      ->condition('client', $client)
      ->condition('resource', $resource)
      ->execute();
  }
  else {
    $id = db_insert('hosting_client_quota')
      ->fields(array(
      'client' => $client,
      'resource' => $resource,
      'value' => $value,
    ))
      ->execute();
  }
}

/**
 * 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 bool|null
 *   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_name = $resource;
    $resource = hosting_quota_get($resource);
  }

  // Get usage and limit for the selected resource
  if ($resource['module']) {
    if (user_access("bypass all quotas")) {
      return TRUE;
    }
    if (user_access("bypass resource {$resource_name} limit")) {
      return TRUE;
    }
    $resource_usage = module_invoke($resource['module'], 'hosting_quota_get_usage', $client, $resource_name, $start, $end);
    $resource_limit = db_query('SELECT value FROM {hosting_client_quota} WHERE client = :client AND resource = :resource', array(
      ':client' => $client,
      ':resource' => $resource_name,
    ))
      ->fetchField();

    // 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
 */

/**
 * @todo Please document this function.
 * @see http://drupal.org/node/1354
 */
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_query('SELECT value FROM {hosting_client_quota} WHERE client = :client AND resource = :resource', array(
        ':client' => $client,
        ':resource' => $resource_name,
      ))
        ->fetchField();

      // 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_node_update().
 */
function hosting_quota_node_update($node) {
  if ($node->type == 'client') {
    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);
        }
      }
    }
  }
}

/**
 *  Implements hook_node_insert().
 */
function hosting_quota_node_insert($node) {
  hosting_quota_node_update($node);
}

/**
 *  Implements hook_node_load().
 */
function hosting_quota_node_load($nodes, $types) {
  if (in_array('client', $types)) {
    foreach ($nodes as $nid => $node) {
      if ($node->type == 'client') {
        $nodes[$nid]->quota = hosting_quota_get_all_info($node->nid);
      }
    }
  }
}

/**
 *  Implements hook_node_view().
 */
function hosting_quota_node_view($node, $view_mode, $langcode) {
  global $user;
  if ($node->type == 'client') {
    $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',
        '#markup' => theme('hosting_quota_client', array(
          'node' => $node,
        )),
        '#weight' => 5,
      );
    }
  }
}

/**
 * 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 (!isset($node->quota)) {
      $quota_info = module_invoke_all('hosting_quota_resource');
    }
    else {
      $quota_info = $node->quota;
    }
    $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 (!isset($quota['limit'])) {
        $quota['limit'] = variable_get("hosting_quota_default_{$resource}", 0);
      }
      $form['quota']['quota-' . $resource] = array(
        '#title' => check_plain($quota['title']),
        '#description' => check_plain($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(
      'variables' => array(
        'node' => NULL,
      ),
    ),
    'hosting_quota_admin_list' => array(
      'variables' => array(
        'client_quotas' => array(),
        'resources' => array(),
        'items_per_page' => 25,
      ),
    ),
  );
}

/**
 * Theme the admin list of client quotas
 *
 * @param $variables array
 * @return string
 *   String containing table
 */
function theme_hosting_quota_admin_list($variables) {
  $client_quotas = $variables['client_quotas'];
  $resources = $variables['resources'];
  $items_per_page = $variables['items_per_page'];
  $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' => array(
            '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', array(
    'header' => $header,
    'rows' => $rows,
  )) . theme('pager', array(
    'tags' => array(),
  ));
}

/**
 * Theme the client quota information.
 *
 * @param $variables array
 *
 * @return string
 */
function theme_hosting_quota_client($variables) {
  $node = $variables['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', array(
      'header' => $header,
      'rows' => $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 @todo Please document this function.
hosting_quota_get_usage @todo Please document this function.
hosting_quota_menu Implements hook_menu().
hosting_quota_node_insert Implements hook_node_insert().
hosting_quota_node_load Implements hook_node_load().
hosting_quota_node_update Implements hook_node_update().
hosting_quota_node_view Implements hook_node_view().
hosting_quota_numeric_value Validate that quota values are numeric
hosting_quota_permission Implements hook_permission().
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.