first import

This commit is contained in:
Bachir Soussi Chiadmi
2015-04-08 11:40:19 +02:00
commit 1bc61b12ad
8435 changed files with 1582817 additions and 0 deletions

View File

@@ -0,0 +1,93 @@
Drupal module: Variable Realms
============================================
This is an API module that works as an arbitrator for multiple modules overriding global variables. It can
handle multiple realms defined by different modules. Examples: 'global', 'language', 'country',
Each realm has a weight and a current status. Realms with higher weights will override realms with lower weight.
There's a special 'global/default' realm that is the one storing default global variables. It has a weight of 0
so realms with weights higher than that (default weight for new realms is 10) will override these.
Any number of realms can be defined by different modules. If two modules use the same realm, the last one's variables
and weight will override the previous one. Every time we switch a realm, the $conf global array will be rebuilt.
At any moment the $conf global array of variables will be a combination of the active realms.
If we've got these two reamls defined:
- global/default, weight 0, which is defined by this module, will hold global default variables
- mymodule/key, weight 10, which may be defined by any contrib module on hook_boot() or hook_init()
The resulting variable set will be a combination of these two, with the second overriding the first one,
because of a higher weight. This is how we calculate the resulting variables when using variable_realm_switch()
$conf = $variables['global/default'] + $variables['mymodule/key']
API Example
-----------
This is an example of how realms work:
// We add a language realm with some variables and immediately switch to it
variable_realm_add('language', 'es', $spanish_variables);
variable_realm_switch('language', 'es');
// We add a country realm on top of it with some more variables but don't switch to it yet.
// Note the first time we add a domain we can set the weight for it.
variable_realm_add('country', 'spain', $spain_variables, 100);
// We add another country realm, but don't switch to it.
// The same weight from previous 'country' realm will be used
variable_realm_add('country', 'mexico', $mexico_variables);
// Now we can switch to the 'spanish/spain' set of variables
variable_realm_switch('country', 'spain');
// Or we can use the 'spanish/mexico' set
variable_realm_switch('country', 'mexico');
// Still we can add one more realm which will override some variables for the current node's content type
// These will override all the others because of its higher weight
variable_realm_add('nodetype', 'story', $story_variables, 200)
variable_realm_switch('nodetype', 'story')
An example of a module using this API is Internationalization's i18n_variable module.
Variable Realm Union.
====================================
This an API that allows combining two existing realms into a new one
whose keys are a combination of the other two.
An example of this module in action is the 'Domain+I18n Variables Integration' module
which is part of 'Domain Variable' module.
How to use it.
=============
To define a new domain that is a combination of two or more existing ones:
1. Implement hook_variable_realm_info() to define the realm name and properties.
function domain_i18n_variable_variable_realm_info() {
$realm['domain_language'] = array(
'title' => t('Domain+Language'),
// Display on settings forms but without form switcher.
'form settings' => TRUE,
'form switcher' => FALSE,
'variable name' => t('multilingual domain'),
);
return $realm;
}
2. Implement hook_variable_realm_controller() to define the Controller class to
be used and which other realms it is a combination of. Example:
function domain_i18n_variable_variable_realm_controller() {
$realm['domain_language'] = array(
'weight' => 200,
'class' => 'VariableStoreRealmController',
'union' => array('domain', 'language'),
);
return $realm;
}

View File

@@ -0,0 +1,96 @@
<?php
/**
* @file
* Documents hooks provided by Variable Realm API.
*/
/**
* @addtogroup hooks
* @{
*/
/**
* Provides information about controller classes and weights needed by the realm system
* and some more meta-information for realm administration.
*
* This information is mainly used to build exportable realms as Features.
*
* @see i18n_variable_variable_realm_info()
*
* @return array
* Array keyed by realm name which contains the following elements:
* - 'title', Humam readable name for the realm.
* - 'controller class', Class name for realm controller, implementing VariableRealmControllerInterface.
* - 'store class', Class name for realm store, implementing VariableRealmStoreInterface.
* - 'weight', Default weight for this realm.
* - 'keys', Associative array with human readable names for keys.
* - 'keys callback', Callback function to provide the keys.
* - 'default key', The default key.
* - 'options', Array of variable names that may be set for this realm. If not set
* any variable will be allowed for this realm.
* - 'list callback', Callback function to provide variable list for this realm.
* - 'select', Boolean flag whether variables for this realm can be selected from a list.
* - 'select path', Path to variable selection form (optional).
* - 'variable name', Name for variables that belong to this realm: e.g. 'multilingual' variable/s
* - 'variable class', CSS class name for annotated variables in system settings forms.
* - 'form settings', Boolean flag, whether realm variables should be handled automatically
* in system settings forms.
* - 'form switcher', Boolean flag, whether a realm switcher should be auto-generated
* for settings forms which contain variables that belong to this realm.
*/
function hook_variable_realm_info() {
$realm['language'] = array(
'title' => t('Language'),
'controller class' => 'I18nVariableLanguageRealm',
'store class' => 'VariableStoreRealmStore',
'keys' => locale_language_list('name', TRUE),
'default key' => language_default('language'),
'options' => _i18n_variable_variable_realm_list(),
'select' => TRUE,
'select path' => 'admin/config/regional/i18n/variable',
'variable name' => t('multilingual'),
'variable class' => 'i18n-variable',
'form settings' => TRUE,
);
return $realm;
}
/**
* Allow other modules to act when enabling a realm.
*
* This hook is invoked right after the realm controller is enabled
* and it may have a valid key already set or it may be FALSE.
*
* @param $realm_name
* Realm that is switched.
* @param $realm_key
* New realm key.
*/
function hook_variable_realm_enable($realm_name, $realm_key) {
}
/**
* Allow other modules to act on realm switching.
*
* This hook is invoked right after the realm key is switched but before
* the global variables are rebuilt.
*
* @param $realm_name
* Realm that is switched.
* @param $realm_key
* New realm key.
*/
function hook_variable_realm_switch($realm_name, $realm_key) {
}
/**
* Allow other modules to act when rebuilding the configuration.
*
* This hook is invoked before the global variables are rebuilt
* using the active realms.
*/
function hook_variable_realm_rebuild() {
}
/**
* @} End of "addtogroup hooks".
*/

View File

