Skip to:
Content

BuddyPress.org

Opened 8 years ago

Last modified 4 years ago

#6677 assigned enhancement

Groups: Draft, Locked or Suspended status

Reported by: dcavins's profile dcavins Owned by: dcavins's profile dcavins
Milestone: Awaiting Contributions Priority: normal
Severity: normal Version: 2.6.1.1
Component: Groups Keywords: has-patch dev-feedback
Cc: dcavins, espellcaste@…, egyptimhotep@…, info@…, aqua6617@…

Description

I've been thinking about groups a bit lately, and in a more project-oriented setup, sometimes it would be useful to move a group to an inactive status. Examples:

  • You're getting ready to launch a new project but are not quite ready, so a group might be "draft". (Maybe the members could see it, maybe they couldn't? We use hidden for this now.)
  • There's some poor behavior in a group, and you want to suspend it until you get it straightened out. (Maybe the members would only see a suspended notice but no content when they visit it?)
  • A project has ended and you want the group to continue to be a resource for its members but want to prevent new activity. "Carbonite," um "Locked".

Is this functionality that would be useful to others, or is this so specific that it's really not applicable in more vanilla BP setups?

Attachments (1)

6677.1.patch (107.4 KB) - added by dcavins 8 years ago.
First draft of adding group capability checks.

Download all attachments as: .zip

Change History (24)

#1 @hnla
8 years ago

Interesting, I'd say probably quite useful series of group admin settings.

Like the idea of a sort of 'Read Only' group setting, keeps the group visible but suspends activity in it.

#2 @boonebgorges
8 years ago

Yeah, some variation on this would be useful on many sites that I've worked on.

Technically, I'd suggest that we do *not* use the 'status' column to hold this information. Something like 'draft' would be a piece of info that coexists with visibility status. Maybe a taxonomy? See https://buddypress.trac.wordpress.org/ticket/1125#comment:6 for some old but still relevant thoughts about the monolithic nature of group 'status'.

More to the point, if things like 'visibility' and 'updatabality' and 'appearance in directories' were independent, it becomes possible to imagine a group configuration process that allows for "draft" groups (or whatever) without making any overly specific assumptions about use cases.

#3 @dcavins
8 years ago

Hmm. I've been turning over in my mind various schemes we've talked about for a more flexible group-definition system and have been dreaming of something like WP's role/capabilities system for groups, like current_group_can( 'show_in_directories' ), so maybe that's the real solution here. I can imagine a few core group types (that could be editable by site admins) like a user role :

public => 'show_in_directories', 'anyone_can_join', 'send_invites',
private => 'show_in_directories', 'accepts_membership_requests', 'send_invites',
hidden => 'send_invites'

And site admins could add custom group types that mix and match from our core set of capabilities. Components could add capabilities and defaults via the Group_Extension class and filter caps that are already in place. Site admins could even give a custom set of caps to a single group if they wished, maybe that's how we'd put a group into read-only mode. related ideas #6094, #6095.

We'd still have a problem that if a group became locked, group-related plugins would have to act, too, like BP Docs or bbPress, so that's sort of a hairy problem. :)

#4 @DJPaul
8 years ago

  • Milestone changed from Awaiting Review to Future Release

Integrating capabilities is a bit different than suggesting group statuses (though they may be how we choose to implement group statuses).

Not sold by all your examples but I think you're onto something.

#5 @dcavins
8 years ago

  • Keywords has-patch dev-feedback added
  • Version changed from 2.3.3 to 2.6.1.1

Here's my first draft of an approach to adding more flexible group statuses and adding finer-grained control over group capabilities. This approach allows developers to filter the common group statuses, add completely new statuses, and check group capabilities. This is sort of a simplification of WP's user role capability system applied to groups.

Ways to filter group statuses:

Filter one of the default statuses (applies to all groups with that status):

add_filter( 'bp_groups_public_group_status_caps', 'my_edit_public_group_status_filter' );
function my_edit_public_group_status_filter( $caps ) {
    // Members must request to join public groups and be approved.
    $caps['join_method'] = 'accepts_membership_requests';
    return $caps;
}

Add a completely new status (or remove an existing status):

add_action( 'bp_groups_register_group_statuses', 'my_register_group_status' );
function my_register_group_status() {
    // A generally public group with moderated membership.
    bp_groups_register_group_status( 'sprivate', array(
        'display_name'    => 'Semi Private',
        'capabilities'    => array( 'join_method' => 'accepts_membership_requests' ),
        'fallback_status' => 'public',
        'priority'        => 20,
    ) );
    // Make a group visible only to site admins.
    bp_groups_register_group_status( 'suspended', array(
        'display_name'    => 'Suspended',
        'capabilities'    => array( 'show_group' => 'noone', 'access_group' => 'noone', ),
        'fallback_status' => 'hidden',
        'priority'        => 95,
    ) );
    // Remove the stock "hidden" status (this would be a bad idea in the short term).
    bp_groups_deregister_group_status( 'hidden' );
}

