You are here

vars.module in Variable API 7

Same filename and directory in other branches
  1. 6.2 vars.module
  2. 6 vars.module
  3. 7.2 vars.module

Implement an API to handle persistent variables.

File

vars.module
View source
<?php

/**
 * @file
 * Implement an API to handle persistent variables.
 */
class Vars implements ArrayAccess {

  /**
   * The constants for the type of variable saved in the database.
   */
  const VARS_DYNAMIC = 1;
  const VARS_NODE_TYPE = 3;
  protected $module;
  protected $sysVars = array();

  /**
   * Constructs a Vars object.
   *
   * @param $module
   *   The name of the module that implements the class.
   * @param $options
   *   An array of options. The currently defined option is 'sysVars', used to
   *   define the default values for variables defined from modules not using
   *   Variable API.
   */
  public function __construct($module = '', array $options = array()) {
    $this->module = $module;
    if (!empty($options['sysVars'])) {
      $this->sysVars = $options['sysVars'];
    }
  }

  /**
   * Returns the default values for the variable passed as argument.
   *
   * Returns the default values for the variable passed as argument. It is used
   * to get the default value for variables defined in a module that doesn't
   * use the Variable API module.
   *
   * @param $name
   *   The name of the variable.
   * @return
   *   The default value for the variable, or NULL if it is not found.
   */
  protected function defaultValue($name) {
    return isset($this->sysVars[$name]) ? $this->sysVars[$name] : NULL;
  }

  /**
   * Deletes the specified persistent variables.
   *
   * Deletes the specified persistent variables from memory, and from the
   * database.
   *
   * @param $names
   *   An array of persistent variable names.
   *
   * @see Vars::renameVariables()
   */
  public static function deleteVariables(array $names) {
    global $conf;
    $count = 0;
    foreach ($names as $name) {
      unset($conf[$name]);
      $count++;
    }
    if ($count) {
      db_delete('variable')
        ->condition('name', $names, 'IN')
        ->execute();
      cache_clear_all('variables', 'cache_bootstrap');
    }
  }

  /**
   * Returns the default value for the variables used by the module.
   *
   * A module using Variable API should normally implement a class derived
   * from Vars, and overwrite this method.
   *
   * @return
   *  An array containing information about the implemented persistent
   *  variables.
   *
   * @see Vars::saveDefaults()
   */
  protected function getDefaults() {
    return array();
  }

  /**
   * Loads the default value for all the variables respecting some conditions.
   *
   * This function is used to load the default value for all the variables
   * respecting some conditions. The function should not be called from
   * modules; it's thought to be used only from the Variable API module.
   *
   * @param $cid
   *   The cache ID of the data to retrieve.
   * @param $conditions
   *   A DatabaseCondition object for the conditions the persistent variables
   *   must respect.
   * @return
   *   An array containing information about the default value for the
   *   persistent variables.
   *
   * @see vars_node_type()
   */
  public static function loadDefaults($cid, DatabaseCondition $conditions = NULL) {
    if ($cache = cache_get($cid, 'cache_vars')) {
      return $cache->data;
    }
    if ($cid == 'node_type') {
      $conditions = db_and()
        ->condition('vd.flags', Vars::VARS_NODE_TYPE);
    }
    $defaults = array();
    $query = db_select('variable_default', 'vd')
      ->fields('vd', array(
      'name',
      'value',
      'flags',
    ));
    if (isset($conditions)) {
      $query
        ->condition($conditions);
    }
    foreach ($query
      ->execute() as $var) {
      $index = $var->flags ? 'dynamic' : 'static';
      $defaults[$index][$var->name] = unserialize($var->value);
    }
    drupal_alter('vars_default_values', $defaults, $cid);
    cache_set($cid, $defaults, 'cache_vars');
    return $defaults;
  }

  /**
   * Implements ArrayAccess::offsetExists().
   */
  public function offsetExists($offset) {
    $value = $this
      ->offsetGet($offset);
    return isset($value);
  }

