Version 1
[yaffs-website] / web / modules / contrib / permissions_by_term / permissions_by_term.module
diff --git a/web/modules/contrib/permissions_by_term/permissions_by_term.module b/web/modules/contrib/permissions_by_term/permissions_by_term.module
new file mode 100644 (file)
index 0000000..5886d98
--- /dev/null
@@ -0,0 +1,300 @@
+<?php
+
+/**
+ * @file
+ * Allows access to terms in a vocabulary to be limited by user or role.
+ */
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Form\FormState;
+use Drupal\permissions_by_term\Controller\PermissionsByTermController;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\node\NodeInterface;
+use Drupal\Core\Session\AccountInterface;
+use Drupal\taxonomy\Entity\Term;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Cache\Cache;
+
+/**
+ * Implements hook_help().
+ */
+function permissions_by_term_help($route_name, RouteMatchInterface $arg) {
+  switch ($route_name) {
+    case 'help.page.permissions_by_term':
+      $output = '';
+      $output .= '<h3>' . t('About') . '</h3>';
+      $output .= '<p>' . t('The "Permissions by Term" (PbT) module allows taxonomy administrators the
+        ability to restrict setting individual terms on nodes by user
+        or role. If a user is unable to set any terms for a required
+        vocabulary, they are blocked from adding or editing content with
+        that vocabulary. For more information, see the online documentation for <a href=":PbT-documentation" target="_blan" title="Online Documentation">Permissions by Term</a>.', [':PbT-documentation' => 'https://www.drupal.org/project/permissions_by_term']) . '</p>';
+      $output .= '<h3>' . t('Uses') . '</h3>';
+      $output .= '<dl>';
+      $output .= '<dt>' . t('General') . '</dt>';
+      $output .= '<dd>' . t('Use Permissions by Term to easily build access-restricted content areas on your websites.') . '</dd>';
+      $output .= '<dt>' . t('Lightweight Access Control') . '</dt>';
+      $output .= '<dd>' . t('Permissions by Term restricts user access to specified Drupal nodes based on taxonomy terms - a core part of Drupal’s functionality. PbT lets you restrict content access while relying on very little contributed code.') . '</dd>';
+      $output .= '<dt>' . t('Example use cases') . '</dt>';
+      $output .= '<dd>' . t('A club or service site with premium- or member-only content.') . '</dd>';
+      $output .= '<dd>' . t('School websites with content intended for teachers only and content aimed at individual classes within the school.') . '</dd>';
+      $output .= '<dd>' . t('Company intranets with sensitive or proprietary content alongside non-restricted content.') . '</dd>';
+      $output .= '</dl>';
+
+      return $output;
+  }
+}
+
+/**
+ * Validation handler for permissions_by_term_form_alter().
+ */
+function permissions_by_term_validate($form, FormState $oFormState) {
+  foreach ($form as $field) {
+    if (!is_object($field) && !empty($field['widget']['target_id']['#target_type']) && $field['widget']['target_id']['#target_type'] == 'taxonomy_term') {
+      $field_name = $field['widget']['#field_name'];
+      $terms = $oFormState->getValues()[$field_name]['target_id'];
+      $not_allowed_term_names = [];
+      if (!empty($terms)) {
+        foreach ($terms as $term) {
+          $term_id = $term['target_id'];
+          /* @var \Drupal\permissions_by_term\AccessCheck $access_check_service */
+          $access_check_service = \Drupal::service('permissions_by_term.access_check');
+          if (!$access_check_service->isAccessAllowedByDatabase($term_id)) {
+            $term = Term::load($term_id);
+            $not_allowed_term_names[] = $term->getName();
+          }
+        }
+      }
+    }
+  }
+  if (!empty($not_allowed_term_names)) {
+    if (count($not_allowed_term_names) > 1) {
+      $term_names = implode(', ', $not_allowed_term_names);
+    }
+    else {
+      $term_names = $not_allowed_term_names['0'];
+    }
+    $oFormState->setErrorByName('field_tags', t('You are not allowed to use specific taxonomy terms like the following: "term-names". Remove the restricted taxonomy terms from the form field and try again.',
+      ['term-names' => $term_names]));
+  }
+}
+
+/**
+ * Submit handler for permissions_by_term_form_alter().
+ */
+function permissions_by_term_submit($form, FormState $formState) {
+  $termId = $formState->getFormObject()->getEntity()->id();
+  /* @var \Drupal\permissions_by_term\AccessStorage $access_storage */
+  $access_storage = \Drupal::service('permissions_by_term.access_storage');
+  $access_storage->saveTermPermissions($formState, $termId);
+  /**
+   * @var \Drupal\permissions_by_term\NodeAccess $nodeAccess
+   */
+  $nodeAccess = \Drupal::service('permissions_by_term.node_access');
+  $nodeAccess->rebuildByTid($termId, $formState);
+  Cache::invalidateTags(['search_index:node_search']);
+}
+
+/**
+ * Implements hook_form_alter().
+ */
+function permissions_by_term_form_taxonomy_term_form_alter(&$form, FormStateInterface $oFormState, $form_id) {
+  if (\Drupal::currentUser()->hasPermission('show term permission form on term page')) {
+    $iTermId = $oFormState->getFormObject()->getEntity()->id();
+
+    /* @var \Drupal\permissions_by_term\AccessStorage $access_storage */
+    $access_storage = \Drupal::service('permissions_by_term.access_storage');
+
+    $form['access'] = [
+      '#type' => 'fieldset',
+      '#title' => t('Permissions'),
+      '#description' => t('To limit access to this term by user or roles,
+      add users or roles to the following lists. Leave empty to allow
+      node access by single node view, node listing in views and taxonomy
+      term selection by all users.'),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
+      '#attributes' => ['id' => 'fieldset_term_access'],
+      '#weight' => -5,
+      '#tree' => TRUE,
+    ];
+
+    $aAllowedUsers = $access_storage->getAllowedUserIds($iTermId);
+    if (!empty($aAllowedUsers)) {
+      $aAllowedUsers = user_load_multiple($aAllowedUsers);
+      $sUserFormValue = $access_storage->getUserFormValue($aAllowedUsers);
+    }
+    else {
+      $sUserFormValue = NULL;
+    }
+
+    // Note that the autocomplete widget will only enable for users with the
+    // 'access profiles' permission. Other users will have to specify the name
+    // manually.
+    $form['access']['user'] = [
+      '#type' => 'entity_autocomplete',
+      '#target_type' => 'user',
+      '#title' => t('Allowed users'),
+      '#description' => t('Enter a comma-seperated list of user names to give') . ' ' .
+      t('them permission to use this term and access related nodes in single node view
+      and views listings.'),
+      '#value' => $sUserFormValue,
+      '#size' => 60,
+      '#autocomplete_route_name' => 'permissions_by_term.autocomplete_multiple',
+      '#weight' => -10,
+    ];
+
+    $aAllowedRoles = $access_storage->getExistingRoleTermPermissionsByTid($iTermId);
+
+    // Firstly fetch all translated allowed role names.
+    $aTranslatedAllowedRoleNames = [];
+    foreach ($aAllowedRoles as $role) {
+      $aTranslatedAllowedRoleNames[] = $role;
+    }
+
+    // Get all roles for the complete form and translate them.
+    $aTranslatedUserRoles = [];
+    $array_key_counter = 1;
+    foreach (user_roles() as $user_role_id => $user_role_name) {
+      $aTranslatedUserRoles[$user_role_id] = $user_role_name->label();
+      $array_key_counter++;
+    }
+
+    // Generate the default values for the form.
+    $aSetRoles = [];
+    if (!empty($aTranslatedAllowedRoleNames)) {
+      foreach ($aTranslatedAllowedRoleNames as $role_name) {
+        $aSetRoles[] = $role_name;
+      }
+    }
+
+    // Now, lets do the Roles table.
+    $form['access']['role'] = [
+      '#type' => 'checkboxes',
+      '#title' => t('Allowed roles'),
+      '#description' => t('Select a role to allow all members of this role to
+        use this term and access related nodes in single node view and views
+        listings.'),
+      '#default_value' => $aSetRoles,
+      '#options' => $aTranslatedUserRoles,
+      '#multiple' => FALSE,
+      '#weight' => 5,
+    ];
+
+    $form['#validate'][] = 'permissions_by_term_validate';
+    $form['actions']['submit']['#submit'][] = 'permissions_by_term_submit';
+  }
+}
+
+/**
+ * Implements hook_form_alter().
+ */
+function permissions_by_term_form_alter(&$form, FormStateInterface $oFormState, $form_id) {
+  $form['#validate'][] = 'permissions_by_term_validate';
+}
+
+/**
+ * Implements hook_node_access().
+ *
+ * Forwards user by drupal_access_denied(); to an access denied page, if a
+ * single restricted node is called.
+ *
+ * This hook is not fired if admin is logged in. Users with the
+ * "bypass node access" permission may always view and edit content
+ * through the administrative interface.
+ */
+function permissions_by_term_node_access(NodeInterface $node, $op, AccountInterface $account) {
+  if (method_exists($node, 'id') && $op == 'view') {
+    if (!$node->isPublished() && !$account->hasPermission('Bypass content access control', $account)) {
+      return AccessResult::forbidden();
+    }
+
+    /* @var \Drupal\permissions_by_term\AccessCheck $access_check_service */
+    $access_check_service = \Drupal::service('permissions_by_term.access_check');
+    $oPermissionsByTermController = new PermissionsByTermController($access_check_service);
+
+    return $oPermissionsByTermController->handleNode($node->id());
+  }
+}
+
+/**
+ * Implements hook_node_grants().
+ */
+function permissions_by_term_node_grants(\Drupal\Core\Session\AccountInterface $account, $op)
+{
+    if ($op == 'view') {
+      /**
+       * @var \Drupal\permissions_by_term\AccessStorage $accessStorage
+       */
+      $accessStorage = \Drupal::service('permissions_by_term.access_storage');
+      $grants = $accessStorage->getGidsByRealm('permissions_by_term__uid_' . \Drupal::currentUser()->id());
+
+      return $grants;
+    }
+}
+
+/**
+ * Implements hook_node_access_records().
+ *
+ * Permissions can be rebuild at /admin/reports/status/rebuild.
+ */
+function permissions_by_term_node_access_records(\Drupal\node\NodeInterface $node) {
+  /**
+   * @var \Drupal\permissions_by_term\NodeAccess $nodeAccess
+   */
+  $nodeAccess = \Drupal::service('permissions_by_term.node_access');
+  $grantsForThisNode = $nodeAccess->createGrants($node->id());
+
+  $grants = [];
+  if (!empty($grantsForThisNode)) {
+    foreach ($grantsForThisNode as $grantObject) {
+      $grants[] = [
+        'realm' => $grantObject->realm,
+        'gid' => $grantObject->gid,
+        'grant_view' => $grantObject->grant_view,
+        'grant_update' => $grantObject->grant_update,
+        'grant_delete' => $grantObject->grant_delete,
+        'langcode' => $grantObject->langcode,
+        'fallback' => 1,
+        'nid' => $node->id(),
+      ];
+    }
+  }
+
+  return $grants;
+}
+
+/**
+ * Implements hook_user_insert().
+ */
+function permissions_by_term_user_insert($user) {
+  /**
+   * @var \Drupal\permissions_by_term\NodeAccess $nodeAccess
+   */
+  $nodeAccess = \Drupal::service('permissions_by_term.node_access');
+  $nodeAccess->rebuildByUid($user->id(), TRUE);
+  Cache::invalidateTags(['search_index:node_search']);
+}
+
+/**
+ * Implements hook_user_update().
+ */
+function permissions_by_term_user_update($user) {
+  /**
+   * @var \Drupal\permissions_by_term\NodeAccess $nodeAccess
+   */
+  $nodeAccess = \Drupal::service('permissions_by_term.node_access');
+  $nodeAccess->rebuildByUid($user->id());
+  Cache::invalidateTags(['search_index:node_search']);
+}
+
+/**
+ * Implements hook_node_insert().
+ */
+function permissions_by_term_node_insert($node) {
+  /**
+   * @var \Drupal\permissions_by_term\NodeAccess $nodeAccess
+   */
+  $nodeAccess = \Drupal::service('permissions_by_term.node_access');
+  $nodeAccess->rebuildByNid($node->id());
+  Cache::invalidateTags(['search_index:node_search']);
+}