Change woocommerce subscription "shop" link inside my account page - php

I'm a newbie in coding and currently using woocommerce subscription plugin and wanted to change the default "shop" if I don't have any subscription. I want it to link to a specific product instead of the shop.
I want to change the red part:
Below are the current code for this section:
<?php
// translators: placeholders are opening and closing link tags to take to the shop page
printf( esc_html__( 'Anda masih belum melanggan. Mula melanggan %sdi sini%s.', 'woocommerce-subscriptions' ), '', '' );
?>
</p>
<?php endif; ?>
I want to change the example.com/shop into something like example.com/product-category/myproduct
Any help will be appreciated.

To achieve that, you will need:
A conditional function that detect if the current user has an active subscription
A custom function hooked in woocommerce_subscriptions_message_store_url filter hook, where you will define your new URL linked to your product.
Here is the code:
// Conditional function detecting if the current user has an active subscription
function has_active_subscription( $user_id=null ) {
// if the user_id is not set in function argument we get the current user ID
if( null == $user_id )
$user_id = get_current_user_id();
// Get all active subscrptions for a user ID
$active_subscriptions = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_subscription', // Subscription post type
'post_status' => 'wc-active', // Active subscription
) );
// if user has an active subscription
if( ! empty( $active_subscriptions ) ) return true;
else return false;
}
// Change woocommerce subscription “shop” link inside my account page
add_filter( 'woocommerce_subscriptions_message_store_url', 'custom_subscriptions_message_store_url', 10, 1 );
function custom_subscriptions_message_store_url( $url ){
// If current user has NO active subscriptions
if( ! has_active_subscription() ){
// HERE Define below the new URL linked to your product.
$url = home_url( "/product-category/myproduct/" );
}
return $url;
}
This code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works

Related

Remove specific tabs in from WooCommerce admin settings

