diff --git a/og_subgroups.common.inc b/og_subgroups.common.inc
index e69de29..fe4fd62 100644
--- a/og_subgroups.common.inc
+++ b/og_subgroups.common.inc
@@ -0,0 +1,390 @@
+<?php
+
+/**
+ * @file
+ * Common functions used in og_subgroups.
+ */
+
+/**
+ * Get parent groups.
+ *
+ * This functions works by traversing the tree from the current
+ * group up to the a root group, which has no parents.
+ * Since we want every path, even if branches are interconnected,
+ * we use forks to take note of the point in the current traversal
+ * where a group had more than one parent. When we are at the top
+ * (for this traversal) we reset the $parent array only from the fork
+ * to the root, and we continue.
+ * We also check for recursive loops.
+ *
+ * @param $entity_type
+ *   The entity type. Defaults to 'node'.
+ * @param $entity
+ *   The entity object or entity ID.
+ * @param $paths
+ *   An array used for tracking forked paths.
+ * @param $reverse
+ *   A boolean that determines whether or not to reverse returned array.
+ * @param $parents
+ *   An array used for tracking all parents.
+ */
+function og_subgroups_get_parents($entity_type = 'node', $entity, &$paths = array(), $reverse = FALSE, &$parents = array()) {
+  static $forks;
+  $groups = og_get_entity_groups($entity_type, $entity);
+  if (!empty($groups)) {
+    // We still have parents to record.
+    if (_og_subgroups_count_groups($groups) > 1) {
+      // There's a fork.
+      $forks[] = count($parents);
+    }
+    foreach ($groups as $group_type => $data) {
+      foreach ($data as $membership_id => $group_id) {
+        if (_og_subgroups_parent_search($group_type, $group_id, $parents)) {
+          // We found a parent we already found: this is a loop, which is a problem.
+          // We skip this parent, and we log this error.
+          // This should never happen, as we validate the parent group against loops.
+          watchdog('og_subgroups', "Loop detected in group tree: entity type: %type, id %id already present in tree: %parents ", array('%type' => $group_type, '%id' => $group_id, '%parents' => serialize($parents)), WATCHDOG_CRITICAL);
+        }
+        else {
+          // We can safely add this parent to the list.
+          $parents[] = array(
+            'type' => $group_type,
+            'id' => $group_id,
+          );
+          og_subgroups_get_parents($group_type, $group_id, $paths, $reverse, $parents);
+        }
+      }
+    }
+  }
+  else {
+    $paths[] = $reverse ? array_reverse($parents) : $parents;
+    if ($forks) {
+      $length = array_pop($forks);
+    }
+    else {
+      $length = 0;
+    }
+    $parents = array_slice($parents, 0, $length);
+  }
+}
+
+/**
+ * Helper function to count the number of groups in an array of results
+ *
+ * @param $groups
+ *   An array of groups as returned by og_get_entity_groups().
+ *
+ * @return
+ *   The number of groups in a groups array.
+ *
+ * @see: og_subgroups_get_parents()
+ */
+function _og_subgroups_count_groups($groups) {
+  $count = 0;
+  if ($groups) {
+    foreach ($groups as $type => $data) {
+      $count += count($data);
+    }
+  }
+  return $count;
+}
+
+/**
+ * Search for an entity among parents (used to detect and avoid loops).
+ *
+ * @param $entity_type
+ *   The entity type. Defaults to 'node'.
+ * @param $entity
+ *   The entity object or entity ID.
+ * @param $parents
+ *   An array of parents as returned by og_get_entity_groups().
+ *
+ * @return
+ *   The number of groups in a groups array.
+ *
+ * @see: og_subgroups_get_parents()
+ */
+function _og_subgroups_parent_search($entity_type, $entity, $parents) {
+  $result = FALSE;
+  foreach ($parents as $parent) {
+    if ($parent['type'] == $entity_type && $parent['id'] == $entity) {
+      $result = TRUE;
+      break;
+    }
+  }
+  return $result;
+}
+
+/**
+ * Add the loaded entity to all the entities in all the paths.
+ *
+ * @param $paths
+ *   An array used for tracking forked paths.
+ *
+ * @see: og_subgroups_get_parents()
+ */
+function og_subgroups_populate_paths(&$paths) {
+  $entities = array();
+  // Store all the entities divided in types.
+  foreach ($paths as $path) {
+    foreach ($path as $entity) {
+      $entities[$entity['type']][$entity['id']] = TRUE;
+    }
+  }
+  // We use entity_load() with multiple ids for performance.
+  foreach ($entities as $type => $ids) {
+    $loaded_entities[$type] = entity_load($type, array_keys($ids));
+  }
+  // Save the loaded entities into the paths.
+  foreach ($paths as $path_delta => $path) {
+    foreach ($path as $entity_delta => $entity) {
+      $paths[$path_delta][$entity_delta]['entity'] = $loaded_entities[$entity['type']][$entity['id']];
+    }
+  }
+}
+
+/**
+ * Get users that are associated with a group.
+ *
+ * @param $entity_type
+ *   The entity type. Defaults to 'node'.
+ * @param $entity
+ *   Optional; The entity object or entity ID.
+ * @param $states
+ *   Optional; Array with the state to return. Defaults to active.
+ *
+ * @return
+ *  An array with the entities' entity type as the key, and array - keyed by
+ *  the OG membership ID and the Entity ID as the value. If nothing found,
+ *  then an empty array.
+ */
+function og_subgroups_get_users_group($entity_type = 'node', $entity = NULL, $states = array(OG_STATE_ACTIVE)) {
+  $cache = &drupal_static(__FUNCTION__, array());
+  if (is_object($entity)) {
+    // Get the entity ID.
+    list($id) = entity_extract_ids($entity_type, $entity);
+  }
+  else {
+    $id = $entity;
+  }
+  // Get a string identifier of the states, so we can retrieve it from cache.
+  if ($states) {
+    sort($states);
+    $state_identifier = implode(':', $states);
+  }
+  else {
+    $state_identifier = 0;
+  }
+  if (isset($cache[$entity_type][$id][$state_identifier])) {
+    // Return cached values.
+    return $cache[$entity_type][$id][$state_identifier];
+  }
+  $cache[$entity_type][$id][$state_identifier] = array();
+  $query = new EntityFieldQuery();
+  $query
+  ->entityCondition('entity_type', 'og_membership', '=')
+  ->propertyCondition('entity_type', 'user', '=')
+  ->propertyCondition('group_type', $entity_type, '=')
+  ->propertyCondition('gid', $id, '=');
+
+  if ($states) {
+    $query->propertyCondition('state', $states, 'IN');
+  }
+  $result = $query->execute();
+  if (!empty($result['og_membership'])) {
+    // Get the group ID from the group membership.
+    $og_memberships = og_membership_load_multiple(array_keys($result['og_membership']));
+    foreach ($og_memberships as $og_membership) {
+      $cache[$entity_type][$id][$state_identifier]['user'][$og_membership->id] = $og_membership->etid;
+    }
+  }
+  return $cache[$entity_type][$id][$state_identifier];
+}
+
+/**
+ * Get non-users entities that are associated with a group.
+ *
+ * @param $entity_type
+ *   The entity type.
+ * @param $entity
+ *   The entity object or entity ID.
+ *
+ * @return
+ *  An array with the entities' entity type as the key, and array - keyed by
+ *  the OG membership ID and the Entity ID as the value. If nothing found,
+ *  then an empty array.
+ */
+function og_subgroups_get_associated_entities($entity_type, $entity) {
+  $cache = &drupal_static(__FUNCTION__, array());
+  if (is_object($entity)) {
+    // Get the entity ID.
+    list($id) = entity_extract_ids($entity_type, $entity);
+  }
+  else {
+    $id = $entity;
+  }
+  if (isset($cache[$entity_type][$id])) {
+    // Return cached values.
+    return $cache[$entity_type][$id];
+  }
+  $cache[$entity_type][$id] = array();
+  $query = new EntityFieldQuery();
+  $query
+  ->entityCondition('entity_type', 'og_membership', '=')
+  ->propertyCondition('entity_type', 'user', '!=')
+  ->propertyCondition('group_type', $entity_type, '=')
+  ->propertyCondition('gid', $id, '=');
+  $result = $query->execute();
+  if (!empty($result['og_membership'])) {
+    // Get the group ID from the group membership.
+    $og_memberships = og_membership_load_multiple(array_keys($result['og_membership']));
+    foreach ($og_memberships as $og_membership) {
+      $cache[$entity_type][$id][$og_membership->entity_type][$og_membership->id] = $og_membership->etid;
+    }
+  }
+  return $cache[$entity_type][$id];
+}
+
+/**
+ * Return an array of inherited users from the parent groups that
+ * allow for user inheritance.
+ *
+ * @param $entity_type
+ *   The entity type. Defaults to 'node'.
+ * @param $entity
+ *   Optional; The entity object or entity ID.
+ * @param $states
+ *   Optional; Array with the state to return. Defaults to active.
+ *
+ * @return
+ *  An array with the entities' entity type as the key, and array - keyed by
+ *  the OG membership ID and the Entity ID as the value. If nothing found,
+ *  then an empty array.
+ *
+ * @see: og_subgroups_views_pre_render()
+ */
+function _og_subgroups_get_inherited_users($group_type, $group_id, $states = array(OG_STATE_ACTIVE)) {
+  $inherited_users = array();
+  $parents = _og_subgroups_get_unique_parents($group_type, $group_id);
+  foreach ($parents as $parent) {
+    $users = og_subgroups_get_users_group($parent['type'], $parent['id'], $states);
+    foreach ($users['user'] as $membership_id => $uid) {
+      $roles = og_get_user_roles($parent['type'], $parent['id'], $uid);
+      $membership_ids[] = $membership_id;
+      $user_ids[] = $uid;
+      $inherited_from[$parent['type']][] = $parent['id'];
+      $inherited_users[$uid][] = array(
+        'uid' => $uid,
+        'membership_id' => $membership_id,
+        'roles' => $roles,
+        'inherited_from' => array(
+          'type' => $parent['type'],
+          'id' => $parent['id'],
+        )
+      );
+    }
+  }
+  // Populate the array with *_multiple() functions (performance).
+  if (!empty($membership_ids)) {
+    $memberships = og_membership_load_multiple($membership_ids);
+    $accounts = user_load_multiple($user_ids);
+    foreach ($inherited_from as $type => $ids) {
+      $inherited_from_entities[$type] = entity_load($type, $ids);
+    }
+    foreach ($inherited_users as $uid => $inheritance) {
+      foreach ($inheritance as $delta => $data) {
+        $inherited_users[$uid][$delta]['user'] = $accounts[$uid];
+        $inherited_users[$uid][$delta]['membership'] = $memberships[$data['membership_id']];
+        $inherited_users[$uid][$delta]['inherited_from']['entity'] = $inherited_from_entities[$data['inherited_from']['type']][$data['inherited_from']['id']];
+      }
+    }
+  }
+  return $inherited_users;
+}
+
+/**
+ * Return an array of all the parent groups, optionally filtered
+ * including only the groups that allow for inheritance.
+ *
+ * @param $group_type
+ *   The group type.
+ * @param $group_id
+ *   The group ID.
+ * @param $filter
+ *   Boolean value for whether to return only groups that allow for inheritance.
+ *
+ * @return
+ *  An array with the entities' entity type and entity id as the key, and array
+ *  containing the entity type, entity id, and entity object as values.
+ *  If nothing is found, returns an empty array.
+ */
+function _og_subgroups_get_unique_parents($group_type, $group_id, $filter = TRUE) {
+  $groups = array();
+  og_subgroups_get_parents($group_type, $group_id, $paths);
+  og_subgroups_populate_paths($paths);
+  foreach ($paths as $path) {
+    foreach ($path as $group) {
+      $entity = $group['entity'];
+      if (!$filter || (isset($entity->{OG_USER_INHERITANCE_FIELD}) && $entity->{OG_USER_INHERITANCE_FIELD}[LANGUAGE_NONE][0]['value'] == 1)) {
+        $groups[$group['type'] . '-' . $group['id']] = $group;
+      }
+    }
+  }
+  return $groups;
+}
+
+/**
+ * Return all the groups a user belongs to because of inheritance.
+ *
+ * @param $account
+ *   A user object.
+ *
+ * @return
+ *   An array of inherited groups a user is a member of.
+ *
+ * @see: og_subgroups_node_grants()
+ *
+ * @todo: add static cache.
+ */
+function _og_subgroup_get_user_inherited_groups($account) {
+  $children_groups = array();
+  $groups = og_get_entity_groups('user', $account);
+  if (!empty($groups)) {
+    foreach ($groups as $group_type => $gids) {
+      foreach ($gids as $gid => $group_id) {
+        $group_entity = current(entity_load($group_type, array($group_id)));
+        if (isset($group_entity->{OG_USER_INHERITANCE_FIELD}[LANGUAGE_NONE][0]['value']) && $group_entity->{OG_USER_INHERITANCE_FIELD}[LANGUAGE_NONE][0]['value']) {
+          _og_subgroups_get_children_groups($group_type, $group_id, $children_groups);
+        }
+      }
+    }
+  }
+  return $children_groups;
+}
+
+/**
+ * Helper function for _og_subgroup_get_user_inherited_groups().
+ *
+ * @param $group_type
+ *   The group type.
+ * @param $group_id
+ *   The group ID.
+ * @param $children_groups
+ *   An array of children groups.
+ *
+ * @see: _og_subgroup_get_user_inherited_groups()
+ */
+function _og_subgroups_get_children_groups($group_type, $group_id, &$children_groups) {
+  $children = og_subgroups_get_associated_entities($group_type, $group_id);
+  foreach ($children as $children_type => $children_ids) {
+    $children_entities = entity_load($children_type, $children_ids);
+    foreach ($children_entities as $child_id => $child_entity) {
+      if (og_is_group($children_type, $child_entity)) {
+        $children_groups[$children_type][$child_id] = $child_entity;
+        if (isset($child_entity->{OG_USER_INHERITANCE_FIELD}[LANGUAGE_NONE][0]['value']) && $child_entity->{OG_USER_INHERITANCE_FIELD}[LANGUAGE_NONE][0]['value']) {
+          _og_subgroups_get_children_groups($children_type, $child_id, $children_groups);
+        }
+      }
+    }
+  }
+}
diff --git a/og_subgroups.info b/og_subgroups.info
old mode 100755
new mode 100644
index d2e8e93..8879b09
--- a/og_subgroups.info
+++ b/og_subgroups.info
@@ -8,4 +8,4 @@ version = VERSION
 files[] = og_subgroups.module
 
 ; Test files.
