Hi I use Woocommerce plugin. All works great, I have added a custom field or attribute to a product which is fine and it shows on the products detail page but my problem is getting this data to come through in the PayPal IPN.
I am trying to edit this code as I believe the custom field data is held in meta but cannot find the id of my custom field or where to add it:
// Cart Contents
$item_loop = 0;
if ( sizeof( $order->get_items() ) > 0 ) {
foreach ( $order->get_items() as $item ) {
if ( $item['qty'] ) {
$item_loop++;
$product = $order->get_product_from_item( $item );
$item_name = $item['name'];
$item_meta = new WC_Order_Item_Meta( $item['item_meta'] );
if ( $meta = $item_meta->display( true, true ) )
$item_name .= ' ( ' . $meta . ' )';
$paypal_args[ 'item_name_' . $item_loop ] = html_entity_decode( $item_name, ENT_NOQUOTES, 'UTF-8' );
$paypal_args[ 'quantity_' . $item_loop ] = $item['qty'];
$paypal_args[ 'amount_' . $item_loop ] = $order->get_item_subtotal( $item, false );
if ( $product->get_sku() )
$paypal_args[ 'item_number_' . $item_loop ] = $product->get_sku();
}
}
}
Need to change script that send "order_id" to PayPal on script to send my custom field to PayPal. That's all.
Appreciate any answers. Thanks.!
Related
I found the following code in an older thread (Shortcode that display all product attributes set for a WooCommerce product) which basicly SHOULD be the solution to what im looking for
function get_product_attributes_shortcode($atts ) {
// Extract shortcode attributes
extract( shortcode_atts( array(
'id' => get_the_ID(),
), $atts, 'display-attributes' ) );
global $product;
if ( ! is_a($product, 'WC_Product') ) {
$product = wc_get_product( $id );
}
if ( is_a($product, 'WC_Product') ) {
$html = []; // Initializing
foreach ( $product->get_attributes() as $attribute => $values ) {
$attribute_name = wc_attribute_label($values->get_name());
$attribute_data = $values->get_data();
$is_taxonomy = $attribute_data['is_taxonomy'];
$option_values = array(); // Initializing
// For taxonomy product attribute values
if( $is_taxonomy ) {
$terms = $values->get_terms(); // Get attribute WP_Terms
// Loop through attribute WP_Term(s)
foreach ( $terms as $term ) {
$term_link = get_term_link( $term, $attribute );
$option_values[] = ''.$term->name.'';
}
}
// For "custom" product attributes values
else {
// Loop through attribute option values
foreach ( $values->get_options() as $term_name ) {
$option_values[] = $term_name;
}
}
$html[] = '<strong>' . $attribute_name . '</strong>: ' . implode(', ', $option_values);
}
return '<div class="product-attributes">' . implode(' | ', $html) . '<div>';
}
}
add_shortcode( 'display-attributes', 'get_product_attributes_shortcode' );
I modified the output part to display the attributes in a table
// Loop through attribute WP_Term(s)
foreach ( $terms as $term ) {
$option_values[] = $term->name;
}
}
// For "custom" product attributes values
else {
// Loop through attribute option values
foreach ( $values->get_options() as $term_name ) {
$option_values[] = $term_name;
}
}
$html[] = '<tr><td class="column-1">' . $attribute_name . '</td><td class="column-2">' . implode(', ', $option_values) . '</td></tr>';
}
return '<h4>Technische Daten</h4><table class="tablepress table produktdatenblatt tablepress-responsive"><tbody class="row-hover">' . implode($html) . '</tbody></table>';
}
}
add_shortcode( 'display_attributes', 'get_product_attributes_shortcode' );
Usage should be like this: [display-attributes] or with a defined product Id [display-attributes id="254"]
But its not showing the attributes from the respective ID i put into the shortcode. Its just showing attributes from one product. I want to use the shortcode on Wordpress Pages and Posts to enrich product descriptions i do.
I tried to figure out if i can fix it myself, but im realy bad when it comes to coding :)
Can somebody help me with this?
I need to display customer Bio in WooCommerce admin order edit pages after the billing address.
Actually I only succeeded to display in a column like that:
With this code:
// Adding a custom new column to admin orders list
add_filter( 'manage_edit-shop_order_columns', 'custom_column_eldest_players', 20 );
function custom_column_eldest_players($columns)
{
$reordered_columns = array();
// Inserting columns to a specific location
foreach( $columns as $key => $column){
$reordered_columns[$key] = $column;
if( $key == 'order_status' ){
// Inserting after "Status" column
$reordered_columns['user-bio'] = __( 'Note client', 'woocommerce');
}
}
return $reordered_columns;
}
// Adding custom fields meta data for the column
add_action( 'manage_shop_order_posts_custom_column' , 'custom_orders_list_column_content', 20, 2 );
function custom_orders_list_column_content( $column, $post_id ) {
if ( 'user-bio' === $column ) {
global $the_order;
echo ( $user = $the_order->get_user() ) ? $user->description : 'n/c';
}
}
But I don't know how to insert in WooCommerce admin order edit pages. Any advice?
Do display the user description on the admin order pages after billing adress you can use the woocommerce_admin_order_data_after_billing_address acton hook.
So you get:
// Display on admin order pages after billing adress
function action_woocommerce_admin_order_data_after_billing_address( $order ) {
// Get user
$user = $order->get_user();
// Initialize
$output = __( 'Bio: ', 'woocommerce' );
// Is a WP user
if ( is_a( $user, 'WP_User' ) ) {
! empty( $user->description ) ? $output .= $user->description : $output .= __( 'n/c', 'woocommerce' );
} else {
$output .= __( 'n/c', 'woocommerce' );
}
// Output
echo $output;
}
add_action( 'woocommerce_admin_order_data_after_billing_address', 'action_woocommerce_admin_order_data_after_billing_address', 10, 1 );
How is it possible to sort WooCommerce products by Advanced Custom Field values?
I've added some custom fields to the back-end and front-end of the website. The front-end implementation in my functions.php looks like so:
add_action( 'woocommerce_before_add_to_cart_form', 'tmy_eventbooking', 20 );
function tmy_eventbooking() {
if( !empty( get_field('datum') ) ) { // if your custom field is not empty…
echo '<p class="acf-info">Findet statt am: <span>' . get_field('datum') . '</span></p>';
}
if( !empty( get_field('datum_ende') ) ) { // if your custom field is not empty…
echo '<p class="acf-info">Bis: <span>' . get_field('datum_ende') . '</span></p>';
}
if( !empty( get_field('veranstaltungsort') ) ) { // if your custom field is not empty…
echo '<p class="acf-info">Ort: <span>' . get_field('veranstaltungsort') . '</span></p>';
}
return;
}
This works fine.
Now I would like to be able to sort products by these ACF fields (type date and text).
If a user clicks for example on a 'date' button or selects a location from a dropdown menu, all events get sorted accordingly. Events are regular WooCommerce service products.
What is a good way to approach this?
You need to use two filter hooks to perform custom sorting in the archive page based on ACF.
Use woocommerce_catalog_orderby filter hooks to add custom date
and location options.
// Add these date and location sorting options on the frontend.
function add_new_custom_postmeta_orderby( $sortby ) {
$sortby['date'] = __( 'Sort by date', 'woocommerce' );
$sortby['location'] = __( 'Sort by location', 'woocommerce' );
return $sortby;
}
add_filter( 'woocommerce_catalog_orderby', 'add_new_custom_postmeta_orderby' );
Use woocommerce_get_catalog_ordering_args filter hook to modified
orderby and order based on option you choosed
function add_custom_postmeta_ordering_args( $sort_args ) {
$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
switch( $orderby_value ) {
case 'date':
$sort_args['orderby'] = 'meta_value_num';
$sort_args['order'] = 'desc';
$sort_args['meta_key'] = 'date';
break;
case 'location':
$sort_args['orderby'] = 'meta_value';
$sort_args['order'] = 'asc';
$sort_args['meta_key'] = 'location';
break;
}
return $sort_args;
}
add_filter( 'woocommerce_get_catalog_ordering_args', 'add_custom_postmeta_ordering_args' );
USEFUL LINKS
custom-sorting-options-ascdesc
I have added a custom column in Woocommerce admin side order listing page to display Ordered item Products name and total Quantity like this -> [http://prntscr.com/p11rdl] by using the following code:
add_filter('manage_edit-shop_order_columns', 'misha_order_items_column' );
function misha_order_items_column( $order_columns ) {
$order_columns['order_products'] = "Qty-Products Name-SKU";
return $order_columns;
}
add_action( 'manage_shop_order_posts_custom_column' , 'misha_order_items_column_cnt' );
function misha_order_items_column_cnt( $colname ) {
global $the_order; // the global order object
if( $colname == 'order_products' ) {
// get items from the order global object
$order_items = $the_order->get_items();
if ( !is_wp_error( $order_items ) ) {
foreach( $order_items as $order_item ) {
echo $order_item['quantity'] .' × '. $order_item['name'] .'<br />';
}
}
}
}
Now I also want to display ordered product SKU number after the product name. So anyone have solution for this then please provide help me.
Thank you,
Ketan
Just replace with follows code snippets to add SKU -
add_action( 'manage_shop_order_posts_custom_column' , 'misha_order_items_column_cnt' );
function misha_order_items_column_cnt( $colname ) {
global $the_order; // the global order object
if( $colname == 'order_products' ) {
// get items from the order global object
$order_items = $the_order->get_items();
if ( !is_wp_error( $order_items ) ) {
foreach( $order_items as $order_item ) {
$product = $order_item->get_product();
// product checking
$sku = ( $product && $product->get_sku() ) ? ' - ' . $product->get_sku() : '';
echo $order_item['quantity'] .' × '. $order_item['name'] . ''. $sku . '<br />';
}
}
}
}
Thank you so much I've found this thread extremely helpful, I couldn't thank the original poster enough as well the help from #itzmekhokan and various other contributors, this community is awesome.
What I'm needing now is to add product shelve location straight after SKU.
I have the below code for location fields but not sure how to amend to the code above to make it work. I'm new to coding in general, but have found snippets of code and made it work so far.
Your help and guidance would be greatly appreciated.
// Add Location field
add_action( 'woocommerce_product_options_stock_fields', 'product_shelf' );
function product_shelf() {
global $woocommerce, $post;
woocommerce_wp_text_input(
array(
'id' => 'product_shelf',
'placeholder' => 'Enter product shelf location here',
'label' => 'Shelf Location',
'description' => 'Shelf location of product',
'desc_tip' => 'true',
)
);
}
// Save location data
add_action( 'woocommerce_process_product_meta', 'product_shelf_data' );
function product_shelf_data( $post_id ) {
// grab the location from $_POST
$product_shelf = isset( $_POST[ 'product_shelf' ] ) ? sanitize_text_field( $_POST[ 'product_shelf' ] ) : '';
// grab the product
$product = wc_get_product( $post_id );
// save the location using WooCommerce built-in functions
$product->update_meta_data( 'product_shelf', $product_shelf_data );
$product->save();
}
I have created a recently viewed script which generated a shortcode which I then inserted into my home page.
The script is designed so that people who may have visited my website and left, once they come back can see instantly what products they had been viewing on their last visit.
I have placed the shortcode [woocommerce_recently_viewed_products]
and have generated the shortcode using the following script:
function rc_woocommerce_recently_viewed_products( $atts, $content = null ) {
// Get shortcode parameters
extract(shortcode_atts(array(
"per_page" => '5'
), $atts));
// Get WooCommerce Global
global $woocommerce;
// Get recently viewed product cookies data
$viewed_products = ! empty( $_COOKIE['woocommerce_recently_viewed'] ) ? (array) explode( '|', $_COOKIE['woocommerce_recently_viewed'] ) : array();
$viewed_products = array_filter( array_map( 'absint', $viewed_products ) );
// If no data, quit
if ( empty( $viewed_products ) )
return __( 'You have not viewed any product yet!', 'rc_wc_rvp' );
// Create the object
ob_start();
wc_setcookie( 'woocommerce_recently_viewed', implode( '|', $viewed_products ) );
}
// Get products per page
if( !isset( $per_page ) ? $number = 4 : $number = $per_page )
// Create query arguments array
$query_args = array(
'posts_per_page' => $number,
'no_found_rows' => 1,
'post_status' => 'publish',
'post_type' => 'product',
'post__in' => $viewed_products,
'orderby' => 'rand'
);
// Add meta_query to query args
$query_args['meta_query'] = array();
// Check products stock status
$query_args['meta_query'][] = $woocommerce->query->stock_status_meta_query();
// Create a new query
$r = new WP_Query($query_args);
// If query return results
if ( $r->have_posts() ) {
$content = '<ul class="rc_wc_rvp_product_list_widget">';
// Start the loop
while ( $r->have_posts()) {
$r->the_post();
global $product;
$content .= '<li>
<a href="' . get_permalink() . '">
' . ( has_post_thumbnail() ? get_the_post_thumbnail( $r->post->ID, 'shop_thumbnail' ) : woocommerce_placeholder_img( 'shop_thumbnail' ) ) . ' ' . get_the_title() . '
</a> ' . $product->get_price_html() . '
</li>';
}
$content .= '</ul>';
}
// Get clean object
$content .= ob_get_clean();
// Return whole content
return $content;
}
// Register the shortcode
add_shortcode("woocommerce_recently_viewed_products",
"rc_woocommerce_recently_viewed_products");
Everything seems to have registered. However,when I test this myself. I view a few products, go back to the homepage where the shortcode is registered and I see the text
You have not viewed any product yet!
I can not figure out what might be missing in order to register and show the products which I or a potential customer may have viewed.
Woocommerce only save the recently viewed cookie IF woocommerce_recently_viewed_products WIDGET is ACTIVE! See code in wc-product-functions.php wc_track_product_view() function.
Code to save the cookie always in functions.php:
/**
* Track product views. Always.
*/
function wc_track_product_view_always() {
if ( ! is_singular( 'product' ) /* xnagyg: remove this condition to run: || ! is_active_widget( false, false, 'woocommerce_recently_viewed_products', true )*/ ) {
return;
}
global $post;
if ( empty( $_COOKIE['woocommerce_recently_viewed'] ) ) { // #codingStandardsIgnoreLine.
$viewed_products = array();
} else {
$viewed_products = wp_parse_id_list( (array) explode( '|', wp_unslash( $_COOKIE['woocommerce_recently_viewed'] ) ) ); // #codingStandardsIgnoreLine.
}
// Unset if already in viewed products list.
$keys = array_flip( $viewed_products );
if ( isset( $keys[ $post->ID ] ) ) {
unset( $viewed_products[ $keys[ $post->ID ] ] );
}
$viewed_products[] = $post->ID;
if ( count( $viewed_products ) > 15 ) {
array_shift( $viewed_products );
}
// Store for session only.
wc_setcookie( 'woocommerce_recently_viewed', implode( '|', $viewed_products ) );
}
remove_action('template_redirect', 'wc_track_product_view', 20);
add_action( 'template_redirect', 'wc_track_product_view_always', 20 );
You need to set the cookie when you are viewing a single product page so use something like this where I set the cookie to equal the product ID I just viewed. In your case you'll need to get the cookie value if it exists then append the new product to the list of products.
function set_user_visited_product_cookie() {
global $post;
if ( is_product() ){
// manipulate your cookie string here, explode, implode functions
wc_setcookie( 'woocommerce_recently_viewed', $post->ID );
}
}
add_action( 'wp', 'set_user_visited_product_cookie' );
Below code to set cookie 'woocommerce_recently_viewed' worked for me. Hope it helps other
$Existing_product_id = $_COOKIE['woocommerce_recently_viewed'];
if ( is_product() )
{
$updated_product_id = $Existing_product_id.'|'.$post->ID;
wc_setcookie( 'woocommerce_recently_viewed', $updated_product_id );
}