$groupnode ? $groupnode->nid : -1); } // ---------- Table OG function og_views_data_og() { $data['og']['table']['group'] = t('Organic groups'); $data['og']['table']['join'] = array( 'node' => array( 'left_field' => 'nid', 'field' => 'nid', ), ); $data['og']['description'] = array( 'title' => t('Group: Description'), 'field' => array( 'handler' => 'views_handler_field_markup', 'format' => FILTER_FORMAT_DEFAULT, 'click sortable' => FALSE, ), ); $data['og']['member_count'] = array( 'title' => t('Group: Members count'), 'field' => array( 'handler' => 'views_handler_field_og_member_count', 'click sortable' => TRUE, 'help' => t('Number of members for a group. Excludes memberships which are pending approval.'), ), ); $data['og']['post_count'] = array( 'title' => t('Group: Post count'), 'field' => array( 'handler' => 'views_handler_field_og_post_count', 'click sortable' => TRUE, 'help' => t('Number of published posts in a group. Can be restricted by node type using the Option dropdown.'), 'notafield' => TRUE, ), ); $data['og']['post_count_new'] = array( 'title' => t('Group: Post count *new*'), 'field' => array( 'handler' => 'views_handler_field_og_post_count_new', 'click sortable' => TRUE, 'help' => t('Number of new posts in a group for the current user.'), ), ); $data['og']['selective'] = array( 'title' => t('Group: Selective'), 'help' => t('The group preference which determines how membership requests are managed (moderated, invite only, etc.).'), 'field' => array( 'handler' => 'views_handler_field_og_selective', ), 'filter' => array( 'handler' => 'views_handler_filter_og_selective', ), ); $data['og']['private'] = array( 'title' => t('Group: Private'), 'help' => t('Is the group home page private or not.'), 'field' => array( 'handler' => 'views_handler_field_boolean', ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); $data['og']['directory'] = array( 'title' => t('Group: List in directory'), 'help' => t('Admin specifies whether or not a group appears in the public listings.'), 'field' => array( 'handler' => 'views_handler_field_boolean', ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); $data['og']['subscribe'] = array( 'title' => t('Group: Join link'), 'help' => t('Displays a links for joining a group when a user is not already a member.'), 'field' => array( 'handler' => 'views_handler_field_og_subscribe', ), ); $data['og']['notification'] = array( 'title' => t('Group: Notification'), 'help' => t('Does group sending email notifications to its members by default'), 'field' => array( 'handler' => 'views_handler_field_boolean', ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); if (module_exists('locale')) { $data['og']['language'] = array( 'title' => t('Group: Language'), 'help' => t('Displays the language selected for a given group.'), 'field' => array( 'handler' => 'views_handler_field_node_language', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_node_language', ), 'argument' => array( 'handler' => 'views_handler_argument_node_language', ), ); } // pseudofield // Node type $data['og']['type_groups'] = array( 'title' => t('Group types'), // The item it appears as on the UI, 'help' => t('The type of a group (for example, "blog entry", "forum post", "story", etc).'), 'real field' => 'type', 'filter' => array( 'handler' => 'views_handler_filter_og_type', ), ); $data['og']['type_groups_all'] = array( 'title' => t('Group types (all)'), // The item it appears as on the UI, 'help' => t('The type of a group (for example, "blog entry", "forum post", "story", etc).'), 'real field' => 'type', 'filter' => array( 'handler' => 'views_handler_filter_og_type_all', 'help' => t('Restrict to all content types that have been marked as groups.'), ), ); return $data; } /** * We do not try to run db_rewrite_sql() on this subquery so the count is potentially more than the user can see. */ class views_handler_field_og_post_count extends views_handler_field_numeric { function query() { $sql = "SELECT COUNT(n.nid) FROM {node} n INNER JOIN {og_ancestry} oga ON n.nid = oga.nid WHERE n.status = 1 AND oga.group_nid = %d"; $sql = str_replace('%d', 'og.nid', $sql); $this->query->add_field('', "($sql)", 'post_count'); $this->field_alias = 'post_count'; } } class views_handler_field_og_member_count extends views_handler_field_numeric { function query() { $sql = og_list_users_sql(1, 0, NULL, TRUE); $sql = str_replace('%d', 'og.nid', $sql); $this->query->add_field('', "($sql)", 'member_count'); $this->field_alias = 'member_count'; } function render($values) { $nid = $values->nid; $txt = $values->member_count; if (og_is_group_member($nid)) { return og_is_picture() ? l($txt, "og/users/$nid/faces") : l($txt, "og/users/$nid"); } else { return parent::render($values); } } } class views_handler_filter_og_type_all extends views_handler_filter { function query() { if ($group_types = og_get_types('group')) { $placeholders = db_placeholders($group_types, 'varchar'); $table = $this->query->ensure_table('node'); $this->query->add_where($this->options['group'], "$table.type IN ($placeholders)", $group_types); } else { $this->query->add_where($this->options['group'], "FALSE"); drupal_set_message(t('You have no node types which are acting as groups. See the notes section of the !readme_file and the content types fieldset at top of OG settings.', array('!readme_file' => og_readme(), '!settings' => url('admin/og/og'))), 'error'); } } } // TODOL: query() does not work. class views_handler_filter_og_type extends views_handler_filter_node_type { function get_value_options() { if (!isset($this->value_options)) { $this->value_title = t('Group node type'); $group_types = og_get_types('group'); $types = node_get_types(); foreach ($group_types as $group_type) { $options[$group_type] = $types[$group_type]->name; } $this->value_options = $options; } } } /** * Field handler to show Selective state. * * @ingroup views_field_handlers */ class views_handler_field_og_selective extends views_handler_field { function render($values) { $map = og_selective_map(); return $map[$values->{$this->field_alias}]; } } /* * Field handler to filter by Selective state * * @ingroup views_filter_handlers */ class views_handler_filter_og_selective extends views_handler_filter_in_operator { function get_value_options() { if (isset($this->value_options)) { return; } $this->value_options = array(); foreach (og_selective_map() as $key => $name) { $this->value_options[$key] = $name; } } } /** * Field handler to allow show 'join' link or empty if already member. * * @ingroup views_field_handlers */ class views_handler_field_og_subscribe extends views_handler_field { function construct() { parent::construct(); $this->additional_fields['selective'] = 'selective'; } function query() { $this->ensure_my_table(); $this->add_additional_fields(); } function render($values) { global $user; if (!in_array($values->nid, array_keys($user->og_groups))) { switch ((int)$values->{$this->aliases['selective']}) { case OG_CLOSED: return ''. t('Closed'). ''; case OG_INVITE_ONLY: return ''. t('Invite only'). ''; default: return og_subscribe_link(node_load((int)$values->nid)); } } } } // ------------ Table 'og_ancestry' function og_views_data_og_ancestry() { $data['og_ancestry']['table']['group'] = t('Organic groups'); $data['og_ancestry']['table']['base'] = array( 'field' => 'nid', 'title' => t('Group posts'), 'help' => t('Posts which are affiiated with a group.'), ); $data['og_ancestry']['table']['join'] = array( 'node' => array( 'left_field' => 'nid', 'field' => 'nid', ), ); $filterhelp = t('Posts are filtered for specified organic groups. The page context (if Display is a page) will be set to the first listed group. That means that blocks and breadcrumbs (and theme and locale, if applicable) will be based upon the first specified node id.'); $data['og_ancestry']['group_nid'] = array( 'title' => t('Groups'), 'help' => t('The groups for a post.'), 'field' => array( 'handler' => 'views_handler_field_og_group_nids', ), 'relationship' => array( 'title' => t('Group node (post)'), 'help' => t("Bring in information about the group node based on a post's groups."), 'base' => 'node', 'field' => 'group_nid', 'handler' => 'views_handler_relationship', 'label' => t('Group node (post)'), ), 'filter' => array( 'handler' => 'views_handler_filter_og_group_nid', 'numeric' => TRUE, 'help' => $filterhelp, ), 'argument' => array( 'name' => t('Post: in specified group (by number)'), 'name field' => 'title', // the field to display in the summary. 'validate type' => 'nid', 'handler' => 'views_handler_argument_og_group_nid', 'help' => $filterhelp, ), ); $data['og_ancestry']['nid'] = array( 'title' => t('Post: Nid'), 'help' => t('The node ID of the node.'), 'field' => array( 'handler' => 'views_handler_field_node', ), ); $data['og_ancestry']['picg'] = array( 'title' => t('OG: Posts in current group'), 'help' => t('Posts in current group. Useful for blocks where determining context is hard. If page is not in any group context, no nodes are listed and thus a block would not appear.'), 'filter' => array( 'handler' => 'views_handler_filter_og_picg', ), ); // TOODL: yes_empty field $data['og_ancestry']['is_public'] = array( 'title' => t('Post: Public'), 'help' => t('Is a given post public or private according to OG.'), 'field' => array( 'handler' => 'views_handler_field_boolean', ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); return $data; } class views_handler_filter_og_group_nid extends views_handler_filter_numeric { function query() { $node = node_load((int)$this->value['value']); og_set_group_context($node); parent::query(); } } class views_handler_argument_og_group_nid extends views_handler_argument_numeric { // Set context based on first node passed. function query() { $args = explode(',', $this->argument); $node = node_load((int)$args[0]); og_set_group_context($node); parent::query(); } /** * Override the behavior of title(). Get the title of the node. */ function title_query() { $titles = array(); $placeholders = implode(', ', array_fill(0, sizeof($this->value), '%d')); $result = db_query("SELECT n.title FROM {node} n WHERE n.nid IN ($placeholders)", $this->value); while ($term = db_fetch_object($result)) { $titles[] = check_plain($term->title); } return $titles; } } class views_handler_field_og_group_nids extends views_handler_field_prerender_list { function init(&$view, $options) { parent::init($view, $options); $this->additional_fields['og_ancestry_nid'] = array('table' => 'og_ancestry', 'field' => 'nid'); } /** * Add this term to the query */ function query() { $this->add_additional_fields(); } // we have to query to get all the groups into a single element function pre_render($values) { // field_alias is used by our render method. $this->field_alias = $this->aliases['og_ancestry_nid']; foreach ($values as $value) { $result = og_get_node_groups_result($value->nid); while ($row = db_fetch_object($result)) { $this->items[$value->nid][$row->group_nid] = l($row->title, "node/$row->group_nid"); } } } } /** * Lovely filter handler which restricts posts to the current group. Useful for group related blocks. **/ class views_handler_filter_og_picg extends views_handler_filter { function query() { $table = $this->ensure_my_table(); $this->query->add_where($this->options['group'], "$table.group_nid = ***CURRENT_GID***"); } } // --------- Table og_uid function og_views_data_og_uid() { $data['og_uid']['table']['group'] = t('Organic groups'); $data['og_uid']['table']['join'] = array( 'node' => array( 'left_field' => 'nid', 'field' => 'nid', ), 'users' => array( 'left_field' => 'uid', 'field' => 'uid', ), ); $data['og_uid']['nid'] = array( 'title' => t('Group'), 'help' => t('Group that a member belongs to.'), 'relationship' => array( 'title' => t('Group node (member)'), 'help' => t("Bring in information about the group node based on a user's membership."), 'base' => 'node', 'field' => 'nid', 'handler' => 'views_handler_relationship', 'label' => t('Group node (member)'), ), 'argument' => array( 'title' => t('Group node'), 'handler' => 'views_handler_argument_og_uid_nid', 'help' => t('Members are filtered for a specific group.'), ), ); $data['og_uid']['uid'] = array( 'title' => t('Group member'), // 'help' => t('foo') 'filter' => array( 'handler' => 'views_handler_filter_user_current', 'help' => t("OG: Group in user's groups"), ), ); $data['og_uid']['mail_type'] = array( 'title' => t('OG: Notification email'), 'help' => t('Does member receive email notifications for a group.'), 'field' => array( 'handler' => 'views_handler_field_boolean', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); $data['og_uid']['managelinkadmin'] = array( 'title' => t('OG: Admin manage link'), 'help' => t('A link to the Admin create or remove page.'), 'field' => array( 'handler' => 'views_handler_field_og_managelinkadmin', 'click sortable' => FALSE, ), ); $data['og_uid']['managelinkmy'] = array( 'title' => t('OG: Edit membership link'), 'help' => t('A link to the My membership page.'), 'field' => array( 'handler' => 'views_handler_field_og_managelinkmy', 'click sortable' => FALSE, ), ); $data['og_uid']['managelink'] = array( 'title' => t('OG: Approve/Deny/Remove membership link'), 'help' => t('A link to approve/deny/remove a group member.'), 'field' => array( 'handler' => 'views_handler_field_og_managelink', 'click sortable' => FALSE, ), ); $data['og_uid']['is_admin'] = array( 'title' => t('OG: Is member an admin in a group'), 'help' => t('Add admin text if user is the group manager.'), 'field' => array( 'handler' => 'views_handler_field_og_is_admin', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_og_is_admin', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); $data['og_uid']['is_active'] = array( 'title' => t('OG: Is membership approved'), 'help' => t("Add approval needed user if user's membership request is pending."), 'field' => array( 'handler' => 'views_handler_field_og_is_active', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', ), 'sort' => array( 'handler' => 'views_handler_sort', ), ); $data['og_uid']['is_manager'] = array( 'title' => t('OG: Is the group manager'), 'help' => t('Add manager text if user is the group manager.'), 'field' => array( 'handler' => 'views_handler_field_og_is_manager', 'click sortable' => FALSE, ), 'filter' => array( 'handler' => 'views_handler_filter_boolean_operator', ), ); $data['og_uid']['created'] = array( 'title' => t('OG: Membership create date'), 'help' => t('The date when the membership was created.'), 'field' => array( 'handler' => 'views_handler_field_date', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_date', ), 'sort' => array( 'handler' => 'views_handler_sort_date', ), ); $data['og_uid']['changed'] = array( 'title' => t('OG: Membership last updated date'), 'help' => t('The date when the membership was last updated.'), 'field' => array( 'handler' => 'views_handler_field_date', 'click sortable' => TRUE, ), 'filter' => array( 'handler' => 'views_handler_filter_date', ), 'sort' => array( 'handler' => 'views_handler_sort_date', ), ); return $data; } /** * Allow Group ID(s) as argument * * @ingroup views_argument_handlers */ class views_handler_argument_og_uid_nid extends views_handler_argument_numeric { // TODOL: set context? /** * Give an argument the opportunity to modify the breadcrumb, if it wants. * This only gets called on displays where a breadcrumb is actually used. * * The breadcrumb will be in the form of an array, with the keys being * the path and the value being the already sanitized title of the path. */ function set_breadcrumb(&$breadcrumb) { $nid = $this->value[0];; // TODOL: not working. // $breadcrumb = og_views_set_breadcrumb($nid); } } class views_handler_filter_og_is_admin extends views_handler_filter_in_operator { function get_value_options() { if (!isset($this->value_options)) { $this->value_title = t('Member types'); $options = array(t('Members'), t('Group administrators')); $this->value_options = $options; } } // 0 won't work as a key for checkboxes. function value_form(&$form, &$form_state) { parent::value_form($form, $form_state); $form['value']['#type'] = 'select'; $form['value']['#multiple'] = TRUE; } // Remove problematic array_filter(). function value_submit($form, &$form_state) { $form_state['values']['options']['value'] = $form_state['values']['options']['value']; } } /** * Field handler to show if user is admin or not. * * @ingroup views_field_handlers */ class views_handler_field_og_is_active extends views_handler_field { function render($values) { $is_active = $values->{$this->field_alias}; if (!$is_active) { return '('. t('approval needed'). ')'; } } } /** * Field handler to show if user is admin or not. * * @ingroup views_field_handlers */ class views_handler_field_og_is_admin extends views_handler_field { function render($values) { $is_admin = $values->{$this->field_alias}; // don't use og_is_group_admin() here since we don't want mark on 'admin nodes' people. if ($is_admin) { return t('admin'); } } } /** * Field handler to show if user is manager or not of the displayed group node. * * @ingroup views_field_handlers */ class views_handler_field_og_is_manager extends views_handler_field { function construct() { parent::construct(); $this->additional_fields['uid'] = array('table' => 'og_uid', 'field' => 'uid'); // TODOL: Sometimes node table is not recognized (i.e. when listing users). $this->additional_fields['node_uid'] = array('table' => 'node', 'field' => 'uid'); } function query() { $this->ensure_my_table(); $this->query->ensure_table('node'); $this->add_additional_fields(); } function render($values) { $uid = $values->{$this->aliases['uid']}; $node_uid = $values->{$this->aliases['node_uid']}; if ($uid == $node_uid) { return ''. t('Manager'). ''; } } } /** * Field handler to add/remove an admin. * * @ingroup views_field_handlers */ class views_handler_field_og_managelinkadmin extends views_handler_field { function construct() { parent::construct(); $this->additional_fields['uid'] = array('table' => 'og_uid', 'field' => 'uid'); $this->additional_fields['is_admin'] = array('table' => 'og_uid', 'field' => 'is_admin'); $this->additional_fields['nid'] = array('table' => 'og_uid', 'field' => 'nid'); } function query() { $this->ensure_my_table(); $this->add_additional_fields(); } function render($values) { $nid = $values->{$this->aliases['nid']}; $uid = $values->{$this->aliases['uid']}; $is_admin = $values->{$this->aliases['is_admin']}; $node = node_load($nid); // Only show links to group admins. And don't show next to group manager. if (og_is_group_admin($node) && $uid != $node->uid) { if ($is_admin) { return l(t('Admin: Remove'), "og/delete_admin/$nid/$uid", array('query' => drupal_get_destination())); } else { return l(t('Admin: Create'), "og/create_admin/$nid/$uid", array('query' => drupal_get_destination())); } } } } /** * Field handler to approve/deny a subscription request, or remove a member. * * @ingroup views_field_handlers */ class views_handler_field_og_managelink extends views_handler_field { function construct() { parent::construct(); $this->additional_fields['is_active'] = array('table' => 'og_uid', 'field' => 'is_active'); $this->additional_fields['uid'] = array('table' => 'og_uid', 'field' => 'uid'); $this->additional_fields['nid'] = array('table' => 'og_uid', 'field' => 'nid'); } function query() { $this->ensure_my_table(); $this->add_additional_fields(); } function render($values) { $nid = $values->{$this->aliases['nid']}; $uid = $values->{$this->aliases['uid']}; $is_active = $values->{$this->aliases['is_active']}; $node = node_load($nid); // Only show links to group admins. And don't show next to group manager. if (og_is_group_admin($node) && $uid != $node->uid) { if ($is_active) { return l(t('Remove membership'), "og/unsubscribe/$nid/$uid", array('query' => drupal_get_destination())); } else { $token = og_get_token($nid); return t('Request: approve or deny.', array('@approve' => url("og/approve/$nid/$uid/$token", array('query' => drupal_get_destination())), '@deny' => url("og/deny/$nid/$uid/$token", array('query' => drupal_get_destination())))); } } } } class views_handler_field_og_managelinkmy extends views_handler_field { function query() { $this->ensure_my_table(); $this->add_additional_fields(); } function render($values) { global $user; return l(t('Edit membership'), "og/manage/$values->nid", array('query' => drupal_get_destination())); } } /** * An implementation of hook_views_plugins(). */ function og_views_plugins() { return array( 'argument validator' => array( 'og_group_types' => array( 'title' => t('Group nodes'), 'handler' => 'views_plugin_argument_validate_og_group_types', ), ), ); } /** * Validate whether an argument is a group node. Borrows heavily form the Node argument validator. */ class views_plugin_argument_validate_og_group_types extends views_plugin_argument_validate { // What does this do? var $option_name = 'validate_argument_og_group_types'; function validate_form(&$form, &$form_state) { $form['validate_argument_nid_type'] = array( '#type' => 'select', '#title' => t('Argument type'), '#options' => array( 'nid' => t('Node ID'), 'nids' => t("Node ID's separated by , or +"), ), '#default_value' => isset($this->argument->options['validate_argument_nid_type']) ? $this->argument->options['validate_argument_nid_type'] : 'nid', '#process' => array('views_process_dependency'), '#dependency' => array('edit-options-validate-type' => array($this->id)), ); $form['validate_argument_is_member'] = array( '#type' => 'checkbox', '#title' => t('Validate current user is a member of a specified group'), '#default_value' => !empty($this->argument->options['validate_argument_is_member']), '#process' => array('views_process_dependency'), '#dependency' => array('edit-options-validate-type' => array($this->id)), ); } function validate_argument($argument) { $types = og_get_types('group'); $type = isset($this->argument->options['validate_argument_nid_type']) ? $this->argument->options['validate_argument_nid_type'] : 'nid'; switch ($type) { case 'nid': if (!is_numeric($argument)) { return FALSE; } $node = node_load($argument); if (!$node) { return FALSE; } if (!og_is_group_type($node->type)) { return FALSE; } if (!empty($this->argument->options['validate_argument_is_member'])) { if (!og_is_group_member($node->nid)) { return FALSE; } } // Save the title() handlers some work. $this->argument->validated_title = check_plain($node->title); // Admin has not setup any content types to behave as a group. Thats unsupported. if (empty($types)) { return TRUE; } return TRUE; case 'nids': $nids = new stdClass(); $nids->value = array($argument); $nids = views_break_phrase($argument, $nids); if ($nids->value == -1) { return FALSE; } $placeholders = implode(', ', array_fill(0, sizeof($nids->value), '%d')); $has_membership = FALSE; $titles = array(); $test_nids = drupal_map_assoc($nids->value); $result = db_query("SELECT nid, type, title FROM {node} WHERE nid IN ($placeholders)", $nids->value); while ($node = db_fetch_object($result)) { if (!og_is_group_type($node->type)) { return FALSE; } if (!empty($this->argument->options['validate_argument_is_member'])) { // If user is a member of any of the specified groups, then she has access. if (!$has_membership && og_is_group_member($node->nid)) { $has_membership = TRUE; } } else { $has_membership = TRUE; } $titles[] = check_plain($node->title); unset($test_nids[$node->nid]); } $this->argument->validated_title = implode($nids->operator == 'or' ? ' + ' : ', ', $titles); // If $test is not empty, we did not find a nid. return empty($test_nids) && $has_membership; } } } function og_views_set_breadcrumb($nid) { $node = node_load((int)$nid); $bc = array( '' => t('Home'), "node/$nid" => check_plain($node->title), ); return $bc; }