Si vous pouvez vivre en remplaçant toutes les limites de saisie semi-automatique, vous pouvez remplacer un service principal dans Drupal 8;
Le service que vous devez remplacer est ici dans core.services.yml:
entity.autocomplete_matcher:
class: Drupal\Core\Entity\EntityAutocompleteMatcher
arguments: ['@plugin.manager.entity_reference_selection']
Dans votre module personnalisé, ajoutez une classe qui implémente 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);
}
}
Copiez ensuite EntityAutocompleteMatcher.php dans votre module à /src/Entity/EntityAutocompleteMatcherCustom.php
Ensuite, mettez à jour le 10 codé en dur à 50, ou quelle que soit la limite que vous souhaitez:
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;
}
}
Évidemment, remplacer les services de base comporte certains risques, mais c'est cool que vous puissiez le faire.
Quels sont les risques de remplacer un service principal?
1) Vous pouvez perdre les avantages des mises à jour lorsque vous mettez à jour le noyau. S'il existe un correctif de sécurité critique dans le service et que votre copie modifiée comporte une faille de sécurité, vous ne bénéficierez pas de la mise à jour de ce code par la communauté.
2) Les autres modules que vous installez peuvent avoir des dépendances avec le service d'origine avec son jeu de fonctionnalités d'origine. Disons donc qu'il y a du code dans un autre module qui se cassera si le nombre d'entrées de saisie semi-automatique est supérieur ou inférieur à 10, vous ne le saurez pas, jusqu'à ce qu'il vous affecte.
3) Cela rend votre base de code plus difficile à maintenir. Vous devez vous rappeler que vous n'utilisez pas le noyau Drupal, mais une version étendue. Les autres développeurs qui rejoignent votre projet après votre départ peuvent avoir du mal à comprendre pourquoi un service se comporte de manière non standard.
S'agit-il d'un noyau de piratage?
Cela dépend de la façon dont vous le voyez. Cela ne va pas dans le module de base et ne change pas de code. Il ne s'agit même pas de créer un patch, de l'appliquer et de le suivre avec un gestionnaire de packages tel que composer. Il s'agit davantage d'une personnalisation unique qui modifie le comportement du cœur d'un site, similaire à un crochet ALTER. Il est plus autonome qu'un hack de base, car il se trouve dans votre propre module personnalisé sur votre site. Ainsi, les mises à jour principales du service d'origine ne seront pas affectées, de la même manière que si vous corrigiez ou piratiez le code de service d'origine.
Mais il présente certains des mêmes risques que le noyau de piratage, comme mentionné ci-dessus.
Dans la question d'origine, le problème était que les titres des nœuds n'étaient pas assez uniques. La meilleure solution, autre que la modification globale de la limite lors des listes déroulantes, serait de résoudre le problème de l'unicité.
Ce que je suggérerais, c'est d'ajouter un nouveau champ field_display_title et de l'utiliser sur la page, et si vous en avez besoin, un autre champ field_teaser_title à afficher sur les pages de liste où vous avez besoin d'un titre plus court. Ensuite, le titre réel qui est tiré dans la liste déroulante de sélection de référence d'entité peut être utile à vos éditeurs et être unique, comme «Mon article (page 1)» si le problème est que chaque page a le même titre. Vous n'avez alors pas à remplacer un service principal.
Lorsque vous rencontrez un problème avec Drupal, essayez de trouver la solution qui nécessite le moins de code personnalisé. Cela rend votre site plus stable, plus facile à entretenir et vous fait gagner du temps.