Commit afe0a66b authored by Yurii Panchuk's avatar Yurii Panchuk Committed by Artem Sylchuk
Browse files

Issue #3050359 by Panchuk, phjou, artem_sylchuk: The number of results of the...

Issue #3050359 by Panchuk, phjou, artem_sylchuk: The number of results of the autocomplete is not configurable
parent 8a9bfa9c
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -82,13 +82,21 @@ private_message.private_message_thread_settings:
    _permission: 'administer private message module'

private_message.members_widget_callback:
  path: '/private-message/autocomplete/members'
  path: '/private-message/autocomplete/members/{target_type}/{selection_handler}/{selection_settings_key}'
  defaults:
    _controller: '\Drupal\private_message\Controller\AjaxController::privateMessageMembersAutocomplete'
  requirements:
    _csrf_token: 'TRUE'
    _user_is_logged_in: 'TRUE'
    _permission: 'use private messaging system,access user profiles'
  options:
    parameters:
      target_type:
        type: string
      selection_handler:
        type: string
      selection_settings_key:
        type: string

private_message.admin_config:
  path: '/admin/config/private-message'
+23 −2
Original line number Diff line number Diff line
@@ -2,12 +2,14 @@

namespace Drupal\private_message\Controller;

use Drupal\Component\Utility\Crypt;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Site\Settings;
use Drupal\private_message\Ajax\PrivateMessageInboxUpdateCommand;
use Drupal\private_message\Ajax\PrivateMessageInsertNewMessagesCommand;
use Drupal\private_message\Ajax\PrivateMessageInboxInsertThreadsCommand;
@@ -20,6 +22,7 @@ use Drupal\private_message\Entity\PrivateMessageThread;
use Drupal\private_message\Service\PrivateMessageServiceInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

/**
 * Controller to handle Ajax requests.
@@ -176,11 +179,29 @@ class AjaxController extends ControllerBase implements AjaxControllerInterface {
  /**
   * {@inheritdoc}
   */
  public function privateMessageMembersAutocomplete() {
  public function privateMessageMembersAutocomplete($target_type, $selection_handler, $selection_settings_key) {
    $response = new AjaxResponse();

    // Selection settings are passed in as a hashed key of a serialized array
    // stored in the key/value store.
    $selection_settings = \Drupal::keyValue('entity_autocomplete')->get($selection_settings_key, FALSE);
    if ($selection_settings !== FALSE) {
      $selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt());
      if (!hash_equals($selection_settings_hash, $selection_settings_key)) {
        // Disallow access when the selection settings hash does not match the
        // passed-in key.
        throw new AccessDeniedHttpException('Invalid selection settings key.');
      }
    }
    else {
      // Disallow access when the selection settings key is not found in the
      // key/value store.
      throw new AccessDeniedHttpException();
    }

    $match_limit = isset($selection_settings['match_limit']) ? (int) $selection_settings['match_limit'] : self::AUTOCOMPLETE_COUNT;
    $username = $this->requestStack->getCurrentRequest()->get('username');
    $accounts = $this->privateMessageService->getUsersFromString($username, self::AUTOCOMPLETE_COUNT);
    $accounts = $this->privateMessageService->getUsersFromString($username, $match_limit);
    $user_info = [];
    foreach ($accounts as $account) {
      if ($account->access('view', $this->currentUser) && $account->isActive()) {
+8 −1
Original line number Diff line number Diff line
@@ -21,9 +21,16 @@ interface AjaxControllerInterface {
  /**
   * Create AJAX response containing usernames for an autocomplete callback.
   *
   * @param $target_type
   *    Target type of autocomplete.
   * @param $selection_handler
   *    Selection handler of autocomplete.
   * @param $selection_settings_key
   *    Key to the hashed settings.
   *
   * @return \Drupal\Core\Ajax\AjaxResponse
   *   The ajax response
   */
  public function privateMessageMembersAutocomplete();
  public function privateMessageMembersAutocomplete($target_type, $selection_handler, $selection_settings_key);

}
+23 −2
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@

namespace Drupal\private_message\Plugin\Field\FieldWidget;

use Drupal\Component\Utility\Crypt;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Access\CsrfTokenGenerator;
use Drupal\Core\Config\ConfigFactoryInterface;
@@ -12,6 +13,7 @@ use Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteWidget
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Site\Settings;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
@@ -166,7 +168,6 @@ class PrivateMessageThreadMemberWidget extends EntityReferenceAutocompleteWidget
    $form = parent::settingsForm($form, $form_state);
    // This setting has no bearing on this widget, so it is removed.
    unset($form['match_operator']);
    unset($form['match_limit']);

    $form['max_members'] = [
      '#type' => 'number',
@@ -211,7 +212,27 @@ class PrivateMessageThreadMemberWidget extends EntityReferenceAutocompleteWidget
    if (!$style_disabled) {
      $element['#attached']['library'][] = 'private_message/members_widget_style';
    }
    $url = Url::fromRoute('private_message.members_widget_callback');

    $target_type = $element['target_id']['#target_type'];
    $selection_handler = $element['target_id']['#selection_handler'];

    // Store the selection settings in the key/value store and pass a hashed key
    // in the route parameters.
    $selection_settings = $element['target_id']['#selection_settings'] ?? [];
    $data = serialize($selection_settings) . $target_type . $selection_handler;
    $selection_settings_key = Crypt::hmacBase64($data, Settings::getHashSalt());

    $key_value_storage = \Drupal::keyValue('entity_autocomplete');
    if (!$key_value_storage->has($selection_settings_key)) {
      $key_value_storage->set($selection_settings_key, $selection_settings);
    }

    $url = Url::fromRoute('private_message.members_widget_callback', [
      'target_type' => $target_type,
      'selection_handler' => $selection_handler,
      'selection_settings_key' => $selection_settings_key,
    ]);

    $token = $this->csrfTokenGenerator->get($url->getInternalPath());
    $url->setOptions(['query' => ['token' => $token]]);