Display header based on user role and page (Wordpress) - php

I have created multiple different headers as templates with Elementor.
I would like to display all of the different headers based on user role (Logged in/Logged out) and page.
I'm looking for a code snippet that I could easily customize to assign all of the different headers for different scenarios.
Could someone please create an example code snippet that would:
Display header A for Logged Out users on the entire
website, EXCEPT pages X and Y.
Display header B for Logged In users on the entire
website, EXCEPT pages X and Y.
Display header C for Logged Out users only on pages X and
Y.
Display header D for Logged In users only on pages X and
Y.
This way, people can easily copy the code and customize it to fit their needs.
EDIT
There's 2 places where I can create templates.
1st one is added by Elementor and is found in Admin > Templates > Saved Templates. Here I can create either section or page templates (Screenshot).
2nd one is added by my theme, OceanWP, and is found in Admin > Theme Panel > My Library. Here I can create only 1 type of template. The templates created here can later be assigned as custom headers or footers to individual pages or the entire website.
Are the templates created in these 2 places considered to be template parts? Is there a difference where I choose to create the header templates?
Here's a list of the header templates I have created:
Template title
Post ID
A
Main Header (Logged Out)
5448
B
Main Header (Logged In)
6714
C
Checkout Header (Logged Out)
6724
D
Checkout Header (Logged In)
3960
Here's the page I want to have a different header than the entire website:
Page title
Post ID
Slug
X
Checkout
18
checkout

Something like this should work:
<?php
if (! is_user_logged_in() && ! is_page(array( 'page-x-slug', 'page-y-slug' ))){
// display header A
}
if (is_user_logged_in() && ! is_page(array( 'page-x-slug', 'page-y-slug' ))){
// display header B
}
if (! is_user_logged_in() && is_page(array( 'page-x-slug', 'page-y-slug' ))){
// display header C
}
if (is_user_logged_in() && is_page(array( 'page-x-slug', 'page-y-slug' ))){
// display header D
}
?>

The following offer the same result as the previous answer but is minified and has less repetitiveness.
<?php
if ( is_page( [ 'page-x', 'page-y' ] ) )
if ( is_user_logged_in() )
get_header( 'B' ); //... header-B.php
else
get_header( 'A' ); //... header-A.php
else
if ( is_user_logged_in() )
get_header( 'D' ); //... header-D.php
else
get_header( 'C' ); //... header-C.php
?>
Following your comments
I'm guessing that what you refer as...
section templates
...are in fact templates part. Instead of using get_header( string $name ); you would then use get_template_part( string $slug, string $name = null );.
$slug and $name can be anything that you chose.
Source # https://developer.wordpress.org/reference/functions/get_template_part/
For example, section-A.php would be get_template_part( 'section', 'A' );.
<?php
//...
if ( is_user_logged_in() )
get_template_part( 'section', 'B' ); //... section-B.php
else
get_template_part( 'section', 'A' ); //... section-A.php
?>
In regards to specifying pages and templates. is_page() can take IDs, slugs or titles.
is_page( int|string|int[]|string[] $page = '' )
Parameter
Description
$page
(int|string|int[]|string[]) (Optional) Page ID, title, slug, or array of such to check against. Default value: ''
Source # https://developer.wordpress.org/reference/functions/is_page/
But you could also use other is_ function like is_search() or is_archives(), is_404()... etc.
Here is a complete list # https://codex.wordpress.org/Conditional_Tags
If you want to add multiple conditional statement you can just add elseif statements in-between.
<?php
if ( is_page( [ 'page-x', 'page-y' ] ) )
//...
elseif ( is_search() || is_archive() )
//...
else
//...
?>
If you want to get a better understanding of PHP operators, which are how conditional statements are built, take a look # https://www.w3schools.com/php/php_operators.asp

Related

WordPress category based template

I have a task to create a template which is specific to the category. So Lets say I have 10 categories but I want to create a specific template for lets say 3 of them. So if the category is a,b or c I will apply a certain template.
And then when I create a post and attach it to the specific category I need to show that specific template associated to the category.
Any headers?
The Advanced Custom Fields https://www.advancedcustomfields.com/ plugin should allow you to show different templates based off categories. It has some pretty fancy functionality, but can't remember if it can do exactly this.
There is a free version, so give it a try. Let me know how you go ;)
Delete everything in single.php
Insert the ‘switching’ code (see below)
Create 3(three) new templates with unique names. like : single-a,single-b,single-c.
On the server, the magical fairy dust in your modified single.php will automatically load the correct template when the page is requested
Please try below Code for the same.
if (in_category('21')) {include (TEMPLATEPATH . '/single-a.php');
}
else if (in_category('22')) {include (TEMPLATEPATH . '/single-b.php');
}
else if (in_category('23')) {include (TEMPLATEPATH . '/single-c.php');
}
else { include (TEMPLATEPATH . '/single-29.php');
}
There is single-a,single-b,single-c are 3 templates for different categories and your main code in it.
If you refer to Category_Templates
Wordpress will auto retrieve category files in the following format:
category-slug.php or category-ID.php
Let's say you have 3 categories, category a, category b, category c, to assign each of the template differently you can easily create category-a.php, category-b.php, category-c.php and place your desire template within the file and Wordpress will handle the rest.
Here you can use category_template
function wp_category_template( $template ) {
$cat = get_queried_object(); // get category object
if( 1 ) // check condition
$template = locate_template( 'template.php' ); // load template
return $template;
}
add_filter( 'category_template', 'wp_category_template' );
or as #shashi suggested you can use plugin custom-category-template
You have 3 options :
Option 1 : You can create 3 templates and name them according to the WordPress Template Hierarchy like this :
category-1.php
category-2.php
category-3.php
Option 2 : Use PHP code in your functions file to load 1 template for 3 different categories :
add_filter( 'template_include', 'custom_category_template', 99 );
function custom_category_template( $template ) {
if ( is_category(array( 1,2,3 ) ) ) {
$new_template = locate_template( array( 'custom.php' ) );
if ( '' != $new_template ) {
return $new_template;
}
}
return $template;
}
Use the in_category or is_category conditional tag depending on whether you want to load the template for posts in specific categories or only for the category archive page.
Option 3 : You can use the code in option 2 with the category_template filter :
add_filter( 'category_template', 'custom_category_template' );
function custom_category_template( $template ) {
if ( is_category(array( 1,2,3 ) ) ) {
$template = locate_template( 'custom.php' );
}
return $template;
}
Assumes your category i.d's are 1, 2 and 3. Swap out these to match your installations category i.d's

Add login form shortcode programatically to every published product page

