'Group context', 'description' => 'Group context detection and selection', 'page callback' => 'drupal_get_form', 'page arguments' => array('og_context_configure_form'), 'access arguments' => array('administer group'), 'file' => 'og_context.admin.inc', 'type' => MENU_LOCAL_TASK, ); return $items; } /** * Implements hook_theme(). */ function og_context_theme() { return array( 'og_context_configure_form' => array( 'render element' => 'form', ), ); } /** * Implement hook_preprocess_html(). * * HTML preprocess; Add context related templates and CSS. */ function og_context_preprocess_html(&$variables) { if ($group = og_context()) { // Add template suggestions. $variables['theme_hook_suggestions'][] = 'page__group_context'; $variables['theme_hook_suggestions'][] = 'page__group_context__group_' . $group->gid; $variables['theme_hook_suggestions'][] = 'page__group_context__' . $group->entity_type; $variables['theme_hook_suggestions'][] = 'page__group_context__' . $group->entity_type . '_' . $group->etid; // Add CSS. $clean_html = drupal_html_class('group-context-' . $group->entity_type); $variables['classes_array'][] = 'group-context'; $variables['classes_array'][] = 'group-context-group-' . $group->gid; $variables['classes_array'][] = $clean_html; $variables['classes_array'][] = $clean_html . '-' . $group->etid; // Add context to JS. og_context_add_js($group); } } /** * Implements hook_og_context_negotiation_info(). */ function og_context_og_context_negotiation_info() { $providers = array(); $providers['url'] = array( 'name' => t('URL'), 'description' => t("Select groups if they were passed in the URL (e.g. node/add/post?gids_node[]=4,5,6)."), 'callback' => 'og_context_handler_url', ); $providers['node'] = array( 'name' => t('Node'), 'description' => t("Determine context by checking if a node is a group or a group content."), 'callback' => 'og_context_handler_node', 'menu path' => array('node/%', 'node/%/edit'), ); $providers['user-view'] = array( 'name' => t('User view'), 'description' => t("Determine context by checking if a user is a group or a group content on the 'user view' page."), 'callback' => 'og_context_handler_user_view', 'menu path' => array('user/%'), ); $providers['user-edit'] = array( 'name' => t('User edit'), 'description' => t("Determine context by checking if a user is a group or a group content on the 'user edit' page."), 'callback' => 'og_context_handler_user_edit', 'menu path' => array('user/%/edit'), ); return $providers; } /** * Implement hook_init(). */ function og_context_init() { og_context(); } /** * Implements hook_views_api(). */ function og_context_views_api() { return array( 'api' => 2, 'path' => drupal_get_path('module', 'og_context') . '/includes', ); } /** * Implements hook_og_invalidate_cache(). */ function og_context_og_invalidate_cache($gids = array()) { $caches = array( 'og_context', 'og_context_js', ); foreach ($caches as $cache) { drupal_static_reset($cache); } if ($gids && !empty($_SESSION['og_context']) && in_array($_SESSION['og_context'], $gids)) { // Remove group's context. $_SESSION['og_context'] = NULL; } } /** * Get or set group context using the menu system. * * @param $group * Optional; The group entity to set as the context. * @param $account * Optional; The user entity to determine context form. * * @return * A group entity, or FALSE if no context was found. */ function og_context($group = NULL, $account = NULL) { global $user; $context = &drupal_static(__FUNCTION__, FALSE); if (!empty($group)) { $context = $group; } if (empty($context)) { // Get context from context handlers. if (($context = og_context_determine_context()) && $user->uid) { // TODO: Add option to save session for anonymous users as-well? // Save the group ID in the authenticated user's session, $_SESSION['og_context'] = $context->gid; } } return $context; } /** * Add the group entity of the context to the Drupal javascript entity. * * @param $group * A group entity. */ function og_context_add_js($group) { // Static variable to indicate if group was already added to javascript. $js = &drupal_static(__FUNCTION__, FALSE); if (empty($js)) { drupal_add_js(array('group' => array('og_context' => $group)), 'setting'); $js = TRUE; } } /** * Return all the defined group context providers. * * @return * An array of group context providers. */ function og_context_negotiation_info() { $group_context_providers = &drupal_static(__FUNCTION__); if (!isset($group_context_providers)) { // Collect all the module-defined og_context negotiation providers. $group_context_providers = module_invoke_all('og_context_negotiation_info'); // Let other modules alter the list of og_context providers. drupal_alter('og_context_negotiation_info', $group_context_providers); } // Assign default values. foreach ($group_context_providers as &$group_context_provider) { $group_context_provider += array( 'menu path' => array(), ); } return $group_context_providers; } /** * Save a list of language providers. * * @param $type * The language negotiation type. * @param $language_providers * An array of language provider ids. */ function og_context_negotiation_set($group_context_providers) { $type = 'group_context'; // Save only the necessary fields. $provider_fields = array('callbacks'); $negotiation = array(); $providers_weight = array(); $defined_providers = og_context_negotiation_info(); // Initialize the providers weight list. foreach ($group_context_providers as $id => $provider) { $providers_weight[$id] = og_context_provider_weight($provider); } // Order providers list by weight. asort($providers_weight); foreach ($providers_weight as $id => $weight) { if (isset($defined_providers[$id])) { $provider = $defined_providers[$id]; $provider_data = array(); foreach ($provider_fields as $field) { if (isset($provider[$field])) { $provider_data[$field] = $provider[$field]; } } $negotiation[$id] = $provider_data; } } variable_set("og_context_negotiation_$type", $negotiation); } /** * Return the passed group context provider weight or a default value. * * @param $provider * A group context provider data structure. * * @return * A numeric weight. */ function og_context_provider_weight($provider) { $default = is_numeric($provider) ? $provider : 0; return isset($provider['weight']) && is_numeric($provider['weight']) ? $provider['weight'] : $default; } /** * Determine the best matching context of a viewed page. * * @param $item * Optional; A menu item that context should be extracted from. If empty * defaults to the current menu item by using menu_get_item(). */ function og_context_determine_context($item = NULL) { $context = FALSE; // Enable url and node context handlers by default. $defaults = array('url' => -5, 'node' => -4); if ($enabled_providers = array_keys(variable_get("og_context_negotiation_group_context", $defaults))) { if (empty($item)) { $item = menu_get_item(); } foreach (og_context_negotiation_info() as $name => $provider) { if (in_array($name, $enabled_providers)) { $invoke = FALSE; if (!empty($provider['menu path'])) { foreach ($provider['menu path'] as $path) { if (strpos($item['path'], $path) === 0) { $invoke = TRUE; // Path matches, so we can break. break; } } } else { // Context isn't determined by the menu item. $invoke = TRUE; } $gids = array(); if ($invoke && ($gids = call_user_func($provider['callback']))) { // Check if one of the group IDs already exists in the session, and if // so use it. if (!empty($_SESSION['og_context']) && in_array($_SESSION['og_context'], $gids)) { $gid = $_SESSION['og_context']; } else { // Grab the first group ID. $gid = reset($gids); } $context = og_load($gid); // We found the first context, so we can break. break; } } } } return $context; } /** * Context handler; Get groups from URL. */ function og_context_handler_url() { $context = array(); if ($gids = og_get_context_by_url()) { $context = $gids; } return $context; } /** * Context handler; Get groups from existing node. */ function og_context_handler_node() { $return = array(); // menu_get_object() doesn't play nicely if the path is node/%/foo, so we load // it ourself. $item = menu_get_item(); if (!empty($item['map'][1])) { if (is_object($item['map'][1])) { $node = $item['map'][1]; } else { $node = node_load($item['map'][1]); } $return = _group_context_handler_entity('node', $node); } return $return; } /** * Context handler; Get groups from user view. */ function og_context_handler_user_view() { global $user; return _group_context_handler_entity('user', $user); } /** * Context handler; Get groups from user edit. */ function og_context_handler_user_edit() { return _group_context_handler_entity('user'); } /** * Helper function to get group context from an entity. * * @param $entity_type * The entity type. * @param $entity * Optional; The entity object. * @param $position * Optional; The position that should be used in menu_get_object(). */ function _group_context_handler_entity($entity_type = 'node', $entity = NULL, $position = 1) { $context = array(); if (empty($entity)) { $entity = menu_get_object($entity_type, $position); } if ($entity) { // Check if the entity is itself a group. list($id) = entity_extract_ids($entity_type, $entity); if ($group = og_get_group($entity_type, $id)) { $context = drupal_map_assoc(array($group->gid)); } elseif ($gids = og_get_entity_groups($entity_type, $entity)) { $context = $gids; } } return $context; }