diff --git a/core/includes/form.inc b/core/includes/form.inc index c793f11338637f840be2a345e0326ff17d2087b3..8aee8f02e51a6afcd9f5044e9ed9c9cf775f86f2 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -4078,16 +4078,42 @@ function theme_vertical_tabs($variables) { * @code * '#autocomplete_path' => 'mymodule_autocomplete/' . $some_key . '/' . $some_id, * @endcode + * Or if your route is called 'mymodule_autocomplete' with the path of + * '/mymodule-autocomplete/{a}/{b}': + * @code + * '#autocomplete_route_name' => 'mymodule_autocomplete', + * '#autocomplete_route_parameters' => array('a' => $some_key, 'b' => $some_id), + * @endcode * The user types in "keywords" so the full path called is: * 'mymodule_autocomplete/$some_key/$some_id?q=keywords' * - * @param $element + * @param array $element * The form element to process. Properties used: * - #autocomplete_path: A system path to be used as callback URL by the * autocomplete JavaScript library. + * - #autocomplete_route_name: A route to be used as callback URL by the + * autocomplete JavaScript library. + * - #autocomplete_route_parameters: The parameters to be used in conjunction + * with the route name. + * @param array $form_state + * An associative array containing the current state of the form. + * + * @return array + * The form element. */ function form_process_autocomplete($element, &$form_state) { - if (!empty($element['#autocomplete_path']) && drupal_valid_path($element['#autocomplete_path'])) { + $access = FALSE; + if (!empty($element['#autocomplete_route_name'])) { + $parameters = isset($element['#autocomplete_route_parameters']) ? $element['#autocomplete_route_parameters'] : array(); + + $path = Drupal::urlGenerator()->generate($element['#autocomplete_route_name'], $parameters); + $access = Drupal::service('access_manager')->checkNamedRoute($element['#autocomplete_route_name'], $parameters); + } + elseif (!empty($element['#autocomplete_path'])) { + $path = url($element['#autocomplete_path'], array('absolute' => TRUE)); + $access = drupal_valid_path($element['#autocomplete_path']); + } + if ($access) { $element['#attributes']['class'][] = 'form-autocomplete'; $element['#attached']['library'][] = array('system', 'drupal.autocomplete'); // Provide a hidden element for the JavaScript behavior to bind to. Since @@ -4097,7 +4123,7 @@ function form_process_autocomplete($element, &$form_state) { $element['autocomplete'] = array( '#type' => 'hidden', '#input' => FALSE, - '#value' => url($element['#autocomplete_path'], array('absolute' => TRUE)), + '#value' => $path, '#disabled' => TRUE, '#attributes' => array( 'class' => array('autocomplete'), diff --git a/core/modules/comment/lib/Drupal/comment/CommentFormController.php b/core/modules/comment/lib/Drupal/comment/CommentFormController.php index 3cef2ff757750882cba244883622aafad93db779..ad4b9a007f793fb9b5f8dba817d08cf3a093ccde 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentFormController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentFormController.php @@ -87,7 +87,7 @@ public function form(array $form, array &$form_state) { if ($is_admin) { $form['author']['name']['#title'] = t('Authored by'); $form['author']['name']['#description'] = t('Leave blank for %anonymous.', array('%anonymous' => \Drupal::config('user.settings')->get('anonymous'))); - $form['author']['name']['#autocomplete_path'] = 'user/autocomplete'; + $form['author']['name']['#autocomplete_route_name'] = 'user_autocomplete'; } elseif ($user->isAuthenticated()) { $form['author']['name']['#type'] = 'item'; diff --git a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php index 08cc6932dda77c9f353600b89831c198fae27fb2..3374ddfe622495115e995d93ba2770b18eec516c 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php @@ -274,7 +274,7 @@ public function entityFormAlter(array &$form, array &$form_state, EntityInterfac '#type' => 'textfield', '#title' => t('Authored by'), '#maxlength' => 60, - '#autocomplete_path' => 'user/autocomplete', + '#autocomplete_route_name' => 'user_autocomplete', '#default_value' => $name, '#description' => t('Leave blank for %anonymous.', array('%anonymous' => variable_get('anonymous', t('Anonymous')))), ); diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php index 045f1d97a8c0612cefdc9e09131b03768ca5c0ff..08f54d1595680023531f4178df150384a7c704b7 100644 --- a/core/modules/node/lib/Drupal/node/NodeFormController.php +++ b/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -190,7 +190,7 @@ public function form(array $form, array &$form_state) { '#type' => 'textfield', '#title' => t('Authored by'), '#maxlength' => 60, - '#autocomplete_path' => 'user/autocomplete', + '#autocomplete_route_name' => 'user_autocomplete', '#default_value' => !empty($node->name) ? $node->name : '', '#weight' => -1, '#description' => t('Leave blank for %anonymous.', array('%anonymous' => $user_config->get('anonymous'))), diff --git a/core/modules/node/lib/Drupal/node/Plugin/Action/AssignOwnerNode.php b/core/modules/node/lib/Drupal/node/Plugin/Action/AssignOwnerNode.php index 59255e260abb54860ff398305c46cb8093cf8a8c..7a2753cd3c68019e9068cd11336e3aafdd0fca56 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/Action/AssignOwnerNode.php +++ b/core/modules/node/lib/Drupal/node/Plugin/Action/AssignOwnerNode.php @@ -107,7 +107,7 @@ public function buildConfigurationForm(array $form, array &$form_state) { '#type' => 'textfield', '#title' => t('Username'), '#default_value' => $owner_name, - '#autocomplete_path' => 'user/autocomplete', + '#autocomplete_route_name' => 'user_autocomplete', '#size' => '6', '#maxlength' => '60', '#description' => $description, diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeCreationTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeCreationTest.php index cd5d89ffc6c954c8f465e681d533e0a854001f6b..09e78a28e39af3853bbd5741649d1d11d71b8513 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeCreationTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeCreationTest.php @@ -123,4 +123,26 @@ function testUnpublishedNodeCreation() { $this->assertRaw(t('!post %title has been created.', array('!post' => 'Basic page', '%title' => $edit["title"]))); } + /** + * Tests the author autocompletion textfield. + */ + public function testAuthorAutocomplete() { + $admin_user = $this->drupalCreateUser(array('administer nodes', 'create page content')); + $this->drupalLogin($admin_user); + + $this->drupalGet('node/add/page'); + + $result = $this->xpath('//input[@id = "edit-name-autocomplete"]'); + $this->assertEqual(count($result), 0, 'No autocompletion without access user profiles.'); + + $admin_user = $this->drupalCreateUser(array('administer nodes', 'create page content', 'access user profiles')); + $this->drupalLogin($admin_user); + + $this->drupalGet('node/add/page'); + + $result = $this->xpath('//input[@id = "edit-name-autocomplete"]'); + $this->assertEqual((string) $result[0]['value'], url('user/autocomplete')); + $this->assertEqual(count($result), 1, 'Ensure that the user does have access to the autocompletion'); + } + } diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php index e3521ccf6a4edace0a0115917577b35faf9d394c..be13136edbc0ee3e10e2db82ab9df39bd6d2c555 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php @@ -126,4 +126,28 @@ function testGroupElements() { $elements = $this->xpath('//div[@class="vertical-tabs-panes"]//details[@id="edit-meta-2"]//label'); $this->assertTrue(count($elements) == 1); } + + /** + * Tests a form with a autocomplete setting.. + */ + public function testFormAutocomplete() { + $this->drupalGet('form-test/autocomplete'); + + $result = $this->xpath('//input[@id = "edit-autocomplete-1-autocomplete"]'); + $this->assertEqual(count($result), 0, 'Ensure that the user does not have access to the autocompletion'); + $result = $this->xpath('//input[@id = "edit-autocomplete-2-autocomplete"]'); + $this->assertEqual(count($result), 0, 'Ensure that the user did not had access to the autocompletion'); + + $user = $this->drupalCreateUser(array('access autocomplete test')); + $this->drupalLogin($user); + $this->drupalGet('form-test/autocomplete'); + + $result = $this->xpath('//input[@id = "edit-autocomplete-1-autocomplete"]'); + $this->assertEqual((string) $result[0]['value'], url('form-test/autocomplete-1')); + $this->assertEqual(count($result), 1, 'Ensure that the user does have access to the autocompletion'); + $result = $this->xpath('//input[@id = "edit-autocomplete-2-autocomplete"]'); + $this->assertEqual((string) $result[0]['value'], url('form-test/autocomplete-2/value')); + $this->assertEqual(count($result), 1, 'Ensure that the user does have access to the autocompletion'); + } + } diff --git a/core/modules/system/tests/modules/form_test/form_test.module b/core/modules/system/tests/modules/form_test/form_test.module index 762d7fcf5f363393423cd503aa0b4c19ed00f547..fa16bf9046e34a94f939b02fded2381cdc9fdf9b 100644 --- a/core/modules/system/tests/modules/form_test/form_test.module +++ b/core/modules/system/tests/modules/form_test/form_test.module @@ -376,6 +376,9 @@ function form_test_permission() { 'access vertical_tab_test tabs' => array( 'title' => t('Access vertical_tab_test tabs'), ), + 'access autocomplete test' => array( + 'title' => t('Access autocomplete test'), + ), ); return $perms; } diff --git a/core/modules/system/tests/modules/form_test/form_test.routing.yml b/core/modules/system/tests/modules/form_test/form_test.routing.yml index 00915616d6d4b50f5868a57d2ecc8ade5fb250f4..34e437d4ebee3eb497136e1fb99a202cb47373e1 100644 --- a/core/modules/system/tests/modules/form_test/form_test.routing.yml +++ b/core/modules/system/tests/modules/form_test/form_test.routing.yml @@ -46,3 +46,24 @@ form_test.route7: _form: '\Drupal\form_test\ConfirmFormArrayPathTestForm' requirements: _access: 'TRUE' + +form_test.route8: + pattern: '/form-test/autocomplete' + defaults: + _form: '\Drupal\form_test\FormTestAutocompleteForm' + requirements: + _access: 'TRUE' + +form_test.autocomplete_1: + pattern: '/form-test/autocomplete-1' + defaults: + controller: '\Drupal\form_test\AutocompleteController::autocomplete1' + requirements: + _permission: 'access autocomplete test' + +form_test.autocomplete_2: + pattern: '/form-test/autocomplete-2/{param}' + defaults: + controller: '\Drupal\form_test\AutocompleteController::autocomplete1' + requirements: + _permission: 'access autocomplete test' diff --git a/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/AutocompleteController.php b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/AutocompleteController.php new file mode 100644 index 0000000000000000000000000000000000000000..203f40f64f0574859e30388561ac34b29a991387 --- /dev/null +++ b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/AutocompleteController.php @@ -0,0 +1,27 @@ +<?php + +/** + * @file + * Contains \Drupal\form_test\AutocompleteController. + */ + +namespace Drupal\form_test; + +use Symfony\Component\HttpFoundation\JsonResponse; + +/** + * Defines a controller class with methods for autocompletion. + */ +class AutocompleteController { + + /** + * Returns some autocompletion content. + * + * @return \Symfony\Component\HttpFoundation\JsonResponse + * A JSON response. + */ + public function autocomplete1() { + return new JsonResponse(array('key' => 'value')); + } + +} diff --git a/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/FormTestAutocompleteForm.php b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/FormTestAutocompleteForm.php new file mode 100644 index 0000000000000000000000000000000000000000..fb38218b6565378ed9eac9fc15432169ef3ef7d9 --- /dev/null +++ b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/FormTestAutocompleteForm.php @@ -0,0 +1,55 @@ +<?php + +/** + * @file + * Contains \Drupal\form_test\FormTestAutocompleteForm. + */ + +namespace Drupal\form_test; + +use Drupal\Core\Form\FormInterface; + +/** + * Defines a test form using autocomplete textfields. + */ +class FormTestAutocompleteForm implements FormInterface { + + /** + * {@inheritdoc} + */ + public function getFormID() { + return 'form_test_autocomplete'; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, array &$form_state) { + $form['autocomplete_1'] = array( + '#type' => 'textfield', + '#title' => 'Autocomplete 1', + '#autocomplete_route_name' => 'form_test.autocomplete_1', + ); + $form['autocomplete_2'] = array( + '#type' => 'textfield', + '#title' => 'Autocomplete 2', + '#autocomplete_route_name' => 'form_test.autocomplete_2', + '#autocomplete_route_parameters' => array('param' => 'value'), + ); + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, array &$form_state) { + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, array &$form_state) { + } + +} diff --git a/core/modules/user/lib/Drupal/user/Plugin/views/filter/Name.php b/core/modules/user/lib/Drupal/user/Plugin/views/filter/Name.php index 3742917c8c5b6a9029815f946248aa97d411e754..0f633a67391201aa570070c691db801a1287cb07 100644 --- a/core/modules/user/lib/Drupal/user/Plugin/views/filter/Name.php +++ b/core/modules/user/lib/Drupal/user/Plugin/views/filter/Name.php @@ -42,7 +42,7 @@ protected function valueForm(&$form, &$form_state) { '#title' => t('Usernames'), '#description' => t('Enter a comma separated list of user names.'), '#default_value' => $default_value, - '#autocomplete_path' => 'user/autocomplete/anonymous', + '#autocomplete_route_name' => 'user_autocomplete_anonymous', ); if (!empty($form_state['exposed']) && !isset($form_state['input'][$this->options['expose']['identifier']])) {