diff --git a/private_message.module b/private_message.module index 26f2452ca6e068941452018dc6fa9cace57cd5f4..0ff0ffab3f7e0eaa85c6760d09c6cbd149c037eb 100644 --- a/private_message.module +++ b/private_message.module @@ -10,12 +10,15 @@ declare(strict_types=1); use Drupal\Component\Render\MarkupInterface; use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\Query\QueryInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Render\Element; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; use Drupal\private_message\Entity\PrivateMessage; use Drupal\user\Entity\User; +use Drupal\user\Plugin\EntityReferenceSelection\UserSelection; +use Drupal\user\RoleInterface; /** * Implements hook_views_data(). @@ -691,3 +694,59 @@ function private_message_theme_suggestions_private_message_thread_alter(array &$ function private_message_theme_suggestions_private_message_alter(array &$suggestions, array &$vars): void { $suggestions[] = 'private_message__' . $vars['elements']['#view_mode']; } + +/** + * Implements hook_entity_query_ENTITY_TYPE_alter(). + */ +function private_message_entity_query_user_alter(QueryInterface $query): void { + if (!$handler = $query->getMetadata('entity_reference_selection_handler')) { + return; + } + if (!$handler instanceof UserSelection) { + return; + } + + // Filter out blocked users. + $config = $handler->getConfiguration(); + if (empty($config['private_message']['active_users_selection'])) { + return; + } + + $roles = array_filter( + \Drupal::entityTypeManager()->getStorage('user_role')->loadMultiple(), + fn(RoleInterface $role): bool => $role->hasPermission('use private messaging system'), + ); + + if (!$rids = array_keys($roles)) { + // Provide condition which will not return any results. + $query->condition('uid'); + return; + } + + $current_user_id = \Drupal::currentUser()->id(); + $subquery = \Drupal::database()->select('private_message_ban', 'pmb') + ->fields('pmb', ['target']); + $subquery->condition('owner', $current_user_id); + + $query->condition('uid', $subquery, 'NOT IN'); + if (!in_array('authenticated', $rids)) { + $query->condition('roles', $rids, 'IN'); + } + + $query->condition('uid', $current_user_id, '<>'); +} + +/** + * Implements hook_config_schema_info_alter(). + */ +function private_message_config_schema_info_alter(array &$definitions): void { + if (isset($definitions['entity_reference_selection.default:user'])) { + // Required to pass config_inspector validation. + $definitions['entity_reference_selection.default:user']['mapping']['private_message'] = [ + 'active_users_selection' => [ + 'type' => 'boolean', + 'label' => 'Whether to filter out blocked user on member selection widget', + ], + ]; + } +} diff --git a/src/Form/BanUserForm.php b/src/Form/BanUserForm.php index b73c88cedaa36101bdd772b4d16edf1543464577..a2ba5bda9fbba973924fb18195df4bc54b8ec884 100644 --- a/src/Form/BanUserForm.php +++ b/src/Form/BanUserForm.php @@ -41,9 +41,13 @@ class BanUserForm extends FormBase { '#type' => 'entity_autocomplete', '#target_type' => 'user', '#tags' => FALSE, - '#selection_handler' => 'private_message:not_blocked_user', + '#selection_handler' => 'default:user', '#selection_settings' => [ 'include_anonymous' => FALSE, + // @see \private_message_entity_query_user_alter() + 'private_message' => [ + 'active_users_selection' => TRUE, + ], ], ]; diff --git a/src/Plugin/EntityReferenceSelection/NotBlockedUserSelection.php b/src/Plugin/EntityReferenceSelection/NotBlockedUserSelection.php deleted file mode 100644 index 4f2408304a54fd3505e8a8a21a82312cb6ad529f..0000000000000000000000000000000000000000 --- a/src/Plugin/EntityReferenceSelection/NotBlockedUserSelection.php +++ /dev/null @@ -1,67 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\private_message\Plugin\EntityReferenceSelection; - -use Drupal\Core\Entity\Attribute\EntityReferenceSelection; -use Drupal\Core\Entity\Query\QueryInterface; -use Drupal\Core\StringTranslation\TranslatableMarkup; -use Drupal\user\Plugin\EntityReferenceSelection\UserSelection; -use Drupal\user\RoleInterface; - -/** - * Provides reference selection for not blocked users. - */ -#[EntityReferenceSelection( - id: "private_message:not_blocked_user", - label: new TranslatableMarkup("Not blocked user selection"), - group: "private_message", - weight: 3, - entity_types: ["user"] -)] -class NotBlockedUserSelection extends UserSelection { - - /** - * {@inheritdoc} - */ - protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS'): QueryInterface { - $query = parent::buildEntityQuery($match, $match_operator); - - $rids = $this->getCanUseRids(); - // Provide condition which will not return any results. - if (empty($rids)) { - $query->condition('uid'); - return $query; - } - - $subquery = $this->connection->select('private_message_ban', 'pmb') - ->fields('pmb', ['target']); - $subquery->condition('owner', $this->currentUser->id()); - - $query->condition('uid', $subquery, 'NOT IN'); - if (!in_array('authenticated', $rids)) { - $query->condition('roles', $rids, 'IN'); - } - - $query->condition('uid', $this->currentUser->id(), '<>'); - - return $query; - } - - /** - * Returns role ids with permission to use PM system. - * - * @return int[]|string[] - * Array of role IDs. - */ - protected function getCanUseRids(): array { - $use_pm_permission = 'use private messaging system'; - $roles = array_filter( - $this->entityTypeManager->getStorage('user_role')->loadMultiple(), - fn(RoleInterface $role): bool => $role->hasPermission($use_pm_permission), - ); - return array_keys($roles); - } - -} diff --git a/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php b/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php index c429729e4bba968232ea631d097e3a947d55c7cd..8cfa8272fa141f93d7b86961116cbddd6c270f70 100644 --- a/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php +++ b/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php @@ -124,9 +124,13 @@ class PrivateMessageThreadMemberWidget extends EntityReferenceAutocompleteWidget $element['target_id']['#title'] = $this->t('To'); $element['target_id']['#required'] = TRUE; $element['target_id']['#default_value'] = $items->referencedEntities(); - $element['target_id']['#selection_handler'] = 'private_message:not_blocked_user'; + $element['target_id']['#selection_handler'] = 'default:user'; $element['target_id']['#selection_settings'] = [ 'include_anonymous' => FALSE, + // @see \private_message_entity_query_user_alter() + 'private_message' => [ + 'active_users_selection' => TRUE, + ], ]; $element['target_id']['#validate_reference'] = TRUE;