workbench_access.module in Workbench Access 8
Same filename and directory in other branches
Contains workbench_access.module.
File
workbench_access.moduleView source
<?php
/**
* @file
* Contains workbench_access.module.
*/
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\workbench_access\Entity\AccessSchemeInterface;
use Drupal\workbench_access\FormAlterHelper;
/**
* Implements hook_help().
*/
function workbench_access_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the workbench_access module.
case 'help.page.workbench_access':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Hierarchical access control module.') . '</p>';
return $output;
default:
}
}
/**
* Implements hook_form_alter().
*
* Restricts selection options for the node form.
*/
function workbench_access_form_alter(&$form, FormStateInterface $form_state) {
$form_object = $form_state
->getFormObject();
if (!$form_object instanceof EntityForm) {
return;
}
$entity = $form_object
->getEntity();
if (!$entity instanceof ContentEntityInterface) {
return;
}
\Drupal::classResolver()
->getInstanceFromDefinition(FormAlterHelper::class)
->alterForm($form, $form, $form_state, $entity);
}
/**
* Implements hook_entity_access().
*/
function workbench_access_entity_access(EntityInterface $entity, $op, AccountInterface $account) {
// Return net result of all enabled access schemes. If one scheme allows
// access, then it is granted.
// We don't care about the View operation right now.
if ($op === 'view' || $op === 'view label' || $account
->hasPermission('bypass workbench access')) {
// Return early.
return AccessResult::neutral();
}
return array_reduce(\Drupal::entityTypeManager()
->getStorage('access_scheme')
->loadMultiple(), function (AccessResult $carry, AccessSchemeInterface $scheme) use ($entity, $op, $account) {
$carry
->addCacheableDependency($scheme)
->cachePerPermissions()
->addCacheableDependency($entity);
return $carry
->orIf($scheme
->getAccessScheme()
->checkEntityAccess($scheme, $entity, $op, $account));
}, AccessResult::neutral());
}
/**
* Implements hook_entity_delete().
*/
function workbench_access_entity_delete(EntityInterface $entity) {
foreach (\Drupal::entityTypeManager()
->getStorage('access_scheme')
->loadMultiple() as $scheme) {
$entity_type = $scheme
->getAccessScheme()
->entityType();
if ($entity_type === $entity
->getEntityTypeId()) {
// Delete all associated storage.
$section_storage = \Drupal::entityTypeManager()
->getStorage('section_association');
$sections = $section_storage
->loadByProperties([
'access_scheme' => $scheme
->id(),
'section_id' => $entity
->id(),
]);
$section_storage
->delete($sections);
\Drupal::service('workbench_access.user_section_storage')
->resetCache($scheme);
}
}
}
/**
* Implements hook_node_create_access().
*
* @link https://www.drupal.org/node/2348203
*/
function workbench_access_entity_create_access(AccountInterface $account, $context, $entity_bundle) {
// @todo move this to the access schemes.
$return = AccessResult::neutral();
// User can bypass.
if ($account
->hasPermission('bypass workbench access')) {
return $return
->cachePerPermissions();
}
// Check that access control applies to this entity type.
$entity_type_id = $context['entity_type_id'];
$schemes = array_filter(\Drupal::entityTypeManager()
->getStorage('access_scheme')
->loadMultiple(), function (AccessSchemeInterface $scheme) use ($entity_type_id, $entity_bundle, $return) {
$return
->addCacheableDependency($scheme);
return $scheme
->getAccessScheme()
->applies($entity_type_id, $entity_bundle);
});
if (!$schemes) {
return $return
->addCacheTags([
'access_scheme_list',
]);
}
// Check that the user is able to assign content to a section.
$user_section_storage = \Drupal::service('workbench_access.user_section_storage');
$forbidden = AccessResult::forbidden();
$invalid_schemes = array_reduce($schemes, function ($carry, AccessSchemeInterface $scheme) use ($user_section_storage, $account, $forbidden) {
$sections = $user_section_storage
->getUserSections($scheme, $account);
if (!$sections) {
$carry[] = $scheme
->label();
}
$forbidden
->addCacheableDependency($scheme);
return $carry;
}, []);
if ($invalid_schemes) {
return $forbidden
->setReason(sprintf('User has no active sections for the following access scheme(s): %s', implode(', ', $invalid_schemes)));
}
return $return;
}
/**
* Implements hook_views_data_alter().
*/
function workbench_access_views_data_alter(array &$data) {
$scheme_storage = \Drupal::entityTypeManager()
->getStorage('access_scheme');
if ($schemes = $scheme_storage
->loadMultiple()) {
/** @var \Drupal\workbench_access\Entity\AccessSchemeInterface $scheme */
foreach ($schemes as $id => $scheme) {
$scheme
->getAccessScheme()
->viewsData($data, $scheme);
$data['users']['workbench_access_section__' . $scheme
->id()] = [
'title' => t('Workbench Section: @name', [
'@name' => $scheme
->label(),
]),
'help' => t('The sections to which this user belongs for the @name scheme.', [
'@name' => $scheme
->label(),
]),
'field' => [
'id' => 'workbench_access_user_section',
'scheme' => $scheme
->id(),
],
'filter' => [
'field' => 'uid',
'scheme' => $scheme
->id(),
'id' => 'workbench_access_section',
],
];
}
}
// Legacy support.
// @todo Remove in 8.x-2.x.
if ($default = \Drupal::state()
->get('workbench_access_upgraded_scheme_id')) {
if ($scheme = $scheme_storage
->load($default)) {
$data['users']['workbench_access_section'] = [
'title' => t('Workbench Section: @name (legacy)', [
'@name' => $scheme
->label(),
]),
'help' => t('The sections to which this user belongs for the @name scheme.', [
'@name' => $scheme
->label(),
]),
'field' => [
'id' => 'workbench_access_user_section',
'scheme' => $scheme
->id(),
],
'filter' => [
'field' => 'uid',
'scheme' => $scheme
->id(),
'id' => 'workbench_access_section',
],
];
}
if (isset($data['node']['workbench_access_section__default'])) {
$data['node']['workbench_access_section'] = $data['node']['workbench_access_section__default'];
$data['node']['workbench_access_section']['title'] = t('Workbench Section: @name (legacy)', [
'@name' => $scheme
->label(),
]);
}
}
}
/**
* Implements hook_element_info_alter().
*/
function workbench_access_element_info_alter(array &$info) {
if (isset($info['inline_entity_form'])) {
$info['inline_entity_form']['#process'][] = 'workbench_access_process_inline_entity_form';
}
}
/**
* Process callback for inline entity form.
*/
function workbench_access_process_inline_entity_form(array &$element, FormStateInterface $form_state, &$complete_form) {
$entity = $element['#entity'];
if (!$entity instanceof ContentEntityInterface) {
return $element;
}
return \Drupal::classResolver()
->getInstanceFromDefinition(FormAlterHelper::class)
->alterForm($element, $complete_form, $form_state, $entity);
}
/**
* Implements hook_ENTITY_TYPE_delete().
*/
function workbench_access_user_delete($account) {
$uid = $account
->id();
$storage_handler = \Drupal::entityTypeManager()
->getStorage('section_association');
// Retrieve all the section associations referencing this user.
$section_user_associations = $storage_handler
->loadByProperties([
'user_id' => $uid,
]);
foreach ($section_user_associations as $section_association) {
// For each retrived association, remove this user.
if ($user_ids = $section_association
->getCurrentUserIds()) {
$remaining_user_ids = array_diff($user_ids, [
$uid,
]);
$section_association
->set('user_id', $remaining_user_ids);
$section_association
->save();
}
}
}
/**
* Implements hook_ENTITY_TYPE_delete().
*/
function workbench_access_user_role_delete($role) {
$role_section_storage = \Drupal::service('workbench_access.role_section_storage');
$scheme_storage = \Drupal::entityTypeManager()
->getStorage('access_scheme');
foreach ($scheme_storage
->loadMultiple() as $scheme) {
$role_section_storage
->deleteRoleSections($scheme, $role
->id());
}
}
/**
* Implements hook_token_info().
*/
function workbench_access_token_info() {
return \Drupal::service('workbench_access.tokens')
->getTokenInfo();
}
/**
* Implements hook_tokens().
*/
function workbench_access_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
return \Drupal::service('workbench_access.tokens')
->getTokens($type, $tokens, $data, $options, $bubbleable_metadata);
}
Functions
Name | Description |
---|---|
workbench_access_element_info_alter | Implements hook_element_info_alter(). |
workbench_access_entity_access | Implements hook_entity_access(). |
workbench_access_entity_create_access | Implements hook_node_create_access(). |
workbench_access_entity_delete | Implements hook_entity_delete(). |
workbench_access_form_alter | Implements hook_form_alter(). |
workbench_access_help | Implements hook_help(). |
workbench_access_process_inline_entity_form | Process callback for inline entity form. |
workbench_access_tokens | Implements hook_tokens(). |
workbench_access_token_info | Implements hook_token_info(). |
workbench_access_user_delete | Implements hook_ENTITY_TYPE_delete(). |
workbench_access_user_role_delete | Implements hook_ENTITY_TYPE_delete(). |
workbench_access_views_data_alter | Implements hook_views_data_alter(). |