franck@0: array( franck@9: 'description' => t('Add selected values to field'), franck@0: 'type' => 'node', franck@0: 'configurable' => FALSE, franck@0: 'hooks' => array( franck@0: 'nodeapi' => array() franck@0: ) franck@0: ) franck@0: ); franck@0: } franck@0: franck@0: /** franck@0: * Implémentation concrète de l'action de selection. franck@0: * franck@0: * On vide toute eventuelle selection précédente, puis on passe dans le cookie franck@0: * les informations sur la selection qui a été faite. franck@0: */ franck@0: function noderef_view_select($node, $context) { franck@0: static $count = 0; franck@0: if ($count == 0 && is_array($_COOKIE['noderef'])) { franck@0: // Reset the cookies franck@0: $before = time() - 300; franck@0: foreach($_COOKIE['noderef'] as $id => $val) { franck@0: setcookie('noderef['. $id .']', 0, $before, '/'); franck@0: } franck@0: } franck@0: $count++; franck@0: $five = time() + 300; franck@0: setrawcookie('noderef['. $node->nid .']', rawurlencode($node->title), $five, '/'); franck@11: drupal_set_message(t('!title added to selection', franck@11: array('!title' => $node->title))); franck@0: } franck@0: franck@0: /** franck@0: * Implémentation de hook_form_alter(). franck@0: * franck@0: * On parcoure tous les formulaires à la recherche d'éventuels champs franck@0: * de type "Node Reference" sur lesquels appliqués nos transformations. franck@0: */ franck@0: function noderef_view_form_alter(&$form, $form_state, $form_id) { franck@0: if (isset($form['type']) && $form_id == $form['type']['#value'] .'_node_form') { franck@0: // That's a node form, get the fields and alter the form if needed franck@0: $fields = content_fields(); franck@11: $alter = _noderef_view_walk_form($form, $fields, $form); franck@0: if ($alter) { franck@0: // We've changed the form, add the JS-behavior and Views CSS franck@0: // (the latter to deal with exposed filters in the popup) franck@6: $path = drupal_get_path('module', 'noderef_view'); franck@6: drupal_add_js($path .'/noderef_view.js'); franck@6: drupal_add_css($path .'/noderef_view.css'); franck@0: drupal_add_css(drupal_get_path('module', 'views') .'/css/views.css'); franck@0: } franck@0: } franck@0: elseif ($form_id == 'views_exposed_form' && isset($_GET['destination'])) { franck@0: // Views "Exposed Filter" forms doesn't preserve destination by default. franck@0: $form['destination'] = array( franck@0: '#type' => 'hidden', franck@0: '#value' => $_GET['destination'] franck@0: ); franck@0: } franck@0: } franck@0: franck@0: /** franck@0: * Parcoure le tableau contenant le formulaire à la recherche franck@0: * d'élement à modifier. franck@0: * @return franck@0: * TRUE si un élement a été modifié, FALSE sinon franck@0: */ franck@11: function _noderef_view_walk_form(&$form, $fields, $items) { franck@0: $alter = FALSE; franck@11: foreach($items as $key => $item) { franck@0: if (is_array($item)) { franck@0: if (isset($fields[$key])) { franck@0: $alter |= noderef_view_alter_item($form, $key, $fields[$key]); franck@0: } franck@0: else { franck@11: $alter |= _noderef_view_walk_form($form, $fields, $item); franck@0: } franck@0: } franck@0: } franck@0: return $alter; franck@0: } franck@0: franck@0: /** franck@0: * Modification d'un élement en particulier du formulaire. franck@0: * franck@0: * @return franck@0: * TRUE si l'element a été modifié, FALSE sinon. franck@0: */ franck@0: function noderef_view_alter_item(&$form, $key, $field) { franck@0: if (is_array($field) && $field['type'] == 'nodereference') { franck@2: $link = _noderef_view_get_link($field); franck@0: if (!empty($link)) { franck@0: return TRUE; franck@0: } franck@0: } franck@0: return FALSE; franck@0: } franck@0: franck@0: /** franck@0: * Création d'un lien vers une éventuelle vue associé au champ. franck@0: * franck@0: * @return franck@0: * - Un lien vers la vue si une vue est associée franck@0: * - Une chaine vide sinon franck@11: */ franck@0: function _noderef_view_get_link($field) { franck@0: $path = ''; franck@0: // Check if there's a view associated with this field franck@0: if (isset($field['advanced_view']) && $field['advanced_view'] !== '--') { franck@0: $view = views_get_view($field['advanced_view']); franck@0: // Try to find a path for this view, looking at the displays franck@13: if (!is_array($view->display)) { franck@13: return ''; franck@13: } franck@0: $path = ''; franck@0: foreach($view->display as $display) { franck@0: if (is_array($display->display_options) franck@0: && isset($display->display_options['path'])) { franck@0: $path = $display->display_options['path']; franck@2: break; franck@0: } franck@0: } franck@0: } franck@0: // If we found a view with a suitable display, then link to it franck@0: if (!empty($path)) { franck@0: popups_add_popups(); franck@0: $options = array( franck@12: 'attributes' => array('class' => 'popups-form-noupdate noderef_view_link'), franck@0: 'query' => array('destination' => 'node') franck@0: ); franck@0: $path = l(t('Search'), $path, $options); franck@0: } franck@2: return $path; franck@0: } franck@0: franck@11: function noderef_view_theme() { franck@11: return array( franck@11: 'noderef_view_autocomplete' => array( franck@11: 'arguments' => array('element' => NULL) franck@11: ) franck@11: ); franck@11: } franck@11: franck@11: function noderef_view_widget_info() { franck@11: return array( franck@11: 'noderef_view_autocomplete' => array( franck@11: 'label' => t('Autocomplete text field with View'), franck@11: 'field types' => array('nodereference'), franck@11: 'multiple values' => CONTENT_HANDLE_CORE, franck@11: 'callbacks' => array( franck@11: 'default value' => CONTENT_CALLBACK_DEFAULT, franck@11: ), franck@11: ), franck@11: ); franck@11: } franck@11: franck@11: function noderef_view_elements() { franck@11: return array( franck@11: 'noderef_view_autocomplete' => array( franck@11: '#input' => TRUE, franck@11: '#columns' => array('name'), '#delta' => 0, franck@11: '#process' => array('noderef_view_autocomplete_process'), franck@11: '#autocomplete_path' => FALSE, franck@11: ), franck@11: ); franck@11: } franck@11: franck@11: function noderef_view_widget(&$form, &$form_state, $field, $items, $delta = 0) { franck@11: switch ($field['widget']['type']) { franck@11: case 'noderef_view_autocomplete': franck@11: $element = array( franck@11: '#type' => 'noderef_view_autocomplete', franck@11: '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL, franck@11: '#value_callback' => 'nodereference_autocomplete_value', franck@11: ); franck@11: break; franck@11: } franck@11: return $element; franck@11: } franck@11: franck@11: /** franck@11: * Process an individual element. franck@11: * franck@11: * Build the form element. When creating a form using FAPI #process, franck@11: * note that $element['#value'] is already set. franck@11: * franck@11: */ franck@11: function noderef_view_autocomplete_process($element, $edit, $form_state, $form) { franck@11: // The nodereference autocomplete widget doesn't need to create its own franck@11: // element, it can wrap around the text_textfield element and add an autocomplete franck@11: // path and some extra processing to it. franck@11: // Add a validation step where the value can be unwrapped. franck@11: $fields = content_fields(); franck@11: $link = _noderef_view_get_link($fields[$element['#field_name']]); franck@11: $field_key = $element['#columns'][0]; franck@11: $element[$field_key] = array( franck@11: '#type' => 'text_textfield', franck@11: '#default_value' => isset($element['#value']) ? $element['#value'] : '', franck@11: '#autocomplete_path' => 'nodereference/autocomplete/'. $element['#field_name'], franck@11: // The following values were set by the content module and need franck@11: // to be passed down to the nested element. franck@11: '#title' => $element['#title'], franck@11: '#required' => $element['#required'], franck@11: '#description' => $element['#description'], franck@11: '#field_name' => $element['#field_name'], franck@11: '#type_name' => $element['#type_name'], franck@11: '#delta' => $element['#delta'], franck@11: '#columns' => $element['#columns'], franck@11: ); franck@11: if ($link) { franck@11: $element[$field_key]['#noderef_view_link'] = $link; franck@11: $element[$field_key]['#prefix'] = "
"; franck@11: $element[$field_key]['#suffix'] = $link ."
"; franck@11: } franck@11: if (empty($element[$field_key]['#element_validate'])) { franck@11: $element[$field_key]['#element_validate'] = array(); franck@11: } franck@11: array_unshift($element[$field_key]['#element_validate'], 'nodereference_autocomplete_validate'); franck@11: franck@11: // Used so that hook_field('validate') knows where to flag an error. franck@11: $element['_error_element'] = array( franck@11: '#type' => 'value', franck@11: // Wrapping the element around a text_textfield element creates a franck@11: // nested element, so the final id will look like 'field-name-0-nid-nid'. franck@11: '#value' => implode('][', array_merge($element['#parents'], array($field_key, $field_key))), franck@11: ); franck@11: return $element; franck@11: } franck@11: franck@11: function theme_noderef_view_autocomplete($element) { franck@11: return << franck@11: {$element['#children']} franck@11: {$element['#noderef_view_link']} franck@11: franck@11: franck@11: EOT; franck@11: }