I want to show the admin bar on my single.php page ONLY when the actual author of the post is on the page.
I took this article as a reference and was able to make the admin bar visible on single.php pages only, but I also want to add a condition to hide it to non-author viewers.
https://second-cup-of-coffee.com/hiding-the-wordpress-admin-bar-on-certain-pages/
And this is the code I tried on my functions.php:
function my_theme_hide_admin_bar($bool) {
$logged_in_user = wp_get_current_user();
$logged_in_user_id = $logged_in_user->ID;
if ( ! is_single() && $logged_in_user_id !== get_the_author_meta('ID') ) :
return false;
else :
return $bool;
endif;
}
add_filter('show_admin_bar', 'my_theme_hide_admin_bar');
However, the admin bar still shows when I view a post from another author.
You've got to compare the two ID's, the one from the post author and the one from the current user. We also want to make sure that the user is an actual author for redundancy.
Function
Description
get_post_field( 'post_author' )
Retrieve data from a post field based on Post ID.
get_current_user_id()
Get the current user’s ID.
current_user_can( 'author' )
Returns whether the current user has the specified capability.
<?php
add_filter( 'show_admin_bar', function( $show ) {
if( is_single() && current_user_can( 'author' ) && get_post_field( 'post_author' ) == get_current_user_id() ) {
return $show;
} else {
return;
};
} ); ?>
EDIT:
While checking against particular roles in place of a capability is supported in part, this practice is discouraged as it may produce unreliable results.
Source # https://developer.wordpress.org/reference/functions/current_user_can/#description
Having that in mind using current_user_can( 'author' ) isn't considered best practice. Instead an actual capability handle should be used. You can refer to the Roles and Capabilities page for a complete list of users and capabilities.
I decided to use the export capability, but you can use anything from Capability vs. Role Table.
<?php
add_filter( 'show_admin_bar', function( $show ) {
if( is_single() && current_user_can( 'export' ) && get_post_field( 'post_author' ) == get_current_user_id() ) {
return $show;
} else {
return;
};
} ); ?>
Special thanks to #Xhynk in the comments for the tips and the optimization.
Related
I would like:
http://www.gadgetgogo.co.uk/?s=ipod
to return as:
http://www.gadgetgogo.co.uk/?s=ipod&post_type=product
So when using searches (slider banner and default WordPress search) it produces the second URL.
I was looking for similar solution as you but couldn't find any and at last I combined last few answers that I read here and got this working fine as I wanted.
Add below code in your theme's functions.php file
function wpb_change_search_url() {
if ( is_search() && ! empty( $_GET['s'] ) && ($_GET['post_type'] != 'product') ) {
wp_redirect( home_url( "/?s=" ) . urlencode( get_query_var( 's' ) ) . "&post_type=product" );
exit();
}
}
add_action( 'template_redirect', 'wpb_change_search_url' );
hope it will help you and others.
Apparently current WooCommerce versions only consider a search query a product search (and render using the appropriate template), if $query->is_post_type_archive( 'product' ) is true, so the key is to set not only the post_type, but the is_post_type_archive property as well, and to do it before WooCommerce loads its filter (default priority of 10), so with a priority of 9 or smaller.
Example to add into funtions.php:
function my_search_filter($query) {
if ( $query->is_search && ! is_admin() ) {
$query->set( 'post_type', 'product' );
$query->is_post_type_archive = true;
}
}
add_filter('pre_get_posts','my_search_filter', 9);
Please note, that this code will override all searches as product serach, so if you have other searches as well, implement appropriate checks at the begining of my_search_filter.
Just add this line to top of search.php
$_GET['post_type'] = 'product'
This can be done using pre_get_posts filter. Add below code in your theme's functions.php file
add_filter( 'pre_get_posts', 'search_by_product_only' );
function search_by_product_only( $query ) {
// check if search query only
if ( $query->is_search ) {
$query->set( 'post_type', array( 'product') ); // here you can add multiple post types in whcih you want to search
}
return $query;
}
I'm trying to edit a field in the meta data of a post before it is being displayed on the screen.
I have been looking at the 'load-post.php' hook, but this is called before the post is loaded (if I've understood that correctly), so the post id and meta data are null.
I've tried other hooks, but I haven't been able to make this work.
The following post meta field needs to be changed before it is displayed on the edit page.
$post_price = get_post_meta(get_the_ID(), 'price', TRUE);
Example: Price = 10 in the database, but I want it to be Price = 15 when it is displayed on the post edit page.
Any links, tips and ideas are much appreciated. :)
Edit:
My current solution:
add_action('load-post.php','calculate_price');
function calculate_price(){
$post_id = $_GET['post'];
//get price from post by post_id and do stuff
}
Is this the correct way?
The best hook I found is load-post.php using $current_screen.
For Woocommerce product, that works :
add_action('load-post.php', "calculate_price" );
function calculate_price( ){
global $current_screen;
if( is_admin() && $current_screen->post_type === 'product' ){
$post_id = (int) $_GET['post'];
$post = get_post( $post_id );
//Do something
}
}
EDIT: okay I thought you just need to work with ID of post. If you need to change post objects (already loaded from db and ready to be printed), you can use 'the_post' instead. Since you just need to access to post id, I would do something like this:
function my_the_post_action( $post ) {
$screen = get_current_screen();
if( is_admin() && $screen->parent_base == 'edit' && get_post_type() == 'product' ) {
$post_id = $post->ID;
$price = (int) get_post_meta( $post_id, 'price', true );
update_post_meta( $post_id, 'price', $price + 5 );
}
}
add_action( 'the_post', 'my_the_post_action' );
This part:
get_post_type() == 'product'
is not necessary, but you should determine for which kind of post (based on post type, category, metafield etc.) you want to run this piece of code. Without it will be executed everytime in admin query. This code is not tested, if something is wrong feel free to report.
How can I detect if the "myaccount/my-account.php" template is used on the Dashboard.
Currently I use:
<?php
global $wp;
if ( !isset($wp->query_vars['page']) ) {
?>
Back to my Account
<?php } ?>
<div class="myaccount_content">
<?php
do_action( 'woocommerce_account_content' );
?>
</div>
But that feels kind of hacky. Isn't there something like a is_myaccount_dashboard() function?
Update: Detecting specifically the My account "Dashboard" page
<?php
global $wp;
$request = explode( '/', $wp->request );
// If NOT in My account dashboard page
if( ! ( end($request) == 'my-account' && is_account_page() ) ){
?>
Back to my Account Dashboard
<?php
}
?>
<div class="myaccount_content">
<?php
do_action( 'woocommerce_account_content' );
?>
</div>
Tested and works.
Original answer:
Yes of course there is is_account_page() native WooCommerce conditional that returns true on the customer’s account pages.
Here is an example using is_account_page() and is_user_logged_in(). To get the my account link url you can use: get_permalink( get_option('woocommerce_myaccount_page_id') ).
if ( !is_account_page() ) { // User is NOT on my account pages
if ( is_user_logged_in() ) { // Logged in user
// Link to "My Account pages dashboard".
?>
<?php _e( 'My Account', 'woocommerce' ); ?>
<?php }
else { // User is NOT logged in
// Link to "Login / register page".
?>
<?php _e( 'Login / Register', 'woocommerce' ); ?>
<?php
}
}
?>
Reference:
Official WooCommerce Conditional Tags
Display My Account link in a template file
After that you can Override WooCommerce Templates via a Theme using my account templates to fine tune even more WooCommerce behaviors…
To detect the exact page you're in, within the My Account area, (to allow you to determine which template is being used), I don't think Woocommerce provides a way.
I think you'll have to get the current URL, with vanilla PHP, and compare it to the URL of the page that is set to be the Dashboard/My Account Home page.
e.g.
$current_url = (isset($_SERVER['HTTPS']) ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$dashboard_url = get_permalink( get_option('woocommerce_myaccount_page_id'));
if($dashboard_url == $current_url){
// do your stuff here
}
Woocommerce's is_account_page() conditional function will return true for ALL the My Account sub pages, so can't be used to determine if you're specifically on the Dashboard page.
I had the same question (years later, lol). For people looking at the answer and wondering why it isn't helpful there are endpoint detecting functions available in woocommerce that do exactly what you're looking for. You can read the list of functions available here.
This is taken directly from the woocommerce docs. I am just copying it just incase the link is broken in the future
is_account_page() =>
Returns true on the customer’s account pages.
is_wc_endpoint_url() =>
Returns true when viewing any WooCommerce endpoint
is_wc_endpoint_url( 'order-pay' ) =>
When the endpoint page for order pay is being displayed.
is_wc_endpoint_url( 'order-received' ) =>
When the endpoint page for order received is being displayed.
is_wc_endpoint_url( 'view-order' ) =>
When the endpoint page for view order is being displayed.
is_wc_endpoint_url( 'edit-account' ) =>
When the endpoint page for edit account is being displayed.
is_wc_endpoint_url( 'edit-address' ) =>
When the endpoint page for edit address is being displayed.
is_wc_endpoint_url( 'lost-password' ) =>
When the endpoint page for lost password is being displayed.
is_wc_endpoint_url( 'customer-logout' ) =>
When the endpoint page for customer logout is being displayed.
is_wc_endpoint_url( 'add-payment-method' ) =>
When the endpoint page for add payment method is being displayed.
Actually I found out this condition that seems to work fine in order to detect the WC Dashboard page with native WC code only:
if (is_user_logged_in() && is_account_page() && !is_wc_endpoint_url()) {
echo 'WC Dashboard';
} else {
echo 'no WC Dashboard';
}
<?php if(is_page("account") && !is_wc_endpoint_url()) { ?>
Assuming your account page is at /account/, this will detect your dashboard.
If you were to only do is_page("account"), the conditional would trigger for all account pages. However, because the dashboard isn't considered a WC endpoint like 'view-order' or 'last-password' is, this simple check will do the job.
I also needed to identify the dashboard specifically and found this question but I didn't like any of the answers and WooCommerce still has no built-in tag to do this...
I have 2 issues with the answers, the first is using is_wc_endpoint_url() (not infallible) and the second is comparing URLs (personal taste I guess?)
is_wc_endpoint_url() can return false for endpoints which are
added by a theme or plugin so you can get a false negative. There's
a filter so you can add your own but you can't trust that a plugin
will do that.
Comparing URLs feels hacky to me. You can probably get
trustworthy results and it's pretty straightforward, so it's not
necessarily a bad way to do it. Although I would forgo hardcoding parts of the URL(s) or at least allow for translating.
Now if you think about it, WooCommerce itself knows without fail when to load dashboard.php so I just took that code and refactored it to simply identify the dashboard:
function is_dashboard(){
global $wp;
if( ! empty( $wp->query_vars ) ){
foreach ( $wp->query_vars as $key => $value ) {
// Ignore pagename param.
if ( 'pagename' === $key ) {
continue;
}
if ( has_action( 'woocommerce_account_' . $key . '_endpoint' ) ) {
return false;
}
}
}
return true;
}
For me, this is the most foolproof way to do it, although if done correctly, comparing URLs might be sufficient. You just can't trust is_wc_endpoint_url() for this issue.
Hope this helps anyone still looking for an is_dashboard() or is_account_page('dashboard')
okay so I'm using the following code to show different content to users with different levels in WordPress
<?php global $user_ID; if( $user_ID ) : ?>
<?php if( current_user_can('level_10') ) : ?>
Admin
<?php else : ?>
FREE
<?php endif; ?>
<?php endif; ?>
How can I get different content to show for users with level 10, level 9, level 8, level 7 ect...
Thanks in advance
there are many ways to do level based filtering - and it depends on what you want to do exactly, but basically you just need simple conditionals ( if - else or if - then or switch statements ) again - depends on context.
if( current_user_can( 'level_10' ) ){
echo 'A - content for user level 10';
} elseif( current_user_can( 'level_8' ) ) {
echo 'B - content for user level 8 and above';
} elseif( current_user_can( 'level_6' ) ) {
echo 'C - content for user level 6 and above';
} // ok for wordpress < 3.0
/*
* Please read my note below regarding user levels to roles conversion
*/
if( current_user_can( 'manage_options' ) ){
echo 'A - content for user level Admin';
} elseif( current_user_can( 'publish_pages' ) ) {
echo 'B - content for user level Editor and above';
} elseif( current_user_can( 'publish_posts' ) ) {
echo 'C - content for user level Author and above';
} // ok for wordpress > 3.0
which will output totally different content for each user , but also means that user level 10 will NOT SEE the content of level 6.. ( unless you drop the else.. )
// when Admin logged
A - content for user level Admin
// when level editor and above logged
B - content for user level Editor and above
// when level author and above logged
C - content for user level Author and above
or
if( current_user_can( 'publish_posts' ) ){ // Author
echo 'A - content for Author and above';
if( current_user_can( 'publish_pages' ) ){ // Editor
echo 'B - Additional content for Editor and above';
if( current_user_can( 'manage_options' ) ){ // Administrator
echo 'C - Additional content for administrator ';
}
}
}
which will ADD output based on user levels - so user 10 see user 6 content PLUS user 8 content PLUS user 10 content
Put in plain human language example one will show content for level 10 OR content for level 8 OR .. while example 2 will show content for level 10 AND content for level 8 AND ..
Like said before - there are many many ways to use it , but it all depends on context .
Note : Since wp 3.0 the user_level system was deprecated . you will need to filter by Capabilities using the user level to role Conversion system ..
if( current_user_can( 'administrator' ) ){} // only if administrator
if( current_user_can( 'editor' ) ){} // only if editor
if( current_user_can( 'author' ) ){} // only if author
if( current_user_can( 'contributor' ) ){} // only if contributor
if( current_user_can( 'subscriber' ) ){} // only if subscriber
How can I hide posts from some category with some ID from main page of my site? I need solution like filter:
function exclude_post($query) {
if ($query->is_home) {
...
}
return $query;
}
add_filter('pre_get_posts', 'exclude_post');
Can somebody provide an example?
Use $query->set( $query_var, $value ); where $query_var is the variable you want to add/update in query. So put this inside your condition:
// 1st parameter is the query variable the 2nd is its value, in this case an array of category IDs
$query->set( 'category__not_in', array( 2, 6 ) );
Remember is good practice put in condition a check to $query->is_main_query(). pre_get_posts is an action hook so you have to change add_filter to add_action.
An action hook doesn't return a value, a filter does.
Example
function exclude_post( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
$query->set( 'category__not_in', array( 2, 6 ) );
}
}
add_action('pre_get_posts', 'exclude_post');
UPDATE
According to the new details emerging by the question,in order to exclude some posts in feeds stream, but not in category archive, the conditional check might look like:
if( $query->is_feed() && !$query->is_archive() )
OR
if( $query->is_feed() && !$query->is_category() )
Hope it helps!
you can also use the following way to exclude the a category from post query
<?php
if ( is_home() )
{
query_posts($query_string . '&cat=-3');
}
?>
You can use simple exclude in the query parameters :-
<?php wp_list_categories('orderby=name&show_count=1&exclude=10'); ?>
Its only sample , how to you exclude.
Hop it work..