Astuce Drupal 7 : Ajoutez des liens contextuels à n'importe quoi

Posted by: 
Dominique De Cooman

Dans Drupal 7, nous avons quelque chose qui s'appelle des liens contextuels. C'est cette petite roue que vous voyez lorsque vous survolez les blocs que vous pouvez modifier sur place. Il s'agit d'une grande amélioration de la convivialité mais ce n'est pas toujours évident de savoir comment les appliquer.

La fonctionnalité des liens contextuels était un module contrib dans d6 maintenant c'est un module de base.

Réutilisation de tâches locales déjà défini sur un élément personnalisé

Par exemple sur un projet récent, nous avons une liste de liens par thème. Les liens sont regroupés par thème de nœud, nous utilisons un champ lien pour maintenir les liens pour être imprimé. Maintenant, nous aimerions que les liens contextuels sur notre petit bloc de façon à ce que nous pouvons modifier le nœud et de sorte que nous pouvons changer nos liens. Voici comment faire:

<?php
  
// Nous avons un render array défini dans un module personnalisé
  
$block['#theme_wrappers'] = array('thema_block');
  
$block['title'] = l($node->title$url);
  
$block['class'] = "themablock themablock-" $block_count " num-" $block_in_row;
  
$block['more'] =  theme('more_link', array('title' => 'Read more''url' => $url));         

  
// Les liens contextuels que nous accordons à notre élément
  
$block['#contextual_links']['thema_blocks'] = array('node', array($node->nid));  
  
  
render $block;
?>

Laissez-moi vous expliquer ce qui se passe. Tous les liens avec un type MENU_LOCAL_TASK (tels que définis dans leurs hook_menu respectifs) et un contexte MENU_CONTEXT_INLINE sous-jacent du nœud du chemin sont affichés. L'entrée simple dans le tableau #contextual_links ira chercher tous les taks du nœud local.
Regardez comment le module Node définit node / %node / éditer et node / %node / supprimer et il sera clair.

<?php
  $items
['node/%node/edit'] = array(
    
'title' => 'Edit',
    
'page callback' => 'node_page_edit',
    
'page arguments' => array(1),
    
'access callback' => 'node_access',
    
'access arguments' => array('update'1),
    
'weight' => 0,
    
'type' => MENU_LOCAL_TASK,
    
'context' => MENU_CONTEXT_PAGE MENU_CONTEXT_INLINE,
    
'file' => 'node.pages.inc',
  );
  
$items['node/%node/delete'] = array(
    
'title' => 'Delete',
    
'page callback' => 'drupal_get_form',
    
'page arguments' => array('node_delete_confirm'1),
    
'access callback' => 'node_access',
    
'access arguments' => array('delete'1),
    
'weight' => 1,
    
'type' => MENU_LOCAL_TASK,
    
'context' => MENU_CONTEXT_INLINE,
    
'file' => 'node.pages.inc',
  );
?>

Cela signifie que vous ne pouvez pas afficher simplement n'importe quel lien défini dans hook_menu, seule la tâche locale avec une ligne contexte va fonctionner pour des liens contextuels.

Ensuite nous avons besoin d'un thème crochet pour mettre en œuvre notre emballage thème des éléments.

<?php
/**
 * Implements hook_theme().
 */
function glue_theme() {
  
$items = array(
    
'thema_block' => array(
      
'render element' => 'element',
      
'template' => 'tpl/thema_block',
    ),
  );  
  
  return 
$items;
}
?>

Dans un fichier de prétraitement nous pouvons affecter nos variables.

<?php
/**
 * Implements preprocess_thema_block()
 */
function glue_preprocess_thema_block(&$variables) {
  
$variables['classes_array'][] = $variables['element']['class'];
  
$variables['title'] = $variables['element']['title'];
  
$variables['content'] = $variables['element']['#children'];
  
$variables['more'] = $variables['element']['more'];
}
?>

Maintenant la seule chose dont nous avons besoin est un fichier modèle pour imprimer le tout.

