Conectar-se ao formatador de campo de outro módulo?

9

Atualmente, estou tentando implementar um campo de imagem referenciado por nó no meu site Drupal 7 que mudará seu 'modo de exibição', dependendo da lógica programática antes da renderização. No momento, o campo está sendo renderizado em vários tipos de conteúdo por meio de suas configurações de modo de exibição, cada um usando o formatador de campo 'Nó renderizado'.

primeira tentativa

Minha primeira idéia foi implementar o seguinte, considerando que um gancho é um gancho é um 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, trocando HOOK pelo nome do meu módulo.

Realmente não importava se o item acima seria acionado antes ou depois da função original node_reference_field_formatter_view, node_reference.moduleporque eu substituiria totalmente a saída ou, esperançosamente, modificaria seus valores antes da renderização. O único problema é que o gancho acima parece funcionar apenas por módulo - ou seja, não é de todo o site, portanto, basicamente, não é acionado para o meu módulo.

Agora, obviamente, eu posso escrever meu próprio formatador de campo para gerar um nó renderizado. Mas parece um desperdício, considerando que já existe um.

outras abordagens

Minhas outras abordagens foram HOOK_preprocess_nodee, HOOK_preprocess_fieldmas a primeira não contém nenhuma view_modeinformação, e a segunda contém pelo menos cinco estruturas complicadas diferentes, todas com referências a uma view_modepropriedade em diferentes níveis - e parece um pouco invasivo ter que modificar cada uma delas. valores. Mesmo quando eu mudei certas view_modepropriedades, a imagem resultante não muda.

questão

Alguém sabe uma maneira clara de intervir antes que um formatador de campo seja processado (de um módulo contrib) e altere suas configurações com base na solicitação por página - ou seja, não sendo necessário alterar as configurações do modo de visualização permanente do tipo de conteúdo real?

Pebbl
fonte
2
Estou procurando um hook_field_formatter_view_alter()ou similar há provavelmente mais de um ano, mas isso simplesmente não existe. FYI hook_preprocess_node()definitivamente não têm view_modeà sua disposição, está em $vars['view_mode'], não $vars['node']->view_modeo que você poderia ter sido tentado a experimentar.
Clive
@ Clive obrigado pela informação, oh e por apontar o view_modeon hook_preprocess_node, me engane ! Pergunto-me se qualquer coisa como hook_field_formatter_view_alter()isto existe em D8 ...
Pebbl
Ainda não vi nada ... mas tudo está sendo convertido em plug-ins no D8 (não tenho certeza sobre os campos); portanto, você pode simplesmente substituir uma classe existente para concluir o trabalho, isso seria o ideal . Aqui está esperando!
Clive
1
@Clive, você encontrou seu gancho de alteração mágico mencionado aqui para o D7?
tyler.frankenstein

Respostas:

11

A pergunta menciona que hook_field_formatter_view()é chamada apenas no módulo de origem, mas você pode assumir a propriedade do formatador de campo por meio de hook_field_formatter_info_alter().

Você deve poder definir a modulechave do formatador como MYMODULE como:

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

Em seguida, você pode implementar MYMODULE_field_formatter_view(), alimentando opcionalmente o módulo existente que o tratou para obter um elemento para alterar.

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
fonte
Você pode elaborar sua resposta? Fornecer algum código?
Scott Joudry
Solução agradável, quase nunca penso em tomar posse total dos negócios de outro módulo (e retransmitir após as alterações) ... apenas tentei e acabei com um código muito mais simples. Felicidades!
Pebbl 02/08/14
1
O @ScottJoudry ~ pode valer a pena notar que, se você assumir o controle dessa maneira, precisará ter métodos para toda a field_formatterfuncionalidade do node_reference, isto é, MYMODULE_field_formatter_settings_summarye MYMODULE_field_formatter_settings_form(mesmo que sejam apenas funções proxy no módulo original), caso contrário, o back- A interface do usuário final é interrompida em qualquer painel do modo de exibição, quando ele tenta encontrar esses métodos no módulo errado.
Pebbl
A abordagem do Graham C é interessante, mas requer muitas substituições.
milkovsky
2

Ok, então eu percebi por que minhas alterações #view_modeno hook_preprocess_nodee hook_preprocess_fieldsnão estavam funcionando. (Obrigado a Clive por apontar que eu tinha perdido totalmente a presença de #view_modein hook_preprocess_node) .

Meu problema surgiu do fato de que #view_modejá havia sido processado e convertido na #image_stylepropriedade correta - algo que eu havia deixado de procurar.

Mesmo assim, alterar esse valor parece muito dependente de qual gancho você o modificou. Finalmente, finalmente consegui trabalhar com um código que realmente altera a imagem 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;
  }
}

O exposto acima ainda não parece muito eloquente, mas pelo menos funciona. Vou aceitar a palavra de Clive no fato de que esse método _alter não existe para os formatadores de campo - é uma pena, os formatadores são um recurso extremamente poderoso do D7, seria bom ter mais capacidade de aumento.

De qualquer forma, se alguém do futuro tiver idéias melhores, responda :)

Pebbl
fonte
0

A abordagem mais fácil será usar o Panelizer .

Se não usar o Panelizer, mas os modos de exibição padrão do Drupal ou o Display Suite, tente hook_field_display_alter () ou hook_field_display_ENTITY_TYPE_alter () .

Você tem entidade, exibe o contexto e todas as configurações do formatador. E você pode facilmente alterar as configurações de renderização do campo. Você pode até mudar o formatador de campo para outro.

A abordagem funciona perfeita para mim. A única desvantagem é que você pode estar confuso com diferentes configurações na interface do usuário "Gerenciar exibição".

milkovsky
fonte
0

https://www.drupal.org/node/2130757 É um bom exemplo. hook_field_formatter_third_party_settings_form () é útil para alterar a forma do formatador de campo existente.

Mas isso não funciona com grupos de campo.

Pierre Noel
fonte