Jeśli możesz żyć z nadpisywaniem wszystkich limitów autouzupełniania, możesz zastąpić usługę podstawową w Drupal 8;
Usługa, którą należy zastąpić, znajduje się tutaj w pliku core.services.yml:
entity.autocomplete_matcher:
class: Drupal\Core\Entity\EntityAutocompleteMatcher
arguments: ['@plugin.manager.entity_reference_selection']
W niestandardowym module dodaj klasę, która implementuje 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);
}
}
Następnie skopiuj EntityAutocompleteMatcher.php do swojego modułu na /src/Entity/EntityAutocompleteMatcherCustom.php
Następnie zaktualizuj zakodowane 10 na 50 lub dowolny limit, jaki chcesz:
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;
}
}
Oczywiście zastąpienie podstawowych usług wiąże się z pewnym ryzykiem, ale fajnie jest to zrobić.
Jakie jest ryzyko zastąpienia usługi podstawowej?
1) Możesz stracić zalety aktualizacji podczas aktualizacji rdzenia. Jeśli w usłudze jest krytyczna poprawka bezpieczeństwa, a zmieniona kopia ma dziurę w zabezpieczeniach, społeczność nie zaktualizuje tego kodu.
2) Inne instalowane moduły mogą zależeć od oryginalnej usługi z jej oryginalnym zestawem funkcji. Powiedzmy więc, że jest jakiś kod w innym module, który się zepsuje, jeśli liczba pozycji autouzupełniania będzie większa lub mniejsza niż 10, nie będziesz o tym wiedział, dopóki nie wpłynie to na ciebie.
3) Utrudnia utrzymanie bazy kodu. Musisz pamiętać, że nie używasz podstawowego Drupala, ale jego rozszerzoną wersję. Inni programiści, którzy dołączają do twojego projektu po twoim odejściu, mogą mieć trudności z ustaleniem, dlaczego usługa zachowuje się w niestandardowy sposób.
Czy to rdzeń hakerski?
Zależy jak na to spojrzeć. Nie wchodzi do modułu podstawowego i nie zmienia kodu. Nie tworzy nawet łatki, nie stosuje jej i nie śledzi za pomocą menedżera pakietów, takiego jak kompozytor. Jest to bardziej jednorazowe dostosowanie, które zmienia podstawowe zachowanie witryny, podobnie jak hak ALTER. Jest to bardziej samowystarczalne niż hack rdzenia, ponieważ znajduje się w twoim własnym niestandardowym module na twojej stronie. Tak więc nie będzie to miało wpływu na podstawowe aktualizacje oryginalnej usługi, tak jak w przypadku łatania lub zhakowania oryginalnego kodu usługi.
Ale wiąże się to z takimi samymi zagrożeniami jak hakowanie rdzenia, jak wspomniano powyżej.
W pierwotnym pytaniu problem polegał na tym, że tytuły węzłów nie są wystarczająco unikalne. Lepszym rozwiązaniem, poza globalną zmianą limitu list rozwijanych, byłoby rozwiązanie problemu wyjątkowości.
Sugeruję dodanie nowego pola field_display_title i użycie go na stronie, a jeśli będzie to potrzebne, kolejne pole field_teaser_title do wyświetlenia na stronach list, na których potrzebujesz krótszego tytułu. Wówczas faktyczny tytuł, który zostanie wciągnięty do menu wyboru odniesienia do encji, może być przydatny dla twoich redaktorów i być unikalny, taki jak „Mój artykuł (strona 1)”, jeśli problem polega na tym, że każda strona ma ten sam tytuł. Wtedy nie musisz zastępować usługi podstawowej.
Gdy napotkasz problem z Drupalem, spróbuj znaleźć rozwiązanie, które wymaga najmniejszej ilości niestandardowego kodu. Dzięki temu witryna jest bardziej stabilna, łatwiejsza w utrzymaniu i oszczędza czas.
Podejrzewam, że zastąpienie EntityAutocompleteMatcher wpłynie na wszystkie elementy formularza autouzupełniania w Twojej witrynie. Aby zamiast tego utworzyć nową wtyczkę wyboru encji, ponieważ jest to bardziej szczegółowe podejście. Wtyczkę można włączyć dla każdego pola. Oto przykład takiej wtyczki. https://drupal.stackexchange.com/a/220136/433
W twoim przypadku wdrożenie byłoby jeszcze bardziej trywialne:
Plik: moduły / przykład / src / Plugin / EntityReferenceSelection / ExampleSelection.php
Użycie NodeSelection jako klasy bazowej zamiast DefaultSelection umożliwiłoby filtrowanie węzłów, do których istnieją odniesienia, według ich statusu. Pamiętaj, że odwoływanie się do innych typów jednostek nie jest jeszcze obsługiwane .
W odróżnieniu od widżetu odnośnika do encji nie można określić wtyczki wyboru poprzez interfejs użytkownika, dlatego należy ustawić ją programowo za pomocą hook_field_widget_WIDGET_TYPE_form_alter () .
Ważne jest, aby identyfikator wtyczki zawierał średnik.
źródło
Innym łatwym sposobem na modyfikację liczby wyników jest zmiana wartości zakresu w zapytaniu:
źródło
@Weri, unikałbym tego, po prostu wdrożyłem twoją sugestię i spędziłem większość dnia próbując rozwiązać inny problem.
Sugerowana zmiana zapytania wpływa również na odwołanie do zapytania podczas łączenia akapitów z węzłami. Węzeł, na którym się obudziłem, miał ponad 80 akapitowy element, zanim dodałem alter. Po dodaniu nie mogłem zapisać węzła. Usunięcie / skomentowanie zmiany rozwiązało problem.
Aktualizacja
Zawijanie $ query-> range () podczas sprawdzania trasy rozwiązuje problem, na przykład:
źródło
FWIW, możesz po prostu ustawić wyświetlanie pola pola na „Wybierz listę” zamiast „Autouzupełniania”.
Następnie otrzymasz wszystkie opcje, aczkolwiek w mniej wygodnym formacie, ale nie wymaga to włamań.
źródło