Как я могу переопределить поле абзацев и выходные данные пакета с помощью пользовательского шаблона в пользовательском модуле?
Предыстория
Я создал несколько пакетов абзацев. Моя цель - иметь абсолютный контроль над выводом этих пакетов (1), а также выводом содержащего поля (2) масштабируемым способом (для удобства добавления пакетов в будущем - в будущем может быть более 30 пакетов).
Где я нахожусь
Я создал предложение по теме, используя HOOK_theme_suggestions_HOOK_alter
, чтобы переопределить вывод пакетов. Это позволило мне создавать пользовательские шаблоны веток для каждый сверток.
/**
* Implements hook_theme()
*
* Register a theme for each paragraph type
*
*/
function MYMODULE_theme($existing, $type, $theme, $path){
$theme_templates = [];
$paragraph_types = MYMODULE_get_paragraph_types();
// Register custom Paragraph bundle templates
foreach ($paragraph_types as $paragraph_type){
$theme_templates['paragraph__MYMODULE__' . $paragraph_type] = [
'base hook' => 'paragraph'
];
}
// Register custom Paragraph bundle template fallback
$theme_templates['paragraph__MYMODULE'] = [
'base hook' => 'paragraph'
];
// Register custom Paragraph field wrapper
// $module_path = drupal_get_path('module', 'MYMODULE');
// $theme_templates['paragraph__MYMODULE__field_wrapper'] = [
// 'base hook' => 'field',
// 'template' => 'paragraph--MYMODULE--field-wrapper',
// 'path' => $module_path . '/templates'
// ];
return $theme_templates;
}
/**
* Implements HOOK_theme_suggestions_HOOK_alter
*/
function MYMODULE_theme_suggestions_field_alter(array &$suggestions, array $variables, $hook) {
$field = $variables['element']['#field_name'];
if( $field == 'field_content_modules' ) {
$suggestions[] = 'paragraph__MYMODULE__field_wrapper';
}
}
/**
* Implements HOOK_theme_suggestions_HOOK_alter
*/
function MYMODULE_theme_suggestions_paragraph_alter(&$suggestions, $variables){
$entity = $variables['elements']['#paragraph'];
$sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
$type = $entity->getType();
$suggestions[] = 'paragraph__MYMODULE';
$suggestions[] = 'paragraph__MYMODULE__' . $type;
$suggestions[] = 'paragraph__MYMODULE__' . $type . '__' . $sanitized_view_mode;
}
/**
* Implements hook_theme_registry_alter()
*/
function MYMODULE_theme_registry_alter(&$theme_registry) {
$module_path = drupal_get_path('module', 'MYMODULE');
$template_objects = drupal_find_theme_templates($theme_registry, '.html.twig', $module_path);
$paragraph_types = MYMODULE_get_paragraph_types();
// 1. Loop through the paragraph types
// 2. Check if each paragraph exists in the `$template_objects` array
// 3. If it doesn't exist, remove it from the registry so we don't get any errors
// 4. If it does exist, set actual path to template
foreach ($paragraph_types as $type){
$template = 'paragraph__MYMODULE__' . $type;
if(!isset($template_objects[$template])){
unset($theme_registry['paragraph__MYMODULE__' . $type]);
} else {
$theme_registry['paragraph__MYMODULE__' . $type]['path'] = $template_objects[$template]['path'];
}
}
}
/**
* Helper function to get a list of paragraph types by machine name
*
* @return array
*/
function MYMODULE_get_paragraph_types(){
$paragraph_bundles = \Drupal::service('entity_type.bundle.info')->getBundleInfo('paragraph');
return array_keys($paragraph_bundles);
}
Итак, часть 1 завершена.
Часть 2 управляет HTML-контейнером поля абзаца (не пакета). Это должно быть простое переопределение шаблона поля. Я добавил файл:
/modules/custom/MYMODULE/templates/paragraph--MYMODULE--field-wrapper.html.twig
...и опустил содержимое поля.html.twig.
Когда я раскомментирую код hook_theme
выше ("Зарегистрировать пользовательскую оболочку поля абзаца"), я получаю эту ошибку:
На веб-сайте произошла непредвиденная ошибка. Пожалуйста, повторите попытку позже. Излечимый смертельный ошибка: Аргумент 1 передан Drupal\Core\Render\Элемент::children() должен иметь тип массива, заданный null, вызываемый в /Пользователи/фил/Сайты/поляны/www/модули/контент/абзацы/абзацы. модуль в строке 238 и определен в Drupal\Core\Render\Элемент::дети() (строка 71 из core/lib/Drupal/Core/Render/Element.php).
Есть какие-нибудь мысли относительно того, что я делаю неправильно с переопределением шаблона поля?
Большая часть этого была вдохновлена комментарием Джереми Питера здесь: https://www.drupal.org/node/2499827#comment-12159763
1 answers
Согласно комментарию 4k4 к исходному сообщению, это была проблема с соглашением об именовании, как показано здесь: https://www.drupal.org/docs/8/theming/twig/twig-template-naming-conventions
В функции hook_theme и hook_theme_suggestions_hook_alter выше я изменил:
paragraph__contentmodules__field_wrapper
Кому:
field__paragraph__contentmodules__field_wrapper
Рабочий код:
<?php
/**
* Implements hook_theme()
*
* Register a theme for each paragraph type
*
*/
function MYMODULE_theme($existing, $type, $theme, $path){
$theme_templates = [];
$paragraph_types = MYMODULE_get_paragraph_types();
// Register custom Paragraph bundle templates
foreach ($paragraph_types as $paragraph_type){
$theme_templates['paragraph__MYMODULE__' . $paragraph_type] = [
'base hook' => 'paragraph'
];
}
// Register custom Paragraph bundle template fallback
$theme_templates['paragraph__MYMODULE'] = [
'base hook' => 'paragraph'
];
// Register custom Paragraph field wrapper
$theme_templates['field__paragraph__MYMODULE__field_wrapper'] = [
'base hook' => 'field',
];
return $theme_templates;
}
/**
* Implements HOOK_theme_suggestions_HOOK_alter
*/
function MYMODULE_theme_suggestions_field_alter(array &$suggestions, array $variables, $hook) {
$field = $variables['element']['#field_name'];
if( $field == 'field_content_modules' ) {
$suggestions[] = 'field__paragraph__MYMODULE__field_wrapper';
}
}
/**
* Implements HOOK_theme_suggestions_HOOK_alter
*/
function MYMODULE_theme_suggestions_paragraph_alter(&$suggestions, $variables){
$entity = $variables['elements']['#paragraph'];
$sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
$type = $entity->getType();
$suggestions[] = 'paragraph__MYMODULE';
$suggestions[] = 'paragraph__MYMODULE__' . $type;
$suggestions[] = 'paragraph__MYMODULE__' . $type . '__' . $sanitized_view_mode;
}
/**
* Implements hook_theme_registry_alter()
*/
function MYMODULE_theme_registry_alter(&$theme_registry) {
$module_path = drupal_get_path('module', 'MYMODULE');
$template_objects = drupal_find_theme_templates($theme_registry, '.html.twig', $module_path);
$paragraph_types = MYMODULE_get_paragraph_types();
// 1. Loop through the paragraph types
// 2. Check if each paragraph exists in the `$template_objects` array
// 3. If it doesn't exist, remove it from the registry so we don't get any errors
// 4. If it does exist, set actual path to template
foreach ($paragraph_types as $type){
$template = 'paragraph__MYMODULE__' . $type;
if(!isset($template_objects[$template])){
unset($theme_registry['paragraph__MYMODULE__' . $type]);
} else {
$theme_registry['paragraph__MYMODULE__' . $type]['path'] = $template_objects[$template]['path'];
}
}
}
/**
* Helper function to get a list of paragraph types by machine name
*
* @return array
*/
function MYMODULE_get_paragraph_types(){
$paragraph_bundles = \Drupal::service('entity_type.bundle.info')->getBundleInfo('paragraph');
return array_keys($paragraph_bundles);
}