Updated: Comment #19

Problem/Motivation

menu_get_item() is broken for routes that were formerly MENU_CALLBACK.
This prevents drupal_valid_path() from working, which in turn prevents form_process_autocomplete() from working.

Steps to reproduce:

Go to node/add/page
Expand the "Authoring Information" details element
Attempt to change the user

Expected:
A throbber appears before typing, is activated while typing, and what you type is autocompleted.
Actual:
Nothing.

Proposed resolution

While menu_get_item() needs to be fixed, we should also be moving away from path-bound autocomplete.
This adds #autocomplete_route, which takes a route name instead.

Developers should use #autocomplete_route going forward instead of #autocomplete_path.

Remaining tasks

  • Write tests
  • Write documentation
  • Write change notice

User interface changes

N/A (other than fixed regression)

API changes

API addition of #autocomplete_route, #autocomplete_path is left for hook_menu() page callbacks.

N/A

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tim.plunkett’s picture

Status: Active » Needs review
FileSize
5.09 KB
pwolanin’s picture

We should at least have a @todo to replace menu_item_route_access() with the new method at #2046737: Add a method to the AccessManager that only needs a route name and parameters

Status: Needs review » Needs work

The last submitted patch, autocomplete-2056627-1.patch, failed testing.

tim.plunkett’s picture

This needs to support parameters too (taxonomy autocomplete will need to pass the vocab), so maybe this should just wait on #2046737: Add a method to the AccessManager that only needs a route name and parameters

(that was a random fail)

dawehner’s picture

@@ -4087,7 +4087,14 @@ function theme_vertical_tabs($variables) {
+  if (!empty($element['#autocomplete_route'])) {
+    $route = Drupal::service('router.route_provider')->getRouteByName($element['#autocomplete_route']);
+    $element['#autocomplete_path'] = trim($route->getPath(), '/');
+    $map = array();

Yeah you don't want to use the router provider by the url generator and pass in the route name and paramters.

tim.plunkett’s picture

Assigned: Unassigned » tim.plunkett
Status: Needs work » Postponed

Well we still need that to check access. We'll see what it looks like after the AccessManager issue.

tim.plunkett’s picture

Status: Postponed » Needs work

Blocker was in. Will revisit this soon.

dawehner’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
11.1 KB

Working on the patch 10mins, getting the tests right: 30 minutes. Good night!

I have chosen to use route_name to just tell people that it is the name.
This for sure needs some documentation, though it is seriously too late now.

dawehner’s picture

Working on the patch 10mins, getting the tests right: 30 minutes. Good night!

I have chosen to use route_name to just tell people that it is the name.
This for sure needs some documentation, though it is seriously too late now.

tim.plunkett’s picture

  1. +++ b/core/includes/form.inc
    @@ -4087,7 +4087,18 @@ function theme_vertical_tabs($variables) {
    +  $access = FALSE;
    +  if (!empty($element['#autocomplete_route_name'])) {
    +    $route_name = $element['#autocomplete_route_name'];
    +    $parameters = isset($element['#autocomplete_route_parameters']) ? $element['#autocomplete_route_parameters'] : array();
    +
    +    $access = Drupal::service('access_manager')->checkNamedRoute($route_name, $parameters);
    +    $path = Drupal::urlGenerator()->generate($route_name, $parameters);
    +  }
    +  else {
    +    $path = url($element['#autocomplete_path'], array('absolute' => TRUE));
    +  }
    +  if ($access || !empty($element['#autocomplete_path']) && drupal_valid_path($element['#autocomplete_path'])) {
    

    I was trying to minimize code changes here, but I think this is awkward. We should just move the drupal_valid_path() into the else {} part.

  2. +++ b/core/modules/system/lib/Drupal/system/Tests/Form/ElementTest.php
    @@ -126,4 +126,29 @@ function testGroupElements() {
       }
    +
    +
    +  /**
    +   * Tests a form with a autocomplete setting..
    

    Double blank line. Nice test though!

  3. +++ b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/AutocompleteController.php
    @@ -0,0 +1,16 @@
    +  /**
    +   * Returns
    +   */
    +
    +} ¶
    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
    

    A bit strange :)

  4. +++ b/core/modules/system/tests/modules/form_test/lib/Drupal/form_test/FormTestAutocompleteForm.php
    @@ -0,0 +1,55 @@
    +  }
    +
    +} ¶
    

    Trailing whitespace

mradcliffe’s picture

Postgresql catches this hard as user entity tries to load the uid 'autocomplete', which fails strict typing. Mysql driver probably ignores or munges the data.

Status: Needs review » Needs work

