I am trying to change the styling format of the meta data that woocommerce collects when a product is purchased in my store.
I found the filter that I can hook into.. But I can not figure out how to get it to change the data.
So I hooked into $html = apply_filters( 'woocommerce_display_item_meta', $html, $item, $args );
I can strip the html from the output... But I cant seem to figure out how to edit the $args array with before, after, seperator, echo, autop, label_before, and label_after.
Any help is appriciated!
//Here is the Wooocommerce code I want to change -
if ( ! function_exists( 'wc_display_item_meta' ) ) {
/**
* Display item meta data.
*
* @since 3.0.0
* @param WC_Order_Item $item Order Item.
* @param array $args Arguments.
* @return string|void
*/
function wc_display_item_meta( $item, $args = array() ) {
$strings = array();
$html = '';
$args = wp_parse_args(
$args,
array(
'before' => '<ul class="wc-item-meta"><li>',
'after' => '</li></ul>',
'separator' => '</li><li>',
'echo' => true,
'autop' => false,
'label_before' => '<strong class="wc-item-meta-label">',
'label_after' => ':</strong> ',
)
);
foreach ( $item->get_formatted_meta_data() as $meta_id => $meta ) {
$value = $args['autop'] ? wp_kses_post( $meta->display_value ) : wp_kses_post( make_clickable( trim( $meta->display_value ) ) );
$strings[] = $args['label_before'] . wp_kses_post( $meta->display_key ) . $args['label_after'] . $value;
}
if ( $strings ) {
$html = $args['before'] . implode( $args['separator'], $strings ) . $args['after'];
}
$html = apply_filters( 'woocommerce_display_item_meta', $html, $item, $args );
if ( $args['echo'] ) {
echo $html; // WPCS: XSS ok.
} else {
return $html;
}
}
}
I'd like to change the $args array to this:
'before' => '<span for="booked_product" class="wcfm-title wcfm_title">',
That way the formating will match where the meta data is going.
Here is the code I am using in order to write the order meta details! On the front end, I use the woocommerce product add ons plugin to gather additional information... this code will put it anywhere. I have tested it in several places other than my desired location.
//Function to Write Order Details In Booking Page
function add_more_booking_details() {
///Get Access
global $wp, $WCFM, $WCFMu, $thebooking, $wpdb;
if( !current_user_can( 'manage_bookings_settings' ) && !current_user_can( 'manage_bookings' ) ) {
wcfm_restriction_message_show( "Bookings" );
return;
}
if ( ! is_object( $thebooking ) ) {
if( isset( $wp->query_vars['wcfm-bookings-details'] ) && !empty( $wp->query_vars['wcfm-bookings-details'] ) ) {
$thebooking = get_wc_booking( $wp->query_vars['wcfm-bookings-details'] );
}
}
$booking_id = $wp->query_vars['wcfm-bookings-details'];
if( $booking_id ) {
$post = get_post($booking_id);
$booking = new WC_Booking( $post->ID );
$order = $booking->get_order();
$product_id = $booking->get_product_id( 'edit' );
$resource_id = $booking->get_resource_id( 'edit' );
$customer_id = $booking->get_customer_id( 'edit' );
$product = $booking->get_product( $product_id );
$resource = new WC_Product_Booking_Resource( $resource_id );
$customer = $booking->get_customer();
$statuses = array_unique( array_merge( get_wc_booking_statuses( null, true ), get_wc_booking_statuses( 'user', true ), get_wc_booking_statuses( 'cancel', true ) ) );
$statuses = apply_filters( 'wcfm_allowed_booking_status', $statuses );
}
if( wcfm_is_vendor() ) {
$is_booking_for_vendor = $WCFM->wcfm_vendor_support->wcfm_is_component_for_vendor( $booking_id, 'booking' );
if( !$is_booking_for_vendor ) {
if( apply_filters( 'wcfm_is_show_booking_restrict_message', true, $booking_id ) ) {
wcfm_restriction_message_show( "Restricted Booking" );
}
}
}
?>
<?php
if( $allow_wp_admin_view = apply_filters( 'wcfm_allow_wp_admin_view', true ) ) {
?>
<?php }
if ( $order && is_a( $order, 'WC_Order' ) ) { ?>
<?php }
///Print Order Details
$order_detail = getOrderDetailById($order);
print_r($order_detail);
}
//get order details
if (!function_exists('getOrderDetailById')) {
function getOrderDetailById($id) {
$order = wc_get_order($id);
foreach ($order->get_items() as $item_id => $item) {
$product = $item;
$order_data['line_items'][] =
wc_display_item_meta($item);
}
}
}
//Hook+Call Add Booking Details into Booking Details Block
add_action('wcfm_booking_details_block', 'add_more_booking_details' );
Alright... So the new code provided below (when linked to wp_head just to see it) returns the meta data like this, without the formatting still. Stray Data happening
Something like this should do the trick
add_filter('woocommerce_display_item_meta', function ($html, $item, $args) {
$strings = [];
$html = '';
foreach ($item->get_formatted_meta_data() as $meta_id => $meta) {
$value = $args['autop'] ? wp_kses_post($meta->display_value) : wp_kses_post(make_clickable(trim($meta->display_value)));
$strings[] = $args['label_before'] . wp_kses_post($meta->display_key) . $args['label_after'] . $value;
}
$args['before'] = '<span for="booked_product" class="wcfm-title wcfm">';
$args['after'] = '</span>';
if ($strings)
$html = $args['before'] . implode($args['after'] . $args['before'], $strings) . $args['after'];
return $html;
});
The above example recreates the $strings
variable since this variable is not passed by the filter. We then change the before
and after
values in the $args
array variable and recreate the $html
variable with the new $args
values.
This is not tested but I feel confident it will do what you asked. There might be a better solution on this but this is all I got for now.
Answer extension after additional information provided
So based on the code you just provided I would say you can change this line
$order_data['line_items'][] = wc_display_item_meta($item);
to this
$order_data['line_items'][] = wc_display_item_meta($item, [
'echo' => false,
'before' => '<span for="booked_product" class="wcfm-title wcfm">',
'after' => '</span>',
'seperator' => '</span><span for="booked_product" class="wcfm-title wcfm">'
]);
That should do the trick for you. The wc_display_item_meta
function accepts the $args
argument.
Also the code you provided has many errors, I'm not sure if you removed bits and pieces from the code but anyway here is a re-coded getOrderDetailById
function.
function getOrderDetailById($id)
{
if ($id instanceof WC_Order)
$order = $id;
else
$order = wc_get_order($id);
$order_data['line_items'] = [];
foreach ($order->get_items() as $item_id => $item) {
$order_data['line_items'][] = wc_display_item_meta($item, [
'echo' => false,
'before' => '<span for="booked_product" class="wcfm-title wcfm">',
'after' => '</span>',
'seperator' => '</span><span for="booked_product" class="wcfm-title wcfm">'
]);
}
return $order_data['line_items'];
}
I added the instance check because from what I can see you are passing WC_Order
instance and not the order id. I also added a return statement because I can see that you tried to put getOrderDetailById
into an array but the function wasn't returning any data.
Hope it helps.