-files[] = og_subgroups.test
\ No newline at end of file
+files[] = og_subgroups.test
diff --git a/og_subgroups.module b/og_subgroups.module
old mode 100755
new mode 100644
index f55ba1b..4d57056
--- a/og_subgroups.module
+++ b/og_subgroups.module
@@ -2,206 +2,106 @@
 
 /**
  * @file
- * Enable defining hierarchy of groups for organic groups.
+ * Provides users the ability to inherit permissions on subgroups.
  */
 
-/**
- * Implementation of hook_ctools_plugin_directory().
- */
-function og_subgroups_ctools_plugin_directory($module, $plugin) {
-  // Safety: go away if CTools is not at an appropriate version.
-  if (!module_invoke('ctools', 'api_version', OG_REQUIRED_CTOOLS_API)) {
-    return;
-  }
+// Add field widget related code.
+require drupal_get_path('module', 'og_subgroups') . '/og_subgroups.common.inc';
 
-  if ($module == 'ctools') {
-    return 'plugins/' . $plugin;
-  }
-}
 /**
- * Check if a user has access permission in one of the ancestors groups
- * and return the tree structure of the group hierarchy.
- *
- * @param $entity_groups
- *    Array of group id to check and start moving up in the hierarchy.
- * @param $account
- *    Optional; The account to check
- * @param $string
- *    Optional; The permission string, if empty return the full tree structure in
- *    $structure, otherwise stops when the permission is grant.
- * @param $structure
- *     Optional; This is the array that you should send by refeference to get back
- *     all the tree structure of the given groups.
- *    Array contain 2 keys ['gid'] - group id, and ['level'] the depth of the
- *    parent.
- * @param $level
- *     Optional; Level of tree to start counting from, normally there is no need
- *    to change this. Default to 0 being the entity given.
- *
- *  @return
- *    TRUE if user has access grant with the given perm to one of the enstertors
- *    groups.
+ * Group default roles and permissions field.
  */
