Revision: 2343
          http://mrbs.svn.sourceforge.net/mrbs/?rev=2343&view=rev
Author:   cimorrison
Date:     2012-07-20 14:29:27 +0000 (Fri, 20 Jul 2012)
Log Message:
-----------
Made the users table use an Ajax data source for better performance with large 
numbers of users

Modified Paths:
--------------
    mrbs/trunk/web/edit_users.php
    mrbs/trunk/web/jquery/datatables/css/mrbs-table.css
    mrbs/trunk/web/js/edit_users.js.php
    mrbs/trunk/web/js/general.js.php
    mrbs/trunk/web/session/session_cookie.inc
    mrbs/trunk/web/session/session_http.inc
    mrbs/trunk/web/session/session_php.inc
    mrbs/trunk/web/session/session_remote_user.inc

Modified: mrbs/trunk/web/edit_users.php
===================================================================
--- mrbs/trunk/web/edit_users.php       2012-07-20 11:31:37 UTC (rev 2342)
+++ mrbs/trunk/web/edit_users.php       2012-07-20 14:29:27 UTC (rev 2343)
@@ -51,7 +51,10 @@
 $taken_name = get_form_var('taken_name', 'string');
 $pwd_not_match = get_form_var('pwd_not_match', 'string');
 $pwd_invalid = get_form_var('pwd_invalid', 'string');
+$ajax = get_form_var('ajax', 'int');  // Set if this is an Ajax request
+$datatable = get_form_var('datatable', 'int');  // Will only be set if we're 
using DataTables
 
+
 // Validates that the password conforms to the password policy
 // (Ideally this function should also be matched by client-side
 // validation, but unfortunately JavaScript's native support for Unicode
@@ -123,6 +126,119 @@
 }
 
 
+function output_row(&$row)
+{
+  global $ajax, $json_data;
+  global $level, $min_user_viewing_level, $min_user_editing_level, $user;
+  global $auth, $fields, $ignore_columns, $select_options;
+  global $PHP_SELF;
+  
+  $values = array();
+  
+  // Check whether ordinary users are allowed to see other users' details.  If 
not,
+  // then skip past this row if it's not the current user or the user is not 
an admin
+  if ($auth['only_admin_can_see_other_users'] &&
+      ($level < $min_user_viewing_level) &&
+      (strcasecmp($row['name'], $user) != 0))
+  {
+    continue;
+  }
+    
+  // First column, which is the name
+  $html_name = htmlspecialchars($row['name']);
+  // You can only edit a user if you have sufficient admin rights, or else if 
that user is yourself
+  if (($level >= $min_user_editing_level) || (strcasecmp($row['name'], $user) 
== 0))
+  {
+    $link = htmlspecialchars(basename($PHP_SELF)) . "?Action=Edit&amp;Id=" . 
$row['id'];
+    $values[] = "<a title=\"$html_name\" href=\"$link\">$html_name</a>";
+  }
+  else
+  {
+    $values[] = "<span class=\"normal\" 
title=\"$html_name\">$html_name</span>";
+  }
+    
+  // Other columns
+  foreach ($fields as $field)
+  {
+    $key = $field['name'];
+    if (!in_array($key, $ignore_columns))
+    {
+      $col_value = $row[$key];
+      switch($key)
+      {
+        // special treatment for some fields
+        case 'level':
+          // the level field contains a code and we want to display a string
+          // (but we put the code in a span for sorting)
+          $values[] = "<span title=\"$col_value\"></span>" .
+                      "<div>" . get_vocab("level_$col_value") . "</div>";
+          break;
+        case 'email':
+          // we don't want to truncate the email address
+          $values[] = "<div>" . htmlspecialchars($col_value) . "</div>";
+          break;
+        default:
+          // Where there's an associative array of options, display
+          // the value rather than the key
+          if (isset($select_options["users.$key"]) &&
+              is_assoc($select_options["users.$key"]))
+          {
+            if (isset($select_options["users.$key"][$row[$key]]))
+            {
+              $col_value = $select_options["users.$key"][$row[$key]];
+            }
+            else
+            {
+              $col_value = '';
+            }
+            $values[] = "<div>" . htmlspecialchars($col_value) . "</div>";
+          }
+          elseif (($field['nature'] == 'boolean') || 
+              (($field['nature'] == 'integer') && isset($field['length']) && 
($field['length'] <= 2)) )
+          {
+            // booleans: represent by a checkmark
+            $values[] = "<div class=\"int\">" .
+                        ((!empty($col_value)) ? "<img src=\"images/check.png\" 
alt=\"check mark\" width=\"16\" height=\"16\">" : "&nbsp;") .
+                         "</div>";
+          }
+          elseif (($field['nature'] == 'integer') && isset($field['length']) 
&& ($field['length'] > 2))
+          {
+            // integer values
+            $values[] = "<div class=\"int\">" . $col_value . "</div>";
+          }
+          else
+          {
+             // strings
+            $values[] = "<div title=\"" . htmlspecialchars($col_value) . "\">" 
.
+                        htmlspecialchars($col_value) . "</div>";
+          }
+          break;
+      }  // end switch
+    }
+  }  // end foreach
+
+  if ($ajax)
+  {
+    $json_data['aaData'][] = $values;
+  }
+  else
+  {
+    echo "<tr>\n<td>\n";
+    echo implode("</td>\n<td>", $values);
+    echo "</td>\n</tr>\n";
+  }
+}
+
+// Set up for Ajax.   We need to know whether we're capable of dealing with 
Ajax
+// requests, which will only be if (a) the browser is using DataTables and (b)
+// we can do JSON encoding.    We also need to initialise the JSON data array.
+$ajax_capable = $datatable && function_exists('json_encode');
+
+if ($ajax)
+{
+  $json_data['aaData'] = array();
+}
+
 // Get the information about the fields in the users table
 $fields = sql_field_info($tbl_users);
 