<?php
<div class="<?php print $classes; ?>" <?php print $attributes?>>
  <?php print render($title_prefix); ?>
  <h2 <?php print $title_attributes?>><?php print $title;?></h2>
  <div class="content"<?php print $content_attributes?>>
    <?php print $content ?>
  </div>
  <?php print $more ?>
  <?php print render($title_suffix); ?>
</div>
?>

Ici nous pouvons voir, nous avons imprimé les $classes qui contiendra les classes du lien contextuel. Les liens contextuels sont remplis par la fonction render. Les liens réels que vous trouverez dans $title_prefix , sont également mis en place par la fonction render. En rendant ce tableau le code HTML des liens sera imprimé. Le jQuery ajouté par le module contextual_links va transformer tous les tableaux avec les classes correctes à une petite roue surlaquelle vous pouvez cliquer.

vos propres liens contextuels
Maintenant, si nous voulons nos propres liens contextuels, nous devons créer un hook_menu et définir nos propres articles comme des tâches locales avec un contexte en ligne. Voici un exemple trouvé sur l'ajout de nouvelle page de liens contextuels sur http://drupal.org/node/1089922

Dans l'exemple nous allons ajouter nos liens dans le hook_menu et avec un hook_block_view_alter nous allons changer le tableau render des blocs et y ajouter nos liens.

<?php
  
// Un exemple de menu de lien contextuel .
  
$items['contextual/%/information'] = array(
    
'title' => 'Block information',
    
'type' => MENU_LOCAL_ACTION,
    
'context' => MENU_CONTEXT_INLINE,
    
'page callback' => 'contextual_example_page',
    
'page arguments' => array(1),
    
'access callback' => TRUE,
  );
  
// Pour utiliser les éléments de menu des tâches locales, il doit y avoir une page parent.
  
$items['contextual'] = array(
    
'title' => 'The contextual example page',
    
'page callback' => 'contextual_example_page',
    
'page arguments' => array(1),
    
'access callback' => TRUE,
  );
</ 
Php>

<
php>
  
/**
  * Implanter hook_block_view_alter ().
  */
  
function contextual_example_block_view_alter(&$data$block) {
    
// Contextual links can be added as a renderable element to the content of
    // a render array. We check if the block has content, and if so add a
    // contextual link to it.
    
if (isset($data['content']) && is_array($data['content'])) {
      
$contextual_links = array(
        
'contextual',
        array(
$block->module),
      );

      
$data['content']['#contextual_links']['contextual_example'] = $contextual_links;
  }
}
?>

Comme vous pouvez le voir, ça fonctionne parfaitement. Le chemin aux

<?php
$contextual_links 
= array('contextual', array($block->module));
?>

points auxquels nous avons défini dans le hook_menu récupère tout sous le chemin «contextuelle» et le $block->module est l'argument passé.

Si nous voulons ajouter ces liens à notre élément personnalisé dans l'exemple précédent la seule chose nécessaire serait de les ajouter au tableau.

<?php
  
// Nous avons un tableau render défini dans un module personnalisé
  
$block['#theme_wrappers'] = array('thema_block');
  
$block['title'] = l($node->title$url);
  
$block['class'] = "themablock themablock-" $block_count " num-" $block_in_row;
  
$block['more'] =  theme('more_link', array('title' => 'Read more''url' => $url));         


  
// Les liens contextuels que nous mettons dans notre élément
  
$block['#contextual_links']['thema_blocks'] = array('node', array($node->nid));
  
  
$block['#contextual_links']['whatever'] = array('contextual', array($something_usefull));
  
// Sur $something_usefull , vous aurez besoin de mettre quelque chose tel que votre fonction contextuelle/%/ informations saurait quoi faire dans le contexte donné.
  
  
render $bloc;
</
Php>

<
h3Modifier </h3>
Encore une autre méthode d'ajout de liens contextuels est la méthode modifier. Ceci est pris de la <a href="<a href="http://api.drupal.org/api/drupal/modules--system--system.api.php/function/hook_menu_contextual_links_alter/7">api">http://api.drupal.org/api/drupal/modules--system--system.api.php/functio...</a> page</a>