  /**
   * Implements ArrayAccess::offsetGet().
   */
  public function offsetGet($offset) {
    global $conf;
    if (isset($conf[$offset])) {
      return $conf[$offset];
    }
    $value = $this
      ->defaultValue($offset);
    if (isset($value)) {
      return $value;
    }
    $defaults =& drupal_static('vars_default_values', array());
    if (isset($defaults['static'][$offset])) {
      return $defaults['static'][$offset];
    }
    if (!empty($defaults['dynamic'])) {
      foreach ($defaults['dynamic'] as $var => $value) {
        if (strpos($offset, $var . '_') === 0) {
          $defaults['static'][$offset] = $value;
          return $value;
        }
      }
    }
    $module = db_query_range("SELECT module FROM {variable_default} WHERE name = :name OR (:name LIKE CONCAT(name, '\\_%') AND flags > 0)", 0, 1, array(
      ':name' => $offset,
    ))
      ->fetchField();
    if (!$module) {
      return NULL;
    }
    $vars = self::loadDefaults('module:' . $this->module, db_and()
      ->condition('vd.module', $this->module));
    if (!empty($vars)) {
      $defaults['static'] = array_merge(empty($defaults['static']) ? array() : $defaults['static'], empty($vars['static']) ? array() : $vars['static']);
      $defaults['dynamic'] = array_merge(empty($defaults['dynamic']) ? array() : $defaults['dynamic'], empty($vars['dynamic']) ? array() : $vars['dynamic']);
      if (isset($defaults['static'][$offset])) {
        return $defaults['static'][$offset];
      }
      if (!empty($defaults['dynamic'])) {
        foreach ($defaults['dynamic'] as $var => $value) {
          if (strpos($offset, $var) === 0) {
            $defaults['static'][$offset] = $value;
            return $value;
          }
        }
      }
    }
  }

  /**
   * Implements ArrayAccess::offsetSet().
   */
  public function offsetSet($offset, $value) {
    if (!empty($offset)) {
      variable_set($offset, $value);
    }
  }

  /**
   * Implements ArrayAccess::offsetUnset().
   */
  public function offsetUnset($offset) {
    $this
      ->deleteVariables(array(
      $offset,
    ));
  }

  /**
   * Removes the default values contained in the table variable_default.
   *
   * Remove the default values that are contained in the database table
   * created by the Variables API module. The function should be called from
   * the implementations of hook_uninstall(), or hook_update_N().
   *
   * This function is deprecated. Variable API will automatically remove the default
   * values from its database table, once the modules are uninstalled.
   *
   * @param $set
   *   An optional array of variables to remove. If the parameter is not
   *   passed, the function will remove all the variables defined from the
   *   module.
   *   The variables are also removed from memory, and from the table of
   *   persistent variables used by Drupal core.
   *
   * @see Vars::saveDefaults()
   */
  public function removeDefaults(array $set = array()) {
  }

  /**
   * Renames persistent variables.
   *
   * Renames the persistent variables whose name matched the passed argument.
   * The variables are renamed in memory, and in the database table used by
   * Drupal core code.
   *
   * @param $names
   *   A array whose keys are the names of the variables to rename, and the
   *   values are the new names to give to the persistent variables.
   *
   * @see Vars::deleteVariables()
   */
  public static function renameVariables(array $names) {
    global $conf;
    $count = 0;
    foreach ($names as $old_name => $new_name) {
      if (isset($conf[$old_name])) {
        $conf[$new_name] = $conf[$old_name];
        db_merge('variable')
          ->key(array(
          'name' => $new_name,
        ))
          ->fields(array(
          'value' => serialize($conf[$old_name]),
        ))
          ->execute();
        unset($conf[$old_name]);
        $count++;
      }
    }
    if ($count) {
      db_delete('variable')
        ->condition('name', array_keys($names), 'IN')
        ->execute();
      cache_clear_all('variables', 'cache_bootstrap');
    }
  }

  /**
   * Saves the default value for the variables defined from the module.
   *
   * Saves the default values for the variables defined from the module
   * implementing a subclass of Vars.
   * The function should be called from the implementations of hook_install(),
   * or hook_update_N().
   */
  public function saveDefaults() {
    $vars = $this
      ->getDefaults();
    if (!empty($vars) && is_array($vars)) {
      foreach ($vars as $name => $info) {
        if (!is_array($info)) {
          $info = array(
            'value' => $info,
          );
        }
        $info += array(
          'value' => '',
          'flags' => 0,
        );
        try {
          db_merge('variable_default')
            ->key(array(
            'module' => $this->module,
            'name' => $name,
          ))
            ->fields(array(
            'value' => serialize($info['value']),
            'flags' => $info['flags'],
          ))
            ->execute();
        } catch (Exception $e) {
        }
        $clear_cache = TRUE;
      }
      if (isset($clear_cache)) {
        cache_clear_all('variables', 'cache_bootstrap');
        cache_clear_all('module:' . $this->module, 'cache_vars');
        drupal_static_reset('vars_default_values');
      }
    }
  }