@@ -731,19 +847,22 @@
 
 /* Print the standard MRBS header */
 
-print_header(0, 0, 0, "", "");
+if (!$ajax)
+{
+  print_header(0, 0, 0, "", "");
 
-print "<h2>" . get_vocab("user_list") . "</h2>\n";
+  print "<h2>" . get_vocab("user_list") . "</h2>\n";
 
-if ($level >= $min_user_editing_level) /* Administrators get the right to add 
new users */
-{
-  print "<form id=\"add_new_user\" method=\"post\" action=\"" . 
htmlspecialchars(basename($PHP_SELF)) . "\">\n";
-  print "  <div>\n";
-  print "    <input type=\"hidden\" name=\"Action\" value=\"Add\">\n";
-  print "    <input type=\"hidden\" name=\"Id\" value=\"-1\">\n";
-  print "    <input type=\"submit\" value=\"" . get_vocab("add_new_user") . 
"\">\n";
-  print "  </div>\n";
-  print "</form>\n";
+  if ($level >= $min_user_editing_level) /* Administrators get the right to 
add new users */
+  {
+    print "<form id=\"add_new_user\" method=\"post\" action=\"" . 
htmlspecialchars(basename($PHP_SELF)) . "\">\n";
+    print "  <div>\n";
+    print "    <input type=\"hidden\" name=\"Action\" value=\"Add\">\n";
+    print "    <input type=\"hidden\" name=\"Id\" value=\"-1\">\n";
+    print "    <input type=\"submit\" value=\"" . get_vocab("add_new_user") . 
"\">\n";
+    print "  </div>\n";
+    print "</form>\n";
+  }
 }
 
 if ($initial_user_creation != 1)   // don't print the user table if there are 
no users
@@ -754,131 +873,64 @@
   // Display the data in a table
   $ignore_columns = array('id', 'password', 'name'); // We don't display these 
columns or they get special treatment
   
-  echo "<div id=\"user_list\" class=\"datatable_container\">\n";
-  echo "<table class=\"admin_table display\" id=\"users_table\">\n";
+  if (!$ajax)
+  {
+    echo "<div id=\"user_list\" class=\"datatable_container\">\n";
+    echo "<table class=\"admin_table display\" id=\"users_table\">\n";
   
-  // The table header
-  echo "<thead>\n";
-  echo "<tr>";
+    // The table header
+    echo "<thead>\n";
+    echo "<tr>";
   
-  // First column which is the name
-  echo "<th>" . get_vocab("users.name") . "</th>\n";
+    // First column which is the name
+    echo "<th>" . get_vocab("users.name") . "</th>\n";
   
-  // Other column headers
-  foreach ($fields as $field)
-  {
-    $fieldname = $field['name'];
+    // Other column headers
+    foreach ($fields as $field)
+    {
+      $fieldname = $field['name'];
     
-    if (!in_array($fieldname, $ignore_columns))
-    {
-      echo "<th>" . get_loc_field_name($tbl_users, $fieldname) . "</th>";
+      if (!in_array($fieldname, $ignore_columns))
+      {
+        echo "<th>" . get_loc_field_name($tbl_users, $fieldname) . "</th>";
+      }
     }
+  
+    echo "</tr>\n";
+    echo "</thead>\n";
+  
+    // The table body
+    echo "<tbody>\n";
   }
   
-  echo "</tr>\n";
-  echo "</thead>\n";
-  
-  // The table body
-  echo "<tbody>\n";
-  for ($i = 0; ($row = sql_row_keyed($res, $i)); $i++)
+  // If we're Ajax capable and this is not an Ajax request then don't ouput
+  // the table body, because that's going to be sent later in response to
+  // an Ajax request
+  if (!$ajax_capable || $ajax)
   {
-    // Check whether ordinary users are allowed to see other users' details.  
If not,
-    // then skip past this row if it's not the current user or the user is not 
an admin
-    if ($auth['only_admin_can_see_other_users'] &&
-        ($level < $min_user_viewing_level) &&
-        (strcasecmp($row['name'], $user) != 0))
+    for ($i = 0; ($row = sql_row_keyed($res, $i)); $i++)
     {
-      continue;
+      output_row($row);
     }
-    
-    echo "<tr>\n";
-    
-    // First column, which is the name
-    $html_name = htmlspecialchars($row['name']);
-    // You can only edit a user if you have sufficient admin rights, or else 
if that user is yourself
-    if (($level >= $min_user_editing_level) || (strcasecmp($row['name'], 
$user) == 0))
-    {
-      $link = htmlspecialchars(basename($PHP_SELF)) . "?Action=Edit&amp;Id=" . 
$row['id'];
-      echo "<td><a title=\"$html_name\" href=\"$link\">$html_name</a></td>\n";
-    }
-    else
-    {
-      echo "<td title=\"$html_name\">$html_name</td>\n";
-    }
-    
-    // Other columns
-    foreach ($fields as $field)
-    {
-      $key = $field['name'];
-      if (!in_array($key, $ignore_columns))
-      {
-        $col_value = $row[$key];
-        switch($key)
-        {
-          // special treatment for some fields
-          case 'level':
-            // the level field contains a code and we want to display a string
-            // (but we put the code in a span for sorting)
-            echo "<td>";
-            echo "<span title=\"$col_value\"></span>";
-            echo "<div>" . get_vocab("level_$col_value") . "</div></td>\n";
-            break;
-          case 'email':
-            // we don't want to truncate the email address
-            echo "<td><div>" . htmlspecialchars($col_value) . "</div></td>\n";
-            break;
-          default:
-            // Where there's an associative array of options, display
-            // the value rather than the key
-            if (isset($select_options["users.$key"]) &&
-                is_assoc($select_options["users.$key"]))
-            {
-              if (isset($select_options["users.$key"][$row[$key]]))
-              {
-                $col_value = $select_options["users.$key"][$row[$key]];
-              }
-              else
-              {
-                $col_value = '';
-              }
-              echo "<td><div>" . htmlspecialchars($col_value) . 
"</div></td>\n";
-            }
-            elseif (($field['nature'] == 'boolean') || 
-                (($field['nature'] == 'integer') && isset($field['length']) && 
($field['length'] <= 2)) )
-            {
-              // booleans: represent by a checkmark
-              echo "<td class=\"int\"><div>";
-              echo (!empty($col_value)) ? "<img src=\"images/check.png\" 
alt=\"check mark\" width=\"16\" height=\"16\">" : "&nbsp;";
-              echo "</div></td>\n";
-            }
-            elseif (($field['nature'] == 'integer') && isset($field['length']) 
&& ($field['length'] > 2))
-            {
-              // integer values
-              echo "<td class=\"int\"><div>" . $col_value . "</div></td>\n";
-            }
-            else
-            {
-               // strings
-              echo "<td title=\"" . htmlspecialchars($col_value) . "\"><div>";
-              echo htmlspecialchars($col_value);
-              echo "</div></td>\n";
-            }
-            break;
-        }  // end switch
-      }
-    }  // end foreach
-
-    echo "</tr>\n";
-    
-  }  // end while
+  }
   
-  echo "</tbody>\n";
+  if (!$ajax)
+  {
+    echo "</tbody>\n";
   
-  echo "</table>\n";
-  echo "</div>\n";
+    echo "</table>\n";
+    echo "</div>\n";
+  }
   
 }   // ($initial_user_creation != 1)
 
-output_trailer();
+if ($ajax)
+{
+  echo json_encode($json_data);
+}
+else
+{
+  output_trailer();
+}
 
 ?>

Modified: mrbs/trunk/web/jquery/datatables/css/mrbs-table.css
===================================================================
--- mrbs/trunk/web/jquery/datatables/css/mrbs-table.css 2012-07-20 11:31:37 UTC 
(rev 2342)
+++ mrbs/trunk/web/jquery/datatables/css/mrbs-table.css 2012-07-20 14:29:27 UTC 
(rev 2343)
@@ -563,3 +563,9 @@
   display: none;
 }
 
