Podłącz się do formatyzatora pola innego modułu?

9

Obecnie próbuję zaimplementować pole obrazu, do którego odwołuje się węzeł, w mojej witrynie Drupal 7, która zmieni tryb wyświetlania w zależności od logiki programowej tuż przed renderowaniem. Pole jest obecnie renderowane na wielu typach treści za pomocą ustawień trybu wyświetlania, z których każdy używa formatera pola „Rendered node”.

pierwsze podejscie

Moim pierwszym pomysłem było wdrożenie następujących, biorąc pod uwagę, że hak to hak to hak:

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;
  }
}

Oczywiście wymiana HACKA na nazwę mojego modułu.

To nie ma znaczenia, czy powyższe będzie ogień przed lub po pierwotnej funkcji node_reference_field_formatter_vieww node_reference.modulebo bym albo zastąpić go za całkowicie lub wyjście, z nadzieją, zmodyfikować jego wartości przed renderowania. Jedyny problem polega na tym, że powyższy hak wydaje się działać tylko dla poszczególnych modułów - tzn. Nie jest szeroki dla całej witryny, więc w zasadzie nie uruchamia się dla mojego modułu.

Teraz oczywiście mogę napisać własny formater pola, aby wyrenderować renderowany węzeł. Ale wydaje się to trochę marnotrawstwem, biorąc pod uwagę, że już istnieje.

inne podejścia

Moje inne podejścia zostały do HOOK_preprocess_nodea HOOK_preprocess_fieldjednak były nie zawierają żadnych view_modeinformacji, a druga zawiera co najmniej 5 różnych skomplikowanych struktur, które wszystkie mają odniesienia do view_modewłaściwości na różnych poziomach - i czuje się dość hacky musiał modyfikować każdy z ich wartości. Nawet po zmianie niektórych view_modewłaściwości wynikowy obraz się nie zmienia.

pytanie

Czy ktoś wie o czystym sposobie wejścia przed renderowaniem formatera pola (modułu contrib) i zmiany jego ustawień na podstawie żądania na stronę - tj. Bez konieczności zmiany ustawień stałego trybu wyświetlania rzeczywistego typu zawartości?

Pebbl
źródło
2
Szukałem czegoś hook_field_formatter_view_alter()podobnego od ponad roku, po prostu niestety nie istnieje. FYI hook_preprocess_node()zdecydowanie nie mieć view_modedostęp do niego, to w $vars['view_mode']nie $vars['node']->view_modektórych może być skłonny spróbować.
Clive
@Clive dziękuję za informacje, och i za wskazanie view_modedalej hook_preprocess_node, głupcze mnie! Zastanawiam się, czy coś takiego hook_field_formatter_view_alter()istnieje w D8 ...
Pebbl
Jeszcze nic nie widziałem ... ale potem wszystko jest konwertowane na wtyczki w D8 (nie jestem pewien co do pól), więc może być tak, że możesz po prostu zastąpić istniejącą klasę, aby wykonać zadanie, byłoby idealnie . Mam nadzieję!
Clive
1
@Clive, czy znalazłeś wspomniany tutaj magiczny hak do zamiany dla D7?
tyler.frankenstein

Odpowiedzi:

11

Pytanie wspomina, że hook_field_formatter_view()jest wywoływane tylko w module inicjującym, ale możesz przejąć na własność formatyzatora pól za pośrednictwem hook_field_formatter_info_alter().

Powinieneś być w stanie ustawić moduleklucz formatyzatora na MYMODULE, np .:

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

Następnie możesz wdrożyć MYMODULE_field_formatter_view(), opcjonalnie zasilając istniejący moduł, który go obsłużył, aby uzyskać element do zmiany.

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
}
Graham C.
źródło
Czy potrafisz rozwinąć swoją odpowiedź? Podać kod?
Scott Joudry
Fajne rozwiązanie, prawie nigdy nie sądzę, aby całkowicie przejąć działalność innego modułu (i wrócić po zmianach) ... po prostu wypróbowałem to i otrzymałem znacznie prostszy kod. Twoje zdrowie!
Pebbl
1
@ScottJoudry ~ może być po prostu warte odnotowania, że ​​jeśli przejmiesz w ten sposób, musisz upewnić się, że masz metody dla całej field_formatterfunkcjonalności węzła_referencyjnego tj. MYMODULE_field_formatter_settings_summaryI MYMODULE_field_formatter_settings_form(nawet jeśli są to tylko funkcje proxy z powrotem do oryginalnego modułu), w przeciwnym razie back- end UI psuje się na dowolnym panelu trybu wyświetlania, gdy próbował znaleźć te metody w niewłaściwym module.
Pebbl
Podejście Grahama C jest interesujące, ale wymaga zbyt wielu przesłonięć.
Milkovsky
2

Ok, więc zdałem sobie sprawę, dlaczego moje zmiany #view_modew albo hook_preprocess_nodei hook_preprocess_fieldsnie działa. (Podziękowania dla Clive'a za wskazanie, że całkowicie przegapiłem obecność #view_modew hook_preprocess_node) .

Mój problem wynikał z faktu, że #view_modezostał już przetworzony i przekształcony we właściwą #image_stylewłaściwość - coś, czego nie szukałem.

Mimo to zmiana tej wartości wydaje się zbyt mocno zależeć od tego, w jaki hak ją zmodyfikowałeś. W końcu udało mi się jednak trochę kodu, który faktycznie zmienia renderowany obraz:

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;
  }
}

Powyższe wciąż nie wydaje się bardzo wymowne, ale przynajmniej działa. Przyjmuję słowo Clive'a, że ​​taka metoda _alter nie istnieje dla formaterów pola - szkoda, formaterery są niezwykle potężną cechą D7, fajnie byłoby mieć większą zdolność rozszerzania.

W każdym razie, jeśli przyszli ludzie będą mieli lepsze pomysły, odpowiedz :)

Pebbl
źródło
0

Najłatwiejszym rozwiązaniem będzie użycie Panelizatora .

Jeśli nie korzystasz z Panelizera, ale z domyślnych trybów widoku Drupal lub Display Suite, spróbuj hook_field_display_alter () lub hook_field_display_ENTITY_TYPE_alter () .

Masz encję, kontekst wyświetlania oraz wszystkie ustawienia formatyzatora. I możesz łatwo zmienić ustawienia renderowania w polu. Możesz nawet zmienić formatyzator pól na inny.

To podejście działa dla mnie idealnie. Jedyną wadą jest to, że możesz pomylić się z różnymi ustawieniami w interfejsie użytkownika „Zarządzaj wyświetlaniem”.

Milkovsky
źródło
0

https://www.drupal.org/node/2130757 To dobry przykład. hook_field_formatter_third_party_settings_form () jest przydatny do zmiany formy istniejącego formatera pola.

Ale to nie działa z grupami pól.

Pierre Noel
źródło