Если вы можете переопределить все ограничения автозаполнения, вы можете переопределить основную службу в Drupal 8;
Служба, которую вы должны переопределить, находится здесь в core.services.yml:
entity.autocomplete_matcher:
class: Drupal\Core\Entity\EntityAutocompleteMatcher
arguments: ['@plugin.manager.entity_reference_selection']
В свой пользовательский модуль добавьте класс, который реализует 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->hasAlias($id); $id = (string) $container->getAlias($id));
$definition = $container->getDefinition($id);
$definition->setClass('Drupal\mymodule\Entity\EntityAutocompleteMatcherCustom');
$container->setDefinition($id, $definition);
}
}
Затем скопируйте EntityAutocompleteMatcher.php в свой модуль по адресу /src/Entity/EntityAutocompleteMatcherCustom.php
Затем измените жестко запрограммированное 10 на 50 или любое другое ограничение:
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' => $target_type,
'handler' => $selection_handler,
'handler_settings' => $selection_settings,
);
$handler = $this->selectionManager->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->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 => $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' => $key, 'label' => $label);
}
}
}
return $matches;
}
}
Очевидно, что переопределение основных служб сопряжено с некоторыми рисками, но это здорово, что вы можете сделать это.
Каковы риски переопределения основного сервиса?
1) Вы можете потерять преимущества обновлений при обновлении ядра. Если в службе есть критическое исправление безопасности, и ваша измененная копия имеет дыру в безопасности, вы не получите пользы от обновления этого кода сообществом.
2) Другие модули, которые вы устанавливаете, могут иметь зависимости от исходного сервиса с его исходным набором функций. Итак, допустим, что в другом модуле есть какой-то код, который сломается, если число записей автозаполнения больше или меньше 10, вы не будете знать об этом, пока это не повлияет на вас.
3) Это делает вашу кодовую базу труднее поддерживать. Вы должны помнить, что вы используете не ядро Drupal, а расширенную версию. Другим разработчикам, которые присоединяются к вашему проекту после вашего ухода, может быть трудно понять, почему сервис ведет себя нестандартным образом.
Это хакерское ядро?
Зависит от того, как ты смотришь на это. Это не входит в основной модуль и не меняет код. Это даже не создание патча, его применение и отслеживание с помощью менеджера пакетов, такого как composer. Это больше одноразовая настройка, которая изменяет поведение ядра сайта, аналогично перехвату ALTER. Он более автономен, чем основной хак, потому что он находится внутри вашего собственного пользовательского модуля на вашем сайте. Таким образом, основные обновления оригинальной службы не будут затронуты так же, как если бы вы исправили или взломали исходный код службы.
Но он имеет некоторые из тех же рисков, что и хакерское ядро, как упомянуто выше.
В первоначальном вопросе проблема заключалась в том, что названия узлов не были достаточно уникальными. Лучшим решением, кроме глобального изменения ограничения на выпадающие списки, было бы решение проблемы уникальности.
Я бы предложил добавить новое поле field_display_title и использовать его на странице, а при необходимости другое поле field_teaser_title для отображения на страницах списка, где вам нужен более короткий заголовок. Тогда фактический заголовок, который добавляется в раскрывающийся список выбора ссылки на сущность, может быть полезен для ваших редакторов и быть уникальным, например «Моя статья (страница 1)», если проблема заключается в том, что каждая страница имеет одинаковый заголовок. Тогда вам не нужно переопределять основной сервис.
Когда вы сталкиваетесь с проблемой с Drupal, попробуйте найти решение, которое требует наименьшего количества пользовательского кода. Это делает ваш сайт более стабильным, простым в обслуживании и экономит ваше время.