The last submitted patch, autocomplete-2056627-8.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
FileSize
11.45 KB

Thank you for the review!

Status: Needs review » Needs work

The last submitted patch, autocomplete-2056627-13.patch, failed testing.

tim.plunkett’s picture

Assigned: tim.plunkett » Unassigned
Status: Needs work » Needs review
Issue tags: +Needs tests
FileSize
3 KB
12.46 KB

Fixed some docs and coding style, #2062745: Automatically set the request context on the url generator fixed the bugs.

We should have regression testing for the author autocomplete on the node form.

dawehner’s picture

Here is a test for the author form. Yes we could invent even more tests for every damn place a user auto-completion appears but I don't think we need that as we test the same functionality all over again.

dawehner’s picture

A general question is whether we want to support the new routing system in drupal_valid_url, see https://drupal.org/node/876580 for a rough comment.

mradcliffe’s picture

+++ b/core/includes/form.incundefined
+++ b/core/includes/form.incundefined
@@ -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.

Just a note: It may be nice for new developers to point out why one would use path or route. I think this could be done initially in a change notice and in handbook documentation.

dawehner’s picture

On the longrun you should never use autocomplete_path, that is just in there as long we haven't converted all autocompletions.

effulgentsia’s picture

Title: Form API autocomplete is broken for routes » Regression: Form API autocomplete is broken for routes
Priority: Major » Critical
Issue tags: +API change, +D8 upgrade path

I think this approach makes sense, but I'm not crazy about:

#autocomplete_path is left for hook_menu() page callbacks

I'd rather see this issue remove it, so that entity_reference module can be updated to use #autocomplete_route in all cases. Tagging for upgrade path because of that. Looks like #1987858: Convert taxonomy_autocomplete() to a new style controller is close to done. Can we focus on getting that in quickly, and then do the full conversion of #autocomplete_* here?

effulgentsia’s picture

Issue tags: +Approved API change

@alexpott approves, since this is a critical fallout of router conversion.

tim.plunkett’s picture

If we convert the taxonomy autocomplete before this goes in, then it too will be broken...
If that is the last usage of #autocomplete_path, why not put this in now, and then remove #autocomplete_path over there.

dawehner’s picture

Issue tags: -Needs tests

I agree. There is neither a fundamental problem nor actually a lot of work if we keep autocomplete_path in for now. This seems really like overthinking ;)

Remove wrong tag.

tim.plunkett’s picture

I posted too many patches to RTBC, but the test looks great!

ParisLiakos’s picture

Status: Needs review » Reviewed & tested by the community

looks great

effulgentsia’s picture

Status: Reviewed & tested by the community » Needs work

If that is the last usage of #autocomplete_path, why not put this in now, and then remove #autocomplete_path over there.

Well, per #20, putting this in now only fixes the user autocompletes that the patch touches, and leaves ER fields targeting users still using the broken #autocomplete_path. But I guess that's not a further regression, just a very incomplete fix. So ok, let's do this one first. As long as we recognize that this is in fact an API change, not merely an addition, because the retaining of #autocomplete_path is just an artifact of patch order, not something that's releasable.

+++ b/core/includes/form.inc
@@ -4078,16 +4078,42 @@ function theme_vertical_tabs($variables) {
+    $path = Drupal::urlGenerator()->generate($element['#autocomplete_route_name'], $parameters);
...
+++ b/core/includes/form.inc
@@ -4078,16 +4078,42 @@ function theme_vertical_tabs($variables) {
+    $path = url($element['#autocomplete_path'], array('absolute' => TRUE));

I don't know why we need the second one to be an absolute URL, but I think that's been that way in HEAD since autocomplete functionality was first added to Drupal. Given that, we should probably be consistent and make the new way also output absolute URLs.

effulgentsia’s picture

Status: Needs work » Reviewed & tested by the community

#26 was an xpost with #25. I'm ok with it being a follow up though, so back to RTBC.

catch’s picture

Title: Regression: Form API autocomplete is broken for routes » Change notice: Form API autocomplete is broken for routes
Status: Reviewed & tested by the community » Active
Issue tags: +Needs change record

Committed/pushed to 8.x, thanks!

Will need a change notice.

catch’s picture

Category: bug » task
dawehner’s picture

Status: Active » Needs review
tim.plunkett’s picture

Title: Change notice: Form API autocomplete is broken for routes » Form API autocomplete is broken for routes
Category: task » bug
Status: Needs review » Fixed
Issue tags: -Needs change record
jibran’s picture

dawehner’s picture

Good addition tim!

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Issue summary: View changes

Updated issue summary as of comment #19

cilefen’s picture