Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.1087
diff -u -p -r1.1087 common.inc
--- includes/common.inc	13 Jan 2010 06:26:49 -0000	1.1087
+++ includes/common.inc	14 Jan 2010 04:39:00 -0000
@@ -6540,6 +6540,19 @@ function entity_path($entity_type, $enti
     return $info['path callback']($entity);
   }
 }
+/**
+ * Invokes entity insert/update hooks.
+ *
+ * @param $op
+ *   One of 'insert' or 'update'.
+ * @param $entity_type
+ *   The entity type; e.g. 'node' or 'user'.
+ * @param $entity
+ *   The entity object being operated on.
+ */
+function entity_invoke($op, $entity_type, $entity) {
+  module_invoke_all('entity_' . $op, $entity, $entity_type);
+}
 
 /**
  * Performs one or more XML-RPC request(s).
Index: includes/file.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/file.inc,v
retrieving revision 1.200
diff -u -p -r1.200 file.inc
--- includes/file.inc	30 Dec 2009 08:16:55 -0000	1.200
+++ includes/file.inc	14 Jan 2010 04:39:01 -0000
@@ -488,11 +488,13 @@ function file_save(stdClass $file) {
     drupal_write_record('file', $file);
     // Inform modules about the newly added file.
     module_invoke_all('file_insert', $file);
+    entity_invoke('insert', 'file', $file);
   }
   else {
     drupal_write_record('file', $file, 'fid');
     // Inform modules that the file has been updated.
     module_invoke_all('file_update', $file);
+    entity_invoke('update', 'file', $file);
   }
 
   return $file;
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.835
diff -u -p -r1.835 comment.module
--- modules/comment/comment.module	13 Jan 2010 06:44:31 -0000	1.835
+++ modules/comment/comment.module	14 Jan 2010 04:39:03 -0000
@@ -1369,6 +1369,7 @@ function comment_save($comment) {
       field_attach_update('comment', $comment);
       // Allow modules to respond to the updating of a comment.
       module_invoke_all('comment_update', $comment);
+      entity_invoke('update', 'comment', $comment);
       // Add an entry to the watchdog log.
       watchdog('content', 'Comment: updated %subject.', array('%subject' => $comment->subject), WATCHDOG_NOTICE, l(t('view'), 'comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid)));
     }
@@ -1452,6 +1453,7 @@ function comment_save($comment) {
 
       // Tell the other modules a new comment has been submitted.
       module_invoke_all('comment_insert', $comment);
+      entity_invoke('insert', 'comment', $comment);
       // Add an entry to the watchdog log.
       watchdog('content', 'Comment: added %subject.', array('%subject' => $comment->subject), WATCHDOG_NOTICE, l(t('view'), 'comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid)));
     }
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1211
diff -u -p -r1.1211 node.module
--- modules/node/node.module	13 Jan 2010 06:26:49 -0000	1.1211
+++ modules/node/node.module	14 Jan 2010 04:39:04 -0000
@@ -1035,6 +1035,7 @@ function node_save($node) {
     $function('node', $node);
 
     module_invoke_all('node_' . $op, $node);
+    entity_invoke($op, 'node', $node);
 
     // Update the node access table for this node.
     node_access_acquire_grants($node);
Index: modules/system/system.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v
retrieving revision 1.120
diff -u -p -r1.120 system.api.php
--- modules/system/system.api.php	13 Jan 2010 06:26:49 -0000	1.120
+++ modules/system/system.api.php	14 Jan 2010 04:39:07 -0000
@@ -221,6 +221,32 @@ function hook_entity_load($entities, $ty
 }
 
 /**
+ * Act on entities when inserted.
+ *
+ * Generic insert hook called for all entity types via entity_invoke().
+ *
+ * @param $entity
+ *   The entity object.
+ * @param $type
+ *   The type of entity being inserted (i.e. node, user, comment).
+ */
+function hook_entity_insert($entity, $type) {
+}
+
+/**
+ * Act on entities when updated.
+ *
+ * Generic update hook called for all entity types via entity_invoke().
+ *
+ * @param $entity
+ *   The entity object.
+ * @param $type
+ *   The type of entity being updated (i.e. node, user, comment).
+ */
+function hook_entity_update($entity, $type) {
+}
+
+/**
  * Define administrative paths.
  *
  * Modules may specify whether or not the paths they define in hook_menu() are
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.563
diff -u -p -r1.563 taxonomy.module
--- modules/taxonomy/taxonomy.module	13 Jan 2010 06:26:49 -0000	1.563
+++ modules/taxonomy/taxonomy.module	14 Jan 2010 04:39:07 -0000
@@ -338,12 +338,14 @@ function taxonomy_vocabulary_save($vocab
   if (!empty($vocabulary->vid) && !empty($vocabulary->name)) {
     $status = drupal_write_record('taxonomy_vocabulary', $vocabulary, 'vid');
     module_invoke_all('taxonomy_vocabulary_update', $vocabulary);
+    entity_invoke('update', 'taxonomy_vocabulary', $vocabulary);
   }
   elseif (empty($vocabulary->vid)) {
     $status = drupal_write_record('taxonomy_vocabulary', $vocabulary);
     field_attach_create_bundle('taxonomy_term', $vocabulary->machine_name);
     taxonomy_vocabulary_create_field($vocabulary);
     module_invoke_all('taxonomy_vocabulary_insert', $vocabulary);
+    entity_invoke('insert', 'taxonomy_vocabulary', $vocabulary);
   }
 
   cache_clear_all();
@@ -470,12 +473,14 @@ function taxonomy_term_save($term) {
     $status = drupal_write_record('taxonomy_term_data', $term, 'tid');
     field_attach_update('taxonomy_term', $term);
     module_invoke_all('taxonomy_term_update', $term);
+    entity_invoke('update', 'taxonomy_term', $term);
   }
   else {
     $status = drupal_write_record('taxonomy_term_data', $term);
     _taxonomy_clean_field_cache($term);
     field_attach_insert('taxonomy_term', $term);
     module_invoke_all('taxonomy_term_insert', $term);
+    entity_invoke('insert', 'taxonomy_term', $term);
   }
 
   db_delete('taxonomy_term_hierarchy')
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.1107
diff -u -p -r1.1107 user.module
--- modules/user/user.module	13 Jan 2010 06:44:31 -0000	1.1107
+++ modules/user/user.module	14 Jan 2010 04:39:08 -0000
@@ -482,6 +482,7 @@ function user_save($account, $edit = arr
       }
 
       user_module_invoke('update', $edit, $user, $category);
+      entity_invoke('update', 'user' $user);
     }
     else {
       // Allow 'uid' to be set by the caller. There is no danger of writing an
@@ -514,6 +515,7 @@ function user_save($account, $edit = arr
       field_attach_insert('user', $object);
 
       user_module_invoke('insert', $edit, $user, $category);
+      entity_invoke('insert', 'user', $user);
 
       // Note, we wait with saving the data column to prevent module-handled
       // fields from being saved there.
