', $form['note']['#value']);
}
return $form;
}
function _forum_access_forum_form_after_build($form, &$form_state) {
if (isset($form_state['clicked_button']['#name']) && $form_state['clicked_button']['#name'] == $form['template']['load_button']['#name']) {
// Load a setting from a template:
$template_tid = reset(array_values($form['#post']['forum_access']['template']['taxonomy']));
$form_state['values']['forum_access']['template']['template_tid'] = $template_tid;
$form['template']['#collapsed'] = FALSE;
$settings = _forum_access_get_settings($template_tid);
foreach (array('view', 'create', 'update', 'delete') as $grant_type) {
if (empty($form[$grant_type])) {
continue;
}
foreach (element_children($form[$grant_type]) as $tid) {
$checked = array_search($tid, $settings[$grant_type]) !== FALSE;
$form[$grant_type][$tid]['#value'] = ($checked ? $tid : 0);
}
}
$form['interference']['advanced']['priority']['#value'] = $settings['priority'];
if ($settings['priority'] != 0) {
$form['interference']['advanced']['#collapsed'] = FALSE;
}
}
elseif (is_array(reset($form_state['values']['forum_access']['template']['taxonomy']))) {
$template_tid = reset(reset($form_state['values']['forum_access']['template']['taxonomy']));
}
if (isset($template_tid)) {
$form['template']['select_by_default']['#value'] = ($template_tid && $template_tid == variable_get('forum_access_default_template_tid', 0));
$form['template']['load_for_new']['#value'] = ($template_tid && $template_tid == variable_get('forum_access_new_template_tid', 0));
}
return $form;
}
function _forum_access_form_validate($form, &$form_state) {
global $user;
if ($user->uid == 1) {
return;
}
$access = $form_state['values']['forum_access']; // shortcut
foreach ($access['view'] as $rid => $checked) {
if ($checked && isset($user->roles[$rid])) {
return;
}
}
form_set_error('forum_access][view', t('You must assign %View access to a role that you hold.', array('%View' => 'View')));
}
function _forum_access_form_submit($form, &$form_state) {
$access = $form_state['values']['forum_access']; // shortcut
// Save template choice:
$template_tid = reset(array_values($access['template']['taxonomy']));
if ($access['template']['select_by_default']) {
variable_set('forum_access_default_template_tid', $template_tid);
}
elseif (variable_get('forum_access_default_template_tid', 0) == $template_tid) {
variable_del('forum_access_default_template_tid');
}
if ($access['template']['load_for_new']) {
variable_set('forum_access_new_template_tid', $template_tid);
}
elseif (variable_get('forum_access_new_template_tid', 0) == $template_tid) {
variable_del('forum_access_new_template_tid');
}
module_load_include('node.inc', 'forum_access');
$moderator_rid = _forum_access_get_moderator_rid(TRUE); // create the moderators role if it doesn't exist
// check for changes
$is_changed = $is_new = strpos($_GET['q'], 'admin/content/forum/add/') === 0;
$is_changed = $is_changed || !empty($access['force_update']);
$form_initial_values = $form; // avoid Coder warning
$form_initial_values = $form_initial_values['forum_access'];
foreach (array('view', 'create', 'update', 'delete') as $grant_type) {
if (isset($form_initial_values[$grant_type])) {
$defaults = $form_initial_values[$grant_type]['#default_value'];
$defaults = array_flip($defaults);
foreach ($access[$grant_type] as $rid => $checked) {
$is_changed = $is_changed || (empty($form_initial_values[$grant_type][$rid]['#disabled']) && !empty($checked) != isset($defaults[$rid]));
}
}
}
if (!$is_changed && $access['acl']['user_list'] == $form_initial_values['acl']['user_list']['#default_value'] && $access['interference']['advanced']['priority'] == $form_initial_values['interference']['advanced']['priority']['#default_value']) {
drupal_set_message(t('The content access permissions are unchanged.'));
return;
}
$tid = $form_state['values']['tid'];
db_query("DELETE FROM {forum_access} WHERE tid = %d", $tid);
$fa_priority = isset($access['interference']['advanced']['priority']) ? $access['interference']['advanced']['priority'] : 0;
if (array_key_exists('acl', $access)) {
$moderators = unserialize($access['acl']['user_list']);
acl_save_form($access['acl'], $fa_priority);
}
$permissions = _forum_access_get_role_permissions();
foreach ($access['view'] as $rid => $checked) {
if ($rid == $moderator_rid) {
continue;
}
if (isset($permissions[$rid]['administer nodes'])) {
// We prefer not to save records for node administrators, because these have access anyway.
if (isset($permissions[$rid]['administer forums']) && $access['view'][$rid]) {
// For forum administrators, View needs to be saved, ...
}
else {
// ... otherwise forget View.
$access['view'][$rid] = FALSE;
}
if ($access['view'][$rid] || $access['create'][$rid]) {
db_query("INSERT INTO {forum_access} (tid, rid, grant_view, grant_update, grant_delete, grant_create, priority) VALUES (%d, %d, %d, %d, %d, %d, %d)",
$tid, $rid, !empty($access['view'][$rid]), 0, 0, !empty($access['create'][$rid]), $fa_priority);
}
}
else {
db_query("INSERT INTO {forum_access} (tid, rid, grant_view, grant_update, grant_delete, grant_create, priority) VALUES (%d, %d, %d, %d, %d, %d, %d)",
$tid, $rid, (bool) $checked, !empty($access['update'][$rid]), !empty($access['delete'][$rid]), !empty($access['create'][$rid]), $fa_priority);
}
}
$tr = 't';
$link = l($tr('edit'), 'admin/content/forum/edit/forum/'. $tid);
watchdog('access', 'Changed grants for %forum forum.', array('%forum' => $form_state['values']['name']), WATCHDOG_NOTICE, $link);
if (!$is_new && $form_state['values']['form_id'] != 'forum_form_container') {
if (!isset($access['update_choice']) || $access['update_choice'] == 2) {
node_access_needs_rebuild(TRUE);
}
elseif ($access['update_choice'] == 0) {
// update immediately (but use the batch functions anyway
$save_redirect = $form_state['redirect'];
$form_state['redirect'] = $_GET['q'];
$context = array();
$pending_error_messages = drupal_get_messages('error', FALSE);
$our_error_message_index = (isset($pending_error_messages['error']) ? count($pending_error_messages['error']) : 0);
_forum_access_update_batch_finished(FALSE, array(), array()); // add our error message (in case we die underway)
_forum_access_update_batch_operation($tid, 999999, 1, $context);
$pending_error_messages = drupal_get_messages('error', TRUE); // still alive, get and clear all 'error' messages
unset($pending_error_messages['error'][$our_error_message_index]); // remove our error message
foreach ($pending_error_messages['error'] as $message) { // replay any others
drupal_set_message($message, 'error');
}
_forum_access_update_batch_finished(TRUE, array(), array());
$form_state['redirect'] = $save_redirect;
}
else {
// mass update in batch mode, modeled after node.module
$limit = $access['update_limit'];
$count = db_result(db_query("SELECT COUNT(DISTINCT n.nid) FROM {node} n INNER JOIN {term_node} tn ON tn.vid = n.vid WHERE tn.tid = %d", $tid));
$batch = array(
'title' => t('Updating content access permissions'),
'file' => drupal_get_path('module', 'forum_access') .'/forum_access.admin.inc',
'operations' => array(
array('_forum_access_update_batch_operation', array($tid, $limit, $count)),
),
'finished' => '_forum_access_update_batch_finished'
);
batch_set($batch);
}
}
variable_del('forum_access_rids'); // clear cache
}
/**
* Batch operation for forum_access_form_submit().
*
* This is a multistep operation : we go through all nodes by packs of 20.
* The batch processing engine interrupts processing and sends progress
* feedback after 1 second execution time.
*/
function _forum_access_update_batch_operation($tid, $limit, $count, &$context) {
if (empty($context['sandbox'])) {
// Initiate multistep processing.
$context['sandbox']['progress'] = 0;
$context['sandbox']['current_node'] = 0;
$context['sandbox']['max'] = $count;
}
// Process the next 20 nodes.
$result = db_query_range("SELECT DISTINCT n.nid FROM {node} n INNER JOIN {term_node} tn ON tn.vid = n.vid WHERE n.nid > %d AND tn.tid = %d ORDER BY n.nid ASC", $context['sandbox']['current_node'], $tid, 0, $limit);
while ($row = db_fetch_array($result)) {
$loaded_node = node_load($row['nid'], NULL, TRUE);
// To preserve database integrity, only aquire grants if the node
// loads successfully.
if (!empty($loaded_node)) {
node_access_acquire_grants($loaded_node);
}
$context['sandbox']['progress']++;
$context['sandbox']['current_node'] = $loaded_node->nid;
}
// Multistep processing : report progress.
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
/**
* Post-processing for forum_access_form_submit().
*/
function _forum_access_update_batch_finished($success, $results, $operations) {
if ($success) {
drupal_set_message(t('The content access permissions have been updated.'));
cache_clear_all();
}
else {
drupal_set_message(t('The content access permissions have not been properly updated.'), 'error');
}
}
/**
* Add our settings to the forum administration settings page.
*/
function _forum_access_forum_admin_settings_form(&$form, &$form_state) {
$variables = array(
'!Forum_Access' => 'Forum Access',
'%View' => 'View',
'%Post' => 'Post',
'%post_comments' => 'post comments',
);
$form['forum_access'] = array(
'#type' => 'fieldset',
'#title' => 'Forum Access',
'#attributes' => array('id' => 'edit-forum-admin-settings-forum-access'),
);
$form['forum_access']['note'] = array(
'#type' => 'item',
'#value' => t('Note: All other !Forum_Access controls are on the administration pages of the individual forums.', $variables),
);
$form['forum_access']['forum_access_D5_legacy_mode'] = array(
'#type' => 'checkbox',
'#title' => t('Drupal 5 legacy mode', $variables),
'#default_value' => variable_get('forum_access_D5_legacy_mode', FALSE),
'#description' => t('In Drupal 5, comment posting was not restricted by !Forum_Access; users with %View access (and the %post_comments permission) were always allowed to post forum comments. Starting with Drupal 6, posting comments is now restricted to users with %Post access. Turn this option on to revert to the old behavior. The default is OFF.', $variables),
);
$buttons = $form['buttons'];
unset($form['buttons']);
$form['buttons'] = $buttons;
}
/**
* Helper function to retrieve the settings for a forum.
*/
function _forum_access_get_settings($tid = NULL) {
$return = array('view' => array(), 'create' => array(), 'update' => array(), 'delete' => array(), 'priority' => 0);
if (!isset($tid)) {
// Default to all users can read; all logged in users can post.
$return['view'] = array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID);
$return['create'] = array(DRUPAL_AUTHENTICATED_RID);
}
else {
$result = db_query("SELECT * FROM {forum_access} where tid = %d", $tid);
while ($access = db_fetch_object($result)) {
if ($access->grant_view) {
$return['view'][] = $access->rid;
}
if ($access->grant_update) {
$return['update'][] = $access->rid;
}
if ($access->grant_delete) {
$return['delete'][] = $access->rid;
}
if ($access->grant_create) {
$return['create'][] = $access->rid;
}
if ($access->rid == DRUPAL_AUTHENTICATED_RID) { // this is our reference
$return['priority'] = $access->priority;
}
}
}
return $return;
}
/**
* Remove unusable 'edit' links from overview form.
*/
function _forum_access_forum_overview(&$form, &$form_state) {
global $user;
if ($user->uid == 1) {
return;
}
foreach ($form as $key => $value) {
if (preg_match('/^tid:(.*):0$/', $key, $matches)) {
if (!forum_access_access($matches[1], 'view', NULL, FALSE)) {
$form[$key]['edit']['#access'] = FALSE;
if (preg_match('|
]*>([^<]*)|', $form[$key]['view']['#value'], $matches)) {
$form[$key]['view']['#value'] = $matches[1];
}
}
}
}
}
/**
* We must know when a role is deleted.
*/
function _forum_access_user_admin_role_form(&$form, &$form_state) {
$form['#submit'][] = '_forum_access_user_admin_role_submit';
}
/**
* If a role is deleted, we remove the grants it provided.
* Also, we complain if the Forum Moderator role is deleted.
*/
function _forum_access_user_admin_role_submit($form, &$form_state) {
if ($form_state['values']['op'] == $form_state['values']['delete']) {
$rid = $form_state['values']['rid'];
db_query("DELETE FROM {forum_access} WHERE rid = %d", $rid);
db_query("DELETE FROM {node_access} WHERE gid = %d AND realm = 'forum_access'", $rid);
if ($rid === forum_access_query_moderator_rid()) {
drupal_set_message(t('The role you have just deleted is required by !Forum_Access; it will be recreated automatically.', array('!Forum_Access' => 'Forum Access')), 'error');
}
}
}
/**
* Add warnings on Content Access admin forms where CA wants
* to control the same content types as we do.
*/
function _forum_access_content_access_admin_form() {
$tr = 't';
$variables = array(
'!Content_Access' => 'Content Access',
'!Forum_Access' => 'Forum Access',
'!Forum_Access_link' => l('Forum Access', 'admin/content/forum'),
'%anonymous_user' => $tr('anonymous user'),
'%authenticated_user' => $tr('authenticated user'),
'%Advanced' => $tr('Advanced'),
);
if (arg(3) == 'forum') {
drupal_set_message(t('Note: In Drupal, access can only be granted, not taken away. Whatever access you grant here will not be reflected in the !Forum_Access_link settings, but !Forum_Access can only allow
more access, not less.', $variables)
.'
'. t('Specifically, any rights granted to the %anonymous_user and/or the %authenticated_user will override the settings of !Forum_Access!', $variables) .''
.'
'. t('To avoid conflicts with !Forum_Access settings, you may want to lower the priority of !Content_Access (under %Advanced below) below the priority of !Forum_Access for the content types that you want to be controlled by !Forum_Access.', $variables), 'warning');
}
else {
$vid = _forum_access_get_vid();
$vocabulary = taxonomy_vocabulary_load($vid);
if (isset($vocabulary->nodes[arg(3)])) {
drupal_set_message(t('Note: Nodes of this content type can be put inside forums, where access to them will also be controlled by !Forum_Access.
In Drupal, access can only be granted, not taken away. Whatever access you grant here will not be reflected on the !Forum_Access_link settings, and vice versa, but any node access module can only allow
more access, not less.', $variables), 'warning');
}
}
}
/**
* Keep the user from changing the permissions of the Forum Moderator role.
*
* Disable the checkboxes in the Forum Moderators column on
* admin/user/permissions.
*/
function _forum_access_user_admin_perm_form(&$form, &$form_state) {
$moderator_rid = forum_access_query_moderator_rid();
if (isset($moderator_rid) && array_key_exists($moderator_rid, $form['role_names'])) {
drupal_set_message(t('The %role role is used internally by the @Forum_Access module and must not be changed!', array('%role' => $form['role_names'][$moderator_rid]['#value'], '@Forum_Access' => 'Forum Access')), 'warning', FALSE);
$form['checkboxes'][$moderator_rid]['#disabled'] = TRUE;
}
array_unshift($form['#submit'], '_forum_access_user_admin_perm_form_submit');
}
/**
* Submit handler for the admin/user/permissions form.
*
* Avoid losing the Forum Moderators record by removing the (empty!) FM values
* before the real handler gets them.
*/
function _forum_access_user_admin_perm_form_submit($form, &$form_state) {
$moderator_rid = forum_access_query_moderator_rid();
if (isset($moderator_rid)) {
unset($form_state['values'][$moderator_rid]);
}
}
/**
* Keep the user from bulk-assigning the Forum Moderator role.
*
* Remove the Forum Moderator role from the selection list on
* admin/user/user.
*/
function _forum_access_user_admin_account_form(&$form, &$form_state) {
$moderator_rid = forum_access_query_moderator_rid();
if (isset($moderator_rid)) {
unset($form['options']['operation']['#options'][t('Add a role to the selected users')]["add_role-$moderator_rid"]);
}
}
/**
* Keep the user from assigning the Forum Moderator role.
*
* Disable the Forum Moderator checkbox on user/UID/edit.
*/
function _forum_access_user_profile_form(&$form, &$form_state) {
//dpm($form, '_forum_access_user_profile_form()');
$moderator_rid = forum_access_query_moderator_rid();
if (isset($moderator_rid) && isset($form['account']['roles']['#options'][$moderator_rid])) {
$form['account']['roles'][$moderator_rid] = array(
'#type' => 'checkbox',
'#title' => $form['account']['roles']['#options'][$moderator_rid] .' ('. t('reserved for internal use by the @Forum_Access module', array('@Forum_Access' => 'Forum Access')) .')',
'#default_value' => in_array($moderator_rid, $form['account']['roles']['#default_value']),
'#disabled' => TRUE,
);
unset($form['account']['roles']['#options'][$moderator_rid]);
}
}
/**
* Create the Forum Moderator role.
*/
function _forum_access_create_moderator_rid($verbose = FALSE) {
$tr = 't';
$variables = array('!Forum_Access' => 'Forum Access', '%administer_comments' => $tr('administer comments'), '%administer_nodes' => $tr('administer nodes'));
$role_name = t('Forum Moderator');
$role = new stdClass();
$role->name = $role_name;
for ($i = 2; $i <= 12; ++$i) {
$variables['%role'] = $role->name;
if (!db_result(db_query("SELECT COUNT(rid) FROM {role} WHERE name = '%s'", $role->name)) &&
drupal_write_record('role', $role)) {
$rid = $role->rid;
variable_set('forum_access_moderator_rid', $rid);
$permission = new stdClass();
$permission->rid = $rid;
$permission->perm = 'administer comments, administer nodes';
drupal_write_record('permission', $permission);
$msg = t('!Forum_Access has created a new role named %role and given it the %administer_nodes and %administer_comments permissions. This role is used internally by !Forum_Access. You can change the name of the role as you like, but you must keep it unmodified otherwise.', $variables);
if ($verbose) {
drupal_set_message($msg, 'warning');
}
watchdog('user', $msg, NULL, WATCHDOG_NOTICE);
return $rid;
}
else {
$msg = t('!Forum_Access cannot create the %role role!', $variables);
watchdog('user', $msg, NULL, WATCHDOG_WARNING);
drupal_set_message($msg .' '. t('Is it already in use?'), 'error');
$role->name = $role_name .' '. $i;
}
}
$msg = t('!Forum_Access has given up and will not work correctly! Rename one of the roles listed above, so that !Forum_Access can use its name.', $variables);
drupal_set_message($msg, 'error');
watchdog('user', $msg, NULL, WATCHDOG_CRITICAL);
}