+table.display span.normal {
+  display: inline;
+}
+
+
+

Modified: mrbs/trunk/web/js/edit_users.js.php
===================================================================
--- mrbs/trunk/web/js/edit_users.js.php 2012-07-20 11:31:37 UTC (rev 2342)
+++ mrbs/trunk/web/js/edit_users.js.php 2012-07-20 14:29:27 UTC (rev 2343)
@@ -5,7 +5,7 @@
 require "../defaultincludes.inc";
 
 header("Content-type: application/x-javascript");
-expires_header(60*30); // 30 minute expiry
+expires_header(0); // Cannot cache file because it depends on $HTTP_REFERER
 
 // 
=================================================================================
 
@@ -19,6 +19,20 @@
   <?php // Turn the list of users into a dataTable ?>
   
   var tableOptions = new Object();
+  <?php
+  // Use an Ajax source if we can - gives much better performance for large 
tables
+  if (function_exists('json_encode'))
+  {
+    if (strpos($HTTP_REFERER, '?') !== FALSE)
+    {
+      list( ,$query_string) = explode('?', $HTTP_REFERER, 2);
+    }
+    $ajax_url = "edit_users.php?" . (empty($query_string) ? '' : '&') . 
"ajax=1";
+    ?>
+    tableOptions.sAjaxSource = "<?php echo $ajax_url ?>";
+    <?php
+  }
+  ?>
   <?php // The Rights column has a span with title for sorting ?>
   tableOptions.aoColumnDefs = [{"sType": "title-numeric", "aTargets": [1]}]; 
   var usersTable = makeDataTable('#users_table',

Modified: mrbs/trunk/web/js/general.js.php
===================================================================
--- mrbs/trunk/web/js/general.js.php    2012-07-20 11:31:37 UTC (rev 2342)
+++ mrbs/trunk/web/js/general.js.php    2012-07-20 14:29:27 UTC (rev 2343)
@@ -29,6 +29,8 @@
   // (which will be if JavaScript is enabled and we're not running IE6 or 
below).   We
   // need to know this because when we're using an Ajax data source we don't 
