diff -urpN og.module og.module
--- og.module	2009-01-02 05:58:21.000000000 +0200
+++ og.module	2009-01-20 17:33:23.000000000 +0200
@@ -424,121 +424,133 @@ function og_og($op, $gid, $uid, $args) {
 }
 
 /**
- * Set group context based on URL. Modules may override what we set here.
- * Set a custom theme based on what group is being displayed (if any).
- * Be smart about selecting the 'active' group for ambiguous urls like node/$nid
- * TODOL see http://api.drupal.org/api/function/menu_get_object/6
+ * Set group context using the menu system.
+ *
+ * Modules may override the custom theme and group context set here.
+ * @see og_set_group_context().
  */
 function og_determine_context() {
-  global $custom_theme;
-  $group_node = NULL; // a node object containing the 'active' group for this request
-  
-  // Recognize context when handling a request from a Views ajax block. See views_ajax().
-  $path = isset($_REQUEST['view_path']) ? $_REQUEST['view_path'] : NULL;
+  global $user;
+  $item = menu_get_item();
+  $object = menu_get_object();
+
+  // Use the menu system to get the path.
+  $path = $item['path'];
 
-  if (arg(0, $path) == 'og' && is_numeric(arg(2, $path))) {
-    $group_node = og_set_theme(arg(2, $path));
+  // Check if this is an existing node.
+  if (!empty($object->nid)) {
+    $node = $object;
+  }
+  // Check if we are in the node add page.
+  elseif (strpos($path, 'node/add') === 0 && !empty($_REQUEST['gids'])) {
+    // URL pattern: node/add/story?gids[]=1
+    $gid = intval(current($_REQUEST['gids']));
+    $node = node_load($gid);
   }
-  elseif (arg(0, $path) == 'node' && is_numeric(arg(1, $path))) {
-    $group_node = og_set_theme(arg(1, $path));
+  elseif ($item['map'][0] == 'og' && !empty($item['map'][2])) {
+    $node = menu_get_object('node', 2);
   }
-  elseif (arg(0, $path) == 'node' && arg(1, $path) == 'add' && arg(2, $path) == 'book' && arg(3, $path) == 'parent') {
-    $group_node = og_set_theme(arg(4, $path));
-    $_REQUEST['edit']['og_groups'][] = $group_node->nid; // checks the right box on node form
+  elseif ($path == 'comment/reply/%') {
+    $node = $item['page_arguments'][0];
   }
-  elseif (arg(0, $path) == 'node' && arg(1, $path) == 'add' && isset($_REQUEST['gids'])) {
-    $gid = intval(current($_REQUEST['gids']));
-    $group_node = node_load($gid);
-    $custom_theme = $group_node->og_theme;
+  elseif ($path == 'comment/edit' || $path == 'comment/delete') {
+    // Get the node from the comment object.
+    $comment = _comment_load($item['page_arguments'][0]);
+    $node = node_load($comment->nid);
   }
-  elseif (arg(0, $path) == 'comment' && in_array(arg(1, $path), array('edit', 'delete')) && is_numeric(arg(2, $path))) {
-    $nid = db_result(db_query('SELECT nid FROM {comments} WHERE cid = %d', arg(2, $path)));
-    $group_node = og_set_theme($nid);
+
+  if (!empty($node)) {
+    $group_node = og_determine_context_get_group($node);
+    og_set_theme($group_node);
+    og_set_group_context($group_node);
   }
-  elseif (arg(0, $path) == 'comment' && is_numeric(arg(2, $path))) {
-    // comment/reply/cid/nid URL pattern. 
-    $group_node = og_set_theme(arg(2, $path));
+  return !empty($group_node) ? $group_node : NULL;
+}
+
+/**
+ * Helper function; Find the most appropriate group node to be set the group
+ * conext.
+ * @param $node
+ *   The node that the context should be retrieved from.
+ *   It can be a group node or a group post.
+ * @see
+ * og_determine_context().
+ */
+function og_determine_context_get_group($node) {
+  global $user;
+  if (og_is_group_type($node->type) && (user_access('administer organic groups') || !empty($user->og_groups[$node->nid]))) {
+    $group_node = $node;
   }
-  elseif (arg(0, $path) == 'comment' && is_numeric(arg(2, $path))) {
-    // comment/reply/cid/nid URL pattern. 
-    $group_node = og_set_theme(arg(2, $path));
+  elseif (og_is_group_post_type($node->type) && count($node->og_groups)) {
+    // Group post belongs to multiple groups. Selection order:
+    // 1) URL has gids[] and user is a group member.
+    // 2) The group we showed on the prior page view (if any).
+    // 3) The only or one of the group(s) the current user is a member of.
+    // 4) The first group, if the user has 'administer organic groups'
+    // permission.
+    if (!empty($_GET['gids']) && (user_access('administer organic groups') || !empty($user->og_groups[current($_GET['gids'])]))) {
+      $group = intval(current($_GET['gids']));
+    }
+    elseif (isset($_SESSION['og_last']) && in_array($_SESSION['og_last'], $node->og_groups)) {
+      $group = $_SESSION['og_last'];
+    }
+    // Intersect the node's groups with the user's groups.
+    elseif (!empty($user->og_groups) && ($gid = current(array_intersect($node->og_groups, array_keys($user->og_groups))))) {
+      $group = $gid;
+    }
+    elseif (user_access('administer organic groups')) {
+      $group = current($node->og_groups);
+    }
+    if (!empty($group)) {
+      $group_node = node_load($group);
+    }
   }
-
-  return og_set_group_context($group_node);
+  return !empty($group_node) ? $group_node : NULL;
 }
 
 /**
- * API function for getting the group context (if any) for the current request. Used
- * for things like setting current theme and breadcrumbs. This context is set during og_determine_context()
- *
- * @return $node object
+ * API function for getting the group context (if any) for the current request.
+ * Used for things like setting current theme and breadcrumbs.
+ * This context is set during og_determine_context()
+ * @return
+ *   The group node object if exists.
  */
 function og_get_group_context() {
   return og_set_group_context();
 }
 
 /**
- * API function for setting the group context for the current request. Modules may set this as needed. 
+ * API function; Set the group context for the current request.
+ * Modules may set this as needed.
  * This context is originally set during og_determine_context().
- *
+ * @param $node
+ *   The node that context should be retrieved from.
  * @return $node object
  */
-function og_set_group_context($group_node = NULL) {
+function og_set_group_context($node = NULL) {
   static $stored_group_node;
-  
-  if (is_object($group_node) && og_is_group_type($group_node->type)) {
-    $stored_group_node = $group_node;
+  if (is_object($node)) {
+    $stored_group_node = og_determine_context_get_group($node);
   }
   return $stored_group_node;
 }
 
-function og_set_theme($nid) {
+/**
+ * API function; Set the theme for the current request.
+ * @param $node
+ *   Pass the node object or the node id.
+ * @return
+ *   The group node object.
+ */
+function og_set_theme($group_node) {
   global $custom_theme, $user;
-  $node = node_load(intval($nid));
-  if (og_is_group_type($node->type)) {
-    if (!$custom_theme) {
-      $custom_theme = $node->og_theme;
-    }
-    return $node;
+  if (!is_object($group_node)) {
+    $group_node = node_load($group_node);
   }
-  elseif (isset($node->og_groups)) {
-    switch (count($node->og_groups)) {
-      case 0:
-        return NULL;
-      case 1:
-        $group_node = node_load(current($node->og_groups));
-        if (!$custom_theme) {
-          $custom_theme = $group_node->og_theme;
-        }
-        break;
-      default:
-        // Node is in multiple groups. Preference goes to the group we showed on the prior page view (if any),
-        // Then to a group the current user is a member of.
-        if (isset($_SESSION['og_last']) && in_array($_SESSION['og_last'], $node->og_groups)) {
-          $group_node = node_load($_SESSION['og_last']);
-          if (!$custom_theme) {
-            $custom_theme = $group_node->og_theme;
-          }
-        }
-        else {
-          $groups = array();
-          // intersect the node's groups with the user's groups
-          if ($user->uid) {
-            $groups = array_intersect($node->og_groups, array_keys($user->og_groups));
-          }
-          // no user is logged in, or none of the node's groups are the user's groups
-          if (empty($groups)) {
-            $groups = $node->og_groups;
-          }
-          // use array_shift and not [0] because array_intersect preserves keys
-          $group_node = node_load(array_shift($groups));
-          if (!$custom_theme) {
-            $custom_theme = $group_node->og_theme;
-          }
-        }
-    }
-    return $group_node;
+  if (!$custom_theme && !empty($group_node->og_theme)) {
+    $custom_theme = $group_node->og_theme;
   }
+  return $group_node;
 }
 
 /**
@@ -1670,30 +1682,55 @@ function og_msgid_server() {
   return strtolower($at);
 }
 
+/**
+ * Implementation of hook_form_alter().
+ */
 function og_form_alter(&$form, &$form_state, $form_id) {
+  global $user;
   // Add audience selection to node forms
   if (isset($form['#node']) && $form_id == $form['#node']->type .'_node_form') {
     $node = $form['#node'];
     if (og_is_group_type($node->type)) {
       $form = array_merge($form, og_group_form($node, $form_state));
-      
+
       // Don't trample on custom label.
       if (isset($form['body_field']) && $form['body_field']['body']['#title'] == t('Body')) {
         $form['body_field']['body']['#title'] = t('Mission statement');
         $form['body_field']['body']['#description'] = t('A welcome greeting for your group home page. Consider listing the group objectives and mission.');
       }
-      
+
       $form['author']['name']['#title'] = t('Group manager');
       $form['options']['sticky']['#title'] = t('Sticky at top of group home page and other lists.');
     }
     elseif (og_is_group_post_type($node->type)) {
-      if ($group_node = og_get_group_context()) {
+      if (!$group_node = og_get_group_context()){
+        if (!empty($form_state['values']['og_groups'])) {
+          $gids = array_filter($form_state['values']['og_groups']);
+          // Intersect the post's groups with the user's groups.
+          if (!empty($gids) && ($groups = array_intersect($gids, array_keys($user->og_groups)))) {
+            $gid = current($groups);
+            $group = node_load($gid);
+          }
+        }
+        elseif (!empty($node->nid)) {
+          $group = $node;
+        }
+        elseif (variable_get('og_audience_required', 0) == 1 && count($user->og_groups) == 1) {
+          $gid = current($user->og_groups);
+          $group = node_load($gid['nid']);
+        }
+        if (!empty($group)) {
+          $group_node = og_set_group_context($group);
+        }
+      }
+      if (!empty($group_node)) {
+        $group_node = og_get_group_context($group);
         $bc = og_get_breadcrumb($group_node);
         if (isset($node->nid)) {
           $bc[] = l($node->title, "node/$node->nid");
         }
         drupal_set_breadcrumb($bc);
-      } 
+      }
       og_form_add_og_audience($form, $form_state);
     }
   }
diff -urpN tests/og.context.test tests/og.context.test
--- tests/og.context.test	1970-01-01 02:00:00.000000000 +0200
+++ tests/og.context.test	2009-01-16 10:29:09.000000000 +0200
@@ -0,0 +1,118 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Context test for the organic groups module.
+ */
+
+require_once drupal_get_path('module', 'og') . '/tests/og_testcase.php';
+
+class OgContext extends OgTestCase {
+  function getInfo() {
+    return array(
+      'name'  => t('Organic groups context tests'),
+      'description' => t('Tests the context system that determines how a group should be presented to the user.'),
+      'group' => t('Organic groups'),
+    );
+  }
+
+  function setUp() {
+    parent::setUp('og');
+    // Create a user with admin permissions.
+    $web_admin = $this->drupalCreateUser(array('administer nodes', 'administer content types', 'access administration pages', 'administer site configuration', 'administer organic groups', 'administer blocks'));
+    $this->drupalLogin($web_admin);
+
+    // Create a group node content type.
+    $og_group_type = $this->drupalCreateContentType();
+    variable_set('og_content_type_usage_'. $og_group_type->name, 'group');
+    $this->group_type = $og_group_type->name;
+
+    // Create a second group node content type, so user is a member of
+    // two groups.
+    $og_group_type_second = $this->drupalCreateContentType();
+    variable_set('og_content_type_usage_'. $og_group_type_second->name, 'group');
+
+    // Create a group post content type.
+    $og_post_type = $this->drupalCreateContentType();
+    variable_set('og_content_type_usage_'. $og_post_type->name, 'group_post_standard');
+    $this->post_type = $og_post_type->name;
+
+    // Rebuild the menu so the new content types will appear in the menu.
+    menu_rebuild();
+
+    // Create a group node.
+    $this->group_nid = $this->addOgGroup($og_group_type->name);
+    // Create the second group node.
+    $this->addOgGroup($og_group_type_second->name);
+
+    // Create a post node.
+    $this->post_nid = $this->addOgPost($og_post_type->name, array($this->group_nid));
+
+    // Add the 'Group details' block (it's delta is 0).
+    $edit = array();
+    $edit['og_0[region]'] = 'left';
+    $this->drupalPost('admin/build/block', $edit, t('Save blocks'));
+
+    // Confirm that the block was moved to the proper region.
+    $this->assertText(t('The block settings have been updated.'), t('Block successfully added.'));
+  }
+
+  /**
+   * Test the context in different situations.
+   */
+  function testOgContex() {
+    // Prepare all the tests, with the URLs and if the block should appear or
+    // be hidden.
+    $tests = array(
+      'group node view' => array(
+        'path' => 'node/'. $this->group_nid,
+        'display' => TRUE,
+      ),
+      'group node add' => array(
+        'path' => 'node/add/'. $this->group_type,
+        'display' => FALSE,
+      ),
+      'group post view' => array(
+        'path' => 'node/'. $this->post_nid,
+        'display' => TRUE,
+      ),
+      'group post edit' => array(
+        'path' => 'node/'. $this->post_nid .'/edit',
+        'display' => TRUE,
+      ),
+      'group post delete' => array(
+        'path' => 'node/'. $this->post_nid .'/delete',
+        'display' => TRUE,
+      ),
+      'group post add' => array(
+        'path' => 'node/add/'. $this->post_type,
+        'display' => FALSE,
+      ),
+      'group post add with ?gids[] in the URL' => array(
+        'path' => 'node/add/'. $this->post_type,
+        'query' => 'gids[]='. $this->group_nid,
+        'display' => TRUE,
+      ),
+      "OG's menu callback (group manage)" => array(
+        'path' => 'og/manage/'. $this->group_nid,
+        'display' => TRUE,
+      ),
+    );
+
+    foreach ($tests as $test_name => $test) {
+      $this->drupalGet($test['path'], !empty($test['query']) ? array('query' => $test['query']) : array());
+      if ($test['display']) {
+        $assert_func = 'assertText';
+        $display = t('displayed');
+      }
+      else {
+        $assert_func = 'assertNoText';
+        $display = t('hidden');
+      }
+      // Confirm that the block is being displayed/ hidden.
+      $this->$assert_func(t('My membership'), t('Block successfully being @display on the %test_name page.', array('@display' => $display, '%test_name' => $test_name)));
+    }
+  }
+}
+