I would like specific users to only see the WooCommerce -> Settings -> Shipping menu. I've managed to remove other tabs e.g. Products, Payments, etc, but stuck on the following 2 things that I want to accomplish:
Remove the "GENERAL" tab in WooCommerce Settings.
Remove the "ORDER STATUSES" Tab from a plugin. (Note: this isn't a tab exactly, the slug is
'edit.php?post_type=wc_order_status')
When I try to remove the GENERAL tab, it eliminates the entire Settings menu. As for the 'Order Statuses', my code just doesn't work.
add_filter( 'woocommerce_settings_tabs_array', 'remove_woocommerce_setting_tabs', 200, 1 );
function remove_woocommerce_setting_tabs( $array ) {
global $current_user;
//Declare the tabs we want to hide
$tabs_to_hide = array(
'general' => 'General', //this one removes the entire Settings menu
'wc_order_status' => 'Order Statuses'// this doesn't work, maybe bc it's a post_type
);
// Remove tab if user role is shipping_manager
if ( in_array("shipping_manager", $$current_user->roles) ) {
$array = array_diff_key($array, $tabs_to_hide);
}
}
I had also tried the below code to remove the ORDER STATUSES tab, but still no luck:
add_action( 'admin_menu', 'remove_order_statuses_tab', 999);
function remove_order_statuses_tab()
{
global $current_user;
if ( in_array("shipping_manager", $current_user->roles) ) {
remove_menu_page( 'edit.php?post_type=wc_order_status' ); //not working either
}
}
The correct hook to be used is woocommerce_settings_tabs_array.
First you need to find which are the array keys that you need to remove from the tabs array in your code.
For that you will use first the following function that will display all array data in Admin WooCommerce settings (only for testing, to be removed):
add_filter( 'woocommerce_settings_tabs_array', 'filter_wc_settings_tabs_array', 990, 1 );
function filter_wc_settings_tabs_array( $tabs_array ) {
// Display raw array data
echo '<pre>'; print_r( $tabs_array ); echo '</pre>';
return $tabs_array;
}
It will display something like (with all required array keys):
Now you can get the array keys slugs that you need, to remove the corresponding tab settings. So now you will be able to find the correct array key slug for you Third party plugin WooCommerce setting tab, that you will use in the function code below.
To target a specific user role, you can either use global $current_user; $current_user->roles; or the Wordpress dedicated function current_user_can()…
So the working code that will remove specific setting tabs for a user role is:
add_filter( 'woocommerce_settings_tabs_array', 'filter_wc_settings_tabs_array', 200, 1 );
function filter_wc_settings_tabs_array( $tabs_array ) {
// Only for "shipping_manager" user role
if( current_user_can( 'shipping_manager' ) ) {
// Remove some specific tabs
unset( $tabs_array['general'], $tabs_array['order_status'] ); // <== replace 'order_status' by
}
return $tabs_array;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
add_filter( 'woocommerce_settings_tabs_array', 'remove_woocommerce_setting_tabs', 200, 1 );
function remove_woocommerce_setting_tabs( $array ) {
global $current_user;
// Remove tab if user role is shipping_manager
if ( in_array( "shipping_manager", $current_user->roles ) ) {
unset( $array[ 'general' ] );
?>
<script>
document.querySelector("[href='<?php echo esc_url( admin_url( 'edit.php?post_type=wc_order_status' ) ); ?>']").style.display = 'none';
</script>
<?php
}
return $array;
}
Try this code snippet

Hide products published by certain users on Woocommerce

I'm trying to hide products in Woocommerce according to the user ID who published them.
I have created the following code but it doesn't work well.
function Products_for_vendor() {
$args = array( 'post_type' => 'product', 'post_author' => '2' );
$products = get_posts( $args );
foreach ($products as $product->ID) {
$post_id = $product->ID
$terms = array( 'exclude-from-catalog', 'exclude-from-search' );
wp_set_object_terms( $post_id, $terms, 'product_visibility', false );
}
}
add_action( 'init', 'Products_for_vendor' );
to hide the post I extracted the code mentioned in this query: Change product visibility via PHP on Woocommerce 3+
Any help or comment is well received.
Thanks in advance.
You shouldn't be changing things like this directly - WooCommerce has special functions to ensure future compatibility with any database structural changes, and to ensure that product data is properly synchronised within its internal caches.
Instead, inside of your foreach loop, use this:
// Get an instance of the product
$theproduct = wc_get_product($product->ID);
// Change the product visibility (options are: 'hidden', 'visible', 'search' and 'catalog'.
$theproduct->set_catalog_visibility('hidden');
// Finally, save and sync the product changes
$theproduct->save();

Detecting if the current user has an active subscription

I'm developing a website in WordPress with WooCommerce. I'm using additionally WC Paid Listings and WooCommerce Subscriptions plugins to handle my work.
The problem is when a user with "subscriber" role with an active subscription login tries to post content every time he/she has to choose a package even if he has an active subscription.
Is there anyone with an idea of how to detect if the user has an active subscription, if it returns true then the step choosing package is skipped?
Updated (2019)
New conditional function using WooCommerce Subscriptions wcs_user_has_subscription().
New conditional function using a much lighter code version (SQL query).
Original enhanced conditional function based on an improved WP_Query.
The following custom conditional functions have an optional argument $user_id (a defined user_id) and will return true when the current user (or a defined user) has active subscriptions.
So this can be done now using 3 different ways (that do the same thing):
1) Using WooCommerce Subscriptions dedicated conditional function wcs_user_has_subscription():
function has_active_subscription( $user_id='' ) {
// When a $user_id is not specified, get the current user Id
if( '' == $user_id && is_user_logged_in() )
$user_id = get_current_user_id();
// User not logged in we return false
if( $user_id == 0 )
return false;
return wcs_user_has_subscription( $user_id, '', 'active' );
}
2) The same thing with a much lighter SQL query (added on March 2019):
function has_active_subscription( $user_id=null ) {
// When a $user_id is not specified, get the current user Id
if( null == $user_id && is_user_logged_in() )
$user_id = get_current_user_id();
// User not logged in we return false
if( $user_id == 0 )
return false;
global $wpdb;
// Get all active subscriptions count for a user ID
$count_subscriptions = $wpdb->get_var( "
SELECT count(p.ID)
FROM {$wpdb->prefix}posts as p
JOIN {$wpdb->prefix}postmeta as pm
ON p.ID = pm.post_id
WHERE p.post_type = 'shop_subscription'
AND p.post_status = 'wc-active'
AND pm.meta_key = '_customer_user'
AND pm.meta_value > 0
AND pm.meta_value = '$user_id'
" );
return $count_subscriptions == 0 ? false : true;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
3) The original enhanced code, that will also do the same:
function has_active_subscription( $user_id=null ) {
// When a $user_id is not specified, get the current user Id
if( null == $user_id && is_user_logged_in() )
$user_id = get_current_user_id();
// User not logged in we return false
if( $user_id == 0 )
return false;
// Get all active subscriptions for a user ID
$active_subscriptions = get_posts( array(
'numberposts' => 1, // Only one is enough
'meta_key' => '_customer_user',
'meta_value' => $user_id,
'post_type' => 'shop_subscription', // Subscription post type
'post_status' => 'wc-active', // Active subscription
'fields' => 'ids', // return only IDs (instead of complete post objects)
) );
return sizeof($active_subscriptions) == 0 ? false : true;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Update of usage:
1) USAGE for the current user:
if( has_active_subscription() ){ // Current user has an active subscription
// do something … here goes your code
// Example of displaying something
echo '<p>I have active subscription</p>';
}
2) USAGE for a defined user ID:
if( has_active_subscription(26) ){ // Defined User ID has an active subscription
// do something … here goes your code
// Example of displaying something
echo '<p>User ID "26" have an active subscription</p>';
}
This code is tested and it works
Related answers:
WooCommerce Subscriptions - Check if product already has an active subscriber
WooCommerce - Get active subscriptions in a list between start / end date
Use wcs_user_has_subscription()
$has_sub = wcs_user_has_subscription( '', '', 'active' );
if ( $has_sub) {
// User have active subscription
}

Enabling permanently review checkbox option for all WooCommerce products

