如果您可以覆盖所有自动完成限制,则可以覆盖 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)对其进行跟踪。它是一种一次性定制,可以更改站点的核心行为,类似于ALTER挂钩。它比核心hack更独立,因为它位于站点上您自己的自定义模块中。因此,对原始服务的核心更新不会受到影响,就像您修补或破解原始服务代码一样。
但是,如上所述,它确实具有与黑客核心相同的风险。
在最初的问题中,问题在于节点标题不够唯一。除了全局更改下拉菜单的限制之外,更好的解决方案是解决唯一性问题。
我建议添加一个新字段field_display_title并在页面上使用它,如果需要,则另一个字段field_teaser_title用于显示在需要较短标题的列表页面上。然后,如果问题是每个页面具有相同的标题,则被拉入“实体引用选择”下拉列表中的实际标题可能对您的编辑者有用并且是唯一的,例如“我的文章(第1页)”。然后,您不必重写核心服务。
当您遇到Drupal的问题时,请尝试查找需要最少数量的自定义代码的解决方案。这使您的网站更稳定,更易于维护并节省时间。