--- og.module	2009-03-26 20:28:24.000000000 +0200
+++ og.module	2009-03-31 01:10:54.000000000 +0300
@@ -436,122 +436,121 @@ 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;
+  $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])) || $path == 'comment/reply/%') {
+    $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/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) == 'node' && arg(1, $path) == 'add' && isset($_REQUEST['gids'])) {
-    $gid = intval(current($_REQUEST['gids']));
-    $group_node = node_load($gid);
-    if (!$custom_theme)
-      $custom_theme = $group_node->og_theme;
+
+  if (!empty($node) && ($group_node = og_determine_context_get_group($node))) {
+    og_set_theme($group_node);
+    og_set_group_context($group_node);
+  }
+  return !empty($group_node) ? $group_node : NULL;
+}
+
+/**
+ * Helper function; Get an appropriate group node to be set as the group conext.
+ *
+ * @param $node
+ *   The node that the context should be retrieved from.
+ * @param $account
+ *   (optional) The account to check, if not given use currently logged in user.
+ * @return
+ *   The group node if exists and accesiable by the user.
+ * @see og_determine_context()
+ */
+function og_determine_context_get_group($node, $account = NULL) {
+  if (empty($account)) {
+    global $user;
+    $account = $user;
   }
-  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 (og_is_group_type($node->type)) {
+    $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) && !empty($node->og_groups)) {
+    // Get the group node from the group post.
+    $gid = current($node->og_groups);
+    $group_node = node_load($gid);
   }
-  elseif (arg(0, $path) == 'comment' && is_numeric(arg(2, $path))) {
-    // comment/reply/cid/nid URL pattern. 
-    $group_node = og_set_theme(arg(2, $path));
+  if (!empty($group_node) && node_access('view', $group_node, $account)) {
+    return $group_node;
   }
-
-  return og_set_group_context($group_node);
 }
 
 /**
- * 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()
+ * 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
+ * @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().
- *
- * @return $node object
+ * @param $node
+ *   The group node object that should be set as the context.
+ *   You can use og_determine_context_get_group() to assist you with finding
+ *   the appropriate group node.
+ * @return
+ *   The group node object if set.
  */
-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 (!empty($node) && og_is_group_type($node->type)) {
+    $stored_group_node = $node;
   }
-  return $stored_group_node;
+  return !empty($stored_group_node) ? $stored_group_node : NULL;
 }
 
-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;
 }
 
 /**
--- tests/og.context.test	1970-01-01 02:00:00.000000000 +0200
+++ tests/og.context.test	2009-03-31 01:12:03.000000000 +0300
@@ -0,0 +1,116 @@
+<?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'));
+    $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)));
+    }
+  }
+}
+