Filter the capabilities for a particular group (or based on some group characteristic):

add_filter( 'bp_groups_group_object_set_caps', 'my_edit_group_no_2_caps', 10, 2 );
function my_edit_group_no_2_caps( $caps, $partial_group_object ) {
    // Members must request to join the group with the id of 2.
    if ( 2 == $partial_group_object->id ) {
        $caps['join_method'] = 'accepts_membership_requests';
    }
    return $caps;
}

Check the capability for a particular group by passing the group object into the following function:

$who_can_access = bp_groups_group_has_cap( $group, 'access_group' );

Caveats:

Custom statuses or very changed statuses will cause unexpected behavior in plugins that are checking the status for the three basic statuses: public, private, or hidden.

We'd need to get group-related plugins updated like this:
For instance, code that decided whether to create a public activity post like this:

if ( 'public' === $group->status ) {
    # do the thing
}

might become

if ( version_compare( bp_get_version(), '2.7', '>=' ) ) {
    if ( 'anyone' != bp_groups_group_has_cap( $group, 'access_group' ) ) {
        # do the thing
    }
} else {
    if ( 'public' === $group->status ) {
        # do the thing
    }
}

Orphaned custom statuses will also produce unexpected results.

It would be easy enough to build a status migration tool for the BP tools screen that displays unregistered group statuses and asks the site admin which status to migrate those groups to. But, this could be kind of awkward. We could also store a group's capabilities as a groupmeta item, but that has the disadvantage of requiring meta lookups. (Then the issue could be the group's status and the stored capability meta could get out of sync.)

To provide more granular visibility and access, I’ve added a potentially expensive routine get_hidden_group_ids() in BP_Groups_Group and BP_Groups_Members. The results are cached, but I’ll have to test this on a site with many users and groups to see if it’s viable.

Other changes:

I added two new parameters to the BP_Groups_Group object: is_visible and user_has_access which reflect the current user's relationship to the group.

Because of the caveats, I'm not entirely sold on this approach, but I'm putting it forward so we can figure out how to improve on it or do something smarter.

@dcavins
8 years ago

First draft of adding group capability checks.

This ticket was mentioned in Slack in #buddypress by dcavins. View the logs.


8 years ago

#7 @espellcaste
8 years ago

  • Cc espellcaste@… added

This ticket was mentioned in Slack in #buddypress by dcavins. View the logs.


8 years ago

This ticket was mentioned in Slack in #buddypress by dcavins. View the logs.


8 years ago

#10 follow-up: @imath
8 years ago

Thanks a lot @dcavins for your great work on this feature. I haven't tested the patch but here are my global point of view about this feature. I must say i feel using capabilities for groups is not right. If we look at WordPress post status. The logic is a bit different and i think it's the good one. Post status have properties eg:

  • label
  • internal
  • _builtin'
  • label_count
  • show_in_admin_status_list
  • private
  • protected
  • public
  • exclude_from_search
  • etc

And it's the user's cap that tels if he can read or write the post having a specific status for instance. I think we should probably have the same logic.

eg: bp_groups_user_can( $user_id, 'join_group', array( 'group' => $group ) )

Then you could check inside the list of status properties (anyone_can_join, accepts_membership_requests...).

Then i think we shouldn't develop a specific property for the retired forum component eg: post_in_forum. You can provide a specific filter but it should follow the generic restrictions.

Finally i'm not sure to understand what the status property of the group became. IMHO $group->status should always return the "id " of the status eg: public, private, hidden or whatever and then we can get the detailed properties of this status by using the global group status object, no ? Meaning if a plugin do stuff with this status it should still work? Why would we need to check the BuddyPress version ?

FYI there's a var_dump in src/bp-groups/bp-groups-template.php at line 3196 of your patch

#11 in reply to: ↑ 10 @dcavins
8 years ago

  • Owner set to dcavins
  • Status changed from new to assigned

Replying to imath:
Thanks, @imath, for your thoughtful comments. I'll take a look at the post status approach and see how it can help. I started originally working with the WP user roles/capabilities model because it's built to be extended, but I'm also somewhat familiar with it. So thanks for the suggestion for another inspiration.

Also, don't get hung up on the term "capabilities." I think your suggestion of "properties" is the right term, but the point is that certain group statuses convey allowances to group/user interactions, no matter what those things are called.

