how to create a shortcode from a variable in plugin - php

i'm using WP User Frontend Pro plugin
i want to echo the pack title using a shortcode to put it in bakery visual.
all what i know is : this is the title $pack->post_title;
$pack is coming from here :
public function current_pack() {
global $pack;
$pack = $this->pack;
if ( ! isset( $this->pack['pack_id'] ) ) {
$pack_page = get_permalink( wpuf_get_option( 'subscription_page', 'wpuf_payment' ) );
return new WP_Error( 'no-pack', sprintf( __( 'You must purchase a subscription package before posting', 'wp-user-frontend'), $pack_page ) );
}
// seems like the user has a pack, now check expiration
if ( $this->expired() ) {
return new WP_Error( 'expired', __( 'The subscription pack has expired. Please buy a pack.', 'wp-user-frontend' ) );
}
return $pack;
}
i try to do something like this :
function wpc_shortcode_pack_title() {
global $pack;
return $pack->post_title;
}
add_shortcode( 'sub_name', 'wpc_shortcode_pack_title' );
to explain more
the slected code in line 5 is working correctly in the plugin pages
but i want it as a shortcode
but it didn't work
any help please ?

The callback function of add_shortcode() should return the content, not print it.
Meaning, you have to return $pack->post_title instead of echo $pack->post_title.
Like so:
function wpc_shortcode_pack_title() {
global $pack;
return $pack->post_title;
}
add_shortcode( 'sub_name', 'wpc_shortcode_pack_title' );
Edit: After taking a look at the source of “WP User Frontend Pro”:
$pack seems to be getting its value from WPUF_Subscription::get_subscription() passing the subscription id, which basically gets the post with that id.
The subscription id seems to be getting its value from WPUF_Subscription::get_user_pack() passing the user id.
So, I guess you could call get_current_user_id() and try something like this:
function wpc_shortcode_pack_title() {
$user_id = get_current_user_id();
if ( ! class_exists( 'WPUF_Subscription' ) ) {
return 'WP User Frontend Pro is not installed/activated';
}
$user_sub = WPUF_Subscription::get_user_pack( $user_id );
$pack = WPUF_Subscription::get_subscription( $user_sub['pack_id'] );
return $pack->post_title;
}
add_shortcode( 'sub_name', 'wpc_shortcode_pack_title' );
Edit #2: To get the expire date as well, you would do something similar:
function wpc_shortcode_pack_title() {
$user_id = get_current_user_id();
if ( ! class_exists( 'WPUF_Subscription' ) ) {
return 'WP User Frontend Pro is not installed/activated';
}
// Get WPUF subscription/pack
$user_sub = WPUF_Subscription::get_user_pack( $user_id );
$pack = WPUF_Subscription::get_subscription( $user_sub['pack_id'] );
// Get expiration date
$expire = ( $user_sub['expire'] == 'unlimited' ) ? ucfirst( 'unlimited' ) : wpuf_date2mysql( $user_sub['expire'] );
return sprintf(
'Subscription name: %1$s | Expire date: %2$s',
$pack->post_title,
wpuf_get_date( $expire )
);
}
add_shortcode( 'sub_name', 'wpc_shortcode_pack_title' );

Related

Add custom my account menu item based on user role in WooCommerce 3+