@@ -0,0 +1,544 @@
<?php
/**
* @file
* Variable realm controller
*/
/**
* Realm Controller Interface.
*/
interface VariableRealmControllerInterface {
/**
* Class constructor.
*
* @param $realm_name
* Realm name.
* @param $store_class
* Realm key.
*/
public function __construct($realm_name);
/**
* Check whether the realm is enabled (has a key set).
*/
public function isEnabled();
/**
* Check whether the realm is active (has a valid key set).
*/
public function isActive();
/**
* Start this realm with request key.
*
* This will only change the realm key if the realm is not initialized yet.
*/
public function enable($realm_key = NULL);
/**
* Get title for this realm.
*/
public function getTitle();
/**
* Get name for variables in this realm.
*/
public function getVariableName();
/**
* Add store for realm key.
*
* @param $variables
* Optional array with variable values to initialize the realm key store.
*/
public function addStore($realm_key, $variables = NULL);
/**
* Get store for realm key.
*/
public function getStore($realm_key);
/**
* Set store for realm key.
*/
public function setStore($realm_key, $realm_store);
/**
* Get current realm key.
*/
public function getKey();
/**
* Get default key for this realm.
*/
public function getDefaultKey();
/**
* Get key for this page request.
*/
public function getRequestKey();
/**
* Set current realm key.
*/
public function setKey($realm_key);
/**
* Get all keys for this realm.
*/
public function getAllKeys();
/**
* Get other realms this one may depend upon.
*/
public function getParentRealms();
/**
* Get current realm weight.
*/
public function getWeight();
/**
* Set current realm weight.
*/
public function setWeight($weight);
/**
* Implementation of VariableRealmControllerInterface::getWeight().
*/
public function getDefaultWeight();
/**
* Get current variable store.
*/
public function getCurrentStore();
/**
* List all current variable values.
*/
public function getCurrentVariables();
/**
* Get information for this realm.
*
* Return information provided by hook_variable_realm_info()
*/
public function getInfo($property = NULL, $default = NULL);
/**
* Get list of variables available for this realm.
*/
public function getAvailableVariables();
/**
* Get list of variables enabled for this realm.
*/
public function getEnabledVariables();
/**
* Get system variable for this realm.
*/
public function getRealmVariable($name, $default = NULL);
/**
* Set system variable for this realm.
*/
public function setRealmVariable($name, $value);
/**
* Delete variable for all keys this realm.
*
* @param $variable_name
* Variable name to delete.
*/
public function deleteVariable($variable_name);
}
/**
* Variable Realm Hooks.
*/
interface VariableRealmHooks {
/**
* Callback function that will be invoked when a realm is enabled.
*/
public function variableRealmEnable($realm_name, $realm_key);
/**
* Callback method that will be invoked when a realm is switched.
*/
public function variableRealmSwitch($realm_name, $realm_key);
}
/**
* Realm Store Interface.
*/
interface VariableRealmStoreInterface {
/**
* Class constructor.
*
* @param $realm
* Realm name.
* @param $key
* Realm key.
* @param $variables
* Optional array of variables to initialize the realm with.
*/
public function __construct($realm, $key, $variables = NULL);
/**
* Initialize variables.
*/
public function variable_init();
/**
* Get single variable.
*
* @param $name
* Variable name
* @param $default
* Default value
*/
public function variable_get($name, $default = NULL);
/**
* Set single variable.
*
* @param $name
* Variable name
* @param $value
* Variable value
*/
public function variable_set($name, $value);
/**
* Delete single variable.
*
* @param $name
* Variable name
*/
public function variable_del($name);
/**
* Add single variable to the realm for current request.
*
* While variable set actually sets the variable on whatever realm storage
* we are using, this function just sets a runtime value.
*
* @param $name
* Variable name
* @param $value
* Variable value
*/
public function variable_add($name, $value);
/**
* Check whether a variable exists in the realm.
*/
public function variable_exists($name);
/**
* List all current variable values.
*/
public function variable_list();
}
/**
* Base class, keeps static list of variables.
*/
class VariableRealmDefaultController implements VariableRealmControllerInterface {
// Unique realm name (language, domain..)
public $realm_name;
// Current realm key.
public $current_key;
// Current realm weight.
public $current_weight;
// Array of variable stores indexed by realm key.
protected $store;
/**
* Implementation of VariableRealmControllerInterface::__construct().
*/
public function __construct($realm_name) {
$this->realm_name = $realm_name;
$this->current_weight = $this->getDefaultWeight();
}
/**
* Implementation of VariableRealmControllerInterface::isEnabled()
*/
public function isEnabled() {
return isset($this->current_key);
}
/**
* Implementation of VariableRealmControllerInterface::isActive()
*/
public function isActive() {
return $this->isEnabled() && $this->current_key !== FALSE;
}
/**
* Implementation of VariableRealmControllerInterface::enable().
*/
public function enable($realm_key = NULL) {
if (!isset($this->current_key)) {
return $this->current_key = isset($realm_key) ? $realm_key : $this->getRequestKey();
}
}
/**
* Implementation of VariableRealmControllerInterface::getTitle().
*/
public function getTitle() {
return $this->getInfo('title');
}
/**
* Implementation of VariableRealmControllerInterface::getVariableName().
*/
public function getVariableName() {
return $this->getInfo('variable name');
}
/**
* Implementation of VariableRealmControllerInterface::getStore().
*/
public function getStore($realm_key) {
if (isset($this->store[$realm_key])) {
return $this->store[$realm_key];
}
else {
return $this->addStore($realm_key);
}
}
/**
* Implementation of VariableRealmControllerInterface::addStore().
*/
public function addStore($realm_key, $variables = NULL) {
$store = $this->createStore($realm_key, $variables);
$this->setStore($realm_key, $store);
return $store;
}
/**
* Create Store for key.
*/
protected function createStore($realm_key, $variables = NULL) {
$class = $this->getInfo('store class');
$class = $class && class_exists($class) ? $class : 'VariableRealmDefaultStore';
return new $class($this->realm_name, $realm_key, $variables);
}
/**
* Set store for realm key.
*/
public function setStore($realm_key, $realm_store) {
$this->store[$realm_key] = $realm_store;
}
/**
* Implementation of VariableRealmControllerInterface::setKey().
*/
public function setKey($realm_key) {
$this->current_key = $realm_key;
}
/**
* Implementation of VariableRealmControllerInterface::getKey().
*/
public function getKey() {
return isset($this->current_key) ? $this->current_key : FALSE;
}
/**
* Implementation of VariableRealmControllerInterface::getAllKeys().
*/
public function getAllKeys() {
return $this->getInfo('keys', array());
}
/**
* Implementation of VariableRealmControllerInterface::getDefaultKey().
*/
public function getDefaultKey() {
return $this->getInfo('default key', FALSE);
}
/**
* Implementation of VariableRealmControllerInterface::getRequestKey().
*/
public function getRequestKey() {
return FALSE;
}
/**
* Implementation of VariableRealmControllerInterface::getWeight().
*/
public function getWeight() {
return isset($this->current_weight) ? $this->current_weight : $this->controller_data['weight'];
}
/**
* Implementation of VariableRealmControllerInterface::setWeight().
*/
public function setWeight($weight) {
$this->current_weight = $weight;
}
/**
* Implementation of VariableRealmControllerInterface::getWeight().
*/
public function getDefaultWeight() {
return $this->getRealmVariable('weight', $this->getInfo('weight', 0));
}
/**
* Implementation of VariableRealmControllerInterface::getParentRealms().
*/
public function getParentRealms() {
return array();
}
/**
* Implementation of VariableRealmControllerInterface::getCurrentVariables().
*/
public function getCurrentVariables() {
if ($store = $this->getCurrentStore()) {
return $store->variable_list();
}
else {
return array();
}
}
/**
* Implementation of VariableRealmControllerInterface::getCurrentStore().
*/
public function getCurrentStore() {
if ($this->isActive()) {
return $this->getStore($this->getKey());
}
else {
return NULL;
}
}
/**
* Implementation of VariableRealmControllerInterface::getAvailableVariables().
*/
public function getAvailableVariables() {
if ($options = $this->getInfo('options')) {
return $options;
}
else {
// Defaults to all available variables.
return array_keys(variable_get_info());
}
}
/**
* Implementation of VariableRealmControllerInterface::getEnabledVariables().
*/
public function getEnabledVariables() {
if ($this->getInfo('select')) {
return $this->getRealmVariable('list', array());
}
else {
// If the variable is not set it will default to all variables
return $this->getAvailableVariables();
}
}
/**
* Implementation of VariableRealmControllerInterface::getInfo().
*/
public function getInfo($property = NULL, $default = NULL) {
$info = variable_realm_info($this->realm_name);
if ($property) {
return isset($info[$property]) ? $info[$property] : $default;
}
else {
return $info;
}
}
/**
* Implementation of VariableRealmControllerInterface::getRealmVariable().
*/
public function getRealmVariable($name, $default = NULL) {
return variable_get('variable_realm_' . $name . '_' . $this->realm_name, $default);
}
/**
* Implementation of VariableRealmControllerInterface::setRealmVariable().
*/
public function setRealmVariable($name, $value) {
variable_realm_global_set('variable_realm_' . $name . '_' . $this->realm_name, $value);
}
/**
* Implementation of VariableRealmControllerInterface::deleteVariable().
*/
public function deleteVariable($variable_name) {
foreach ($this->getAllKeys() as $key => $name) {
variable_realm_del($this->realm_name, $key, $variable_name, FALSE);
}
}
}
/**
* Base class, keeps static list of variables.
*/
class VariableRealmDefaultStore implements VariableRealmStoreInterface {
public $realm;
public $key;
protected $variables;
/**
* Class constructor.
*/
public function __construct($realm, $key, $variables = NULL) {
$this->realm = $realm;
$this->key = $key;
$this->variables = $variables;
}
/**
* Initialize variables.
*/
public function variable_init() {
if (!isset($this->variables)) {
$this->variables = array();
}
}
/**
* Get single variable.
*
* @param $name
* Variable name
* @param $default
* Default value
*/
public function variable_get($name, $default = NULL) {
$this->variable_init();
return isset($this->variables[$name]) ? $this->variables[$name] : $default;
}
/**
* Set single variable.
*
* @param $name
* Variable name
* @param $value
* Variable value
*/
public function variable_set($name, $value) {
$this->variable_init();
$this->variables[$name] = $value;
}
/**
* Delete single variable.
*
* @param $name
* Variable name
*/
public function variable_del($name) {
$this->variable_init();
unset($this->variables[$name]);
}
/**
* Implementation of VariableRealmStoreInterface::variable_add().
*/
public function variable_add($name, $value) {
$this->variable_init();
$this->variables[$name] = $value;
}
/**
* Implementation of VariableRealmStoreInterface::variable_exists().
*/
public function variable_exists($name) {
$this->variable_init();
return isset($this->variables[$name]);
}
/**
* List all current variable values.
*/
public function variable_list() {
$this->variable_init();
return $this->variables;
}
}
/**
* Controller for default system variables.
*/
class VariableRealmGlobalStore extends VariableRealmDefaultStore {
/**
* Initialize variables.
*/
public function variable_init() {
if (!isset($this->variables)) {
$this->variables = $GLOBALS['conf'];
}
}
/**
* Set single variable.
*
* @param $name
* Variable name
* @param $value
* Variable value
*/
public function variable_set($name, $value) {
parent::variable_set($name, $value);
variable_set($name, $value);
}
/**
* Delete single variable.
*
* @param $name
* Variable name
*/
public function variable_del($name) {
parent::variable_del($name);
variable_del($name);
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* @file
* Drush commands for Variable Realm.
*/
/**
* Implements hook_drush_command().
*/
function variable_realm_drush_command() {
$items['variable-realm-get'] = array(
'description' => 'Get a variable for a specific realm and key.',
'examples' => array(
'drush variable-realm-get language es site_frontpage',
'drush variable-realm-get language es',
),
'arguments' => array(
'domain_name' => 'The realm name for the variable.',
'domain_key' => 'The domain key for the variable.',
'variable_name' => 'Optional variable name variable to get. If not present list all variables for that realm and key.',
),
);
$items['variable-realm-set'] = array(
'description' => 'Set a variable for a specific realm and key.',
'examples' => array(
'drush variable-realm-set language es site_frontpage /home ',
),
'arguments' => array(
'domain_name' => 'The realm name for the variable.',
'domain_key' => 'The domain key for the variable.',
'variable_name' => 'The name variable to set (e.g. site_frontpage).',
'value' => 'The value to set for this variable.'
),
);
$items['variable-realm-del'] = array(
'description' => 'Delete a variable for a specific realm and key.',
'examples' => array(
'drush variable-realm-del language es site_frontpage',
),
'arguments' => array(
'domain_name' => 'The realm name for the variable.',
'domain_key' => 'The domain key for the variable.',
'variable_name' => 'The name variable to set (e.g. site_frontpage).',
),
);
return $items;
}
/**
* Implements hook_drush_help().
*/
function variable_realm_drush_help($section) {
$items = variable_realm_drush_command();
$name = str_replace('domain:', '', $section);
if (isset($items[$name])) {
return dt($items[$name]['description']);
}
}
/**
* Drush command callback.
* Set realm's variables.
*/
function drush_variable_realm_set($realm_name, $realm_key, $variable_name, $value) {
variable_realm_set($realm_name, $realm_key, $variable_name, $value);
drush_print('Variable set.');
}
/**
* Drush command callback.
* Validate parameters
*/
function drush_variable_realm_set_validate($realm_name = NULL, $realm_key = NULL, $variable_name = NULL, $value = NULL) {
if (is_null($realm_name) | is_null($realm_key) || is_null($variable_name) || is_null($value)) {
return drush_set_error('variable_realm', dt('Please enter all four required arguments, "dc-set realm_name realm_key variable_name value".'));
}
}
/**
* Drush command callback.
* Delete realm's variables.
*/
function drush_variable_realm_del($realm_name, $realm_key, $variable_name) {
variable_realm_del($realm_name, $realm_key, $variable_name);
drush_print('Variable deleted.');
}
/**
* Drush command callback.
* List realm's variables.
*/
function drush_variable_realm_get($realm_name, $realm_key, $variable_name) {
if ($variable_name) {
$variables[$variable_name] = variable_realm_get($realm_name, $realm_key, $variable_name);
}
else {
$variables = variable_realm($realm_name, $realm_key)->variable_list();
}
foreach ($variables as $name => $value) {
drush_print_pipe(drush_format($value, $name, 'export'));
drush_print(drush_format($value, $name));
$returns[$name] = $value;
}
if (empty($variables)) {
return drush_set_error('No matching variable found.');
}
else {
return $returns;
}
}

View File

@@ -0,0 +1,127 @@
<?php
/**
* @file
* Features support for Variable store.
*/
/**
* Implements hook_features_export_options().
*/
function variable_realm_features_export_options() {
foreach (variable_realm_info() as $name => $realm) {
$controller = variable_realm_controller($name);
$realm_keys = $controller->getAllKeys();
if (count($realm_keys) > 1) {
$options[$name] = $controller->getTitle() . ': ' . t('all');
}
foreach ($realm_keys as $key => $title) {
$options[$name . ':' . $key] = $controller->getTitle() . ': ' . $title;
}
}
return $options;
}
/**
* Implements hook_features_export().
*/
function variable_realm_features_export($data, &$export, $module_name) {
$export['dependencies']['variable_realm'] = 'variable_realm';
$list = variable_realm_features_selection($data);
foreach ($list as $machine_name) {
// Add module that provides the exported realm
list($realm, $key) = explode(':', $machine_name, 2); // limit 2 because keys can contain colons
if ($realm_info = variable_realm_info($realm)) {
$export['dependencies'][$realm_info['module']] = $realm_info['module'];
}
$export['features']['variable_realm'][$machine_name] = $machine_name;
}
return array();
}
/**
* Processes export data selections consistently.
*
* @param $data
* Array of selections from the features component form.
*
* @return
* An array of realms, keyed by machine_name.
*/
function variable_realm_features_selection($data) {
$list = array();
foreach ($data as $machine_name) {
if (strpos($machine_name, ':')) {
$list[] = $machine_name;
}
else {
foreach (variable_realm_keys($machine_name) as $key => $title) {
$list[] = "$machine_name:$key";
}
}
}
return $list;
}
/**
* Implements hook_features_export_render().
*/
function variable_realm_features_export_render($module_name, $data, $export = NULL) {
variable_realm_features_load($module_name, 'variable_realm_default_variables', FALSE);
$code = array();
$code[] = '$realm_variables = array();';
foreach ($data as $machine_name) {
list($realm, $key) = explode(':', $machine_name, 2); // limit 2 because keys can contain colons
$variable_realm = variable_realm($realm, $key);
$variables = $variable_realm->variable_list();
$code[] = " \$realm_variables['{$realm}']['{$key}'] = " . features_var_export($variables) .";";
}
$code[] = "\nreturn \$realm_variables;";
$output = implode("\n", $code);
return array('variable_realm_default_variables' => $output);
}
/**
* Implements hook_features_revert().
*/
function variable_realm_features_revert($module) {
return variable_realm_features_rebuild($module);
}
/**
* Implements hook_features_rebuild().
*/
function variable_realm_features_rebuild($module) {
if ($defaults = variable_realm_features_load($module, 'variable_realm_default_variables', TRUE)) {
foreach ($defaults as $realm => $realm_data) {
foreach ($realm_data as $key => $variables) {
$variable_realm = variable_realm($realm, $key);
foreach ($variables as $name => $value) {
$variable_realm->variable_set($name, $value);
}
}
}
}
}
/**
* Features doesn't know how to load custom includes.
*
* @param $module
* The name of the feature to load.
* @param $hook
* The name of the domain hook.
* @param $return
* Boolean indicator to return the results of the function.
*
* @return
* The results of the $hook implemenation, if requested.
*/
function variable_realm_features_load($module, $hook, $return = TRUE) {
// Features does not handle module loading of custom files.
module_load_include('inc', $module, $module . '.variable');
$function = $module . '_' . $hook;
if ($return && function_exists($function)) {
return $function();
}
}

View File

@@ -0,0 +1,400 @@
<?php
/**
* @file
* Administrative forms for variable realms.
*/
/**
* Select variables for realm.
*/
function variable_realm_select_variables_form($form, &$form_state, $realm_name) {
$controller = variable_realm_controller($realm_name);
$current = $controller->getEnabledVariables();
$optional = $controller->getAvailableVariables();
// The final list will be the sum of both lists. We may have unknown variables
// we want to preserve.
$list = array_unique(array_merge($optional, $current));
$form['realm_name'] = array('#type' => 'value', '#value' => $realm_name);
$form['message']['select']['#markup'] = '<h3>' . t('Select variables to be set for this realm.') . '</h3>';
if ($current) {
$form['message']['current']['#markup'] = '<p>' . t('Currently selected variables are: <em>!variables</em>', array('!variables' => variable_list_name($current))) . '</p>';
}
$form['variables'] = array(
'#type' => 'vertical_tabs',
'#tree' => TRUE,
);
$variable_groups = variable_group_variables($list);
foreach ($variable_groups as $group => $group_list) {
$group_info = variable_get_group($group);
$group_current = array_intersect($group_list, $current);
$form['variables'][$group] = array(
'#type' => 'fieldset',
'#title' => $group_info['title'],
'#theme' => 'variable_table_select',
'#collapsible' => TRUE, '#collapsed' => TRUE,
);
foreach ($group_list as $name) {
// Variable names may clash with form element names, so we need to replace '[' and ']'
$safename = str_replace(array('[', ']'), array('<', '>'), $name);
$form['variables'][$group][$safename] = array(
'#type' => 'checkbox',
'#default_value' => in_array($name, $group_current),
'#variable_name' => $name,
'#parents' => array('variables', $safename),
);
}
}
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
return $form;
}
/**
* Select variables for realm.
*/
function variable_realm_select_variables_form_submit($form, &$form_state) {
// Get realm name and current list of variables.
$realm_name = $form_state['values']['realm_name'];
$controller = variable_realm_controller($realm_name);
$old_variables = $controller->getEnabledVariables();
// Get main variable names
$variables = $form_state['values']['variables'];
unset($variables['variables__active_tab']);
$variables = array_keys(array_filter($variables));
// Translate variable names
foreach ($variables as $index => $name) {
$variables[$index] = str_replace(array('<', '>'), array('[', ']'), $name);
}
// Hook for modules to alter this variable list.
drupal_alter('variable_realm_variable_list', $variables, $realm_name);
// And save the list to a variable.
$controller->setRealmVariable('list', $variables);
// Spawn multiple variables and translate into actual variables
$new_list = variable_children($variables);
// Delete variables from realm that are not in the new list.
$old_list = variable_children($old_variables);
foreach (array_diff($old_list, $new_list) as $name) {
$controller->deleteVariable($name);
drupal_set_message(t('Deleted existing values of %name from realm variables.', array('%name' => $name)));
}
}
/**
* Edit variables for realm.
*/
function variable_realm_edit_variables_form($form, &$form_state, $realm_name, $realm_key) {
$controller = variable_realm_controller($realm_name);
$form['realm_name'] = array('#type' => 'value', '#value' => $realm_name);
$form['realm_key'] = array('#type' => 'value', '#value' => $realm_key);
$options['realm'] = variable_realm($realm_name, $realm_key);
if ($variable_list = $controller->getEnabledVariables()) {
// Group variables by variable group for vertical tabls
$group_list = array();
foreach ($variable_list as $variable_name) {
$variable_info = variable_get_info($variable_name, $options);
$group = $variable_info['group'];
$group_list[$group][] = $variable_name;
}
$form['variables'] = array(
'#type' => 'vertical_tabs',
'#tree' => TRUE,
);
foreach ($group_list as $group => $group_variables) {
$group_info = variable_get_group($group);
$form['variables'][$group] = array(
'#type' => 'fieldset',
'#title' => $group_info['title'],
'#collapsible' => TRUE, '#collapsed' => TRUE,
);
// Set form parents for this variable / group.
$options['form parents'] = array('variables', $group);
$form['variables'][$group] += variable_edit_subform($group_variables, $options);
}
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save configuration'));
}
else {
$form['message']['#markup'] = '<h3>' . t('No variables have been selected as %realm_name specific.', array('%realm_name' => $controller->getTitle())) . '</h3>';
}
if (!empty($realm_info['select path'])) {
$form['select']['#markup'] = t('To select variables to be configured, see <a href="!select-url">%realm_name variable settings</a>.', array(
'%realm_name' => $realm_info['title'],
'!select-url' => url($realm_info['select path'])
));
}
return $form;
}
/**
* Edit variables for realm.
*/
function variable_realm_edit_variables_form_submit($form, &$form_state) {
$realm_name = $form_state['values']['realm_name'];
$realm_key = $form_state['values']['realm_key'];
foreach ($form_state['values']['variables'] as $group => $group_variables) {
if (is_array($group_variables)) {
foreach ($group_variables as $name => $value) {
$current = variable_realm_get($realm_name, $realm_key, $name);
if ($current !== $value) {
variable_realm_set($realm_name, $realm_key, $name, $value);
}
}
}
}
// Redirect later depending on query string parameters.
_variable_realm_form_submit_redirect($form, $form_state);
}
/**
* Key selector for realm forms.
*/
function variable_realm_form_key_selector($realm_name, $current_key) {
$element_name = VARIABLE_REALM_FORM_SWITCHER . $realm_name;
$query_name = 'variable_realm_' . $realm_name . '_key';
$controller = variable_realm_controller($realm_name);
$form[$element_name] = array(
'#type' => 'fieldset',
'#title' => t('There are %name variables in this form', array('%name' => $controller->getVariableName())),
'#weight' => -100,
'#description' => t('Check you are editing the variables for the right %realm value or select the desired %realm.', array('%realm' => $controller->getTitle())),
);
// Replace only this element on current query string, there may be others.
$current_query = $_GET;
unset($current_query['q']);
foreach ($controller->getAllKeys() as $realm_key => $key_name) {
$query[VARIABLE_REALM_QUERY_STRING . $realm_name] = $realm_key;
$link = l($key_name, $_GET['q'], array('query' => $query + $current_query));
$items[] = $current_key == $realm_key ? '<strong>' . $link . '</strong>' : $link;
}
$form[$element_name]['select_key'] = array(
'#type' => 'item',
'#markup' => implode(' | ', $items),
);
return $form;
}
/**
* Get current realm key from query string or from current realm value.
*/
function variable_realm_form_key_current($realm_name) {
$realm_controller = variable_realm_controller($realm_name);
if ($key = variable_realm_params($realm_name)) {
return $key;
}
elseif ($key = $realm_controller->getKey()) {
return $key;
}
elseif ($key = $realm_controller->getRequestKey()) {
return $key;
}
else {
return $realm_controller->getDefaultKey();
}
}
/**
* Alter settings form and return list of found variables.
*/
function _variable_realm_variable_settings_form_alter(&$form, $realm_name, $variables) {
$result = array();
foreach (element_children($form) as $field) {
if (count(element_children($form[$field])) && empty($form[$field]['#tree'])) {
// Rewrite fieldsets recursively.
$result += _variable_realm_variable_settings_form_alter($form[$field], $realm_name, $variables);
}
elseif (in_array($field, $variables)) {
if (isset($form[$field]['#variable_realm'])) {
// Oh-oh, variable already taken by another realm.
_variable_realm_variable_settings_form_conflict($field);
$form[$field]['#disabled'] = TRUE;
}
else {
// Mark variable as already taken by a realm
$form[$field]['#variable_realm'] = $realm_name;
}
_variable_realm_variable_settings_form_mark($realm_name, $form[$field]);
// Addd field => name to result
$result[$field] = !empty($form[$field]['#title']) ? $form[$field]['#title'] : $field;
}
}
return $result;
}
/**
* Mark variable as belonging to a realm.
*/
function _variable_realm_variable_settings_form_mark($realm_name, &$element) {
$realm_info = variable_realm_info($realm_name);
// Add form field class (i18n-variable) and description text.
if (!empty($realm_info['variable class'])) {
$element['#attributes']['class'][] = $realm_info['variable class'];
}
$element['#description'] = !empty($element['#description']) ? $element['#description'] : '';
$element['#description'] .= ' <strong>' . t('This is a @name variable.', array('@name' => $realm_info['variable name'])) . '</strong> ';
}
/**
* Warning about variable conflict.
*/
function _variable_realm_variable_settings_form_conflict($variable) {
static $warnings;
if (!isset($warnings[$variable])) {
$warnings[$variable] = TRUE;
drupal_set_message(t('There are conflicting realm variables in the form. The variable %name is enabled for more than one realm. Review your realm settings', array('%name' => variable_name($variable))), 'warning');
}
}
/**
* Save realm variables and remove them from form.
*/
function variable_realm_variable_settings_form_submit($form, &$form_state) {
$op = isset($form_state['values']['op']) ? $form_state['values']['op'] : '';
foreach ($form['#realm_keys'] as $realm_name => $realm_key) {
$realm_controller = variable_realm_controller($realm_name);
//$language = i18n_language($form_state['values']['i18n_variable_language']);
//unset($form_state['values']['i18n_variable_language']);
$variables = array_keys($form['#realm_variables'][$realm_name]);
foreach ($variables as $variable_name) {
if (isset($form_state['values'][$variable_name])) {
if ($op == t('Reset to defaults')) {
variable_realm_del($realm_name, $realm_key, $variable_name);
}
else {
$value = $form_state['values'][$variable_name];
if (is_array($value) && isset($form_state['values']['array_filter'])) {
$value = array_keys(array_filter($value));
}
variable_realm_set($realm_name, $realm_key, $variable_name, $value);
}
// If current is not default realm key, we don't set any global variable (without realm)
if ($realm_key != $realm_controller->getDefaultKey()) {
unset($form_state['values'][$variable_name]);
}
}
}
}
// Redirect later depending on query string parameters.
_variable_realm_form_submit_redirect($form, $form_state);
// The form will go now through system_settings_form_submit()
}
/**
* Process system_theme_settings form submissions.
*
* @see system_theme_settings_submit()
*/
function variable_realm_variable_theme_form_submit($form, &$form_state) {
// Regular theme submission without variable set.
$values = $form_state['values'];
// If the user uploaded a new logo or favicon, save it to a permanent location
// and use it in place of the default theme-provided file.
if ($file = $values['logo_upload']) {
unset($values['logo_upload']);
$filename = file_unmanaged_copy($file->uri);
$values['default_logo'] = 0;
$values['logo_path'] = $filename;
$values['toggle_logo'] = 1;
}
if ($file = $values['favicon_upload']) {
unset($values['favicon_upload']);
$filename = file_unmanaged_copy($file->uri);
$values['default_favicon'] = 0;
$values['favicon_path'] = $filename;
$values['toggle_favicon'] = 1;
}
// If the user entered a path relative to the system files directory for
// a logo or favicon, store a public:// URI so the theme system can handle it.
if (!empty($values['logo_path'])) {
$values['logo_path'] = _system_theme_settings_validate_path($values['logo_path']);
}
if (!empty($values['favicon_path'])) {
$values['favicon_path'] = _system_theme_settings_validate_path($values['favicon_path']);
}
if (empty($values['default_favicon']) && !empty($values['favicon_path'])) {
$values['favicon_mimetype'] = file_get_mimetype($values['favicon_path']);
}
$key = $values['var'];
// Exclude unnecessary elements before saving.
unset($values['var'], $values['submit'], $values['reset'], $values['form_id'], $values['op'], $values['form_build_id'], $values['form_token']);
// Set realm variable.
$variable_name = $key;
$realm_name = $form['#realm_theme'];
$realm_key = $form['#realm_keys'][$realm_name];
variable_realm_set($realm_name, $realm_key, $variable_name, $values);
// If current is default realm key, set global variable too.
$realm_controller = variable_realm_controller($realm_name);
if ($realm_key == $realm_controller->getDefaultKey()) {
variable_set($variable_name, $values);
}
// Confirmation, clear cache, taken from system_theme_settings_submit()
drupal_set_message(t('The configuration options have been saved.'));
cache_clear_all();
// Redirect later depending on query string parameters.
_variable_realm_form_submit_redirect($form, $form_state);
}
/**
* Get variable list for settings forms handling multiple realms.
*
* Variables available for more than one realm, will be kept only in the list
* for the realm with the higher weight.
*/
function _variable_realm_variable_settings_form_list() {
$list = array();
foreach (variable_realm_list_all() as $realm_name => $controller) {
if ($controller->getInfo('form settings') && ($realm_list = $controller->getEnabledVariables())) {
// Remove from previous realms with lower weight.
foreach ($list as $name => $variables) {
$list[$name] = array_diff($variables, $realm_list);
}
$list[$realm_name] = $realm_list;
}
}
return $list;
}
/**
* Redirect to current page after form submission, using query string parameters.
*/
function _variable_realm_form_submit_redirect($form, &$form_state) {
if ($query_params = variable_realm_params()) {
foreach ($query_params as $realm => $value) {
$query[VARIABLE_REALM_QUERY_STRING . $realm] = $value;
}
// Parameters to be passed to drupal_goto().
$form_state['redirect'] = array(current_path(), array('query' => $query));
}
}
/**
* Add realm switcher to the form.
*/
function _variable_realm_variable_settings_form_switcher(&$form) {
// Add switchers for current realms and current key.
// Add realm values and subform realm / key selector.
foreach (array_keys($form['#realm_variables']) as $realm_name) {
$current_key = variable_realm_form_key_current($realm_name);
$info = variable_realm_info($realm_name);
if (!empty($info['form switcher'])) {
$form += variable_realm_form_key_selector($realm_name, $current_key);
}
$form['#realm_keys'][$realm_name] = $current_key;
}
// Make sure realm switchers are added for all parent realms of current ones.
foreach (variable_realm_list_all() as $realm_name => $realm_controller) {
if (($parent_realms = $realm_controller->getParentRealms()) && !empty($form['#realm_variables'][$realm_name]) && empty($form[VARIABLE_REALM_FORM_SWITCHER . $realm_name])) {
// Check we have selectors for the other realms.
foreach ($parent_realms as $realm) {
$info = variable_realm_info($realm);
if (!empty($info['form switcher']) && empty($form[VARIABLE_REALM_FORM_SWITCHER . $realm])) {
$current_key = variable_realm_form_key_current($realm);
$form += variable_realm_form_key_selector($realm, $current_key);
}
}
}
}
}

View File

@@ -0,0 +1,16 @@
name = Variable realm
description = API to use variable realms from different modules
dependencies[] = variable
package = Variable
core = 7.x
version = 7.x-2.x
files[] = variable_realm.class.inc
files[] = variable_realm_union.class.inc
; Information added by drupal.org packaging script on 2013-01-13
version = "7.x-2.2"
core = "7.x"
project = "variable"
datestamp = "1358075138"

View File

@@ -0,0 +1,21 @@
<?php
/**
* @file
* Variable API module install file
*/
/**
* Implements hook_install()
*/
function variable_realm_install() {
// Set module weight for it to run before most modules and initialize variable realms
db_query("UPDATE {system} SET weight = -1000 WHERE name = 'variable_realm' AND type = 'module'");
}
/**
* Refresh cache so new classes are found.
*/
function variable_realm_update_7000() {
drupal_flush_all_caches();
}

View File

@@ -0,0 +1,635 @@
<?php
/**
* @file
* Variable API module - Realms
*
* Each variable realm can be in one of four states.
* - Undefined, The realm controller has not been created yet.
* - Defined, The realm controller has been created.
* - Enabled, A value has been set for the realm key, though it may be disabled (FALSE)
* - Active, The realm key has been set and is not FALSE.
*/
// Prefix for realm keys on query string.
define('VARIABLE_REALM_QUERY_STRING', 'variable_realm_key_');
// Prefix for realm switcher element in forms.
define('VARIABLE_REALM_FORM_SWITCHER', 'variable_realm_selector_');
/**
* Implements hook_boot()
*
* We set current variable realms as early as possible in the page request.
*/
function variable_realm_boot() {
variable_realm_status('global', 'default');
variable_realm_rebuild();
}
/**
* Implements hook_init()
*
* Let realms be overriden by query string parameters, but only for:
* - Admin paths (not variable admin pages)
*/
function variable_realm_init() {
if (arg(0) == 'admin' && arg(3) != 'variable' && ($params = variable_realm_params()) && user_access('administer site configuration')) {
foreach ($params as $realm_name => $realm_key) {
variable_realm_switch($realm_name, $realm_key, FALSE);
}
variable_realm_rebuild();
}
}
/**
* Initialize realm and set key depending on request.
*
* @param $realm_name
* Variable realm name.
* @param $realm_key
* Optional key to be set when we don't have other key.
*/
function variable_realm_initialize($realm_name, $realm_key = NULL) {
$realm_controller = variable_realm_controller($realm_name);
if ($realm_controller && !$realm_controller->isEnabled()) {
$new_key = $realm_controller->enable($realm_key);
_variable_realm_invoke_all('variable_realm_enable', $realm_name, $new_key);
_variable_realm_hook('variableRealmEnable', $realm_name, $new_key);
// If we have already built the configuration, rebuild it.
if ($new_key && drupal_static('variable_realm_rebuild')) {
variable_realm_rebuild();
}
}
}
/**
* Get list of all available realm names ordered by default weight.
*/
function variable_realm_list() {
return _variable_realm_invoke(variable_realm_list_all(), 'getTitle');
}
/**
* Get all available realm controllers ordered by default weight.
*/
function variable_realm_list_all() {
$list = array();
foreach (array_keys(variable_realm_info()) as $name) {
if ($controller = variable_realm_controller($name)) {
$list[$name] = $controller;
}
uasort($list, '_variable_realm_sort_default');
}
return $list;
}
/**
* Get realm parameters from query string.
*/
function variable_realm_params($realm_name = NULL) {
$realm_params = &drupal_static(__FUNCTION__);
if (!isset($realm_params)) {
$realm_params = array();
foreach (variable_realm_info() as $realm => $realm_info) {
if (!empty($realm_info['form switcher'])) {
$param = VARIABLE_REALM_QUERY_STRING . $realm;
if (!empty($_GET[$param]) && array_key_exists($_GET[$param], variable_realm_keys($realm))) {
$realm_params[$realm] = $_GET[$param];
}
}
}
}
if ($realm_name) {
return isset($realm_params[$realm_name]) ? $realm_params[$realm_name] : FALSE;
}
else {
return $realm_params;
}
}
/**
* Get information about variable realms.
*/
function variable_realm_info($realm_name = NULL) {
$realm_info_tmp = $realm_info = &drupal_static(__FUNCTION__);
if (!isset($realm_info_tmp)) {
$realm_info_tmp = _variable_realm_invoke_all('variable_realm_info');
// If first param is NULL, module_load_all() only returns a boolean
// indicating whether all modules have been loaded.
if (module_load_all(NULL)) {
// Due to the fact that variable_realm_info() gets called by some
// modules and the menu access callbacks early in the bootstrap,
// we could not cache the realm info for later calls until all
// modules have been loaded.
$realm_info = $realm_info_tmp;
}
}
if ($realm_name) {
return isset($realm_info_tmp[$realm_name]) ? $realm_info_tmp[$realm_name] : array();
}
else {
return $realm_info_tmp;
}
}
/**
* Implements hook_variable_realm_info().
*/
function variable_realm_variable_realm_info() {
$realm['global'] = array(
'title' => t('Global'),
'weight' => 0,
'controller class' => 'VariableRealmDefaultController',
'store class' => 'VariableRealmGlobalStore',
'keys' => array(
'default' => t('All variables')
),
);
return $realm;
}
/**
* Get keys for realm.
*/
function variable_realm_keys($realm_name) {
if ($controller = variable_realm_controller($realm_name)) {
return $controller->getAllKeys();
}
}
/**
* Get variable realm store.
*
* The first time this function is invoked we initialize the realm system
* and store global variables in the global/default realm.
*
* @param $realm
* Name of the realm to get / create.
* @param $key
* Realm key to get / create
*
* @return VariableRealmControllerInterface
*/
function variable_realm($realm, $key) {
$controller = variable_realm_controller($realm);
return $controller ? $controller->getStore($key) : NULL;
}
/**
* Get variable realm controller or create it if not defined.
*/
function variable_realm_controller($realm_name = NULL) {
static $drupal_static_fast;
if (!isset($drupal_static_fast)) {
$drupal_static_fast['realm'] = &drupal_static(__FUNCTION__, array());
if ($global = _variable_realm_controller('global')) {
$global->addStore('default', $GLOBALS['conf']);
$drupal_static_fast['realm']['global'] = $global;
}
}
$variable_realm = &$drupal_static_fast['realm'];
if ($realm_name) {
if (!isset($variable_realm[$realm_name])) {
$variable_realm[$realm_name] = _variable_realm_controller($realm_name);
}
return $variable_realm[$realm_name];
}
else {
// Return only existing realms.
return array_filter($variable_realm);
}
}
/**
* Get value from realm
*/
function variable_realm_get($realm, $key, $name = NULL, $default = NULL) {
if ($store = variable_realm($realm, $key)) {
return $store->variable_get($name, $default);
}
}
/**
* Set values for variable realm
*
* @param $realm
* Realm name.
* @param $key
* Realm key.
* @param $values
* Array of runtime variable values to add to the realm.
* @param $weight
* Optional explicit weight for this realm.
* @param $rebuild
* Whether to rebuild domains immediately
*/
function variable_realm_add($realm, $key, $values = array(), $weight = NULL, $rebuild = TRUE) {
if ($variable_realm = variable_realm($realm, $key)) {
foreach ($values as $name => $value) {
$variable_realm->variable_add($name, $value);
}
if (isset($weight)) {
variable_realm_weight($realm, $weight);
}
// Rebuild only if this is the current realm
if ($rebuild && variable_realm_status($realm) === $key) {
variable_realm_rebuild();
}
}
}
/**
* Set value for realm variable.
*/
function variable_realm_set($realm, $key, $name, $value, $rebuild = TRUE) {
if ($store = variable_realm($realm, $key)) {
$old_value = variable_realm_get($realm, $key, $name);
$store->variable_set($name, $value);
if ($rebuild) {
variable_realm_refresh($realm, $key, $name);
}
$options = array(
'realm' => $store->realm,
'key' => $store->key,
);
module_invoke_all('variable_update', $name, $value, $old_value, $options);
}
}
/**
* Delete variable from realm
*/
function variable_realm_del($realm, $key, $name, $rebuild = TRUE) {
if ($store = variable_realm($realm, $key)) {
$store->variable_del($name);
if ($rebuild) {
variable_realm_refresh($realm, $key, $name);
}
}
}
/**
* Refresh variable value.
*/
function variable_realm_refresh($realm_name, $realm_key, $variable_name) {
$value = NULL;
// Only update value if this is the current realm.
if (variable_realm_status($realm_name) === $realm_key) {
foreach (variable_realm_current() as $realm_controller) {
$value = $realm_controller->getCurrentStore()->variable_get($variable_name, $value);
}
}
if (isset($value)) {
$GLOBALS['conf'][$variable_name] = $value;
}
else {
unset($GLOBALS['conf'][$variable_name]);
}
}
/**
* Get active realm controllers ordered by weight.
*/
function variable_realm_current() {
$active = array_filter(variable_realm_controller(), '_variable_realm_active');
uasort($active, '_variable_realm_sort_current');
return $active;
}
/**
* Check whether a realm is defined.
*/
function variable_realm_defined($realm_name) {
$controllers = variable_realm_controller();
return !empty($controllers[$realm_name]);
}
/**
* Get current realm values ordered by weights, only realms that are set.
*
* @return array
* Ordered array of name => key pairs.
*/
function variable_realm_current_keys() {
return array_map('_variable_realm_status', variable_realm_current());
}
/**
* Get current realm values ordered by weights.
*
* @return array
* Ordered array of name => value pairs, only realms that are set.
*/
/**
* Get original global variable
*/
function variable_realm_global_get($name, $default = NULL) {
return variable_realm_get('global', 'default', $name, $default);
}
/**
* Switch global variable
*
* @param $name
* Optional global variable name. If not set, it will reset all global variables to its original value.
* @param $value
* Optional new value for global variable. If not set, it will reset the variable to its original value.
* @param $rebuild
* Whether to rebuild the current global $conf
*/
function variable_realm_global_set($name, $value = NULL, $rebuild = TRUE) {
variable_realm_set('global', 'default', $name, $value, $rebuild);
}
/**
* Set / get current realm values.
*
* @param $realm
* Optional realm name
* @param $key
* Optional realm value to set a status for this realm.
* FALSE to disable this realm.
*/
function variable_realm_status($realm, $key = NULL) {
if ($realm_controller = variable_realm_controller($realm)) {
if (isset($key)) {
$realm_controller->setKey($key);
}
return $realm_controller->getKey();
}
}
/**
* Switch current variable realms.
*
* @see variable_realm_weight()
*
* @param $realm
* Realm name. Example 'language'.
* @param $key
* Realm key. Example, for language will be a language code, 'en
* FALSE to unset the realm.
* @param $rebuild
* Whether we need to rebuild the configuration.
*/
function variable_realm_switch($realm, $key, $rebuild = TRUE) {
// Check previous status, if not changed no need to rebuild.
$current = variable_realm_status($realm);
if (!isset($current) || $current !== $key) {
variable_realm_status($realm, $key);
_variable_realm_invoke_all('variable_realm_switch', $realm, $key);
_variable_realm_hook('variableRealmSwitch', $realm, $key);
if ($rebuild) {
variable_realm_rebuild();
}
}
}
/**
* Get / set realm weights.
*
* The default realm will have a weight of 0. Realms with higher weights will override
* global variables.
*
* @param $realm
* Realm name
* @param $weight
* Optional numeric value for realm weight.
* @return integer
* Current realm weight
*/
function variable_realm_weight($realm, $weight = NULL) {
if ($realm_controller = variable_realm_controller($realm)) {
if (isset($weight)) {
$realm_controller->setWeight($weight);
}
return $realm_controller->getWeight();
}
}
/**
* Rebuild current variable realm.
*/
function variable_realm_rebuild() {
$rebuild_keys = &drupal_static(__FUNCTION__);
_variable_realm_invoke_all('variable_realm_rebuild');
$rebuild_keys = variable_realm_current_keys();
$GLOBALS['conf'] = _variable_realm_build();
}
/**
* Reset realms, deleting currently set ones
*
* If no parameters passed, it will reset global variables to original values.
*
* @param $realm_keys
* Array of realm name => realm key to be set.
*/
function variable_realm_reset($realm_keys = array()) {
// We need at least some value for the global realm
$status = $realm_keys + array('global', 'default');
// Disable current active realms not in the list
foreach (variable_realm_current() as $realm_name => $realm_controller) {
if (!isset($status[$realm_name])) {
variable_realm_switch($realm_name, FALSE, FALSE);
}
}
foreach ($status as $realm_name => $realm_key) {
variable_realm_switch($realm_name, $realm_key, FALSE);
}
variable_realm_rebuild();
}
/**
* Implements hook_variable_delete().
*/
function variable_realm_variable_delete($variable, $options) {
// If there's a realm option, we are already deleting variable for a realm only.
if (empty($options['realm'])) {
// Delete each variable for each current and existing realm/key
foreach (variable_children($variable['name']) as $variable_name) {
foreach (variable_realm_list_all() as $realm_controller) {
$realm_controller->deleteVariable($variable_name);
}
}
variable_realm_rebuild();
}
}
/**
* Implements hook_features_api().
*/
function variable_realm_features_api() {
$components = array(
'variable_realm' => array(
'name' => t('Realm variables'),
'default_hook' => 'variable_realm_default_variables',
'default_file' => FEATURES_DEFAULTS_CUSTOM,
'default_filename' => 'variable',
'features_source' => TRUE,
'file' => drupal_get_path('module', 'variable_realm') .'/variable_realm.features.inc',
),
);
return $components;
}
/**
* Check whether realm is active.
*/
function _variable_realm_active($realm_controller) {
return $realm_controller && $realm_controller->isActive();
}
/**
* Build current realm.
*
* Buids an array of variables for the current realm with higher weights overriding
* lower weights.
*/
function _variable_realm_build() {
$variables = array();
foreach (variable_realm_current() as $realm_controller) {
if ($values = $realm_controller->getCurrentVariables()) {
$variables = array_merge($variables, $values);
}
}
return $variables;
}
/**
* Invoke method on a list of objects.
*/
function _variable_realm_invoke($list, $method) {
$result = array();
foreach ($list as $index => $object) {
$result[$index] = $object->$method();
}
return $result;
}
/**
* Invokes all realm controllers that implement a method.
*
* @param $method
* Method name
* @param $arg1, $arg2...
* Variable number of arguments to pass to the method.
*/
function _variable_realm_hook() {
$args = func_get_args();
$method = array_shift($args);
$result = array();
foreach (variable_realm_controller() as $realm_name => $realm_controller) {
if (method_exists($realm_controller, $method)) {
$result[$realm_name] = call_user_func_array(array($realm_controller, $method), $args);
}
}
return $result;
}
/**
* Create realm controller object.
*
* This may be invoked really early in the bootstrap so it needs to be safe enough
* for module updates and check whether the class really exists. It returns FALSE if not.
*/
function _variable_realm_controller($realm_name) {
$info = variable_realm_info($realm_name);
$class = !empty($info['controller class']) ? $info['controller class'] : 'VariableRealmDefaultController';
return class_exists($class) ? new $class($realm_name) : FALSE;
}
/**
* Get current weight for realm controller.
*/
function _variable_realm_weight($realm_controller) {
return $realm_controller->getWeight();
}
/**
* Order realms by default weight.
*/
function _variable_realm_sort_default($a, $b) {
return $a->getDefaultWeight() - $b->getDefaultWeight();
}
/**
* Order realms by current weight.
*/
function _variable_realm_sort_current($a, $b) {
return $a->getWeight() - $b->getWeight();
}
/**
* Get status (current key) for realm controller.
*/
function _variable_realm_status($realm_controller) {
return $realm_controller->getKey();
}
/**
* Invoke variable realm hook on all currently loaded modules.
*
* Variable realm usually starts from bootstrap, on hook_boot() and from here it is not
* safe to user regular hook invokation so we use our own function, similar to
* bootstrap_invoke_all() but returning the values (with deep merge).
*
* @see boostrap_invoke_all()
* @see module_invoke()
*
* @pram $hook
* Hook to invoke in all loaded modules
* @param $arg1, $arg2...
* A variable number of arguments.
*/
function _variable_realm_invoke_all() {
$args = func_get_args();
$hook = array_shift($args);
$result = array();
foreach (module_list() as $module) {
if (module_hook($module, $hook) && $merge = call_user_func_array($module . '_' . $hook, $args)) {
$result = drupal_array_merge_deep($result, $merge);
unset($merge);
}
}
return $result;
}
/**
* Implements hook_form_FORM_ID_alter()
*/
function variable_realm_form_system_theme_settings_alter(&$form, &$form_state, $form_id) {
module_load_include('form.inc', 'variable_realm');
$theme_variable = $form['var']['#value'];
foreach (_variable_realm_variable_settings_form_list() as $realm_name => $variables) {
if (in_array($theme_variable, variable_children($variables))) {
// Mark theme settings and include other variables in the form.
_variable_realm_variable_settings_form_mark($realm_name, $form['theme_settings']);
$realm_variables = element_children($form);
$realm_variables = array_merge($realm_variables, array('default_logo', 'logo_path', 'default_favicon', 'favicon_path'));
_variable_realm_variable_settings_form_alter($form, $realm_name, $realm_variables);
// Replace variable (theme) name so we use a temporary storage variable
$form['#realm_variables'][$realm_name] = $realm_variables;
// This is a single variable so there can be one realm only.
$form['#realm_theme'] = $realm_name;
break;
}
}
if (!empty($form['#realm_theme'])) {
// Replace callback and user our own realm function.
$form['#submit'] = str_replace('system_theme_settings_submit', 'variable_realm_variable_theme_form_submit', $form['#submit']);
// Add realm switcher/s.
_variable_realm_variable_settings_form_switcher($form);
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* @file
* Variable hooks.
*/
/**
* Implements hook_variable_info().
*/
function variable_realm_variable_info($options) {
$variables['variable_realm_list_[variable_realm]'] = array(
'type' => 'multiple',
'group' => 'variable',
'multiple' => 'variable_realm',
'title' => t('Realm list', array(), $options),
'description' => t('List of variables that can be set for a realm.', array(), $options),
'repeat' => array(
'type' => 'array',
),
);
$variables['variable_realm_weight_[variable_realm]'] = array(
'type' => 'multiple',
'group' => 'variable',
'multiple' => 'variable_realm',
'title' => t('Realm weight', array(), $options),
'description' => t('Override default weight for realm variables.', array(), $options),
'repeat' => array(
'type' => 'number',
),
);
return $variables;
}
/**
* Implements hook_variable_type_info().
*/
function variable_realm_variable_type_info() {
$type['variable_realm'] = array(
'title' => t('Variable realm'),
'type' => 'select',
'options callback' => 'variable_realm_list',
);
return $type;
}
/**
* Implements hook_variable_settings_form_alter().
*/
function variable_realm_variable_settings_form_alter(&$form, &$form_state, $form_id) {
module_load_include('form.inc', 'variable_realm');
foreach (_variable_realm_variable_settings_form_list() as $realm_name => $variables) {
if ($realm_variables = _variable_realm_variable_settings_form_alter($form, $realm_name, variable_children($variables))) {
$form['#realm_variables'][$realm_name] = $realm_variables;
}
}
if (!empty($form['#realm_variables'])) {
array_unshift($form['#submit'], 'variable_realm_variable_settings_form_submit');
// Add form switcher and current key for each realm.
_variable_realm_variable_settings_form_switcher($form);
}
}

View File

@@ -0,0 +1,155 @@
<?php
/**
* @file
* Classes for Realm Union.
*/
/**
* Default Realm Union class
*/
class VariableRealmUnionController extends VariableRealmDefaultController implements VariableRealmHooks {
protected $union_realms;
/**
* Implementation of VariableRealmControllerInterface::__construct().
*/
public function __construct($realm_name) {
parent::__construct($realm_name);
// Get / create realm controllers for each of the union realms.
foreach ($this->getParentRealms() as $realm_name) {
$this->union_realms[$realm_name] = variable_realm_controller($realm_name);
}
}
/**
* Implementation of VariableRealmControllerInterface::start().
*/
public function start($realm_key = NULL) {
if (!isset($this->current_key)) {
if (isset($realm_key)) {
return $this->current_key = $realm_key;
}
elseif ($request_key = $this->getRequestKey()) {
return $this->current_key = $request_key;
}
}
}
/**
* Implementation of VariableRealmControllerInterface::getAllKeys().
*/
public function getAllKeys() {
$all_realm_keys = $this->invokeUnionRealms('getAllKeys');
// First build all combinations of realm keys.
$combine = array(array('keys' => array(), 'names' => array()));
foreach ($all_realm_keys as $realm => $realm_keys) {
$new_combine = array();
foreach ($combine as $index => $data) {
foreach ($realm_keys as $new_key => $new_name) {
$keys = $data['keys'];
$names = $data['names'];
$keys[$realm] = $new_key;
$names[$realm] = $new_name;
$new_combine[] = array('keys' => $keys, 'names' => $names);
}
}
$combine = $new_combine;
}
// Now build all realm keys for the combinations.
$keys = array();
foreach ($combine as $data) {
$key = $this->buildUnionKey($data['keys']);
$name = $this->buildUnionName($data['names']);
$keys[$key] = $name;
}
return $keys;
}
/**
* Implementation of VariableRealmControllerInterface::getDefaultKey().
*/
public function getDefaultKey() {
$keys = $this->invokeUnionRealms('getDefaultKey');
return $this->buildUnionKey($keys);
}
/**
* Implementation of VariableRealmControllerInterface::getRequestKey().
*/
public function getRequestKey() {
// We'll have a request key if union realms have a current key.
$keys = $this->invokeUnionRealms('getKey');
return $this->buildUnionKey($keys);
}
/**
* Implementation of VariableRealmControllerInterface::getAvailableVariables().
*/
public function getAvailableVariables() {
$variables = $this->invokeUnionRealms('getAvailableVariables');
return call_user_func_array('array_intersect', $variables);
}
/**
* Implementation of VariableRealmControllerInterface::getEnabledVariables().
*/
public function getEnabledVariables() {
$variables = $this->invokeUnionRealms('getEnabledVariables');
return call_user_func_array('array_intersect', $variables);
}
/**
* Implementation of VariableRealmControllerInterface::getParentRealms().
*/
public function getParentRealms() {
return $this->getInfo('union', array());
}
/**
* Get union realms controllers.
*/
protected function getUnionRealms() {
return $this->union_realms;
}
/**
* Implementation of VariableRealmHooks::variableRealmEnable()
*/
public function variableRealmEnable($realm_name, $realm_key) {
// If this realm is enabled but not active, try to find a key.
if ($this->isEnabled() && !$this->isActive() && $this->isUnionRealm($realm_name) && $union_key = $this->getRequestKey()) {
$this->setKey($union_key);
}
}
/**
* Implementation of VariableRealmHooks::variableRealmSwitch()
*/
public function variableRealmSwitch($realm_name, $realm_key) {
// If the this realm is active, try to find new key.
if ($this->isActive() && $this->isUnionRealm($realm_name) && ($union_key = $this->getRequestKey())) {
$this->setKey($union_key);
}
}
/**
* Check whether a realm belongs to the union realms.
*/
protected function isUnionRealm($realm_name) {
return isset($this->union_realms[$realm_name]);
}
/**
* Invoke function on all realms.
*/
protected function invokeUnionRealms($method) {
return _variable_realm_invoke($this->getUnionRealms(), $method);
}
/**
* Build key from union realm keys.
*/
protected static function buildUnionKey($keys) {
if (in_array(FALSE, $keys, TRUE)) {
return FALSE;
}
else {
// Make sure values are in correct order
ksort($keys);
// implode values
return implode(':', $keys);
}
}
/**
* Build key name from union realm key names.
*/
protected static function buildUnionName($names) {
return implode(', ', $names);
}
}