To resolve stupidity with a 3rd-party plugin, I had to give subscriber level users some edit capabilities that I don't want them to actually have. (This does not give them access to edit links, but they could access the edit URL directly if they were clever.) Since my site has only subscriber and administrative users, I can solve the problem by simply amending the capability check in wp-admin/post.php to require an additional capability that subscribers don't have, like so:
if ( ! current_user_can( 'edit_post', $post_id ))
wp_die( __( 'Sorry, you are not allowed to edit this item.' ) );
Becomes:
if ( ! current_user_can( 'edit_post', $post_id ) OR ! current_user_can('edit_pages'))
wp_die( __( 'Sorry, you are not allowed to edit this item.' ) );
This works perfectly, but I know that it will be overwritten and need to be re-done every time Wordpress updates. Is there a way to apply this fix in a more permanent manner via a filter or similar?
You don't need to modify post.php file. Use this code in your functions.php:
add_filter('user_has_cap',function($allcaps,$need_caps, $args) {
if ($_SERVER['SCRIPT_NAME']=='/wp-admin/post.php' && isset($_GET['action']) && $_GET['action']=='edit' && $args[0]=='edit_post' && ! current_user_can('edit_pages')) {
foreach ($need_caps as $cap) {
unset($allcaps[$cap]);
}
}
return $allcaps;
},10,3);
The above comment works.... and so does this, just add either to your functions file.
function authority_check(){
global $pagenow;
if(is_admin() && !current_user_can('manage-capabilities')){
if(in_array($pagenow,array('post.php')) || in_array($pagenow, array('post-new.php'))){
wp_die(__( 'Sorry, you are not allowed to edit this item.'));
}
}
}
add_action('admin_init', 'authority_check');
Related
I've managed to find the below snippet which hides all posts excepts the ones made by the current user when added to functions.php
However, I want to make this also allow posts from a specific user ID, particularly the admin posts in order to enable the normal Blog to be visible. I'm not sure how I can achieve that.
P.S. I have zero programming knowledge and while I can kind of get what this does I'm unable to expand it since I don't know the proper formatting...
add_action('pre_get_posts', 'wptw_query_disable_post_media' );
function wptw_query_disable_post_media( $wp_query ) {
global $current_user;
if( is_admin() && !current_user_can('edit_others_posts') ) {
$wp_query->set( 'author', $current_user->ID );
add_filter('views_edit-post', 'wptw_show_post_counts');
add_filter('views_upload', 'wptw_show_media_counts');
}
}
Well, I did the most basic thing possible. Just duplicated the code above, renaming the function and replacing "$current_user->ID" with just the ID of the user I wanted (in this case 12.) So the code for including one more user's posts looks like this:
add_action('pre_get_posts', 'show_admin_posts' );
function show_admin_posts( $wp_query ) {
global $current_user;
if( is_admin() && !current_user_can('edit_others_posts') ) {
$wp_query->set( 'author', 12);
}
}
I have different users registered on my WordPress website with different roles. Apart from the rest of users, I want to allow advertisers (users with advertiser role - advertiser is a custom role that I have created) to place their own products on my site and also manage them. But they need to be limited only to manage (create, edit and delete) their own products, not of others.
So far, I have tried the following code but it seems to be not valid. I am sure I can accomplish my goal using pre_get_posts action and the following function can help me but I need some help in resolving the issues with this code. I am not sure about the post type of products.
Here is the code that I am trying to accomplish my goal with:
function show_specific_advertiser_products( $query ) {
$current_user = wp_get_current_user();
if ( is_admin() && in_array ($query->get( 'post_type'), array( 'woocommerce_products' ) ) && !user_can( $current_user, 'administrator' ) ) {
$query->set( 'author__in', $current_user->ID );
}
}
add_action( 'pre_get_posts', 'show_specific_advertiser_products' );
Any help will highly be appreciated.
The error in your code comes from the post_type… for woocommerce products it's simply product. You will have to replace administrator by your custom user role.
So try the following instead:
add_action( 'pre_get_posts', 'show_specific_advertiser_products' );
function show_specific_advertiser_products( $query ) {
$user = wp_get_current_user();
if ( is_admin() && $query->get( 'post_type') === 'product' && in_array('administrator', $user->roles) ) {
$query->set( 'author', $user->ID );
}
}
Code goes in function.php file of your active child theme (or active theme). It should works.
I've made a function to hide the Mine filter in the screen wp-admin/edit.php, using unset:
But when I click in the Posts menu (wp-admin/edit.php), it will not go to All by default, it still goes to Mine filter.
How to make the default to be All?
We can intercept what page we arrived at the very beginning of the load process (with load-(page)) and check if redirection is needed. See comments for logic.
add_action( 'load-edit.php', function()
{
global $typenow;
// Not our post type, bail out
if( 'post' !== $typenow )
return;
// Administrator users don't need this, bail out
if( current_user_can('add_users') )
return;
// Only the Mine tab fills this conditions, redirect
if( !isset( $_GET['post_status'] ) && !isset( $_GET['all_posts'] ) )
{
wp_redirect( admin_url('edit.php?all_posts=1') );
exit();
}
});
I'm building a fairly complex project that has many frontend editing pages. For example, add/edit/list custom post types, edit profile, and so on, all from the frontend.
At the moment I can of course check if user is logged in on each frontend login-walled page. However, this seems like a bad way of solving this problem as I'll have the same conditional on many pages and thus lots of repeated code.
I was thinking perhaps there is a better way where I could authenticate based on some hook (that I can't finds). I hoped I could do something like:
# create array of URLs where login is required
$needLoginArr = array(url1, url2, url3, ...)
# If current requested URL is in above array, then redirect or show different view based on whether or not user is logged in
It might not be practical in future to have conditional on each page as I plan on integrating within different plugins, so would be useful to use URL to authenticate.
I'm probably missing something here so if there's a better way please let me know.
Thanks
You could add your list of page IDs into an option:
$need_login = array(
'page1',
'page1/subpage',
'page2',
// and so forth
);
$need_login_ids = array();
foreach( $need_login as $p ) {
$pg = get_page_by_path( $p );
$need_login_ids[] = $pg->ID;
}
update_option( 'xyz_need_login', $need_login_ids );
Then, to check if your page is in the $need_login group:
add_filter( 'the_content', 'so20221037_authenticate' );
function so20221037_authenticate( $content ) {
global $post;
$need_login_ids = get_option( 'xyz_need_login' );
if( is_array( $need_login_ids ) && in_array( $post->ID, $need_login_ids ) ) {
if( is_user_logged_in() ) {
// alter the content as needs
$content = 'Stuff for logged-in users' . $content;
}
}
return $content;
}
References
get_page_by_path()
is_user_logged_in()
update_option()
get_option()
I have added a few custom roles to my blog. They work fine and the capabilities are as I have specified. The thing is that every user has a list of 'all' the posts in his posts window. He can only edit his own posts but does see posts written by other users.
How can I add a restriction to the role (or any different way) to make sure a user only sees his own posts?
Try pasting this into your functions.php file. Anywhere, likely at the bottom away from other functions. This should restrict user's from seeing posts that don't belong to them.
I hope this works for you! :)
function posts_for_current_author($query) {
global $pagenow;
if( 'edit.php' != $pagenow || !$query->is_admin )
return $query;
if( !current_user_can( 'manage_options' ) ) {
global $user_ID;
$query->set('author', $user_ID );
}
return $query;
}
add_filter('pre_get_posts', 'posts_for_current_author');