From b523586c88ae750d28cbced7888df01a15e89bcc Mon Sep 17 00:00:00 2001 From: Claudiu Cristea <clau.cristea@gmail.com> Date: Tue, 21 Jan 2025 18:56:52 +0200 Subject: [PATCH 1/3] Use default:selection handler --- private_message.module | 46 +++++++++++++ src/Form/BanUserForm.php | 3 +- .../NotBlockedUserSelection.php | 67 ------------------- .../PrivateMessageThreadMemberWidget.php | 3 +- 4 files changed, 50 insertions(+), 69 deletions(-) delete mode 100644 src/Plugin/EntityReferenceSelection/NotBlockedUserSelection.php diff --git a/private_message.module b/private_message.module index 26f2452c..856a2d6c 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,46 @@ 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_query_TAG_alter(). + */ +function private_message_query_entity_reference_alter(QueryInterface $query): void { + if (!$handler = $query->getMetadata('entity_reference_selection_handler')) { + return; + } + assert($handler instanceof UserSelection); + + $config = $handler->getConfiguration(); + // Filter out blocked users. + if (!empty($config['private_message:not_blocked_user'])) { + $use_pm_permission = 'use private messaging system'; + $roles = array_filter( + \Drupal::entityTypeManager()->getStorage('user_role')->loadMultiple(), + fn(RoleInterface $role): bool => $role->hasPermission($use_pm_permission), + ); + + 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, '<>'); + + // Cleanup custom configuration. + unset($config['private_message:not_blocked_user']); + $handler->setConfiguration($config); + } +} diff --git a/src/Form/BanUserForm.php b/src/Form/BanUserForm.php index b73c88ce..75462fc5 100644 --- a/src/Form/BanUserForm.php +++ b/src/Form/BanUserForm.php @@ -41,9 +41,10 @@ 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, + 'private_message:not_blocked_user' => TRUE, ], ]; diff --git a/src/Plugin/EntityReferenceSelection/NotBlockedUserSelection.php b/src/Plugin/EntityReferenceSelection/NotBlockedUserSelection.php deleted file mode 100644 index 4f240830..00000000 --- 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 c429729e..a7c188c3 100644 --- a/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php +++ b/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php @@ -124,9 +124,10 @@ 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, + 'private_message:not_blocked_user' => TRUE, ]; $element['target_id']['#validate_reference'] = TRUE; -- GitLab From 975fd4581438f9cca94c0b4afcebdb6283b5b7a8 Mon Sep 17 00:00:00 2001 From: Claudiu Cristea <clau.cristea@gmail.com> Date: Tue, 21 Jan 2025 20:20:55 +0200 Subject: [PATCH 2/3] Use entity query --- private_message.module | 58 ++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/private_message.module b/private_message.module index 856a2d6c..b030bead 100644 --- a/private_message.module +++ b/private_message.module @@ -696,44 +696,46 @@ function private_message_theme_suggestions_private_message_alter(array &$suggest } /** - * Implements hook_query_TAG_alter(). + * Implements hook_entity_query_ENTITY_TYPE_alter(). */ -function private_message_query_entity_reference_alter(QueryInterface $query): void { +function private_message_entity_query_user_alter(QueryInterface $query): void { if (!$handler = $query->getMetadata('entity_reference_selection_handler')) { return; } - assert($handler instanceof UserSelection); + if (!$handler instanceof UserSelection) { + return; + } - $config = $handler->getConfiguration(); // Filter out blocked users. - if (!empty($config['private_message:not_blocked_user'])) { - $use_pm_permission = 'use private messaging system'; - $roles = array_filter( - \Drupal::entityTypeManager()->getStorage('user_role')->loadMultiple(), - fn(RoleInterface $role): bool => $role->hasPermission($use_pm_permission), - ); - - if (!$rids = array_keys($roles)) { - // Provide condition which will not return any results. - $query->condition('uid'); - return; + $config = $handler->getConfiguration(); + if (empty($config['private_message:not_blocked_user'])) { + return; + } - } + // Cleanup custom configuration. + unset($config['private_message:not_blocked_user']); + $handler->setConfiguration($config); - $current_user_id = \Drupal::currentUser()->id(); - $subquery = \Drupal::database()->select('private_message_ban', 'pmb') - ->fields('pmb', ['target']); - $subquery->condition('owner', $current_user_id); + $roles = array_filter( + \Drupal::entityTypeManager()->getStorage('user_role')->loadMultiple(), + fn(RoleInterface $role): bool => $role->hasPermission('use private messaging system'), + ); - $query->condition('uid', $subquery, 'NOT IN'); - if (!in_array('authenticated', $rids)) { - $query->condition('roles', $rids, 'IN'); - } + if (!$rids = array_keys($roles)) { + // Provide condition which will not return any results. + $query->condition('uid'); + return; + } - $query->condition('uid', $current_user_id, '<>'); + $current_user_id = \Drupal::currentUser()->id(); + $subquery = \Drupal::database()->select('private_message_ban', 'pmb') + ->fields('pmb', ['target']); + $subquery->condition('owner', $current_user_id); - // Cleanup custom configuration. - unset($config['private_message:not_blocked_user']); - $handler->setConfiguration($config); + $query->condition('uid', $subquery, 'NOT IN'); + if (!in_array('authenticated', $rids)) { + $query->condition('roles', $rids, 'IN'); } + + $query->condition('uid', $current_user_id, '<>'); } -- GitLab From 52d7bbb057e21fb1d1d5a7f0dd035b99d8c54663 Mon Sep 17 00:00:00 2001 From: Claudiu Cristea <clau.cristea@gmail.com> Date: Thu, 23 Jan 2025 11:51:52 +0200 Subject: [PATCH 3/3] Honour config schema --- private_message.module | 21 ++++++++++++++----- src/Form/BanUserForm.php | 5 ++++- .../PrivateMessageThreadMemberWidget.php | 5 ++++- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/private_message.module b/private_message.module index b030bead..0ff0ffab 100644 --- a/private_message.module +++ b/private_message.module @@ -708,14 +708,10 @@ function private_message_entity_query_user_alter(QueryInterface $query): void { // Filter out blocked users. $config = $handler->getConfiguration(); - if (empty($config['private_message:not_blocked_user'])) { + if (empty($config['private_message']['active_users_selection'])) { return; } - // Cleanup custom configuration. - unset($config['private_message:not_blocked_user']); - $handler->setConfiguration($config); - $roles = array_filter( \Drupal::entityTypeManager()->getStorage('user_role')->loadMultiple(), fn(RoleInterface $role): bool => $role->hasPermission('use private messaging system'), @@ -739,3 +735,18 @@ function private_message_entity_query_user_alter(QueryInterface $query): void { $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 75462fc5..a2ba5bda 100644 --- a/src/Form/BanUserForm.php +++ b/src/Form/BanUserForm.php @@ -44,7 +44,10 @@ class BanUserForm extends FormBase { '#selection_handler' => 'default:user', '#selection_settings' => [ 'include_anonymous' => FALSE, - 'private_message:not_blocked_user' => TRUE, + // @see \private_message_entity_query_user_alter() + 'private_message' => [ + 'active_users_selection' => TRUE, + ], ], ]; diff --git a/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php b/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php index a7c188c3..8cfa8272 100644 --- a/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php +++ b/src/Plugin/Field/FieldWidget/PrivateMessageThreadMemberWidget.php @@ -127,7 +127,10 @@ class PrivateMessageThreadMemberWidget extends EntityReferenceAutocompleteWidget $element['target_id']['#selection_handler'] = 'default:user'; $element['target_id']['#selection_settings'] = [ 'include_anonymous' => FALSE, - 'private_message:not_blocked_user' => TRUE, + // @see \private_message_entity_query_user_alter() + 'private_message' => [ + 'active_users_selection' => TRUE, + ], ]; $element['target_id']['#validate_reference'] = TRUE; -- GitLab