Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added multitag support #542

Open
wants to merge 36 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
fa10f28
Access Query: Store protected doc IDs in singleton.
dcavins Mar 22, 2016
18ae587
Introduce bp_docs_comment_access taxonomy.
dcavins Mar 22, 2016
7e6a26f
Add doc comment protection to BP_Docs_Access_Query.
dcavins Mar 22, 2016
9308217
Enforce doc comment visibility settings.
dcavins Mar 22, 2016
abde079
Use WP cache to store protected doc and comment IDs.
dcavins Mar 29, 2016
faf6f6e
Access Query: Store protected doc IDs in singleton.
dcavins Mar 22, 2016
6cc9c03
Introduce bp_docs_comment_access taxonomy.
dcavins Mar 22, 2016
9d16358
Add doc comment protection to BP_Docs_Access_Query.
dcavins Mar 22, 2016
b5a960c
Enforce doc comment visibility settings.
dcavins Mar 22, 2016
0300513
Use WP cache to store protected doc and comment IDs.
dcavins Mar 29, 2016
a2cea13
Make BP_Docs_Access_Query singleton handle multiple users.
dcavins Mar 30, 2016
a0564c0
Hide some activity from Group Email Subscription.
dcavins Mar 30, 2016
03dcedb
Add tests for the behavior of BP_Docs_Access_Query.
dcavins Mar 30, 2016
fe0c793
Merge remote-tracking branch 'origin/activity-stream-exclusions' into…
dcavins Mar 30, 2016
9e14cdd
Correct restricted_doc and comment ID caching.
dcavins Apr 4, 2016
b09c60e
Correct basic bp_docs_access_query tests.
dcavins Apr 4, 2016
290ac04
Add tests for BP_Docs_Access_Query.
dcavins Apr 4, 2016
750c316
Add tests for BP_Docs_Access_Query.
dcavins Apr 4, 2016
6ebfe87
Add more bp_docs_access_query tests.
dcavins Apr 7, 2016
4fb98da
Correct @since tags for comment/activity item protection.
dcavins Apr 26, 2016
8d65ac9
Better behavior for activity action formatters when doc ID is empty.
boonebgorges Apr 11, 2016
2ec11d9
Readme.
boonebgorges Apr 11, 2016
4694e5a
Allow plugins to force the Folders metabox to be shown in an arbitrar…
boonebgorges Apr 20, 2016
2936b08
Don't attempt to cache htaccess path for the pageload.
boonebgorges Apr 24, 2016
369384f
Don't allow an activity item to be created when an unchanged revision…
boonebgorges Apr 24, 2016
b1040f7
Add `@group` annotation to attachment tests.
boonebgorges Apr 24, 2016
b65bf15
Fix incorrect ID on folder setting element.
boonebgorges Apr 25, 2016
43b367a
when attachments array is empty, use dummy array
christianwach Apr 29, 2016
bf96a7d
set higher priority for attachment filter
boonebgorges Apr 29, 2016
fbb1ef8
Readme.
boonebgorges Apr 29, 2016
82f36bd
Added catalan translation
sarjona May 6, 2016
116eea4
Readme.
boonebgorges May 6, 2016
d0c22f6
Tested up to WordPress 4.5.
boonebgorges May 6, 2016
6cdaf64
Bump stable tag to 1.9.1.
boonebgorges May 6, 2016
5da3ac2
Update .pot for 1.9.1.
boonebgorges May 6, 2016
55ef7d5
Added multitag support
sarjona May 9, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions bp-docs.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
class BP_Docs {
var $post_type_name;
var $associated_item_tax_name;
var $access_tax_name;
var $comment_access_tax_name;

/**
* Folders add-on.
Expand All @@ -28,6 +30,7 @@ function __construct() {
$this->post_type_name = apply_filters( 'bp_docs_post_type_name', 'bp_doc' );
$this->associated_item_tax_name = apply_filters( 'bp_docs_associated_item_tax_name', 'bp_docs_associated_item' );
$this->access_tax_name = apply_filters( 'bp_docs_access_tax_name', 'bp_docs_access' );
$this->comment_access_tax_name = apply_filters( 'bp_docs_comment_access_tax_name', 'bp_docs_comment_access' );

// :'(
wp_cache_add_non_persistent_groups( array( 'bp_docs_nonpersistent' ) );
Expand Down Expand Up @@ -329,6 +332,13 @@ function register_post_type() {
'query_var' => false,
) );

// Register the bp_docs_comment_access taxonomy.
register_taxonomy( $this->comment_access_tax_name, array( $this->post_type_name ), array(
'hierarchical' => false,
'show_ui' => false,
'query_var' => false,
) );

do_action( 'bp_docs_registered_post_type' );

// Only register on the root blog
Expand Down
257 changes: 235 additions & 22 deletions includes/access-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,37 @@ class BP_Docs_Access_Query {
protected $tax_query = array();
protected $user_groups = array();
protected $levels = array();
protected $comment_levels = array();
protected $comment_tax_query = array();

public static function init( $user_id = 0 ) {
static $instance;

if ( empty( $instance ) ) {
$instance = new BP_Docs_Access_Query( $user_id );
if ( empty( $instance[$user_id] ) ) {
$instance[$user_id] = new BP_Docs_Access_Query( $user_id );
}

return $instance;
return $instance[$user_id];
}

public function __construct( $user_id = 0 ) {
$this->user_id = intval( $user_id );
$this->set_up_levels();
$this->prepare_tax_query();
$this->prepare_comment_tax_query();
}

protected function set_up_levels() {
// Everyone can see 'anyone' docs
$this->levels[] = bp_docs_get_access_term_anyone();
$this->comment_levels[] = bp_docs_get_comment_access_term_anyone();

// Logged-in users
// Note that we're not verifying that the user actually exists
// For now this kind of check is up to whoever's instantiating
if ( $this->user_id != 0 ) {
$this->levels[] = bp_docs_get_access_term_loggedin();
$this->comment_levels[] = bp_docs_get_comment_access_term_loggedin();

if ( bp_is_active('groups') ) {

Expand All @@ -39,13 +44,15 @@ protected function set_up_levels() {
if ( isset($this->user_groups['groups']) ) {
foreach ( $this->user_groups['groups'] as $member_group ) {
$this->levels[] = bp_docs_get_access_term_group_member( $member_group );
$this->comment_levels[] = bp_docs_get_comment_access_term_group_member( $member_group );
}
}

// admins-mods
if ( isset($this->user_groups['admin_mod_of']) ) {
foreach ( $this->user_groups['admin_mod_of'] as $adminmod_group ) {
$this->levels[] = bp_docs_get_access_term_group_adminmod( $adminmod_group );
$this->comment_levels[] = bp_docs_get_comment_access_term_group_adminmod( $adminmod_group );
}
}
}
Expand All @@ -54,6 +61,7 @@ protected function set_up_levels() {
// creator
// @todo What's the difference?
$this->levels[] = bp_docs_get_access_term_user( $this->user_id );
$this->comment_levels[] = bp_docs_get_comment_access_term_user( $this->user_id );
}
}

Expand All @@ -66,6 +74,15 @@ protected function prepare_tax_query() {
);
}

protected function prepare_comment_tax_query() {
$this->comment_tax_query[] = array(
'terms' => $this->comment_levels,
'taxonomy' => bp_docs_get_comment_access_tax_name(),
'field' => 'slug',
'operator' => 'IN',
);
}

/**
* Get a list of a user's groups, as well as those groups of which
* the user is an admin or mod
Expand Down Expand Up @@ -96,39 +113,182 @@ public function get_tax_query() {
return $this->tax_query;
}


/**
* Returns the tax_query param for the WP_Query args
*
* @since 2.0
* @return array
*/
public function get_comment_tax_query() {
// bp_moderate users can see anything, so no query needed
if ( user_can( $this->user_id, 'bp_moderate' ) ) {
return array();
}

return $this->comment_tax_query;
}

/**
* Fetch a list of Doc IDs that are forbidden for the user
*
* @since 1.2.8
*/
public function get_doc_ids() {
remove_action( 'pre_get_posts', 'bp_docs_general_access_protection', 28 );
// Check the cache first.
$last_changed = wp_cache_get( 'last_changed', 'bp_docs_nonpersistent' );
if ( false === $last_changed ) {
$last_changed = microtime();
wp_cache_set( 'last_changed', $last_changed, 'bp_docs_nonpersistent' );
}

$cache_key = 'bp_docs_forbidden_docs_for_user_' . $this->user_id . '_' . $last_changed;
$cached = wp_cache_get( $cache_key, 'bp_docs_nonpersistent' );
if ( false !== $cached ) {
return $cached;
} else {
remove_action( 'pre_get_posts', 'bp_docs_general_access_protection', 28 );

$tax_query = $this->get_tax_query();
foreach ( $tax_query as &$tq ) {
$tq['operator'] = "NOT IN";
}

// If the tax_query is empty, no docs are forbidden
if ( empty( $tax_query ) ) {
$protected_doc_ids = array( 0 );
} else {
$forbidden_fruit = new WP_Query( array(
'post_type' => bp_docs_get_post_type_name(),
'posts_per_page' => -1,
'nopaging' => true,
'tax_query' => $tax_query,
'update_post_term_cache' => false,
'update_post_meta_cache' => false,
'no_found_rows' => 1,
'fields' => 'ids',
) );
if ( $forbidden_fruit->posts ) {
$protected_doc_ids = $forbidden_fruit->posts;
} else {
/*
* If no results are returned, we save a 0 value to avoid the
* post__in => array() fetches everything problem.
*/
$protected_doc_ids = array( 0 );
}
}

add_action( 'pre_get_posts', 'bp_docs_general_access_protection', 28 );

// Set the cache to avoid duplicate requests.
wp_cache_set( $cache_key, $protected_doc_ids, 'bp_docs_nonpersistent' );

return $protected_doc_ids;
}
}

/**
* Fetch a list of Doc IDs whose comments the user cannot read.
*
* @since 1.2.8
*/
public function get_restricted_comment_doc_ids() {
// Check the cache first.
$last_changed = wp_cache_get( 'last_changed', 'bp_docs_nonpersistent' );
if ( false === $last_changed ) {
$last_changed = microtime();
wp_cache_set( 'last_changed', $last_changed, 'bp_docs_nonpersistent' );
}

$cache_key = 'bp_docs_forbidden_comment_docs_for_user_' . $this->user_id . '_' . $last_changed;
$cached = wp_cache_get( $cache_key, 'bp_docs_nonpersistent' );
if ( false !== $cached ) {
return $cached;
} else {
remove_action( 'pre_get_posts', 'bp_docs_general_access_protection', 28 );

$tax_query = $this->get_comment_tax_query();
foreach ( $tax_query as &$tq ) {
$tq['operator'] = "NOT IN";
}

// If the tax_query is empty, no docs are forbidden
if ( empty( $tax_query ) ) {
$restricted_comment_doc_ids = array( 0 );
} else {
$forbidden_fruit = new WP_Query( array(
'post_type' => bp_docs_get_post_type_name(),
'posts_per_page' => -1,
'nopaging' => true,
'tax_query' => $tax_query,
'update_post_term_cache' => false,
'update_post_meta_cache' => false,
'no_found_rows' => 1,
'fields' => 'ids',
) );
if ( $forbidden_fruit->posts ) {
$restricted_comment_doc_ids = $forbidden_fruit->posts;
} else {
/*
* If no results are returned, we save a 0 value to avoid the
* post__in => array() fetches everything problem.
*/
$restricted_comment_doc_ids = array( 0 );
}
}

add_action( 'pre_get_posts', 'bp_docs_general_access_protection', 28 );

$tax_query = $this->get_tax_query();
foreach ( $tax_query as &$tq ) {
$tq['operator'] = "NOT IN";
// Set the cache to avoid duplicate requests.
wp_cache_set( $cache_key, $restricted_comment_doc_ids, 'bp_docs_nonpersistent' );

return $restricted_comment_doc_ids;
}
}

/**
* Fetch a list of Comment IDs that are forbidden for the user
*
* @since 2.0
*/
public function get_comment_ids() {
/*
* Check the cache first.
* WordPress caches the 'last_changed' comment time, so let's use that.
*/
$last_changed = wp_cache_get( 'last_changed', 'comment' );
if ( false === $last_changed ) {
$last_changed = microtime();
wp_cache_set( 'last_changed', $last_changed, 'comment' );
}

// If the tax_query is empty, no docs are forbidden
if ( empty( $tax_query ) ) {
$forbidden_fruit_ids = array();
$cache_key = 'bp_docs_forbidden_comments_for_user_' . $this->user_id . '_' . $last_changed;
$cached = wp_cache_get( $cache_key, 'bp_docs_nonpersistent' );
if ( false !== $cached ) {
return $cached;
} else {
$forbidden_fruit = new WP_Query( array(
'post_type' => bp_docs_get_post_type_name(),
'posts_per_page' => -1,
'nopaging' => true,
'tax_query' => $tax_query,
'update_post_term_cache' => false,
'update_post_meta_cache' => false,
'no_found_rows' => 1,
remove_action( 'pre_get_comments', 'bp_docs_general_comment_protection' );

$protected_comment_ids = get_comments( array(
'post__in' => $this->get_restricted_comment_doc_ids(),
'fields' => 'ids',
) );
$forbidden_fruit_ids = $forbidden_fruit->posts;
}
if ( ! $protected_comment_ids ) {
/*
* If no results are returned, we save a 0 value to avoid the
* post__in => array() fetches everything problem.
*/
$protected_comment_ids = array( 0 );
}

add_action( 'pre_get_posts', 'bp_docs_general_access_protection', 28 );
add_action( 'pre_get_comments', 'bp_docs_general_comment_protection' );

return $forbidden_fruit_ids;
// Set the cache to avoid duplicate requests.
wp_cache_set( $cache_key, $protected_comment_ids, 'bp_docs_nonpersistent' );

return $protected_comment_ids;
}
}
}

Expand Down Expand Up @@ -199,3 +359,56 @@ function bp_docs_general_access_protection( $query ) {
// Hooked at an oddball priority to avoid conflicts with nested actions and
// other plugins using 'pre_get_posts'. See https://github.com/boonebgorges/buddypress-docs/issues/425
add_action( 'pre_get_posts', 'bp_docs_general_access_protection', 28 );

/**
* Keep comments that the user shouldn't see out of primary WP_Comment_Query queries.
*
* By catching the query at pre_get_comments, we ensure that all queries are
* filtered appropriately.
*
* @since 2.0
*/
function bp_docs_general_comment_protection( $query ) {

// Access is unlimited when the current user is a site admin.
if ( current_user_can( 'bp_moderate' ) ) {
return;
}

// Since we're using post__not_in, we have to be aware of post__in requests.
$bp_docs_access_query = bp_docs_access_query();
$restricted_comment_doc_ids = $bp_docs_access_query->get_restricted_comment_doc_ids();

if ( $query->query_vars['post_id'] || $query->query_vars['post__in'] ) {
// Is this a request for the comments of a specific post?
if ( $query->query_vars['post_id'] ) {
if ( in_array( $query->query_vars['post_id'] , $restricted_comment_doc_ids ) ) {
$query->query_vars['post_id'] = 0;
}
}

// Is this a request for the comments of a group of posts?
if ( $query->query_vars['post__in'] ) {
$allowed_posts = array_diff( $query->query_vars['post__in'], $restricted_comment_doc_ids );
$query->query_vars['post__in'] = $allowed_posts;
}
} else {
// Other situations where the parent posts aren't specified.
$query->query_vars['post__not_in'] = $restricted_comment_doc_ids;
}
}
add_action( 'pre_get_comments', 'bp_docs_general_comment_protection' );

/**
* Reset the 'last_changed' cache incrementor when posts are updated.
*
* Big hammer, small nail.
*
* @since 2.0.0
*/
function bp_docs_cache_invalidate_last_changed_incrementor() {
wp_cache_delete( 'last_changed', 'bp_docs_nonpersistent' );
}
add_action( 'save_post_bp_doc', 'bp_docs_cache_invalidate_last_changed_incrementor' );
add_action( 'trashed_post', 'bp_docs_cache_invalidate_last_changed_incrementor' );
add_action( 'set_object_terms', 'bp_docs_cache_invalidate_last_changed_incrementor' );
Loading