3); } else if ($module == 'spaces' && $api == 'plugins') { return array('version' => 3); } } /** * Implementaton of hook_enable(). */ function spaces_og_enable() { // Configure purl, grab OG method, set to path if not configured. $purl_types = variable_get('purl_types', array()); if (!variable_get('purl_method_spaces_og', FALSE)) { $purl_types['path'] = 'path'; variable_set('purl_types', $purl_types); variable_set('purl_method_spaces_og', 'path'); } // The next 2 lines are for Simpletest, it won't have it otherwise. // variable_get up top retrieves the settings from the host, while // variable_set here writes into the test site. As a result, // variable_get('purl_method_spaces_og') will retrieve the value of the host // site. If it is present in the host site, the initial configuration is not // being executed and the tests fail. variable_set('purl_types', $purl_types); variable_set('purl_method_spaces_og', variable_get('purl_method_spaces_og', FALSE)); // Weight spaces_og to be after OG $weight = db_result(db_query("SELECT weight FROM {system} WHERE type = 'module' AND name = 'og'")); db_query("UPDATE {system} SET weight = %d WHERE name = 'spaces_og'", ($weight + 1)); } /** * Implementation of hook_purl_provider(). */ function spaces_og_purl_provider() { $items = array(); $items["spaces_og"] = array( 'name' => t('Group space'), 'description' => t('Sets a space as the active space.'), 'callback' => 'spaces_init_space', 'callback arguments' => array('og'), 'example' => 'my-space', ); return $items; } /** * Implementation of hook_spaces_plugins(). */ function spaces_og_spaces_plugins() { $plugins = array(); $plugins['space_og'] = array( 'handler' => array( 'path' => drupal_get_path('module', 'spaces_og') .'/plugins', 'file' => 'space_og.inc', 'class' => 'space_og', 'parent' => 'space_type_purl', ), ); return $plugins; } /** * Implementation of hook_spaces_registry(). */ function spaces_og_spaces_registry() { return array( 'types' => array( 'og' => array( 'title' => t('Group space'), 'plugin' => 'space_og', 'path' => 'node/%node', ), ), ); } /** * Implementation of hook_spaces_presets(). */ function spaces_og_spaces_presets() { $export = array(); $spaces_presets = new stdClass; $spaces_presets->disabled = FALSE; /* Edit this to true to make a default spaces_presets disabled initially */ $spaces_presets->api_version = 3; $spaces_presets->name = 'og_controlled'; $spaces_presets->title = 'Controlled group'; $spaces_presets->description = 'All users may view public content from this group. Users must request to join this group.'; $spaces_presets->space_type = 'og'; $spaces_presets->value = array( 'variable' => array( 'spaces_og_selective' => '1', 'spaces_og_register' => 1, 'spaces_og_directory' => 1, 'spaces_og_private' => 0, ), ); $export['og_controlled'] = $spaces_presets; $spaces_presets = new stdClass; $spaces_presets->disabled = FALSE; /* Edit this to true to make a default spaces_presets disabled initially */ $spaces_presets->api_version = 3; $spaces_presets->name = 'og_private'; $spaces_presets->title = 'Private group'; $spaces_presets->description = 'Only members will be able to access this group. Membership is strictly managed by admins.'; $spaces_presets->space_type = 'og'; $spaces_presets->value = array( 'variable' => array( 'spaces_features' => array(), 'spaces_preset_og' => 'og_private', 'spaces_og_selective' => '3', 'spaces_og_register' => 0, 'spaces_og_directory' => 0, 'spaces_og_private' => 1, ), 'context' => array(), ); $export['og_private'] = $spaces_presets; $spaces_presets = new stdClass; $spaces_presets->disabled = FALSE; /* Edit this to true to make a default spaces_presets disabled initially */ $spaces_presets->api_version = 3; $spaces_presets->name = 'og_public'; $spaces_presets->title = 'Public group'; $spaces_presets->description = 'All users may view public content from this group. User may join this group at will.'; $spaces_presets->space_type = 'og'; $spaces_presets->value = array( 'variable' => array( 'spaces_features' => array(), 'spaces_og_selective' => '0', 'spaces_og_register' => 1, 'spaces_og_directory' => 1, 'spaces_og_private' => 0, ), ); $export['og_public'] = $spaces_presets; return $export; } /** * Implementation of hook_menu(). */ function spaces_og_menu() { $items = array(); $items['user/%user/edit/groups'] = array( 'file' => 'spaces_og.pages.inc', 'title' => 'Groups', 'page callback' => 'drupal_get_form', 'page arguments' => array('spaces_og_user_groups_form', 1), 'access callback' => 'user_edit_access', 'access arguments' => array(1), 'type' => MENU_LOCAL_TASK, ); if (module_exists('ucreate')) { $items["og/users/%node/ucreate"] = array( 'file' => 'spaces_og.pages.inc', 'type' => MENU_LOCAL_TASK, 'title' => 'Add new account', 'page callback' => 'spaces_og_ucreate', 'page arguments' => array(2), 'access callback' => 'spaces_access_admin', 'access arguments' => array(), 'weight' => 1, ); } return $items; } /** * Implementation of hook_menu_alter(). */ function spaces_og_menu_alter(&$items) { if (isset($items['node/%node/features'])) { $items['node/%node/features']['access callback'] = 'spaces_og_access_admin'; $items['node/%node/features']['access arguments'] = array(1); } if (isset($items['node/%node/overrides'])) { $items['node/%node/overrides']['access callback'] = 'spaces_og_access_admin'; $items['node/%node/overrides']['access arguments'] = array(1); } } /** * Access callback for OG administrative items under node/%. * Prevents items from showing up under node types that are not groups. */ function spaces_og_access_admin($node) { return og_is_group_type($node->type) ? spaces_access_admin() : FALSE; } /** * Implementation of hook_user(). */ function spaces_og_user($op, &$edit, &$account, $category = NULL) { global $user; switch ($op) { case 'categories': $data = array(); $data[] = array( 'name' => 'groups', 'title' => t('Groups'), 'weight' => 10, ); return $data; } } /** * Implementation of hook_perm(). */ function spaces_og_perm() { return array('view users outside groups'); } /** * Implementation of hook_nodeapi(). */ function spaces_og_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) { // Groups if (og_is_group_type($node->type)) { switch ($op) { case 'load': $modifier = purl_load(array('id' => isset($node->nid) ? $node->nid : NULL, 'provider' => 'spaces_og')); $node->purl = $modifier['value']; break; case 'insert': case 'update': $space = spaces_load('og', $node->nid, TRUE); if ($space) { // Save preset values. if (!empty($node->spaces_preset_og)) { $space->controllers->variable->set('spaces_preset_og', $node->spaces_preset_og); } // Configure OG directly from space object as node_save() may be // called from outside of actual group space. $selective = $space->controllers->variable->get('spaces_og_selective'); $node->og_selective = $selective === NULL ? OG_OPEN : $selective; $register = $space->controllers->variable->get('spaces_og_register'); $node->og_register = $register === NULL ? TRUE : $register; $directory = $space->controllers->variable->get('spaces_og_directory'); $node->og_directory = $directory === NULL ? TRUE : $directory; $private = $space->controllers->variable->get('spaces_og_private'); if ($op == 'update' && $private != $node->og_private) { // Privacy has changed, update og_public flags, and queue a rebuid. db_query("UPDATE {og_access_post} og_p INNER JOIN {og_ancestry} og_a ON og_p.nid = og_a.nid INNER JOIN {node} n ON og_p.nid = n.nid SET og_public = %d WHERE og_a.group_nid = %d", !$private, $node->nid); node_access_needs_rebuild(TRUE); } $node->og_private = $private === NULL ? FALSE : $private; og_update_group($node); } // Save PURL modifier. $modifier = array('provider' => 'spaces_og', 'id' => $node->nid); if (is_array($node->purl) && !empty($node->purl['value'])) { $modifier['value'] = $node->purl['value']; purl_save($modifier); } else if (empty($node->purl)) { $modifier['value'] = "{$node->type}-{$node->nid}"; purl_save($modifier); } break; case 'delete': spaces_delete('og', $node->nid); purl_delete(array('provider' => 'spaces_og', 'id' => $node->nid)); break; } } // Nodes in groups else if (!og_is_omitted_type($node->type)) { switch ($op) { case 'validate': // Enforce groups for OG. OG enforces audiences via required form // elements that Spaces removes. // @see og_form_add_og_audience() // @see _spaces_og_form_alter_node() if (variable_get('og_audience_required', FALSE) && empty($node->og_groups)) { if (isset($node->spaces_og_audience) && ((int)$node->spaces_og_audience !== 0)) { $node->og_groups[$node->spaces_og_audience] = $node->spaces_og_audience; } else { // @todo This error will leave none 'administer nodes' users in a // dead end. Ideally, access should be restricted on the menu // level. form_set_error('spaces_og_audience', t('This content type must be posted in a group.')); } } break; case 'prepare': case 'presave': $space = spaces_get_space(); if ($space && $space->type == 'og') { _spaces_og_enforce_privacy($space->id, $node); } else if (!empty($node->og_groups)) { _spaces_og_enforce_privacy(current($node->og_groups), $node); } if (isset($node->spaces_og_audience) && ((int)$node->spaces_og_audience !== 0)) { $node->og_groups[$node->spaces_og_audience] = $node->spaces_og_audience; } break; } } } /** * Implementation of hook_form_alter() for ctools_export_ui_edit_item(). */ function spaces_og_form_ctools_export_ui_edit_item_form_alter(&$form, $form_state) { if (isset($form_state['item'], $form_state['item']->table, $form_state['item']->space_type) && $form_state['item']->space_type === 'og') { module_load_include('inc', 'spaces_og', 'spaces_og.pages'); _spaces_og_form_spaces_preset_editor_alter($form, $form_state); } } /** * Implementation of hook_form_alter() for node_delete_confirm(). */ function spaces_og_form_node_delete_confirm_alter(&$form, $form_state) { module_load_include('inc', 'spaces_og', 'spaces_og.pages'); $node = node_load($form['nid']['#value']); if (og_is_group_type($node->type)) { $form['#submit'][] = '_spaces_og_node_delete_confirm_submit'; } elseif (og_is_group_post_type($node->type)) { $space = spaces_get_space(); if ($space && $space->type == 'og') { $preset_val = $space->controllers->variable->get('site_frontpage', 'preset'); $space_val = $space->controllers->variable->get('site_frontpage', 'space'); if (!empty($preset_val) || !empty($space_val)) { $form['#redirect'] = url('', array('absolute' => TRUE,'purl' => array('provider' => 'spaces_og', 'id' => $space->id))); } } } } /** * Implementation of hook_form_alter(). */ function spaces_og_form_alter(&$form, $form_state, $form_id) { if ($form['#id'] == 'node-form' && (arg(0) .'/'. arg(1) != 'admin/content')) { // Group nodes if (og_is_group_type($form['#node']->type)) { module_load_include('inc', 'spaces_og', 'spaces_og.pages'); _spaces_og_form_alter_group($form, $form_state); } // Group enabled content types else if (!og_is_omitted_type($form['#node']->type)) { module_load_include('inc', 'spaces_og', 'spaces_og.pages'); _spaces_og_form_alter_node($form, $form_state); } } } /** * Group form submit handler. */ function spaces_og_form_group_submit($form, &$form_state) { if (!empty($form_state['nid']) && $space = spaces_load('og', $form_state['nid'])) { $preset_val = $space->controllers->variable->get('site_frontpage', 'preset'); $space_val = $space->controllers->variable->get('site_frontpage', 'space'); if (!empty($preset_val) || !empty($space_val)) { purl_goto($space->controllers->variable->get('site_frontpage'), array('purl' => array('provider' => 'spaces_og', 'id' => $space->id))); } else { purl_goto("node/{$space->id}", array('purl' => array('provider' => 'spaces_og', 'id' => $space->id))); } } } /** * Custom subscription link - use "join" instead of "subscribe" - make it shorter. */ function spaces_og_subscription_link() { global $user; if ($user->uid && is_array($user->og_groups) && $space = spaces_get_space()) { $gid = $space->id; $node = node_load($gid); // User is a member if (isset($user->og_groups[$gid])) { // Do not let managers leave the group -- TODO: figure out a // better workflow for these situations. if (!og_is_group_admin($node) && $node->og_selective != OG_CLOSED) { return array( 'title' => t('Leave this group'), 'href' => "og/unsubscribe/{$node->nid}/{$user->uid}", 'query' => 'destination='. $_GET['q'], ); } } // User has requested membership else if (db_result(db_query("SELECT count(nid) FROM {og_uid} WHERE nid = %d AND uid = %d AND is_active = 0", $gid, $user->uid))) { return array( 'title' => t('Cancel request to join'), 'href' => "og/unsubscribe/{$node->nid}/{$user->uid}", 'query' => 'destination='. $_GET['q'], ); } // User is not a member else { if ($node->og_selective == OG_MODERATED) { return array( 'title' => t('Request to join'), 'href' => "og/subscribe/". $node->nid, 'query' => 'destination='. $_GET['q'], ); } elseif ($node->og_selective == OG_OPEN) { return array( 'title' => t('Join this group'), 'href' => "og/subscribe/". $node->nid, 'query' => 'destination='. $_GET['q'], ); } } } return; } /** * Enforces OG group and privacy settings on a node. */ function _spaces_og_enforce_privacy($gid, &$node) { if ($group = node_load($gid)) { if ($group->og_private) { $node->og_public = OG_VISIBLE_GROUPONLY; } else { $node->og_public = OG_VISIBLE_BOTH; } $node->og_groups = array($gid => $gid); return TRUE; } return FALSE; } /** * Implementation of hook_context_page_reaction(). * Allows Spaces OG to set the breadcrumb just prior to theme('page') * taking over. */ function spaces_og_context_page_reaction() { $space = spaces_get_space(); if ($space && $space->type === 'og') { $item = menu_get_item(); // Only set the breadcrumb if user has access to this page. if ($item['access']) { $bc = og_get_breadcrumb($space->group); $bc[0] = l(t('Home'), "", array('purl' => array('disabled' => TRUE))); drupal_alter('spaces_og_breadcrumb', $bc); drupal_set_breadcrumb($bc); } } } /** * Implementation of hook_db_rewrite_sql(). */ function spaces_og_db_rewrite_sql($query, $primary_table, $primary_field, $args) { switch ($primary_table) { case 'term_data': case 'td': case 't': // This check prevents rewrites of queries run against single nodes // (e.g. node_load()) and rewrites in the admin section of the site. if (arg(0) !== 'admin' && strpos($query, 'r.vid = %d') === FALSE) { $return = array(); $return['distinct'] = 1; $return['join'] = " LEFT JOIN {term_node} spaces_og_tn ON {$primary_table}.{$primary_field} = spaces_og_tn.tid LEFT JOIN {vocabulary} spaces_og_v ON {$primary_table}.vid = spaces_og_v.vid LEFT JOIN {og_ancestry} spaces_og_oga ON spaces_og_tn.nid = spaces_og_oga.nid LEFT JOIN {node} spaces_og_n ON spaces_og_oga.group_nid = spaces_og_n.nid"; // Show tags that haven't been used or are on non-og enabled nodes. $return['where'] = "(spaces_og_oga.group_nid IS NULL)"; // Allow any terms that do not belong to a freetagging vocab. $return['where'] .= " OR (spaces_og_v.tags = 0)"; // Allow any tags that belong to nodes in a user's groups. global $user; if (!empty($user->og_groups)) { $groups = array_keys($user->og_groups); $groups = implode(', ', $groups); $return['where'] .= " OR (spaces_og_oga.group_nid IN ({$groups}) AND spaces_og_n.status = 1)"; } return $return; } break; case 'users': case 'u'; // This check prevents rewrites of queries run to retrive single users, // (e.g. user_load()) and rewrites in the admin sectin of the site. if (arg(0) !== 'admin' && !user_access('view users outside groups') && (strpos($query, 'uid = %d') === FALSE)) { $return = array(); $return['distinct'] = 1; $return['join'] = " LEFT JOIN {og_uid} spaces_og_ogu ON {$primary_table}.{$primary_field} = spaces_og_ogu.uid JOIN {node} spaces_og_n ON spaces_og_ogu.nid = spaces_og_n.nid"; // Filter by user's groups. global $user; if (!empty($user->og_groups)) { $groups = array_keys($user->og_groups); $groups = implode(', ', $groups); $return['where'] = " (spaces_og_ogu.nid IN ({$groups}) AND spaces_og_n.status = 1) OR ({$primary_table}.{$primary_field} = {$user->uid})"; } // If not in a group and not a member of any groups, show no one. else { $return['where'] = "FALSE OR ({$primary_table}.{$primary_field} = {$user->uid})"; } return $return; } break; } } /** * Implementation of hook_views_api(). */ function spaces_og_views_api() { return array( 'api' => 2, 'path' => drupal_get_path('module', 'spaces_og') .'/views', ); }