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.
Je suppose que remplacer EntityAutocompleteMatcher affectera tous les éléments du formulaire de saisie semi-automatique sur votre site. Pour que je crée un nouveau plugin de sélection d'entité à la place, car c'est une approche plus granulaire. Le plugin pourrait être activé par champ. Voici un exemple d'un tel plugin. https://drupal.stackexchange.com/a/220136/433
Dans votre cas, la mise en œuvre serait encore plus triviale:
Fichier: modules / example / src / Plugin / EntityReferenceSelection / ExampleSelection.php
L'utilisation de NodeSelection comme classe de base au lieu de DefaultSelection vous permettrait de filtrer les nœuds référencés par leur état. Notez que le référencement d'autres types d'entités n'est pas encore pris en charge .
Contrairement au widget de lien de référence d'entité ne permettant pas de spécifier le plug-in de sélection via l'interface utilisateur, vous devez donc le définir par programme à l'aide de hook_field_widget_WIDGET_TYPE_form_alter () .
Il est important que l'ID du plugin contienne un point-virgule.
la source
Un autre moyen simple de modifier le nombre de résultats consiste à modifier la valeur de la plage dans la requête:
la source
@Weri, j'éviterais de le faire, après avoir implémenté votre suggestion et passé la meilleure partie de la journée à essayer de résoudre un autre problème.
La modification de requête que vous proposez affecte également la référence d'entrée lors de la liaison des paragraphes aux nœuds. Un nœud sur lequel je me réveillais avait 80+ éléments de paragraphe avant d'ajouter la modification. Une fois ajouté, je n'ai pas pu enregistrer le nœud. Supprimer / commenter l'alter a résolu le problème.
Mise à jour
Envelopper le $ query-> range () dans une vérification d'itinéraire résout le problème pour moi, par exemple,
la source
FWIW, vous pouvez simplement définir l'affichage du formulaire du champ sur "Sélectionner la liste" au lieu de "Saisie semi-automatique".
Ensuite, vous obtiendrez toutes les options, bien que dans un format moins pratique, mais aucun piratage requis.
la source