forum_access-8.x-1.0-alpha2/forum_access.module

forum_access.module
<?php

/**
 * @file
 * Contains forum_access.module.
 */

use Drupal\comment\CommentInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Database\Query\AlterableInterface;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\node\Entity\Node;
use Drupal\node\NodeInterface;
use Drupal\user\Entity\Role;

/**
 * Implements hook_help().
 *
 * @inheritdoc
 */
function forum_access_help($route_name, RouteMatchInterface $route_match) {
  $output = '';

  switch ($route_name) {

    // Main module help for the forum_access module.
    case 'help.page.forum_access':
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('Allows forums to be set private and to be given moderators.') . '</p>';

  }
  return $output;
}

/**
 * Implements hook_theme().
 *
 * @inheritdoc
 */
function forum_access_theme($existing, $type, $theme, $path) {
  $result['forum_access_table'] = [
    'render element' => 'form',
  ];
  return $result;
}

/**
 * Implements hook_node_grants().
 *
 * This function supplies the forum access grants. forum_access simply uses
 * roles as ACLs, so rids translate directly to gids.
 *
 * @inheritdoc
 */
function forum_access_node_grants(AccountInterface $account, $op) {
  $roles_gids = \Drupal::configFactory()
    ->getEditable('forum_access.settings')
    ->get('forum_access_roles_gids');
  $grants = [];
  /** @var string $role */
  foreach ($account->getRoles() as $role) {
    if (isset($roles_gids[$role])) {
      $grants['forum_access'][] = $roles_gids[$role];
    }
  }
  return $grants;
}

/**
 * Implements hook_node_access().
 *
 * @inheritdoc
 */
function forum_access_node_access(NodeInterface $node, $op, AccountInterface $account) {
  if ($node->bundle() != 'forum') {
    return AccessResult::neutral();
  }

  // Disallow if user has no access to view.
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.common');
  if (!forum_access_entity_access_by_tid('view', $node)) {
    return AccessResult::forbidden();
  }
  $author = $node->get('uid')->first()->get('entity')->getTarget()->getValue();
  switch ($op) {
    case 'view':
      if ($node->isPublished()) {
        $access = forum_access_entity_access_by_tid($op, $node);
      }
      elseif ($author->id() == $account->id() && $account->hasPermission('view own unpublished content')) {
        $access = forum_access_entity_access_by_tid($op, $node);
      }
      break;

    case 'update':
      if ($op == 'update' && ($account->hasPermission('edit any forum content') || ($author->id() == $account->id() && $account->hasPermission('edit own forum content')))) {
        $access = forum_access_entity_access_by_tid('view', $node);
      }
      break;

    case 'delete':
      if ($op == 'delete' && ($account->hasPermission('delete any forum content') || ($author->id() == $account->id() && $account->hasPermission('delete own forum content')))) {
        $access = forum_access_entity_access_by_tid('view', $node);
      }
      break;
  }
  if (isset($access)) {
    return $access ? AccessResult::allowed() : AccessResult::forbidden();
  }
  return AccessResult::neutral();
}

/**
 * Implements hook_node_access_records().
 *
 * Returns a list of grant records for the passed in node object.
 * Checks to see if maybe we're being disabled.
 *
 * @inheritdoc
 */
function forum_access_node_access_records(NodeInterface $node) {
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.common');
  $grants = &drupal_static(__FUNCTION__, []);
  $seers = &drupal_static(__FUNCTION__ . '__seers');
  $tid = forum_access_get_tid($node);
  $roles_gids = \Drupal::configFactory()
    ->getEditable('forum_access.settings')
    ->get('forum_access_roles_gids');
  if ($tid) {
    // We want to give our rights only for published nodes.
    if ($node->isPublished()) {
      if (!isset($grants[$tid])) {
        if (!isset($seers)) {
          $bypass_node_access_permission = 'bypass node access';
          $seers = array_filter(Role::loadMultiple(), function ($role) use ($bypass_node_access_permission) {
            return $role->hasPermission($bypass_node_access_permission);
          });
        }
        $result = forum_access_get_grants_by_tid($tid);
        foreach ($result as $grant) {
          if (isset($seers[$grant->rid])) {
            // Don't provide any useless grants!
            continue;
          }
          $grants[$tid][] = [
            'realm' => 'forum_access',
            // We change machine_name of role to its numeric equivalent.
            'gid' => $roles_gids[$grant->rid],
            'grant_view' => $grant->grant_view,
            'grant_update' => $grant->grant_update,
            'grant_delete' => $grant->grant_delete,
            'priority' => $grant->priority,
          ];
        }
      }
      if (isset($grants[$tid])) {
        return $grants[$tid];
      }
    }
  }
  return [];
}

