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.