-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PE-672 Bulk group membership management (#636)
* PE-672 Bulk group membership management * PE-672 Modify items selected list for group_content-based actions to provide better context. * PE-672 Give error if multiple group types are selected
- Loading branch information
1 parent
6d0b955
commit 2b0bdbc
Showing
16 changed files
with
1,369 additions
and
51 deletions.
There are no files selected for viewing
153 changes: 153 additions & 0 deletions
153
web/modules/custom/employees/src/Plugin/Action/AddGroupMembershipAction.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
<?php | ||
|
||
namespace Drupal\employees\Plugin\Action; | ||
|
||
use Drupal\views_bulk_operations\Action\ViewsBulkOperationsActionBase; | ||
use Drupal\Core\Session\AccountInterface; | ||
use Drupal\Core\StringTranslation\StringTranslationTrait; | ||
use Drupal\Core\Action\Attribute\Action; | ||
use Drupal\Core\Entity\EntityTypeManagerInterface; | ||
use Drupal\Core\Form\FormStateInterface; | ||
use Drupal\Core\Plugin\PluginFormInterface; | ||
use Drupal\user\UserInterface; | ||
use Drupal\group\Entity\Group; | ||
|
||
|
||
/** | ||
* Views bulk operations action that allows adding mulitple users to a group in bulk. | ||
* | ||
* @Action( | ||
* id = "employees_add_users_to_group", | ||
* label = @Translation("Add users to a group (custom action)"), | ||
* type = "user", | ||
* confirm = FALSE, | ||
* ) | ||
*/ | ||
final class AddGroupMembershipAction extends ViewsBulkOperationsActionBase implements PluginFormInterface { | ||
|
||
use StringTranslationTrait; | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function execute(UserInterface $user = NULL) { | ||
if ($user === NULL || $this->configuration['group_id'] === 0) { | ||
return $this->t('Invalid entity or configuration.'); | ||
} | ||
|
||
$group_id = $this->configuration['group_id']; | ||
$role_ids = $this->configuration['role_ids']; | ||
$group = \Drupal::entityTypeManager()->getStorage('group')->load($group_id); | ||
$membership = $group->getMember($user); | ||
if ($membership === FALSE) { | ||
// Add user to the group with the assigned role(s) | ||
$role_ids = array_diff($role_ids, [0]); // Remove array elements with the value of "0" | ||
$group->addMember($user, ['group_roles' => array_keys($role_ids)]); | ||
} else { | ||
// User is already a member of the group so just update the role(s) | ||
foreach ($role_ids as $role_id => $assign_role) { | ||
if ($assign_role) { | ||
$membership->addRole($role_id); | ||
} else { | ||
$membership->removeRole($role_id); | ||
} | ||
} | ||
} | ||
|
||
return $this->t('User has been added to the group with the assigned roles.'); | ||
} | ||
|
||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) { | ||
// Step tracking | ||
$current_step = $form_state->get('current_step') ?? 1; | ||
|
||
// Build the form based on the current step | ||
switch ($current_step) { | ||
case 1: | ||
$form['step_desc'] = [ | ||
'#type' => 'markup', | ||
'#markup' => '<h4>' . t('Step 1 of 2: Select the group') . '</h4>', | ||
]; | ||
$form['group_id'] = [ | ||
'#type' => 'entity_autocomplete', | ||
'#title' => $this->t('Group'), | ||
'#placeholder' => $this->t('Enter group name'), | ||
'#target_type' => 'group', | ||
'#selection_settings' => ['filter' => ['access' => 'administer members']], | ||
'#required' => TRUE, | ||
'#tags' => FALSE, | ||
]; | ||
|
||
$form['actions']['submit']['#value'] = t('Next'); | ||
break; | ||
|
||
case 2: | ||
$form['step_desc'] = [ | ||
'#type' => 'markup', | ||
'#markup' => '<h4>' . t('Step 2 of 2: Assign group role(s)') . '</h4>', | ||
]; | ||
|
||
$form['group'] = [ | ||
'#type' => 'markup', | ||
'#markup' => '<p><strong>Group:</strong> ' . $form_state->getUserInput()['group_id'] . '</p>', | ||
]; | ||
|
||
$group_id = $form_state->getValue('group_id'); | ||
$form['group_id'] = [ | ||
'#type' => 'hidden', | ||
'#value' => $group_id, | ||
]; | ||
|
||
// Get the group roles associated with the selected group | ||
$roles = \Drupal::entityTypeManager()->getStorage('group')->load($group_id)->getGroupType()->getRoles(FALSE); | ||
$role_options = array(); | ||
foreach ($roles as $role) { | ||
$role_options[$role->id()] = $role->label(); | ||
} | ||
$form['role_ids'] = [ | ||
'#type' => 'checkboxes', | ||
'#title' => $this->t('Roles'), | ||
'#options' => $role_options, | ||
'#required' => TRUE, | ||
'#description' => $this->t('IMPORTANT: If a user already belongs to the selected group, this will remove their current roles and assign the roles selected here.'), | ||
]; | ||
break; | ||
} | ||
|
||
// Store the current step | ||
$form_state->set('current_step', $current_step); | ||
|
||
return $form; | ||
} | ||
|
||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { | ||
$button = $form_state->getTriggeringElement()['#value']->getUntranslatedString(); | ||
|
||
if ($button === 'Next') { | ||
$current_step = $form_state->get('current_step'); | ||
$form_state->set('current_step', ++$current_step); | ||
$form_state->setRebuild(); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function access($object, ?AccountInterface $account = NULL, $return_as_object = FALSE) { | ||
// This checks for edit access on the selected users' accounts. We can't really check if the operator | ||
// has the necessary group permissions because the group hasn't been chosen yet, but since this action is | ||
// only available on the /admin/people view which requires sitewide admin permissions, we can assume the | ||
// operator has the necessary permissions. | ||
return $object->access('edit', $account, $return_as_object); | ||
} | ||
|
||
} |
131 changes: 131 additions & 0 deletions
131
web/modules/custom/employees/src/Plugin/Action/AddGroupMembershipsAction.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
<?php | ||
|
||
namespace Drupal\employees\Plugin\Action; | ||
|
||
use Drupal\views_bulk_operations\Action\ViewsBulkOperationsActionBase; | ||
use Drupal\Core\Session\AccountInterface; | ||
use Drupal\Core\StringTranslation\StringTranslationTrait; | ||
use Drupal\Core\Action\Attribute\Action; | ||
use Drupal\Core\Entity\EntityTypeManagerInterface; | ||
use Drupal\Core\Form\FormStateInterface; | ||
use Drupal\Core\Plugin\PluginFormInterface; | ||
use Drupal\group\Entity\Group; | ||
use Drupal\Core\Access\AccessResult; | ||
|
||
/** | ||
* Views bulk operations action that allows adding users to multiple groups in bulk. | ||
* | ||
* @Action( | ||
* id = "employees_add_user_to_groups", | ||
* label = @Translation("Add or update members (custom action)"), | ||
* type = "group", | ||
* confirm = FALSE, | ||
* ) | ||
*/ | ||
final class AddGroupMembershipsAction extends ViewsBulkOperationsActionBase implements PluginFormInterface { | ||
|
||
use StringTranslationTrait; | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function execute(Group $group = NULL) { | ||
if ($group === NULL || \count($this->configuration['user_id']) === 0) { | ||
return $this->t('Invalid entity or configuration.'); | ||
} | ||
|
||
$user_ids = []; | ||
foreach ($this->configuration['user_id'] as $item) { | ||
$user_ids[$item['target_id']] = $item['target_id']; | ||
} | ||
|
||
$role_ids = $this->configuration['role_ids']; | ||
foreach (\Drupal::entityTypeManager()->getStorage('user')->loadMultiple($user_ids) as $user) { | ||
$membership = $group->getMember($user); | ||
if ($membership === FALSE) { | ||
// Add user to the group with the assigned role(s) | ||
$role_ids = array_diff($role_ids, [0]); // Remove array elements with the value of "0" | ||
$group->addMember($user, ['group_roles' => array_keys($role_ids)]); | ||
} else { | ||
// User is already a member of the group so just update the role(s) | ||
foreach ($role_ids as $role_id => $assign_role) { | ||
if ($assign_role) { | ||
$membership->addRole($role_id); | ||
} else { | ||
$membership->removeRole($role_id); | ||
} | ||
} | ||
} | ||
} | ||
|
||
return $this->t('User has been added to the group with the assigned roles.'); | ||
} | ||
|
||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) { | ||
// Make sure all selected groups are of the same group type | ||
$groups = $form_state->getStorage()['views_bulk_operations']['list']; | ||
$group_types = array(); | ||
foreach ($groups as $group) { | ||
$group_id = $group[0]; | ||
$group_type = \Drupal::entityTypeManager()->getStorage('group')->load($group_id)->getGroupType(); | ||
$group_types[$group_type->id()] = $group_type->label(); | ||
|
||
if (count($group_types) > 1) { | ||
$group_type_labels = implode(', ', $group_types); | ||
$form['error'] = [ | ||
'#type' => 'markup', | ||
'#markup' => '<p>' . t("Error: All selected groups must be of the same group type. Current selection includes groups of type $group_type_labels.") . '</p>', | ||
]; | ||
$form['actions']['submit']['#disabled'] = TRUE; | ||
return $form; | ||
} | ||
} | ||
|
||
$form['user_id'] = [ | ||
'#type' => 'entity_autocomplete', | ||
'#title' => $this->t('User'), | ||
'#placeholder' => $this->t('Enter user name'), | ||
'#target_type' => 'user', | ||
'#selection_settings' => ['filter' => ['access' => 'administer members']], | ||
'#required' => TRUE, | ||
'#tags' => TRUE, | ||
'#description' => $this->t('Use a comma to select multiple users.'), | ||
]; | ||
|
||
// Get the group roles associated with the first selected group | ||
$groups = $form_state->getStorage()['views_bulk_operations']['list']; | ||
$first_key = array_keys($groups)[0]; | ||
$group_id = $groups[$first_key][0]; | ||
$roles = \Drupal::entityTypeManager()->getStorage('group')->load($group_id)->getGroupType()->getRoles(FALSE); | ||
$role_options = array(); | ||
foreach ($roles as $role) { | ||
$role_options[$role->id()] = $role->label(); | ||
} | ||
$form['role_ids'] = [ | ||
'#type' => 'checkboxes', | ||
'#title' => $this->t('Roles'), | ||
'#options' => $role_options, | ||
'#required' => TRUE, | ||
'#description' => $this->t('IMPORTANT: If a user already belongs to a selected group, this will remove their current roles and assign the roles selected here.'), | ||
]; | ||
|
||
return $form; | ||
} | ||
|
||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function access($object, ?AccountInterface $account = NULL, $return_as_object = FALSE) { | ||
$has_access = $object->hasPermission('administer members', $account, $return_as_object); | ||
if ($return_as_object) { | ||
return $has_access ? AccessResult::allowed() : AccessResult::forbidden(); | ||
} else { | ||
return $has_access; | ||
} | ||
} | ||
} |
97 changes: 97 additions & 0 deletions
97
web/modules/custom/employees/src/Plugin/Action/EditGroupMembershipAction.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
<?php | ||
|
||
namespace Drupal\employees\Plugin\Action; | ||
|
||
use Drupal\views_bulk_operations\Action\ViewsBulkOperationsActionBase; | ||
use Drupal\Core\Session\AccountInterface; | ||
use Drupal\Core\StringTranslation\StringTranslationTrait; | ||
use Drupal\Core\Action\Attribute\Action; | ||
use Drupal\Core\Entity\EntityTypeManagerInterface; | ||
use Drupal\Core\Form\FormStateInterface; | ||
use Drupal\Core\Plugin\PluginFormInterface; | ||
use Drupal\group\Entity\GroupMembership; | ||
use Drupal\Core\Access\AccessResult; | ||
|
||
/** | ||
* Views bulk operations action that allows editing multiple users group memberships in bulk. | ||
* | ||
* @Action( | ||
* id = "employees_edit_users_membership", | ||
* label = @Translation("Edit group roles (custom action)"), | ||
* type = "group_content", | ||
* confirm = FALSE, | ||
* ) | ||
*/ | ||
final class EditGroupMembershipAction extends ViewsBulkOperationsActionBase implements PluginFormInterface { | ||
|
||
use StringTranslationTrait; | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function execute(GroupMembership $membership = NULL) { | ||
if ($membership === NULL || \count($this->configuration['role_ids']) === 0) { | ||
return $this->t('Invalid entity or configuration.'); | ||
} | ||
|
||
$role_ids = $this->configuration['role_ids']; | ||
foreach ($role_ids as $role_id => $assign_role) { | ||
if ($assign_role) { | ||
$membership->addRole($role_id); | ||
} else { | ||
$membership->removeRole($role_id); | ||
} | ||
} | ||
|
||
return $this->t('The user\'s group roles have been updated.'); | ||
} | ||
|
||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) { | ||
// Get the group roles associated with the group | ||
$group_contents = $form_state->getStorage()['views_bulk_operations']['list']; | ||
$first_key = array_keys($group_contents)[0]; | ||
$group_content_id = $group_contents[$first_key][0]; | ||
$roles = \Drupal::entityTypeManager()->getStorage('group_content')->load($group_content_id)->getGroup()->getGroupType()->getRoles(FALSE); | ||
$role_options = array(); | ||
foreach ($roles as $role) { | ||
$role_options[$role->id()] = $role->label(); | ||
} | ||
$form['role_ids'] = [ | ||
'#type' => 'checkboxes', | ||
'#title' => $this->t('Roles'), | ||
'#options' => $role_options, | ||
'#required' => TRUE, | ||
'#description' => $this->t('IMPORTANT: This will remove the users\' current roles and assign the roles selected here.'), | ||
]; | ||
|
||
// The "Items selected" list on group_content-based views has the user’s name. Include the | ||
// selected groups' name too. | ||
$list = $form_state->getStorage()['views_bulk_operations']['list']; | ||
$count = 0; | ||
foreach ($list as $item) { | ||
$entity_id = $item[0]; | ||
$username = $form['list']['#items'][$count]; | ||
$group = \Drupal::entityTypeManager()->getStorage('group_content')->load($entity_id)->getGroup(); | ||
$form['list']['#items'][$count++] = "$username in " . $group->label(); | ||
} | ||
|
||
return $form; | ||
} | ||
|
||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function access($object, ?AccountInterface $account = NULL, $return_as_object = FALSE) { | ||
$has_access = $object->getGroup()->hasPermission('administer members', $account, $return_as_object); | ||
if ($return_as_object) { | ||
return $has_access ? AccessResult::allowed() : AccessResult::forbidden(); | ||
} else { | ||
return $has_access; | ||
} | ||
} | ||
} |
Oops, something went wrong.