function hook_menu_contextual_links_alter(&$links, $router_item, $root_path) {
  // Add a link to all contextual links for nodes.
<php>
  if ($root_path == '
node/%') {
    $links['
foo'] = array(
      '
title' => t('Do fu'), 
      '
href' => 'foo/do', 
      '
localized_options' => array(
        '
query' => array(
          '
foo' => 'bar',
        ),
      ),
    );
  }
}
?>

Bien sûr, cela ne fonctionnera que pour les chemins existants et sur des éléments existants.

Sur les rangées vues
Nous pouvons également ajouter des liens contextuels aux rangées vues. Dans notre premier exemple, nous voulons ajouter un lien contextuel à nos diapositives de notre mode diaporama. Voici ce que nous avons fait:

<?php
/**
 * Fabricant de liens contextuels
 */
function glue_make_contextual_links($output$nid) {
  
$render_array =
      array(
        
'children' => $output,
        
'#theme_wrappers' => array('contextual_container'),
        
'#contextual_links' => array(
          
'glue' => array('node', array($nid)),
        ),
  );
  return 
render($render_array);
}

/ **
 * 
Ajouter des liens contextuels aux modèles vues
 
* /
function 
glue_preprocess_views_view_field(&$vars) {
  if (isset(
$vars['field']->field_info['field_name']) && $vars['field']->field_info['field_name'] == 'field_slide_image') {
    
$vars['output'] = glue_make_contextual_links($vars['output'], $vars['row']->nid);
  }
}
?>

Nous avons implémenté le prétraitement crochet views_view_field et nous avons enveloppé les liens contextuels autour de notre champ que nous affichons dans l'interface. Vu que la diapositive dans le diaporama est un nœud, nous pouvons utiliser le nid comme argument pour appeler les bons liens contextuels qui nous permette de modifier/supprimer la diapositive affichée.

Pour être complet voici la theme_hook et le prétraitement

<?php
/**
 * Implementer hook_theme().
 */
function glue_theme() {
  
$items = array(
    
'contextual_container' => array(
      
'render element' => 'element',
      
'template' => 'tpl/contextual_container',
    ),
  );  
  
  return 
$items;
}


/ **
 * 
Implanter hook_preprocess_contextual_container ()
 * /
function 
glue_preprocess_contextual_container(&$variables) {
  
$variables['content'] = $variables['element']['children'];
}
?>

Et le fichier modèle:

<?php
<div class="<?php print $classes; ?>" <?php print $attributes?>>
  <div <?php print $content_attributes?>>
    <?php print $content ?>
  </div>
  <div class="custom-contextual-links">
    <?php print render($title_suffix); ?>
  </div>
</div>
?>

Dans notre prochain exemple nous l'avons fait différement. Nous avons une table et nous voulons ajouter un champ avec lien contextuel. Nous avons ajouté un champ lien noeud modifier à notre affichage de la table vue. Dans le modèle de ce champ nommé: nous avons mis ceci:

<?php
<div class="contextual-links-region">
  <
div class="contextual-links-wrapper">
    <
ul class="contextual-links">
      <
li>
        <?
php print $output?>
      </li>
    </ul>  
  </div>
</div>
?>

Celui-ci est moins propre, car vous ne pouvez ajouter qu'un élément de ce genre. En théorie, il serait possible de l'ajouter à la ligne de la table, mais cela signifie d'adapter le jQuery à partir de liens contextuels pour cibler aussi les éléments TR, à la base, il ne cible que les éléments div, les mettre autour d'éléments TR n'est pas du HTML valide.

Sur les modèles
Sur notre site, nous utilisons également le module modèle qui fournit «une entité conteneur». C'est une entité avec juste un titre et son champ. Au lieu de mettre en œuvre un bon nombre de crochets vous même , vous pourriez prendre ce module et faire en sorte que cette entité fonctionne immédiatement. (Http://drupal.org/project/model) Nous utilisons l'entité modèle qui stocke des informations qui n'ont pas besoin de l'extra qu'un nœud offre, comme le workflow, de création, etc. Nous en avons besoins juste pour stocker des trucs dans les champs. Parfait pour stocker des images d'en-tête et le chemin surlequel ils ont besoin d'être affiché. En utilisant ce bundle header_image nous pouvons montrer une en-tête différente sur les chemins spécifiés. Maintenant que c'est fait ne serait il pas magnifique d'avoir des liens contextuels sur elle? C'est ainsi que nous l'avons fait:

