Accrocher au formateur de champ d'un autre module?

9

J'essaie actuellement d'implémenter un champ d'image référencé par nœud sur mon site Drupal 7 qui changera son «mode d'affichage» en fonction de la logique de programmation juste avant le rendu. Le champ est en cours de rendu sur un certain nombre de types de contenu via leurs paramètres de mode d'affichage, chacun utilisant le formateur de champ «Noeud rendu».

premier essai

Ma première idée a été d'implémenter ce qui suit, considérant qu'un crochet est un crochet est un crochet:

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

Échange évident de HOOK pour le nom de mon module.

Il n'a pas vraiment d' importance si le serait au- dessus de feu avant ou après la fonction d' origine node_reference_field_formatter_viewen node_reference.moduleparce que je soit remplacer entièrement sa sortie ou, je l' espère, modifier ses valeurs avant de rendre. Le seul problème est que le crochet ci-dessus semble fonctionner uniquement par module - c'est-à-dire qu'il n'est pas à l'échelle du site, donc en gros il ne se déclenche pas pour mon module.

Maintenant, je peux évidemment écrire mon propre formateur de champ pour sortir un nœud rendu. Mais cela semble un peu un gaspillage étant donné qu'il y en a déjà un qui existe.

d'autres approches

Mes autres approches ont été HOOK_preprocess_nodeet HOOK_preprocess_fieldmais la première ne contient aucune view_modeinformation, et la seconde contient au moins 5 structures compliquées différentes qui ont toutes des références à une view_modepropriété à différents niveaux - et il semble plutôt hacky de devoir modifier chacune de leurs valeurs. Même lorsque j'ai modifié certaines view_modepropriétés, l'image résultante ne change pas.

question

Quelqu'un connaît-il un moyen propre d'intervenir avant le rendu d'un formateur de champ (d'un module contrib) et de modifier ses paramètres sur une base de demande par page - c'est-à-dire en n'ayant pas à modifier les paramètres du mode d'affichage permanent du type de contenu réel?

Pebbl
la source
2
Je recherche un hook_field_formatter_view_alter()ou similaire depuis probablement plus d'un an maintenant, il n'existe tout simplement pas malheureusement. Pour votre information , sans hook_preprocess_node()aucun doute n'avoir à sa disposition, il est dans , pas que vous auriez pu être tentés d'essayer. view_mode$vars['view_mode']$vars['node']->view_mode
Clive
@Clive merci pour l'info, oh et pour avoir signalé view_modele hook_preprocess_node, stupide moi! Je me demande si quelque chose comme hook_field_formatter_view_alter()ça existe dans D8 ...
Pebbl
Je n'ai encore rien vu ... mais ensuite tout est converti en plugins dans D8 (je ne suis pas sûr des champs) donc il se peut que vous puissiez simplement remplacer une classe existante pour faire le travail, ce serait l'idéal . En espérant!
Clive
1
@Clive, avez-vous trouvé votre crochet magique mentionné ici pour D7?
tyler.frankenstein du

Réponses:

11

La question mentionne qu'il hook_field_formatter_view()est uniquement appelé sur le module d'origine, mais vous pouvez vous approprier le formateur de champ via hook_field_formatter_info_alter().

Vous devriez pouvoir définir la moduleclé du formateur sur MYMODULE comme:

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

Ensuite, vous pouvez l'implémenter MYMODULE_field_formatter_view(), en passant éventuellement par le module existant qui l'a géré pour obtenir un élément à modifier.

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
la source
Pouvez-vous développer votre réponse? Fournissez du code?
Scott Joudry
Belle solution, je ne pense presque jamais prendre complètement possession des affaires d'un autre module (et relayer après les changements) ... je l'ai juste essayé et je me retrouve avec un code beaucoup plus simple. À votre santé!
Pebbl
1
@ScottJoudry ~ pourrait être utile de noter que si vous prenez le relais de cette manière, vous devez vous assurer que vous avez des méthodes pour toutes les field_formatterfonctionnalités de node_reference, c'est MYMODULE_field_formatter_settings_summary-à- dire et MYMODULE_field_formatter_settings_form(même si ce ne sont que des fonctions proxy vers le module d'origine) sinon le back- fin d'interruption de l'interface utilisateur sur tous les panneaux du mode d'affichage, lorsqu'il a tenté de trouver ces méthodes dans le mauvais module.
Pebbl
L'approche de Graham C est intéressante, mais nécessite trop de dérogations.
milkovsky
2

D'accord, je me suis rendu compte pourquoi mes changements #view_modedans l'un hook_preprocess_nodeet l' autre hook_preprocess_fieldsne fonctionnaient pas. (Merci à Clive d'avoir souligné que j'avais totalement raté la présence de #view_modein hook_preprocess_node) .

Mon problème #view_modevenait du fait qu'il avait déjà été traité et converti en la #image_stylepropriété correcte - quelque chose que j'avais négligé de rechercher.

Même ainsi, la modification de cette valeur semble trop dépendante du hook dans lequel vous l'avez modifiée. J'ai finalement réussi à faire fonctionner du code, qui change en fait l'image rendue:

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

Ce qui précède ne semble toujours pas très éloquent, mais au moins cela fonctionne. Je vais prendre la parole de Clive sur le fait qu'une telle méthode _alter n'existe pas pour les formateurs de champ - c'est dommage, les formateurs sont une fonctionnalité extrêmement puissante de D7, il serait bien d'avoir plus de capacité d'augmentation.

Quoi qu'il en soit, si des personnes futures ont de meilleures idées, répondez loin :)

Pebbl
la source
0

L'approche la plus simple sera d'utiliser le Panelizer .

Si vous n'utilisez pas Panelizer mais les modes d'affichage Drupal par défaut ou Display Suite, essayez hook_field_display_alter () ou hook_field_display_ENTITY_TYPE_alter () .

Vous avez l'entité, le contexte d'affichage ainsi que tous les paramètres du formateur. Et vous pouvez facilement modifier les paramètres de rendu des champs. Vous pouvez même changer le formateur de champs en un autre.

L'approche fonctionne parfaitement pour moi. Le seul inconvénient est que vous pouvez être confondu avec différents paramètres dans l'interface utilisateur "Gérer l'affichage".

milkovsky
la source
0

https://www.drupal.org/node/2130757 Il donne un bon exemple. hook_field_formatter_third_party_settings_form () est utile pour modifier la forme du formateur de champ existant.

Mais cela ne fonctionne pas avec les groupes de terrain.

Pierre Noel
la source