Problem/Motivation

As link widget for internal links allows to have entity reference autocomplete, it would be nice to have opportunity to select the reference method the same way as it is possible for entity reference field. This way it would be possible to easily find content that is needed using, for example, views entity reference handler.

We can also add the same settings available to the default entity reference widget that allow for customization of how matches are queried and the number of matches returned.

Steps to reproduce

Standard Drupal installation, article content type, add link field allowing both internal and external links or only internal.

Proposed resolution

Add handler and handler_settings field settings to the LinkItem field type.

Add match_operator and match_limit settings to the LinkWidget.

Remaining tasks

Usability review

User interface changes

Field settings for link field type would have "Reference method" setting, the same as entity reference field.

Before:
The link field settings form before applying the merge request

After:
The link field settings form after applying the merge request showing the addition of the reference method settings

Link widget settings will allow setting the "Autocomplete matching" and "Number of Results".

Before:
The link widget settings form before applying the merge request

After:
The link widget settings form after applying the merge request showing the addition of the autocomplete matching and number of results settings

API changes

None

Data model changes

None

Release notes snippet

Issue fork drupal-3373258

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

a.dmitriiev created an issue. See original summary.

a.dmitriiev’s picture

StatusFileSize
new19.54 KB

Attaching the first patch. It is mostly the copy from EntityReferenceItem class

a.dmitriiev’s picture

Status: Active » Needs review
a.dmitriiev’s picture

StatusFileSize
new20.29 KB

Forgot config schema changes.

a.dmitriiev’s picture

StatusFileSize
new29.91 KB

Uploading the patch that combines also match_limit and match_operator settings from related issue.

Status: Needs review » Needs work

The last submitted patch, 5: 3373258-link-field-handler-settings-5.patch, failed testing. View results

a.dmitriiev’s picture

StatusFileSize
new29.58 KB

Updating trigger_error format

a.dmitriiev’s picture

I have a question how now to change content of this file core/modules/system/tests/fixtures/update/drupal-9.4.0.filled.standard.php.gz, because now the trigger_error makes the tests fail

a.dmitriiev’s picture

StatusFileSize
new32.89 KB

Trying to fix tests and the logic of the update. Add update test.

a.dmitriiev’s picture

Status: Needs work » Needs review

The last submitted patch, 7: 3373258-link-field-handler-settings-7.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 9: 3373258-link-field-handler-settings-9.patch, failed testing. View results

a.dmitriiev’s picture

Status: Needs work » Needs review
StatusFileSize
new33.77 KB

Fixing tests.

Status: Needs review » Needs work

The last submitted patch, 13: 3373258-link-field-handler-settings-13.patch, failed testing. View results

a.dmitriiev’s picture

Status: Needs work » Needs review
StatusFileSize
new33.88 KB

Fixing core/modules/link/tests/src/Functional/LinkFieldUITest.php test

smustgrave’s picture

Status: Needs review » Needs work
Issue tags: +Needs Review Queue Initiative, +Needs change record

Could a CR be written for this new change and setting please.

a.dmitriiev’s picture

I have created a change record https://www.drupal.org/node/3375174 . This is my first change record, so please take it into account. Is it ok to have screenshots in the change record? Or it should be more "textish"?

a.dmitriiev’s picture

Status: Needs work » Needs review
Issue tags: -Needs change record

I have rephrased the change record, so it is easier to read.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

On a standard install
Applied patch
Create a basic page and article page
Verified the post_update hooks run without issue.
Added a link field to the Article content type and only allowed link reference to Basic pages
Created another Article page and searching for article page from before didn't show up but basic page did.

quietone’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs work, +Usability, +Needs change record

I am doing triage on the core RTBC queue.

The patch needs an update, setting to needs work.

The issue summary is straight forward with a proposed resolution. This is making changes to the UI so I am adding the Usability tag. There are no unanswered items in the comments. The patch has been manually tested, including the post_update hook. But all changes need a code review as well.

@a.dmitriiev, thank you for your first change record! It has all the sections that it should. Nice job!

Looking at the screenshots in the CR, the first one has 'Browse available tokens' which is not a string in core. The screenshots are nearly always made from a 'standard' install. Can someone update that? I also think it would be easier for the reader if the 'Field Settings' screenshots were a smaller. If needed, they could just include the 'Allowed link type' and the 'Allow link text' section. Oh, and the text would benefit from some improvements for grammar and readability.