  /**
   * Resets one or all centrally stored static variable(s).
   *
   * This static method is provided for compatibility with code using Drupal 6;
   * code for Drupal 7 should use the function provided by Drupal.
   *
   * @param $name
   * Name of the static variable to reset. Omit to reset all variables.
   */
  public static function staticReset($name = NULL) {
    drupal_static($name, NULL, TRUE);
  }

  /**
   * Central static variable storage.
   *
   * This static method is provided for compatibility with code using Drupal 6;
   * code for Drupal 7 should use the function provided by Drupal.
   *
   * @param $name
   *   Globally unique name for the variable. For a function with only one
   *   static variable, the function name (e.g. via the PHP magic
   *   __FUNCTION__ constant) is recommended. For a function with multiple
   *   static variables add a distinguishing suffix to the function name for
   *   each one.
   *
   * @param $default_value
   *   Optional default value.
   *
   * @param $reset
   *   TRUE to reset a specific named variable, or all variables if $name is
   *   NULL.
   *   Resetting every variable should only be used, for example, for running
   *   unit tests with a clean environment. Should be used only though via
   *   function vars_static_reset() and the return value should not be used in
   *   this case.
   *
   * @return
   *   Returns a variable by reference.
   */
  public static function &staticValue($name, $default_value = NULL, $reset = FALSE) {
    return drupal_static($name, $default_value, $reset);
  }

}

/**
 * Implements hook_boot().
 *
 * The hook is intentionally empty, as it is used only to assure the module is
 * loaded on early bootstrap time.
 */
function vars_boot() {
}

/**
 * Implements hook_flush_caches().
 */
function vars_flush_caches() {
  return array(
    'cache_vars',
  );
}

/**
 * Implements hook_modules_uninstalled().
 */
function vars_modules_uninstalled($modules) {
  global $conf;
  $defaults = db_select('variable_default', 'vd')
    ->condition('vd.module', $modules, 'IN')
    ->fields('vd', array(
    'name',
    'value',
    'flags',
  ))
    ->execute();
  $variables = array();
  foreach ($defaults as $default) {
    $name = $default->name;
    if ($default->flags & self::VARS_DYNAMIC) {
      $name_like = db_like($name . '_') . '%';
      $vars = db_select('variable', 'v')
        ->condition(db_or()
        ->condition('v.name', $name_like, 'LIKE')
        ->condition('v.name', $name))
        ->fields('v', array(
        'name',
      ))
        ->execute();
      foreach ($vars as $var) {
        unset($conf[$var->name]);
        $variables[] = $var->name;
      }
    }
    else {
      $variables[] = $name;
      unset($conf[$name]);
    }
  }
  if (!empty($variables)) {
    db_delete('variable')
      ->condition('name', $variables, 'IN')
      ->execute();
    db_delete('variable_default')
      ->condition('module', $modules, 'IN')
      ->execute();
    foreach ($modules as $module) {
      cache_clear_all('module:' . $module, 'cache_vars');
    }
    cache_clear_all('variables', 'cache_bootstrap');
    Vars::staticReset('vars_default_values');
  }
}

/**
 * Implements hook_node_type_delete().
 */
function vars_node_type_delete($info) {
  global $conf;
  $names = array();
  $variables = Vars::loadDefaults('node_type');
  if (array_key_exists('dynamic', $variables)) {
    foreach (array_keys($variables['dynamic']) as $var) {
      $names[] = $var->name . '_' . $info->type;
      unset($conf[$var->name . '_' . $info->type]);
    }
  }
  if (!empty($names)) {
    db_delete('variable')
      ->condition('name', $names, 'IN')
      ->execute();
    cache_clear_all('variables', 'cache_bootstrap');
  }
}

Functions

Classes

Namesort descending Description
Vars @file Implement an API to handle persistent variables.