-function og_subgroups_get_reverse_hierarchy_tree_perm($entity_groups, $string = '', $account = NULL, &$structure = array(), &$graph = FALSE , $level = 0) {
-  // Check if user has the permission in a parent group.
-  foreach($entity_groups as $gid) {
-    // Save the hierarchy structure.
-    $structure[$gid] = array();
-    $structure[$gid]['gid'] = $gid;
-    $structure[$gid]['level'] = $level;
-
-    // Build a graph with graph api
-    if (is_array($graph) && module_exists('graphapi')) {
-      $group = og_load($gid);
-      graphapi_set_node_title($graph, $gid,  $group->label);
-    }
-    // Check access permission.
-    if ($string) {
-      if (og_user_access($gid, $string, $account, TRUE)) {
-        return TRUE;
-      }
-    }
-  }
-  // Get all groups that are content of user_groups (as an array of group ids).
-  $groups = og_load_multiple($entity_groups);
-  $parent_groups = array();
-  foreach ($groups as $group) {
-    // Load the entity associated with the group.
-    $entity = og_load_entity_from_group($group->gid);
-    // Get all groups that are associated with passed group.
-    $parents = og_get_entity_groups($group->entity_type, $entity);
-    $parent_groups += $parents;
-    // Build a graph path with graph api
-    if (is_array($graph) && module_exists('graphapi')) {
-      foreach ($parents as $parent) {
-        graphapi_set_node_title($graph, $parent,  $parent);
-        graphapi_set_link_data($graph, $group->gid, $parent, array('color' => '#018FE2'));
-      }
-    }
-  }
-  if ($parent_groups) {
-    // Recurssion call of the function.
-    return og_subgroups_get_reverse_hierarchy_tree_perm($parent_groups, $string, $account, $structure, $graph, ++$level);
-  }
-  else {
-    // Reached a dead end, return false.
-    return FALSE;
-  }
-}
+define('OG_USER_INHERITANCE_FIELD', 'og_user_inheritance');
 
 /**
- * Implements hook_og_user_access_alter()
+ * Implements hook_og_fields_info().
  */
