If user is a specific user OR and Admin - php

I am creating user specific content using ACF User field to determine which user can see what. My code below is working perfectly to show the correct content to the user selected and something different to everyone else -
<?php
$client = get_field('client');
$userID = $client['ID'];
$user_id = get_current_user_id();
if ($user_id == $userID ) {
echo 'YOUR OWN PAGE';
} else {
echo 'NOT YOUR PAGE';
}
?>
However I need to simply add an 'or' statement so any user that is an admin can see all content regardless of who they are, something like below (which doesn't work) -
if ($user_id == $userID ) || is_admin() {
All help is greatly appreciated.

Your brackets are wrong that is all.
if ($user_id == $userID || is_admin() ) {
This assumes the is_admin() function works though :)

While Christian's answer fixes the typo in the question, it doesn't provide a working solution.
The documentation for is_admin() states the following:
This Conditional Tag checks if the Dashboard or the administration panel is attempting to be displayed. It should not be used as a means to verify whether the current user has permission to view the Dashboard or the administration panel (try current_user_can() instead). This is a boolean function that will return true if the URL being accessed is in the admin section, or false for a front-end page.
And further down in the notes section:
is_admin() is not intended to be used for security checks. It will
return true whenever the current URL is for a page on the admin side
of WordPress. It does not check if the user is logged in, nor if the
user even has access to the page being requested. It is a convenience
function for plugins and themes to use for various purposes, but it is
not suitable for validating secured requests.
I do understand the logic that could lead one to think that is_admin() checks if the current user is an administrator. However, checking with the WordPress documentation(and I have to say it's really good for commonly used functions) is always a good idea.
Now that we've got that out of the way, there are two simple options that you can use in order to figure out if the current user has administrator privileges:
1. If you're not going to use WordPress Multisite, or if you will want to only allow Super Administrators to see the content
is_super_admin():
Determine if user is a network (super) admin. Will also check if user is admin if network mode is disabled.
You can pass the ID of a given user to the function, or in your case just do this:
if ( $user_id == $userID || is_super_admin() ) {
2. If you're going to use WordPress Multisite and you will want to allow Super Administrators and site Administrators to see the content
We can create our own function that works very similar to is_super_admin(), except for in a Multisite environment it also checks if the current user is an administrator(in the is_super_admin() function, this is defined by the user having the delete_users capability). Here's the code:
function my_is_user_admin( $user_id = false ) {
if ( ! $user_id || $user_id == get_current_user_id() ) {
$user = wp_get_current_user();
} else {
$user = get_userdata( $user_id );
}
if ( ! $user || ! $user->exists() ) {
return false;
}
if ( is_multisite() ) {
$super_admins = get_super_admins();
if ( ( is_array( $super_admins ) && in_array( $user->user_login, $super_admins ) ) || $user->has_cap( 'delete_users' ) ) {
return true;
}
} else {
if ( $user->has_cap( 'delete_users' ) ) {
return true;
}
}
return false;
}
There is also an alternative solution, which could be more extendable - you can create your own capability and assign it to the Administrator role. That way if for some reason I want to give someone access to all content, but don't want to make them an Administrator on my site, I can just add that particular capability to that particular user(can't find a free plugin at the moment, but there are ways to do it).
This question has decent answers on how to add a custom capability - https://wordpress.stackexchange.com/questions/35165/how-do-i-create-a-custom-role-capability - should you choose to go that way.

Related

Wordpress - Show admin bar only to the post author

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.

Protect Returns & Warranty Requests from other users in Woocommerce

Is there any way to protect WooCommerce Returns & Warranty Requests plugin's request/status page (the slug of the page I created is "returns") from users that the order number or warranty request number doesn't belong too?
In default mode the page is open to public, hence, even if a visitor visits this url .../my-account/returns/?order=35 can see the all warranty request details that the original user requested, is there any way to protect this page? I want to use a code that checks if user is not logged in and if the order number or warranty request number doesn't belong to the logged in user then don't show the /returns/ page.
I was able to use this code in my functions.php to prevent not logged in users to see the /returns/ page:
function template_redirect_returns()
{
if( is_page(returns) && !is_user_logged_in() )
{
$loginUrl = home_url('/my-account/orders/');
wp_redirect($loginUrl);
exit();
}
}
add_action( 'template_redirect', 'template_redirect_returns' );
But how can I also prevent the users from seeing the page if the ?order=35 doesn't belong to them?
I asked the plugin developers and also reported many bugs but they don't care to fix the issues.
I will appreciate your help! With gratitude.
In your code is_page(returns) should be replaced by is_page('returns') as it throws an error.
Try the following (untested):
add_action( 'template_redirect', 'template_redirect_returns' );
function template_redirect_returns()
{
if( is_page('returns') ) {
if( ! is_user_logged_in() ) {
wp_redirect( home_url('/my-account/') ); // instead of '/my-account/orders/'
exit();
}
// For logged in users
else {
// Testing if current user ID match with order customer ID
if( isset($_GET['order']) && get_post_meta( $_GET['order'], '_customer_user', true ) != get_current_user_id() ){
wp_redirect( home_url('/my-account/orders/') );
exit();
}
}
}
}
This is a real security bug in this plugin, and should be notified to authors.

Avoiding redirection to the Dashboard in WordPress

I understand that I can use the following code in WordPress to ensure that users who are already logged into my site are not re-directed to the Dashboard when they click the login button on my home page:
<?php
if(is_user_logged_in()){
// redirect to desired page
}
?>
I would be grateful for advice on where I should place this code and which part of it exactly should be overwritten with the URL for the page to which I wish to send logged in users. I should add that the desired page is the same page as I direct users to on logging in.
Many thanks in advance for your kind assistance.
Just take a look here, for more perspective: https://codex.wordpress.org/Plugin_API/Filter_Reference/login_redirect
If you want to land your Users, for example to this page example.com/some-page/ after login, you can use this code:
function mysite_login_redirect($redirect_to, $request, $user) {
if (!isset($_GET['loggedout'])) {
return (isset($user->roles) && is_array($user->roles) && in_array('administrator', $user->roles)) ? admin_url() : site_url('/some-page/');
}
}
add_filter('login_redirect', 'mysite_login_redirect', 10, 3);
The algorithm for doing this is simple:
If the user is an administrator, continue to admin_url()
Otherwise, redirect to, say the site_url('/some-page/')
The login_redirect filter will pass three arguments to the function:
$redirect_to
$request
$user
We’re primarily concerned with the third as we can take a look at its roles attribute to determine if it contains the administrator value.
And with that, we are now redirecting non-admin users to the specific page rather then the dashboard.
site_url('/some-page/') will transform to example.com/some-page/
Hope it will help you :)
As I undestood about your question, you are trying to prevent users to visualize the dashboard of WordPress. You can prevent non-admin users to go to the Dashboard on the admin init hook.
add_action( "admin_init", "prevent_dashboard_non_admin" );
function prevent_dashboard_non_admin() {
if ( ! current_user_can('manage_options') && ! defined( 'DOING_AJAX' ) ) {
wp_redirect( home_url() ); // You can change that home_url() to any page URL you are tring to redirect
}
}
You can put this code inside functions.php
Note: This code has not been tested, please leave a comment and I will create the update if you have any issues with it.
UPDATE
function my_is_loggin_page() {
if ( $GLOBALS['pagenow'] === 'wp-login.php' ) {
if( is_user_logged_in() ) {
wp_redirect( "yourpage" );
}
}
}
add_action( "init", "my_is_loggin_page", 12 );

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

How to log a user in to Wordpress using only their user_id

Is there any way I can log a Wordpress user in given only their wp user_ID?
I'm sending users emails to confirm something and when they click on the given link to come to the website they need to be logged in to see the page I'm taking them to, so I have to log the user in and then do a header redirect.
I need a php function provided by wordpress, one that I can use in php, could you also give me any extra details as to how I can implement it (if any)
Here a function to auto-log an user (not tested) :
function auto_login() {
if (!is_user_logged_in()) {
//determine WordPress user account to impersonate
$user_login = 'guest';
//get user's ID
$user = get_userdatabylogin($user_login);
$user_id = $user->ID;
//login
wp_set_current_user($user_id, $user_login);
wp_set_auth_cookie($user_id);
do_action('wp_login', $user_login);
}
}
You have to pass 2 parameters in wp_login hook. See Wp codex
wp_set_current_user( $user_id, $user->user_login );
wp_set_auth_cookie( $user_id );
do_action( 'wp_login', $user->user_login, $user );
Create separate table to store all the links you sent and respective temp authentication code, which may be valid only for some time, then pass that temp auth code and email as a url param -
Write a code to validate user based on temp auth code, so that as soon as user clicks on email you can redirect him.
The WordPress plugin temporary-login-without-password implements that and a unique hash / key as per your comments.
Open Source code is here:
https://plugins.trac.wordpress.org/browser/temporary-login-without-password/trunk/public/class-wp-temporary-login-without-password-public.php
public function init_wtlwp() {
if ( ! empty( $_GET['wtlwp_token'] ) ) {
$wtlwp_token = sanitize_key( $_GET['wtlwp_token'] ); // Input var okay.
$users = Wp_Temporary_Login_Without_Password_Common::get_valid_user_based_on_wtlwp_token( $wtlwp_token );
$temporary_user = '';
if ( ! empty( $users ) ) {
$temporary_user = $users[0];
}
if ( ! empty( $temporary_user ) ) {
$temporary_user_id = $temporary_user->ID;
That's a really bad ideea. Consider this:
You send an email to user A and B which contains the following link:
http://wordpressblog.exp/fromemail?user_id=A;
http://wordpressblog.exp/fromemail?user_id=B;
If user B replaces his user id with A's user_id then he has access to User A's account.
Youd be better of constructing a hash for logging a user that way

Categories