/**
 * Implements hook_ENTITY_TYPE_create_access() for node entities.
 *
 * @inheritdoc
 */
function forum_access_node_create_access(AccountInterface $account, array $context, $entity_bundle) {
  if ($entity_bundle != 'forum') {
    return AccessResult::neutral();
  }
  // If we are on forum page we want to restrict access
  // to create forum according to the forum access rules.
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.common');
  $route = \Drupal::routeMatch();
  $route_name = $route->getCurrentRouteMatch()->getRouteName();
  switch ($route_name) {
    case 'forum.page':
      $term = $route->getParameter('taxonomy_term');
      return forum_access_access('create', $term->id()) ? AccessResult::allowed() : AccessResult::forbidden();

    case 'node.add':
      $forum_id = \Drupal::request()->get('forum_id');
      return forum_access_access('create', $forum_id) ? AccessResult::allowed() : AccessResult::forbidden();
  }
  return AccessResult::neutral();
}

/**
 * Implements hook_ENTITY_TYPE_insert() for node entities.
 *
 * @inheritdoc
 */
function forum_access_node_insert(EntityInterface $entity) {
  if ($entity->bundle() != 'forum') {
    return;
  }

  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.common');
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.acl');
  if ($tid = forum_access_get_tid($entity)) {
    $acl_id = forum_access_get_acl($tid, 'moderate');
    acl_node_add_acl($entity->id(), $acl_id, 1, 1, 1);
  }
  $node = Node::load($entity->id());
  // To preserve database integrity, only write grants if the node
  // loads successfully.
  if (!empty($node)) {
    /** @var \Drupal\node\NodeAccessControlHandlerInterface $access_control_handler */
    $access_control_handler = \Drupal::entityTypeManager()->getAccessControlHandler('node');
    $grants = $access_control_handler->acquireGrants($node);
    \Drupal::service('node.grant_storage')->write($node, $grants);
  }
}

/**
 * Implements hook_ENTITY_TYPE_update() for node entities.
 *
 * @inheritdoc
 */
function forum_access_node_update(EntityInterface $entity) {
  if ($entity->bundle() != 'forum') {
    return;
  }

  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.common');
  $old_tid = forum_access_get_tid($entity->original);
  $current_tid = forum_access_get_tid($entity);
  if (isset($old_tid)) {
    if ($current_tid == $old_tid) {
      return;
    }
    acl_node_clear_acls($entity->id(), 'forum_access');
  }
  // For changed and for previously unassigned terms we need to fake an insert.
  forum_access_node_insert($entity);
}

/**
 * Implements hook_ENTITY_TYPE_view_alter() for node entities.
 *
 * @inheritdoc
 */
function forum_access_node_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
  if ($entity->bundle() != 'forum') {
    return;
  }

  // Don't show comment form is user has no access to it.
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.common');
  if (!forum_access_entity_access_by_tid('create', $entity)) {
    $build['comment_forum'][0]['comment_form'] = [];
  }
}

/**
 * Implements hook_node_links_alter().
 *
 * @inheritdoc
 */
function forum_access_node_links_alter(array &$links, NodeInterface $entity, array &$context) {
  if ($entity->bundle() != 'forum') {
    return;
  }
  // Don't show Comment link is user has no access to it.
  if (!forum_access_entity_access_by_tid('create', $entity)) {
    unset($links['comment__comment_forum']);
  }
}