eg: bp_groups_user_can( $user_id, 'join_group', array( 'group' => $group ) )

Yes, much of what we need to check is user-specific, so making those items a bp_user_can() check is a great idea.

Finally i'm not sure to understand what the status property of the group became. IMHO $group->status should always return the "id " of the status eg: public, private, hidden or whatever and then we can get the detailed properties of this status by using the global group status object, no ? Meaning if a plugin do stuff with this status it should still work? Why would we need to check the BuddyPress version ?

My concern is that if one plugin registers a custom group status, but another plugin is checking by legacy status (public, private or hidden) then the logic in the second plugin falls apart for groups that have a custom status. Basically, once group status properties are in place, plugins need to check the property they care about rather than checking the status. Like checking for the user capability edit_others_posts instead of user role of editor.

FYI there's a var_dump in src/bp-groups/bp-groups-template.php at line 3196 of your patch

Thanks!

I also have come up with a plan to fix the problem of orphaned custom statuses, again using the user roles model for guidance. So instead of registering custom statuses on every page load, you'd register your custom status once on plugin activation and it'd be stored. I was trying to avoid that, but it makes for much more reliable behavior. (For instance, if you perform an action that deregisters a custom status, we could at that time switch the groups that have that status to that status's legacy fallback.)

I'll work on another iteration of this patch next week.

Thanks again!

#12 @egyptimhotep
8 years ago

  • Cc egyptimhotep@… added

#13 @dcavins
7 years ago

See #7359 for another use case for flexible statuses.

#14 @kalico
7 years ago

+1 Glad to see this is being worked on. Too bad it didn't make it into 2.6.1. Is there an updated release target?

I would like to add a use case that is basically the opposite of the "read only" status many have mentioned: a "no-read" status. I want to suspend a group without deleting the members, so it could be reinstated later.

I'm working on a membership site for groups. If the group does not pay their membership, we would like to block access to the group in one easy step, but be able to reinstate the group later, with no loss of content. We would like to retain all group settings and members, but suspend access for everyone (including group admins and mods)....with the option to return the group to active status.

Hidden status is not sufficient, because existing members can still get to the group if they know the URL. The proposed "draft" status might work, if it respects and deals with members (drafts don't typically have members) and has some sort of splash screen messaging for anyone who hits the group URL while in draft status....which raises the point of messaging.....

A suspended group should be able to to let group members know why they can't access the group. E.g., for our case we might say something like, "This group is no longer a member of XYZ Foundation. You can still access other areas of our website [here]."

Ideally, the message would be customizable using the post editor (or similar), and the member-facing page would retain the group header (image, cover photo, title, etc.) and just override all the group content and menus.

Again, thanks for working on this. I look forward to the finished result. :)

#15 @mikeboltonca
7 years ago

There are some very promising changes being discussed here.

I'd like to add another use case: open groups.

I use BuddyPress as part of a company intranet. Our groups are used as a quick way to find who works in a particular department or location, or to communicate with a whole department or location at once.

For our purposes, it makes sense for any staff member to be able to use any groups’ activity stream and bbPress forums without having to join that group. The only exceptions would be for hidden groups, such as our Management group; they should still be invisible if the user isn't a member of that group.

Related discussions:
https://buddypress.org/support/topic/open-groups-let-all-members-post-in-every-group-without-joining/
https://buddypress.trac.wordpress.org/ticket/7489#ticket
https://buddypress.org/support/topic/open-groups-allow-all-members-full-rights-in-every-group-without-joining/

#16 @wdfee
7 years ago

  • Cc info@… added

This ticket was mentioned in Slack in #buddypress by dcavins. View the logs.


6 years ago

#18 @DJPaul
6 years ago

@dcavins Any interest left in this ticket from your perspective?

If so, let's chat about it next time to plan next steps.

#19 @dcavins
6 years ago

Hi @DJPaul-

Yes, very much so. Whether the BP team knew it or not, we were already working on it, in these commits, ha ha: r11776, r11762, r11761

I'm hoping to have the chance to revisit my big changeset this month now that some of the prerequisites are in place. Once I have a new patch, I'll be sure to let you know so we can get serious about it!

#20 @DJPaul
6 years ago

😎

#21 @lenasterg
6 years ago

  • Cc aqua6617@… added

#22 @lenasterg
6 years ago

Also, some other possible statuses.

  • Pending group status (must be approved by site admin in order to be a functional group ).
  • "Semi-private". The contents of groups, belonging to that group type, be public but in order to become member, a request must be approved be the group admin.
Last edited 6 years ago by lenasterg (previous) (diff)

This ticket was mentioned in Slack in #buddypress by boone. View the logs.


4 years ago

Note: See TracTickets for help on using tickets.