I would like to enable review checkbox permanently for all existing products and for newly added products too. I have looked in WooCommerce settings, but thatís not possible. I have search over internet, and I didnít find anything.
How can I bulk edit all existing products to get reviews Enabled?
When we add a new product it should be automatically checked too.
Is there a way to do it?
Is it possible?
Thanks in advance.
This is possible, but you will need 2 functions. One to update all existing products inn your shop, that you will use only one time, and the other for all newly published products.
Step 1 - Use this just once on function.php and go to front-end and navigate to any page. Once done comment this code or remove it. All your existing products have been updated.
// Updating all products that have a 'comment_status' => 'closed' to 'open'
function updating_existing_products_once(){
$args = array(
// WC product post type
'post_type' => 'product',
// all posts
'numberposts' => -1,
'comment_status' => 'closed',
'post_status' => 'publish',
);
$shop_products = get_posts( $args );
foreach( $shop_products as $item){
$product = new WC_Product($item->ID);
wp_update_post( array(
'ID' => $item->ID,
'comment_status' => 'open',
) );
}
}
// After usage comment this line below
updating_existing_products_once();
Step 2 - This function will update new created products that have a 'comment_status' => 'closed' to 'open' (reviews on WooCommerce)…
add_action('transition_post_status', 'creating_a_new_product', 10, 3);
function creating_a_new_product($new_status, $old_status, $post) {
if( $old_status != 'publish' && $new_status == 'publish' && !empty($post->ID) && in_array( $post->post_type, array( 'product') ) ) {
if ($post->comment_status != 'open' ){
$product = new WC_Product($post->ID);
wp_update_post( array(
'ID' => $post->ID,
'comment_status' => 'open',
) );
}
}
}
This code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
In addition to LoicTheAztec's excellent answer, I'd like to add a different option for "Step 1".
You could just run a simple query that doesn't require iterating over a loop:
global $wpdb;
$wpdb->query("UPDATE {$wpdb->posts} SET comment_status = 'open' WHERE post_type = 'product'");
Note the intentional omission of the comment_status and post_status in the WHERE clause. It would not matter that unpublished products have an open comment status, nor would it matter that products that already have comment_status set to open are being re-set to open.
Just add the above code to the bottom of your theme's functions.php file, and then comment them out after it has been run once:
// Commented out so it won't run
// global $wpdb;
// $wpdb->query("UPDATE {$wpdb->posts} SET comment_status = 'open' WHERE post_type = 'product'");
I know it's old question but function below could help someone if LoicTheAztec's answer won't work (like for me). It will check reviews' checkbox by default by using jQuery on "Add product" page. I hope help someone, cheers! :-)
add_action( 'woocommerce_product_options_advanced', 'enable_reviews_by_default' );
function enable_reviews_by_default() {
?>
<script>
(function($){
$('input[name=comment_status]').prop('checked', true);
})(jQuery);
</script>
<?php
}
By the way a dirty method of fixing things immediately (reversable). All credits to a guy Evgeniy
https://developer.wordpress.org/reference/functions/comments_open/
While the original thread discusses how to disable comments everywhere, I reversed the effect :)
This disables the possibility for you to decide on a per-product basis, because overrides the checkbox site-wide!
Disclaimer: do at your own risk!
add_filter( 'comments_open', '__return_true' );

woo commerece short codes not working on all posts

I have created a short code to display short description in woo commerce but it is not working on all posts. It is displaying the short description on some posts and not on others.
Function to create that short code in functions.php
function product_shortdesc_shortcode( $atts ){
// use shortcode_atts() to set defaults then extract() to variables
extract( shortcode_atts( array( 'id' => false ), $atts ) );
// if an $id was passed, and we could get a Post for it, and it's a product....
if ( ! empty( $id ) && null != ( $product = get_post( $id ) ) && $product->post_type = 'product' ){
// apply woocommerce filter to the excerpt
echo apply_filters( 'woocommerce_short_description', $product->post_excerpt );
}
}
// process [product_shortdesc] using product_shortdesc_shortcode()
add_shortcode( 'product_shortdesc', 'product_shortdesc_shortcode' );
The way i am getting the data in my single.php file
$custom = get_post_custom(get_the_ID());
$my_custom_field = $custom['woo_id'];
foreach ( $my_custom_field as $key => $value ) {
echo do_shortcode('[product_shortdesc id='.$value.']');
}
PS: in my normal post i have a custom field which has the value of product id of the product in woo commerece.
Your issue is that you are expecting shortcodes to function which no longer exist. On new installs, these pages won't be created, but if you are updating you may already have those pages in place.
Although the upgrade script does attempt to trash them for you, this might not have happened if they were customised. Delete them. Delete edit-account and change password, then go to your 'my account' page and click the change password/edit account links. You'll be taken to and endpoint which offers the same functionality.
Thanks
Short Code must not echo code instead return the things that needs to be rendered
Change this
echo apply_filters( 'woocommerce_short_description', $product->post_excerpt );
to
return apply_filters( 'woocommerce_short_description', $product->post_excerpt );

Categories