Only in members: contrib
diff -ur members.cvs/members.install members/members.install
--- members.cvs/members.install	2007-06-27 00:02:19.000000000 +1000
+++ members/members.install	2007-12-17 12:20:25.000000000 +1100
@@ -84,6 +84,23 @@
   return $ret;	
 }
 
+
+function members_update_2() {
+  $ret = array();
+
+  db_add_column($ret, 'members_page', 'searchables', 'varchar(255)');
+
+  return $ret;	
+}
+
+function members_update_3() {
+  $ret = array();
+
+  db_add_column($ret, 'members_page', 'page_type', 'varchar(20)');
+
+  return $ret;	
+}
+
 function members_uninstall() {
   if (db_table_exists('members_page')) {
     db_query("DROP TABLE {members_page}");
diff -ur members.cvs/members.module members/members.module
--- members.cvs/members.module	2007-11-22 21:36:28.000000000 +1100
+++ members/members.module	2008-01-16 15:22:07.000000000 +1100
@@ -75,6 +75,12 @@
       );
   	}
   }
+  
+  $items[] = array('path' => 'members/auto/user',
+  'title' => t('members autocomplete callback'),
+  'callback' => 'members_autocomplete',
+  'access' => true,
+  'type' => MENU_CALLBACK);         
 
   return $items;
 }
@@ -369,6 +375,14 @@
     '#description' => t('Enter the URL to use for this members page. Do not begin or end the URL with a /. Example: \'members/premium\'.'),
   );
 
+    $form['page-info']['page_type'] = array(
+    '#type' => 'select',
+    '#title' => t('Page type'),
+    '#default_value' => $member->page_type,
+    '#options' => array("table"=>"Table","list"=>"List")
+  );
+
+
   $form['page-info']['page_title'] = array(
     '#type' => 'textfield',
     '#title' => t('Title'),
@@ -597,6 +611,7 @@
     '#title' => t('Filters'),
   );  
 
+ 
   $form['filters']['roles'] = array(
     '#type' => 'select',
     '#title' => t("Role Is One Of"),
@@ -608,6 +623,28 @@
     '#required' => TRUE,
   );
 