/**
 * Implements hook_ENTITY_TYPE_access() for comment entities.
 *
 * @inheritdoc
 */
function forum_access_comment_access(EntityInterface $entity, $operation, AccountInterface $account) {
  // Get parent entity of comment.
  $parent = $entity->get('entity_id')
    ->first()
    ->get('entity')
    ->getTarget()
    ->getValue();
  if (!($parent->getEntityTypeId() == 'node' && $parent->bundle() == 'forum')) {
    return AccessResult::neutral();
  }
  if ($account->hasPermission('administer comments')) {
    return AccessResult::neutral();
  }

  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.common');
  if ($tid = forum_access_get_tid($parent)) {
    // Disallow if user has no access to view.
    if (!forum_access_access('view', $tid)) {
      return AccessResult::forbidden();
    }
    $comment_author = $entity->get('uid')
      ->first()
      ->get('entity')
      ->getTarget()
      ->getValue();
    // Check if user is author of comment.
    $is_author = $account->id() == $comment_author->id();
    if ($operation == 'view' && forum_access_access('view', $tid)) {
      return AccessResult::allowed();
    }
    elseif ($operation == 'update'
      && (forum_access_access('update', $tid) || $account->hasPermission('edit any forum content') || ($is_author && $account->hasPermission('edit own forum content')))) {
      return AccessResult::allowed();
    }
    // Delete operation.
    elseif ($operation == 'delete'
      && (forum_access_access('delete', $tid) || $account->hasPermission('delete any forum content') || ($is_author && $account->hasPermission('delete own forum content')))) {
      return AccessResult::allowed();
    }
    // Approve operation.
    elseif ($operation == 'approve' && (forum_access_access('update', $tid) || forum_access_access('delete', $tid))) {
      return AccessResult::allowed();
    }
  }
  return AccessResult::forbidden();
}

/**
 * Implements hook_query_TAG_alter() for tag 'comment_filter'.
 *
 * @inheritdoc
 */
function forum_access_query_comment_filter_alter(AlterableInterface $query) {
  $entity = $query->getMetaData('entity');
  if (!($entity->getEntityTypeId() == 'node' && $entity->bundle() == 'forum')) {
    return;
  }

  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.common');
  // @todo Replace it with the function.
  $tid = forum_access_get_tid($entity);
  $access = [
    'update' => forum_access_access('update', $tid),
    'delete' => forum_access_access('delete', $tid),
  ];
  // If the user has access to update or delete posts or is moderator
  // of the forum, allow to see unpublished comments.
  if (!($access['update'] || $access['delete'])) {
    return;
  }
  $conditions =& $query->conditions();
  foreach ($conditions as $key => $condition) {
    if (!is_numeric($key)) {
      continue;
    }
    if ($condition['field'] == 'c.status' && $condition['value'] == CommentInterface::PUBLISHED && $condition['operator'] == '=') {
      unset($conditions[$key]);
    }
  }
}

/**
 * Implements hook_comment_links_alter().
 *
 * @inheritdoc
 */
function forum_access_comment_links_alter(array &$links, CommentInterface $entity, array &$context) {
  // Get parent entity of comment.
  $parent = $entity->get('entity_id')
    ->first()
    ->get('entity')
    ->getTarget()
    ->getValue();
  $account = \Drupal::currentUser();
  if (!($parent->getEntityTypeId() == 'node' && $parent->bundle() == 'forum')) {
    return;
  }
  if ($account->hasPermission('administer comments')) {
    return;
  }
  if (!forum_access_entity_access_by_tid('create', $parent)) {
    unset($links['comment']['#links']['comment-reply']);
  }
}

/**
 * Implements hook_ENTITY_TYPE_delete() for taxonomy_term entities.
 *
 * @inheritdoc
 */
