Drupal-7 如何在不覆盖现有格式化程序的情况下调用 hook_field_[formatter_]prepare_view()

标签 drupal-7 drupal-hooks drupal-fields drupal-field-api

在我的模块中,我正在寻找一种在渲染过程中更改文本字段值的方法,但不创建新的格式化程序,并且在当前受影响的格式化程序工作之前。

换句话说,我希望我的更改始终在任何文本字段上进行,作为通用的准备步骤,无论之后使用哪个格式化程序。

为此,请执行以下操作:

  • 我首先考虑使用hook_field_formatter_prepare_view()

    为了调用它,我想使用hook_field_formatter_info_alter() 将我的模块名称添加到此处找到的每个涉及的格式化程序中。但它 看来“模块”索引只接受唯一的模块名称, 不是数组。
    顺便说一句,我对这种缺乏感到非常惊讶:我认为允许一系列格式化程序应该有意义,就像允许一系列 过滤器!

  • 然后我考虑使用hook_field_prepare_view(),这似乎 成为最佳候选者,因为医生说它在 格式化程序拥有 hook_field_formatter_prepare_view()。但那个 也不起作用:仅针对由以下命令创建的字段调用此 Hook 涉及的模块(这个问题已讨论过here)。

有什么想法吗?提前致谢。

最佳答案

我实际上找到了一种很好的方法来完成我所寻找的事情。
该方法具有相当的侵入性,但效果很好,并且可以在不同的情况下重复使用。

<强>1。为了尽可能清楚,首先我用以下方式重新表述我的问题 一般用例:

In the rendering process, how to permit a module to change value of one or more fields (given field-id, given field-type...) before the formatter (if any) do its own job?

<强>2。实现这一点的问题:

We can't make the module define a new formatter, because only one may be defined at the same time for the same field

<强>3。使我达到预期结果的策略:

  • 使用 hook_field_formatter_info_alter() 运行现有的格式化程序,并将我的模块“移植”到我希望干预的模块中
    (参见下面第 4 条的详细信息)
  • 使用hook_field_formatter_prepare_view()来:
    (a) 对字段值执行所需的更改
    (我的模块的目的是:根据给定类型的所有字段或精确识别的字段等,这里可以完成也可以不完成,具体取决于任何详细需求)
    (b) 再次运行格式化程序列表,并在涉及时触发它们自己的 hook_field_formatter_prepare_view()(如果存在)
    (参见下面第 5 条的详细信息)
  • 依次对任何格式化程序的每个其他可能涉及的 Hook 执行与上面 (b) 中相同的工作:
    hook_field_formatter_view()
    hook_field_formatter_setting_form()
    hook_field_formatter_setting_summary()

<强>4。详细介绍一下我的模块如何嫁接的过程:

使用 hook_field_formatter_info_alter(&$info) 我们面临以下 $info 结构:

$info = array(
  ['formatter machine name'] = array(
    ['label'] => 'Human readable formatter description',
    ['field types'] => array(
      [0] => 'a_field_type,
      [1] => 'another_field_type',
      # ...
    ),
    ['settings'] => array(
      ['option A'] => 'option A value',
      ['option B'] => 'option B value',
      # ...
    ),
    ['module'] => 'formatter_module_name',
  ),
  ['formatter machine name'] = array(
    # ...
  ),
  # ...
);

我们可以轻松地浏览格式化程序列表并查看“字段类型”索引来选择我们需要的类型。
然后对于每一个涉及的,我们可以:

  1. 将我们自己的模块名称替换为“模块”索引中的格式化程序模块名称
  2. 在“设置”索引中添加一个新的子索引(例如“我们的模块移植”)来注册原始格式化程序模块名称

所以我们的hook_field_formatter_info_alter()将类似于:

function mymodule_field_formatter_info_alter(&$info) {
  if($info) {
    foreach($info as $name=>$formatter) {
      if(
        !@$formatter['settings']['mymodule graft'] # or already grafted
      and
        array_intersect($formatter['field types'],
          array('text','text_long','text_with_summary')) # here it is for text fields only
      ) {
        # substitute mymodule to original module:
        $info[$name]['settings']['mymodule graft']=$formatter['module'];
        $info[$name]['module']='mymodule';
      }
    }
  }
}

一旦刷新类注册表,现在所有涉及的字段都将其格式化阶段重定向到我们自己的模块。
注意:安装新的格式化程序现在需要再次刷新类注册表,以便我们的模块也能将其掌握在手中。

<强>5。有关如何使原始格式化程序在我们之后工作的详细信息:

如上所述,现在是我们自己的模块在必须格式化字段时收到通知,而不是最初受影响的格式化程序。
因此,我们必须在 hook_field_formatter_prepare_view() 中使用react,它应该如下所示:

function mymodule_field_formatter_prepare_view(
  $entity_type,$entities,$field,$instances,$langcode,&$items,$displays
) {
  # here we do our own job with field values:
  if($items) {
    foreach($items as $nid=>$node_data) {
      # ...
    }
  }
  # then we give original formatter a chance to execute its own hook:
  foreach($displays as $display) {
    $hook=
      $display['settings']['mymodule graft'].'_field_formatter_prepare_view';
    if(function_exists($hook)) {
      $hook(
        $entity_type,$entities,$field,$instances,$langcode,$items,$displays
      );
    }
  }
}

最后,我们还必须给其他格式化程序钩子(Hook)一个执行的机会。
对于每一个,它应该看起来像(用每个钩子(Hook)的正确数据替换 HOOK 和 ARGS):

function mymodule_field_formatter_HOOK(ARGS) {
  $hook=$display['settings']['mymodule graft'].'_field_formatter_HOOK';
  if(function_exists($hook)) {
    return $hook(ARGS);
  }
}

希望这有帮助...

关于Drupal-7 如何在不覆盖现有格式化程序的情况下调用 hook_field_[formatter_]prepare_view(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29311016/

相关文章:

php - 如何在drupal 7中为用户和访客制作不同的菜单 View ?

drupal-8 - 在 Drupal 8 中对特定节点类型使用预处理钩子(Hook)

Drupal 保存数据 hook_form_alter

javascript - 德鲁帕尔 7 : how do I add the async attribute to an external JS script when using drupal_add_js?

drupal - 创建自定义字段格式化程序不起作用

Drupal 7 条件字段 : How to display specific fields based on other select option fields

drupal - 快速构建Drupal模块的技术?

php - 如何让 PagerDefault 查询与 Drupal 7 一起正常工作?

javascript - 如何禁用ckeditor云服务

Drupal View 将 2 列合并为 1?