Index: userreference.module
===================================================================
--- userreference.module	(revision 35)
+++ userreference.module	(working copy)
@@ -78,10 +78,53 @@
         '#default_value' => isset($field['referenceable_status']) && is_array($field['referenceable_status']) ? array_filter($field['referenceable_status']) : array(1),
         '#options' => array(1 => t('Active'), 0 => t('Blocked')),
       );
+      if (module_exists('views')) {
+        $views = array('--' => '--');
+        $all_views = views_get_all_views();
+        foreach ($all_views as $view) {
+          // Only 'node' views that have fields will work for our purpose.
+          if ($view->base_table == 'users' && !empty($view->display['default']->display_options['fields'])) {
+            if ($view->type == 'Default') {
+              $views[t('Default Views')][$view->name] = $view->name;
+            }
+            else {
+              $views[t('Existing Views')][$view->name] = $view->name;
+            }
+          }
+        }
+
+        if (count($views) > 1) {
+          $form['advanced'] = array(
+             '#type' => 'fieldset',
+             '#title' => t('Advanced - Users that can be referenced (View)'),
+             '#collapsible' => TRUE,
+             '#collapsed' => !isset($field['advanced_view']) || $field['advanced_view'] == '--',
+           );
+          $form['advanced']['advanced_view'] = array(
+            '#type' => 'select',
+            '#title' => t('View used to select the users'),
+            '#options' => $views,
+            '#default_value' => isset($field['advanced_view']) ? $field['advanced_view'] : '--',
+            '#description' => t('Choose the "Views module" view that selects the users that can be referenced.<br />Note:<ul><li>Only views that have fields will work for this purpose.</li><li>This will discard the "Referenceable Roles" and "Referenceable Status" settings above. Use the view\'s "filters" section instead.</li><li>Use the view\'s "fields" section to display additional informations about candidate users on user creation/edition form.</li><li>Use the view\'s "sort criteria" section to determine the order in which candidate users will be displayed.</li></ul>'),
+          );
+          $form['advanced']['advanced_view_args'] = array(
+            '#type' => 'textfield',
+            '#title' => t('View arguments'),
+            '#default_value' => isset($field['advanced_view_args']) ? $field['advanced_view_args'] : '',
+            '#required' => FALSE,
+            '#description' => t('Provide a comma separated list of arguments to pass to the view.'),
+          );
+        }
+      }
       return $form;
 
     case 'save':