a.dmitriiev’s picture

I have changed the images in change record.

quietone credited leymannx.

quietone’s picture

Issue tags: -

I changed the status of #3341689: Port entity reference widget autocomplete settings to link field widget to duplicate, and now moving credit.

quietone’s picture

Issue tags: -Needs change record

Oh, I meant to remove a tag. And I think it was supposed to be 'needs change record updates'.

a.dmitriiev’s picture

Status: Needs work » Needs review

Anyone knows how to move forward here? What changes should be done to change record? Are there any instructions on how to proceed?

smustgrave’s picture

Status: Needs review » Needs work

I believe @quietone meant in #20 the tag should of been "needs change record updates" which appears you addressed in #21

But relooking at the patch it appears to be failing drupalCi, recommend turning into an MR for easier reviews.

Too many to list but all new functions should have a typehint return even if it's :void.

Deprecation can probably be bumped from 10.2 to 10.3

a.dmitriiev’s picture

Status: Needs work » Needs review

I have converted patch to MR. All jobs in the pipeline for MR were successful.

smustgrave’s picture

Status: Needs review » Needs work
a.dmitriiev’s picture

Status: Needs work » Needs review

All new functions and their parameters now have typehints. Please review MR once again.

smustgrave’s picture

Status: Needs review » Reviewed & tested by the community

Feedback has been addressed.

taran2l’s picture

Attaching a static patch from the latest changes in the MR (for composer patching purposes)

quietone’s picture

Issue summary: View changes
Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs usability review

I'm triaging RTBC issues. I read the IS and the comments. I didn't find any unanswered questions.

I see that the issue summary has remaining tasks that I think are completed. But as I think about this some more it needs more input from UI folds. I am tagging for a UX review..

ilianoz’s picture

StatusFileSize
new34.42 KB

dcam made their first commit to this issue’s fork.

dcam’s picture

Issue summary: View changes
Status: Needs work » Needs review

The MR needed a rebase badly. I took care of it.

I also updated the issue summary. There was no mention of the changes to the LinkWidget settings. I'm not 100% convinced they belong in this same issue, but since this was already RTBC twice I won't stop it.

Since this hasn't undergone a usability review I'm setting the status to Needs Review.

a.dmitriiev’s picture

@dcam, thank you for rebasing the code. Regarding LinkWidget: the changes are described in the issue description with screenshots of Before and After

rkoller’s picture

after checking out MR5993, i run ddev drush cr i get the following error:

PHP Fatal error:  Uncaught Error: Class "Doctrine\Common\Annotations\TokenParser" not found in /var/www/html/repos/drupal/core/lib/Drupal/Component/Annotation/Doctrine/StaticReflectionParser.php:192
Stack trace:
#0 /var/www/html/repos/drupal/core/lib/Drupal/Component/Annotation/Doctrine/StaticReflectionParser.php(329): Drupal\Component\Annotation\Doctrine\StaticReflectionParser->parse()
#1 /var/www/html/repos/drupal/core/lib/Drupal/Core/Hook/HookCollectorPass.php(507): Drupal\Component\Annotation\Doctrine\StaticReflectionParser->getMethodAttributes()
#2 /var/www/html/repos/drupal/core/lib/Drupal/Core/Hook/HookCollectorPass.php(402): Drupal\Core\Hook\HookCollectorPass->collectModuleHookImplementations()
#3 /var/www/html/repos/drupal/core/lib/Drupal/Core/Hook/HookCollectorPass.php(138): Drupal\Core\Hook\HookCollectorPass::collectAllHookImplementations()
#4 /var/www/html/vendor/symfony/dependency-injection/Compiler/Compiler.php(73): Drupal\Core\Hook\HookCollectorPass->process()
#5 /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php(826): Symfony\Component\DependencyInjection\Compiler\Compiler->compile()
#6 /var/www/html/repos/drupal/core/lib/Drupal/Core/DrupalKernel.php(1397): Symfony\Component\DependencyInjection\ContainerBuilder->compile()
#7 /var/www/html/repos/drupal/core/lib/Drupal/Core/DrupalKernel.php(916): Drupal\Core\DrupalKernel->compileContainer()
#8 /var/www/html/repos/drupal/core/lib/Drupal/Core/DrupalKernel.php(507): Drupal\Core\DrupalKernel->initializeContainer()
#9 /var/www/html/drush/Commands/core_development/DevelopmentProjectCommands.php(90): Drupal\Core\DrupalKernel->boot()
#10 /var/www/html/drush/Commands/core_development/DevelopmentProjectCommands.php(68): Drush\Commands\core_development\DevelopmentProjectCommands->drupal_rebuild()
#11 [internal function]: Drush\Commands\core_development\DevelopmentProjectCommands->rebuild()
#12 /var/www/html/vendor/consolidation/annotated-command/src/CommandProcessor.php(276): call_user_func_array()
#13 /var/www/html/vendor/consolidation/annotated-command/src/CommandProcessor.php(212): Consolidation\AnnotatedCommand\CommandProcessor->runCommandCallback()
#14 /var/www/html/vendor/consolidation/annotated-command/src/CommandProcessor.php(175): Consolidation\AnnotatedCommand\CommandProcessor->validateRunAndAlter()
#15 /var/www/html/vendor/consolidation/annotated-command/src/AnnotatedCommand.php(387): Consolidation\AnnotatedCommand\CommandProcessor->process()
#16 /var/www/html/vendor/symfony/console/Command/Command.php(318): Consolidation\AnnotatedCommand\AnnotatedCommand->execute()
#17 /var/www/html/vendor/symfony/console/Application.php(1073): Symfony\Component\Console\Command\Command->run()
#18 /var/www/html/vendor/symfony/console/Application.php(356): Symfony\Component\Console\Application->doRunCommand()
#19 /var/www/html/vendor/symfony/console/Application.php(195): Symfony\Component\Console\Application->doRun()
#20 /var/www/html/vendor/drush/drush/src/Runtime/Runtime.php(110): Symfony\Component\Console\Application->run()
#21 /var/www/html/vendor/drush/drush/src/Runtime/Runtime.php(40): Drush\Runtime\Runtime->doRun()
#22 /var/www/html/vendor/drush/drush/drush.php(140): Drush\Runtime\Runtime->run()
#23 /var/www/html/vendor/bin/drush.php(119): include('...')
#24 {main}
  thrown in /var/www/html/repos/drupal/core/lib/Drupal/Component/Annotation/Doctrine/StaticReflectionParser.php on line 192

