Если вы можете переопределить все ограничения автозаполнения, вы можете переопределить основную службу в 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, попробуйте найти решение, которое требует наименьшего количества пользовательского кода. Это делает ваш сайт более стабильным, простым в обслуживании и экономит ваше время.
Я предполагаю, что переопределение EntityAutocompleteMatcher повлияет на все элементы автозаполнения формы на вашем сайте. Так что вместо этого я бы создал новый плагин выбора сущностей, потому что это более детальный подход. Плагин может быть включен для каждого поля. Вот пример такого плагина. https://drupal.stackexchange.com/a/220136/433
В вашем случае реализация будет еще более тривиальной:
Файл: modules / example / src / Plugin / EntityReferenceSelection / ExampleSelection.php
Использование NodeSelection в качестве базового класса вместо DefaultSelection позволит вам фильтровать ссылочные узлы по их статусу. Обратите внимание, что ссылки на другие типы объектов еще не поддерживаются .
В отличие от виджета ссылка на сущность не позволяет указывать плагин выбора через пользовательский интерфейс, поэтому вам нужно установить его программно, используя hook_field_widget_WIDGET_TYPE_form_alter () .
Важно, чтобы идентификатор плагина содержал точку с запятой.
источник
Другой простой способ изменить количество результатов - изменить значение диапазона в запросе:
источник
@Weri, я бы не стал этого делать, просто реализовав ваше предложение и потратив большую часть дня, пытаясь решить другую проблему.
Предложенный вами запрос на изменение также влияет на начальную ссылку при связывании абзацев с узлами. У узла, на котором я проснулся, было более 80 пунктов абзаца, прежде чем я добавил изменение. После добавления я не смог сохранить узел. Удаление / комментирование измененного исправило проблему.
Обновить
Обертывание $ query-> range () в проверке маршрута устраняет проблему для меня, например,
источник
FWIW, вы можете просто установить отображение формы поля на «Выбрать список» вместо «Автозаполнение».
Затем вы получите все опции, хотя и в менее удобном формате, но никаких взломов не требуется.
источник