I am using WordPress and WooCommerce and I have followed this article https://rudrastyh.com/woocommerce/my-account-menu.html to add new menu items in WooCommerce my account menus.
This is my working code.
function getUserRolesByUserId( $id ) {
if ( !is_user_logged_in() ) { return false; }
$oUser = get_user_by( 'id', $id );
$aUser = get_object_vars( $oUser );
$sRoles = $aUser['roles'];
return $sRoles;
}
function createMenuBasedonUserRole($userId)
{
$userRoleIds = getUserRolesByUserId(get_current_user_id());
$urlMenuData = [];
if(!empty($userRoleIds) && in_array('mindesk_var_account',$userRoleIds)) {
$urlMenuData = [
'pageName' => "Clients",
"pageLink" => "clients"
];
} else if(!empty($userRoleIds) && in_array('mindesk_owner_account',$userRoleIds)) {
$urlMenuData = [
'pageName' => "Children",
"pageLink" => "children"
];
}
return $urlMenuData;
}
/*
* Step 1. Add Link (Tab) to My Account menu
*/
add_filter ( 'woocommerce_account_menu_items', 'mindesk_clients_children_link', 40 );
function mindesk_clients_children_link( $menu_links ){
$urlData = createMenuBasedonUserRole(get_current_user_id());
if(!empty($urlData)){
$menu_links = array_slice( $menu_links, 0, 5, true ) + array( $urlData['pageLink'] => $urlData['pageName'] ) + array_slice( $menu_links, 5, NULL, true );
}
return $menu_links;
}
/*
* Step 2. Register Permalink Endpoint
*/
add_action( 'init', 'mindesk_add_menu_endpoint' );
function mindesk_add_menu_endpoint() {
add_rewrite_endpoint( 'clients', EP_PAGES );
add_rewrite_endpoint( 'children', EP_PAGES );
}
/*
* Step 3. Content for the new page in My Account, woocommerce_account_{ENDPOINT NAME}_endpoint
*/
add_action( 'woocommerce_account_clients_endpoint', 'mindesk_clients_my_account_endpoint_content' );
function mindesk_clients_my_account_endpoint_content() {
require_once(get_template_directory() . '/myaccount/clients.php') ;
}
add_action( 'woocommerce_account_children_endpoint', 'mindesk_children_my_account_endpoint_content' );
function mindesk_children_my_account_endpoint_content() {
require_once(get_template_directory() . '/myaccount/children.php') ;
}
/* Step 4
*/
// Go to Settings > Permalinks and just push "Save Changes" button.
And this is my how my new menu called as "Clients" showing.
As you can see above, I have added new menu and executing the page and based on user role mindesk_var_account I need to show clients and mindesk_owner_account I need to show children.
I have created these 2 php pages at /wp-content/themes/twentytwentyone/myaccount and its working fine.
However, I want to use wp_die or something if user with another role try to access one of the page which they are not allowed to.
So for example if logged in user has mindesk_var_account role then if they try to go to http://localhost/wordpress/my-account/clients/ then i need to use wp_die() to not execute it.
I tried to use wp_die inside these new 2 pages but then menus and other things executed. I just want something like this.
I tried to use following code...
add_action( 'template_redirect', 'my_account_redirect' );
function my_account_redirect() {
if( is_page( 'my-account' ) ) {
wp_die('fg');
}
}
But then its checking for all my-account pages .. and I want it to be checked only for inner pages like client or children.
Can someone guide me how can I achieve this what should I do from here on.
Thanks
There are still some little mistakes in your code, some missing things and since WooCommerce 3 there are some related changes within step 2 for My account endpoints. Some things can be simplified too.
To avoid non allowed user roles to access to some prohibited section(s) or endpoint(s) you can use a custom function hooked in template_redirect hook that will redirect user to an allowed section.
Here is the complete code:
// Custom function that get My account menu item data based on user roles
function get_menu_item_by_user_role() {
$user_roles = wp_get_current_user()->roles;
if ( ! empty($user_roles) ) {
$menu_item = [];
// if ( in_array('mindesk_var_account', $user_roles) ) {
if ( in_array( 'mindesk_var_account', $user_roles ) ) {
$menu_item = [ 'clients' => __( "Clients", "woocommerce" ) ];
}
elseif( in_array( 'mindesk_owner_account', $user_roles ) ) {
$menu_item = [ 'children' => __( "Children", "woocommerce" ) ];
}
}
return $menu_item;
}
// Step 1 - Add Link (Tab) to My Account menu
add_filter ( 'woocommerce_account_menu_items', 'add_mindesk_custom_menu_items', 40 );
function add_mindesk_custom_menu_items( $menu_items ){
$new_item = get_menu_item_by_user_role();
if ( ! empty($new_item) ) {
$menu_items = array_slice( $menu_items, 0, 5, true ) + $new_item + array_slice( $menu_items, 5, null, true );
}
return $menu_items;
}
// Step 2 - Enable endpoint (and endpoint permalink) - Since WooCommerce 3
add_filter( 'woocommerce_get_query_vars', 'add_mindesk_menu_item_endpoint' );
function add_mindesk_menu_item_endpoint( $query_vars ) {
$query_vars['clients'] = 'clients';
$query_vars['children'] = 'children';
return $query_vars;
}
// Step 3. Content for the new page in My Account, woocommerce_account_{ENDPOINT NAME}_endpoint
add_action( 'woocommerce_account_clients_endpoint', 'add_mindesk_account_clients_endpoint_content' );
function add_mindesk_account_clients_endpoint_content() {
require_once(get_template_directory() . '/myaccount/clients.php') ;
}
add_action( 'woocommerce_account_children_endpoint', 'add_mindesk_account_children_endpoint_content' );
function add_mindesk_account_children_endpoint_content() {
require_once(get_template_directory() . '/myaccount/children.php') ;
}
// Step 4. Endpoint page title
add_filter( 'woocommerce_endpoint_clients_title', 'set_mindesk_account_clients_endpoint_title', 10, 2 );
function set_mindesk_account_clients_endpoint_title( $title, $endpoint ) {
$title = __("Clients", "woocommerce" );
return $title;
}
add_filter( 'woocommerce_endpoint_children_title', 'set_mindesk_account_children_endpoint_title', 10, 2 );
function set_mindesk_account_children_endpoint_title( $title, $endpoint ) {
$title = __( "Children", "woocommerce" );
return $title;
}
// Step 5. Redirect if not allowed user role
add_action( 'template_redirect', 'redirect_mindesk_account_dashboard' );
function redirect_mindesk_account_dashboard() {
if ( is_account_page() ) {
global $wp;
$item_key = array_keys(get_menu_item_by_user_role());
$page_url = get_permalink( get_option('woocommerce_myaccount_page_id') );
if ( empty($item_key) && ( isset($wp->query_vars['children']) || isset($wp->query_vars['clients']) ) ) {
wp_safe_redirect( get_permalink($page_id) );
exit();
}
elseif ( 'clients' == reset($item_key) && isset($wp->query_vars['children']) ) {
wp_safe_redirect( get_permalink($page_id) . 'clients/' );
exit();
}
elseif ( 'children' == reset($item_key) && isset($wp->query_vars['clients']) ) {
wp_safe_redirect( get_permalink($page_id) . 'children/' );
exit();
}
}
}
// Step 6. FLush rewrite rules:
// Go to Settings > Permalinks and click on "Save Changes".
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
related: WooCommerce My Account custom endpoint menu item

Display a custom field next in the Woocommerce admin panel

I'm at wits end with this now and could really use a hand.
I've added a form on the front end that asks the customer to register with their IRL user account number, I've managed to get that to store in the back end as "morello_account_number". Now I want to echo that account number on the order page in Woocommerce so that I can process orders easier without searching the customers username etc manually. I'm not really a PHP programmer, but here's my code so far:
add_filter('manage_edit-shop_order_columns', 'morello_account_number_column' );
function morello_account_number_column( $order_columns ) {
$order_columns['morello_account_number'] = "Morello Account Number";
return $order_columns;
}
add_action( 'manage_shop_order_posts_custom_column' , 'morello_placeholder' );
function morello_placeholder( $colname ) {
global $the_order; // the global order object
if( $colname == 'morello_account_number' ) {
$morello_account_number = $order->get_morello_account_number();
echo morello_account_number;
}
}
Apologies if this is super trivial - still learning. And thanks so much in advance.
Assuming you've used update_post_meta before in your previous code?
Then you could apply the following
/**
* Add columns
*/
function morello_account_number_column( $columns ) {
$columns['morello_account_number'] = "Morello Account Number";
return $columns;
}
add_filter('manage_edit-shop_order_columns', 'morello_account_number_column', 10, 1 );
/**
* Populate columns
*/
function morello_placeholder( $column, $post_id ) {
if( $column == 'morello_account_number' ) {
// https://developer.wordpress.org/reference/functions/get_post_meta/
$m_a_n = get_post_meta( $post_id, 'morello_account_number', true );
// Value is found
if ( !empty($m_a_n) ) {
echo $m_a_n;
} else {
echo 'something else';
}
}
}
add_filter( 'manage_shop_order_posts_custom_column', 'morello_placeholder', 10, 2 );