Fatal error: Uncaught Error: Class "Doctrine\Common\Annotations\TokenParser" not found in /var/www/html/repos/drupal/core/lib/Drupal/Component/Annotation/Doctrine/StaticReflectionParser.php:192
Stack trace:
#0 /var/www/html/repos/drupal/core/lib/Drupal/Component/Annotation/Doctrine/StaticReflectionParser.php(329): Drupal\Component\Annotation\Doctrine\StaticReflectionParser->parse()
#1 /var/www/html/repos/drupal/core/lib/Drupal/Core/Hook/HookCollectorPass.php(507): Drupal\Component\Annotation\Doctrine\StaticReflectionParser->getMethodAttributes()
#2 /var/www/html/repos/drupal/core/lib/Drupal/Core/Hook/HookCollectorPass.php(402): Drupal\Core\Hook\HookCollectorPass->collectModuleHookImplementations()
#3 /var/www/html/repos/drupal/core/lib/Drupal/Core/Hook/HookCollectorPass.php(138): Drupal\Core\Hook\HookCollectorPass::collectAllHookImplementations()
#4 /var/www/html/vendor/symfony/dependency-injection/Compiler/Compiler.php(73): Drupal\Core\Hook\HookCollectorPass->process()
#5 /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php(826): Symfony\Component\DependencyInjection\Compiler\Compiler->compile()
#6 /var/www/html/repos/drupal/core/lib/Drupal/Core/DrupalKernel.php(1397): Symfony\Component\DependencyInjection\ContainerBuilder->compile()
#7 /var/www/html/repos/drupal/core/lib/Drupal/Core/DrupalKernel.php(916): Drupal\Core\DrupalKernel->compileContainer()
#8 /var/www/html/repos/drupal/core/lib/Drupal/Core/DrupalKernel.php(507): Drupal\Core\DrupalKernel->initializeContainer()
#9 /var/www/html/drush/Commands/core_development/DevelopmentProjectCommands.php(90): Drupal\Core\DrupalKernel->boot()
#10 /var/www/html/drush/Commands/core_development/DevelopmentProjectCommands.php(68): Drush\Commands\core_development\DevelopmentProjectCommands->drupal_rebuild()
#11 [internal function]: Drush\Commands\core_development\DevelopmentProjectCommands->rebuild()
#12 /var/www/html/vendor/consolidation/annotated-command/src/CommandProcessor.php(276): call_user_func_array()
#13 /var/www/html/vendor/consolidation/annotated-command/src/CommandProcessor.php(212): Consolidation\AnnotatedCommand\CommandProcessor->runCommandCallback()
#14 /var/www/html/vendor/consolidation/annotated-command/src/CommandProcessor.php(175): Consolidation\AnnotatedCommand\CommandProcessor->validateRunAndAlter()
#15 /var/www/html/vendor/consolidation/annotated-command/src/AnnotatedCommand.php(387): Consolidation\AnnotatedCommand\CommandProcessor->process()
#16 /var/www/html/vendor/symfony/console/Command/Command.php(318): Consolidation\AnnotatedCommand\AnnotatedCommand->execute()
#17 /var/www/html/vendor/symfony/console/Application.php(1073): Symfony\Component\Console\Command\Command->run()
#18 /var/www/html/vendor/symfony/console/Application.php(356): Symfony\Component\Console\Application->doRunCommand()
#19 /var/www/html/vendor/symfony/console/Application.php(195): Symfony\Component\Console\Application->doRun()
#20 /var/www/html/vendor/drush/drush/src/Runtime/Runtime.php(110): Symfony\Component\Console\Application->run()
#21 /var/www/html/vendor/drush/drush/src/Runtime/Runtime.php(40): Drush\Runtime\Runtime->doRun()
#22 /var/www/html/vendor/drush/drush/drush.php(140): Drush\Runtime\Runtime->run()
#23 /var/www/html/vendor/bin/drush.php(119): include('...')
#24 {main}
  thrown in /var/www/html/repos/drupal/core/lib/Drupal/Component/Annotation/Doctrine/StaticReflectionParser.php on line 192
 [warning] Drush command terminated abnormally.
Failed to run drush cr: exit status 1

... on 11.x i dont get that error. i am on php 8.3 with ddev.

Update: the error happened also after i'Ve dropped the db and reinstalled the site. per @benjifisher recommendation i should have tried git merge 11.x or git rebase 11.x. i first tried the rebase but that had conflicts. I'Ve aborted the rebase and tried the merge and that went through. after the merge of the latest 11.x i was able to run drush cr without any errors. so i suppose the MR needs a rebase as well?

benjifisher’s picture

Status: Needs review » Needs work
Issue tags: -Needs usability review +Needs followup

Usability review

We discussed this issue at #3555446: Drupal Usability Meeting 2025-11-14. That issue has a link to a recording of the meeting. I am giving issue credit here to the attendees at the usability meeting: @benjifisher, @rkoller, and @simohell.

There are a few usability issues we noticed while testing the current MR:

  • It is not clear that the <details> element "Reference type" applies to internal links.
  • The expanded <details> element separates the existing options. Experienced site builders are used to having those options next to each other.
  • When adding a Link field, it is no longer possible to submit the form (accepting default values) because the required "Content types" option requires input.
  • Changing the option in the "Reference method" <select> element triggers an AJAX reload, which scrolls to the top of the modal window.

The last point is out of scope for this issue, since it is an existing problem (for reference fields). But please check for an existing issue, and add a new one if you cannot find one. I am adding the issue tag for a followup issue.

The usability team suggests the following steps to fix the other issues:

  1. Change the label on the <details> element to "Reference method for internal links".
  2. Change the default value for the "Content types" checkboxes from none selected to all selected.
  3. Make the <details> element collapsed by default.

We think that the new feature is something that most sites will not use, so we want to add it in a way that interrupts the existing workflow as little as possible. After (2), a site builder can submit the form, accepting defaults. As a result, there is no problem with (3).

If you want more feedback from the usability team, a good way to reach out is in the #ux channel in Slack.

inaw’s picture

StatusFileSize
new33.62 KB

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.