-      return array('referenceable_roles', 'referenceable_status');
+			$settings = array('referenceable_roles', 'referenceable_status');
+      if (module_exists('views')) {
+        $settings[] = 'advanced_view';
+        $settings[] = 'advanced_view_args';
+      }			
+			return $settings;
 
     case 'database columns':
       $columns = array(
@@ -462,6 +505,31 @@
  * Fetch an array of all candidate referenced users, for use in presenting the selection form to the user.
  */
 function _userreference_potential_references($field, $string = '', $uid = NULL) {
+  static $results = array();
+
+  if (!isset($results[$field['field_name']][$string][$uid])) {
+    $references = FALSE;
+    if (module_exists('views') && !empty($field['advanced_view']) && $field['advanced_view'] != '--') {
+      $references = _userreference_potential_references_views($field, $string, $uid);
+    }
+    // If the view doesn't exist, we got FALSE, and fallback to the regular 'standard mode'.
+
+    if ($references === FALSE) {
+      $references = _userreference_potential_references_standard($field, $string, $uid);
+    }
+
+    // Store the results.
+    $results[$field['field_name']][$string][$uid] = $references;
+  }
+
+  return $results[$field['field_name']][$string][$uid];
+}
+
+/**
+ * Helper function for _userreference_potential_references():
+ * referenceable users defined by user role and status
+ */
+function _userreference_potential_references_standard($field, $string = '', $uid = NULL) {
   $where = array();
   $args = array();
   $join = array();
@@ -510,6 +578,67 @@
 }
 
 /**
+ * Helper function for _userreference_potential_references():
+ * case of Views-defined referenceable users.
+ */
+function _userreference_potential_references_views($field, $string = '', $uid = NULL) {
+  $view_name = $field['advanced_view'];
+
+  if ($view = views_get_view($view_name)) {
+    // We add a display, and let it derive from the 'default' display.
+    // TODO: We should let the user pick a display in the fields settings - sort of requires AHAH...
+    $display = $view->add_display('userreference_simple');
+    $view->set_display($display);
+
+    // TODO from merlinofchaos on IRC : arguments using summary view can defeat the style setting.
+    // We might also need to check if there's an argument, and set *its* style_plugin as well.
+    $view->display_handler->set_option('style_plugin', 'userreference_php_array');
+    $view->display_handler->set_option('row_plugin', 'fields');
+
+    // Get arguments for the view.
+    if (!empty($field['advanced_view_args'])) {
+      // TODO: Support Tokens using token.module ?
+      $view_args = array_map('trim', explode(',', $field['advanced_view_args']));
+    }
+    else {
+      $view_args = array();
+    }
+
+    // We do need name field, so add it if not present (unlikely, but...)
+    $fields = $view->get_items('field', $display);
+    if (!isset($fields['name'])) {
+      $view->add_item($display, 'field', 'users', 'name');
+    }
+    if ($string !== '') {
+      // Add an instance of the 'name' filter.
+      $options = array('value' => $string, 'operator' => 'starts');
+      $id = $view->add_item($display, 'filter', 'users', 'name', $options);
+    }
+
+    // If not set, make all fields inline and define a separator.
+    $options = $view->display_handler->get_option('row_options');
+    if (empty($options['inline'])) {
+      $options['inline'] = drupal_map_assoc(array_keys($view->get_items('field', $display)));
+    }
+    if (empty($options['separator'])) {
+      $options['separator'] = '-';
+    }
+    $view->display_handler->set_option('row_options', $options);
+
+    // Make sure the query is not cached
+    $view->is_cacheable = FALSE;
+
+    // Get the results.
+    $result = $view->execute_display($display, $view_args);
+  }
+  else {
+    $result = FALSE;
+  }
+	
+  return $result;
+}
+
+/**
  * Provide a list of users to filter on.
  */
 function _userreference_filter_handler($op, $filterinfo) {
@@ -610,4 +739,4 @@
 
 function theme_userreference_autocomplete($element) {
   return $element['#children'];
-}
\ No newline at end of file
+}
Index: userreference.views.inc
===================================================================
--- userreference.views.inc	(revision 0)
+++ userreference.views.inc	(revision 0)
@@ -0,0 +1,110 @@
+<?php
+// $Id: userreference.views.inc,v 1.1.2.3 2008/08/07 21:23:00 yched Exp $
+
+/**
+ * @file
+ * Interface between userreference.module and views.module.
+ */
+function userreference_views_plugins() {
+  $path = drupal_get_path('module', 'userreference');
+  $plugins = array(
+    'module' => 'userreference', // This just tells our themes are elsewhere.
+    'display' => array(
+      'userreference_simple' => array(
+        // Those strings are not translated for now.
+        // We'll need to change that if / when we remove 'no ui'
+        'title' => 'Simple', // TODO: better name ? (currently not displayed anyway)
+        'help' => 'Destination-agnostic display. Mostly useful for programmatic views.',
+        'no ui' => TRUE, // Programmatic use only.
+        'handler' => 'userreference_plugin_display_simple',
+        'uses hook menu' => FALSE,
+        'use ajax' => FALSE,
+        'use pager' => FALSE,
+        'accept attachments' => FALSE,
+      ),
+    ),
+    'style' => array(
+      'userreference_php_array' => array(
+        // Those strings are not translated for now.
+        // We'll need to change that if / when we remove 'no ui'
+        'title' => 'Results array (with title)',
+        'help' => 'Returns the view as a PHP array of names + rendered rows.',
+        'handler' => 'userreference_plugin_style_php_array',
+        'no ui' => TRUE, // Programmatic use only.
+        'uses row plugin' => TRUE,
+        'uses fields' => TRUE,
+        'type' => 'userref',
+        'even empty' => TRUE,
+      ),
+    ),
+  );
+  return $plugins;
+}
+
+/**
+ * Display plugin
+ */
+class userreference_plugin_display_simple extends views_plugin_display {
+  function execute() {
+    return $this->view->render($this->display->id);
+  }
+
+  function render() {
+    return !empty($this->view->result) || !empty($this->view->style_plugin->definition['even empty']) ? $this->view->style_plugin->render($this->view->result) : '';
+  }
+}
+
+/**
+ * Style plugin that simply return a PHP array of themed rows.
+ */
+class userreference_plugin_style_php_array extends views_plugin_style {
+  function render() {
+    $results = array();
+
+    // Group the rows according to the grouping field, if specified.
+    $sets = $this->render_grouping($this->view->result, $this->options['grouping']);
+
+    $base_field = $this->view->base_field;
+    $title_field = $this->view->field['name']->field_alias;
+
+    // TODO : We don't display grouping info for now.
+    // Could be useful for select widget, though.
+    foreach ($sets as $name => $records) {
+      foreach ($records as $label => $row) {
+        $results[$row->{$base_field}] = $row->{$title_field};
+      }
+    }
+    return $results;
+  }
+
+//  function render() {
+//    $results = array();
+//    if (empty($this->row_plugin)) {
+//      vpr('userreference_plugin_style_results_array: Missing row plugin');
+//      return $results;
+//    }
+//
+//    // Group the rows according to the grouping field, if specified.
+//    $sets = $this->render_grouping($this->view->result, $this->options['grouping']);
+//
+//    // Render each group separately.
+//    $base_field = $this->view->base_field;
+//    foreach ($sets as $title => $records) {
+//      $rows = array();
+//      foreach ($records as $label => $row) {
+//        $rows[$row->{$base_field}] = $this->row_plugin->render($row);
+//      }
+//      $results[$title] = $rows;
+//    }
+//    return $results;
+//  }
+}
+
+/**
+ * Implementation of hook_views_data_alter().
+ * Adds a string filter handler to the users/name field for use with autocomplete.
+ */
+function userreference_views_data_alter(&$data) {
+  $data['users']['name']['filter'] = array('handler' => 'views_handler_filter_string');
+}
+
