Index: README.txt
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/user_relationships/README.txt,v
retrieving revision 1.2
diff -u -r1.2 README.txt
--- README.txt	9 Sep 2007 07:52:35 -0000	1.2
+++ README.txt	10 Oct 2007 23:13:39 -0000
@@ -29,6 +29,49 @@
 3. Create relationship types in "User Management -> User Relationships -> Add relationship"
 
 
+Memcache Users
+--------------
+
+The User Relationships module uses drupal's caching API to save results across page loads. The memcache
+module replaces drupal's default API with it's own implementations of cache_set, cache_get and
+cache_clear_all. Unfortunately, memcache's implementation of cache_clear_all doesn't honor the third
+(wildcard) parameter. If you have memcache installed, then the cache will not be properly cleared when
+you delete a user or a relationship type, resulting in stale data that may persist indefinitely.
+
+If you have memcache installed, you should implement the following two hooks in your module:
+
+/*
+ * Implementation of hook_user()
+ */
+function YOURMODULE_user($op, &$edit, &$account, $category = NULL) {
+  switch ($op) {
+    case 'delete':
+      if (module_exists('memcache')) {
+        // memcache's implementation of cache_clear_all doesn't support wildcarding,
+        // so wipe the entire user relationship cache by passing a null cache id
+        dpm("Deleting a user - clearing UR cache");
+        cache_clear_all(NULL, 'cache_user_relationships');
+      }
+      break;
+  }
+}
+
+/*
+ * Implementation of hook_user_relationships()
+ */
+function YOURMODULE_user_relationships($type, &$relationship, $category = NULL) {
+  switch ($type) {
+    case 'delete type':
+      if (module_exists('memcache')) {
+        // memcache's implementation of cache_clear_all doesn't support wildcarding,
+        // so wipe the entire user relationship cache by passing a null cache id
+        cache_clear_all(NULL, 'cache_user_relationships');
+      }
+      break;
+  }
+}
+
+
 Developers
 ------------
 I tried to make this module as modular as possible (is that a horrible sentence? I don't care).
Index: user_relationships_api.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/user_relationships/user_relationships_api.inc,v
retrieving revision 1.11
diff -u -r1.11 user_relationships_api.inc
--- user_relationships_api.inc	8 Oct 2007 19:49:37 -0000	1.11
+++ user_relationships_api.inc	10 Oct 2007 23:13:39 -0000
@@ -10,38 +10,37 @@
  *
  * @param $array
  *    An associative array of attributes to search for in selecting the
- *    relationship, such as id or name.
+ *    relationship, such as rtid or name. Attributes must match column names
+ *    in the user_relationships table.
  *
  * @return
  *    object of the requested relationship type
  *
  */
-function user_relationships_relationship_type_load($array = array()) {
-  static $user_relationship_types = array();
-  $cache_key = implode('', array_keys($array) + $array);
-
-  if (!$user_relationship_types[$cache_key]) {
-    $query  = array();
-    $params = array();
-
-    foreach($array as $key => $value) {
-      if ($key == 'rtid') {
-        $query[] = "$key = %d";
-        $params[] = $value;
+function user_relationships_relationship_type_load($criteria = array()) {
+  if (!sizeof($criteria)) {
+    return NULL;
+  }
+
+  $types = user_relationships_relationship_types_load();
+  foreach ($types as $type) {
+    $found = TRUE; // assume this is the type we're looking for
+
+    foreach($criteria as $column => $value) {
+      $column = strtolower($column);
+      if ($column == 'name' || $column == 'plural_name') {
+        $value = strtolower($value);
       }
-      else {
-        $query[]= "LOWER($key) = LOWER('%s')";
-        $params[] = $value;
+
+      if ($type->$column != $value) {
+        $found=FALSE; // value doesn't match, so this isn't the type after all
       }
     }
-    $relationship = db_fetch_object(db_query('SELECT * FROM {user_relationship_types} WHERE '. implode(' AND ', $query), $params));
-
-    _user_relationships_invoke('load type', $relationship);
-
-    $user_relationship_types[$cache_key] = $relationship;
+    if ($found) {
+      return $type;
+    }
   }
-
-  return $user_relationship_types[$cache_key];
+  return NULL;
 }
 
 /**
@@ -78,15 +77,20 @@
 
   if (!key_exists($uid, $relationships)) {
     $relationships[$uid] = array();
-
-    $results = db_query(
-       'SELECT r.*, rt.name, rt.plural_name, rt.is_oneway FROM {user_relationships} r, {user_relationship_types} rt
-        WHERE (requester_id = %d OR requestee_id = %d)
-          AND r.rtid = rt.rtid',
-      $uid, $uid
-    );
-    while ($relationship = db_fetch_object($results)) {
-      $relationships[$uid][] = $relationship;
+    if (($cache = cache_get("user_relationships_relationships_{$uid}", 'cache_user_relationships')) && !empty($cache->data)) {
+      $relationships[$uid] = unserialize($cache->data);
+    }
+    else {
+      $results = db_query(
+         'SELECT r.*, rt.name, rt.plural_name, rt.is_oneway FROM {user_relationships} r, {user_relationship_types} rt
+          WHERE (requester_id = %d OR requestee_id = %d)
+            AND r.rtid = rt.rtid',
+        $uid, $uid
+      );
+      while ($relationship = db_fetch_object($results)) {
+        $relationships[$uid][] = $relationship;
+      }
+      cache_set("user_relationships_relationships_{$uid}", 'cache_user_relationships', serialize($relationships[$uid]));
     }
   }
 
@@ -107,7 +111,10 @@
   static $user_relationships = array(); 
 
   if (!$user_relationships[$rid]) {
-    if ($relationship = db_fetch_object(db_query("SELECT * FROM {user_relationships} WHERE rid = %d", $rid))) {
+    if (($cache = cache_get("user_relationships_relationship_{$rid}", 'cache_user_relationships')) && !empty($cache->date)) {
+      $user_relationships[$rid] = unserialize($cache->data);
+    }
+    elseif ($relationship = db_fetch_object(db_query("SELECT * FROM {user_relationships} WHERE rid = %d", $rid))) {
       $relationship->requester    = user_load(array('uid' => $relationship->requester_id));
       $relationship->requestee    = user_load(array('uid' => $relationship->requestee_id));
       $relationship->type         = user_relationships_relationship_type_load(array('rtid' => $relationship->rtid));
@@ -116,6 +123,7 @@
 
       _user_relationships_invoke('load', $relationship);
       $user_relationships[$rid] = $relationship;
+      cache_set("user_relationships_relationship_{$rid}", 'cache_user_relationships', serialize($relationship));
     }
   }
 
@@ -183,6 +191,8 @@
     $relationship_type->rtid,
     ($approved ? 1 : 0)
   );
+  cache_clear_all("user_relationships_relationships_{$requester->uid}", 'cache_user_relationships');
+  cache_clear_all("user_relationships_relationships_{$requestee->uid}", 'cache_user_relationships');
 
   $relationship = user_relationships_relationship_load($rid);
   _user_relationships_invoke('insert', $relationship);
@@ -207,6 +217,7 @@
   _user_relationships_invoke('update', $updated_relationship);
 
   db_query("DELETE FROM {user_relationships} WHERE rid = %d", $relationship->rid);
+  cache_clear_all("user_relationships_relationship_{$relationship->rid}", 'cache_user_relationships');
 
   $updated_relationship->rid = db_next_id('{user_relationships}_id');
   db_query(
@@ -219,6 +230,11 @@
     ($updated_relationship->approved ? 1 : 0),
     $relationship->created_at
   );
+  // requester and requestee should be the same in the old and new relationships, but better safe than sorry
+  cache_clear_all("user_relationships_relationships_{$relationship->requester->uid}", 'cache_user_relationships');
+  cache_clear_all("user_relationships_relationships_{$relationship->requestee->uid}", 'cache_user_relationships');
+  cache_clear_all("user_relationships_relationships_{$updated_relationship->requester->uid}", 'cache_user_relationships');
+  cache_clear_all("user_relationships_relationships_{$updated_relationship->requestee->uid}", 'cache_user_relationships');
 
   return $updated_relationship;
 }
@@ -238,8 +254,11 @@
 function user_relationships_delete_relationship(&$relationship, &$deleted_by, $op = 'remove') {
   $relationship->deleted_by = $deleted_by;
   db_query("DELETE FROM {user_relationships} WHERE rid = %d", $relationship->rid);
+  cache_clear_all("user_relationships_relationship_{$relationship->rid}", 'cache_user_relationships');
 
   _user_relationships_invoke('delete', $relationship, $op);
+  cache_clear_all("user_relationships_relationships_{$relationship->requester_id}", 'cache_user_relationships');
+  cache_clear_all("user_relationships_relationships_{$relationship->requestee_id}", 'cache_user_relationships');
 }
 
 
Index: user_relationships_actions.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/user_relationships/user_relationships_actions.inc,v
retrieving revision 1.12
diff -u -r1.12 user_relationships_actions.inc
--- user_relationships_actions.inc	9 Oct 2007 01:22:09 -0000	1.12
+++ user_relationships_actions.inc	10 Oct 2007 23:13:39 -0000
@@ -88,6 +88,7 @@
 function user_relationships_type_delete_submit($form_id, &$form_values) {
   $rtid = arg(4);
 
+  cache_clear_all("user_relationships", 'cache_user_relationships', TRUE);
   db_query("DELETE FROM {user_relationship_types} WHERE rtid = %d", $rtid);
   db_query("DELETE FROM {user_relationships} WHERE rtid = %d", $rtid);
 
Index: user_relationships_hooks.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/user_relationships/user_relationships_hooks.inc,v
retrieving revision 1.10
diff -u -r1.10 user_relationships_hooks.inc
--- user_relationships_hooks.inc	8 Oct 2007 19:49:37 -0000	1.10
+++ user_relationships_hooks.inc	10 Oct 2007 23:13:39 -0000
@@ -224,6 +224,7 @@
 
   case 'delete':
     db_query("DELETE FROM {user_relationships} WHERE requester_id = %d OR requestee_id = %d", $account->uid, $account->uid);
+    cache_clear_all("user_relationships", 'cache_user_relationships', TRUE);
     break;
 
   case 'form':
Index: user_relationships.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/user_relationships/user_relationships.install,v
retrieving revision 1.5
diff -u -r1.5 user_relationships.install
--- user_relationships.install	25 Sep 2007 20:35:26 -0000	1.5
+++ user_relationships.install	11 Oct 2007 00:01:11 -0000
@@ -58,7 +58,18 @@
       KEY requester_id (requester_id),
       KEY requestee_id (requestee_id),
       KEY rtid (rtid)
-    ) /*!40100 DEFAULT CHARACTER SET utf8*/;"
+    ) /*!40100 DEFAULT CHARACTER SET utf8*/;",
+
+    "CREATE TABLE {cache_user_relationships} (
+      cid varchar(255) NOT NULL default '',
+      data longblob,
+      expire int(11) NOT NULL default 0,
+      created int(11) NOT NULL default 0,
+      headers text,
+      serialized int(1) NOT NULL default 0,
+      PRIMARY KEY (cid),
+      KEY expire (expire)
+    ) /*!40100 DEFAULT CHARACTER SET utf8*/;",
   );
   _user_relationships_installation_query($queries);
 }
@@ -69,6 +80,7 @@
 function user_relationships_uninstall() {
   db_query('DROP TABLE {user_relationships}');
   db_query('DROP TABLE {user_relationship_types}');
+  db_query('DROP TABLE {cache_user_relationships}');
 
   variable_del('user_relationships_require_approval');
   variable_del('user_relationships_allow_multiple');
@@ -106,3 +118,21 @@
     "ALTER TABLE {user_relationship_types} ADD plural_name varchar(255) NOT NULL default '' after name;"
   ));
 }
+
+/**
+ * Update 4: Add separate cache table for user relationship data
+ */
+function user_relationships_update_4() {
+  _user_relationships_installation_query(array(
+    "CREATE TABLE {cache_user_relationships} (
+      cid varchar(255) NOT NULL default '',
+      data longblob,
+      expire int(11) NOT NULL default 0,
+      created int(11) NOT NULL default 0,
+      headers text,
+      serialized int(1) NOT NULL default 0,
+      PRIMARY KEY (cid),
+      KEY expire (expire)
+    ) /*!40100 DEFAULT CHARACTER SET utf8*/;"
+  ));
+}
