Commit fc10987f authored by young hahn's avatar young hahn
Browse files

#533354: Implement weakarm mode for strongarm.

parent 721c5ded
<?php
// $Id$
/**
* Main admin page menu callback.
*/
function strongarm_admin_page() {
$output = '';
$output .= drupal_get_form('strongarm_admin_settings_form');
if (variable_get('strongarm_mode', STRONGARM_MODE_STRONG) == STRONGARM_MODE_WEAK) {
$output .= drupal_get_form('strongarm_admin_form');
}
return $output;
}
/**
* Get a map of variable to culprit (implementers of hook_strongarm()).
*/
function strongarm_get_culprits() {
$culprits = array();
foreach (module_implements('strongarm') as $module) {
$module_conf = module_invoke($module, 'strongarm');
foreach ($module_conf as $name => $value) {
$culprits[$name] = $module;
}
}
return $culprits;
}
/**
* Settings form.
*/
function strongarm_admin_settings_form() {
$form = array();
$form['strongarm_mode'] = array(
'#title' => t('Strongarm mode'),
'#description' => t('Choose the strength of strongarm\'s restrictive behavior.'),
'#type' => 'radios',
'#options' => array(
STRONGARM_MODE_STRONG => t('Force variables values'),
STRONGARM_MODE_WEAK => t('Allow variable overrides'),
),
'#default_value' => variable_get('strongarm_mode', STRONGARM_MODE_STRONG),
);
$form['strongarm_show_messages'] = array(
'#title' => t('Show messages'),
'#description' => t('Show helper messages to site administrators when variables have been strongarmed or overridden.'),
'#type' => 'checkbox',
'#default_value' => variable_get('strongarm_show_messages', TRUE),
);
return system_settings_form($form);
}
/**
* Variable management strongarm form.
*/
function strongarm_admin_form() {
$form = array();
$var_conf = strongarm_get_conf();
$culprits = strongarm_get_culprits();
$overridden = array();
$result = db_query("SELECT * FROM {variable} ORDER BY name ASC");
while ($row = db_fetch_object($result)) {
$value = unserialize($row->value);
if (isset($var_conf[$row->name]) && $var_conf[$row->name] != $value) {
$overridden[$row->name] = $value;
}
}
if (!empty($overridden)) {
$form = array('#theme' => 'strongarm_admin_form',);
foreach ($overridden as $name => $value) {
$form['revert']['#tree'] = TRUE;
$form['revert'][$name] = array('#type' => 'checkbox');
$form['name'][$name] = array(
'#type' => 'markup',
'#value' => $name,
);
$form['current_value'][$name] = array(
'#type' => 'markup',
'#value' => _strongarm_readable($overridden[$name]),
);
$form['default_value'][$name] = array(
'#type' => 'markup',
'#value' => _strongarm_readable($var_conf[$name]),
);
$form['culprit'][$name] = array(
'#type' => 'markup',
'#value' => $culprits[$name],
);
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Revert'),
'#submit' => array('strongarm_admin_revert_submit'),
);
}
return $form;
}
/**
* Revert form submit handler.
*/
function strongarm_admin_revert_submit(&$form, &$form_state) {
if (!empty($form_state['values']['revert'])) {
foreach ($form_state['values']['revert'] as $name => $revert) {
if ($revert) {
variable_del($name);
}
}
// Re-set strongarm and variable caches
strongarm_flush_caches();
$var_conf = strongarm_get_conf();
strongarm_set_conf($var_conf);
}
}
/**
* Recursive function that hunts down form elements that are likely to
* be related to strongarm'd variables and locks them down.
*/
function _strongarm_lockdown(&$form, $pattern = '', $position = STRONGARM_PATTERN_PREFIX) {
$var_conf = strongarm_get_conf();
foreach (element_children($form) as $elem) {
$children = element_children($form[$elem]);
$key = $elem;
$match = FALSE;
if (isset($var_conf[$key])) {
$match = TRUE;
}
else if (!empty($pattern)) {
$key = ($position == STRONGARM_PATTERN_PREFIX) ? "{$pattern}_{$key}" : "{$key}_{$pattern}";
if (isset($var_conf[$key])) {
$match = TRUE;
}
}
if ($match) {
// If the default form value matches the strongarm value,
// it is highly likely we have a match. Disable the field.
if (isset($form[$elem]['#default_value']) && $var_conf[$key] == $form[$elem]['#default_value']) {
$form[$elem]['#disabled'] = TRUE;
$form[$elem]['#value'] = $form[$elem]['#default_value'];
}
if (!isset($form[$elem]['#attributes']['class'])) {
$form[$elem]['#attributes']['class'] = "strongarm";
}
else {
$form[$elem]['#attributes']['class'] .= " strongarm";
}
$altered = TRUE;
}
// If this is a tree'd element, recurse
if (!empty($form[$elem]['#tree']) || !empty($children)) {
$altered = _strongarm_lockdown($form[$elem], $pattern, $position) || $altered;
}
}
return $altered;
}
/**
* Display variables in a nicer way.
*/
function _strongarm_readable($var) {
if (is_string($var) || is_bool($var) || is_numeric($var)) {
return $var;
}
else if (is_array($var)) {
$test = $detected = array();
$test['keys'] = array_keys($var);
$test['values'] = array_values($var);
foreach ($test as $type => $values) {
$numeric = TRUE;
$sequential = 0;
$boolean = TRUE;
foreach ($values as $v) {
$numeric = is_numeric($v) && $numeric;
$sequential = is_numeric($v) && ($sequential == $v) && $sequential !== FALSE ? $sequential + 1 : FALSE;
$boolean = $boolean && ($v === 0 || $v === 1 || $v === '1' || $v === '0' || $v === TRUE || $v === FALSE);
}
$detected[$type]['numeric'] = $numeric;
$detected[$type]['sequential'] = $sequential !== FALSE;
$detected[$type]['boolean'] = $boolean;
}
// List of things
if (!empty($var) && $detected['keys']['numeric'] && $detected['keys']['sequential']) {
return implode(', ', $var);
}
return '-';
}
}
/**
* Theme function for the strongarm admin form.
*/
function theme_strongarm_admin_form($form) {
$output = '';
$overridden = element_children($form['revert']);
if (!empty($overridden)) {
drupal_add_js('misc/tableselect.js');
$rows = $headers = array();
$output .= "<h3>". t('Manage overridden variables') ."</h3>";
// Add checkboxes to the header and the rows.
$headers[] = theme('table_select_header_cell');
$headers[] = t('Variable');
$headers[] = t('Current value');
$headers[] = t('Module value');
$headers[] = t('Module');
foreach ($overridden as $name) {
$row = array();
$row[] = drupal_render($form['revert'][$name]);
$row[] = drupal_render($form['name'][$name]);
$row[] = drupal_render($form['current_value'][$name]);
$row[] = drupal_render($form['default_value'][$name]);
$row[] = drupal_render($form['culprit'][$name]);
$rows[] = $row;
}
$output .= theme('table', $headers, $rows);
$output .= drupal_render($form);
}
return $output;
}
......@@ -4,36 +4,117 @@
define('STRONGARM_PATTERN_PREFIX', 0);
define('STRONGARM_PATTERN_SUFFIX', 1);
define('STRONGARM_MODE_STRONG', 0);
define('STRONGARM_MODE_WEAK', 1);
/**
* Implementation of hook_boot().
* This is a very aggressive way of ensuring that these variables are
* set. Necessary for variables that are checked by modules on hook_init().
*/
function strongarm_boot() {
global $conf;
$var_conf = strongarm_get_cache();
$var_conf = strongarm_get_conf(FALSE);
strongarm_set_conf($var_conf);
}
/**
* Implementation of hook_init().
*/
function strongarm_init() {
$var_conf = strongarm_get_conf();
strongarm_set_conf($var_conf);
// Display a status message if any variables are overridden.
if ($_GET['q'] != 'admin/settings/strongarm' && variable_get('strongarm_mode', STRONGARM_MODE_STRONG) == STRONGARM_MODE_WEAK) {
$overridden = strongarm_overridden_vars();
if (arg(0) == 'admin' && !empty($overridden) && user_access('administer site configuration') && variable_get('strongarm_show_messages', TRUE)) {
drupal_set_message(t('The following variables have overridden values: !vars. Manage these variables on the !strongarm_page.', array('!vars' => implode(', ', $overridden), '!strongarm_page' => l(t('Strongarm admin page'), 'admin/settings/strongarm'))), 'warning', FALSE);
}
}
}
/**
* Retrieve variable configuration from the cache.
*/
function strongarm_get_conf($bootstrapped = TRUE, $reset = FALSE) {
static $var_conf;
if (!isset($var_conf) || $reset) {
if (!$reset) {
$cache = cache_get('strongarm', 'cache');
$var_conf = $cache ? $cache->data : NULL;
}
if (!isset($var_conf) && $bootstrapped) {
// We don't use module_invoke_all() here since
// array_merge_recursive() can alter the desired structure of
// some variables.
foreach (module_implements('strongarm') as $module) {
$module_conf = module_invoke($module, 'strongarm');
foreach ($module_conf as $name => $value) {
if (isset($var_conf[$name])) {
if (is_array($value)) {
$var_conf[$name] = array_merge($var_conf[$name], $value);
}
else {
// Blow the earlier one away
$var_conf[$name] = $value;
}
}
else {
$var_conf[$name] = $value;
}
}
}
cache_set('strongarm', $var_conf);
}
}
return $var_conf;
}
/**
* Sets the global configuration. When in Weakarm mode, will log any
* values that have been overridden and leave their conf values alone.
*/
function strongarm_set_conf($var_conf = array()) {
if (!empty($var_conf)) {
global $conf;
foreach ($var_conf as $k => $v) {
$conf[$k] = $v;
// The variable is overridden -- let it be, but log the override if we are in Weakarm mode.
if ((variable_get('strongarm_mode', STRONGARM_MODE_STRONG) == STRONGARM_MODE_WEAK) && isset($conf[$k]) && $conf[$k] != $v) {
strongarm_overridden_vars($k);
}
else {
$conf[$k] = $v;
}
}
}
}
/**
* Implementation of hook_init().
* Log overridden values.
*/
function strongarm_init() {
$var_conf = strongarm_get_cache();
if (empty($var_conf)) {
strongarm_set_cache(TRUE);
function strongarm_overridden_vars($set = '') {
static $overridden = array();
if (!empty($set)) {
$overridden[$set] = $set;
}
return $overridden;
}
/**
* Implementation of hook_flush_caches().
* Implementation of hook_menu().
*/
function strongarm_flush_caches() {
strongarm_invalidate_cache();
function strongarm_menu() {
$items = array();
$items['admin/settings/strongarm'] = array(
'title' => 'Strongarm',
'description' => 'Manage Drupal variable settings that have been strongarmed.',
'page callback' => 'strongarm_admin_page',
'access callback' => 'user_access',
'access arguments' => array('administer site configuration'),
'file' => 'strongarm.admin.inc',
'type' => MENU_NORMAL_ITEM,
);
return $items;
}
/**
......@@ -50,122 +131,37 @@ function strongarm_form_alter(&$form, &$form_state, $form_id) {
$pattern = $form['#node_type']->type;
$position = STRONGARM_PATTERN_SUFFIX;
}
if (!empty($lockdown)) {
else if (arg(0) === 'admin' && $form_id != 'strongarm_admin_form') {
$lockdown = TRUE;
}
if (!empty($lockdown) && variable_get('strongarm_mode', STRONGARM_MODE_STRONG) == STRONGARM_MODE_STRONG) {
module_load_include('inc', 'strongarm', 'strongarm.admin');
drupal_add_css(drupal_get_path('module', 'strongarm') .'/strongarm.css');
$altered = _strongarm_lockdown($form, $pattern, $position);
if ($altered) {
drupal_set_message(t('The highlighted fields below may need to retain their current values for your site to operate properly. Settings may be disabled or reverted automatically if they are not compatible with one or more of your site\'s modules.'), 'warning');
if (_strongarm_lockdown($form, $pattern, $position) && variable_get('strongarm_show_message', TRUE)) {
drupal_set_message(t('The hilighted fields below may need to retain their current values for your site to operate properly. Settings may be disabled or reverted automatically if they are not compatible with one or more of your site\'s modules.'), 'warning', FALSE);
}
}
}
/**
* Retrieve variable configuration from the cache.
*/
function strongarm_get_cache($reset = FALSE) {
static $conf;
if (!isset($conf) || $reset) {
$conf = array();
$cache = cache_get('strongarm', 'cache');
if ($cache) {
$conf = $cache->data;
}
// Clear strongarm & variable caches on modules page.
if ($form_id == 'system_module') {
strongarm_flush_caches();
}
return $conf;
}
/**
* Set the variable configuration cache. Optionally overrides the global
* $conf array as well to populate variable values.
* Implementation of hook_theme().
*/
function strongarm_set_cache($set_vars = FALSE) {
$var_conf = array();
// We don't use module_invoke_all() here since
// array_merge_recursive() can alter the desired structure of
// some variables.
foreach (module_implements('strongarm') as $module) {
$module_conf = module_invoke($module, 'strongarm');
foreach ($module_conf as $name => $value) {
if (isset($var_conf[$name])) {
if (is_array($value)) {
$var_conf[$name] = array_merge($var_conf[$name], $value);
}
else {
// Blow the earlier one away
$var_conf[$name] = $value;
}
}
else {
$var_conf[$name] = $value;
}
}
}
cache_set('strongarm', $var_conf);
if ($set_vars) {
global $conf;
if (!empty($var_conf)) {
foreach ($var_conf as $k => $v) {
$conf[$k] = $v;
}
}
}
function strongarm_theme() {
return array(
'strongarm_admin_form' => array(),
);
}
/**
* Invalidates the strongarm cache.
* Implementation of hook_flush_caches().
*/
function strongarm_invalidate_cache() {
function strongarm_flush_caches() {
cache_clear_all('variables', 'cache');
cache_clear_all('strongarm', 'cache');
}
/**
* Recursive function that hunts down form elements that are likely to
* be related to strongarm'd variables and locks them down.
*/
function _strongarm_lockdown(&$form, $pattern = '', $position = STRONGARM_PATTERN_PREFIX) {
$altered = FALSE;
$var_conf = strongarm_get_cache();
foreach (element_children($form) as $elem) {
$children = element_children($form[$elem]);
$key = $elem;
$match = FALSE;
if (isset($var_conf[$key])) {
$match = TRUE;
}
else if (!empty($pattern)) {
$key = ($position == STRONGARM_PATTERN_PREFIX) ? "{$pattern}_{$key}" : "{$key}_{$pattern}";
if (isset($var_conf[$key])) {
$match = TRUE;
}
}
if ($match) {
// If the default form value matches the strongarm value,
// it is highly likely we have a match. Disable the field.
if (isset($form[$elem]['#default_value']) && $var_conf[$key] == $form[$elem]['#default_value']) {
$form[$elem]['#disabled'] = TRUE;
$form[$elem]['#value'] = $form[$elem]['#default_value'];
}
if (!isset($form[$elem]['#attributes']['class'])) {
$form[$elem]['#attributes']['class'] = "strongarm";
}
else {
$form[$elem]['#attributes']['class'] .= " strongarm";
}
$altered = TRUE;
}
// If this is a tree'd element, recurse
if (!empty($form[$elem]['#tree']) || !empty($children)) {
$altered = $altered || _strongarm_lockdown($form[$elem], $pattern, $position);
}
}
return $altered;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment