Allow users to manage only comments on their own posts - php

I want to restrict contributer and author users to seeing and manageing comments only on their own posts.
I have tried the following filter with no success.
//Manage Your Own Comments Only
function myplugin_comments_thisuseronly( $wp_query ) {
if ( strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/edit-comments.php' ) !== false ) {
if ( !current_user_can( 'edit_others_posts' ) ) {
global $current_user;global $wpdb;
$usersposts = $wpdb->get_results( $wpdb->prepare("SELECT ID FROM wp_posts WHERE post_author = %s", $current_user->id) );
$wp_query->set('comment_post_ID', array($usersposts));
}
}
}
add_filter('parse_query', 'myplugin_comments_thisuseronly' );
I also tried
$wp_query->set('comment_post_ID__in', array($usersposts));

Ok, I figured this out.
First, the user needs to have a role with permission to edit published posts AND to moderate comments. The latter is not standard for authors/contributors.
Then, by filtering the query which gets the comments (using comments_clauses) and adding a join you can show only comments for posts by the currently logged in user.
function my_plugin_get_comment_list_by_user($clauses) {
if (is_admin()) {
global $user_ID, $wpdb;
$clauses['join'] = ", wp_posts";
$clauses['where'] .= " AND wp_posts.post_author = ".$user_ID." AND wp_comments.comment_post_ID = wp_posts.ID";
};
return $clauses;
};
// Ensure that editors and admins can moderate all comments
if(!current_user_can('edit_others_posts')) {
add_filter('comments_clauses', 'my_plugin_get_comment_list_by_user');
}
Works perfectly. The changes to roles may not suit every setup, but as it happens it does work for me on this site.

Related

How to let users post only once for custom post type (php / wordpress)?

I need to let users only post once for custom post 'projects'.
The code below counts the number of the post:
$userid = get_current_user_id();
function count_user_posts_by_type($userid, $post_type = 'projects', $post_status = 'publish') {
global $wpdb;
$query = "SELECT COUNT(*) FROM $wpdb->posts WHERE post_author = $userid AND post_type = '$post_type' AND post_status = '$post_status'";
$count = $wpdb->get_var($query);
return apply_filters('get_usernumposts', $count, $userid);
}
And shows correct number with
<?php echo count_user_posts_by_type($userid); ?>
My question:
I need to combine it with add_action.
So that when the result is 0 the user can post, when the result is !=0 the user cannot post.
The code below is something that I want to implement but it doesn't work at all and I have no idea how to combine together.
Would you please let me know how to combine codes together?
add_action( 'count-user-posts-by-type', 'count_user_posts_by_type' );
$postcount = count_user_posts_by_type($userid);
if($postcount != 0){
return ( 'www.mywebsite.com/cannot-post/' );
} else{
return ( 'www.mywebsite.com/can-post/' );
}
}
Thank you.
You can use is_user_logged_in() to check whether the current user is logged in or not.
Then you can use the template_redirect hook to perform the check :
function only_post_once_redirect()
{
if( is_user_logged_in() ) {
$userid = get_current_user_id(); //-- get the user id
$postcount = count_user_posts_by_type( $userid ); //-- get the count
if( $postcount != 0 ){ //-- not equal to zero
wp_redirect( home_url( 'www.mywebsite.com/cannot-post/' ) );
die;
} else{ //-- equal to zero
wp_redirect( home_url( 'www.mywebsite.com/can-post/' ) );
die;
}
}
}
add_action( 'template_redirect', 'only_post_once_redirect' );
You may need to add some more login to it, say to check which the user is now or something like that.
Or if you want this check & redirect to happen just after the login, you could try the login_redirect hook.
EDIT
I believe you have to spend some time polishing your PHP skills. Look for some basic PHP tutorials like this. You will recall everything after you spend an hour or two in those tutorials.
To answer your question(which you asked in comments), you can simply pass the second parameter as string. No need of that $post_type = part in it. Only in function definition (ie, when you define how the function should perform), you write the default values. When you make function calls, you simply pass the values as parameter. No need of the assignments in the parameters.
In short, your function call should be like this:
$postcount = count_user_posts_by_type( $userid2, 'projects' );
Since you've already mentioned the default value of the second parameter to be projects in your function definition, you can simply use this:
$postcount = count_user_posts_by_type( $userid2 );
I solved the problem using different code, in case someone needs it :
add_shortcode( 'current-user-has-posts' , 'current_user_has_posts' );
function current_user_has_posts(){
$args = array(
'post_type' => 'projects',
'author' => get_current_user_id(),
);
$wp_posts = get_posts($args);
if (count($wp_posts)) {
return ( 'www.mywebsite.com/cannot-post/' );
} else {
return ( 'www.mywebsite.com/can-post/' );
}
}

wordpress show media files for user

I would like to present the user only his media files but only if he is in a custom group (Teachers). If he is Author or above he can see all media files.
e.g. I have a user Teacher 1 and he is in group Author and Teachers.
User Accountant is in group Author.
Teacher can see only his files, Accountant can see all files.
I tried the following funcition
function wpb_show_current_user_attachments( $query ) {
$user_id = get_current_user_id();
if ( $user_id && !current_user_can('activate_plugins') && !current_user_can('edit_others_posts') ) {
/* $query['author'] = $user_id;*/
$query['Teacher'] = $user_id;
}
return $query;
}
add_filter( 'ajax_query_attachments_args', 'wpb_show_current_user_attachments' );
Thank you

Can I create a function for auto-enrolling WP Roles in a Learndash course?

Currently, LearnDash has a function (to be added to functions.php) that allows you to auto enroll a specific user in a course. I was wondering if a simple function could be added to my theme's function file and change this from user_id to a user ROLE? That way every user in that role is enrolled.
Here is the starting point: (found in the dev section on Learndash)
//* To enroll user to course:
ld_update_course_access($user_id, $course_id, $remove = false);
I have tried this:
//* Add users to course by role
ld_update_course_access($role_name = Subscriber, $course_id = 949, $remove = false);
On the "edit course" page editor I now see "1,0,12,Subscriber" inside the "course access list" but it doesn't actually work. Obviously, that access list is working with users only.
My thought process is creating a function that will:
1) Get user IDs from user role "My-Custom-Role"
2) Return IDs and update course access.
Is something like this possible?
Yep, totally possible. The get_users() function allows you to get a list of users by role. See: https://codex.wordpress.org/Function_Reference/get_users
For example:
$users = get_users( [ 'role__in' => [ 'subscriber', 'author' ] ] );
foreach ( $users as $user ) {
ld_update_course_access( $user->ID, 949, false );
}
I worked with the development team and came up with a different although incomplete solution, so I've marked Linnea's as correct, because it works as asked in the question. This solution goes through their access hook sfwd_lms_has_access, however the "course list" never gets updated so a user is not officially "enrolled" until they start the course. By this I mean, you wont see them enrolled in the course on their profile, but if they start a lesson, it all of a sudden shows up! Thought it might help to post here in case it may help anyone as a starting point.
add_filter( 'sfwd_lms_has_access', function( $return, $post_id, $user_id ) {
if ( empty( $user_id ) ) {
$user_id = get_current_user_id();
}
if(empty($user_id))
return $return;
$course_id = learndash_get_course_id( $post_id );
$allowed_course_ids = array( 949, 1135 );
if( !in_array($course_id, $allowed_course_ids))
return $return;
if(user_can($user_id, "3a_textbook"))
return true;
if(user_can($user_id, "subscriber"))
return true;
return $return;
}, 10, 3 );

Need some PHP help for making a change to wordpress plugin Groups

