How to display more than 10 items in link widget autocomplete? This is a question about the Link module. Since with the Link module you can enter external or internal links both, we strongly rely on it.

Unfortunately the number of items to be displayed from its autocomplete field is limited to 10. We have a lot of nodes with nearly identical titles and so it comes that the node we are searching for doesn't get displayed in the autocomplete field when there are more than 10 matching titles.

The limit is hardcoded in core/lib/Drupal/Core/Entity/EntityAutocompleteMatcher.php. Is there an elegant way to increase this little number from within a custom module? Do I have to extend class EntityAutocompleteMatcher? Where would I have to place my extension and how to ensure it gets executed from within the link widget?
If you can live with overriding all of the autocomplete limits, you can override a core service in Drupal 8;

The service you need to override is here in core.services.yml:

  entity.autocomplete_matcher:
    class: Drupal\Core\Entity\EntityAutocompleteMatcher
    arguments: ['@plugin.manager.entity_reference_selection']


In your custom module, add a class that implements ServiceModifierInterface

namespace Drupal\mymodule;

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\DependencyInjection\ServiceModifierInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;

class MyModuleServiceProvider implements ServiceModifierInterface {

  /**
   * Modifies existing service definitions.
   *
   * @param ContainerBuilder $container
   *   The ContainerBuilder whose service definitions can be altered.
   */
  public function alter(ContainerBuilder $container) {

    for ($id = 'entity.autocomplete_matcher'; $container-&gt;hasAlias($id); $id = (string) $container-&gt;getAlias($id));
    $definition = $container-&gt;getDefinition($id);
    $definition-&gt;setClass('Drupal\mymodule\Entity\EntityAutocompleteMatcherCustom');
    $container-&gt;setDefinition($id, $definition);
  }

}


Then copy EntityAutocompleteMatcher.php into your module at /src/Entity/EntityAutocompleteMatcherCustom.php

Then update the hardcoded 10 to a 50, or whatever limit you'd like:

namespace Drupal\mymodule\Entity;

use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\Tags;
use Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManagerInterface;
use Drupal\Core\Entity\EntityAutocompleteMatcher;

/**
 * Matcher class to get autocompletion results for entity reference.
 */
class EntityAutocompleteMatcherCustom extends EntityAutocompleteMatcher {

  /*
   * {@inheritdoc]
   */
  public function getMatches($target_type, $selection_handler, $selection_settings, $string = '') {

    $matches = array();

    $options = array(
      'target_type' =&gt; $target_type,
      'handler' =&gt; $selection_handler,
      'handler_settings' =&gt; $selection_settings,
    );
    $handler = $this-&gt;selectionManager-&gt;getInstance($options);

    if (isset($string)) {
      // Get an array of matching entities.
      $match_operator = !empty($selection_settings['match_operator']) ? $selection_settings['match_operator'] : 'CONTAINS';
      // Changing limit from 10 to 50.
      $entity_labels = $handler-&gt;getReferenceableEntities($string, $match_operator, 50);

      // Loop through the entities and convert them into autocomplete output.
      foreach ($entity_labels as $values) {
        foreach ($values as $entity_id =&gt; $label) {
          $key = "$label ($entity_id)";
          // Strip things like starting/trailing white spaces, line breaks and
          // tags.
          $key = preg_replace('/\s\s+/', ' ', str_replace("\n", '', trim(Html::decodeEntities(strip_tags($key)))));
          // Names containing commas or quotes must be wrapped in quotes.
          $key = Tags::encode($key);
          $matches[] = array('value' =&gt; $key, 'label' =&gt; $label);
        }
      }
    }

    return $matches;
  }

}


Obviously override core services has some risks, but it's cool that you can do this.

What are the risks of overriding a core service?

1) You may lose the benefits of updates when you update core.  If there is a critical security fix in the service, and your altered copy has the security hole, you will not benefit from the community updating that code.

2) Other modules you install may have dependencies to the original service with its original feature set.  So let's say there is some code in another module that will break if the number of autocomplete entries are greater than or less than 10, you won't know about it, until it affects you.

3) It makes your codebase harder to maintain.  You have to remember that you are not using core Drupal, but an extended version.  Other developers who join your project after you left may have a hard time figuring out why a service is behaving in a non-standard way.

Is this hacking core?

Depends on how you look at it.  It's not going into the core module and changing code.  It's not even creating a patch and applying it and tracking it with a package manager such as composer.  It's more of a one-off customization that alters a sites core behavior, similiar to an ALTER hook. It's more self-contained that a core hack, because it's within your own custom module on your site.  So core updates to the original service will not be affected, the same way as if you patched or hacked the original service code.

But it does have some of the same risks as hacking core, as mentioned above.

In the original question, the issue was the node titles are not unique enough.  The better solution, other than changing the limit globally on drop downs would be solve the uniqueness problem.

What I would suggest is to add a new field field_display_title and use that on the page, and if you need it another field field_teaser_title for display on list pages where you need a shorter title.  Then the actual title that gets pulled into entity reference select dropdown can be useful to your editors and be unique, such as "My Article (page 1)" if the issue is each page has the same title.  Then you don't have to override a core service.

When you come across a problem with Drupal, try to find the solution that requires the least amount of custom code.  This makes your site more stable, easier to maintain and saves you time.