Wenn Sie damit leben können, alle Grenzwerte für die automatische Vervollständigung zu überschreiben, können Sie einen Kerndienst in Drupal 8 überschreiben .
Der Dienst, den Sie überschreiben müssen, befindet sich hier in core.services.yml:
entity.autocomplete_matcher:
class: Drupal\Core\Entity\EntityAutocompleteMatcher
arguments: ['@plugin.manager.entity_reference_selection']
Fügen Sie in Ihrem benutzerdefinierten Modul eine Klasse hinzu, die ServiceModifierInterface implementiert
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);
}
}
Kopieren Sie dann EntityAutocompleteMatcher.php in Ihr Modul unter /src/Entity/EntityAutocompleteMatcherCustom.php
Aktualisieren Sie dann die fest codierte 10 auf 50 oder ein beliebiges Limit, das Sie möchten:
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;
}
}
Das Überschreiben von Kerndiensten birgt natürlich einige Risiken, aber es ist cool, dass Sie dies tun können.
Was sind die Risiken beim Überschreiben eines Kerndienstes?
1) Sie können die Vorteile von Updates verlieren, wenn Sie den Core aktualisieren. Wenn der Dienst eine kritische Sicherheitslücke enthält und Ihre geänderte Kopie die Sicherheitslücke aufweist, können Sie nicht davon profitieren, dass die Community diesen Code aktualisiert.
2) Andere Module, die Sie installieren, sind möglicherweise vom ursprünglichen Dienst mit seinem ursprünglichen Funktionsumfang abhängig. Nehmen wir also an, in einem anderen Modul befindet sich Code, der beschädigt wird, wenn die Anzahl der Einträge für die automatische Vervollständigung größer oder kleiner als 10 ist. Sie werden nichts davon wissen, bis Sie davon betroffen sind.
3) Es macht es schwieriger, Ihre Codebasis zu pflegen. Sie müssen sich daran erinnern, dass Sie nicht Core Drupal verwenden, sondern eine erweiterte Version. Andere Entwickler, die sich Ihrem Projekt anschließen, nachdem Sie das Projekt verlassen haben, haben möglicherweise Schwierigkeiten herauszufinden, warum sich ein Dienst nicht standardmäßig verhält.
Ist das Hacking Core?
Kommt darauf an, wie du es betrachtest. Es geht nicht in das Kernmodul und ändert den Code. Es geht nicht einmal darum, einen Patch zu erstellen, ihn anzuwenden und mit einem Paketmanager wie Composer zu verfolgen. Es handelt sich eher um eine einmalige Anpassung, die das Kernverhalten einer Site ändert, ähnlich einem ALTER-Hook. Es ist eigenständiger als ein Core-Hack, da es sich in Ihrem eigenen benutzerdefinierten Modul auf Ihrer Site befindet. Kernaktualisierungen des ursprünglichen Dienstes sind also nicht betroffen, genauso wie wenn Sie den ursprünglichen Dienstcode gepatcht oder gehackt haben.
Aber es hat einige der gleichen Risiken wie Hacking Core, wie oben erwähnt.
In der ursprünglichen Frage war das Problem, dass die Knotentitel nicht eindeutig genug sind. Die bessere Lösung als die globale Änderung des Grenzwerts für Dropdowns wäre die Lösung des Eindeutigkeitsproblems.
Was ich vorschlagen würde, ist, ein neues Feld field_display_title hinzuzufügen und dieses auf der Seite zu verwenden, und wenn Sie es benötigen, ein anderes Feld field_teaser_title für die Anzeige auf Listenseiten, auf denen Sie einen kürzeren Titel benötigen. Dann kann der tatsächliche Titel, der in die Dropdown-Liste zur Auswahl von Entitätsreferenzen gezogen wird, für Ihre Redakteure nützlich und eindeutig sein, z. B. "Mein Artikel (Seite 1)", wenn das Problem darin besteht, dass jede Seite denselben Titel hat. Dann müssen Sie einen Kerndienst nicht überschreiben.
Wenn Sie auf ein Problem mit Drupal stoßen, versuchen Sie, die Lösung zu finden, die die geringste Menge an benutzerdefiniertem Code erfordert. Dies macht Ihre Site stabiler, einfacher zu warten und spart Ihnen Zeit.
Ich nehme an, dass das Überschreiben von EntityAutocompleteMatcher alle Formularelemente für die automatische Vervollständigung auf Ihrer Site beeinflusst. Damit ich stattdessen ein neues Entity-Auswahl-Plugin erstellen würde, da es detaillierter ist. Das Plugin kann pro Feld aktiviert werden. Hier ist ein Beispiel für ein solches Plugin. /drupal//a/220136/433
In Ihrem Fall wäre die Implementierung noch trivialer:
Datei: modules / example / src / Plugin / EntityReferenceSelection / ExampleSelection.php
Wenn Sie NodeSelection als Basisklasse anstelle von DefaultSelection verwenden, können Sie referenzierte Knoten nach ihrem Status filtern. Beachten Sie, dass das Verweisen auf andere Entitätstypen noch nicht unterstützt wird .
Im Gegensatz zum Entitätsreferenz-Link-Widget kann das Auswahl-Plugin nicht über die Benutzeroberfläche angegeben werden. Daher müssen Sie es programmgesteuert mit hook_field_widget_WIDGET_TYPE_form_alter () festlegen .
Es ist wichtig, dass die Plugin-ID ein Semikolon enthält.
quelle
Eine andere einfache Möglichkeit, die Anzahl der Ergebnisse zu ändern, besteht darin, den Bereichswert in der Abfrage zu ändern:
quelle
@Weri, ich würde das vermeiden, da ich gerade Ihren Vorschlag umgesetzt und den größten Teil eines Tages damit verbracht habe, ein anderes Problem zu beheben.
Die von Ihnen vorgeschlagene Abfrageänderung wirkt sich auch auf die Gesamtreferenz aus, wenn Absätze mit Knoten verknüpft werden. Ein Knoten, auf dem ich aufwachte, hatte mehr als 80 Absätze, bevor ich die Änderung hinzufügte. Nach dem Hinzufügen konnte ich den Knoten nicht speichern. Durch Entfernen / Auskommentieren der Änderung wurde das Problem behoben.
Aktualisieren
Das Umschließen von $ query-> range () in eine Routenprüfung behebt das Problem für mich, z.
quelle
FWIW, Sie können einfach die Formularanzeige des Feldes auf "Liste auswählen" anstelle von "Autocomplete" setzen.
Dann erhalten Sie alle Optionen, allerdings in einem weniger praktischen Format, aber ohne Hacks.
quelle