diff -urp og_subgroups.module og_subgroups.module
--- og_subgroups.module	2008-11-22 20:01:53.000000000 +0200
+++ og_subgroups.module	2008-12-12 21:47:51.000000000 +0200
@@ -29,7 +29,7 @@ function og_subgroups_menu() {
     'description' => "Manage your site's subgroups outline.",
     'page callback' => 'drupal_get_form',
     'page arguments' => array('og_subgroups_admin_settings'),
-    'access arguments' => array('administer subgroups'),    
+    'access arguments' => array('administer subgroups'),
     'weight' => 1,
     'file' => 'og_subgroups.admin.inc',
    );
@@ -78,7 +78,7 @@ function og_subgroups_block($op = 'list'
           if ($book['bid'] == $current_bid) {
             // If the current page is a node associated with a book, the menu
             // needs to be retrieved.
-            $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book['menu_name'], $node->book));
+            $book_menus[$book_id] = menu_tree_output(menu_tree_all_data($node->book['menu_name'], NULL));
           }
           else {
             // Since we know we will only display a link to the top node, there
@@ -93,7 +93,7 @@ function og_subgroups_block($op = 'list'
       elseif ($current_bid) {
         // Only display this block when the user is browsing a book.
         $title = db_result(db_query(db_rewrite_sql('SELECT n.title FROM {node} n WHERE n.nid = %d'), $node->book['bid']));
-        // Only show the block if the user has view access for the top-level 
+        // Only show the block if the user has view access for the top-level
         // node.
         if ($title) {
           $tree = menu_tree_all_data($node->book['menu_name'], $node->book);
@@ -124,7 +124,7 @@ function og_subgroups_block($op = 'list'
 }
 
 /**
- * Propagate a group post along the subgroup outline. 
+ * Propagate a group post along the subgroup outline.
  *
  * @param $node
  *   The node object that is being inserted/ updated.
@@ -135,12 +135,12 @@ function og_subgroups_propogate_content(
   foreach ($nodes as $key => $value) {
     // Check that post isn't already assigned to the group.
     $save = FALSE;
-    if (og_is_group_post_type($node->type) && !in_array($key, $node->og_groups)) {  
+    if (og_is_group_post_type($node->type) && !in_array($key, $node->og_groups)) {
       // Add og's data to the group post node.
       $node->og_groups[] = $key;
       $node->og_groups_both[$key] = $value['title'];
       $save = TRUE;
-      
+
     }
     // Save the node only if it was changed.
     if ($save) {
@@ -155,58 +155,65 @@ function og_subgroups_propogate_content(
 function og_subgroups_og($op, $gid, $uid, $args = array()) {
   switch ($op) {
     case 'user insert':
-      og_subgroups_propogate_user($gid, $uid, $args);        
+      og_subgroups_propogate_user($gid, $uid, $args);
       break;
     case 'user update':
-      og_subgroups_propogate_user($gid, $uid, $args);        
+      og_subgroups_propogate_user($gid, $uid, $args);
       break;
-    case 'user delete': 
-      og_subgroups_propogate_user($gid, $uid, $args);      
+    case 'user delete':
+      og_subgroups_propogate_user($gid, $uid, $args);
       break;
-  }  
+  }
 }
 
 /**
 * Propagates members and admins along the subgroups outline.
-* 
+*
 * @param $gid
 *   The group id.
 * @param $uid
-*   The propagated user id. 
+*   The propagated user id.
 * @param $args
 *   Array with the updated action, as returned from hook_og()
 */
 function og_subgroups_propogate_user($gid, $uid, $args) {
-  if (!empty($args['og_subgroups'])) {
+  if (empty($args['og_subgroups'])) {
     global $user;
     if ($user->uid != $uid) {
-      $user = user_load(array('uid' => $uid));
+      $account = user_load(array('uid' => $uid));
+    }
+    else {
+      $account = $user;
     }
     $admin_propagate = variable_get('og_subgroups_propagate_type', 'admin_propagate');
     $is_admin = $args['is_admin'] && $admin_propagate != 'no_admin_propagate';
     $demote = variable_get('og_subgroups_propagate_demote', array());
-    
+
     if (!$is_admin && $admin_propagate == 'only_admin_propagate' && !$demote['remove_admin']) {
       // If propagate only admin rights and it's a regular membership
       // and there is no admin rights demotion - do nothing.
       // Like this we can escape redundant calculations.
-      return;        
+      return;
     }
-    elseif ($node = node_load($gid)) {     
-      $directions = variable_get('og_subgroups_propagate_member', array());      
+    elseif ($node = node_load($gid)) {
+      $directions = variable_get('og_subgroups_propagate_member', array());
       $nodes = og_subgroups_get_groups_for_propagate($node, $directions);
       // Remove the original group node from the nodes list.
       unset($nodes[$gid]);
-      foreach ($nodes as $group_nid => $value) {        
+      foreach ($nodes as $group_nid => $value) {
+        // TODO: OG should allow passing $args['og_subgroups'] as it currently
+        // loops over and over again.
         if (empty($args) && $demote['unsubscribe']) {
           // Remove user from groups.
-          og_delete_subscription($group_nid, $user->uid);         
+          og_delete_subscription($group_nid, $account->uid);
         }
-        // Check user isn't already subscribed with same rights.
-        // If demoting admin rights make sure user is a member of the group.
-        elseif (($member = !og_is_group_member($group_nid, TRUE, $user->uid) && !(!$is_admin && $admin_propagate == 'only_admin_propagate')) || ($is_admin && empty($user->og_groups[$group_nid]['is_admin']) && $admin_propagate !='no_admin_propagate') || ($member && !$is_admin && $demote['remove_admin'])) {
+        // Make sure:
+        // 1) User isn't a member;
+        // 2) or Admin propagation, and member isn't admin;
+        // 3) or Admin demotion and user is member of the group.
+        elseif (!og_is_group_member($group_nid, TRUE, $account->uid) || ($is_admin && !$account->og_groups[$group_nid]['is_admin']) || (!empty($account->og_groups[$group_nid]['is_admin']) && !$args['is_admin'] && $demote['remove_admin'])) {
           // Pass in the $args info about propagation done by og_subgroups module.
-          og_save_subscription($group_nid, $uid, array('is_active' => 1, 'is_admin' => $is_admin, 'og_subgroups' => TRUE));              
+          og_save_subscription($group_nid, $uid, array('is_active' => 1, 'is_admin' => $is_admin, 'og_subgroups' => TRUE));
         }
       }
     }
@@ -214,51 +221,56 @@ function og_subgroups_propogate_user($gi
 }
 
 /**
- * Helper function; get all the groups which content/ user should be propagated 
+ * Helper function; get all the groups which content/ user should be propagated
  * to.
  *
  * @param $node
  *   The loaded node object.
- * @return 
- *   The nids and depth relative to the menu item the node group node 
- *   belongs to. 
+ * @return
+ *   The nids and depth relative to the menu item the node group node
+ *   belongs to.
  */
 function og_subgroups_get_groups_for_propagate($node, $directions = array()) {
   $nodes = array();
-  // Clean up the directions of propagation.   
+  // Clean up the directions of propagation.
   $directions = array_filter($directions);
 
-  // Propagation can be done only if there is a direction and 
+  // Propagation can be done only if there is a direction and
   // on group posts and group nodes.
   // and if node belongs to any group(s).
-  if ($directions && (og_is_group_post_type($node->type) && $groups = og_get_node_groups($node)) || (og_is_group_type($node->type))) {      
-    if (empty($groups)) {
-      $groups[$node->nid] = $node->title; 
+  if ($directions && (og_is_group_post_type($node->type) || og_is_group_type($node->type))) {
+    if (!empty($node->og_groups)) {
+      // Node is a group post.
+      $groups = $node->og_groups;
+    }
+    else {
+      // Node is a group node.
+      $groups[$node->nid] = $node->nid;
     }
-    foreach ($groups as $gid => $title) {
+    foreach ($groups as $gid) {
       // Check if node isn't already loaded.
       if ($gid == $node->nid) {
-        $group_node = $node;      
+        $group_node = $node;
       }
       else {
-        $group_node = node_load($gid);  
-      }  
+        $group_node = node_load($gid);
+      }
       // Get the menu from root down.
-      $menu = menu_tree_all_data($group_node->book['menu_name'], $group_node->book);
-      
+      $menu = menu_tree_all_data($group_node->book['menu_name'], NULL);
+
       // Get the nids of every menu item.
       $node_links = array();
       menu_tree_collect_node_links($menu, $node_links);
-      
+
       // If direction is up, down and side then all groups will be used.
-      // Otherwise remove the unnecessary groups. 
+      // Otherwise remove the unnecessary groups.
       if (count($directions) != OG_SUBGROUPS_DIRECTION_COUNT && $node_links) {
         $mlid = array_values($node_links[$gid]);
         $mlid = $mlid[0]['mlid'];
         _og_subgroups_filter_groups($gid, $mlid, $node_links, $directions);
       }
-      
-      // Get all the nodes required for propagation. 
+
+      // Get all the nodes required for propagation.
       // Duplicate groups will be removed as it is an associative array.
       $nodes += $node_links;
     }
@@ -288,14 +300,14 @@ function _og_subgroups_filter_groups($gi
       $i = 1;
       while ($i <= MENU_MAX_DEPTH && $remove && $node_links[$gid][$mlid]['p'. $i] != 0) {
         $node_links[$gid][$mlid]['p'. $i] == $item_key ? $remove = FALSE : $i++;
-      }     
+      }
     }
     if (isset($directions['down'])) {
       // Get children parent is in their menu.
       $i = 1;
       while ($i <= MENU_MAX_DEPTH && $remove && $links[$item_key]['p'. $i] != 0) {
-        $links[$item_key]['p'. $i] == $mlid ? $remove = FALSE : $i++;    
-      }     
+        $links[$item_key]['p'. $i] == $mlid ? $remove = FALSE : $i++;
+      }
     }
     // Get brothers that have the same parent.
     if (isset($directions['side']) && $links[$item_key]['plid'] == $node_links[$gid][$mlid]['plid']) {
@@ -303,10 +315,10 @@ function _og_subgroups_filter_groups($gi
     }
     if (!$remove) {
       $group = node_load($key);
-      // Check node is a group node, as there might be non-group nodes 
+      // Check node is a group node, as there might be non-group nodes
       // in the book outline.
       if (!og_is_group_type($group->type)) {
-        $remove = TRUE;  
+        $remove = TRUE;
       }
     }
     if ($remove) {
diff -urp tests/og_subgroups_content_propagation.test tests/og_subgroups_content_propagation.test
--- tests/og_subgroups_content_propagation.test	2008-10-19 16:32:02.000000000 +0200
+++ tests/og_subgroups_content_propagation.test	2008-12-12 21:48:19.000000000 +0200
@@ -25,7 +25,8 @@ class OgSubgroupsContentPropagation exte
    *   |- Node 1 (book node)
    *    |- Node 2 (group node)
    *     |- Node 3 (group node)
-   *    |- Node 4 (group node)
+   *      |- Node 4 (group node)
+   *    |- Node 5 (group node)
    *
    */
   function setUp() {
@@ -55,11 +56,12 @@ class OgSubgroupsContentPropagation exte
 
     // Create the book hierarchy.
     $this->nodes = array();
-    $this->nodes[] = $this->addOgSubgroupsGroup($this->og_group_type, $book->nid); // Node 0
-    $this->nodes[] = $this->addOgSubgroupsGroup('book', $book->nid, $this->nodes['0']->book['mlid']); // Node 1
+    $this->nodes[] = $this->addOgSubgroupsGroup($this->og_group_type, $book->nid);                                  // Node 0
+    $this->nodes[] = $this->addOgSubgroupsGroup('book', $book->nid, $this->nodes['0']->book['mlid']);               // Node 1
     $this->nodes[] = $this->addOgSubgroupsGroup($this->og_group_type, $book->nid, $this->nodes['1']->book['mlid']); // Node 2
     $this->nodes[] = $this->addOgSubgroupsGroup($this->og_group_type, $book->nid, $this->nodes['2']->book['mlid']); // Node 3
-    $this->nodes[] = $this->addOgSubgroupsGroup($this->og_group_type, $book->nid, $this->nodes['1']->book['mlid']); // Node 4
+    $this->nodes[] = $this->addOgSubgroupsGroup($this->og_group_type, $book->nid, $this->nodes['3']->book['mlid']); // Node 4
+    $this->nodes[] = $this->addOgSubgroupsGroup($this->og_group_type, $book->nid, $this->nodes['1']->book['mlid']); // Node 5
 
     // The directions a content can propagate.
     $this->directions = array('up', 'down', 'side');
@@ -78,8 +80,8 @@ class OgSubgroupsContentPropagation exte
           $this->assertKeysExist($group_post->og_groups, array($this->nodes['2']->nid, $this->nodes['0']->nid), t('Content propagated up.'));
           break;
         case 'down':
-          // Node post should have propagated to node 3.
-          $this->assertKeysExist($group_post->og_groups, array($this->nodes['2']->nid, $this->nodes['3']->nid), t('Content propagated down.'));
+          // Node post should have propagated to node 3, 4.
+          $this->assertKeysExist($group_post->og_groups, array($this->nodes['2']->nid, $this->nodes['3']->nid, $this->nodes['4']->nid), t('Content propagated down.'));
           break;
         case 'side':
           // Node post should have propagated to node 4.
