vars.module in Variable API 6
Same filename and directory in other branches
Implement an API to handle persistent variables.
File
vars.moduleView 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.
*
* Return 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_query("DELETE FROM {variable} WHERE name IN (" . db_placeholders($names, 'varchar') . ")", $names);
cache_clear_all('variables', 'cache');
}
}
/**
* 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
* An array of conditions the persistent variables
* must respect.
* @param $args
* An array of arguments for the passed conditions.
* @return
* An array containing information about the default value for the
* persistent variables.
*
* @see vars_node_type()
*/
public static function loadDefaults($cid, $conditions, $args) {
if ($cache = cache_get($cid, 'cache_vars')) {
return $cache->data;
}
if (!is_array($conditions)) {
$conditions = array(
$conditions,
);
}
if (!is_array($args)) {
$args = array(
$args,
);
}
$conditions = implode(' AND ', $conditions);
$defaults = array();
$result = db_query("SELECT * FROM {variable_default} WHERE " . $conditions, $args);
while ($var = db_fetch_object($result)) {
$index = $var->flags ? 'dynamic' : 'static';
$defaults[$index][$var->name] = unserialize($var->value);
}
if ($cid != 'node_type') {
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 =& self::staticValue('vars_default_values', array());
if (isset($defaults['static'][$offset])) {
return $defaults['static'][$offset];
}
if (isset($defaults['dynamic'])) {
foreach ($defaults['dynamic'] as $var => $value) {
if (strpos($offset, $var . '_') === 0) {
$defaults['static'][$offset] = $value;
return $value;
}
}
}
$module = db_result(db_query_range("SELECT module FROM {variable_default} WHERE name = '%s' OR ('%s' LIKE CONCAT(name, '\\_%') AND flags > 0)", $offset, $offset, 0, 1));
if (!$module) {
return NULL;
}
$vars = self::loadDefaults('module:' . $module, "module = '%s'", $module);
if (!empty($vars)) {
$defaults['static'] = array_merge(isset($defaults['static']) ? $defaults['static'] : array(), isset($vars['static']) ? $vars['static'] : array());
$defaults['dynamic'] = array_merge(isset($defaults['dynamic']) ? $defaults['dynamic'] : array(), isset($vars['dynamic']) ? $vars['dynamic'] : array());
if (isset($defaults['static'][$offset])) {
return $defaults['static'][$offset];
}
if (isset($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 Variable API module. The function should be called from
* the implementations of hook_uninstall(), or hook_update_N().
*
* @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()) {
global $conf;
$args = $this->module;
$query = "SELECT * FROM {variable_default} WHERE module = '%s'";
if (!empty($set)) {
$args = array_merge($args, $set);
$query .= " AND name IN (" . db_placeholders($set, 'varchar') . ")";
}
$vars = db_query($query, $args);
while ($var = db_fetch_object($vars)) {
$name = $var->name;
if ($var->flags & self::VARS_DYNAMIC) {
$count = 0;
$name_like = str_replace(array(
'_',
'%',
), array(
'\\_',
'\\%',
), $name) . '\\_%';
$result = db_query("SELECT name FROM {variable} WHERE name LIKE '%s' OR name = '%s'", $name_like, $name);
while ($row = db_fetch_object($result)) {
unset($conf[$row->name]);
$count++;
}
if ($count) {
db_query("DELETE FROM {variable} WHERE name LIKE '%s' OR name = '%s'", $name_like, $name);
cache_clear_all('variables', 'cache');
}
$clear_cache = TRUE;
}
else {
unset($conf[$name]);
db_query("DELETE FROM {variable} WHERE name = '%s'", $name);
cache_clear_all('variables', 'cache');
$clear_cache = TRUE;
}
}
if (isset($clear_cache)) {
db_query("DELETE FROM {variable_default} WHERE module = '%s'", $this->module);
cache_clear_all('module:' . $this->module, 'cache_vars');
self::staticReset('vars_default_values');
}
}
/**
* Renames persistent variables.
*
* Renames the persistent variables whose name matches 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])) {
$serialized_value = serialize($conf[$old_name]);
db_query("UPDATE {variable} SET value = '%s' WHERE name = '%s'", $serialized_value, $new_name);
if (!db_affected_rows()) {
@db_query("INSERT INTO {variable} (name, value) VALUES ('%s', '%s')", $new_name, $serialized_value);
}
$conf[$new_name] = $conf[$old_name];
unset($conf[$old_name]);
$count++;
}
}
if ($count) {
$args = array_keys($names);
db_query("DELETE FROM {variable} WHERE name IN (" . db_placeholders($args, 'varchar') . ")", $args);
cache_clear_all('variables', 'cache');
}
}
/**
* 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,
);
$result = db_fetch_object(db_query_range("SELECT * FROM {variable_default} WHERE module = '%s' AND name = '%s'", $this->module, $name, 0, 1));
if ($result === FALSE) {
$var = new stdClass();
$var->module = $this->module;
$var->name = $name;
}
else {
$var = $result;
}
$var->value = serialize($info['value']);
$var->flags = $info['flags'];
drupal_write_record('variable_default', $var, $result === FALSE ? array() : 'vdid');
$clear_cache = TRUE;
}
if (isset($clear_cache)) {
cache_clear_all('variables', 'cache');
cache_clear_all('module:' . $this->module, 'cache_vars');
self::staticReset('vars_default_values');
}
}
}
/**
* Resets one or all centrally stored static variable(s).
*
* This is the back port of the function drupal_static_reset() defined in
* Drupal 7.
*
* @param $name
* Name of the static variable to reset. Omit to reset all variables.
*/
public static function staticReset($name = NULL) {
self::staticValue($name, NULL, TRUE);
}
/**
* Central static variable storage.
*
* This is the back port of drupal_static() defined in Drupal 7.
*
* @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) {
static $data = array(), $default = array();
if (!isset($name)) {
foreach ($default as $name => $value) {
$data[$name] = $value;
}
return $data;
}
if ($reset) {
if (array_key_exists($name, $default)) {
$data[$name] = $default[$name];
}
else {
return $data;
}
}
elseif (!array_key_exists($name, $data)) {
$default[$name] = $data[$name] = $default_value;
}
return $data[$name];
}
}
/**
* 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_node_type().
*/
function vars_node_type($op, $info) {
global $conf;
if ($op == 'delete') {
$variables = Vars::loadDefaults('node_type', "flags = %d", Vars::VARS_NODE_TYPE);
if (array_key_exists('dynamic', $variables)) {
foreach (array_keys($variables['dynamic']) as $var) {
db_query("DELETE FROM {variable} WHERE name = '%s'", $var . '_' . $info->type);
unset($conf[$name]);
$clear_cache = TRUE;
}
}
if (isset($clear_cache)) {
cache_clear_all('variables', 'cache');
}
}
}
Functions
Name | Description |
---|---|
vars_boot | Implements hook_boot(). |
vars_flush_caches | Implements hook_flush_caches(). |
vars_node_type | Implements hook_node_type(). |