I'm really in a jam here. I am extremely close to launching my wordpress site. I have one rather large obstacle in my way that should be an easy fix. I am beginner level php so I am really struggling on this and any help or direction would be extremely appreciated since I have been trying to solve this issue for two weeks through reading and research.
Here is the issue and I will try to be as detailed as possible:
I have a custom post type called Portfolio.
I have a Portfolio page where it loads all of the featured images of
the Portfolio Posts into a grid on the Portfolio Page. You know a
basic portfolio setup where if you click the image it takes you to
the portfolio post.
Using the Groups plugin, when I restrict access to a Portfolio Post,
it removes the featured image from the Portfolio Page grid. Like the
post doesn't exist for non group members.
I am trying to sell access to these Portfolio Posts so if someone is
not a member they will not know there is anything there to buy.
I don't know how to make it to where those featured images still show on the Portfolio Page. I need people to know they are there but not be able to access them. As I mentioned in the support question, I cannot use a shortcode for this because the video is hard coded in to my theme. I need to add it to the code in a custom plugin to change groups to not remove that featured image from my portfolio page regardless of the restriction on the post.
I have gone through the API and found the section that controls access to the restricted posts. The Class is Groups-Post-Access. When both of these are removed from the class-groups-access.php I am able to see the featured images on the Portfolio page but it also removes the function that restricts the actual post. I don't know how I could tell the plugin to only return the featured image but still hide access to the post.
add_filter( 'posts_where', array( __CLASS__, 'posts_where' ), 10, 2 );
/**
* Filters out posts that the user should not be able to access.
*
* #param string $where current where conditions
* #param WP_Query $query current query
* #return string modified $where
*/
public static function posts_where( $where, &$query ) {
global $wpdb;
$user_id = get_current_user_id();
// this only applies to logged in users
if ( $user_id ) {
// if administrators can override access, don't filter
if ( get_option( GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE, GROUPS_ADMINISTRATOR_ACCESS_OVERRIDE_DEFAULT ) ) {
if ( user_can( $user_id, 'administrator' ) ) {
return $where;
}
}
}
// 1. Get all the capabilities that the user has, including those that are inherited:
$caps = array();
if ( $user = new Groups_User( $user_id ) ) {
$capabilities = $user->capabilities_deep;
if ( is_array( $capabilities ) ) {
foreach ( $capabilities as $capability ) {
$caps[] = "'". $capability . "'";
}
}
}
if ( count( $caps ) > 0 ) {
$caps = implode( ',', $caps );
} else {
$caps = '\'\'';
}
// 2. Filter the posts that require a capability that the user doesn't
// have, or in other words: exclude posts that the user must NOT access:
// The following is not correct in that it requires the user to have ALL capabilities:
// $where .= sprintf(
// " AND {$wpdb->posts}.ID NOT IN (SELECT DISTINCT ID FROM $wpdb->posts LEFT JOIN $wpdb->postmeta on {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id WHERE {$wpdb->postmeta}.meta_key = '%s' AND {$wpdb->postmeta}.meta_value NOT IN (%s) ) ",
// self::POSTMETA_PREFIX . self::READ_POST_CAPABILITY,
// $caps
// );
// This allows the user to access posts where the posts are not restricted or where
// the user has ANY of the capabilities:
$where .= sprintf(
" AND {$wpdb->posts}.ID IN " .
" ( " .
" SELECT ID FROM $wpdb->posts WHERE ID NOT IN ( SELECT post_id FROM $wpdb->postmeta WHERE {$wpdb->postmeta}.meta_key = '%s' ) " . // posts without access restriction
" UNION ALL " . // we don't care about duplicates here, just make it quick
" SELECT post_id AS ID FROM $wpdb->postmeta WHERE {$wpdb->postmeta}.meta_key = '%s' AND {$wpdb->postmeta}.meta_value IN (%s) " . // posts that require any capability the user has
" ) ",
self::POSTMETA_PREFIX . self::READ_POST_CAPABILITY,
self::POSTMETA_PREFIX . self::READ_POST_CAPABILITY,
$caps
);
return $where;
}
add_filter( 'the_posts', array( __CLASS__, "the_posts" ), 1, 2 );
/**
* Filter posts by access capability.
*
* #param array $posts list of posts
* #param WP_Query $query
*/
public static function the_posts( $posts, &$query ) {
$result = array();
$user_id = get_current_user_id();
foreach ( $posts as $post ) {
if ( self::user_can_read_post( $post->ID, $user_id ) ) {
$result[] = $post;
}
}
return $result;
}
If someone can give me a better understanding of what is happening here and maybe an example of what he is referring to by creating a template for my custom post type, I would really appreciate it. Thank you so much for your time!
This was solved by using wordpress to handle hiding a specific category vs changing the actual plugin code.

