view noderef_view.module @ 3:9372c6448311

Add the link in an after_build callback to be a lot more robust. This way, we act after the noderefence fields got transformed into normal widgets by the form processing code. We can thus be pretty sure that the code we put in there will end up where we expect it too.
author Franck Deroche <franck@defr.org>
date Mon, 26 Jan 2009 12:28:09 +0100
parents 25a0c2fcbcfb
children 4fc2f22efcdf
line wrap: on
line source
<?php
// vim: set ts=2 sw=2 expandtab syntax=php:

/**
 * @file 
 * Fichier principale du module noderef_view
 * 
 * Ce module permet d'ajouter à tous les champs de type "Node Reference"
 * pour lesquels une vue définissant les nodes autorisés a été définie
 * un lien 'Search' affichant la vue dans une popup (via le module Popups API),
 * permettant de choisir les nodes à mettre dans le champ en disposant de la
 * puissance de Views pour la recherche (Exposed Filters notamment).
 */

/**
 * Implémentation de hook_view_action_info().
 * 
 * On crée une nouvelle action, nommée Select, et qui sera utilisée pour marquer
 * les nodes comme données à utiliser. L'utilisation concrète qui en est faite
 * dans ce module consiste à utiliser ces nœuds selectionés pour les ajouter
 * dans le champ Node Reference étant à l'origine de la recherche.
 */
function noderef_view_action_info() {
  return array(
    'noderef_view_select' => array(
      'description'  => t('Select for later use'),
      'type'         => 'node',
      'configurable' => FALSE,
      'hooks' => array(
        'nodeapi' => array()
      )
    )
  );
}

/**
 * Implémentation concrète de l'action de selection.
 * 
 * On vide toute eventuelle selection précédente, puis on passe dans le cookie
 * les informations sur la selection qui a été faite.
 */
function noderef_view_select($node, $context) {
  static $count = 0;
  if ($count == 0 && is_array($_COOKIE['noderef'])) {
    // Reset the cookies
    $before = time() - 300;
    foreach($_COOKIE['noderef'] as $id => $val) {
      setcookie('noderef['. $id .']', 0, $before, '/');
    }
  }
  $count++;
  $five = time() + 300;
  setrawcookie('noderef['. $node->nid .']', rawurlencode($node->title), $five, '/');
  dsm(t('!title added to selection', array('!title' => $node->title)));
}

/**
 * Implémentation de hook_form_alter().
 *
 * On parcoure tous les formulaires à la recherche d'éventuels champs
 * de type "Node Reference" sur lesquels appliqués nos transformations.
 */
function noderef_view_form_alter(&$form, $form_state, $form_id) {
  if (isset($form['type']) && $form_id == $form['type']['#value'] .'_node_form') {
    // That's a node form, get the fields and alter the form if needed
    $fields = content_fields();
    $alter = _noderef_view_walk_form($form, $fields);
    if ($alter) {
      // We've changed the form, add the JS-behavior and Views CSS
      // (the latter to deal with exposed filters in the popup)
      drupal_add_css(drupal_get_path('module', 'views') .'/css/views.css');
      drupal_add_js(drupal_get_path('module', 'noderef_view') .'/noderef_view.js');
    }
  }
  elseif ($form_id == 'views_exposed_form' && isset($_GET['destination'])) {
    // Views "Exposed Filter" forms doesn't preserve destination by default.
    $form['destination'] = array(
      '#type' => 'hidden',
      '#value' => $_GET['destination']
    );
  }
}

/**
 * Parcoure le tableau contenant le formulaire à la recherche
 * d'élement à modifier.
 * @return
 *   TRUE si un élement a été modifié, FALSE sinon
 */
function _noderef_view_walk_form(&$form, $fields) {
  $alter = FALSE;
  foreach($form as $key => $item) {
    if (is_array($item)) {
      if (isset($fields[$key])) {
        $alter |= noderef_view_alter_item($form, $key, $fields[$key]);
      }
      else {
        $alter |= _noderef_view_walk_form($item, $fields);
      }
    }
  }
  return $alter;
}

/**
 * Modification d'un élement en particulier du formulaire.
 *
 * @return 
 *   TRUE si l'element a été modifié, FALSE sinon.
 */
function noderef_view_alter_item(&$form, $key, $field) {
  if (is_array($field) && $field['type'] == 'nodereference') {
    $link = _noderef_view_get_link($field);
    if (!empty($link)) {
      $form[$key]['#links'] = $link;
      $form[$key]['#after_build'] = array('noderef_view_add_link');
      return TRUE;
    }
  }
  return FALSE;
}

function noderef_view_add_link($form_element) {
  $form_element['#prefix'] = "<div class='noderef-view-wrapper'>" . $form_element['#prefix'];
  $form_element['#suffix'] .= $form_element['#links'] . '<span class="clear"></span></div>';
  return $form_element;
}

/**
 * Création d'un lien vers une éventuelle vue associé au champ.
 *
 * @return
 *  - Un lien vers la vue si une vue est associée
 *  - Une chaine vide sinon
 */
function _noderef_view_get_link($field) {
  $path = '';
  // Check if there's a view associated with this field
  if (isset($field['advanced_view']) && $field['advanced_view'] !== '--') {
    $view = views_get_view($field['advanced_view']);
    // Try to find a path for this view, looking at the displays
    $path = '';
    foreach($view->display as $display) {
      if (is_array($display->display_options) 
        && isset($display->display_options['path'])) {
        $path = $display->display_options['path'];
        break;
      }
    }
  }
  // If we found a view with a suitable display, then link to it
  if (!empty($path)) {
    popups_add_popups();
    $options = array(
      'attributes' => array('class' => 'popups noderef_view_link'),
      'query' => array('destination' => 'node')
    );
    $path = l(t('Search'), $path, $options);
  }
  return $path;
}