Подключиться к модулю поля другого модуля?

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_viewв node_reference.moduleпотому , что я либо переопределить его вывод полностью или, надеюсь, изменить его значение перед визуализацией. Единственная проблема заключается в том, что описанный выше хук, кажется, работает только для каждого модуля, то есть он не распространяется на весь сайт, поэтому в основном он не срабатывает для моего модуля.

Теперь, очевидно, я могу написать свой собственный модуль форматирования поля для вывода визуализированного узла. Но, похоже, это пустая трата, учитывая, что она уже существует.

другие подходы

Мои другие подходы были к HOOK_preprocess_nodeи , HOOK_preprocess_fieldно первый не содержит какой - либо view_modeинформации, а вторая содержит , по меньшей мере , 5 различных сложных структур , которые все имеют ссылки на view_modeсобственность на разных уровнях - и он чувствует себя достаточно Hacky , чтобы изменить у каждого из них ценности. Даже когда я изменил некоторые view_modeсвойства, результирующее изображение не меняется.

вопрос

Кто-нибудь знает чистый способ сделать шаг до того, как форматировщик полей будет отображать (модуля contrib) и изменять его настройки для каждого запроса на странице, то есть не нужно изменять настройки режима постоянного просмотра фактического типа контента?

Pebbl
источник
2
Я искал hook_field_formatter_view_alter()или похожий, вероятно, уже больше года, к сожалению, его просто не существует. К твоему сведению, hook_preprocess_node()безусловно , есть в view_modeналичии, это $vars['view_mode']не то, $vars['node']->view_modeчто ты, возможно, испытал.
Клайв
@Clive спасибо за информацию, о, и за указание view_modeна hook_preprocess_node, глупо меня! Интересно, существует ли что-нибудь подобное hook_field_formatter_view_alter()в D8 ...
Pebbl
Я еще ничего не видел ... но потом все преобразуется в плагины в 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
}
Грэм С
источник
Можете ли вы уточнить свой ответ? Предоставить код?
Скотт Джудри
Хорошее решение, я почти никогда не думаю, что полностью завладею бизнесом другого модуля (и вернусь обратно после изменений) ... просто попробовал его, и в итоге получился гораздо более простой код. Ура!
Pebbl
1
@ScottJoudry ~ может быть просто стоит отметить, что если вы вступите во владение таким образом, вам нужно убедиться, что у вас есть методы для всех field_formatterфункциональных возможностей node_reference, т. Е. MYMODULE_field_formatter_settings_summaryИ MYMODULE_field_formatter_settings_form(даже если они являются просто прокси-функциями обратно в исходный модуль), в противном случае конец пользовательского интерфейса прерывается на любой панели режима отображения, когда он пытался найти эти методы в неправильном модуле.
Pebbl
Подход Graham C интересен, но требует слишком много переопределений.
Милковский
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 для форматировщиков полей не существует - это позор, форматеры - чрезвычайно мощная функция D7, было бы неплохо иметь больше возможностей для расширения.

Во всяком случае, если у кого-нибудь из будущих людей появятся лучшие идеи, ответьте :)

Pebbl
источник
0

Самый простой подход будет использовать Panelizer .

Если вы не используете Panelizer, но по умолчанию используете режимы просмотра Drupal или Display Suite, попробуйте hook_field_display_alter () или hook_field_display_ENTITY_TYPE_alter () .

У вас есть сущность, контекст дисплея, а также все настройки форматера. И вы можете легко изменить настройки визуализации поля. Вы даже можете изменить форматирование поля на другое.

Подход работает идеально для меня. Единственным недостатком является то, что вы можете быть перепутаны с другими настройками в интерфейсе «Управление отображением».

Мильковский
источник
0

https://www.drupal.org/node/2130757 Это хороший пример. hook_field_formatter_third_party_settings_form () полезна для изменения формы существующего форматера полей.

Но это не работает с полевыми группами.

Пьер Ноэль
источник