/[drupal]/contributions/modules/revisionreference/revisionreference.module
ViewVC logotype

Diff of /contributions/modules/revisionreference/revisionreference.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.1.2.1, Sun Feb 24 00:28:59 2008 UTC revision 1.1.2.2, Thu Jun 19 21:16:35 2008 UTC
# Line 0  Line 1 
1    <?php
2    // $Id: revisionreference.module 118 2008-06-03 23:40:41Z danielb $
3    
4    /**
5     * @file
6     * Defines a field type for referencing a node revision from a node.
7     */
8    
9    /**
10     * Implementation of hook_menu().
11     */
12    function revisionreference_menu() {
13      $items = array();
14      $items['revisionreference/autocomplete'] = array(
15        'title' => 'revisionreference autocomplete',
16        'page callback' => 'revisionreference_autocomplete',
17        'access arguments' => array('access content'),
18        'type' => MENU_CALLBACK,
19      );
20      return $items;
21    }
22    
23    /**
24     * Implementation of hook_theme().
25     */
26    function revisionreference_theme() {
27      return array(
28        'revisionreference_item_simple' => array(
29          'arguments' => array('item' => NULL),
30        ),
31        'revisionreference_item_advanced' => array(
32          'arguments' => array('item' => NULL, 'view' => NULL),
33        ),
34        'revisionreference_select' => array(
35          'arguments' => array('element' => NULL),
36        ),
37        'revisionreference_autocomplete' => array(
38          'arguments' => array('element' => NULL),
39        ),
40        'revisionreference_formatter_default' => array(
41          'arguments' => array('element'),
42        ),
43        'revisionreference_formatter_plain' => array(
44          'arguments' => array('element'),
45        ),
46        'revisionreference_formatter_full' => array(
47          'arguments' => array('element'),
48          'function' => 'theme_revisionreference_formatter_full_teaser',
49        ),
50        'revisionreference_formatter_teaser' => array(
51          'arguments' => array('element'),
52          'function' => 'theme_revisionreference_formatter_full_teaser',
53        ),
54      );
55    }
56    
57    /**
58     * Implementation of hook_field_info().
59     *
60     * Here we indicate that the content module will use its default
61     * handling for the view of this field.
62     *
63     * Callbacks can be omitted if default handing is used.
64     * They're included here just so this module can be used
65     * as an example for custom modules that might do things
66     * differently.
67     */
68    function revisionreference_field_info() {
69      return array(
70        'revisionreference' => array(
71          'label' => t('Node revision reference'),
72          'description' => t('Store the ID of a node revision as an integer value.'),
73          'callbacks' => array(
74            'tables' => CONTENT_CALLBACK_DEFAULT,
75            'arguments' => CONTENT_CALLBACK_DEFAULT,
76            ),
77          ),
78      );
79    }
80    
81    /**
82     * Implementation of hook_field_settings().
83     */
84    function revisionreference_field_settings($op, $field) {
85      switch ($op) {
86        case 'form':
87          $form = array();
88          $form['referenceable_revision_types'] = array(
89            '#type' => 'checkboxes',
90            '#title' => t('Content types that can be referenced'),
91            '#multiple' => TRUE,
92            '#default_value' => is_array($field['referenceable_revision_types']) ? $field['referenceable_revision_types'] : array(),
93            '#options' => node_get_types('names'),
94          );
95          if (module_exists('views')) {
96            $views = array('--' => '--');
97            $all_views = views_get_all_views();
98            foreach ($all_views as $view) {
99              // Only views that have fields will work for our purpose.
100              if (!empty($view->display['default']->display_options['fields'])) {
101                $views[t('Existing Views')][$view->name] = $view->name;
102              }
103            }
104    
105            if (count($views) > 1) {
106              $form['advanced_revision'] = array(
107                 '#type' => 'fieldset',
108                 '#title' => t('Advanced - Nodes that can be referenced (View)'),
109                 '#collapsible' => TRUE,
110                 '#collapsed' => !isset($field['advanced_view']) || $field['advanced_view'] == '--',
111               );
112              $form['advanced_revision']['advanced_revision_view'] = array(
113                '#type' => 'select',
114                '#title' => t('View'),
115                '#options' => $views,
116                '#default_value' => isset($field['advanced_revision_view']) ? $field['advanced_revision_view'] : '--',
117                '#description' => t('Choose the "Views module" view that selects the nodes that can be referenced.<br />Note :<ul><li>Only views that have fields will work for this purpose.</li><li>This will discard the "Content types" settings above. Use the view\'s "filters" section instead.</li><li>Use the view\'s "fields" section to display additional informations about candidate nodes on node creation/edition form.</li><li>Use the view\'s "sort criteria" section to determine the order in which candidate nodes will be displayed.</li></ul>'),
118              );
119              $form['advanced_revision']['advanced_revision_view_args'] = array(
120                '#type' => 'textfield',
121                '#title' => t('View arguments'),
122                '#default_value' => isset($field['advanced_revision_view_args']) ? $field['advanced_revision_view_args'] : '',
123                '#required' => FALSE,
124                '#description' => t('Provide a comma separated list of arguments to pass to the view.'),
125              );
126            }
127          }
128          return $form;
129    
130        case 'save':
131          $settings = array('referenceable_revision_types');
132          if (module_exists('views')) {
133            $settings[] = 'advanced_revision_view';
134            $settings[] = 'advanced_revision_view_args';
135          }
136          return $settings;
137    
138        case 'database columns':
139          $columns = array(
140            'vid' => array('type' => 'int', 'unsigned' => TRUE, 'not null' => FALSE),
141          );
142          return $columns;
143    
144        case 'views data':
145          $data = content_views_field_views_data($field);
146          $db_info = content_database_info($field);
147          $table_alias = content_views_tablename($field);
148    
149          // Swap the filter handler to the 'in' operator.
150          $data[$table_alias][$field['field_name'] .'_vid']['filter']['handler'] = 'views_handler_filter_many_to_one_content';
151    
152          // Add a relationship for related node revision.
153          $data[$table_alias][$field['field_name'] .'_vid']['relationship'] = array(
154            'base' => 'node_revisions',
155            'field' => $db_info['columns']['vid']['column'],
156            'handler' => 'views_handler_relationship',
157          );
158          return $data;
159      }
160    }
161    
162    /**
163     * Implementation of hook_field().
164     */
165    function revisionreference_field($op, &$node, $field, &$items, $teaser, $page) {
166      switch ($op) {
167        case 'validate':
168          $refs = _revisionreference_potential_references($field, TRUE);
169          foreach ($items as $delta => $item) {
170            if (is_array($item) && !empty($item['error_field'])) {
171              $error_field = $item['error_field'];
172              unset($item['error_field']);
173              if (!empty($item['vid'])) {
174                if (!in_array($item['vid'], array_keys($refs))) {
175                  form_set_error($error_field, t("%name : This post can't be referenced.", array('%name' => t($field['widget']['label']))));
176                }
177              }
178            }
179          }
180          return $items;
181      }
182    }
183    
184    /**
185     * Implementation of hook_content_is_empty().
186     */
187    function revisionreference_content_is_empty($item, $field) {
188      if (empty($item['vid'])) {
189        return TRUE;
190      }
191      return FALSE;
192    }
193    
194    /**
195     * Implementation of hook_field_formatter_info().
196     */
197    function revisionreference_field_formatter_info() {
198      return array(
199        'default' => array(
200          'label' => t('Title (link)'),
201          'field types' => array('revisionreference'),
202          'multiple values' => CONTENT_HANDLE_CORE,
203        ),
204        'plain' => array(
205          'label' => t('Title (no link)'),
206          'field types' => array('revisionreference'),
207          'multiple values' => CONTENT_HANDLE_CORE,
208        ),
209        'full' => array(
210          'label' => t('Full node'),
211          'field types' => array('revisionreference'),
212          'multiple values' => CONTENT_HANDLE_CORE,
213        ),
214        'teaser' => array(
215          'label' => t('Teaser'),
216          'field types' => array('revisionreference'),
217          'multiple values' => CONTENT_HANDLE_CORE,
218        ),
219      );
220    }
221    
222    /**
223     * Theme function for 'default' revisionreference field formatter.
224     */
225    function theme_revisionreference_formatter_default($element) {
226      $output = '';
227      if (!empty($element['#item']['vid']) && is_numeric($element['#item']['vid']) && ($title = _revisionreference_titles($element['#item']['vid']))) {
228        //$revision = node_load(array('vid' => $element['#item']['vid']));
229        $nid = revisionreference_nid_from_vid($element['#item']['vid']);
230        if (revisionreference_vid_is_current($element['#item']['vid'], $nid)) {
231          $output = l($title, 'node/'. $nid);
232        }
233        else {
234          $output = l($title, 'node/'. $nid .'/revisions/'. $element['#item']['vid'] .'/view');
235        }
236      }
237      return $output;
238    }
239    
240    /**
241     * Theme function for 'plain' revisionreference field formatter.
242     */
243    function theme_revisionreference_formatter_plain($element) {
244      $output = '';
245      if (!empty($element['#item']['vid']) && is_numeric($element['#item']['vid']) && ($title = _revisionreference_titles($element['#item']['vid']))) {
246        $output = check_plain($title);
247      }
248      return $output;
249    }
250    
251    /**
252     * Proxy theme function for 'full' and 'teaser' revisionreference field formatters.
253     */
254    function theme_revisionreference_formatter_full_teaser($element) {
255      static $recursion_queue = array();
256      $output = '';
257      if (!empty($element['#item']['vid']) && is_numeric($element['#item']['vid'])) {
258        // If no 'referencing node' is set, we are starting a new 'reference thread'
259        if (!isset($node->referencing_node)) {
260          $recursion_queue = array();
261        }
262        $recursion_queue[] = $node->vid;
263        if (in_array($element['#item']['vid'], $recursion_queue)) {
264          // Prevent infinite recursion caused by reference cycles :
265          // if the node has already been rendered earlier in this 'thread',
266          // we fall back to 'default' (node title) formatter.
267          return theme('revisionreference_formatter_default', $element);
268        }
269        if ($referenced_node = node_load(array('vid' => $element['#item']['vid']))) {
270          $referenced_node->referencing_node = $node;
271          $referenced_node->referencing_field = $field;
272          _revisionreference_titles($element['#item']['vid'], $referenced_node->title);
273          $output = node_view($referenced_node, $element['#formatter'] == 'teaser');
274        }
275      }
276      return $output;
277    }
278    
279    /**
280     * Helper function for formatters.
281     *
282     * Store node titles collected in the curent request.
283     */
284    function _revisionreference_titles($vid, $known_title = NULL) {
285      static $titles = array();
286      if (!isset($titles[$vid])) {
287        $title = $known_title ? $known_title : db_result(db_query("SELECT title FROM {node_revisions} WHERE vid=%d", $vid));
288        $titles[$vid] = $title ? $title : '';
289      }
290      return $titles[$vid];
291    }
292    
293    /**
294     * Implementation of hook_widget_info().
295     *
296     * We need custom handling of multiple values for the revisionreference_select
297     * widget because we need to combine them into a options list rather
298     * than display multiple elements.
299     *
300     * We will use the content module's default handling for default value.
301     *
302     * Callbacks can be omitted if default handing is used.
303     * They're included here just so this module can be used
304     * as an example for custom modules that might do things
305     * differently.
306     */
307    function revisionreference_widget_info() {
308      return array(
309        'revisionreference_select' => array(
310          'label' => t('Select list'),
311          'field types' => array('revisionreference'),
312          'multiple values' => CONTENT_HANDLE_MODULE,
313          'callbacks' => array(
314            'default value' => CONTENT_CALLBACK_DEFAULT,
315          ),
316        ),
317        'revisionreference_autocomplete' => array(
318          'label' => t('Autocomplete text field'),
319          'field types' => array('revisionreference'),
320          'multiple values' => CONTENT_HANDLE_CORE,
321          'callbacks' => array(
322            'default value' => CONTENT_CALLBACK_DEFAULT,
323          ),
324        ),
325      );
326    }
327    
328    /**
329     * Implementation of FAPI hook_elements().
330     *
331     * Any FAPI callbacks needed for individual widgets can be declared here,
332     * and the element will be passed to those callbacks for processing.
333     *
334     * Drupal will automatically theme the element using a theme with
335     * the same name as the hook_elements key.
336     *
337     * Autocomplete_path is not used by text_widget but other widgets can use it
338     * (see revisionreference and userreference).
339     */
340    function revisionreference_elements() {
341      return array(
342        'revisionreference_select' => array(
343          '#input' => TRUE,
344          '#columns' => array('uid'), '#delta' => 0,
345          '#process' => array('revisionreference_select_process'),
346          ),
347        'revisionreference_autocomplete' => array(
348          '#input' => TRUE,
349          '#columns' => array('name'), '#delta' => 0,
350          '#process' => array('revisionreference_autocomplete_process'),
351          '#autocomplete_path' => FALSE,
352          ),
353        );
354    }
355    
356    /**
357     * Implementation of hook_widget().
358     *
359     * Attach a single form element to the form. It will be built out and
360     * validated in the callback(s) listed in hook_elements. We build it
361     * out in the callbacks rather than here in hook_widget so it can be
362     * plugged into any module that can provide it with valid
363     * $field information.
364     *
365     * Content module will set the weight, field name and delta values
366     * for each form element. This is a change from earlier CCK versions
367     * where the widget managed its own multiple values.
368     *
369     * If there are multiple values for this field, the content module will
370     * call this function as many times as needed.
371     *
372     * @param $form
373     *   the entire form array, $form['#node'] holds node information
374     * @param $form_state
375     *   the form_state, $form_state['values'][$field['field_name']]
376     *   holds the field's form values.
377     * @param $field
378     *   the field array
379     * @param $items
380     *   array of default values for this field
381     * @param $delta
382     *   the order of this item in the array of subelements (0, 1, 2, etc)
383     *
384     * @return
385     *   the form item for a single element for this field
386     */
387    function revisionreference_widget(&$form, &$form_state, $field, $items, $delta = 0) {
388      switch ($field['widget']['type']) {
389        case 'revisionreference_select':
390          $element = array(
391            '#type' => 'revisionreference_select',
392            '#default_value' => $items,
393          );
394          break;
395    
396        case 'revisionreference_autocomplete':
397          $element = array(
398            '#type' => 'revisionreference_autocomplete',
399            '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL,
400            '#value_callback' => 'revisionreference_autocomplete_value',
401          );
402          break;
403      }
404      return $element;
405    }
406    
407    /**
408     * Value for a revisionreference autocomplete element.
409     *
410     * Substitute in the node title for the node vid.
411     */
412    function revisionreference_autocomplete_value($element, $edit = FALSE) {
413      $field_key  = $element['#columns'][0];
414      if (!empty($element['#default_value'][$field_key])) {
415        $vid = $element['#default_value'][$field_key];
416    
417        $row = db_fetch_object(db_query(db_rewrite_sql("
418          SELECT r.nid, r.timestamp, r.title, u.name AS user
419          FROM {node_revisions} r
420          LEFT JOIN {users} u ON r.uid = u.uid
421          WHERE r.vid = %d"), $vid));
422    
423        $current = revisionreference_vid_is_current($row->vid, $row->nid);
424        $value = $row->title .' [nid:'. $row->nid .'] '. ($current ? '(CUR) ' : '') . date('m/d/Y h:m', $row->timestamp) .' by '. $row->user .' [vid:'. $vid .']';
425        return array($field_key => $value);
426      }
427      return array($field_key => NULL);
428    }
429    
430    /**
431     * Process an individual element.
432     *
433     * Build the form element. When creating a form using FAPI #process,
434     * note that $element['#value'] is already set.
435     *
436     * The $fields array is in $form['#field_info'][$element['#field_name']].
437     */
438    function revisionreference_select_process($element, $edit, $form_state, $form) {
439      // The revisionreference_select widget doesn't need to create its own
440      // element, it can wrap around the optionwidgets_select element.
441      // Add a validation step where the value can be unwrapped.
442      $field_key  = $element['#columns'][0];
443      $element[$field_key] = array(
444        '#type' => 'optionwidgets_select',
445        '#default_value' => isset($element['#value']) ? $element['#value'] : '',
446        '#element_validate' => array('optionwidgets_validate', 'revisionreference_select_validate'),
447    
448        // The following values were set by the content module and need
449        // to be passed down to the nested element.
450        '#field_name' => $element['#field_name'],
451        '#delta' => $element['#delta'],
452        '#columns' => $element['#columns'],
453        '#title' => $element['#title'],
454        '#required' => $element['#required'],
455        '#description' => $element['#description'],
456      );
457      return $element;
458    }
459    
460    /**
461     * Process an individual element.
462     *
463     * Build the form element. When creating a form using FAPI #process,
464     * note that $element['#value'] is already set.
465     *
466     */
467    function revisionreference_autocomplete_process($element, $edit, $form_state, $form) {
468      // The revisionreference autocomplete widget doesn't need to create its own
469      // element, it can wrap around the text_textfield element and add an autocomplete
470      // path and some extra processing to it.
471      // Add a validation step where the value can be unwrapped.
472      $field_key = $element['#columns'][0];
473    
474      $element[$field_key] = array(
475        '#type' => 'text_textfield',
476        '#default_value' => isset($element['#value']) ? $element['#value'] : '',
477        '#autocomplete_path' => 'revisionreference/autocomplete/'. $element['#field_name'],
478        '#element_validate' => array('revisionreference_autocomplete_validate'),
479    
480        // The following values were set by the content module and need
481        // to be passed down to the nested element.
482        '#field_name' => $element['#field_name'],
483        '#delta' => $element['#delta'],
484        '#columns' => $element['#columns'],
485        '#title' => $element['#title'],
486        '#required' => $element['#required'],
487        '#description' => $element['#description'],
488      );
489      return $element;
490    }
491    
492    /**
493     * Validate an select element.
494     *
495     * Remove the wrapper layer and set the right element's value.
496     * We don't know exactly where this element is, so we drill down
497     * through the element until we get to our key.
498     */
499    function revisionreference_select_validate($element, &$form_state) {
500      $field_key  = $element['#columns'][0];
501      $new_parents = array();
502      $value = $form_state['values'];
503      foreach ($element['#parents'] as $parent) {
504        $value = $value[$parent];
505        if ($parent == $field_key) {
506          $element['#parents'] = $new_parents;
507          form_set_value($element, $value, $form_state);
508          break;
509        }
510        $new_parents[] = $parent;
511      }
512    }
513    
514    /**
515     * Validate an autocomplete element.
516     *
517     * Remove the wrapper layer and set the right element's value.
518     */
519    function revisionreference_autocomplete_validate($element, &$form_state) {
520      $field_name = $element['#field_name'];
521      $field = content_fields($field_name);
522      $field_key  = $element['#columns'][0];
523      $delta = $element['#delta'];
524      $value = $element['#value'][$field_key];
525      $vid = NULL;
526      if (!empty($value)) {
527        preg_match('/^(?:\s*|(.*) )?\[\s*vid\s*:\s*(\d+)\s*\]$/', $value, $matches);
528        if (!empty($matches)) {
529          // explicit vid
530          list(, $text, $vid) = $matches;
531          $title = explode(' [nid:', $text);
532          $title = $title[0];
533          if (!empty($title) && ($n = node_load(array('vid' => $vid))) && $title != $n->title) {
534            form_set_error($element[$field_key], t('%name: Title mismatch. Please check your selection.'), array('%name' => t($element[$field_key]['#title'])));
535          }
536        }
537        else {
538          // no explicit vid
539          // TODO :
540          // the best thing would be to present the user with an additional form,
541          // allowing the user to choose between valid candidates with the same title
542          // ATM, we pick the first matching candidate...
543          $vids = _revisionreference_potential_references($field, FALSE, $value, TRUE);
544          $vid = (!empty($vids)) ? array_shift(array_keys($vids)) : 0;
545        }
546      }
547      form_set_value($element, $vid, $form_state);
548      return $element;
549    }
550    
551    /**
552     * Implementation of hook_allowed_values().
553     */
554    function revisionreference_allowed_values($field) {
555      $options = _revisionreference_potential_references($field, TRUE);
556      foreach ($options as $key => $value) {
557        $options[$key] = _revisionreference_item($field, $value);
558      }
559      if (!$field['required']) {
560        $options = array(0 => '<'. t('none') .'>') + $options;
561      }
562      return $options;
563    }
564    
565    /**
566     * Fetch an array of all candidate referenced nodes,
567     * for use in presenting the selection form to the user.
568     */
569    function _revisionreference_potential_references($field, $return_full_nodes = FALSE, $string = '', $exact_string = false) {
570      if (module_exists('views')
571      && !empty($field['advanced_revision_view'])
572      && $field['advanced_revision_view'] != '--'
573      && ($view = revisionreference_get_view($field, $string, $exact_string))) {
574        // advanced field : referenceable nodes defined by a view
575        // let views.module build the query
576        $options = array();
577        foreach ($view->result as $item) {
578          $options[$item->vid] = _revisionreference_item($field, $item);
579        }
580        return $options;
581      }
582      else {
583        // standard field : referenceable nodes defined by content types
584        // build the appropriate query
585        $related_types = array();
586        $args = array();
587    
588        if (is_array($field['referenceable_revision_types'])) {
589          foreach ($field['referenceable_revision_types'] as $related_type) {
590            if ($related_type) {
591              $related_types[] = " n.type = '%s'";
592              $args[] = $related_type;
593            }
594          }
595        }
596    
597        $related_clause = implode(' OR ', $related_types);
598    
599        if (!count($related_types)) {
600          return array();
601        }
602    
603        if (isset($string)) {
604          $string_clause = $exact_string ? " AND r.title = '%s'" : " AND r.title LIKE '%%%s%'";
605          $related_clause = "(". $related_clause .")". $string_clause;
606          $args[] = $string;
607        }
608    
609        $result = db_query(db_rewrite_sql("
610          SELECT r.vid, r.nid, r.timestamp, r.title AS node_title, n.type AS node_type, u.name AS user
611          FROM {node_revisions} r
612          LEFT JOIN {node} n ON r.nid = n.nid
613          LEFT JOIN {users} u ON r.uid = u.uid
614          WHERE ". $related_clause ."
615          ORDER BY n.title, n.vid"), $args);
616      }
617    
618      $rows = array();
619    
620      while ($node = db_fetch_object($result)) {
621        if ($return_full_nodes) {
622          $rows[$node->vid] = $node;
623        }
624        else {
625          $rows[$node->vid] = $node->node_title;
626        }
627      }
628    
629      /* To Do: 2nd query to select nodes that match the nid of selected nodes but have vids that don't match already selected vids */
630      return $rows;
631    }
632    
633    /**
634     * Build a revisionreference view.
635     *
636     * Keep the rendered view in a static variable so it isn't
637     * re-rendered more than one in a session, as when getting
638     * a list of potential references and then running each of
639     * them through the theme.
640     *
641     * If $string or $exact_string change, we'll need a new query,
642     * so in that case we need to refresh the view.
643     */
644    function revisionreference_get_view($field, $string = '', $exact_string = false) {
645      static $view = NULL, $prev_string, $prev_exact_string;
646      $view_name = $field['advanced_revision_view'];
647      if (module_exists('views')
648      && !empty($view_name)
649      && $view_name != '--'
650      && (!isset($view) || $view->name != $view_name || $prev_string != $string || $prev_exact_string != $exact_string)) {
651        $prev_string = $string;
652        $prev_exact_string = $exact_string;
653        $view = views_get_view($view_name);
654        $view->init();
655    
656        // TODO is this the right way to do this?
657        // make sure the fields get included in the query.
658    
659        // TODO Which display should we use here?
660        // In our Views 1 to Views 2 updates we are
661        // putting fields in the 'default' display.
662        $display = 'default';
663        $view->init_display($display);
664        $view->display[$display]->style_plugin = 'list';
665        $view->display[$display]->row_plugin = 'fields';
666        $view->display_handler->set_option('use_pager', FALSE);
667        $view->display_handler->set_option('items_per_page', 0);
668    
669        // Get arguments for the view.
670        if (isset($field['advanced_revision_view_args'])) {
671          // TODO: Support Tokens using token.module ?
672          $view_args = array();
673          $view_args = array_map('trim', explode(',', $field['advanced_revision_view_args']));
674        }
675        else {
676          $view_args = array();
677        }
678    
679        //We do need title field, so add it if not present (unlikely, but...)
680        if (!array_key_exists('title', $view->display[$display]->display_options['fields'])) {
681          $view->add_item($display, 'field', 'node', 'title');
682        }
683        if (!empty($string)) {
684          // We use the title filter in the view, so make sure it's there.
685          if (!array_key_exists('title', $view->display[$display]->display_options['filters'])) {
686            $view->add_item($display, 'filter', 'node', 'title');
687          }
688          // TODO Is this the best way to set values?
689          $view->display[$display]->display_options['filters']['title']['value'] = $string;
690          $view->display[$display]->display_options['filters']['title']['operator'] = $exact_string ? '=' : 'contains';
691        }
692    
693        // Make sure the query is not cached
694        $view->is_cacheable = FALSE;
695        $view->execute_display($display, $view_args);
696      }
697      return $view;
698    
699    }
700    
701    /**
702     * Retrieve a pipe delimited string of autocomplete suggestions
703     */
704    function revisionreference_autocomplete($field_name, $string = '') {
705      $fields = content_fields();
706      $field = $fields[$field_name];
707      $matches = array();
708    
709      $references = _revisionreference_potential_references($field, TRUE, $string);
710      foreach ($references as $row) {
711        $current = revisionreference_vid_is_current($row->vid, $row->nid);
712        $matches[$row->node_title .' [nid:'. $row->nid .'] '. ($current ? '(CUR) ' : '') . date('m/d/Y h:m', $row->timestamp) .' by '. $row->user .' [vid:'. $row->vid .']'] = _revisionreference_item($field, $row);
713      }
714      drupal_json($matches);
715    }
716    
717    function _revisionreference_item($field, $item, $html = FALSE) {
718      if (module_exists('views') && isset($field['advanced_revision_view']) && $field['advanced_revision_view'] != '--' && ($view = revisionreference_get_view($field))) {
719        $field_names = array();
720        foreach ($view->field as $name => $viewfield) {
721          $field_names[] = isset($viewfield->definition['content_field_name']) ? $viewfield->definition['content_field_name'] : $name;
722        }
723        $output = theme('revisionreference_item_advanced', $item, $field_names, $view);
724        if (!$html) {
725          // Views theming runs check_plain (htmlentities) on the values.
726          // We reverse that with html_entity_decode.
727          $output = html_entity_decode(strip_tags($output), ENT_QUOTES);
728        }
729      }
730      else {
731        $output = theme('revisionreference_item_simple', $item);
732        $output = $html ? check_plain($output) : $output;
733      }
734      return $output;
735    }
736    
737    function theme_revisionreference_item_advanced($item, $field_names, $view) {
738      $item_fields = array();
739      $item = (array) $item;
740      foreach ($item as $delta => $value) {
741        // remove link tags (ex : for node titles)
742        $value = preg_replace('/<a[^>]*>(.*)<\/a>/iU', '$1', $value);
743        if (!empty($value)) {
744          $item_fields[] = "<span class='view-field view-data-$field_names[$delta]'>$value</span>";;
745        }
746      }
747      $output = implode(' - ', $item_fields);
748      $output = "<span class='view-item view-item-$view->name'>$output</span>";
749      return $output;
750    }
751    
752    function theme_revisionreference_item_simple($item) {
753      $current = revisionreference_vid_is_current($item->vid, $item->nid);
754      return $item->node_title .' [nid:'. $item->nid .'] '. ($current ? '(CUR) ' : '') . date('m/d/Y h:m', $item->timestamp) .' by '. $item->user .' [vid:'. $item->vid .']';
755    }
756    
757    /**
758     * FAPI theme for an individual elements.
759     *
760     * The textfield or select is already rendered by the
761     * textfield or select themes and the html output
762     * lives in $element['#children']. Overvide this theme to
763     * make custom changes to the output.
764     *
765     * $element['#field_name'] contains the field name
766     * $element['#delta]  is the position of this element in the group
767     */
768    function theme_revisionreference_select($element) {
769      return $element['#children'];
770    }
771    
772    function theme_revisionreference_autocomplete($element) {
773      return $element['#children'];
774    }
775    
776    function revisionreference_nid_from_vid($vid) {
777      $nid = db_result(db_query(db_rewrite_sql("SELECT nid from {node_revisions} WHERE vid = %d"), $vid));
778      return $nid;
779    }
780    
781    function revisionreference_vid_is_current($vid, $nid = NULL) {
782      static $max_vid_for_nids = array();
783      if ($nid == NULL) {
784        $nid = revision_nid_from_vid($vid);
785      }
786      if (!isset($max_vid_for_nids[$nid])) {
787        $max_vid_for_nids[$nid] = db_result(db_query(db_rewrite_sql("SELECT MAX(vid) AS vid from {node_revisions} WHERE nid = %d"), $nid));
788      }
789      return ($max_vid_for_nids[$nid] == $vid);
790    }

Legend:
Removed from v.1.1.2.1  
changed lines
  Added in v.1.1.2.2

  ViewVC Help
Powered by ViewVC 1.1.2