¿Enganchar al formateador de campo de otro módulo?

9

Actualmente estoy tratando de implementar un campo de imagen de referencia de nodo en mi sitio Drupal 7 que cambiará su 'modo de vista' dependiendo de la lógica programática justo antes del render. El campo se está representando actualmente en varios tipos de contenido a través de su configuración de modo de visualización, cada uno de los cuales está utilizando el formateador de campo 'Nodo representado'.

primer intento

Mi primera idea fue implementar lo siguiente, considerando que un gancho es un gancho es un gancho:

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

Obviamente intercambiando GANCHO por el nombre de mi módulo.

En realidad no importa si lo anterior habría disparar antes o después de la función original node_reference_field_formatter_viewen node_reference.moduleporque me anular o bien de salida en su totalidad o, con suerte, modificar sus valores antes de la representación. El único problema es que el enlace anterior parece funcionar solo por módulo, es decir, no abarca todo el sitio, por lo que básicamente no se activa para mi módulo.

Ahora, obviamente, puedo escribir mi propio formateador de campo para generar un nodo renderizado. Pero parece un desperdicio teniendo en cuenta que ya existe uno.

otros enfoques

Mis otros enfoques han sido HOOK_preprocess_nodey, HOOK_preprocess_fieldpero el primero no contiene ninguna view_modeinformación, y el segundo contiene al menos 5 estructuras complicadas diferentes que tienen referencias a una view_modepropiedad en diferentes niveles, y se siente bastante extraño tener que modificar cada uno de sus valores. Incluso cuando he cambiado ciertas view_modepropiedades, la imagen resultante no cambia.

pregunta

¿Alguien sabe de una manera limpia de intervenir antes de que un formateador de campo presente (de un módulo contrib) y cambie su configuración por solicitud de página, es decir, al no tener que cambiar la configuración del modo de vista permanente del tipo de contenido real?

Pebbl
fuente
2
He estado buscando uno hook_field_formatter_view_alter()o similar durante probablemente más de un año, desafortunadamente no existe. FYI hook_preprocess_node()definitivamente no tienen view_modea su disposición, está en $vars['view_mode'], no $vars['node']->view_modeque pudiera haber tenido la tentación de tratar.
Clive
@Clive gracias por la información, oh y por señalar el view_modeencendido hook_preprocess_node, ¡tonto! Me pregunto si hook_field_formatter_view_alter()existe algo así en D8 ...
Pebbl
Todavía no he visto nada ... pero luego todo se está convirtiendo en complementos en D8 (no estoy seguro acerca de los campos), por lo que es posible que pueda anular una clase existente para hacer el trabajo, eso sería ideal . ¡Aquí está esperando!
Clive
1
@Clive, ¿has encontrado tu gancho alternativo mágico mencionado aquí para D7?
tyler.frankenstein

Respuestas:

11

La pregunta menciona que hook_field_formatter_view()solo se invoca en el módulo de origen, pero puede tomar posesión del formateador de campo a través de hook_field_formatter_info_alter().

Debería poder establecer la moduleclave del formateador en MYMODULE como:

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

Luego puede implementar MYMODULE_field_formatter_view(), opcionalmente, a través del módulo existente que lo manejó para obtener un elemento para modificar.

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
fuente
¿Puedes dar más detalles sobre tu respuesta? Proporcionar un código?
Scott Joudry
Buena solución, casi nunca pienso tomar posesión completa del negocio de otro módulo (y retransmitir después de los cambios) ... solo lo probé y termino con un código mucho más simple. ¡Salud!
Pebbl
1
@ScottJoudry ~ podría valer la pena señalar que si se hace cargo de esta manera, debe asegurarse de tener métodos para toda la field_formatterfuncionalidad de node_reference, es decir, MYMODULE_field_formatter_settings_summarye MYMODULE_field_formatter_settings_form(incluso si son solo funciones proxy de regreso al módulo original) de lo contrario La interfaz de usuario final se rompe en cualquier panel de modo de pantalla, cuando intenta encontrar estos métodos en el módulo incorrecto.
Pebbl
El enfoque de Graham C es interesante, pero requiere demasiadas anulaciones.
milkovsky
2

Ok por lo que me di cuenta de por qué mis cambios #view_modeen cualquiera hook_preprocess_nodey hook_preprocess_fieldsno funcionaban. (Gracias a Clive por señalar que había extrañado totalmente la presencia de #view_modein hook_preprocess_node) .

Mi problema surgió del hecho de que #view_modeya se había procesado y convertido a la #image_stylepropiedad correcta , algo que no había buscado.

Aun así, cambiar este valor parece demasiado dependiente del gancho en el que lo modificó. Sin embargo, finalmente conseguí que funcionara un código, que en realidad cambia la imagen renderizada:

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

Lo anterior todavía no se siente muy elocuente, pero al menos funciona. Tomaré la palabra de Clive sobre el hecho de que tal método _alter no existe para los formateadores de campo: es una pena, los formateadores son una característica extremadamente poderosa de D7, sería bueno tener una mayor capacidad de aumento.

De todos modos, si alguna persona futura tiene mejores ideas, responda :)

Pebbl
fuente
0

El enfoque más fácil será usar el Panelizer .

Si no utiliza Panelizer pero los modos de vista Drupal predeterminados o Display Suite, pruebe hook_field_display_alter () o hook_field_display_ENTITY_TYPE_alter () .

Tiene entidad, muestra el contexto y todas las configuraciones del formateador allí. Y puede cambiar fácilmente la configuración de procesamiento de campo. Incluso puede cambiar el formateador de campo a uno diferente.

El enfoque funciona perfecto para mí. La única desventaja es que puede confundirse con diferentes configuraciones en la IU "Administrar pantalla".

milkovsky
fuente
0

https://www.drupal.org/node/2130757 Da un buen ejemplo. hook_field_formatter_third_party_settings_form () es útil para alterar la forma del formateador de campo existente.

Pero esto no funciona con grupos de campo.

Pierre Noel
fuente