Check if user is in a group on the main site FROM a subsite of a network (WP Multisite)

I'm using Woocommerce + the groups plugin on my main site to promote users to a 'Premium' group upon purchasing items which works great.
If a user on the main site then browses to the second site within my network, I can no longer check to see if they're within the 'Premium' group.
On my main site, I can use this code:
<?php
$user_id = get_current_user_id();
$group = Groups_Group::read_by_name( 'Premium' );
if ( Groups_User_Group::read( $user_id, $group->group_id ) ) {
?>
Premium content here!
<?php } ?>
But this does not work on the subsite. Is there anyway I can check to see if the user is in a group on my main site FROM a subsite?
I managed to achieve this using the following code:
<?php
$blog_id = 1; //set the blog id to the main site id
switch_to_blog( $blog_id );
$user_id = get_current_user_id();
$group = Groups_Group::read_by_name( 'Premium' );
if ( Groups_User_Group::read( $user_id, $group->group_id ) ) {
echo 'PREMIUM!!';
} else {
echo 'Not premium';
}
restore_current_blog();
?>
Probably not a definitive answer but this should lead to it at least.
Your current code is using a wordpress function to get the users id. This should work across the board and is therefore fine. The next variabe/method uses the class from the groups plugin which I presume is just not being pulled on the subsite.
$user_id = get_current_user_id();
$group = Groups_Group::read_by_name( 'Premium' );
Groups_User_Group::read( $user_id, $group->group_id )
From the look of the class files
$group = Groups_Group::read_by_name( 'Premium' );
This line simply does the method below
public static function read_by_name( $name ) {
global $wpdb;
$result = false;
$group_table = _groups_get_tablename( 'group' );
$group = $wpdb->get_row( $wpdb->prepare(
"SELECT * FROM $group_table WHERE name = %s",
$name
) );
if ( isset( $group->group_id ) ) {
$result = $group;
}
return $result;
}
The next line
Groups_User_Group::read( $user_id, $group->group_id )
Does this method
public static function read( $user_id, $group_id ) {
global $wpdb;
$result = false;
$user_group_table = _groups_get_tablename( 'user_group' );
$user_group = $wpdb->get_row( $wpdb->prepare(
"SELECT * FROM $user_group_table WHERE user_id = %d AND group_id = %d",
Groups_Utility::id( $user_id ),
Groups_Utility::id( $group_id )
) );
if ( $user_group !== null ) {
$result = $user_group;
}
return $result;
}
So all you are doing is pretty simple calls to the database. The issue being that due to the use of multisite there will be discrepancies with the table prefixes etc.
According to this part of the codex
http://codex.wordpress.org/Class_Reference/wpdb#Multi-Site_Variables
You can access other sites on the network much in the same way you can access the current site using $wpdb as a global variable. Therefore once you have ascertained the correct names of your tables, you should be able to modify these methods into simple functions that do the necessary work.
The first method doesn't even need to be used
$group = Groups_Group::read_by_name( 'Premium' );
As $group simply equals the id shown in the dashboard
Therefore the line can be coded statically ie
$group = 2;
The second method is purely checking if there is an entry of user_id 2 for example and group_id 2 say, in the group_users_group table. Here we have user 2 with both registered and premium group privileges. Shown here.
Therefore user 2 (again id can be seen in the dashboard in the users section) will qualify.
I hope this helps.

Categories