diff --git a/core/modules/user/lib/Drupal/user/UserAutocomplete.php b/core/modules/user/lib/Drupal/user/UserAutocomplete.php new file mode 100644 index 0000000000000000000000000000000000000000..4d36923160a36eea2ef8d926e91eca72cc9d4cab --- /dev/null +++ b/core/modules/user/lib/Drupal/user/UserAutocomplete.php @@ -0,0 +1,77 @@ +<?php + +/** + * @file + * Contains \Drupal\user\UserAutocomplete. + */ + +namespace Drupal\user; + +use Drupal\Core\Config\ConfigFactory; +use Drupal\Core\Database\Connection; + +/** + * Defines a helper class to get user autocompletion results. + */ +class UserAutocomplete { + + /** + * The database connection to query for the user names. + * + * @var \Drupal\Core\Database\Connection + */ + protected $connection; + + /** + * The config factory to get the anonymous user name. + * + * @var \Drupal\Core\Config\ConfigFactory + */ + protected $configFactory; + + /** + * Constructs a UserAutocomplete object. + * + * @param \Drupal\Core\Database\Connection $connection + * The database connection to query for the user names. + * @param \Drupal\Core\Config\ConfigFactory $config_factory + * The config factory. + */ + public function __construct(Connection $connection, ConfigFactory $config_factory) { + $this->connection = $connection; + $this->configFactory = $config_factory; + } + + /** + * Get matches for the autocompletion of user names. + * + * @param string $string + * The string to match for usernames. + * + * @param bool $include_anonymous + * (optional) TRUE if the the name used to indicate anonymous users (e.g. + * "Anonymous") should be autocompleted. Defaults to FALSE. + * + * @return array + * An array containing the matching usernames. + */ + public function getMatches($string, $include_anonymous = FALSE) { + $matches = array(); + if ($string) { + if ($include_anonymous) { + $anonymous_name = $this->configFactory->get('user.settings')->get('anonymous'); + // Allow autocompletion for the anonymous user. + if (stripos($anonymous_name, $string) !== FALSE) { + $matches[$anonymous_name] = check_plain($anonymous_name); + } + } + $result = $this->connection->select('users')->fields('users', array('name'))->condition('name', db_like($string) . '%', 'LIKE')->range(0, 10)->execute(); + foreach ($result as $account) { + $matches[$account->name] = check_plain($account->name); + } + } + + return $matches; + } + +} diff --git a/core/modules/user/lib/Drupal/user/UserAutocompleteController.php b/core/modules/user/lib/Drupal/user/UserAutocompleteController.php new file mode 100644 index 0000000000000000000000000000000000000000..9b668bfd020eecf393a57e708ad84dedeec53ef5 --- /dev/null +++ b/core/modules/user/lib/Drupal/user/UserAutocompleteController.php @@ -0,0 +1,70 @@ +<?php + +/** + * @file + * Contains \Drupal\user\UserAutocompleteController. + */ +namespace Drupal\user; + +use Symfony\Component\HttpFoundation\JsonResponse; +use Symfony\Component\HttpFoundation\Request; + +/** + * Controller routines for taxonomy user routes. + */ +class UserAutocompleteController { + + /** + * The user autocomplete helper class to find matching user names. + * + * @var \Drupal\user\UserAutocomplete + */ + protected $userAutocomplete; + + /** + * Constructs an UserAutocompleteController object. + * + * @param \Drupal\user\UserAutocomplete $user_autocomplete + * The user autocomplete helper class to find matching user names. + */ + public function __construct(UserAutocomplete $user_autocomplete) { + $this->userAutocomplete = $user_autocomplete; + } + + /** + * Returns response for the user autocompletion. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The current request object containing the search string. + * @param bool $include_anonymous + * (optional) TRUE if the the name used to indicate anonymous users (e.g. + * "Anonymous") should be autocompleted. Defaults to FALSE. + * + * @return \Symfony\Component\HttpFoundation\JsonResponse + * A JSON response containing the autocomplete suggestions for existing users. + * + * @see \Drupal\user\UserAutocomplete::getMatches() + */ + public function autocompleteUser(Request $request, $include_anonymous = FALSE) { + $matches = $this->userAutocomplete->getMatches($request->query->get('q'), $include_anonymous); + + return new JsonResponse($matches); + } + + /** + * Returns response for the user autocompletion with the anonymous user. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The current request object containing the search string. + * + * @return \Symfony\Component\HttpFoundation\JsonResponse + * A JSON response containing the autocomplete suggestions for existing users. + * + * @see \Drupal\user\UserRouteController\autocompleteUser + */ + public function autocompleteUserAnonymous(Request $request) { + return $this->autocompleteUser($request, TRUE); + } + +} + diff --git a/core/modules/user/lib/Drupal/user/UserBundle.php b/core/modules/user/lib/Drupal/user/UserBundle.php index a4e7d8d01b29403d2fe5694ab073ab44b23813a6..cf2f7de1e43f027e168b75b917085bfd3e794755 100644 --- a/core/modules/user/lib/Drupal/user/UserBundle.php +++ b/core/modules/user/lib/Drupal/user/UserBundle.php @@ -25,5 +25,10 @@ public function build(ContainerBuilder $container) { $container ->register('user.data', 'Drupal\user\UserData') ->addArgument(new Reference('database')); + $container->register('user.autocomplete_controller', 'Drupal\user\UserAutocompleteController') + ->addArgument(new Reference('user.autocomplete')); + $container->register('user.autocomplete', 'Drupal\user\UserAutocomplete') + ->addArgument(new Reference('database')) + ->addArgument(new Reference('config.factory')); } } diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 86623eb25de97503ae74e31952205682b720e2b5..19dc974609e12eb21a57217773224a60f8af8a15 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -865,9 +865,12 @@ function user_register_access() { * Implements hook_menu(). */ function user_menu() { + // @todo Remove once drupal_valid_path() is fixed to find and access check + // paths managed by the new routing system: http://drupal.org/node/1793520. $items['user/autocomplete'] = array( 'title' => 'User autocomplete', - 'page callback' => 'user_autocomplete', + // _menu_router_build() denies access to paths without a page callback. + 'page callback' => 'NOT_USED', 'access callback' => 'user_access', 'access arguments' => array('access user profiles'), 'type' => MENU_CALLBACK, @@ -876,13 +879,15 @@ function user_menu() { $items['user/autocomplete/anonymous'] = array( 'title' => 'User autocomplete including anonymous', - 'page callback' => 'user_autocomplete', + // _menu_router_build() denies access to paths without a page callback. + 'page callback' => 'NOT_USED', 'page arguments' => array(TRUE), 'access callback' => 'user_access', 'access arguments' => array('access user profiles'), 'type' => MENU_CALLBACK, 'file' => 'user.pages.inc', ); + // Registration and login pages. $items['user'] = array( 'title' => 'User account', diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc index 5a872ab2f65c3c07445dff70585a62408bfa84d8..655931393121247f0abb7cb3e509d906e170a771 100644 --- a/core/modules/user/user.pages.inc +++ b/core/modules/user/user.pages.inc @@ -11,39 +11,6 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\HttpKernelInterface; -/** - * Menu callback for user autocompletion. - * - * Like other autocomplete functions, this function inspects the 'q' query - * parameter for the string to use to search for suggestions. - * - * @param bool $include_anonymous - * (optional) TRUE if the the name used to indicate anonymous users (e.g. - * "Anonymous") should be autocompleted. Defaults to FALSE. - * - * @return \Symfony\Component\HttpFoundation\JsonResponse - * A JSON response containing the autocomplete suggestions for existing users. - */ -function user_autocomplete($include_anonymous = FALSE) { - $matches = array(); - $query = drupal_container()->get('request')->query; - if ($string = $query->get('q')) { - if ($include_anonymous) { - $anonymous_name = config('user.settings')->get('anonymous'); - // Allow autocompletion for the anonymous user. - if (stripos($anonymous_name, $string) !== FALSE) { - $matches[$anonymous_name] = check_plain($anonymous_name); - } - } - $result = db_select('users')->fields('users', array('name'))->condition('name', db_like($string) . '%', 'LIKE')->range(0, 10)->execute(); - foreach ($result as $account) { - $matches[$account->name] = check_plain($account->name); - } - } - - return new JsonResponse($matches); -} - /** * Form builder; Request a password reset. * diff --git a/core/modules/user/user.routing.yml b/core/modules/user/user.routing.yml index c3a05d74f2805ebc297980a425373ab2c365e3f1..ad70759b50509453e33d8e4d2fe264fcab57d626 100644 --- a/core/modules/user/user.routing.yml +++ b/core/modules/user/user.routing.yml @@ -4,3 +4,17 @@ user_register: _content: '\Drupal\user\UserRouteController::register' requirements: _access_user_register: 'TRUE' + +user_autocomplete: + pattern: '/user/autocomplete' + defaults: + _controller: 'user.autocomplete_controller:autocompleteUser' + requirements: + _permission: 'access user profiles' + +user_autocomplete_anonymous: + pattern: '/user/autocomplete/anonymous' + defaults: + _controller: 'user.autocomplete_controller:autocompleteUserAnonymous' + requirements: + _permission: 'access user profiles'