changeset 0:a3c1e224e807

Import initial du module noderef_view
author Franck Deroche <franck@defr.org>
date Fri, 23 Jan 2009 14:52:03 +0100
parents
children 71a07534c366
files noderef_view.info noderef_view.js noderef_view.module
diffstat 3 files changed, 214 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/noderef_view.info	Fri Jan 23 14:52:03 2009 +0100
@@ -0,0 +1,6 @@
+name = Node Reference with View popups
+description = Adds a "Search" link to nodereference widgets which use the associated view
+dependencies[] = nodereference
+dependencies[] = views
+package = User Interface
+core = 6.x
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/noderef_view.js	Fri Jan 23 14:52:03 2009 +0100
@@ -0,0 +1,48 @@
+// vim: set ts=2 sw=2 expandtab syntax=php:
+/**
+ * Attach the noderef_view behavior.
+ */
+Drupal.behaviors.noderef_view = function(context) {
+  $('.noderef_view_link', context).each(function(i, obj) {
+    $(obj).addClass('noderef_view_link_processed').click(function() {
+      // Get the wrapper
+      var id = $(this).attr('rel');
+      var wrapper = $('#' + id);
+
+      // Suppress behavior if it was previsously attached
+      $(document).unbind('popups_form_success.noderef_view');
+
+      // And now bind it. This code will be executed after successful
+      // completion of the popup select form
+      $(document).bind('popups_form_success.noderef_view', function() {
+        selection = noderef_view_get_selection();
+        for(nid in selection) {
+          // Autocomplete field
+          $('input.form-autocomplete:not([value])', wrapper)
+            .filter(':first')
+            .val(selection[nid]);
+          // Select field
+          $('select', wrapper).val(nid);
+          // Radio field
+          $('input:radio[value='+ nid + '], input:checkbox[value='+ nid +']', wrapper).attr('checked', 'checked');
+        }
+      });
+    });
+  });
+}
+
+/**
+ * Helper function to extract the references values
+ */
+function noderef_view_get_selection() {
+  var cookies = document.cookie.split(';'), selection = {};
+  for(var i = 0; i < cookies.length; i++) {
+    var cookie = $.trim(cookies[i]).split('=');
+    if (cookie[0].indexOf('noderef[') == 0) {
+      var nid = cookie[0].replace(/noderef\[(\d+)\]/, "$1");
+      var title = decodeURIComponent(cookie[1]);
+      selection[nid] = title;
+    }
+  }
+  return selection;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/noderef_view.module	Fri Jan 23 14:52:03 2009 +0100
@@ -0,0 +1,160 @@
+<?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 view définissant les nodes autorisés a été définie
+ * un lien 'Search' affichant la view dans une popup (via le module Popups API),
+ * permettant de choisir les nodes à mettre dans le champ en disposant de la
+ * puissance des 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') {
+    list($link, $id) = _noderef_view_get_link($field);
+    if (!empty($link)) {
+      $form[$key]['#prefix'] .= "<div id='noderef_view_link_{$id}'>";
+      $form[$key]['#suffix'] = $link .'</div>'. $form[$key]['#suffix'];
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+ * 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) {
+  static $id = 0;
+  $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)) {
+    $id++;
+    popups_add_popups();
+    $options = array(
+      'attributes' => array(
+        'class' => 'popups noderef_view_link',
+        'rel'   => 'noderef_view_link_'. $id),
+      'query' => array('destination' => 'node')
+    );
+    $path = l(t('Search'), $path, $options);
+  }
+  return array($path, $id);
+}
+