+  // search should really be arguments
+  // and then it should be exposed arguments just like views
+  
+  $form['search'] = array(
+    '#type' => 'fieldset',
+    '#collapsible' => TRUE,
+    '#collapsed' => $editfield,
+    '#title' => t('Searchables'),
+  );  
+
+  $form['search']['searchables'] = array(
+    '#type' => 'select',
+    '#title' => t("Search fields"),
+    '#default_value' => $member->searchables,
+    '#options' => _members_searchable_fields(),
+    '#description' => t("Select the fields exposed for searching"),
+    '#extra' => 0,
+    '#multiple' => 1
+  );
+
+  
+  
   // Field settings
 
   if (!empty($tempfields)) {
@@ -716,14 +753,29 @@
   else {
   	$roles = "";
   }
+
+  $searchables = array();
+  foreach($form['searchables'] as $index => $value) {
+    if($value!==0) { 
+      $searchables[] = $index;
+    }
+  }
+  if(!empty($searchables)) {
+    $searchables = implode(",", $searchables);
+  }
+  else {
+  	$searchables = "";
+  }
+  
   
   $fields = implode(",", unserialize($form['tempfields']));
+  
 
   if ($form['mid']) {
-    db_query("UPDATE {members_page} SET name='%s', description='%s', access='%s', page=%d, page_title='%s', url='%s', use_pager=%d, page_header='%s', page_header_format=%d, page_footer='%s', page_footer_format=%d, page_empty='%s', page_empty_format=%d, menu=%d, menu_title='%s', block=%d, block_title='%s', users_per_block=%d, block_more=%d, block_use_page_header=%d, block_header='%s', block_header_format=%d, block_use_page_footer=%d, block_footer='%s', block_footer_format=%d, block_use_page_empty=%d, block_empty='%s', block_empty_format=%d, roles='%s', `fields`='%s', encode_mailto=%d, field_length=%d, users_per_page=%d WHERE mid=%d LIMIT 1", $form['name'], $form['description'], $access, $form['page'], $form['page_title'], $form['url'], $form['use_pager'], $form['page_header'], $form['page_header_format'], $form['page_footer'], $form['page_footer_format'], $form['page_empty'], $form['page_empty_format'], $form['menu'], $form['menu_title'], $form['block'], $form['block_title'], $form['users_per_block'], $form['block_more'], $form['block_use_page_header'], $form['block_header'], $form['block_header_format'], $form['block_use_page_footer'], $form['block_footer'], $form['blocker_footer_format'], $form['block_use_page_empty'], $form['block_empty'], $form['block_empty_format'], $roles, $fields, $form['encode_mailto'], $form['field_length'], $form['users_per_page'], $form['mid']);
+    db_query("UPDATE {members_page} SET name='%s', description='%s', access='%s', page=%d, page_title='%s', url='%s', use_pager=%d, page_header='%s', page_header_format=%d, page_footer='%s', page_footer_format=%d, page_empty='%s', page_empty_format=%d, menu=%d, menu_title='%s', block=%d, block_title='%s', users_per_block=%d, block_more=%d, block_use_page_header=%d, block_header='%s', block_header_format=%d, block_use_page_footer=%d, block_footer='%s', block_footer_format=%d, block_use_page_empty=%d, block_empty='%s', block_empty_format=%d, roles='%s', `searchables`='%s', `fields`='%s', encode_mailto=%d, field_length=%d, users_per_page=%d, page_type='%s' WHERE mid=%d LIMIT 1", $form['name'], $form['description'], $access, $form['page'], $form['page_title'], $form['url'], $form['use_pager'], $form['page_header'], $form['page_header_format'], $form['page_footer'], $form['page_footer_format'], $form['page_empty'], $form['page_empty_format'], $form['menu'], $form['menu_title'], $form['block'], $form['block_title'], $form['users_per_block'], $form['block_more'], $form['block_use_page_header'], $form['block_header'], $form['block_header_format'], $form['block_use_page_footer'], $form['block_footer'], $form['blocker_footer_format'], $form['block_use_page_empty'], $form['block_empty'], $form['block_empty_format'], $roles, $searchables, $fields, $form['encode_mailto'], $form['field_length'], $form['users_per_page'],$form['page_type'], $form['mid']);
   }
   else {
-    db_query("INSERT INTO {members_page} (name, description, access, page, page_title, url, use_pager, page_header, page_header_format, page_footer, page_footer_format, page_empty, page_empty_format, menu, menu_title, block, block_title, users_per_block, block_more, block_use_page_header, block_header, block_header_format, block_use_page_footer, block_footer, block_footer_format, block_use_page_empty, block_empty, block_empty_format, roles, `fields`, encode_mailto, field_length, users_per_page) VALUES ('%s', '%s', '%s', %d, '%s', '%s', %d, '%s', %d, '%s', %d, '%s', %d, %d, '%s', %d, '%s', %d, %d, %d, '%s', %d, %d, '%s', %d, %d, '%s', %d, '%s', '%s', %d, %d, %d)", $form['name'], $form['description'], $access, $form['page'], $form['page_title'], $form['url'], $form['use_pager'], $form['page_header'], $form['page_header_format'], $form['page_footer'], $form['page_footer_format'], $form['page_empty'], $form['page_empty_format'], $form['menu'], $form['menu_title'], $form['block'], $form['block_title'], $form['users_per_block'], $form['block_more'], $form['block_use_page_header'], $form['block_header'], $form['block_header_format'], $form['block_use_page_footer'], $form['block_footer'], $form['block_footer_format'], $form['block_use_page_empty'], $form['block_empty'], $form['block_empty_format'], $roles, $fields, $form['encode_mailto'], $form['field_length'], $form['users_per_page']);
+    db_query("INSERT INTO {members_page} (name, description, access, page, page_title, url, use_pager, page_header, page_header_format, page_footer, page_footer_format, page_empty, page_empty_format, menu, menu_title, block, block_title, users_per_block, block_more, block_use_page_header, block_header, block_header_format, block_use_page_footer, block_footer, block_footer_format, block_use_page_empty, block_empty, block_empty_format, roles, `fields`, `searchables`, encode_mailto, field_length, users_per_page, page_type) VALUES ('%s', '%s', '%s', %d, '%s', '%s', %d, '%s', %d, '%s', %d, '%s', %d, %d, '%s', %d, '%s', %d, %d, %d, '%s', %d, %d, '%s', %d, %d, '%s', %d, '%s', '%s', '%s', %d, %d, %d, '%s')", $form['name'], $form['description'], $access, $form['page'], $form['page_title'], $form['url'], $form['use_pager'], $form['page_header'], $form['page_header_format'], $form['page_footer'], $form['page_footer_format'], $form['page_empty'], $form['page_empty_format'], $form['menu'], $form['menu_title'], $form['block'], $form['block_title'], $form['users_per_block'], $form['block_more'], $form['block_use_page_header'], $form['block_header'], $form['block_header_format'], $form['block_use_page_footer'], $form['block_footer'], $form['block_footer_format'], $form['block_use_page_empty'], $form['block_empty'], $form['block_empty_format'], $roles, $fields, $searchables, $form['encode_mailto'], $form['field_length'], $form['users_per_page'],$form['page_type']);
   }
 
   if ($form['mid']) {
@@ -747,55 +799,77 @@
  * Load the members page settings in an object
  */
 function members_load_settings($name = "") {
+
+  static $members_settings;
   $settings = new stdClass();
   
-  if(!empty($name)) {
-  	if(!is_numeric($name)) {
-      $settings = db_fetch_object(db_query("SELECT * FROM {members_page} WHERE name='%s' LIMIT 1", $name));  
-  	}
-  	else {
-      $settings = db_fetch_object(db_query("SELECT * FROM {members_page} WHERE mid=%d LIMIT 1", $name));    		
-  	}
-    $settings->access = explode(",", $settings->access);
-    $settings->roles  = explode(",", $settings->roles); 
-    $settings->fields = explode(",", $settings->fields);        
+  if(!is_array($members_settings)) {
+    $members_settings=array();
+  }
+  
+  if(!key_exists($name,$members_settings)) {
+      
+    if(!empty($name)) {
+    	if(!is_numeric($name)) {
+        $settings = db_fetch_object(db_query("SELECT * FROM {members_page} WHERE name='%s' LIMIT 1", $name));  
+    	}
+    	else {
+        $settings = db_fetch_object(db_query("SELECT * FROM {members_page} WHERE mid=%d LIMIT 1", $name));    		
+    	}
+      $settings->access = explode(",", $settings->access);
+      $settings->roles  = explode(",", $settings->roles); 
+      $settings->searchables = strlen($settings->searchables) ? explode(",", $settings->searchables) : array();
+      $settings->fields = explode(",", $settings->fields);        
+    }
+    $members_settings[$name]=$settings;
+  } else {
+    $settings = $members_settings[$name];
   }
+  
+
   return $settings;
 }
 
+function _members_searchable_fields() {
+  $output = array();
+    // hook_members fields
+  // Look for extensions from other modules
+  foreach (module_implements('members') as $module) {
+    $function = $module .'_members';
+    $fields = $function('fields');
+    foreach($fields as $field_id =>$field ) {
+      if($field['searchable'] == true ) {
+        $output['hook_'.$module.'_'.$field_id] = check_plain($module).': '.check_plain($field['title']);
+      }
+    }
+  }
+  
+  return $output;  
+}
+
 /**
  * Select all available fields
  */
 function _members_fields() {
   $output = array();
 
-  $output['name'] = t('Username');
   $output['picture'] = t('Picture');    
   $output['mail'] = t('Email');
   $output['created'] = t('Registered');
   $output['access'] = t('Last seen');
   $output['status'] = t('Status');
   $output['rid'] = t('Roles');
-//$output['gid'] = t('Organic groups');
 
-  // Profile fields
-  if (module_exists('profile')) {
-  
-    if (module_exists('i18nprofile')) {
-      $language = i18n_get_lang();
-      $result = db_query("SELECT p.name, t.title FROM {profile_fields} p INNER JOIN {i18n_profile_fields} t ON p.fid = t.fid WHERE t.language='%s' ORDER BY weight ASC, title ASC", $language);
-      while($row = db_fetch_object($result)) {
-        $output["profile.$row->name"] = $row->title;
-      }
-    }
-    else {
-      $result = db_query("SELECT name, title FROM {profile_fields} pf ORDER BY weight ASC, title ASC");
-      while ($row = db_fetch_object($result)) {
-        $output["profile.$row->name"] = $row->title;
-      }
+  // hook_members fields
+  // Look for extensions from other modules
+  foreach (module_implements('members') as $module) {
+    $function = $module .'_members';
+    $fields = $function('fields');
+    foreach($fields as $field_id =>$field ) {
+      $output['hook_'.$module.'_'.$field_id] = check_plain($module).': '.check_plain($field['title']);
     }
   }
-
+  
   return $output;
 }
 
@@ -917,6 +991,44 @@
   }
 }
 
+function add_where_joins_from_search($mid, &$w_joins, $search_fields) {
+  
+  if($_SESSION['members_search_form'][$mid]) {
+    foreach($_SESSION['members_search_form'][$mid] as $field => $value) {
+      if(in_array($field, $search_fields)) {
+        $search_type = _search_item_type($field) ;
+    
+         $hook_info=explode("_",$field,3);
+         $hook_temp_table = 't_'.$hook_info[1].'_'.$hook_info[2];
+        
+        switch($search_type['type']) {
+          case 'bool':      
+              if($value == 'yes') {
+                $w_joins[]=$hook_temp_table.'.'.$hook_info[2].' IS NOT NULL';
+              } 
+          break;
+          case 'selection':
+            // if we care about doing a search for the profile selection field
+            if($value != 'any') {
+              $w_joins[]="$hook_temp_table".'.'.$hook_info[2]." IS NOT NULL";
+            }
+          
+          break;
+          case 'list':
+          case 'textfield':
+            $w_joins[]="$hook_temp_table".'.'.$hook_info[2]." IS NOT NULL";
+          break;
+          
+        }
+      }
+    }
+    
+  }
+  
+  return;
+}
+
+
 /**
  * Display the members page
  */
@@ -924,51 +1036,79 @@
 
   if(empty($mid)) return;
   
-  $member = members_load_settings($mid);
-  
+    $matching_accounts=array();
+    $member = members_load_settings($mid);
+    $pager_active=false;  
     $roles = $member->roles;
 
     if ($roles) {
       $fields = array();
+      $search_fields = array();
       $enabled_fields = $member->fields;
       $all_fields = _members_fields();
-      foreach($member->fields as $field) {
-        $fields[$field] = $all_fields[$field];
-      }
-      foreach ($fields as $field => $data) {
-        if (substr($field, 0, 8) == 'profile.') {
-          $field = 'p.value';
-        } elseif ($field == 'rid') {
-          $field = '';
+
+      $q_joins = array();
+      $s_joins = array();
+      $w_joins = array();
+      $hook_fields = array();
+
+      // preprocess, get ready the data
+      foreach($member->searchables as $field) {
+        $hook_info=explode("_",$field,3);
+        $hook_temp_table = 't_'.$hook_info[1].'_'.$hook_info[2];
+          
+        //invoke that hook so it creates a temp table with the infos
+        $function = $hook_info[1] .'_members';
+        if(function_exists($function)) {
+          // does the hook return true, then it is worth JOINing this to our queries
+          if ( $function('process',$hook_info[2],$hook_temp_table,$_SESSION['members_search_form'][$mid][$field]) ) {
+            // get the hook fields available from this module if this field had searched data
+            if ($_SESSION['members_search_form'][$mid][$field]) {
+              $q_joins[] = "LEFT JOIN {$hook_temp_table} ON $hook_temp_table.uid=u.uid";
+              $s_joins[] = $hook_temp_table.'.'.$hook_info[2];
+              $search_fields[]=$field;
+
+            }
+          }
+          //$avail_fields =  $function('fields');
         }
-        $header[] = array("data" => $data, "field" => $field);
+
       }
       
-      if(in_array("2",$roles)) {
-        $allusers = 1;
-        $query = "SELECT DISTINCT(u.uid) FROM {users} u";
-      } else {
-        $allusers = 0;
-        foreach ($roles as $rid) {
-          $list[] = "'" . db_escape_string($rid) ."'";
+      // start building the data rows
+      foreach ($enabled_fields as $field ) {
+        
+        if(drupal_substr($field, 0, 4) == 'hook') {
+          
+          $hook_info=explode("_",$field,3);
+          $hook_temp_table = 't_'.$hook_info[1].'_'.$hook_info[2];
+          $function = $hook_info[1] .'_members';
+          if(function_exists($function)) {
+            $avail_fields =  $function('fields');
+          }
+          $header[] = array("data" => $avail_fields[$hook_info[2]]['title'], "field" => $hook_temp_table.'.'.$hook_info[2]);
+          
+        } else {
+          $header[] = array("data" => $all_fields[$field], "field" => $field);
         }
-        $list = implode(',', $list);
-        $query = "SELECT DISTINCT(u.uid) FROM {users} u INNER JOIN {users_roles} r ON u.uid=r.uid";
-      }
-      $sort = tablesort_get_order($header);
-      if ($sort['sql'] == 'p.value') {
-        $fieldid = db_result(db_query("SELECT fid FROM {profile_fields} WHERE name='%s'",substr(array_search($sort['name'], $fields), 8)));
-        $query.= " LEFT JOIN {profile_values} p ON u.uid=p.uid WHERE (p.fid = '". db_escape_string($fieldid). "' OR p.fid IS NULL) AND";
-      }
-      else {
-        $query.= " WHERE";
       }
-      if ($allusers == 0) {
-        $query.= " r.rid IN ($list) AND u.status=1" . tablesort_sql($header);
-      } else {
-        $query.= " u.status=1" . tablesort_sql($header);
+
+      $w_joins[]='u.uid > 0';
+
+      // depending on the search form, add some extra WHERE's
+      add_where_joins_from_search($mid, $w_joins, $search_fields);
+         
+      $query = 'SELECT DISTINCT(u.uid),u.* '; // SELECTS
+      if(sizeof($s_joins) > 0) {
+        $query .= ',';
+        $query .= implode($s_joins,', ');
       }
+           
+      $query .= ' FROM {users} u ';
+      $query .= ' '.implode($q_joins,' ').' '; // LEFT JOINS
+      $query .= ' WHERE '.implode($w_joins,' AND '); // WHERE
       
+
       if($type=="block") {
         $query.= " LIMIT " . $member->users_per_block;
         $result = db_query($query);        
@@ -980,74 +1120,56 @@
       	if(!empty($member->users_per_page)) $query.=" LIMIT " . $member->users_per_page;
         $result = db_query($query);	
       }   
-
+      
       $rows = array();
-      $profile_fields = array();
+      
       while ($userid = db_fetch_object($result)) {
         $account = user_load(array('uid' => $userid->uid));
         $row = array();
-        foreach ($fields as $field => $title) {
+        foreach ($enabled_fields as $field ) {
           $data = NULL;
-          if (substr($field, 0, 8) == 'profile.') {
-            $field = substr($field, 8);
-            if (!$profile_fields[$field]) {
-              $profile_fields[$field] = db_fetch_object(db_query("SELECT * FROM {profile_fields} WHERE name='%s'", $field));
-            }
-            $data = profile_view_field($account, $profile_fields[$field]);
-            $length = $member->field_length;
-            if ($length && is_numeric($length)) {
-              $data  = truncate_utf8($data, $length, TRUE);
-            }
-          }
-          elseif ($field == 'rid') {
+          // if this field is a hook, then do some theme callbacks
+          if (drupal_substr($field, 0, 4) == 'hook') {
+            $hook_info=explode("_",$field,3);
+            // hooks provide each field to be themeable
+            $account = user_load(array('uid'=>$userid->uid));
+            $data=theme($hook_info[1].'_field',$account,$hook_info[2], $userid);
+          } // else it is a local code field (which should be depreciated in the future)
+          else if ($field == 'rid') {
             $data = array();
             foreach ($account->roles as $rid => $role) {
               if (in_array($rid, $roles)) {
-                $data[] = $role;
+                $data[] = l($role, 'members/'.$rid);
               }
             }
             $data = implode (', ', $data);
-          }
-          elseif ($field == 'picture') {
-            $data = theme_user_picture($account);
-          }
-          elseif ($field == 'created') {
-            $data = date('F dS Y h:i:s', $account->created);
-          }                    
-          elseif ($field == 'access') {
-            $data = ($account->access) ? format_interval(time() - $account->access) : t('Never');
-          }
-          elseif ($field == 'status') {
-            $data = ($account->status) ? t('Active') : t('Blocked');
-          }
-          elseif ($field == 'count') {
-            $data = db_result(db_query("SELECT count(nid) FROM {node} WHERE uid=%d", $account->uid));
-          }
-          elseif ($field == 'mail') {
-            if ($member->encode_mailto) {
-              $data = _members_encode_mailto($account->mail);
-            }
-            else {
-              $data = $account->mail;
-            }
+          } elseif ($field == 'picture') {
+            $data = theme('user_picture',$account);
           }
           else {
             $data = $account->$field;
           }
+          
           if (stristr($field, 'name')) {
             $data = l($data, 'user/'.$account->uid);
           }
           $row[] = array('data' => $data);
         }
+        $matching_accounts[]=$account;
         $rows[] = $row;
-      }
-
+      } 
+      
       if ($type=="page" && $member->use_pager && $pager = theme("pager", NULL, $member->users_per_page, 0)) {
         $rows[] = array(array("data" => $pager, "colspan" => count($header)));
+        $pager_active=true;
       }
 
-      $output = "";
-      
+      if ( sizeof($member->searchables) > 0 ) {
+        $output = drupal_get_form('members_search_form',$mid);
+      } else {
+        $output = '';
+      }
+     
       // Render header
 
       if(!empty($member->page_header) && ($type=="page" || ($type=="block" && $member->block_use_page_header))) {
@@ -1058,7 +1180,16 @@
       }
       // Render main content
       
-      $output .= '<div id="members-main">'. theme("table", $header, $rows) .'</div>';
+      if(!$member->page_type || $member->page_type == 'table') {
+        $output .= '<div id="members-'.$member->name.'">'. theme("table", $header, $rows) .'</div>';
+      } elseif ($member->page_type == 'list') {
+        if($pager_active) {
+          $pager=end($rows);
+          unset($rows[sizeof($rows)-1]);
+        }
+        $output .= '<div id="members-'.$member->name.'">'. theme('members_view_list',$member, $header, $rows, $matching_accounts) .'</div>';
+        $output .= $pager[0]['data'];
+      }
       
       // Render 'more' link
 
@@ -1069,18 +1200,19 @@
 
       // Render footer
 
-      if(!empty($member->page_footer) && ($type=="page" || ($type=="block" && $member->block_use_page_footer))) {
+      if(!empty($member->page_footer) && ($type=="page" || ($type=="block" && $member->block_use_page_footer))) {
         $output .= check_markup($member->page_footer, $member->page_footer_format, FALSE);
       }
       elseif($type=="block" && !empty($member->block_footer)) {
         $output .= check_markup($member->block_footer, $member->block_footer_format, FALSE);
       }
 
+
       return $output;
     }
     else {
 
-      if(!empty($member->block_page) && ($type=="page" || ($type=="block" && $member->block_use_page_header))) {
+      if(!empty($member->block_page) && ($type=="page" ||($type=="block" && $member->block_use_page_header))) {
       	return check_markup($member->block_page, $member->block_page_format, FALSE);
       }
       elseif($type=="block" && !empty($member->block_page)) {
@@ -1094,6 +1226,112 @@
 
 }
 
+function members_search_form($mid) {
+
+  $form = array();
+  
+  $member = members_load_settings($mid);
+
+  $output = "";
+
+  $form['filter'] = array(
+    '#type' => 'fieldset',
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+    '#title' => t('Search information'),
+  );
+
+  $form['filter']['mid'] = array(
+    '#type' => 'hidden',
+    '#value' => $mid,
+  );
+
+  $enabled_fields = $member->fields;
+  $all_fields = _members_fields();
+
+
+  if($_POST['op']=='Reset Filter') {
+    unset($_SESSION['members_search_form'][$mid]);
+    drupal_goto($_GET['q']); // reload this page
+  } else {
+    $defaults = $_SESSION['members_search_form'][$mid];
+  }
+
+  
+  foreach ($member->searchables as $field ) {
+    $field_info = _search_item_type($field);
+    
+    $field_name = $field;
+    $title = $field_info['title'];
+    $options = $field_info['options'];
+    
+    
+    switch($field_info['type']) {
+      case 'bool':
+        $form['filter'][$field_name] = array(
+          '#type' => 'select',
+          '#title' => $title,
+          '#options' => array('any'=>'Any','yes'=>'Yes'),
+          '#default_value' => $defaults[$field_name]
+        );
+      break;
+      case 'selection':
+        $form['filter'][$field_name] = array(
+          '#type' => 'select',
+          '#title' => $title,
+          '#options' => $options,
+          '#default_value' => $defaults[$field_name]
+        );
+      break;
+      
+      case 'textfield':
+        $form['filter'][$field_name] = array(
+          '#type' => 'textfield',
+          '#title' => $title,
+          '#default_value' => $defaults[$field_name]
+        );
+      break;
+      // we use textfield to represent list items
+      case 'list':
+        $form['filter'][$field_name] = array(
+          '#type' => 'textfield',
+          '#title' => $title,
+          '#default_value' => $defaults[$field_name]
+        );
+      break;      
+    }
+    
+    if ( $field_info['#autocomplete_path'] ) {
+      $form['filter'][$field_name]['#autocomplete_path'] = $field_info['#autocomplete_path'];
+    }
+    
+  }
+  
+  $form['filter']['submit'] = array('#type' => 'submit', '#value' =>t('Search'));
+  
+  $form['filter']['reset'] = array('#type' => 'button', '#value' =>t('Reset Filter'));
+  
+  
+  return $form;
+  
+}
+
+
+function members_search_form_submit($form_id, $form) {
+  $mid = $form['mid'];
+  
+  if(!is_array($_SESSION['members_search_form'][$mid])) {
+    $_SESSION['members_search_form'][$mid]=array();
+  } else {
+    unset($_SESSION['members_search_form'][$mid]);
+  }
+  foreach($_POST as $key => $value) {
+    $_SESSION['members_search_form'][$mid][$key]=$value;
+  }
+  
+}
+  
+
 /**
  * Arrange fields in correct order (keys in following order)
  */
@@ -1121,6 +1359,31 @@
   return $button;
 }
 
+/**
+ * return the type of search that this field name can do
+ * 
+ *
+ * @param string $field_name
+ */
+function _search_item_type($field) {
+
+  $field_info =array();
+  if (drupal_substr($field, 0, 4) == 'hook') {
+    $hook_info=explode("_",$field,3);
+    $function = $hook_info[1] .'_members';
+    if(function_exists($function)) {
+      // get the label/title/type of the field
+      $fields = $function('fields');
+      $field_info = $fields[$hook_info[2]];
+
+    }
+  } else {
+    $field_info['type']='string';
+  }
+
+  return $field_info;
+}
+
 
 /**
  * Render an operation button
@@ -1207,3 +1470,98 @@
   $output.= drupal_render($form);
   return $output;
 }
+
+
+function members_members($op, $a='', $b='', $c='') {
+  global $user;
+    
+  switch($op) {
+    // return array of what fields we can define for members module
+    case 'fields':
+      // this module only has one field of use
+      $fields['username'] = array ('title'=> 'Username', 
+                                   'type' => 'textfield',
+                                   '#autocomplete_path' => 'members/auto/user/username',
+                                   'searchable'=>true);
+      $fields['access'] = array ('title'=> 'Has logged in', 
+                                   'type' => 'bool',
+                                   'searchable'=>true
+                                   );
+      return $fields;
+    break;
+    
+    case 'process':
+      // create a temporary table with our results of who is the current users buddy
+      // members module will be expecting this table ($b) todo a LEFT JOIN on to gather more information
+      if($a == 'username') {
+        db_query("CREATE TEMPORARY TABLE {%s} (uid int, %s int, INDEX (uid), INDEX(%s))",$b,$a,$a);
+        db_query('INSERT INTO {%s} SELECT uid,uid FROM {users} WHERE name LIKE "%%%s%%"',$b,$c);
+        return true;   
+      } elseif ($a == 'access' ) {
+        if($c == 'yes') {
+          $access_str = $c == 'yes' ? 'WHERE u.access > 0' : '';
+          db_query("CREATE TEMPORARY TABLE {%s} (uid int, %s int, INDEX (uid), INDEX(%s))",$b,$a,$a);
+          db_query('INSERT INTO {%s} SELECT uid,uid FROM {users} u %s',$b,$access_str);
+          return true;
+        } else {
+          return false;
+        }
+      }
+      
+      
+      break;
+  }
+}
+
+
+function members_autocomplete($field_name='', $string='') {
+  $matches=array();
+
+  if($field_name == 'username') {
+    $matches = user_autocomplete($string);
+  }
+  
+  print drupal_to_js($matches);
+  exit();
+}
+
+
+/**
+ * hook_theme
+ *
+ * @param $account row from table join
+ * @param $field_id id of field for profile module reference
+ * @param $row_value value of the join in the current members row
+ * @return string with better representation of the row
+ * 
+ * 
+ */
+function theme_members_field($account, $field_id) {
+
+  $output='';
+  switch($field_id) {
+    case 'username':
+      return check_plain($account->name);
+    break;
+    case 'access':
+        return ($account->access) ? format_interval(time() - $account->access) : t('Never');
+    break;
+        
+  }
+          
+}
+
+function theme_members_view_list($member, $fields, $data, $matching_accounts = array()) {
+  
+  $output = '';
+  
+  foreach( $data as $user ) {  
+    $output .= theme('item_list', $user);    
+  }
+  
+  if($member->use_pager){
+    $output .= $pager;
+  }
+  
+  return $output;
+}
