diff --git a/include/class.orm.php b/include/class.orm.php
index 8338b84c7e65e739c9743a0112075de693a6fd47..37178b276c6513cedd70458ca340f7020f19adc1 100644
--- a/include/class.orm.php
+++ b/include/class.orm.php
@@ -895,7 +895,7 @@ class QuerySet implements IteratorAggregate, ArrayAccess, Serializable {
         $query = clone $this;
         if (!$query->ordering && isset($model::$meta['ordering']))
             $query->ordering = $model::$meta['ordering'];
-        if (!$query->related && $model::$meta['select_related'])
+        if (!$query->related && !$query->values && $model::$meta['select_related'])
             $query->related = $model::$meta['select_related'];
         if (!$query->defer && $model::$meta['defer'])
             $query->defer = $model::$meta['defer'];
diff --git a/include/class.user.php b/include/class.user.php
index c8da82c12e6217340df74bbfd75ad5efbb6b3188..8e6382e9dbb04c84e4485b421b18ef47d7f9dd09 100644
--- a/include/class.user.php
+++ b/include/class.user.php
@@ -44,10 +44,12 @@ class UserModel extends VerySimpleModel {
                 'reverse' => 'UserEmailModel.user',
             ),
             'tickets' => array(
+                'null' => true,
                 'reverse' => 'TicketModel.user',
             ),
             'account' => array(
                 'list' => false,
+                'null' => true,
                 'reverse' => 'UserAccount.user',
             ),
             'org' => array(
diff --git a/include/staff/users.inc.php b/include/staff/users.inc.php
index b085496395f501aa5c7b17fb6cecd35bad0e957b..3c1152e918d6f87d58a031131b137459b218b8d3 100644
--- a/include/staff/users.inc.php
+++ b/include/staff/users.inc.php
@@ -3,75 +3,56 @@ if(!defined('OSTSCPINC') || !$thisstaff) die('Access Denied');
 
 $qstr='';
 
-$select = 'SELECT user.*, email.address as email, org.name as organization
-          , account.id as account_id, account.status as account_status ';
-
-$from = 'FROM '.USER_TABLE.' user '
-      . 'LEFT JOIN '.USER_EMAIL_TABLE.' email ON (user.id = email.user_id) '
-      . 'LEFT JOIN '.ORGANIZATION_TABLE.' org ON (user.org_id = org.id) '
-      . 'LEFT JOIN '.USER_ACCOUNT_TABLE.' account ON (account.user_id = user.id) ';
-
-$where='WHERE 1 ';
-
+$users = User::objects()
+    ->annotate(array('ticket_count'=>SqlAggregate::COUNT('tickets')));
 
 if ($_REQUEST['query']) {
-
-    $from .=' LEFT JOIN '.FORM_ENTRY_TABLE.' entry
-                ON (entry.object_type=\'U\' AND entry.object_id = user.id)
-              LEFT JOIN '.FORM_ANSWER_TABLE.' value
-                ON (value.entry_id=entry.id) ';
-
-    $search = db_input(strtolower($_REQUEST['query']), false);
-    $where .= ' AND (
-                    email.address LIKE \'%'.$search.'%\'
-                    OR user.name LIKE \'%'.$search.'%\'
-                    OR org.name LIKE \'%'.$search.'%\'
-                    OR value.value LIKE \'%'.$search.'%\'
-                )';
-
-    $qstr.='&query='.urlencode($_REQUEST['query']);
+    $search = $_REQUEST['query'];
+    $users->filter(Q::any(array(
+        'emails__address__contains' => $search,
+        'name__contains' => $search,
+        'org__name__contains' => $search,
+        // TODO: Add search for cdata
+    )));
 }
 
-$sortOptions = array('name' => 'user.name',
-                     'email' => 'email.address',
-                     'status' => 'account_status',
-                     'create' => 'user.created',
-                     'update' => 'user.updated');
-$orderWays = array('DESC'=>'DESC','ASC'=>'ASC');
+$sortOptions = array('name' => 'name',
+                     'email' => 'emails__address',
+                     'status' => 'account__status',
+                     'create' => 'created',
+                     'update' => 'updated');
+$orderWays = array('DESC'=>'-','ASC'=>'');
 $sort= ($_REQUEST['sort'] && $sortOptions[strtolower($_REQUEST['sort'])]) ? strtolower($_REQUEST['sort']) : 'name';
 //Sorting options...
 if ($sort && $sortOptions[$sort])
     $order_column =$sortOptions[$sort];
 
-$order_column = $order_column ?: 'user.name';
+$order_column = $order_column ?: 'name';
 
 if ($_REQUEST['order'] && $orderWays[strtoupper($_REQUEST['order'])])
     $order = $orderWays[strtoupper($_REQUEST['order'])];
 
-$order=$order ?: 'ASC';
 if ($order_column && strpos($order_column,','))
     $order_column = str_replace(','," $order,",$order_column);
 
 $x=$sort.'_sort';
-$$x=' class="'.strtolower($order).'" ';
+$$x=' class="'.strtolower($order ?: 'desc').'" ';
 $order_by="$order_column $order ";
 
-$total=db_count('SELECT count(DISTINCT user.id) '.$from.' '.$where);
+$total = $users->count();
 $page=($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1;
 $pageNav=new Pagenate($total,$page,PAGE_LIMIT);
 $pageNav->setURL('users.php',$qstr.'&sort='.urlencode($_REQUEST['sort']).'&order='.urlencode($_REQUEST['order']));
+$pageNav->paginate($users);
+
 //Ok..lets roll...create the actual query
 $qstr.='&order='.($order=='DESC'?'ASC':'DESC');
 
-$select .= ', count(DISTINCT ticket.ticket_id) as tickets ';
-
-$from .= ' LEFT JOIN '.TICKET_TABLE.' ticket ON (ticket.user_id = user.id) ';
-
-
-$query="$select $from $where GROUP BY user.id ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit();
 //echo $query;
-$qhash = md5($query);
-$_SESSION['users_qs_'.$qhash] = $query;
+$_SESSION[':Q:users'] = $users;
+
+$users->values('id', 'name', 'default_email__address', 'account__id',
+    'account__status', 'created', 'updated');
 
 ?>
 <h2><?php echo __('User Directory'); ?></h2>
@@ -98,8 +79,7 @@ $_SESSION['users_qs_'.$qhash] = $query;
 <div class="clear"></div>
 <?php
 $showing = $search ? __('Search Results').': ' : '';
-$res = db_query($query);
-if($res && ($num=db_num_rows($res)))
+if($users->exists(true))
     $showing .= $pageNav->showing();
 else
     $showing .= __('No users found!');
@@ -124,52 +104,49 @@ else
     </thead>
     <tbody>
     <?php
-        if($res && db_num_rows($res)):
-            $ids=($errors && is_array($_POST['ids']))?$_POST['ids']:null;
-            while ($row = db_fetch_array($res)) {
+        $ids=($errors && is_array($_POST['ids']))?$_POST['ids']:null;
+        foreach ($users as $U) {
                 // Default to email address mailbox if no name specified
-                if (!$row['name'])
-                    list($name) = explode('@', $row['email']);
+                if (!$U['name'])
+                    list($name) = explode('@', $U['default_email__address']);
                 else
-                    $name = new PersonsName($row['name']);
+                    $name = new PersonsName($U['name']);
 
                 // Account status
-                if ($row['account_id'])
-                    $status = new UserAccountStatus($row['account_status']);
+                if ($U['account__id'])
+                    $status = new UserAccountStatus($U['account__status']);
                 else
                     $status = __('Guest');
 
                 $sel=false;
-                if($ids && in_array($row['id'], $ids))
+                if($ids && in_array($U['id'], $ids))
                     $sel=true;
                 ?>
-               <tr id="<?php echo $row['id']; ?>">
+               <tr id="<?php echo $U['id']; ?>">
                 <td>&nbsp;
-                    <a class="userPreview" href="users.php?id=<?php echo $row['id']; ?>"><?php
+                    <a class="userPreview" href="users.php?id=<?php echo $U['id']; ?>"><?php
                         echo Format::htmlchars($name); ?></a>
                     &nbsp;
                     <?php
-                    if ($row['tickets'])
+                    if ($U['ticket_count'])
                          echo sprintf('<i class="icon-fixed-width icon-file-text-alt"></i>
-                             <small>(%d)</small>', $row['tickets']);
+                             <small>(%d)</small>', $U['ticket_count']);
                     ?>
                 </td>
                 <td><?php echo $status; ?></td>
-                <td><?php echo Format::date($row['created']); ?></td>
-                <td><?php echo Format::datetime($row['updated']); ?>&nbsp;</td>
+                <td><?php echo Format::date($U['created']); ?></td>
+                <td><?php echo Format::datetime($U['updated']); ?>&nbsp;</td>
                </tr>
-            <?php
-            } //end of while.
-        endif; ?>
+<?php   } //end of foreach. ?>
     </tbody>
 </table>
 <?php
-if($res && $num): //Show options..
+if ($total) {
     echo sprintf('<div>&nbsp;'.__('Page').': %s &nbsp; <a class="no-pjax"
             href="users.php?a=export&qh=%s">'.__('Export').'</a></div>',
             $pageNav->getPageLinks(),
             $qhash);
-endif;
+}
 ?>
 </form>