すべてのオートコンプリートの制限を上書きしても問題がなければ、Drupal 8のコアサービスを上書きできます。
オーバーライドする必要のあるサービスは、core.services.ymlにあります。
entity.autocomplete_matcher:
class: Drupal\Core\Entity\EntityAutocompleteMatcher
arguments: ['@plugin.manager.entity_reference_selection']
カスタムモジュールで、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);
}
}
次にEntityAutocompleteMatcher.phpを/src/Entity/EntityAutocompleteMatcherCustom.phpのモジュールにコピーします
次に、ハードコードされた10を50または任意の制限に更新します。
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;
}
}
明らかにコアサービスをオーバーライドすることにはいくつかのリスクがありますが、これを実行できるのは素晴らしいことです。
コアサービスを上書きするリスクは何ですか?
1)コアを更新すると、更新のメリットが失われる可能性があります。サービスに重要なセキュリティ修正があり、変更されたコピーにセキュリティホールがある場合、そのコードを更新するコミュニティのメリットは得られません。
2)インストールする他のモジュールは、元の機能セットを持つ元のサービスに依存している場合があります。したがって、オートコンプリートエントリの数が10以上または以下の場合に機能しなくなる別のモジュールのコードがあるとしましょう。影響するまで、それについてはわかりません。
3)コードベースのメンテナンスが難しくなります。コアのDrupalではなく、拡張バージョンを使用していることを覚えておく必要があります。あなたが去った後にあなたのプロジェクトに参加する他の開発者は、サービスが非標準的な方法で動作している理由を理解するのに苦労するかもしれません。
これはハッキングコアですか?
見方次第です。コアモジュールとコードの変更は行いません。パッチを作成して適用し、composerなどのパッケージマネージャーで追跡することすらありません。これは、サイトのコア動作を変更する1回限りのカスタマイズであり、ALTERフックに似ています。それはあなたのサイトのあなた自身のカスタムモジュール内にあるので、それはコアハックより自己完結型です。そのため、元のサービスコードにパッチを適用したりハッキングした場合と同じように、元のサービスへのコアアップデートは影響を受けません。
ただし、前述のように、コアをハッキングするのと同じリスクがいくつかあります。
元の質問では、問題はノードのタイトルが十分に一意ではないことでした。ドロップダウンの制限をグローバルに変更する以外のより良い解決策は、一意性の問題を解決することです。
私が提案するのは、新しいフィールドfield_display_titleを追加してページで使用することです。必要な場合は、短いタイトルが必要なリストページに表示するために別のフィールドfield_teaser_titleを使用してください。次に、エンティティ参照選択ドロップダウンにプルされる実際のタイトルは、編集者にとって便利で、各ページに同じタイトルが付いている場合は「私の記事(ページ1)」のように一意にすることができます。その後、コアサービスをオーバーライドする必要はありません。
Drupalで問題が発生した場合は、カスタムコードの量が最も少ないソリューションを見つけてください。これにより、サイトがより安定し、保守が容易になり、時間を節約できます。