web-dev-qa-db-fra.com

Comment passer une variable de thème d'un modèle à un autre?

Plusieurs champs d'un nœud doivent être affichés d'une manière particulière selon le corps du bulletin dont ils font partie. Comment passer une variable du corps du bulletin englobant aux champs fermés afin de pouvoir informer le champ de son contexte et contrôler la façon dont le champ est affiché?

J'ai un thème qui a des fonctions de prétraitement à la fois pour le corps du bulletin et pour les champs contenus dans le corps.

Je veux définir une variable dans la fonction de prétraitement du corps et son modèle twig, qui peut être inspecté par la fonction de prétraitement de champ et/ou son propre modèle.

En d'autres termes, je veux que chaque champ soit conscient du contexte corporel dans lequel il est rendu.

Plus précisément, j'ai mytheme_preprocess_simplenews_newsletter_body() qui définit une variable ($variables['summons'] = 'placeholder';) Qui peut être inspectée (et également définie) par le modèle simplenews-newsletter-body.html.twig du thème, mais (parce que c'est dans un tableau de rendu différent) n'est par la suite ni visible par mytheme_preprocess_field() ni par field - node - title.html.twig.

Comment puis-je communiquer entre les deux tableaux de rendu?

Notez que

  1. Il existe apparemment des variables globales comme $db_is_active Et $is_admin.

  2. Parfois, il est possible de réaliser ce genre de chose en cascadant les attributs de classe CSS d'un élément conteneur à un élément contenu. Ce n'est généralement pas satisfaisant et dans ce cas particulier, cela ne lavera pas sur les différents clients de messagerie cible le traitement imprévisible des CSS.

6
iainH

La solution avec laquelle je travaille consiste à utiliser drupal_static() ; éléments essentiels simplifiés dans le code ci-dessous - faites attention aux & esperluettes. Cela me donne le contrôle là où j'en ai besoin.

Donc, en utilisant cette approche, je peux - en tenant compte de leur contexte global - par champ, définir des variables de la manière habituelle, par exemple dans mytheme_preprocess_field() à utiliser ultérieurement dans un modèle connexe comme field--node--title--agenda.html.twig

function mytheme_preprocess_simplenews_newsletter_body(&$variables) {
  // prepare to alter static var ...
  // get a reference binding to static var
  $var = &myvariable_function();
  // alter static var
  $var = 'simplenews_newsletter';
}

function mytheme_preprocess_field(&$variables, $hook) {
  // prepare to read static var
  // assign static var
  $var = myvariable_function();
  // $element is the render array for the field
  $element = $variables['element'];
  // filter those cases where it matters that we're theming a newsletter
  if ($element['#view_mode'] == 'email_html' and $var == 'simplenews_newsletter') {
    // Do stuff here like setting a variable for twig ...
    $variables['summons'] = 'some text';
  }
}
function &myvariable_function() {
  $var = &drupal_static(__FUNCTION__);
  if (!isset($var)) {
    // generate contents of static variable
    $var =  'initial_value';
  }
  return $var;
}

Je suis sûr qu'il existe d'autres façons de communiquer un contexte commun entre différents niveaux de la hiérarchie de rendu d'une page. Dites-moi comment vous le feriez.

4
iainH

J'utilise ce code:

/**
 * Helper function to pass slider variables from preprocess_page to preprocess_page_title_custom
 * @param  string $new_image Image URL
 * @return array             Images URL Array
 */
function _core_slider_images($new_image = NULL) {
  $vars = &drupal_static(__FUNCTION__, array());
  // If a new value has been passed add to the array.
  if ($new_image) {
    $vars[] = $new_image;
  }
  return $vars;
}

A partir de ce modèle:

Dans page.html.twig, Nous avons accès à la variable $ node, et nous devons transmettre les valeurs à un autre modèle qui n'a pas accès à cette variable. Nous allons rechercher les valeurs que nous devons passer et appeler la _core_slider_images(), cette fonction sera le pont entre les deux modèles (fonctions de prétraitement)

/**
 * Implements hook_preprocess_page().
 */
function MODULE_preprocess_page(&$variables) {
  // ...
  // Sending Images URL and titles from page to page_title.
    for ($i = 0; $i < $cant; $i++) {
      // Adding the images to the static function.
      _core_slider_images($variables['node']->field_image[$i]->entity->url());
    }
  }

Vers ce modèle:

page-title-custom.html.twig Est un modèle personnalisé et n'a pas accès à $ node. Comme hook_preprocess_page() est appelé en premier, nous avons stocké les valeurs $ node dans une var statique, et nous n'avons besoin d'appeler que la fonction _core_slider_images().

/**
 * Implements hook_preprocess_HOOK().
 */
function MODULE_preprocess_page_title_custom(&$variables) {
  // Searching the variables for sending to the page-title-custom template.
   $images = _core_slider_images();
}
1
Adrian Cid Almaguer

Je suis encore nouveau sur D8, donc je pourrais facilement rater un truc. Généralement, dans cette situation, vous souhaitez rechercher le crochet le plus spécifique qui vous donne accès à tout ce que vous souhaitez modifier. La modification au niveau du champ est donc trop spécifique et au niveau de la page (par exemple) est trop générale.

Malheureusement, MailEntity n'est pas une véritable entité (Drupal), vous ne pouvez donc pas utiliser de hooks standard pour modifier son tableau de rendu. Il n'invoque aucun crochet personnalisé que je peux voir pour vous permettre de modifier le contenu non plus. Dans D7 dans cette situation, je serais tenté d'utiliser hook_page_alter() qui est sale mais fonctionnerait je pense, mais cela a été supprimé de D8.

Vous pouvez toujours remplacer la classe MailEntity et y fournir vos propres personnalisations, mais avoir besoin de le faire pour les changements de thème me semble un peu mal.

0
Andy