' . 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; }