want to send
   // the HTML version of the table data.
+  //
+  // Also add 'datatable=1' to the link for the user list for the same reason
   ?>
   if (!lteIE6)
   {
@@ -37,6 +39,12 @@
         name: 'datatable',
         value: '1'
       }).appendTo('#header_search');
+      
+    var userList = $('#user_list_link');
+    href = userList.attr('href');
+    href += (href.indexOf('?') < 0) ? '?' : '&';
+    href += 'datatable=1';
+    userList.attr('href', href);
   }
   
   <?php

Modified: mrbs/trunk/web/session/session_cookie.inc
===================================================================
--- mrbs/trunk/web/session/session_cookie.inc   2012-07-20 11:31:37 UTC (rev 
2342)
+++ mrbs/trunk/web/session/session_cookie.inc   2012-07-20 14:29:27 UTC (rev 
2343)
@@ -313,7 +313,7 @@
   }
   if (isset($user_list_link)) 
   {
-    print "<a href=\"$user_list_link\">" . get_vocab('user_list') . "</a>\n";
+    print "<a id=\"user_list_link\" href=\"$user_list_link\">" . 
get_vocab('user_list') . "</a>\n";
   }
 }
 

Modified: mrbs/trunk/web/session/session_http.inc
===================================================================
--- mrbs/trunk/web/session/session_http.inc     2012-07-20 11:31:37 UTC (rev 
2342)
+++ mrbs/trunk/web/session/session_http.inc     2012-07-20 14:29:27 UTC (rev 
2343)
@@ -122,7 +122,7 @@
   }
   if (isset($user_list_link))
   {
-    print "<a href=\"$user_list_link\">" . get_vocab('user_list') . "</a>\n" ;
+    print "<a id=\"user_list_link\" href=\"$user_list_link\">" . 
get_vocab('user_list') . "</a>\n" ;
   } 
 }
 ?>