function forum_access_taxonomy_term_delete(EntityInterface $entity) {
  $vid = $entity->get('vid')->first()->getValue()['target_id'];
  // Delete {forum_access} records when forums are deleted.
  if ($vid == \Drupal::config('forum.settings')->get('vocabulary')) {
    \Drupal::database()->delete('forum_access')
      ->condition('tid', $entity->id())
      ->execute();
  }
}

/**
 * Implements hook_ENTITY_TYPE_access() for entity_type 'taxonomy_term'.
 *
 * @inheritdoc
 */
function forum_access_taxonomy_term_access(EntityInterface $entity, string $operation, AccountInterface $account) {
  if ($entity->bundle() == 'forums') {
    \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.common');
    if (!forum_access_access('view', $entity->id())) {
      return AccessResult::forbidden();
    }
  }
  return AccessResult::neutral();
}

/**
 * Implements hook_query_TAG_alter() for tag 'taxonomy_term_access'.
 *
 * @inheritdoc
 */
function forum_access_query_taxonomy_term_access_alter(SelectInterface $query) {
  // Read meta-data from query, if provided.
  if (!$account = $query->getMetaData('account')) {
    $account = \Drupal::currentUser();
  }
  if (!$op = $query->getMetaData('op')) {
    $op = 'view';
  }
  // If $account can bypass node access, we let them administer the full forum
  // structure and see the nodes, i.e. we don't restrict the query.
  $route = \Drupal::routeMatch()->getRouteName();
  if ($account->hasPermission('bypass node access') && ($route == 'forum.overview' || $route == 'entity.taxonomy_vocabulary.overview_form')) {
    return;
  }
  // Prevent duplicate records.
  $query->distinct();
  // Find all instances of the {taxonomy_term_data} table being joined --
  // could appear more than once in the query, and could be aliased.
  // Join each one to the forum_access table.
  $tables = $query->getTables();
  $rids = $account->getRoles();
  foreach ($tables as $talias => $tableinfo) {
    $table = $tableinfo['table'];
    if ($table == 'taxonomy_term_field_data') {
      // The node_access table has the access grants for any given node.
      $access_alias = $query->leftJoin('forum_access', 'fa', '%alias.tid = ' . $talias . '.tid');
      $acl_alias = $query->leftJoin('acl', 'acl', "%alias.figure = $talias.tid AND %alias.module = 'forum_access' AND %alias.name=:name",
        [
          ':name' => 'moderate',
        ]);
      if ($account->hasPermission('bypass node access')) {
        // If $account can bypass node access, we allow access if any role or
        // account has access.
        $aclu_alias = $query->leftJoin('acl_user', 'aclu', "%alias.acl_id = $acl_alias.acl_id");
        $or = $query->orConditionGroup();
        $or
          ->isNull("$access_alias.rid")
          ->condition("$access_alias.grant_$op", 1, '>=')
          ->isNotNull("$aclu_alias.uid");
        $query->condition($or);
      }
      else {
        $aclu_alias = $query->leftJoin('acl_user', 'aclu', "%alias.acl_id = $acl_alias.acl_id AND %alias.uid = " . $account->id());
        $and = $query->andConditionGroup();
        $and
          ->condition("$access_alias.rid", $rids, 'IN')
          ->condition("$access_alias.grant_$op", 1, '>=');
        $condition = $query->orConditionGroup();
        $condition
          ->isNull("$access_alias.rid")
          ->condition($and)
          ->condition("$aclu_alias.uid", $account->id());
        $query->condition($condition);
      }
    }
  }
}

/**
 * Implements hook_ENTITY_TYPE_insert() for user_role entities.
 *
 * @inheritdoc
 */
function forum_access_user_role_insert(EntityInterface $entity) {
  $config = \Drupal::configFactory()->getEditable('forum_access.settings');
  $roles_gids = array_flip($config->get('forum_access_roles_gids'));
  $roles_gids[] = $entity->id();
  $config->set('forum_access_roles_gids', array_flip($roles_gids));
  $config->save();
}

/**
 * Implements hook_ENTITY_TYPE_delete() for user_role entities.
 *
 * @inheritdoc
 */
