You are here

function _forum_access_forum_form in Forum Access 6

Same name and namespace in other branches
  1. 7 forum_access.admin.inc \_forum_access_forum_form()

Rewrite the forum administration page with our new access rules.

1 call to _forum_access_forum_form()
forum_access_form_alter in ./forum_access.module
Implementation of hook_form_alter().

File

./forum_access.admin.inc, line 14
forum_access.admin.inc

Code

function _forum_access_forum_form(&$form, &$form_state, $is_container) {
  $tid = isset($form['tid']['#value']) ? $form['tid']['#value'] : NULL;
  if (isset($tid) && !forum_access_access($tid, 'view', NULL, FALSE)) {
    drupal_access_denied();

    // Deny access if the user doesn't have View access.
    module_invoke_all('exit');
    exit;
  }
  $roles = user_roles();
  if (isset($tid)) {

    // edit
    $template_tid = variable_get('forum_access_default_template_tid', 0);
    $settings = _forum_access_get_settings($tid);
  }
  else {

    // create
    $template_tid = variable_get('forum_access_new_template_tid', NULL);
    $settings = _forum_access_get_settings($template_tid);
  }
  $fa_priority = $settings['priority'];
  $form['forum_access'] = array(
    '#type' => 'fieldset',
    '#title' => t('Access control'),
    '#collapsible' => TRUE,
    '#tree' => TRUE,
  );
  $tr = 't';
  $variables = array(
    '!access_content' => '<em>' . l($tr('access content'), 'admin/user/permissions', array(
      'fragment' => 'module-node',
      'html' => TRUE,
    )) . '</em>',
    '!access_comments' => '<em>' . l($tr('access comments'), 'admin/user/permissions', array(
      'fragment' => 'module-comment',
      'html' => TRUE,
    )) . '</em>',
    '!create_forum_topics' => '<em>' . l($tr('create forum topics'), 'admin/user/permissions', array(
      'fragment' => 'module-forum',
      'html' => TRUE,
    )) . '</em>',
    '!post_comments' => '<em>' . l($tr('post comments'), 'admin/user/permissions', array(
      'fragment' => 'module-comment',
      'html' => TRUE,
    )) . '</em>',
    '!post_comments_without_approval' => '<em>' . l($tr('post comments without approval'), 'admin/user/permissions', array(
      'fragment' => 'module-comment',
      'html' => TRUE,
    )) . '</em>',
    '!edit_own_forum_topics' => '<em>' . l($tr('edit own forum topics'), 'admin/user/permissions', array(
      'fragment' => 'module-forum',
      'html' => TRUE,
    )) . '</em>',
    '!edit_any_forum_topics' => '<em>' . l($tr('edit any forum topics'), 'admin/user/permissions', array(
      'fragment' => 'module-forum',
      'html' => TRUE,
    )) . '</em>',
    '!delete_own_forum_topics' => '<em>' . l($tr('delete own forum topics'), 'admin/user/permissions', array(
      'fragment' => 'module-forum',
      'html' => TRUE,
    )) . '</em>',
    '!delete_any_forum_topics' => '<em>' . l($tr('delete any forum topics'), 'admin/user/permissions', array(
      'fragment' => 'module-forum',
      'html' => TRUE,
    )) . '</em>',
    '!administer_comments' => '<em>' . l($tr('administer comments'), 'admin/user/permissions', array(
      'fragment' => 'module-comment',
      'html' => TRUE,
    )) . '</em>',
    '!administer_forums' => '<em>' . l($tr('administer forums'), 'admin/user/permissions', array(
      'fragment' => 'module-forum',
      'html' => TRUE,
    )) . '</em>',
    '!administer_nodes' => '<em>' . l($tr('administer nodes'), 'admin/user/permissions', array(
      'fragment' => 'module-node',
      'html' => TRUE,
    )) . '</em>',
  );
  if (!$is_container) {
    $form['forum_access']['permissions'] = array(
      '#type' => 'fieldset',
      '#title' => $tr('Permissions information'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $form['forum_access']['permissions'][] = array(
      '#type' => 'markup',
      '#value' => '<div>' . t('Note that users need') . '<ul style="margin-top: 0"><li>' . t('the !access_content and !access_comments permissions <strong>AND <em>View</em></strong> to be able to see this forum and its content at all,', $variables) . '</li><li>' . t('the !create_forum_topics (and similar) permissions <strong>AND <em>Post</em></strong> to be able to create forum content, and', $variables) . '</li><li>' . t('the !post_comments and (probably) !post_comments_without_approval permission <!TAG>AND <em>Post</em></!TAG> to be able to post comments/replies;', $variables + array(
        '!TAG' => variable_get('forum_access_D5_legacy_mode', FALSE) ? 'del title="' . t('Drupal 5 legacy mode') . '"' : 'strong',
      )) . '</li><li>' . t('the !edit_own_forum_topics or !edit_any_forum_topics (and similar) permissions (<strong>OR <em>Edit</em></strong>) can be added if desired, <strong>plus</strong>', $variables) . '</li><li>' . t('the !delete_own_forum_topics or !delete_any_forum_topics (and similar) permissions (<strong>OR <em>Delete</em></strong>) if desired;', $variables) . '</li><li>' . t('the !administer_comments (global!) permission <strong>OR <em>Edit</em>/<em>Delete</em></strong> to be able to edit/delete comments;', $variables) . '</li><li>' . t('the !administer_forums permission <strong>AND <em>View</em></strong> to be able to administer forums (and change access!).', $variables) . '</li></ul>' . t('Furthermore note that content which is not published is treated in a different way by Drupal: it can be viewed only by its author or by users with the !administer_nodes permission. Unpublished comments and replies are accessible to users with <strong><em>Edit</em> OR <em>Delete</em></strong>, <strong>OR</strong> with the !administer_comments permission, but they are never counted on the forum page.', $variables) . '</div>',
    );
  }

  // Load a template:
  $vid = _forum_access_get_vid();
  $form['forum_access']['template'] = array(
    '#type' => 'fieldset',
    '#title' => $tr('Template'),
    '#collapsible' => TRUE,
    '#collapsed' => empty($template_tid),
  );
  $form['forum_access']['template']['taxonomy'][$vid] = taxonomy_form($vid, array(
    $template_tid,
  ), '');
  $form['forum_access']['template']['taxonomy'][$vid]['#description'] = t("Select a forum and click !Load to retrieve that forum's settings as a starting point for this forum or container.", array(
    '!Load' => '[' . t('Load') . ']',
  ));
  $form['forum_access']['template']['load_button'] = array(
    '#type' => 'button',
    '#name' => 'load_template',
    '#value' => t('Load'),
    '#submit' => FALSE,
  );
  $form['forum_access']['template']['template_tid'] = array(
    '#type' => 'value',
    '#value' => NULL,
  );
  $form['forum_access']['template']['select_by_default'] = array(
    '#type' => 'checkbox',
    '#title' => t('Remember this selection.'),
    '#default_value' => FALSE,
  );
  $form['forum_access']['template']['load_for_new'] = array(
    '#type' => 'checkbox',
    '#title' => t("Use the selected forum's settings as defaults for new forums and containers."),
    '#default_value' => FALSE,
  );
  $form['forum_access']['#after_build'][] = '_forum_access_forum_form_after_build';

  // Column titles:
  $form['forum_access']['headers']['view'] = array(
    '#type' => 'item',
    '#prefix' => '<div class="forum-access-div">',
    '#title' => $is_container ? t('View this container') : t('View this forum'),
    '#suffix' => '</div>',
  );
  $forum_vocabulary = taxonomy_vocabulary_load(_forum_access_get_vid());
  $form['forum_access']['headers']['create'] = array(
    '#type' => 'item',
    '#prefix' => '<div class="forum-access-div" id="forum-access-div-container">',
    '#title' => t('See this container in the %Forums selection list', array(
      '%Forums' => $forum_vocabulary->name,
    )),
    '#suffix' => '</div>',
  );
  if (!$is_container) {
    $form['forum_access']['headers']['create'] = array(
      // overwrite!
      '#type' => 'item',
      '#prefix' => '<div class="forum-access-div">',
      '#title' => t('Post in this forum'),
      '#suffix' => '</div>',
    );
    $form['forum_access']['headers']['update'] = array(
      '#type' => 'item',
      '#prefix' => '<div class="forum-access-div">',
      '#title' => t('Edit posts'),
      '#suffix' => '</div>',
    );
    $form['forum_access']['headers']['delete'] = array(
      '#type' => 'item',
      '#prefix' => '<div class="forum-access-div">',
      '#title' => t('Delete posts'),
      '#suffix' => '</div>',
    );
  }
  $form['forum_access']['headers']['clearer'] = array(
    '#value' => '<div class="forum-access-clearer"></div>',
  );

  // Column content (checkboxes):
  $form['forum_access']['view'] = array(
    '#type' => 'checkboxes',
    '#prefix' => '<div class="forum-access-div">',
    '#suffix' => '</div>',
    '#options' => $roles,
    '#default_value' => $settings['view'],
    '#process' => array(
      'expand_checkboxes',
      '_forum_access_forum_form_disable_checkboxes',
    ),
  );
  $form['forum_access']['create'] = array(
    '#type' => 'checkboxes',
    '#prefix' => '<div class="forum-access-div">',
    '#suffix' => '</div>',
    '#options' => $roles,
    '#default_value' => $settings['create'],
    '#process' => array(
      'expand_checkboxes',
      '_forum_access_forum_form_disable_checkboxes',
    ),
  );
  if (!$is_container) {
    $form['forum_access']['update'] = array(
      '#type' => 'checkboxes',
      '#prefix' => '<div class="forum-access-div">',
      '#suffix' => '</div>',
      '#options' => $roles,
      '#default_value' => $settings['update'],
      '#process' => array(
        'expand_checkboxes',
        '_forum_access_forum_form_disable_checkboxes',
      ),
    );
    $form['forum_access']['delete'] = array(
      '#type' => 'checkboxes',
      '#prefix' => '<div class="forum-access-div">',
      '#suffix' => '</div>',
      '#options' => $roles,
      '#default_value' => $settings['delete'],
      '#process' => array(
        'expand_checkboxes',
        '_forum_access_forum_form_disable_checkboxes',
      ),
    );
  }
  $form['forum_access']['clearer'] = array(
    '#type' => 'item',
    '#prefix' => '<div class="forum-access-clearer">',
    '#suffix' => '</div>',
    '#description' => t('For explanations of special cases, hover your mouse over role names.'),
  );
  if ($is_container) {
    $form['forum_access']['container_note'] = array(
      '#type' => 'item',
      '#description' => t('Users who can see any forum or container within this one should get the <strong><em>View</em></strong> grant. <br /> Users who can post to a forum within this container should get the <strong><em>See</em></strong> grant, so that this forum appears in the proper context in the selection list.', $variables),
    );
  }
  drupal_add_css(drupal_get_path('module', 'forum_access') . '/forum_access.css');

  // Find our moderator ACL:
  if (isset($tid)) {

    // edit, not new
    $acl_id = acl_get_id_by_number('forum_access', $tid);
    if (!$acl_id) {

      // create one
      $acl_id = acl_create_new_acl('forum_access', NULL, $tid);

      // update every existing node in this forum to use this acl.
      $result = db_query("SELECT nid FROM {term_node} WHERE tid = %d", $tid);
      while ($node = db_fetch_object($result)) {

        // all privs to this ACL.
        acl_node_add_acl($node->nid, $acl_id, 1, 1, 1);
      }
    }
    $form['forum_access']['acl'] = acl_edit_form($acl_id, t('Moderators'));
    $form['forum_access']['acl'][] = array(
      '#type' => 'markup',
      '#value' => '<div>' . t('Moderators receive all grants above.') . '</div>',
      '#weight' => -1,
    );
    $form['forum_access']['acl']['note'] = array(
      '#type' => 'markup',
      '#value' => '<div>' . t('Note: Changes to moderators are not saved until you click [!Save] below.', array(
        '!Save' => $tr('Save'),
      )) . '</div>',
    );
    $form['forum_access']['acl']['#after_build'][] = '_forum_access_forum_form_after_build_acl0';
    $form['forum_access']['acl']['#after_build'] = array_reverse($form['forum_access']['acl']['#after_build']);
    $form['forum_access']['acl']['#after_build'][] = '_forum_access_forum_form_after_build_acl2';
  }
  foreach (module_implements('node_access_records') as $module) {
    $na_modules[$module] = $module;
  }
  unset($na_modules['forum_access']);
  unset($na_modules['acl']);
  if (count($na_modules) && !$is_container) {
    $form['forum_access']['interference'] = array(
      '#type' => 'fieldset',
      '#title' => t('Module interference'),
      '#collapsible' => TRUE,
    );
    $variables = array(
      '%content_type' => node_get_types('name', 'forum'),
      '!Forum_Access' => 'Forum Access',
      '!Content_Access' => l('Content Access', 'http://drupal.org/project/content_access'),
      '@Content_Access' => 'Content Access',
      '!ACL' => 'ACL',
      '!module_list' => '<ul><li>' . implode($na_modules, '</li><li>') . '</li></ul>',
    );
    $form['forum_access']['interference'][] = array(
      '#type' => 'item',
      '#value' => '<p>' . t("Besides !Forum_Access (and !ACL) you have installed the following node access module(s): !module_list   The grants of every module are combined for each node. Access can only be granted, not removed &mdash; if a certain module grants a permission, the other(s) cannot deny it.", $variables) . '</p>',
      '#description' => t('Forums can contain other content types besides %content_type; !Forum_Access will contribute the grants defined above to every node in this forum, but other node access control modules may also contribute their grants, especially to nodes of types other than %content_type.', $variables),
    );
    if (module_exists('content_access')) {
      $ca_settings = variable_get('content_access_settings', array());
      foreach (array(
        'view',
        'update',
        'delete',
        'per_node',
      ) as $type) {
        $value = content_access_get_settings($type, 'forum');
        if (!empty($value)) {
          $ca_interferes = TRUE;
        }
      }
      $ca_priority = content_access_get_settings('priority', 'forum');
      $is_conflict = $ca_priority >= $fa_priority && !empty($ca_interferes) || $ca_priority > $fa_priority;
      $variables += array(
        '!link' => l(t('@Content_Access configuration for the %content_type type', $variables), 'admin/content/node-type/forum/access', array(
          'html' => TRUE,
        )),
        '%Advanced' => $tr('Advanced'),
      );
      $specifically = $ca_priority == $fa_priority ? t('Specifically, any grants given by !Content_Access cannot be taken back by !Forum_Access.', $variables) : '';
      if ($is_conflict) {
        $form['forum_access']['interference']['by_content_access'] = array(
          '#type' => 'fieldset',
          '#title' => 'Content Access',
          '#collapsible' => FALSE,
          '#attributes' => array(
            'class' => 'error',
          ),
        );
        $form['forum_access']['interference']['by_content_access'][] = array(
          '#value' => '<div>' . t('You have set the !Content_Access module to control access to content of type %content_type&mdash;this can interfere with proper operation of !Forum_Access!', $variables) . " {$specifically}</div>",
        );
        if ($ca_priority == $fa_priority) {
          $form['forum_access']['interference']['by_content_access'][] = array(
            '#value' => '<div>' . t("Unless you really know what you're doing, we recommend that you go to the !link page and clear all checkboxes. This will instruct @Content_Access to leave the %content_type nodes alone. However, if you put nodes of other content types into forums as well, then these content types will continue to have this problem.", $variables) . '</div>',
          );
        }
        else {
          $form['forum_access']['interference']['by_content_access'][] = array(
            '#value' => '<div>' . t("The priority of @Content_Access ({$ca_priority}) is higher than the priority of !Forum_Access ({$fa_priority}), which means the latter is <strong>completely disabled</strong> for the %content_type type! Unless you really know what you're doing, we recommend that you go to the !link page, change the priority (under %Advanced) to 0, and clear all checkboxes.", $variables) . '</div>',
          );
        }
        $form['forum_access']['interference']['by_content_access'][] = array(
          '#value' => '<div>' . t("Alternatively, you can give !Forum_Access priority over @Content_Access by either raising the priority of !Forum_Access in every forum above the priority of @Content_Access, or by lowering the priority of @Content_Access for the content types in question below the priority of !Forum_Access.", $variables) . '</div>',
        );
      }
      else {
        $form['forum_access']['interference'][] = array(
          '#value' => '<p>' . t('Note: You have installed the !Content_Access module, which has the capability to grant access to content that would otherwise be protected by !Forum_Access. Be careful when configuring @Content_Access!', $variables) . '</p>',
        );
      }
    }
    $form['forum_access']['interference']['advanced'] = array(
      '#type' => 'fieldset',
      '#title' => t('Advanced'),
      '#collapsible' => TRUE,
      '#collapsed' => !($fa_priority != 0),
    );
    $form['forum_access']['interference']['advanced']['priority'] = array(
      '#type' => 'weight',
      '#title' => t('Priority of !Forum_Access node grants in this forum', $variables),
      '#default_value' => $fa_priority,
      '#description' => t("If you have no other node access control modules installed, you should leave this at the default 0. <br /> Otherwise you can raise or lower the priority of !Forum_Access' grants. Out of all the grants contributed to a node, only those with the highest priority are used, and all others are discarded.", $variables),
    );
  }
  if (!$is_container) {
    $variables = array(
      '!Forum_Access' => l('Forum Access', 'http://drupal.org/project/forum_access'),
      '!ACL' => l('ACL', 'http://drupal.org/project/acl'),
      '%Module_interference' => t('Module interference'),
      '!Forum_Access-dev' => l('Forum&nbsp;Access&nbsp;6.x-1.x-dev', 'http://drupal.org/node/96795', array(
        'html' => TRUE,
      )),
      '!ACL-dev' => l('ACL&nbsp;6.x-1.x-dev', 'http://drupal.org/node/96794', array(
        'html' => TRUE,
      )),
      '%devel_node_access' => 'devel_node_access',
      '!Devel' => l('Devel', 'http://drupal.org/project/devel'),
      '!DNA' => 'DNA',
      '!debug_mode' => l('debug mode', 'admin/settings/devel', array(
        'fragment' => 'edit-devel-node-access-debug-mode',
      )),
      '!dna_summary' => l('devel/node_access/summary', 'devel/node_access/summary'),
      '!Rebuild_permissions' => '[' . $tr('Rebuild permissions') . ']',
      '!Post_settings_link' => l('admin/content/node-settings', 'admin/content/node-settings'),
      '!Forum_Access_' => l('Forum Access', 'http://drupal.org/project/issues/forum_access'),
      '!ACL_' => l('ACL', 'http://drupal.org/project/issues/acl'),
    );
    $form['forum_access']['troubleshooting'] = array(
      '#type' => 'fieldset',
      '#title' => t('Trouble-shooting node access'),
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
    );
    $form['forum_access']['troubleshooting'][] = array(
      '#type' => 'item',
      '#value' => '<div>' . t("In case of problems, follow these steps until you've got it worked out:") . '<ol style="margin-top: 0"><li>' . t("Update to the 'recommended' !Forum_Access and !ACL releases for your version of Drupal.", $variables) . '</li><li>' . (count($na_modules) ? t("Read %Module_interference above and update your other node access modules.", $variables) . '</li><li>' : '') . t("Check the release notes of the development snapshots for issues that might have been fixed in !Forum_Access-dev or !ACL-dev since the latest release.", $variables) . '</li><li>' . t("Install the %devel_node_access module (!DNA, part of the !Devel module) and enable its !debug_mode: !DNA will show you all the grants that actually control your nodes in a footer block on each node's page.", $variables) . '</li><li>' . t("Additional insight can be gained from !dna_summary and by enabling the second !DNA block.", $variables) . '</li><li>' . t("Click !Rebuild_permissions on !Post_settings_link and check DNA for changes.", $variables) . '</li><li>' . t("Check the issues queues of !Forum_Access_ and !ACL_ for existing reports and possible solutions.", $variables) . '</li><li>' . t("If all of this hasn't helped, then pick ONE node that is misbehaving, look at it using an account that can see the node (and that should NOT have access if that's your problem!), create a new issue in the issues queue, describe the problem... <ul><li> what did you do? </li><li> what did you expect? </li><li> what happened instead? </li></ul> ... and <strong>attach a screenshot of all the DNA records</strong> for that one node. <br /> Be sure to indicate paths (URLs) for every page and module that you mention.") . '</li></ol></div>',
    );
    $form['forum_access']['troubleshooting'][] = array(
      '#type' => 'item',
      '#value' => '<div>' . t("Note: You should not keep the !Devel module enabled on a production site.", $variables) . '</div>',
    );
  }
  if (!$is_container && isset($tid) && !node_access_needs_rebuild()) {
    $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));
    $limit = 20;

    // from _node_access_rebuild_batch_operation()
    $threshold = variable_get('forum_access_batch_threshold', $limit);

    // change the variable if you want
    $form['forum_access']['update_limit'] = array(
      '#type' => 'value',
      '#value' => $limit,
    );
    $form['forum_access']['update_choice'] = array(
      '#type' => 'radios',
      '#title' => t('Update the permissions'),
      '#description' => t('<em>If</em> you make any node access changes, then each node in this forum needs to be updated. Hover over the radiobuttons for details.'),
      '#options' => NULL,
      0 => array(
        '#type' => 'radio',
        '#title' => t('for all %count nodes immediately', array(
          '%count' => $count,
        )),
        '#attributes' => array(
          'title' => t('This option is the fastest, but with many nodes it can still take considerable time and memory. If it fails, it will leave your !node_access table in an inconsistent state.', array(
            '!node_access' => '{node_access}',
          )),
        ),
        '#return_value' => 0,
        '#default_value' => $count <= $threshold ? 0 : 1,
        '#parents' => array(
          'forum_access',
          'update_choice',
        ),
      ),
      1 => array(
        '#type' => 'radio',
        '#title' => t('in batches of !limit now', array(
          '!limit' => $limit,
        )),
        '#attributes' => array(
          'title' => t('The batch option will always work reliably, but it takes longer to complete.'),
        ),
        '#return_value' => 1,
        '#default_value' => $count <= $threshold ? 0 : 1,
        '#parents' => array(
          'forum_access',
          'update_choice',
        ),
      ),
      2 => array(
        '#type' => 'radio',
        '#title' => t('rebuild <strong>all</strong> permissions later'),
        '#attributes' => array(
          'title' => t("This option will only set a flag to remind you to rebuild all permissions later; this is useful if you want to make multiple changes to your node access settings quickly and delay the updating until you're done."),
        ),
        '#return_value' => 2,
        '#default_value' => $count <= $threshold ? 0 : 1,
        '#parents' => array(
          'forum_access',
          'update_choice',
        ),
      ),
      '#attributes' => array(
        'class' => 'forum-access-flowed',
      ),
    );
  }
  if (isset($tid)) {
    $form['forum_access']['force_update'] = array(
      '#type' => 'checkbox',
      '#title' => t('Update even if unchanged'),
    );
  }

  // Move some stuff down so our block goes in a nice place.
  $form['submit']['#weight'] = 10;
  $form['delete']['#weight'] = 10;
  $form['#validate'][] = '_forum_access_form_validate';
  $form['#submit'][] = '_forum_access_form_submit';
}