Do not submit form after wrong code

I am working on a WordPress plugin which adds an auth code to the login form.
This is the process of checking if the auth code is valid:
add_action( 'wp_authenticate', 'authcode_check', 5 );
function authcode_check($username) {
$options = get_option( 'authcode_settings' );
if(!empty($options['code'])) {
global $wpdb;
if ( !username_exists( $username ) ) {
return;
}
$set_code = $options['code'];
$submit_code = $_POST['auth_key'];
if(empty($submit_code)) {
add_filter( 'login_errors', function( $error ) {$error = '<strong>ERROR</strong>: Authentication code cannot be empty.';return $error;} );
return;
} elseif ( ! ( $set_code == $submit_code ) ) {
add_filter( 'login_errors', function( $error ) {$error = '<strong>ERROR</strong>: Authentication code is invalid.';return $error;} );
return;
}
}
}
The problem is; when the user enters their WordPress name and password correctly, but not the auth code, the form still submits and log the user in.
I tried return false but that didn't work.
Is there any way to prevent the form from logging the user in when they have entered a wrong auth code?
Working Example
Updated after chat with #J.Doe
We can hook into the login_form hook, to display the input for the authentication code:
/**
* 'Authentication Code' Input
*/
add_action( 'login_form', function()
{
// Fetch the stored code
$options = get_option( 'authcode_settings' );
// Display code input
if( isset( $options['code'] ) )
printf(
'<p class="login-authenticate">
<label for="auth_key">%s</label>
<input type="text" name="so38551606_auth_key" id="so38551606_auth_key"
class="input" value="" size="20" autocomplete="off" />
</p>',
esc_html__( 'Authentication Code', 'mydomain' )
);
} );
You can hook into the authenticate filter, within the wp_authenticate() function, for the validating part:
/**
* Validate 'Authentication Code' Input
*/
add_filter( 'authenticate', function( $user )
{
// Fetch stored code value
$options = get_option( 'authcode_settings' );
// Nothing to do if there's no stored code value
if( ! isset( $options['code'] ) )
return $user;
// Fetch the user's code input
$submit_code = isset( $_POST['so38551606_auth_key'] )
? $_POST['so38551606_auth_key']
: null;
// Validation's logic
$is_valid_auth_code = ! is_null( $submit_code )
&& ( $options['code'] === $submit_code );
// Valid auth code
if( $is_valid_auth_code )
return $user;
// Add an unvalid auth code error
if( is_wp_error( $user ) )
$user->add(
'invalid_auth_code',
sprintf(
'<strong>%s</strong>: %s',
esc_html__( 'ERROR', 'mydomain' ),
esc_html__( 'Authentication code is invalid.', 'mydomain' )
)
);
// Create a new auth code error
else
$user = new WP_Error(
'invalid_auth_code',
sprintf(
'<strong>%s</strong>: %s',
esc_html__( 'ERROR', 'mydomain' ),
esc_html__( 'Authentication code is invalid.', 'mydomain' )
)
);
return $user;
}, 100 );
Here we use a priority of 100 because we want to run it after the default callbacks of:
add_filter( 'authenticate', 'wp_authenticate_username_password', 20, 3 );
add_filter( 'authenticate', 'wp_authenticate_email_password', 20, 3 );
add_filter( 'authenticate', 'wp_authenticate_spam_check', 99 );
We prefixed the POST variable with so38551606_ to avoid possible name collision.
Output example:
Instead of return false use return as apparently WordPress prefers it that way, look at the existing username code it just returns, not false, not true, just return
Also place the add filter functions before the return statements as a return signifies that the code stops running at that point, nothing below it is executed anymore, so your filters won't appear unless you move them
Can you prove the user isn't being logged in? Or are you just assuming they are being logged in because the error messages aren't being shown?
Anything after the return keyword won't be run. So in your if statements, you have two return false;s if the auth key doesn't match and then you are calling a function afterwards. This function won't be run so the error code won't be displayed.
What you can do however, is move the function above the return keyword. It will then display the error and return false.

