他のモジュールのフィールドフォーマッタにフックしますか?


9

現在、Drupal 7サイトにノード参照の画像フィールドを実装しようとしています。これにより、レンダリングの直前のプログラムロジックに応じて「表示モード」が変更されます。フィールドは現在、表示モード設定を介していくつかのコンテンツタイプでレンダリングされており、それぞれがフィールドフォーマッター「レンダリングされたノード」を使用しています。

最初の試み

私の最初のアイデアは以下を実装することでした、フックはフックであると考えるとフックです:

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_nodeありましたHOOK_preprocess_fieldが、前者にはview_mode情報が含まれておらず、後者には少なくとも5つの異なる複雑な構造が含まれており、それらはすべてview_mode異なるレベルのプロパティへの参照を持っています。それぞれを変更するのはかなりハッキーな感じです値。特定のview_modeプロパティを変更しても、結果の画像は変更されません。

質問

(contribモジュールの)フィールドフォーマッタがレンダリングされる前に介入し、ページリクエストごとにその設定を変更するためのクリーンな方法を知っている人はいますか?つまり、実際のコンテンツタイプの永続的な表示モード設定を変更する必要はありませんか?


2
私はhook_field_formatter_view_alter()おそらく1年以上前から似たようなものを探していましたが、残念ながら存在しません。FYI hook_preprocess_node()間違いない持っているview_mode、それが利用可能な、それは中だ$vars['view_mode']、ではない$vars['node']->view_modeあなたが試すように誘惑されている可能性があります。
クライヴ

情報、オハイオ州のためと指摘して@Cliveおかげview_modehook_preprocess_node、愚かな私を!hook_field_formatter_view_alter()このようなものがD8に存在するのだろうか...
Pebbl 2013年

まだ何も見ていません...しかし、すべてがD8でプラグインに変換されているので(フィールドについてはわかりません)、既存のクラスをオーバーライドして、仕事を完了することができます。 。期待しています!
クライヴ

1
@ Clive、D7の魔法の変更フックをここで見つけましたか?
tyler.frankenstein

回答:


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 2014

素晴らしい解決策、私は別のモジュールのビジネスを完全に占有する(そして変更後にリレーする)とはほとんど考えていません...試してみただけで、結局ずっと単純なコードになります。乾杯!
Pebbl 2014

1
@ScottJoudry〜はちょうどあなたがこの方法で引き継ぐ場合は、必ずすべての方法持たせる必要があることは注目に値するかもしれないfield_formatternode_referenceすなわちの機能MYMODULE_field_formatter_settings_summaryMYMODULE_field_formatter_settings_form(彼らは、プロキシ機能があり、元のモジュールにバックアップとしても)それ以外の場合はバックを誤ったモジュールでこれらのメソッドを見つけようとしたときに、表示モードパネルでUIが壊れる。
Pebbl 2014

Graham Cのアプローチは興味深いですが、必要なオーバーライドが多すぎます。
milkovsky 2015年

2

わかりましたので、なぜ私の#view_modeどちらにも変更があり、機能hook_preprocess_nodeしてhook_preprocess_fieldsいませんでした。(私は全くの存在見逃していたことを指摘しクライヴのおかげ#view_modeでします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;
  }
}

上記はまだ非常に雄弁な感じがしませんが、少なくともそれは機能します。フィールドフォーマッターにはそのような_alterメソッドは存在しないというのがCliveの言葉です。残念なことに、フォーマッターはD7の非常に強力な機能です。

とにかく、将来の人々がもっと良いアイデアを持っているなら、答えてください:)


0

最も簡単な方法は、パネライザを使用することです

Panelizerを使用せず、デフォルトのDrupalビューモードまたはDisplay Suiteを使用する場合は、hook_field_display_alter()またはhook_field_display_ENTITY_TYPE_alter()を試してください。

エンティティ、表示コンテキスト、およびすべてのフォーマッター設定があります。また、フィールドのレンダリング設定を簡単に変更できます。フィールドフォーマッタを別のフォーマッタに変更することもできます。

このアプローチは私にとって完璧に機能します。唯一の欠点は、「ディスプレイの管理」UIのさまざまな設定と混同される可能性があることです。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.