I am running a wholesale shop on Woocommerce. Login is required to see the prices. This is set up and working properly. Now I wish to add a logon form on every product page to only show to visitors (not logged on users).
I am using the WooCommerce Catalog Visibility plugin. This plugin offers the functionality I described above, but my theme is somehow messing it up. The plugin author says to talk to the theme developer and the theme developer says to talk to the plugin author. So now I am trying to find a workaround.
First issue: The plugin comes with a shortcode [woocommerce_logon_form] that will display a logon form. I don't want to manually add this to every existing product since I have thousands of products on my site. I am looking for a way to get it in through the code for the product page layout.
I found this code (to be added to the functions.php) to work well:
// adds notice at single product page above add to cart
add_action( 'woocommerce_single_product_summary', 'return_policy', 20 );
function return_policy() {
echo '<p id="rtrn">30-day return policy offered. See Terms and Conditions for details.</p>';
}
However, it will only show text. The short code won't work when added instead of the sample text.
Second issue: The short code shows the form even when the customer is already logged in.
I am currently using this nice code that shows or hides content depending on whether the user is logged in or not:
add_shortcode( 'access', 'access_check_shortcode' );
function access_check_shortcode( $attr, $content = null ) {
extract( shortcode_atts( array( 'capability' => 'read' ), $attr ) );
if ( current_user_can( $capability ) && !is_null( $content ) && !is_feed() )
return $content;
return '';
}
add_shortcode( 'visitor', 'visitor_check_shortcode' );
function visitor_check_shortcode( $atts, $content = null ) {
if ( ( !is_user_logged_in() && !is_null( $content ) ) || is_feed() )
return $content;
return '';
}
That shortcode works perfectly for text, but not with other shortcodes.
So the combination of these short codes: [visitor][woocommerce_logon_form][/visitor] will not show the logon form to visitors. Instead it will only show them this as text [woocommerce_logon_form].
Please help! I am sure this is probably easily fixed by someone with coding skills.
I appreciate your effort to answer to this question. Keep in mind that my understanding of code is very limited and it would be great if you can also point out in which file to add or modify code.
To make your shortcode working in php code or in php/html code you need to use a native WordPress function do_shortcode() … You can use it with your shortcode for example in your 1st function this way:
add_action( 'woocommerce_single_product_summary', 'return_policy', 20 );
function return_policy() {
echo do_shortcode('[woocommerce_logon_form]');
}
And this will work…
To see all the different hooks you can use instead of woocommerce_single_product_summary, please see this 2 templates code to chose in case a more convenient hook:
WooCommerce single-product.php template
WooCommerce content-single-product.php template
You can also add it the same way in one of your existing short codes, this way:
add_shortcode( 'visitor', 'visitor_check_shortcode' );
function visitor_check_shortcode( $atts, $content = null ) {
if ( ( !is_user_logged_in() && !is_null( $content ) ) || is_feed() )
return do_shortcode('[woocommerce_logon_form]');
return '';
}
And this will work too.
See as reference this answer: Change markup in WooCommerce shortcode output
So as you can see your problem is solved on both issues

Detect dashboard of WooCommerce "my account" pages

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')

Change page content based on condition Wordpress

I would like to change to homepage of a wordpress website depending on the role of the user who is logged in.
For the simple case ( i.e. whether a user is logged in or not ) I have tried using the function is_user_logged_in()
the code is as below:
if(!is_user_logged_in()){
while ( have_posts() ) : the_post();
// Include the page content template.
get_template_part( 'content', 'page' );
// If comments are open or we have at least one comment, load up the comment template.
if ( comments_open() || get_comments_number() ) {
comments_template();
}
endwhile;
}else{
echo "you are logged in";
}
But the problem is that it changes the content in the each and every page. I would like to do that for a particular page only.. ( i.e. homepage ). How do i do that? Any help would be greatly appreciated.
To do it you would have to add another condition(s), e.g. for the homepage:
if(!is_user_logged_in() && is_home()){
...
}
And similarly for the other type of the content: is_page(), is_category(), is_author(), etc. Check out the docs here.
check for the Id of the page and compare it to your wanted specific page
also you could set a category for the pages you want to alter and check for that

How to duplicate header in checkout pages?

I've three headers in my theme, and i theming the shop with my theme using templates overriding default templates.
i've this in my header.php
Header 1: For my Home site (Not shop)
Header 2: For all pages of my site (Not shop)
Header 3: For shop (Product Categories, single product, archive product)
But, when i buy any product, i go to any checkout page (Register, Cart, My Account, etc), Header 2 appears.
Simplified header.php code:
if(!is_woocommerce()) {
<!--Header Wordpress-->
if(is_home);
Home site header (Header 1)
} else {
All site header (except Home) (Header 2)
<!--End Header Wordpress-->
} else { // Woocommerce conditional
Shop header (Header 3)
}
How to solve it?
The cart and checkout are standard pages with short codes and aren't included in the other Woo templates, i.e. is_woocommerce() won't return true for them. So perhaps use
if ( is_page( 'checkout-page-slug' ) || is_page( 'other_shop_page' ) ) {
instead to target them.
Edit:
Replace checkout-page-slug or other_shop_page with the slug of a page you want to target to have the shop header:
if ( ! is_woocommerce() ) {
if ( is_home() ) {
// Home site header (Header 1)
} elseif( is_page( 'checkout-page-slug' ) || is_page( 'other_shop_page' ) ) {
// Shop header
} else {
// All site header (except Home) (Header 2)
}
} else { // Woocommerce conditional
// Shop header
}

Categories