-function og_subgroups_og_user_access_alter(&$perm, $context) {
-  // Update the permission for a user that tries to access a sub group.
-  // This gives to any users his og group permission to all his subgroups,
-  // without the -need for him to be a member in the groups.
-  $perm[$context['string']] = og_subgroups_get_reverse_hierarchy_tree_perm(array($context['group']->gid),  $context['string'], $context['account']);
+function og_subgroups_og_fields_info() {
+  $allowed_values = array(
+    0 => 'No - subgroups of this group won\'t inherit its users.',
+    1 => 'Yes - subgroups of this group will inherit its users.',
+  );
+  $items[OG_USER_INHERITANCE_FIELD] = array(
+    'type' => array('group'),
+    'description' => t('Determine if the subgroups of a group will inherit its users.'),
+    'entity' => array('node'),
+    'field' => array(
+      'field_name' => OG_USER_INHERITANCE_FIELD,
+      'no_ui' => TRUE,
+      'type' => 'list_boolean',
+      'cardinality' => 1,
+      'settings' => array('allowed_values' => $allowed_values, 'allowed_values_function' => ''),
+    ),
+    'instance' => array(
+      'label' => t('Group user inheritance'),
+      'required' => TRUE,
+      'default_value' => array(0 => array('value' => 1)),
+      'widget_type' => 'options_select',
+      'view modes' => array(
+        'full' => array(
+          'label' => 'above',
+          'type' => 'options_onoff',
+        ),
+        'teaser' => array(
+          'label' => 'above',
+          'type' => 'options_onoff',
+        ),
+      ),
+    ),
+  );
+  return $items;
 }
 
-
 /**
- * Implements hook_node_access_records_alter().
- *
- * This alter is fired on node save, we want to add view permission to a user's
- * subgroups (private groups), to do so we add the parent groups id to all
- * groups.
+ * Implements hook_views_api().
  */
-function og_subgroups_node_access_records_alter(&$grants, $node) {
-  // Relevant only for private groups.
-  if (module_exists('og_access')) {
-    // The group IDs, that in case access is granted, will be recorded.
-    $gids = array();
-    $private = FALSE;
-    $groups = array();
-    // Dealing with a node group that is private.
-    if (!empty($node->{OG_ACCESS_FIELD}[LANGUAGE_NONE][0]['value'])) {
-      $group = og_get_group('node', $node->nid);
-      if ($group) {
-        $groups[] = $group->gid;
-        $private = TRUE;
-      }
-    }
-    // Dealing with a group content.
-    elseif (isset($node->{OG_CONTENT_ACCESS_FIELD}[LANGUAGE_NONE][0]['value'])) {
-      // If no groups with og realm are defined, this means it's a public group
-      //  then do nothing, otherwise treat as a private group.
-      if (($node->{OG_CONTENT_ACCESS_FIELD}[LANGUAGE_NONE][0]['value'] == OG_CONTENT_ACCESS_PRIVATE) ||
-      ($node->{OG_CONTENT_ACCESS_FIELD}[LANGUAGE_NONE][0]['value'] == OG_CONTENT_ACCESS_DEFAULT && og_subgroups_grants_has_og_realm($grants))) {
-        $groups = og_get_entity_groups('node', $node);
-        $private = TRUE;
-      }
-    }
-    // If group is private, then grant permissions for parent groups.
-    if ($private) {
-      og_subgroups_get_reverse_hierarchy_tree_perm($groups, '', NULL, $gids);
-      // Check existing grant and remove from gids[], to avoid duplication.
-      foreach ($grants as $granted) {
-        if (isset($gids[$granted['gid']])) {
-          unset($gids[$granted['gid']]);
-        }
-      }
-      // Build the new access Grant array.
-      foreach ($gids as $gid) {
-        $grants[] = array (
-        'realm' => OG_ACCESS_AUTHENTICATED_REALM,
-        'gid' => $gid['gid'],
-        'grant_view' => 1,
-        'grant_update' => 0,
-        'grant_delete' => 0,
-        'priority' => 0,
-        );
-      }
-    }
-  }
+function og_subgroups_views_api() {
+  return array(
+    'api' => 3.0,
+  );
 }
 
 /**
- * Return TRUE if $grants contain an OG realm
+ * Implements hook_node_grants().
  */
-function og_subgroups_grants_has_og_realm($grants) {
-  foreach ($grants as $granted) {
-    if ($granted['realm'] == OG_ACCESS_AUTHENTICATED_REALM) {
-      return TRUE;
+function og_subgroups_node_grants($account, $op) {
+  if ($op != 'view') {
+    return;
+  }
+  $groups = _og_subgroup_get_user_inherited_groups($account);
+  if (!empty($groups)) {
+    foreach ($groups as $group_type => $gids) {
+      foreach (array_keys($gids) as $gid) {
+        $realm = OG_ACCESS_REALM . ':' . $group_type;
+        $grants[$realm][] = $gid;
+      }
     }
   }
-  return FALSE;
+  return !empty($grants) ? $grants : array();
 }
 
 /**
- * Get hierarchy tree.
+ * Implements hook_og_user_access_alter().
  *
- * @param $entity_type
- * @param $etid
- * @param $options
+ * Inherit every permission the user had in the parent groups;
+ * i.e. we only "add" permissions.
  */
-function og_get_hierarchy($entity_type, $etid, $options = array(), &$tree = array(), $depth = 0) {
-  $options += array(
-    'direction' => 'up',
-    'type' => 'single',
-    'sanitize' => TRUE,
-  );
-
-  $wrapper = entity_metadata_wrapper($entity_type, $etid);
-
-  if ($depth == 0 && $group = $wrapper->group->value()) {
-    if ($options['type'] == 'single') {
-      $tree[$group->gid] = og_label($group->gid, $options['sanitize']);
-    }
-    else {
-      $tree[$depth][$group->gid] = og_label($group->gid, $options['sanitize']);
-    }
+function og_subgroups_og_user_access_alter(&$perms, $context) {
+  if (!empty($perms[$context['string']])) {
+    // Permission is already TRUE, no need to check.
+    return;
   }
-
-  if ($options['direction'] == 'up' && $options['type'] == 'single') {
-    $group = FALSE;
-    // Get the first group associated with the entity.
-    if ($wrapper->og_membership->get(0)->value()) {
-      $group = $wrapper->og_membership->get(0)->group->value();
-      $tree[$group->gid] = og_label($group->gid, $options['sanitize']);
-      og_get_hierarchy($group->entity_type, $group->etid, $options, $tree, $depth + 1);
+  $group_type = $context['group_type'];
+  $group = $context['group'];
+  list($id) = entity_extract_ids($group_type, $group);
+  $parent_groups = _og_subgroups_get_unique_parents($group_type, $id);
+  if (!empty($parent_groups)) {
+    foreach ($parent_groups as $parent_group) {
+      // Recursion is prevented by $skip_alter = TRUE.
+      if (og_user_access($parent_group['type'], $parent_group['id'], $context['string'], $context['account'], TRUE)) {
+        $perms[$context['string']] = TRUE;
+        break;
+      }
     }
   }
-
-  return $tree;
-}
+}
\ No newline at end of file
diff --git a/og_subgroups.test b/og_subgroups.test
index 31129d4..73c3fb7 100644
--- a/og_subgroups.test
+++ b/og_subgroups.test
@@ -1,5 +1,9 @@
 <?php
-// $Id$
+
+/**
+ * @file
+ * Testing functions for OG Subgroups.
+ */
 
 /**
  * Test the Organic groups subgroups API.
@@ -14,19 +18,17 @@ class OgSubgroupsAccessFromDescendanceTestCase extends DrupalWebTestCase {
   }
 
   function setUp() {
-    parent::setUp('og_subgroups', 'entity_test','og_access');
+    parent::setUp('og_subgroups', 'entity_test', 'og_access');
     // Add OG group field to the entity_test's "main" bundle.
     og_create_field(OG_GROUP_FIELD, 'entity_test', 'main');
     og_create_field(OG_AUDIENCE_FIELD, 'entity_test', 'main');
     og_create_field(OG_AUDIENCE_FIELD, 'article', 'main');
   }
-  
-  
 
   /**
    * Use cases:
-   * - Check that parent user has access to all permission he has on groups he 
-   * is not memberof but that are descandents of his group
+   * - Check that parent user has access to all permission he has on groups he
+   * is not member of but that are descendents of his group.
    */
   function testOgSubgroupsGetReverseHierarchyTreePerm() {
     // Create user.
@@ -36,7 +38,7 @@ class OgSubgroupsAccessFromDescendanceTestCase extends DrupalWebTestCase {
     $user4 = $this->drupalCreateUser();
     $web_user = $this->drupalCreateUser(array('create article content', 'create page content'));
     $this->drupalLogin($web_user);
-    
+
     $groups = array();
 
     // Create an entity that is a group.
@@ -44,28 +46,27 @@ class OgSubgroupsAccessFromDescendanceTestCase extends DrupalWebTestCase {
     $entity->{OG_GROUP_FIELD}[LANGUAGE_NONE][0]['value'] = 1;
     $entity->save();
     $groups[0] = og_get_group('entity_test', $entity->pid);
-    
-   // Create a private entity group that is a child group of the group above.
+
+    // Create a private entity group that is a child group of the group above.
     $entity = entity_create('entity_test', array('name' => 'first_child', 'uid' => $user2->uid));
     $entity->{OG_GROUP_FIELD}[LANGUAGE_NONE][0]['value'] = 1;
     $entity->{OG_AUDIENCE_FIELD}[LANGUAGE_NONE][0]['gid'] =  $groups[0]->gid;
     $entity->save();
     $groups[1] = og_get_group('entity_test', $entity->pid);
-    
+
     // Create an entity that is a child group of the group above.
     $entity = entity_create('entity_test', array('name' => 'second_child', 'uid' => $user3->uid));
     $entity->{OG_GROUP_FIELD}[LANGUAGE_NONE][0]['value'] = 1;
     $entity->{OG_AUDIENCE_FIELD}[LANGUAGE_NONE][0]['gid'] =  $groups[1]->gid;
     $entity->save();
     $groups[2] = og_get_group('entity_test', $entity->pid);
-    
+
     // Create an entity that is a group content of group ID 2.
-  
     $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
     $node->{OG_AUDIENCE_FIELD}[LANGUAGE_NONE][0]['gid'] = $groups[2]->gid;
-    node_save($node);    
+    node_save($node);
     $groups[3] = $node;
-    
+
     $group_content[0] = $entity;
 
     // Associate user4 to the group[2].
@@ -73,47 +74,49 @@ class OgSubgroupsAccessFromDescendanceTestCase extends DrupalWebTestCase {
 
     // Assert the user is registered to the new group.
     $string = 'administer group';
+
     // Check user1 has adminster perm on parent group [0]
     debug($groups);
     $this->assertTrue(og_user_access($groups[0]->gid, $string, $user1, TRUE) , t('User1 have admister group permission to parent group 0'));
+
     // Check user has admin perm on sub group that is he not member of.
     $access_res = og_subgroups_get_reverse_hierarchy_tree_perm(array($groups[2]->gid), $string, $user1);
     $this->assertTrue($access_res, t('User1 have admister group permission to subgroup 2'));
 
     // Check permission.
     $this->assertFalse(og_user_access($groups[0]->gid, $string, $user3), t('User3 does not have "Administer group" permission.'));
+
     // Check user3 has no adminster perm on parent group [0]
     $access_res = og_subgroups_get_reverse_hierarchy_tree_perm(array($groups[0]->gid), $string, $user1);
     $this->assertFalse($access_res, t('User3 does not have admister group permission to group 0'));
 
     // Change permissions to authenticated member.
-    //$roles = array_flip(og_get_global_roles());
+    // $roles = array_flip(og_get_global_roles());
     // Authenticated role ID.
-   // $rid = $roles[OG_AUTHENTICATED_ROLE];
+    // $rid = $roles[OG_AUTHENTICATED_ROLE];
 
-   // $permissions = array(
-  //    'delete own article content' => 1,
-  ///    'administer group' => 1,
-  //  );
-  //  og_role_change_permissions($rid, $permissions);
+    // $permissions = array(
+    //    'delete own article content' => 1,
+    ///    'administer group' => 1,
+    //  );
+    //  og_role_change_permissions($rid, $permissions);
 
     // Verify proper permission changes.
-   // $this->assertFalse(og_user_access($group->gid, 'update own article content', $user2), t('User still does not have "update own article content" permission.'));
-   // $this->assertTrue(og_user_access($group->gid, 'delete own article content', $user2), t('User now has "delete own article content" permission.'));
-  //  $this->assertTrue(og_user_access($group->gid, 'administer group', $user2), t('User now has "administer group" permission.'));
+    // $this->assertFalse(og_user_access($group->gid, 'update own article content', $user2), t('User still does not have "update own article content" permission.'));
+    // $this->assertTrue(og_user_access($group->gid, 'delete own article content', $user2), t('User now has "delete own article content" permission.'));
+    //  $this->assertTrue(og_user_access($group->gid, 'administer group', $user2), t('User now has "administer group" permission.'));
 
-   // $permissions = array(
-   //   'delete own article content' => 1,
-   //   'administer group' => 0,
-  //  );
- //  og_role_change_permissions($rid, $permissions);
+    // $permissions = array(
+    //   'delete own article content' => 1,
+    //   'administer group' => 0,
+    //  );
+    //  og_role_change_permissions($rid, $permissions);
 
-  //  $this->assertTrue(og_user_access($group->gid, 'delete own article content', $user2), t('User still has "delete own article content" permission.'));
-  //  $this->assertFalse(og_user_access($group->gid, 'administer group', $user2), t('User no longer has "administer group" permission.'));
+    //  $this->assertTrue(og_user_access($group->gid, 'delete own article content', $user2), t('User still has "delete own article content" permission.'));
+    //  $this->assertFalse(og_user_access($group->gid, 'administer group', $user2), t('User no longer has "administer group" permission.'));
 
   }
-  
-  
+
   /**
    * Test the view access of child node.
    * Use cases:
@@ -121,7 +124,6 @@ class OgSubgroupsAccessFromDescendanceTestCase extends DrupalWebTestCase {
    *  access), that he is not part of.
    * 2. Anonymous user tries to view private child groups node (with public
    *  access).
-   * 
    */
   function testOgSubgroupsNodeAccessRecordsAlter() {
     // Create user.
@@ -131,7 +133,7 @@ class OgSubgroupsAccessFromDescendanceTestCase extends DrupalWebTestCase {
     $user4 = $this->drupalCreateUser();
     $web_user = $this->drupalCreateUser(array('create article content', 'create page content'));
     $this->drupalLogin($web_user);
-    
+
     $groups = array();
 
     // Create an entity that is a group.
@@ -140,15 +142,15 @@ class OgSubgroupsAccessFromDescendanceTestCase extends DrupalWebTestCase {
     $entity->save();
     $groups[0]['group'] = og_get_group('entity_test', $entity->pid);
     $groups[0]['entity'] = $entity;
-    
-   // Create an entity that is a child group of the group above (0).
+
+    // Create an entity that is a child group of the group above (0).
     $entity = entity_create('entity_test', array('name' => 'first_child', 'uid' => $user2->uid));
     $entity->{OG_GROUP_FIELD}[LANGUAGE_NONE][0]['value'] = 1;
     $entity->{OG_AUDIENCE_FIELD}[LANGUAGE_NONE][0]['gid'] =  $groups[0]['group']->gid;
     $entity->save();
     $groups[1]['group'] = og_get_group('entity_test', $entity->pid);
     $groups[1]['entity'] = $entity;
-    
+
     // Create a private entity group that is a child group of the group above. (1).
     $entity = entity_create('entity_test', array('name' => 'second_child', 'uid' => $user3->uid));
     $entity->{OG_GROUP_FIELD}[LANGUAGE_NONE][0]['value'] = 1;
@@ -157,30 +159,26 @@ class OgSubgroupsAccessFromDescendanceTestCase extends DrupalWebTestCase {
     $entity->save();
     $groups[2]['group'] = og_get_group('entity_test', $entity->pid);
     $groups[2]['entity'] = $entity;
-    
+
     // Create an entity that is a group content of group ID 2.
     $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
     $node->{OG_AUDIENCE_FIELD}[LANGUAGE_NONE][0]['gid'] = $groups[2]['group']->gid;
-    node_save($node); 
+    node_save($node);
     $groups[3]['node'] = $node;
-    
-    
 
     $this->drupalLogout();
+
     // Assert the anonymous can't view the node.
     $this->drupalGet('node/' . $groups[3]['node']->nid);
     $this->assertResponse('403', t('Annonymous cannot view private node.'));
-    
+
     $this->drupalLogin($user4);
     $this->drupalGet('node/' . $groups[3]['node']->nid);
     $this->assertResponse('403', t('Not group member or parrent cannot view private node.'));
-    
 
     // Assert another user is not a group member.
     $this->drupalLogin($user1);
     $this->drupalGet('node/' . $groups[3]['node']->nid);
     $this->assertResponse('200', t('Parent group user can view the node'));
-
   }
-  
 }
diff --git a/og_subgroups.views.inc b/og_subgroups.views.inc
index e69de29..0026365 100644
--- a/og_subgroups.views.inc
+++ b/og_subgroups.views.inc
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @file
+ * Provides support for the Views module.
+ */
+
+/**
+ * Implements hook_views_pre_render().
+ */
+function og_subgroups_views_pre_render(&$view) {
+  if ($view->name == 'og_members_admin') {
+    // Add an overview of the users that are inherited from parent groups.
+    $inherited_users = _og_subgroups_get_inherited_users($view->args[0], $view->args[1]);
+    $header = array('Name', 'Inherited from');
+    $rows = array();
+    $membership_states = og_group_content_states();
+    if (!empty($inherited_users)) {
+      foreach ($inherited_users as $inherited_uid => $data) {
+        $row = array();
+        $row[] = l($data[0]['user']->name, 'user/' . $inherited_uid);
+        $inherited_from = array();
+        foreach ($data as $inheritance) {
+          $inherited_from[] = t('!parent (@roles)', array(
+            '!parent' => l(entity_label($inheritance['inherited_from']['type'], $inheritance['inherited_from']['entity']), 'group/' . $inheritance['inherited_from']['type'] . '/' . $inheritance['inherited_from']['id'] . '/admin/people'),
+            '@roles' => implode(', ', $inheritance['roles']),
+          ));
+        }
+        $row[] = implode(', ', $inherited_from);
+        $rows[] = $row;
+      }
+    }
+    $view->attachment_after = theme('table', array(
+      'caption' => t('Inherited users'),
+      'header' => $header,
+      'rows' => $rows,
+      'empty' => t('No inherited users.'),
+    ));
+  }
+}
diff --git a/plugins/content_types/graph/graph.inc b/plugins/content_types/graph/graph.inc
deleted file mode 100755
index 94dfb16..0000000
--- a/plugins/content_types/graph/graph.inc
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-
-/**
- * Plugin defenition
- */
-if (module_exists('graphapi')) {
-  $plugin = array (
-    'title' => t('OG Group hierarchy graph'),
-    'description' => t('Display a graph of group hierarchy starting from a given group.'),
-    'required context' => new ctools_context_required(t('Group'), 'entity:group'),
-    'category' => t('OG subrgoups'),
-  );
-}
-
-function og_subgroups_graph_content_type_render($subtype, $conf, $args, $context) {
-  if (empty($context)) {
-    return;
-  }
-
-  $block = new stdClass();
-  $block->module = 'og_subgroups';
-  $block->title = t('OG Group hierarchy graph');
-
-  $group = clone $context->data;
-  $graph = graphapi_new_graph();
-
-  og_subgroups_get_reverse_hierarchy_tree_perm(array($group->gid), '' , NULL, $structure, $graph);
-
-
-  // TODO: Add settings for the options.
-  $options = array(
-    'width' => 550,
-    'height' => 400,
-    'item-width' => 50,
-  );
-  $block->content = graphapi_container($graph, $options);
-
-  return $block;
-}
-
-function og_subgroups_graph_content_type_edit_form($form, &$form_state) {
-  // provide a blank form so we have a place to have context setting.
-  return $form;
-}