function forum_access_user_role_delete(EntityInterface $entity) {
  // Delete records from access tables.
  \Drupal::database()->delete('forum_access')
    ->condition('rid', $entity->id())
    ->execute();
  \Drupal::database()->delete('node_access')
    ->condition('gid', $entity->id())
    ->condition('realm', 'forum_access')
    ->execute();
  // Delete accordance between roles and numeric value.
  $config = \Drupal::configFactory()->getEditable('forum_access.settings');
  $roles_gids = $config->get('forum_access_roles_gids');
  unset($roles_gids[$entity->id()]);
  $config->set('forum_access_roles_gids', $roles_gids);
  $config->save();
}

/**
 * Implements hook_form_FORM_ID_alter() for node_form.
 *
 * @inheritdoc
 */
function forum_access_form_node_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if (!isset($form['taxonomy_forums'])) {
    return;
  }
  $node = $form_state->getFormObject()->getEntity();
  $account = \Drupal::currentUser();
  // True node administrators are all powerful
  // and do NOT get their forms rewritten here.
  if ($account->hasPermission('bypass node access')) {
    return;
  }

  // Get list of available lists.
  $tids = forum_access_form_node_form_get_available_tids($account, $node);
  $forum_tid = forum_access_get_tid($node);
  // Leave only that forum options for which user has access.
  $form_options = &$form['taxonomy_forums']['widget']['#options'];
  foreach ($form_options as $tid => $name) {
    if (!isset($tids[$tid])) {
      unset($form_options[$tid]);
    }
  }
  // Apply modifications for Moderators (by role or uid).
  if (!$account->hasPermission('administer nodes') && forum_access_is_moderator($account, $forum_tid)) {
    foreach (Element::children($form) as $key) {
      switch ($key) {
        case 'sticky':
          $form[$key]['#access'] = TRUE;
          break;

        case 'revision':
          $form['revision']['#access'] = TRUE;
          break;

        case 'comment_forum':
          $form[$key]['#access'] = TRUE;
          break;

        case 'shadow':
          $form[$key]['#description'] .= ' ' . t('Note: Access to this topic and its shadows is controlled by the forum that contains the topic.');
          break;

        case 'taxonomy_forums':
          $form[$key]['widget']['#description'] .= t('Note: Moving a topic to a different forum may change its accessibility.');
          break;
      }
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter() for taxonomy_term_forums_forum_form.
 *
 * @inheritdoc
 */
function forum_access_form_taxonomy_term_forums_forum_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.admin');
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.acl');
  $tid = $form['tid']['#value'];
  $settings = forum_access_get_settings($tid);
  $form['forum_access'] = [
    '#type' => 'details',
    '#title' => t('Access control'),
    '#collapsible' => TRUE,
    '#tree' => TRUE,
  ];
  // Moderators fields.
  $form['forum_access']['permissions'] = _forum_access_forum_permissions_form();
  $form['forum_access']['grants'] = _forum_access_forum_grants_form($form_state, $settings);
  $form['forum_access']['moderators'] = _forum_access_forum_moderators_form($form_state, $tid);
  $form['actions']['submit']['#submit'][] = '_forum_access_admin_forum_form_submit';
  if (!empty($form['actions']['overview'])) {
    $form['actions']['overview']['#submit'][] = '_forum_access_admin_forum_form_submit';
  }

  if (isset($tid) /*&& !node_access_needs_rebuild()*/) {
    // Count number of nodes which are attached to this term.
    $count = Drupal::database()
      ->select('node__taxonomy_forums')
      ->condition('taxonomy_forums_target_id', $tid)
      ->countQuery()
      ->distinct()
      ->execute()
      ->fetchField();
    $limit = $threshold = 20;
    $form['forum_access']['update_limit'] = [
      '#type' => 'value',
      '#value' => $limit,
    ];
    $form['forum_access']['update_choice'] = [
      '#type' => 'radios',
      '#title' => t('Update the permissions'),
      '#options' => array_flip(['all_now', 'all_later']),
      '#default_value' => 'all_now',
      'all_now' => [
        '#type' => 'radio',
        '#title' => t('rebuild <strong>all</strong> permissions now'),
      ],
      'all_later' => [
        '#type' => 'radio',
        '#title' => t('rebuild <strong>all</strong> permissions later &mdash; do not forget to <a href=":rebuild">Rebuild permissions</a> as soon as possible!', [
          ':rebuild' => Url::fromRoute('node.configure_rebuild_confirm')->toString(),
        ]),
        '#attributes' => ['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.")],
      ],
      '#attributes' => ['class' => ['forum-access-flowed']],
    ];
  }
  if (isset($tid)) {
    $form['forum_access']['force_update'] = [
      '#type' => 'checkbox',
      '#title' => t('Update even if unchanged'),
    ];
  }
  $form['forum_access']['#after_build'][] = 'forum_access_form_taxonomy_term_forums_x_form_alter_after_build';
}

/**
 * Check for moderators, past or new.
 */
function forum_access_form_taxonomy_term_forums_x_form_alter_after_build(array $form, FormStateInterface $form_state) {
  // Open the Moderators details if past or new moderators are set.
  $moderators_form = &$form['moderators'];
  $past_moderators = acl_edit_form_get_user_list($moderators_form, TRUE);
  $future_moderators = acl_edit_form_get_user_list($moderators_form);
  $moderators_form['#open'] = !empty($past_moderators) || !empty($future_moderators);
  if (acl_edit_form_get_user_list_changed($moderators_form)) {
    $form['#open'] = TRUE;
  }
  return $form;
}

/**
 * Submit handler for forum access administrative form.
 */
function _forum_access_admin_forum_form_submit($form, FormStateInterface $form_state) {
  // Shared code.
  _forum_access_admin_container_form_submit($form, $form_state);

  if (\Drupal::routeMatch()->getRouteName() != 'forum.add_forum') {
    // Update access records.
    _forum_access_update_access_records($form, $form_state);
  }
}

/**
 * Implements hook_form_FORM_ID_alter() for taxonomy_term_forums_container_form.
 *
 * @inheritdoc
 */
function forum_access_form_taxonomy_term_forums_container_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.admin');
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.acl');
  $tid = $form['tid']['#value'];
  $settings = forum_access_get_settings($tid);
  $form['forum_access'] = [
    '#type' => 'details',
    '#title' => t('Access control'),
    '#collapsible' => TRUE,
    '#tree' => TRUE,
  ];
  // Moderators fields.
  $form['forum_access']['grants'] = _forum_access_container_grants_form($form_state, $settings);
  $form['forum_access']['moderators'] = _forum_access_forum_moderators_form($form_state, $tid);
  $form['forum_access']['#after_build'][] = 'forum_access_form_taxonomy_term_forums_x_form_alter_after_build';
  $form['actions']['submit']['#submit'][] = '_forum_access_admin_container_form_submit';
  if (!empty($form['actions']['overview'])) {
    $form['actions']['overview']['#submit'][] = '_forum_access_admin_container_form_submit';
  }
}

/**
 * Submit handler for container access administrative form.
 */
function _forum_access_admin_container_form_submit($form, FormStateInterface $form_state) {
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.admin');

  // Save roles permissions.
  _forum_access_form_roles_permissions_save($form_state);

  // (We can't use $form_state here because D8 fails to call #after_build.)
  if (acl_edit_form_get_user_list_changed($form['forum_access']['moderators'])) {
    // Save moderators list.
    _forum_access_form_moderators_save($form_state);
  }
}

/**
 * This is also required by ACL module.
 *
 * @see acl_node_access_records()
 */
function forum_access_enabled($set = NULL) {
  // Not drupal_static!
  static $enabled = TRUE;
  if ($set !== NULL) {
    $enabled = $set;
  }
  return $enabled;
}

/**
 * Retrieve the settings for a taxonomy term.
 *
 * @param int $tid
 *   (optional) Taxonomy term id.
 *
 * @return array
 *   Settings for a taxonomy term.
 */
function forum_access_get_settings($tid = NULL) {
  $settings = [
    'view' => [],
    'create' => [],
    'update' => [],
    'delete' => [],
    'priority' => 0,
  ];
  $result = \Drupal::database()->select('forum_access', 'a')
    ->fields('a', [
      'tid',
      'rid',
      'grant_view',
      'grant_update',
      'grant_delete',
      'grant_create',
      'priority',
    ])
    ->condition('tid', $tid)
    ->execute();
  foreach ($result as $access) {
    if ($access->grant_view) {
      $settings['view'][] = $access->rid;
    }
    if ($access->grant_update) {
      $settings['update'][] = $access->rid;
    }
    if ($access->grant_delete) {
      $settings['delete'][] = $access->rid;
    }
    if ($access->grant_create) {
      $settings['create'][] = $access->rid;
    }
    if ($access->rid == AccountInterface::AUTHENTICATED_ROLE) {
      // This is our reference.
      $settings['priority'] = $access->priority;
    }
  }
  return $settings;
}

/**
 * Set settings for taxonomy term.
 *
 * @param int $tid
 *   Taxonomy term id.
 * @param array $settings
 *   Forum Access settings.
 */
function forum_access_set_settings($tid, array $settings) {
  \Drupal::database()->delete('forum_access')
    ->condition('tid', $tid)
    ->execute();
  $insert = \Drupal::database()->insert('forum_access');
  $insert->fields([
    'tid',
    'rid',
    'grant_view',
    'grant_update',
    'grant_delete',
    'grant_create',
    'priority',
  ]);
  foreach ($settings['view'] as $rid => $checked) {
    $insert->values([
      'tid' => $tid,
      'rid' => $rid,
      'grant_view' => (int) !empty($checked),
      'grant_update' => (int) !empty($settings['update'][$rid]),
      'grant_delete' => (int) !empty($settings['delete'][$rid]),
      'grant_create' => (int) !empty($settings['create'][$rid]),
      'priority' => 0,
    ]);
  }
  $insert->execute();
}

/**
 * Get list of available tids for specific account.
 *
 * @param \Drupal\Core\Session\AccountInterface $account
 *   The user object for the user whose access is being checked.
 * @param \Drupal\node\NodeInterface $node
 *   The node to check.
 *
 * @return array
 *   List of available tids for specific account.
 */
function forum_access_form_node_form_get_available_tids(AccountInterface $account, NodeInterface $node) {
  \Drupal::moduleHandler()->loadInclude('forum_access', 'inc', 'includes/forum_access.common');
  // We figure out what tids we want to show in form according
  // to the forum access settings.
  $forum_access_settings = forum_access_get_settings_by_roles($account->getRoles(), 'create');
  $tids = [];
  foreach ($forum_access_settings as $setting) {
    $tids[$setting->tid] = $setting->tid;
  }
  // Also get all forums they happen to be able to moderate.
  $acl_access_settings = forum_access_get_settings_by_user('forum_access', $account->id(), 'moderate');
  foreach ($acl_access_settings as $setting) {
    $tids[$setting->figure] = $setting->figure;
  }
  // Make available current forum for existed node.
  if (!empty($node)) {
    $forum_tid = forum_access_get_tid($node);
    $tids[$forum_tid] = $forum_tid;
  }
  return $tids;
}

/**
 * Preprocess for output of form with roles and permissions.
 *
 * @param array $variables
 *   An associative array containing:
 *   - form: A render element representing the form with
 *     - check_boxes: A render element representing the forum_access table.
 */
function template_preprocess_forum_access_table(array &$variables) {
  $checkboxes = &$variables['form']['checkboxes'];
  foreach (Element::children($checkboxes) as $child) {
    foreach (Element::children($checkboxes[$child]) as $child2) {
      $variables['form']['rows'][$child2][] = $checkboxes[$child][$child2];
    }
  }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc