How to Add User Role ColunmTo Woocommcerce Orders table - php

Can't seem to figure out the PHP code to add a new column on the woocommcerce orders admin page to show the customers user role?
Thanks for your time
Darren
Strugglinjg to get any PHP snippets ive found to work

Here is the code snippet you can add to your functions.php:
/**
* Add custom column.
*
* #param array $columns Columns.
* #return array
*/
function set_custom_edit_shop_order_columns( $columns ) {
$columns['user_role'] = __( 'Role', 'your-text-domain' );
return $columns;
}
add_filter( 'manage_shop_order_posts_columns', 'set_custom_edit_shop_order_columns', 100, 1 );
/**
* Add data to custom column.
*
* #param string $column Column slug.
* #param id $post_id Post ID.
*/
function custom_shop_order_column( $column, $post_id ) {
if ( 'user_role' === $column ) {
$order_user = get_post_meta( $post_id, '_customer_user', true );
if ( ! empty( $order_user ) ) {
$user = get_user_by( 'ID', $order_user );
if ( ! empty( $user ) ) {
echo implode( ', ', ( array ) $user->roles );
}
}
}
}
add_action( 'manage_shop_order_posts_custom_column', 'custom_shop_order_column', 100, 2 );
This will only work if you have not opted in for High-Performance Order Storage (HPOS), otherwise you may have to tweak custom_shop_order_column() method to retrieve data from new custom order meta table.

Related

How can output the slug of product with custom base slug

first of all thx to everyone who put answers here and to all the staff of stackoverflow.
I write a class(copy paste and mod) of WC_duplicate_product off woocommerce in order to put a meta on duplicates and to generate a slug wit base as "https://website.com/slug-base/product-name", but I cant acomplish the part of slug-base. If anybody can help me i'll appreciate.
This is my code, feel free to use and mod:
/**
* Function to create the duplicate of the product.
*
* #param WC_Product $product The product to duplicate.
* #return WC_Product The duplicate.
*/
public function product_duplicate( $product ) {
/**
* Filter to allow us to exclude meta keys from product duplication..
*
* #param array $exclude_meta The keys to exclude from the duplicate.
* #param array $existing_meta_keys The meta keys that the product already has.
* #since 2.6
*/
$meta_to_exclude = array_filter(
apply_filters(
'woocommerce_duplicate_product_exclude_meta',
array(),
array_map(
function ( $datum ) {
return $datum->key;
},
$product->get_meta_data()
)
)
);
$duplicate = clone $product;
$duplicate->set_id( 0 );
$char = 47;
/* translators: %s contains the name of the original product. */
$duplicate->set_name( sprintf( '%s', $duplicate->get_name()) );
$duplicate->set_total_sales( 0 );
if ( '' !== $product->get_sku( 'edit' ) ) {
$duplicate->set_sku( wc_product_generate_unique_sku( 0, $product->get_sku( 'edit' ) ) );
}
$duplicate->set_status( 'draft' );
$duplicate->set_date_created( null );
$duplicate->set_slug( 'vendor'.sprintf( '%c', $char).'' );
$duplicate->set_rating_counts( 0 );
$duplicate->set_average_rating( 0 );
$duplicate->set_review_count( 0 );
$duplicate->add_meta_data( '_is_clone', 'true' );
foreach ( $meta_to_exclude as $meta_key ) {
$duplicate->delete_meta_data( $meta_key );
}
/**
* This action can be used to modify the object further before it is created - it will be passed by reference.
*
* #since 3.0
*/
do_action( 'woocommerce_product_duplicate_before_save', $duplicate, $product );
// Save parent product.
$duplicate->save();
// Duplicate children of a variable product.
if ( ! apply_filters( 'woocommerce_duplicate_product_exclude_children', false, $product ) && $product->is_type( 'variable' ) ) {
foreach ( $product->get_children() as $child_id ) {
$child = wc_get_product( $child_id );
$child_duplicate = clone $child;
$child_duplicate->set_parent_id( $duplicate->get_id() );
$child_duplicate->set_id( 0 );
$child_duplicate->set_date_created( null );
// If we wait and let the insertion generate the slug, we will see extreme performance degradation
// in the case where a product is used as a template. Every time the template is duplicated, each
// variation will query every consecutive slug until it finds an empty one. To avoid this, we can
// optimize the generation ourselves, avoiding the issue altogether.
$this->generate_unique_slug( $child_duplicate );
if ( '' !== $child->get_sku( 'edit' ) ) {
$child_duplicate->set_sku( wc_product_generate_unique_sku( 0, $child->get_sku( 'edit' ) ) );
}
foreach ( $meta_to_exclude as $meta_key ) {
$child_duplicate->delete_meta_data( $meta_key );
}
/**
* This action can be used to modify the object further before it is created - it will be passed by reference.
*
* #since 3.0
*/
do_action( 'woocommerce_product_duplicate_before_save', $child_duplicate, $child );
$child_duplicate->save();
}
// Get new object to reflect new children.
$duplicate = wc_get_product( $duplicate->get_id() );
}
return $duplicate;
}
this is teh part of code that I need to polish to get the desired slug, so when i run this clas, always obtain https://website.com/slug-baseproduct-name

Add Woocommerce Subscription switch to cart programmatically

I'm looking for a way to programmatically add a switch between two Woocommerce subscription variations to the cart.
We're building a headless WP site, so I don't want to do it with a link, as described in this question
I've tried the following simple way, but it won't allow it that way, since the user is already subscribed:
WC()->cart->add_to_cart( 1907, 1, 1908 );
I want to mimic what is happening when the user goes to the upgrade/downgrade page, selects a new variation and presses Switch subscription. Usually that means that the user is sent to checkout with the switch in cart, I just want it to be added to the cart, since we have our own checkout.
The main issue is that Woocommerce thinks that a subscription product is unpurchaseable when it is added to the cart any other way than through the subscription switch form. The form sends a couple of GET-parameters which sends WC through some extra validation, and then allows the item to be added to the cart if everything else is valid.
My solution to this is to mimic this validation with some functions of my own, mostly stolen from the subscription plugin.
/**
* Must be set to true before programmatically adding subscription switch to cart.
*
* #var bool
*/
$kbhl_adding_switch_to_cart = false;
/**
* Array filled with data about current subscription.
* Should only be retrieved by kbhl_get_current_subscription_data().
*
* #var array
*/
$kbhl_global_current_subscription_data = array();
/**
* Cache whether a given product is purchasable or not to save running lots of queries for the same product in the same request
*
* $is_purchasable_cache taken from plugins\woocommerce-subscriptions\includes\class-wcs-limiter.php
*
* #var array
*/
$kbhl_purchasable_cache = array();
/**
* $user_subscriptions_to_product taken from plugins\woocommerce-subscriptions\includes\class-wcs-limiter.php
*
* #var array
*/
$kbhl_user_subscriptions_to_product = array();
/**
* If a product is being marked as not purchasable because it is limited and the customer has a subscription,
* but the current request is to switch the subscription, then mark it as purchasable.
*
* Function is_purchasable_switch() taken from plugins\woocommerce-subscriptions\includes\class-wcs-limiter.php
*
* #param bool $is_purchasable Current purchasable status.
* #param obj $product Product being checked.
*
* #return bool New purchasable status.
*/
function kbhl_is_purchasable_switch( $is_purchasable, $product ) {
global $kbhl_purchasable_cache;
$kbhl_current_subscription_data = kbhl_get_current_subscription_data();
// Only process this filter if running custom add switch function.
if ( ! empty( $kbhl_current_subscription_data['id'] ) ) {
return $is_purchasable;
}
$product_key = wcs_get_canonical_product_id( $product );
// Set an empty cache if one isn't set yet.
if ( ! isset( $kbhl_purchasable_cache[ $product_key ] ) ) {
$kbhl_purchasable_cache[ $product_key ] = array();
}
// Exit early if we've already determined this product's purchasability via switching.
if ( isset( $kbhl_purchasable_cache[ $product_key ]['switch'] ) ) {
return $kbhl_purchasable_cache[ $product_key ]['switch'];
}
// If the product is already purchasble, we don't need to determine it's purchasibility via switching/auto-switching.
if ( true === $is_purchasable || ! is_user_logged_in() || ! wcs_is_product_switchable_type( $product ) || ! WC_Subscriptions_Product::is_subscription( $product->get_id() ) ) {
$kbhl_purchasable_cache[ $product_key ]['switch'] = $is_purchasable;
return $kbhl_purchasable_cache[ $product_key ]['switch'];
}
$user_id = get_current_user_id();
$product_limitation = wcs_get_product_limitation( $product );
if ( 'no' == $product_limitation || ! wcs_user_has_subscription( $user_id, $product->get_id(), wcs_get_product_limitation( $product ) ) ) {
$kbhl_purchasable_cache[ $product_key ]['switch'] = $is_purchasable;
return $kbhl_purchasable_cache[ $product_key ]['switch'];
}
// Adding to cart.
if ( array_key_exists( $kbhl_current_subscription_data['id'], kbhl_get_user_subscriptions_to_product( $product, $user_id, $product_limitation ) ) ) {
$is_purchasable = true;
}
$kbhl_purchasable_cache[ $product_key ]['switch'] = $is_purchasable;
return $kbhl_purchasable_cache[ $product_key ]['switch'];
}
add_filter( 'woocommerce_subscription_is_purchasable', 'kbhl_is_purchasable_switch', 13, 2 );
/**
* Gets a list of the customer subscriptions to a product with a particular limited status.
*
* Function get_user_subscriptions_to_product() taken from plugins\woocommerce-subscriptions\includes\class-wcs-limiter.php
*
* #param WC_Product|int $product The product object or product ID.
* #param int $user_id The user's ID.
* #param string $limit_status The limit status.
*
* #return WC_Subscription[] An array of a customer's subscriptions with a specific status and product.
*/
function kbhl_get_user_subscriptions_to_product( $product, $user_id, $limit_status ) {
global $user_subscriptions_to_product;
$product_id = is_object( $product ) ? $product->get_id() : $product;
$cache_key = "{$product_id}_{$user_id}_{$limit_status}";
if ( ! isset( $user_subscriptions_to_product[ $cache_key ] ) ) {
// Getting all the customers subscriptions and removing ones without the product is more performant than querying for subscriptions with the product.
$subscriptions = wcs_get_subscriptions(
array(
'customer_id' => $user_id,
'status' => $limit_status,
)
);
foreach ( $subscriptions as $subscription_id => $subscription ) {
if ( ! $subscription->has_product( $product_id ) ) {
unset( $subscriptions[ $subscription_id ] );
}
}
$user_subscriptions_to_product[ $cache_key ] = $subscriptions;
}
return $user_subscriptions_to_product[ $cache_key ];
}
/**
* When a subscription switch is added to the cart, store a record of pertinent meta about the switch.
*
* #since 1.4
*/
/**
* When a subscription switch is added to the cart, store a record of pertinent meta about the switch.
*
* Function set_switch_details_in_cart() taken from plugins\woocommerce-subscriptions\includes\class-wc-subscriptions-switcher.php
*
* #param array $cart_item_data Current cart item data.
* #param int $product_id ID of current product.
* #param int $variation_id ID of current product variation.
*
* #return array Updated cart item data.
*/
function kbhl_set_switch_details_in_cart( $cart_item_data, $product_id, $variation_id ) {
try {
$kbhl_current_subscription_data = kbhl_get_current_subscription_data();
if ( empty( $kbhl_current_subscription_data['id'] ) || empty( $kbhl_current_subscription_data['item'] ) ) {
return $cart_item_data;
}
$subscription = wcs_get_subscription( $kbhl_current_subscription_data['id'] );
// Requesting a switch for someone elses subscription.
if ( ! current_user_can( 'switch_shop_subscription', $subscription->get_id() ) ) {
wc_add_notice( __( 'You can not switch this subscription. It appears you do not own the subscription.', 'woocommerce-subscriptions' ), 'error' );
WC()->cart->empty_cart( true );
return array();
}
$item = wcs_get_order_item( absint( $kbhl_current_subscription_data['item'] ), $subscription );
// Else it's a valid switch.
$product = wc_get_product( $item['product_id'] );
$parent_products = WC_Subscriptions_Product::get_parent_ids( $product );
$child_products = array();
if ( ! empty( $parent_products ) ) {
foreach ( $parent_products as $parent_id ) {
$child_products = array_unique( array_merge( $child_products, wc_get_product( $parent_id )->get_children() ) );
}
}
if ( $product_id != $item['product_id'] && ! in_array( $item['product_id'], $child_products ) ) {
return $cart_item_data;
}
$next_payment_timestamp = $subscription->get_time( 'next_payment' );
// If there are no more payments due on the subscription, because we're in the last billing period, we need to use the subscription's expiration date, not next payment date.
if ( false == $next_payment_timestamp ) {
$next_payment_timestamp = $subscription->get_time( 'end' );
}
$cart_item_data['subscription_switch'] = array(
'subscription_id' => $subscription->get_id(),
'item_id' => absint( $kbhl_current_subscription_data['item'] ),
'next_payment_timestamp' => $next_payment_timestamp,
'upgraded_or_downgraded' => '',
);
return $cart_item_data;
} catch ( Exception $e ) {
wc_add_notice( __( 'There was an error locating the switch details.', 'woocommerce-subscriptions' ), 'error' );
WC()->cart->empty_cart( true );
return array();
}
}
add_filter( 'woocommerce_add_cart_item_data', 'kbhl_set_switch_details_in_cart', 11, 3 );
/**
* Gets subscription data for current user.
*
* #return array Subscription data, also stored to global variable $kbhl_global_current_subscription_data
*/
function kbhl_get_current_subscription_data() {
global $kbhl_adding_switch_to_cart, $kbhl_global_current_subscription_data;
if ( ! $kbhl_adding_switch_to_cart ) {
return array();
}
if ( ! empty( $kbhl_global_current_subscription_data ) ) {
return $kbhl_global_current_subscription_data;
}
$subscription_data = array();
$subs = wcs_get_users_subscriptions();
if ( ! empty( $subs ) ) {
foreach ( $subs as $sub ) {
$subscription_data['id'] = $sub->get_id();
foreach ( $sub->get_items() as $item_id => $item ) {
$subscription_data['item'] = $item_id;
break; // There should only be 1 order item.
}
break; // There should only be 1 subscription.
}
}
$kbhl_global_current_subscription_data = $subscription_data;
return $kbhl_global_current_subscription_data;
}
With this added you can add the switch to the cart as follows:
global $kbhl_adding_switch_to_cart; // If run inside a function.
WC()->cart->empty_cart( true );
$kbhl_adding_switch_to_cart = true;
WC()->cart->add_to_cart( 1907, 1, 1927 );
$kbhl_adding_switch_to_cart = false; // Reset after to get back to default validation.

WooCommerce Orders: Is it possible to add another column and populate it with custom meta fields from Users?

So short version is that I am trying to add an extra column in the orders page and have it populated with the custom field I have created for the users on the site (The name for the custom field is account_manager)
What I'm trying to achieve is for it display the customers account manager in a column in the orders section. Bit of a strange request I know!
I had a look at a few guides and tutorials regarding columns and meta data but it all seemed to be regarding the orders rather than data from the customer directly.
Any help would be greatly appreciated. I don't mind having a go, I just need a little guidance :)
I've tried this but it's not returning any values
function wc_orders_add_account_manager_column($columns)
{
$new_columns = [];
foreach ( $columns as $column_name => $column_info ) {
$new_columns[ $column_name ] = $column_info;
if ( 'order_status' === $column_name ) { // Change order_status to manage column orders
$new_columns['account_manager'] = 'Account Manager';
}
}
return $new_columns;
}
add_filter( 'manage_edit-shop_order_columns', 'wc_orders_add_account_manager_column', 20 );
/**
* Adds 'account_manager' column content to 'Orders' page
*
* #param string $column name of column being displayed
*/
function wc_orders_add_account_manager_column_content($column)
{
global $post;
$order_id = $post->ID;
// Get an instance of the WC_Order object
$order = wc_get_order($order_id);
// Get the user ID from WC_Order methods
$user_id = $order->get_customer_id(); // or $order->get_customer_id();
$meta = get_user_meta($user_id, 'account_manager', true);
return $meta;
if ( 'account_manager' === $columns ) {
echo $meta ;
} else {
echo "Not Valid!";
}
}
add_action( 'manage_shop_order_posts_custom_column', 'wc_orders_add_account_manager_column_content' );
I'm assuming you have stored this 'account_manager' as an order meta on postmeta table. You need to use manage_edit-shop_order_columns filter hook to add the new column to admin orders page and manage_shop_order_posts_custom_column action hook to populate this column.
/**
* Adds 'account_manager' column header to 'Orders' page immediately after 'Order Status' and before 'Total' column.
*
* #param array $columns
* #return array
*/
function wc_orders_add_account_manager_column($columns)
{
$new_columns = [];
foreach ( $columns as $column_name => $column_info ) {
$new_columns[ $column_name ] = $column_info;
if ( 'order_status' === $column_name ) { // Change order_status to manage column orders
$new_columns['account_manager'] = 'Account Manager';
}
}
return $new_columns;
}
add_filter( 'manage_edit-shop_order_columns', 'wc_orders_add_account_manager_column', 20 );
/**
* Adds 'account_manager' column content to 'Orders' page
*
* #param string $column name of column being displayed
*/
function wc_orders_add_account_manager_column_content($column)
{
global $post;
$order = wc_get_order( $post->ID );
$user_id = $order->get_customer_id(); // or $order->get_customer_id();
$meta = get_user_meta($user_id, 'account_manager', true);
if ( 'account_manager' === $column ) {
echo $meta ? $meta : 'Not Valid!';
}
}
add_action( 'manage_shop_order_posts_custom_column', 'wc_orders_add_account_manager_column_content' );
Tested & It's Working
Note: As I mentioned in the code comments, you can change the order of the columns by changing order_status in this code block:
if ( 'order_status' === $column_name ) {
$new_columns['account_manager'] = 'Account Manager';
}
In this case, our new account_manager column will display after the order_status column

How to select Wordpress post category instead of type in functions.php query

How would I need to adjust the following code snippet, so it does not exclude Wordpress posts by post type, but by post category?
More specifically, I want to exclude posts from the Wordpress post category with the id 4 in my functions.php file.
<?php
/**
* #param bool $should_index
* #param WP_Post $post
*
* #return bool
*/
function exclude_post_types( $should_index, WP_Post $post )
{
// Add all post types you don't want to make searchable.
$excluded_post_types = array( 'page' );
if ( false === $should_index ) {
return false;
}
return ! in_array( $post->post_type, $excluded_post_types, true );
}
add_filter( 'test_should_index_searchable_post', 'exclude_post_types', 10, 2 );
Use pre_get_posts. Codex link for pre_get_posts
function exclude_category_type_from_search( $query ) {
if ( $query->is_search ) {
$query->set( 'cat', '-22, -21' );
}
}
add_action( 'pre_get_posts', 'exclude_category_type_from_search', 10 );

WordPress PHP 'printf' giving two values

I'm running WordPress 4.9.6 with BuddyPress and BuddyPress XProfile plugin.
XProfile is getting the users location and returning it as a hyperlink in their profile to search the rest of the site with the same location tag.
The issue I'm getting is the PHP script is returning the location plus a number which changes between 69, 76, and 22.
This is the code that I'm running to get the location:
/**
* Modify the appearance of value.
*
* #param string $field_value Original value of field.
* #param int $field_id Id of field.
*
* #return string Value formatted
*/
public static function display_filter( $field_value, $field_id = 0 ) {
if ( empty( $field_value ) ) {
return;
}
$term_id = absint( $field_value );
$tax = self::get_selected_taxonomy( $field_id );
$term = get_term( $term_id, $tax );
if ( ! $term || is_wp_error( $term ) ) {
return '';
}
return printf( '%2$s', esc_url( get_term_link( $term, $tax ) ), esc_html( $term->name ) );
}
/**
* Get the terms content.
*
* #param int $field_id field id.
*
* #return string
*/
public static function get_selected_taxonomy( $field_id ) {
if ( ! $field_id ) {
return '';
}
return bp_xprofile_get_meta( $field_id, 'field', 'selected_taxonomy', true );
}
}
I changed from sprintf to printf as it was returning the full HTML code.
Since changing to printf, this error has occurred.
What part do I need to amend or remove to lose the number tag being generated, please?
This is a screenshot of the tag plus the number below it

Categories