' . check_plain(print_r($variable['value'], TRUE)) . '';
}
/**
* Get variable child element from multiple variable
*
* @param $parent
* Parent variable
* @param $key
* Key of the children variable (not the full name, just the piece of string that makes the difference)
*/
function variable_get_child($parent, $key, $options = array()) {
$variable = variable_build($parent, $options);
$name = preg_replace('/\[\w+\]/', $key, $variable['name']);
$child = $variable['children'][$name];
// Replace title and description
foreach (array('title', 'description') as $property) {
if (isset($variable[$property])) {
$child[$property] = $variable[$property];
}
}
return $child;
}
/**
* Get variable information
*
* Variable information is collected from modules and cached by language
*
* @param $name
* Optional variable name. Will return all if no name.
* @param $options array
* Options for variable values
* - 'langcode', Language code
*/
function variable_get_info($name = NULL, $options = array()) {
$options = _variable_options($options);
if (!$name) {
return _variable_info('variable', NULL, $options);
}
elseif ($info = _variable_info('variable', $name, $options)) {
return $info;
}
elseif ($parent = variable_parent($name)) {
$info = variable_build(variable_get_info($parent));
$child = $info['children'][$name];
// Copy over some values from parent to child to add some context to it.
$child['title'] = $info['title'] . ' [' . $child['title'] . ']';
if (isset($info['description'])) {
$child['description'] = $info['description'];
}
return $child;
}
else {
return NULL;
}
}
/**
* Get variable group information.
*
* @param $group
* Group name. Will return all if not name.
*/
function variable_get_group($group = NULL) {
return _variable_info('group', $group);
}
/**
* Get variable type information.
*
* @param $type
* Type name. Will return all if no name.
*/
function variable_get_type($type = NULL) {
$info = _variable_info('type', $type);
if ($type && !empty($info['type'])) {
// Add subtipe properties, recursive
$info += variable_get_type($info['type']);
}
return $info;
}
/**
* Get variable option information.
*/
function variable_get_option($type = NULL) {
return _variable_info('option', $type);
}
/**
* Get value for simple scalar variable
*
* @param $variable
* Variable name or array data
* @param $options
* Options array, it may have the following elements
* - language => Language object
* - default => Default value if not set
* - realm => Realm object if working inside a variable realm
*/
function variable_get_value($variable, $options = array()) {
$variable = _variable_variable($variable, $options);
if (isset($variable['value'])) {
return $variable['value'];
}
elseif (!empty($variable['value callback'])) {
variable_include($variable);
return variable_callback($variable['value callback'], $variable, _variable_options($options));
}
else {
if (!empty($options['realm'])) {
$value = $options['realm']->variable_get($variable['name'], NULL);
}
else {
$value = variable_get($variable['name'], NULL);
}
if (isset($value)) {
return $value;
}
else {
return isset($options['default']) ? $options['default'] : variable_get_default($variable, $options);
}
}
}
/**
* Set variable value
*
* This basically sets the variable but also invokes hook_variable_update
*/
function variable_set_value($name, $value, $options = array()) {
$old_value = variable_get_value($name, NULL, $options);
if (!empty($options['realm'])) {
$options['realm']->variable_set($name, $value);
}
else {
variable_set($name, $value);
}
module_invoke_all('variable_update', $name, $value, $old_value, $options);
}
/**
* Get variable default
*
* @param $variable
* Variable name or variable information
*/
function variable_get_default($variable, $options = array()) {
$variable = _variable_variable($variable, $options);
if (isset($variable['default callback'])) {
variable_include($variable);
return call_user_func($variable['default callback'], $variable, _variable_options($options));
}
elseif (isset($variable['default'])) {
return $variable['default'];
}
else {
return NULL;
}
}
/**
* Delete variable (included children variables)
*/
function variable_delete($variable, $options = array()) {
$variable = _variable_variable($variable, $options);
variable_include();
// We need to build the variable, it may be multiple
$variable = variable_build($variable, $options);
if (!empty($variable['children'])) {
$callback = !empty($options['realm']) ? array($options['realm'], 'variable_del') : 'variable_del';
array_map($callback, array_keys($variable['children']));
}
elseif (!empty($options['realm'])) {
$options['realm']->variable_del($variable['name']);
}
else {
variable_del($variable['name']);
}
// Invoke the hook only once even if its multiple
module_invoke_all('variable_delete', $variable, $options);
}
/**
* Provide list of variable titles
*
* @param $names
* List of variable names or full variable arrays
* @return array()
* List of name => title
*/
function variable_list($names) {
$list = array();
foreach ($names as $name) {
if ($variable = _variable_variable($name)) {
$list[$variable['name']] = $variable['title'];
}
}
return $list;
}
/**
* Get human readable name for variable.
*/
function variable_name($variable) {
$variable = _variable_variable($variable);
return $variable['title'];
}
/**
* Get human readable names for variable list.
*/
function variable_list_name($list) {
$names = array_map('variable_name', $list);
return implode(', ', $names);
}
/**
* @} End of "defgroup variable_api".
*/
/**
* Build full variable data
*/
function variable_build($variable, $options = array()) {
variable_include();
$variable = _variable_variable($variable, $options);
return variable_build_variable($variable, $options);
}
/**
* Clear cache
*/
function variable_cache_clear() {
cache_clear_all('*', 'cache_variable', TRUE);
}
/**
* Implementation of hook_flush_caches()
*/
function variable_flush_caches() {
return array('cache_variable');
}
/**
* Implements hook_element_info()
*/
function variable_element_info() {
// A fieldset with variable list
$types['variable_fieldset'] = array(
'#collapsible' => FALSE,
'#collapsed' => FALSE,
'#value' => NULL,
'#process' => array('variable_element_process_fieldset', 'form_process_fieldset', 'ajax_process_form'),
'#pre_render' => array('form_pre_render_fieldset'),
'#theme_wrappers' => array('fieldset'),
'#variable_list' => array(),
);
return $types;
}
/**
* Process variable fieldset
*/
function variable_element_process_fieldset($element) {
$element += variable_edit_subform($element['#variable_list']);
return $element;
}
/**
* Implements hook_hook_info().
*/
function variable_hook_info() {
$hooks['variable_info'] = array(
'group' => 'variable',
);
$hooks['variable_group_info'] = array(
'group' => 'variable',
);
$hooks['variable_type_info'] = array(
'group' => 'variable',
);
$hooks['variable_settings_form_alter'] = array(
'group' => 'variable',
);
return $hooks;
}
/**
* Form for variable list
*
* @param $list
* Variable name or list of variable names.
* @param $options
* Optional array with variable options.
*/
function variable_edit_form($form, &$form_state, $list, $options = array()) {
$list = is_array($list) ? $list : array($list);
$form = variable_base_form($form, $form_state, $list, $options);
$form += variable_edit_subform($list, $options);
return variable_settings_form($form, $options);
}
/**
* Build base form for variable list without fields.
*
* @param $list
* List of variable names.
* @param $options
* Optional array with variable options.
*/
function variable_base_form($form, &$form_state, $list, $options = array()) {
form_load_include($form_state, 'form.inc', 'variable');
// Pass on the values on the form for further reference.
$form['#variable_edit_form'] = $list;
$form['#variable_options'] = $options;
// Run submit callback for variables in form.
$form['#submit'][] = 'variable_form_submit_callback';
return $form;
}
/**
* Form elements for variable list.
*
* @param $list
* Variable name or array of variable names..
* @param $options
* Regular variable options (language, realm, etc) and optional 'form parents' array.
*/
function variable_edit_subform($list, $options = array()) {
module_load_include('form.inc', 'variable');
$list = is_array($list) ? $list : array($list);
$form = array();
foreach ($list as $name) {
if ($variable = variable_get_info($name, $options)) {
$form[$name] = variable_form_element($variable, $options);
}
}
return $form;
}
/**
* Include extended API and files related to specific variable
*
* @param $variable
* Variable array
*/
function variable_include($variable = NULL) {
static $included;
if (!isset($included)) {
// As a first step, include main variable API
module_load_include('inc', 'variable');
$included = array();
}
if ($variable && !isset($included[$variable['name']])) {
// Include module.variable.inc files related to the variable and the variable type.
variable_module_include($variable['module']);
variable_type_include($variable['type']);
$included[$variable['name']] = TRUE;
}
}
/**
* Include variable type files
*/
function variable_type_include($type) {
variable_include();
$info = variable_get_type($type);
variable_module_include($info['module']);
// Include subtype if any
if (!empty($info['type'])) {
variable_type_include($info['type']);
}
}
/**
* Form for module variables
*/
function variable_module_form($form, $form_state, $module) {
variable_include();
// Pass on the values on the form for further reference.
$form['#variable_module_form'] = $module;
return variable_edit_form($form, $form_state, array_keys(variable_list_module($module)));
}
/**
* Form for group variables
*/
function variable_group_form($form, $form_state, $group) {
variable_include();
// Pass on the values on the form for further reference.
$form['#variable_group_form'] = $group;
return variable_edit_form($form, $form_state, array_keys(variable_list_group($group)));
}
/**
* Implements hook_modules_disabled().
*/
function variable_modules_disabled($modules) {
variable_include();
array_map('variable_module_disable', $modules);
variable_cache_clear();
}
/**
* Implements hook_modules_enabled().
*/
function variable_modules_enabled($modules) {
variable_include();
array_map('variable_module_enable', $modules);
variable_cache_clear();
}
/**
* Implements hook_modules_uninstalled().
*/
function variable_modules_uninstalled($modules) {
variable_include();
array_map('variable_module_uninstall', $modules);
variable_cache_clear();
}
/**
* Implements hook_theme()
*/
function variable_theme($existing, $type, $theme, $path) {
return array(
'variable_table_select' => array(
'render element' => 'element',
'file' => 'variable.form.inc',
),
);
}
/**
* Get variable info static data, try the cache, or invoke the hook to collect it.
*
* @param $type
* Name of the info to collect
* - 'variable', Variable information, hook_variable_info()
* - 'group', Group information, hook_variable_group_info()
* - 'type', Type information, hook_variable_type_info()
* @param $options
* Options to retrieve or build the data.
* The only used option to collect the data is 'langcode', though a full array of options may be used for the hooks
*/
function &variable_static($type, $options = array()) {
static $data;
$name = 'variable_' . $type;
$langcode = isset($options['langcode']) ? $options['langcode'] : 'default';
if (!isset($data[$type])) {
$data[$type] = &drupal_static($name);
}
if (!isset($data[$type][$langcode])) {
$cache_id = $type . ':' . $langcode;
if ($cache = cache_get($cache_id, 'cache_variable')) {
$data[$type][$langcode] = $cache->data;
}
else {
variable_include();
$data[$type][$langcode] = variable_build_info($type, $options);
cache_set($cache_id, $data[$type][$langcode], 'cache_variable');
}
}
// Return a reference inside the big array
return $data[$type][$langcode];
}
/**
* Get data from a variable module info array.
*/
function _variable_info($type, $name = NULL, $options = array()) {
$info = &variable_static($type, $options);
if ($name) {
return isset($info[$name]) ? $info[$name] : array();
}
else {
return $info;
}
}
/**
* Get global language object.
*
* Initialize the language system if needed as we absolutely need a language here
*/
function _variable_language() {
global $language;
if (!isset($language)) {
drupal_bootstrap(DRUPAL_BOOTSTRAP_LANGUAGE);
}
return $language;
}
/**
* Normalize variable options
*
* Will fill the following values if not present in the parameters
* - langcode, Language code
* - language, Language object
*/
function _variable_options($options = array()) {
if (!empty($options['language'])) {
$options['langcode'] = $options['language']->language;
}
elseif (!empty($options['langcode']) && ($list = language_list()) && isset($list[$options['langcode']])) {
$options['language'] = $list[$options['langcode']];
}
else {
$language = _variable_language();
$options['language'] = $language;
$options['langcode'] = $language->language;
}
return $options;
}
/**
* Normalize variable data
*
* @param $variable
* Variable name or variable info array
* @return array
* Variable information
*/
function _variable_variable($variable, $options = array()) {
if (is_array($variable)) {
return $variable;
}
elseif ($info = variable_get_info($variable, $options)) {
return $info;
}
else {
// We don't have meta-information about this variable.
return _variable_unknown($variable);
}
}
/**
* Unknown variable
*/
function _variable_unknown($name) {
return array(
'name' => $name,
'title' => t('Unknown variable @name', array('@name' => $name)),
'type' => 'unknown',
'group' => 'default',
'module' => 'variable',
// Space for public service advertisement :-)
'description' => t('We have no meta information for this variable. Please, ask module developers to declare their variables. See Variable module.'),
);
}
/**
* Implements hook_form_alter().
*
* Triggers hook_variable_realm_settings_form_alter() giving other modules a chance
* to act on settings forms after other contrib modules have added their variables.
*/
function variable_form_alter(&$form, &$form_state, $form_id) {
if (isset($form['#submit']) && is_array($form['#submit']) && in_array('system_settings_form_submit', $form['#submit'])) {
// Replace submit callback and use our own function.
$form['#submit'] = str_replace('system_settings_form_submit', 'variable_settings_form_submit', $form['#submit']);
$alter = TRUE;
}
elseif (isset($form['#variable_edit_form'])) {
// This is a variable form, just invoke the hook but don't change submit callback.
$alter = TRUE;
}
if (!empty($alter)) {
foreach (module_implements('variable_settings_form_alter') as $module) {
$function = $module . '_variable_settings_form_alter';
$function($form, $form_state, $form_id);
}
}
}
/**
* Implement validate callback.
*
* This needs to be in the module as it may be needed by form ajax callbacks.
*/
function variable_form_element_validate($element, &$form_state, $form) {
$options = isset($form['#variable_options']) ? $form['#variable_options'] : array();
$variable = $element['#variable'];
variable_include($variable);
$variable['value'] = isset($element['#value']) ? $element['#value'] : NULL;
$error = $variable['validate callback']($variable, $options, $element, $form, $form_state);
if ($error) {
form_error($element, $error);
}
}
/**
* Implements hook_module_implements_alter().
*
* Move variable_form_alter() to the end of the list to give modules manipulating
* variables/realms a chance to act on settings forms.
*
* @param $implementations
* All implementations of the given hook.
* @param $hook
* Name of the hook.
*/
function variable_module_implements_alter(&$implementations, $hook) {
if ($hook == 'form_alter') {
$group = $implementations['variable'];
unset($implementations['variable']);
$implementations['variable'] = $group;
}
}
/**
* Group variable list by variable info property.
*
* @param $list
* Array of variable names or full built variables.
* @param $field
* Field to group by. If empty, they will be added to the '' array.
*
* @result
* Array of arrays indexed by that field value.
*/
function variable_group_variables($list, $field = 'group') {
$groups = array();
foreach ($list as $variable) {
$build = _variable_variable($variable);
$value = isset($build[$field]) ? $build[$field] : '';
$groups[$value][$build['name']] = $variable;
}
return $groups;
}
/**
* Add default buttons to a form and set its prefix.
*
* @param $form
* An associative array containing the structure of the form.
* @param $options
* Aditional options to pass on, like variable realm.
*
* @return
* The form structure.
*
* @see system_settings_form_submit()
* @ingroup forms
*/
function variable_settings_form($form, $options = array()) {
$form['#variable_options'] = $options;
$form['actions']['#type'] = 'actions';
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
if (!empty($_POST) && form_get_errors()) {
drupal_set_message(t('The settings have not been saved because of the errors.'), 'error');
}
$form['#submit'][] = 'variable_settings_form_submit';
// By default, render the form using theme_system_settings_form().
if (!isset($form['#theme'])) {
$form['#theme'] = 'system_settings_form';
}
return $form;
}
/**
* Execute the system_settings_form.
*
* If you want node type configure style handling of your checkboxes,
* add an array_filter value to your form.
*/
function variable_settings_form_submit($form, &$form_state) {
// Exclude unnecessary elements.
form_state_values_clean($form_state);
// This may contain some realm options.
$options = isset($form['#variable_options']) ? $form['#variable_options'] : array();
// Now run regular settings submission but using variable_set_value()
foreach ($form_state['values'] as $key => $value) {
if (is_array($value) && isset($form_state['values']['array_filter'])) {
$value = array_keys(array_filter($value));
}
// Using this function will invoke variable_update hook.
variable_set_value($key, $value, $options);
}
drupal_set_message(t('The configuration options have been saved.'));
}
/**
* Invoke hook on all modules, adding 'module' property
*/
function variable_invoke_all() {
$args = func_get_args();
$hook = $args[0];
unset($args[0]);
$return = array();
foreach (module_implements($hook) as $module) {
$function = $module . '_' . $hook;
if (function_exists($function)) {
$result = call_user_func_array($function, $args);
if (isset($result) && is_array($result)) {
foreach ($result as $key => $value) {
$return[$key] = $value + array('module' => $module);
}
}
}
}
return $return;
}