<?php
function glue_menu() {
  
$items['admin/content/models/model/%/add'] = array(
    
'title' => 'Add',
    
'type' => MENU_LOCAL_ACTION,
    
'context' => MENU_CONTEXT_INLINE,
    
'page callback' => 'glue_model_add_type',
    
'page arguments' => array(4),
    
'access callback' => TRUE,
  );

  return 
$items;
}

/ **
 * 
Aller à la page d'ajout pour le modèle
 * /
function glue_model_add_type($mid) {
  $destination = drupal_get_destination();
  $query = db_select('
model', 'm');
  $result = $query
          ->condition('
m.model_id', $mid, '=')
          ->fields('
m', array('type'))
          ->execute()
          ->fetch();

  $params = array(
    '
query' => array(
      '
destination' => $destination['destination'],
    )
  );
  //Où aller ensuite
  $_GET['
destination'] = url('admin/content/models/add/' . $result->type, $params);
  drupal_goto('
admin/content/models/add/' . $result->type, $params);
}

function create_logo() {
  $model = model_load($item->model_id);
  $logo = field_view_field('
model', $model, 'field_logo_logo', 'full');
  $logo[0]['
#image_style'] = 'logo_style';
  
$logo_and_link = array(
    
'#type' => 'link',
    
'#title' => render($logo[0]),
    
'#href' => '',
    
'#options' => array('html' => TRUE'attributes' => array('class' => $css_class)),
    
'#contextual_links' => array(
      
'logo' => array('admin/content/models/model', array($model->model_id)),
    )
  );
  if (isset(
$model->field_logo_link['und'][0]['url'])) {
    
$header_and_link['#href'] = $model->field_logo_link['und'][0]['url'];
  }
  return 
$logo_and_link;
}
?>

Nous avons ajouté une fonction de rappel du menu pour enregistrer des actions locales pour ajouter chaque modèle. Dans le rappel, nous mettons la requête du type et nous le faisons aller à la page d'ajout. De cette façon, lorsque nous créons un tableau render de liens contextuels, non seulement pour modifier et supprimer, mais aussi seront présents sur le lien Ajouter .

Enfin comment mettre le noeud/ajouter/%type en un truc de lien contextuel

La même astuce que nous avons fait avec les modèles , nous pouvons la faire avec les nœuds:

<?php
function glue_menu() {
  
$items['node/%/add'] = array(
    
'title' => 'Add',
    
'type' => MENU_LOCAL_ACTION,
    
'context' => MENU_CONTEXT_INLINE,
    
'page callback' => 'glue_node_add_type',
    
'page arguments' => array(1),
    
'access callback' => TRUE,
  );

  return 
$items;
}

/ **
 * 
aller à la page d'ajout pour le nœud
 * /
function glue_node_add_type($nid) {
  $destination = drupal_get_destination();
  $query = db_select('
node', 'n');
  $result = $query
          ->condition('
n.nid', $nid, '=')
          ->fields('
n', array('type'))
          ->execute()
          ->fetch();

  $params = array(
    '
query' => array(
      '
destination' => $destination['destination'],
    )
  );
  //Où aller ensuite
  $_GET['
destination'] = url('node/add/' . $result->type, $params);
  drupal_goto('
node/add/' . $result->type, $params);
}
?>

Les slides sont donc les nœuds dans le screenshot ci-dessus que vous pouvez "Toevoegen" qui signifie «Ajouter» en néerlandais. Ceci a été causé par le dernier morceau de code.

Je suis sûr qu'il existe beaucoup d'autres méthodes pour ajouter des liens contextuels. Donc je vous laisse les poster dans les commentaires.

Add new comment

Who are you?


By knowing who you are you will be directed to a page where we have displayed all our drupal services relevant to your professional identity.