You are here

environment.module in Environment 7

Same filename and directory in other branches
  1. 8 environment.module
  2. 6 environment.module

Module for handling changes in server environments

File

environment.module
View source
<?php

/**
 * @file
 * Module for handling changes in server environments
 */

/**
 * Implements hook_menu().
 */
function environment_menu() {
  $items = array();
  $items['admin/config/system/environment'] = array(
    'title' => 'Environment',
    'description' => 'Settings for Environment.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'environment_admin_settings',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'file' => 'environment.admin.inc',
  );
  $items['admin/config/system/environment/settings'] = array(
    'title' => 'Environment',
    'type' => MENU_DEFAULT_LOCAL_TASK,
    'weight' => -10,
  );
  $items['admin/config/system/environment/switch/%environment'] = array(
    'title' => 'Environment Switch',
    'description' => 'Switch the current environment.',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'environment_switch_confirm',
      4,
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'file' => 'environment.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_environment().
 */
function environment_environment() {
  return array(
    'production' => array(
      'label' => t('Production'),
      'allowed' => array(
        'default' => TRUE,
      ),
    ),
    'development' => array(
      'label' => t('Development'),
      'allowed' => array(
        'default' => FALSE,
      ),
    ),
  );
}

/**
 * Implements hook_environment_workflow().
 */
function environment_environment_workflow() {
  return array(
    'default' => array(
      'label' => t('Default'),
      'description' => '',
    ),
  );
}

/**
 * Check if something is allowed in the current environment.
 *
 * @param string $name
 *   Name of the thing to check if allowed, eg. function.
 * @param string $category
 *   Optional; category of the thing to check for, eg. name of module.
 *   Defaults to 'other'.
 * @param bool $default
 *   Optional; what the default should be if no environment value is found.
 *   Defaults to FALSE.
 * @param string $workflow
 *   Optional; specify the workflow state to check for allowance.
 *
 * @return bool
 *   TRUE or FALSE for whether the thing is allowed.
 */
function environment_allowed($name, $category = 'other', $default = FALSE, $workflow = 'default') {
  $env = environment_current($workflow, NULL, TRUE);
  if (!empty($env)) {
    if (!empty($env[$category])) {
      if (isset($env[$category][$name])) {
        $result = $env[$category][$name];
      }
      elseif (isset($env[$category]['default'])) {
        $result = $env[$category]['default'];
      }
    }
    if (!isset($result) && isset($env['default'])) {
      $result = $env['default'];
    }
  }
  if (!isset($result)) {
    $result = $default;
  }
  return $result;
}

/**
 * Switches between two environments.
 *
 * @param string $target_env
 *   Name of the environment to change to.
 * @param bool $force
 *   (optional) Whether to trigger a change even if the environment is the
 *   currently set one. Defaults to FALSE.
 *
 * @return bool
 *   Return TRUE if successful.
 */
function environment_switch($target_env, $force = FALSE, $clear_cache = TRUE) {
  $result = FALSE;
  $messages = array();
  $target_state = environment_load($target_env);
  $workflow = $target_state['workflow'];
  $current_env = environment_current($workflow);
  $override = variable_get('environment_override', '');
  if (!$force && $current_env == $target_env) {
    drupal_set_message(t("The current environment is already set to '!environment'.", array(
      '!environment' => $target_env,
    )), 'notice');
    $result = TRUE;

    // This option is only available in drush.
    if (function_exists('drush_print')) {
      drush_print("To force the environment switch to run anyway, use the '--force' flag.");
    }
  }
  if (!$force && !empty($override)) {
    drupal_set_message(t("The current environment is overriden with '!override'.", array(
      '!override' => $override,
    )), 'error');

    // This option is only available in drush.
    if (function_exists('drush_print')) {
      drush_print("To force the environment switch to run anyway, use the '--force' flag.");
    }
  }
  elseif ($current_env != $target_env || $force) {
    if (empty($target_state)) {
      drupal_set_message(t('Environment !environment does not exist.', array(
        '!environment' => $target_env,
      )), 'warning');
    }
    else {
      environment_set($target_env);
      module_invoke_all('environment_switch', $target_env, $current_env, $workflow);
      if ($clear_cache) {
        drupal_flush_all_caches();
        drupal_set_message('Cleared cache.');
      }
      $result = TRUE;
    }
  }
  return $result;
}

/**
 * Gets the current environment.
 *
 * @param string $workflow
 *   (default: default) Specify an environment workflow to check. If NULL, will
 *   return the current environment state for each workflow. Default workflow
 *   will check environment states not assigned an explicit workflow, this
 *   maintains backwards compatibility.
 * @param string $default
 *   Optional; defaults to NULL. Specify the default value if the current
 *   environment cannot be identified.
 * @param bool $load
 *   (default: FALSE) If TRUE, loads the full environment definition.
 */
function environment_current($workflow = 'default', $default = NULL, $load = FALSE) {
  $current = variable_get('environment', array());
  if (!is_array($current)) {
    $current = array(
      'default' => $current,
    );
  }
  if (is_null($workflow)) {
    $current = empty($current) ? $default : $current;
    return $load ? environment_load($current) : $current;
  }
  elseif (isset($current[$workflow])) {
    $current[$workflow] = empty($current[$workflow]) ? $default : $current[$workflow];
    return $load ? environment_load($current[$workflow]) : $current[$workflow];
  }
  return $default;
}

/**
 * Save the new environment to it's assigned workflow.
 *
 * @param string $new_env
 *   Machine name of the new system environment. If environment has a workflow.
 */
function environment_set($new_env) {
  $environment = variable_get('environment', array());
  $new_state = environment_load($new_env);

  // Maintain backwards compatibility with pre-workflow systems.
  if (!is_array($environment)) {
    $environment = array(
      'default' => $environment,
    );
  }
  $environment[$new_state['workflow']] = $new_state['name'];
  variable_set('environment', $environment);
}

/**
 * Fetches all available environments.
 *
 * @param string $env
 *   (optional) Name of the environment. If NULL, will return all environments.
 *   If an array, will return all environments specified in the array.
 * @param bool $reset
 *   (default: FALSE) Reset the static cache and collect new data.
 *
 * @return array
 *   Return all environments or the specified environment.
 */
function environment_load($env = NULL, $reset = FALSE) {
  static $environments;
  if (!isset($environments) || $reset) {
    $environments = module_invoke_all('environment');
    $environments = array_merge($environments, variable_get('environment_definitions', array()));
    foreach ($environments as $name => $environment) {
      $environments[$name]['name'] = $name;
      if (!isset($environments[$name]['workflow'])) {
        $environments[$name]['workflow'] = 'default';
      }
    }
    drupal_alter('environment', $environments);
  }
  if (empty($env)) {
    return $environments;
  }
  elseif (is_array($env)) {
    return array_intersect_key($environments, array_flip($env));
  }
  else {
    return isset($environments[$env]) ? $environments[$env] : FALSE;
  }
}

/**
 * Get the current assortment of Workflows.
 *
 * @param string $name
 *   Name of the workflow to retrieve information on.
 *   Use 'default' to specify default or NULL workflow.
 * @param bool $reset
 *   Optional; reset the static cache.
 *
 * @return array
 *   Workflows.
 */
function environment_load_workflow($name = NULL, $reset = FALSE) {
  static $workflows;
  if (empty($workflows) || $reset) {
    $workflows = module_invoke_all('environment_workflow');
    drupal_alter('environment_workflow', $workflows);
  }
  return isset($name) ? $workflows[$name] : $workflows;
}

/**
 * Provides environment form options.
 *
 * @param string $workflow
 *   Optional; specify the workflow for specific options. Defaults to states
 *   that are not part of an explicit workflow.
 * @param string $prefix
 *   Optional; prefix the environment label with the specified string. Defaults
 *   to no prefix.
 * @param bool $reset
 *   Optional; reset the static cache.
 *
 * @return array
 *   Array of form options in the style of environment => label
 */
function _environment_state_options($workflow = 'default', $prefix = '', $reset = FALSE) {
  static $options;
  if (empty($options) || $reset) {
    $environments = environment_load();
    foreach ($environments as $name => $state) {
      $options[$state['workflow']][$name] = $prefix . $state['label'];
    }
  }
  return empty($options[$workflow]) ? array() : $options[$workflow];
}

/**
 * Build an options widget with all workflows.
 *
 * Options do not need namespacing because environment machine name is unique.
 * If the same environment needs to come up in multiple places, that should be
 * handled by duplicating the definition and changing the machine name.
 *
 * @param bool $reset
 *   Optional; reset the static cache.
 *
 * @return array
 *   Options widget.
 *
 * @see hook_environment
 */
function _environment_state_options_all($reset = FALSE) {
  $options = array();
  $workflows = environment_load_workflow();
  foreach ($workflows as $name => $workflow) {
    $options[$name] = $workflow['label'];
    $w_opts = _environment_state_options($name, TRUE, '-- ', $reset);
    $options = array_merge($options, $w_opts);
  }
  return $options;
}

/**
 * Implements hook_token_list().
 */
function environment_token_list($type = 'all') {
  $tokens = array();
  if ($type == 'all' || $type == 'global') {
    foreach (environment_load_workflow() as $name => $workflow) {
      $tokens['global']['environment_' . $name] = t('The current environment state for @title workflow.', array(
        '@title' => $workflow['label'],
      ));
      $tokens['global']['environment_' . $name . '-label'] = t('The human-readable version of the current environment state for @title workflow.', array(
        '@title' => $workflow['label'],
      ));
    }
  }
  return $tokens;
}

/**
 * Implements hook_token_values().
 */
function environment_token_values($type, $object = NULL, $options = array()) {
  $values = array();
  if ($type == 'global') {
    foreach (environment_load_workflow() as $name => $workflow) {
      $state = environment_current($name, NULL, TRUE);
      $values['environment_' . $name] = $state['name'];
      $values['environment_' . $name . '-label'] = $state['label'];
    }
  }
  return $values;
}

Functions

Namesort descending Description
environment_allowed Check if something is allowed in the current environment.
environment_current Gets the current environment.
environment_environment Implements hook_environment().
environment_environment_workflow Implements hook_environment_workflow().
environment_load Fetches all available environments.
environment_load_workflow Get the current assortment of Workflows.
environment_menu Implements hook_menu().
environment_set Save the new environment to it's assigned workflow.
environment_switch Switches between two environments.
environment_token_list Implements hook_token_list().
environment_token_values Implements hook_token_values().
_environment_state_options Provides environment form options.
_environment_state_options_all Build an options widget with all workflows.