迷上了其他模块的字段格式化程序?


9

我目前正在尝试在我的Drupal 7网站上实现一个节点引用的图像字段,该字段将根据渲染前的编程逻辑来更改其“查看模式”。当前,正在通过其显示模式设置在多种内容类型上呈现字段,每种内容都使用字段格式化程序“ Rendered node”。

第一次尝试

我的第一个想法是实现以下内容,考虑一个钩子就是一个钩子就是一个钩子:

function HOOK_field_formatter_view( $entity_type, $entity, $field ... ){
  switch ($display['type']) {
    case 'node_reference_node':
      /* Programatical logic here to modfy field render settings */
    break;
  }
}

显然是将HOOK替换为我的模块名称。

上面的代码是否会在原始函数之前或之后触发并不重要node_reference_field_formatter_viewnode_reference.module因为我可以完全覆盖其输出,或者希望在渲染之前修改其值。唯一的问题是,上述挂钩似乎仅在每个模块的基础上起作用-即它不在站点范围内,因此基本上不会为我的模块触发。

现在显然我可以编写自己的字段格式化程序来输出渲染的节点。但是考虑到已经存在一个浪费,这似乎有点浪费。

其他方法

我的其他方法涉及到HOOK_preprocess_nodeHOOK_preprocess_field但前一种方法不包含任何view_mode信息,而后者包含至少5种不同的复杂结构,这些结构都引用了view_mode不同级别的属性-感觉很麻烦,必须修改它们各自的属性。价值观。即使更改了某些view_mode属性,生成的图像也不会更改。

是否有人知道在字段格式化程序渲染(contrib模块的)并按每页请求更改其设置之前的一种干净方法,即不必更改实际内容类型的永久视图模式设置?


2
我一直在寻找一个hook_field_formatter_view_alter()或类似的东西已经有一年多了,不幸的是它并不存在。FYI hook_preprocess_node()绝对不会view_mode提供给它,它在$vars['view_mode'],不是$vars['node']->view_mode你可能被诱惑去尝试。
克莱夫(Clive)

@Clive感谢您的信息,OH和指出了view_modehook_preprocess_node,愚蠢的我!我想知道hook_field_formatter_view_alter()D8中是否存在类似的内容……
Pebbl

我还没有看到任何东西...但是然后所有东西都被转换为D8中的插件(我不确定字段),因此可能是您可以重写现有类来完成工作,这是理想的选择。希望在这里!
克莱夫(Clive)

1
@Clive,您是否找到了这里提到的D7魔术钩?
tyler.frankenstein 2015年

Answers:


11

问题提到hook_field_formatter_view()仅在原始模块上调用,但是您可以通过来获取字段格式化程序的所有权hook_field_formatter_info_alter()

您应该能够module将格式化程序的密钥设置为MYMODULE,例如:

function MYMODULE_field_formatter_info_alter(&$info) {
  $info['some_field_formatter']['module'] = 'MYMODULE';
}

然后,您可以实现MYMODULE_field_formatter_view(),可以选择通过处理它的现有模块来获取要更改的元素。

function MYMODULE_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  // Your custom logic
  $element = OTHER_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display);
  // Any alterations
}

您能否详细说明您的答案?提供一些代码?
Scott Joudry

好的解决方案,我几乎从不认为完全拥有另一个模块的业务(并在更改后转回去)……尽管尝试了一下,但最终得到了更简单的代码。干杯!
Pebbl

1
@ScottJoudry〜可能只是值得注意的是,如果您以这种方式接管,则需要确保您具有用于field_formatternode_reference的所有功能的方法,即MYMODULE_field_formatter_settings_summaryMYMODULE_field_formatter_settings_form(即使它们只是返回原始模块的代理功能),否则当尝试在错误的模块中找到这些方法时,end UI会在任何显示模式面板上中断。
Pebbl 2014年

Graham C的方法很有趣,但是需要太多替代。
milkovsky

2

好了,所以我明白了为什么我的改变#view_mode在任hook_preprocess_nodehook_preprocess_fields不工作。(感谢Clive指出我完全错过了#view_modein 的存在hook_preprocess_node

我的问题源于#view_mode已经被处理并转换为正确#image_style属性的事实,这是我忽略的东西。

即便如此,更改此值似乎在很大程度上取决于您对其进行了修改的钩子。尽管如此,我最终还是可以使用一些代码,实际上可以更改渲染的图像:

function HOOK_preprocess_field( &$vars ){
  $element     = &$vars['element'];
  $entity_type = !empty($element['#entity_type']) ? $element['#entity_type'] : 'unknown';
  $bundle      = !empty($element['#bundle'])      ? $element['#bundle']      : 'unknown';
  $view_mode   = !empty($element['#view_mode'])   ? $element['#view_mode']   : 'unknown';
  $field_name  = !empty($element['#field_name'])  ? $element['#field_name']  : 'unknown';
  switch ( "$entity_type:$view_mode:$bundle/$field_name" ) {
    case 'node:full:mlandingpage/field_lead_image':
      if ( !empty($vars['items']) && 
           ($subelement = &$vars['items'][0]) ) {
        if ( !empty($subelement['field_image']) && 
             ($subfield = &$subelement['field_image'][0]) ) {
          /// this needs to be set to the image_style value, not the view_mode value.
          $subfield['#image_style'] = 'grid-normal-4-cols';
        }
      }
    break;
  }
}

上面的内容仍然不那么雄辩,但至少可以奏效。我会相信Clive的事实,即字段格式化程序不存在这种_alter方法-真可惜,格式化程序是D7的一项极其强大的功能,拥有更多的扩充功能将非常不错。

无论如何,如果将来有人有更好的主意,请回答:)


0

最简单的方法是使用Panelizer

如果不使用Panelizer,而是使用默认的Drupal视图模式或Display Suite,请尝试hook_field_display_alter()hook_field_display_ENTITY_TYPE_alter()

您具有实体,显示上下文以及那里的所有格式设置。而且,您可以轻松更改字段渲染设置。您甚至可以将字段格式化程序更改为其他格式。

该方法对我来说是完美的。唯一的缺点是您可能会对“管理显示” UI中的不同设置感到困惑。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.