? nodeprofile_deleteprofiles_try2.patch
Index: nodeprofile.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/nodeprofile/nodeprofile.install,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 nodeprofile.install
--- nodeprofile.install	10 Feb 2007 19:15:27 -0000	1.1.2.2
+++ nodeprofile.install	21 Feb 2007 18:56:07 -0000
@@ -1,6 +1,13 @@
 <?php
 // $Id: nodeprofile.install,v 1.1.2.2 2007/02/10 19:15:27 fago Exp $
 
+function nodeprofile_install() {
+  // Set the module weight to -1, so nodeprofile_user() gets called before
+  // node_user(), so that one can't set a node's uid to 0 on user deletion
+  // before the profile nodes are deleted.
+  db_query("UPDATE {system} SET weight = -1 WHERE name = 'nodeprofile'");
+}
+
 function nodeprofile_uninstall() {
   foreach (node_get_types('names') as $typename => $visiblename) {
     if (variable_get('nodeprofile_'. $typename, 0)) {
@@ -11,3 +18,12 @@
     }
   }
 }
+
+/**
+ * Set module weight to -1, as explained in nodeprofile_install().
+ */
+function nodeprofile_update_1() {
+  $ret = array();
+  $ret[] = update_sql("UPDATE {system} SET weight = -1 WHERE name = 'nodeprofile'");
+  return $ret;
+}
Index: nodeprofile.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/nodeprofile/nodeprofile.module,v
retrieving revision 1.7.2.1
diff -u -r1.7.2.1 nodeprofile.module
--- nodeprofile.module	3 Feb 2007 16:58:39 -0000	1.7.2.1
+++ nodeprofile.module	21 Feb 2007 18:56:07 -0000
@@ -150,3 +150,95 @@
     }
   }
 }
+
+/**
+ * Implementation of hook_user():
+ * Delete the profile node when the user is deleted.
+ */
+function nodeprofile_user($op, &$edit, &$account, $category = NULL) {
+  switch ($op) {
+    case 'delete':
+      if (!module_exists('usernode')) {
+        break;
+      }
+
+      // retrieve profile node types to be deleted
+      $typenames = array();
+      foreach (node_get_types('names') as $typename => $visiblename) {
+        if (is_nodeprofile($typename)) {
+          $typenames = array_merge($typenames, _nodeprofile_relation_descendants_dive($typename));
+        }
+      }
+
+      // Retrieve the matching profile nodes for this user by issueing an SQL
+      // query. node_load() doesn't work, because its own query still requires
+      // the user to be in the {user} table, which is not the case anymore.
+      // That node_load() doesn't work also means that node_delete() doesn't
+      // work, which is why we have to use _nodeprofile_node_delete() instead.
+
+      $cond = array();
+      $arguments = array();
+
+      foreach ($typenames as $typename) {
+        $cond[] = "type = '%s'";
+        $arguments[] = $typename;
+      }
+      $cond = implode(' OR ', $cond);
+      $arguments[] = $account->uid;
+
+      if ($cond) {
+        $result = db_query("SELECT * FROM {node} WHERE (". $cond .") ".
+                           "AND uid = %d", $arguments);
+
+        while ($node = db_fetch_object($result)) {
+          _nodeprofile_node_delete($node);
+        }
+      }
+      break;
+
+    default:
+      break;
+  }
+}
+
+/**
+ * Return an array containing the given type and its descendant relatives.
+ */
+function _nodeprofile_relation_descendants_dive($typename) {
+  $typenames = array($typename);
+  $children = nodefamily_get_child_types($typename);
+
+  foreach ($children as $child) {
+    $typenames = array_merge($typenames, _nodeprofile_relation_descendants_dive($child));
+  }
+  return $typenames;
+}
+
+/**
+ * The original node_delete() function uses node_load() to get the $node object.
+ * Unfortunately, when a hook_user('delete') is called, node_load() doesn't
+ * work anymore because the user has already been deleted, and node_load()
+ * still expects the user to exist in the {user} table.
+ *
+ * So this is a copy of node_delete(), with the only difference that it
+ * directly takes the $node object as argument instead of fetching it
+ * with node_load().
+ */
+function _nodeprofile_node_delete($node) {
+  db_query('DELETE FROM {node} WHERE nid = %d', $node->nid);
+  db_query('DELETE FROM {node_revisions} WHERE nid = %d', $node->nid);
+
+  // Call the node-specific callback (if any):
+  node_invoke($node, 'delete');
+  node_invoke_nodeapi($node, 'delete');
+
+  // Clear the cache so an anonymous poster can see the node being deleted.
+  cache_clear_all();
+
+  // Remove this node from the search index if needed.
+  if (function_exists('search_wipe')) {
+    search_wipe($node->nid, 'node');
+  }
+  drupal_set_message(t('%title has been deleted.', array('%title' => $node->title)));
+  watchdog('content', t('@type: deleted %title.', array('@type' => t($node->type), '%title' => $node->title)));
+}