Modified: mrbs/trunk/web/session/session_php.inc
===================================================================
--- mrbs/trunk/web/session/session_php.inc      2012-07-20 11:31:37 UTC (rev 
2342)
+++ mrbs/trunk/web/session/session_php.inc      2012-07-20 14:29:27 UTC (rev 
2343)
@@ -266,7 +266,7 @@
   } 
   if (isset($user_list_link))
   {
-    print "<a href=\"$user_list_link\">" . get_vocab('user_list') . "</a>\n";
+    print "<a id=\"user_list_link\" href=\"$user_list_link\">" . 
get_vocab('user_list') . "</a>\n";
   }
 }
 ?>

Modified: mrbs/trunk/web/session/session_remote_user.inc
===================================================================
--- mrbs/trunk/web/session/session_remote_user.inc      2012-07-20 11:31:37 UTC 
(rev 2342)
+++ mrbs/trunk/web/session/session_remote_user.inc      2012-07-20 14:29:27 UTC 
(rev 2343)
@@ -74,7 +74,7 @@
 <?php
     if (isset($user_list_link))
     {
-      print "<a href='$user_list_link'>" . get_vocab('user_list') . "</a>\n" ;
+      print "<a id=\"user_list_link\" href=\"$user_list_link\">" . 
get_vocab('user_list') . "</a>\n" ;
     }
 
     // Retrieve logout link from configuration, if specified

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Mrbs-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mrbs-commits

Reply via email to