Unable to Override WooCommerce Checkout Fields

I've created a custom WooCommerce checkout field with Woothemes Checkout Field Editor labeled "po_number". I would like the PO Number checkout field to only display for the user role "distributor".
So far I've been unsuccessful in overriding the checkout fields. I'm using Wordpress 4.5.1 / Woocommerce 2.5.5. Here's the code I've placed in my child theme's functions.php. I've also tested to make sure it is not a theme conflict.
Any help is greatly appreciated.
This is my code:
function custom_override_checkout_fields( $fields ) {
if ( ! current_user_can( 'distributor' ) && isset( $fields['billing']['po_number'] ) ) {
unset($fields['billing']['po_number']);
}
return $fields;
}
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
The current_user_can() function is related to capabilities of the user roles, but not to detect the user roles themselves. For that reason is not working in your code.
You need to set a conditional function for this purpose (user roles):
function is_user_role( $role, $user_id = null ) {
if ( is_numeric( $user_id ) ) {
$user = get_userdata( $user_id );
} else {
$user = wp_get_current_user();
}
if ( empty( $user ) ) {
return false;
}
if ( in_array( $role, (array) $user->roles ) == 1) {
return true;
} else {
return false;
}
}
Then in your code you can use that function:
function custom_override_checkout_fields( $fields ) {
if ( !is_user_role( 'distributor' ) && isset( $fields['billing']['po_number'] ) ) {
unset($fields['billing']['po_number']);
}
return $fields;
}
add_filter( 'woocommerce_checkout_fields', 'custom_override_checkout_fields' );
This should work in your code.

Wordpress Single User Session

I'm using the Current version of Wordpress (4.2.4) and woocommerce (2.3.6).
Problem: Don't let users share their login details to the site.
Old Solution: The Answer to this question has been working until now.
What i need: Can anyone see what's wrong with this code & why it wouldn't work with the new Wordpress update (4.2.4).
Or offer up another solution.
Code from answer by #manoj-dhiman:
how can I prevent multiple login from same user id from different browsers in wordpress?
if( !class_exists( 'WPSingleUserLoggin' ) ) {
class WPSingleUserLoggin
{
private $session_id;
function __construct()
{
if ( ! session_id() )
session_start();
$this->session_id = session_id();
add_action( 'init', array( $this, 'init' ) );
add_action( 'wp_login', array( $this, 'wp_login' ), 10, 2 );
}
function init()
{
if( ! is_user_logged_in() )
return;
$stored_sess_id = get_user_meta( get_current_user_id(), '_wp_single_user_hash', true );
if( $stored_sess_id != $this->session_id )
{
wp_logout();
wp_redirect( wp_login_url() );
exit;
}
}
function wp_login( $user_login, $user )
{
update_user_meta( $user->ID, '_wp_single_user_hash', $this->session_id );
return;
}
}
new WPSingleUserLoggin();
}

Categories