For a bookings website I have activated 'Timezones'. The visitor's local time should be displayed. In the booking form everything is working fine. The cart data ($start_time, $end_time) is not being displayed correctly when using the function below.
add_filter( 'woocommerce_get_item_data', 'display_cart_data_wc_bookings', 10, 2 );
function display_cart_data_wc_bookings( $item_data, $cart_item ){
if ( ! empty( $cart_item['booking'] ) ) {
$date_format = apply_filters( 'woocommerce_bookings_date_format', wc_date_format() );
$time_format = apply_filters( 'woocommerce_bookings_time_format', wc_time_format() );
$start_date = apply_filters( 'woocommerce_bookings_get_start_date_with_time', date_i18n( $date_format, $cart_item['booking']['_start_date'] ) );
$start_time = apply_filters( 'woocommerce_bookings_get_start_date_with_time', date_i18n( $time_format, $cart_item['booking']['_start_date'] ) );
$end_time = apply_filters( 'woocommerce_bookings_get_end_date_with_time', date_i18n( $time_format, $cart_item['booking']['_end_date'] ) );
$persons = $cart_item['booking']['_persons'];
$ID = $cart_item['booking']['_booking_id'];
echo '<dt class="titel datum">' . __('Date', 'woocommerce') . '</dt><dd class="data datum">' . esc_html( $start_date ) . '</dd>';
echo '<dt class="titel tijdvak">' . __('Time', 'woocommerce') . '</dt><dd class="data tijdvak">' . esc_html( $start_time ) . ' - ' . esc_html( $end_time ) . '</dd>';
foreach($persons as $person){
echo '<dt class="titel personen">' . __('Persons', 'woocommerce') . '</dt><dd class="data personen">' . esc_html( $person) . '</dd>';
}
echo '<dt class="titel booking_id">' . __('Booking #', 'woocommerce') . '</dt><dd class="data booking_id">' . esc_html( $ID) . '</dd>';
}
}
The output of $start_time and $end_time should be displayed in the visitor's local time. How can I achieve this?
To enable the user time zone jQuery and ajax are necessary. Here are the following steps:
early enabling user WooCommerce session ( WC Session ),
getting the user browser time zone (time zone from user computer or device),
sending that timezone to php via ajax,
grab that time zone in the user WC Session ,
then use it in your code on date and time php functions as date(), date_i18n(), time()…
Once the user time zone is saved in WC Session, all the related code will be auto disabled (as not needed anymore).
The code:
// Early enable customer WC_Session (if not done)
add_action( 'init', 'wc_session_enabler' );
function wc_session_enabler() {
if ( isset(WC()->session) && ! WC()->session->has_session() ) {
WC()->session->set_customer_session_cookie( true );
}
}
// Get the browser user timezone and send it to php (Ajax)
add_action( 'wp_head', 'user_timmezone_js' );
function user_timmezone_js() {
if( ! WC()->session->get('time-zone') ) :
?>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.6/jstz.min.js"></script>
<script type="text/javascript">
jQuery( function($){
if (typeof woocommerce_params === 'undefined')
return false;
var tz = jstz.determine();
$.ajax({
type: "POST",
url: woocommerce_params.ajax_url,
data: ({
'action': 'time_zone',
'timezone': tz.name()
}),
success: function(response) {
console.log('Success: '+response);
}
});
});
</script>
<?php
endif;
}
// function that gets the Ajax data and save it to user WC Session
add_action( 'wp_ajax_time_zone', 'set_session_timezone' );
add_action( 'wp_ajax_nopriv_time_zone', 'set_session_timezone' );
function set_session_timezone() {
if ( isset($_POST['timezone']) && ! empty($_POST['timezone']) ){
WC()->session->set('time-zone', esc_attr($_POST['timezone']) );
echo WC()->session->get('time-zone');
}
die();
}
Code goes in function.php file of your active child theme (or active theme).
Then you will include the following to get and set the time zone:
if( $timezone = WC()->session->get('time-zone') ) {
date_default_timezone_set($timezone);
}
Updated:
Now your code is incorrect when using woocommerce_get_item_data as it's a filter hook and require to return filtered content (not to echo html)…
Try the following instead (untested):
add_filter( 'woocommerce_get_item_data', 'display_cart_data_wc_bookings', 10, 2 );
function display_cart_data_wc_bookings( $item_data, $cart_item ){
if ( isset($cart_item['booking']) && ! empty($cart_item['booking']) && ! is_admin() ) {
// Get and set the user time zone
if( $timezone = WC()->session->get('time-zone') ) {
date_default_timezone_set($timezone);
}
$booking_data = $cart_item['booking'];
$date_format = apply_filters( 'woocommerce_bookings_date_format', wc_date_format() );
$time_format = apply_filters( 'woocommerce_bookings_time_format', wc_time_format() );
$start_date = apply_filters( 'woocommerce_bookings_get_start_date_with_time', date_i18n( $date_format, $booking_data['_start_date'] ) );
$start_time = apply_filters( 'woocommerce_bookings_get_start_date_with_time', date_i18n( $time_format, $booking_data['_start_date'] ) );
$end_time = apply_filters( 'woocommerce_bookings_get_end_date_with_time', date_i18n( $time_format, $booking_data['_end_date'] ) );
$persons = $booking_data['_persons'];
$booking_id = $booking_data['_booking_id'];
$item_data[] = array(
'key' => __('Date', 'woocommerce'),
'value' => esc_html( $start_date ),
'display' => esc_html( $start_date ),
);
$item_data[] = array(
'key' => __('Time', 'woocommerce'),
'value' => esc_html( $start_time ),
'display' => esc_html( $start_time ),
);
$count = 1;
foreach($persons as $person){
$item_data[] = array(
'key' => __('Person', 'woocommerce') . $count,
'value' => esc_html( $person ),
'display' => esc_html( $person ),
);
$count++;
}
$item_data[] = array(
'key' => __('Booking #', 'woocommerce'),
'value' => esc_html( $booking_id ),
'display' => esc_html( $booking_id ),
);
}
return $item_data;
}
Partially based on: How to detect user's timezone?
Its little bit tricky, what we can do is always in back-end deal with UTC time format and from front-end convert the UTC time to local time
to convert the localtime you can find the help here, hope this way you can archive your goal
#LoicTheAztec: Thanks for the update. Still not working. I've updated the code based on file 'class-wc-booking-cart-manager.php':
add_filter( 'woocommerce_get_item_data', 'display_cart_data_wc_bookings', 10, 2 );
function display_cart_data_wc_bookings( $item_data, $cart_item ){
if ( isset($cart_item['booking']) && ! empty($cart_item['booking']) ) {
// Get and set the user time zone
$booking_data = $cart_item['booking'];
if ( ! empty( $booking_data['_booking_id'] ) ) {
$booking = get_wc_booking( $booking_data['_booking_id'] );
if ( wc_should_convert_timezone( $booking ) ) {
$timezone_data = array(
'name' => get_wc_booking_data_label( 'timezone', $cart_item['data'] ),
'value' => str_replace( '_', ' ', $booking->get_local_timezone() ),
'display' => '',
);
}
}
$date_format = apply_filters( 'woocommerce_bookings_date_format', wc_date_format() );
$time_format = apply_filters( 'woocommerce_bookings_time_format', wc_time_format() );
$start_date = date_i18n( get_option( 'date_format' ), $booking->get_start( 'view', true ) );
$start_time = date_i18n( get_option( 'time_format' ), $booking->get_start( 'view', true ) );
$end_time = date_i18n( get_option( 'time_format' ), $booking->get_end( 'view', true ) );
$persons = $booking_data['_persons'];
$booking_id = $booking_data['_booking_id'];
$item_data[] = array(
'key' => __('Booking #', 'woocommerce'),
'value' => esc_html( $booking_id ),
'display' => esc_html( $booking_id ),
);
$item_data[] = array(
'key' => __('Date', 'woocommerce'),
'value' => esc_html( $start_date ),
'display' => esc_html( $start_date ),
);
$item_data[] = array(
'key' => __('Start time', 'woocommerce'),
'value' => esc_html( $start_time ),
'display' => esc_html( $start_time ),
);
$item_data[] = array(
'key' => __('End time', 'woocommerce'),
'value' => esc_html( $end_time ),
'display' => esc_html( $end_time ),
);
$count = 1;
foreach($persons as $person){
$item_data[] = array(
'key' => __('Person(s)', 'woocommerce') . $count,
'value' => esc_html( $person ),
'display' => esc_html( $person ),
);
$count++;
}
if ( ! empty( $timezone_data ) ) {
// Add timezone to the end.
$item_data[] = $timezone_data;
}
}
return $item_data;
With this code step 1 to step 4 in your first comment are not necessary. Tested and it works!
Related
I used the answer from this question to create my custom product tabs:
Custom metabox content displayed in single product additional tabs on Woocommerce
Here's my code:
// Add a custom metabox
add_action( 'add_meta_boxes', 'additional_product_tabs_metabox' );
function additional_product_tabs_metabox()
{
add_meta_box(
'add_product_metabox_additional_tabs',
__( 'Additional product Tabs', 'woocommerce' ),
'additional_product_tabs_metabox_content',
'product',
'normal',
'high'
);
}
// Add custom metabox content
function additional_product_tabs_metabox_content( $post )
{
// Shipping
echo '<h4>' . __( 'Shipping', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_custom_shipping', true );
wp_editor( $value, '_custom_shipping', array( 'editor_height' => 100 ) );
// Color
echo '<br><hr><h4>' . __( 'Color', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_custom_color', true );
wp_editor( $value, '_custom_color', array( 'editor_height' => 100 ) );
// Material
echo '<br><hr><h4>' . __( 'Material', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_custom_material', true );
wp_editor( $value, '_custom_material', array( 'editor_height' => 100 ) );
// Size
echo '<br><hr><h4>' . __( 'Size', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_custom_size', true );
wp_editor( $value, '_custom_size', array( 'editor_height' => 100 ) );
// Nonce field (for security)
echo '<input type="hidden" name="additional_product_tabs_nonce" value="' . wp_create_nonce() . '">';
}
// Save product data
add_action( 'save_post_product', 'save_additional_product_tabs', 10, 1 );
function save_additional_product_tabs( $post_id ) {
// Security check
if ( ! isset( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
return $post_id;
}
//Verify that the nonce is valid.
if ( ! wp_verify_nonce( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
if ( ! current_user_can( 'edit_product', $post_id ) ) {
return $post_id;
}
// Sanitize user input and save the post meta fields values.
if( isset($_POST[ '_custom_shipping' ]) )
update_post_meta( $post_id, '_custom_shipping', wp_kses_post($_POST[ '_custom_shipping' ]) );
if( isset($_POST[ '_custom_color' ]) )
update_post_meta( $post_id, '_custom_color', wp_kses_post($_POST[ '_custom_color' ]) );
if( isset($_POST[ '_custom_material' ]) )
update_post_meta( $post_id, '_custom_material', wp_kses_post($_POST[ '_custom_material' ]) );
if( isset($_POST[ '_custom_size' ]) )
update_post_meta( $post_id, '_custom_size', wp_kses_post($_POST[ '_custom_size' ]) );
}
add_filter( 'woocommerce_product_tabs', 'woo_custom_product_tabs' );
function woo_custom_product_tabs( $tabs ) {
// 1) Removing tabs
unset( $tabs['description'] ); // Remove the description tab
unset( $tabs['additional_information'] ); // Remove the additional information tab
// 2 Adding new tabs and set the right order
//Adds Shipping Tab
$tabs['custom_shipping_tab'] = array(
'title' => __( 'Shipping', 'woocommerce' ),
'priority' => 10,
'callback' => 'woo_custom_shipping_tab_content'
);
// Adds Color Tab
$tabs['custom_color_tab'] = array(
'title' => __( 'Color', 'woocommerce' ),
'priority' => 20,
'callback' => 'woo_custom_color_tab_content'
);
// Adds Material Tab
$tabs['custom_material_tab'] = array(
'title' => __( 'Material', 'woocommerce' ),
'priority' => 30,
'callback' => 'woo_custom_material_tab_content'
);
// Adds Size Tab
$tabs['custom_size_tab'] = array(
'title' => __( 'Size', 'woocommerce' ),
'priority' => 40,
'callback' => 'woo_custom_size_tab_content'
);
return $tabs;
}
function woo_custom_shipping_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_custom_shipping' ) . '</p></div>';
}
function woo_custom_color_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_custom_color' ) . '</p></div>';
}
function woo_custom_material_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_custom_material' ) . '</p></div>';
}
function woo_custom_size_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_custom_size' ) . '</p></div>';
}
Then I added custom code to create vertical tabs and added them after woocommerce_share hook.
/* Vertical Product Tabs */
add_action( 'woocommerce_share', 'woocommerce_output_product_data_tabs', 5 );
function woocommerce_output_product_data_tabs() {
$product_tabs = apply_filters( 'woocommerce_product_tabs', array() );
if ( empty( $product_tabs ) ) {
return;
}
foreach ( $product_tabs as $key => $product_tab ) {
echo '<div id="tab-' . esc_attr( $key ) . '">';
if ( isset( $product_tab[ 'callback' ] ) ) {
call_user_func( $product_tab[ 'callback' ], $key, $product_tab );
}
echo '</div>';
}
}
The result was as follows:
All the tabs have lost titles.
Now tabs are shown after woocommerce_share hook and in their old place. They are just copied.
Question:
How do I fix the code to show the tab titles?
How to fix the code so that the tabs are shown only after the woocommerce_share hook?
I would be glad to have your help!
First of all, I've slightly updated your existing code, to more recent version:
// You can use add_meta_boxes_{post_type} for best practice, so your hook will only run when editing a specific post type. This will only receive 1 parameter – $post
function action_add_meta_boxes_product( $post ) {
add_meta_box(
'add_product_metabox_additional_tabs',
__( 'Additional product Tabs', 'woocommerce' ),
'additional_product_tabs_metabox_content',
'product',
'normal',
'high'
);
}
add_action( 'add_meta_boxes_product', 'action_add_meta_boxes_product', 10, 1 );
// Add custom metabox content
function additional_product_tabs_metabox_content( $post ) {
// Shipping
echo '<h4>' . __( 'Shipping', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_custom_shipping', true );
wp_editor( $value, '_custom_shipping', array( 'editor_height' => 100 ) );
// Color
echo '<br><hr><h4>' . __( 'Color', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_custom_color', true );
wp_editor( $value, '_custom_color', array( 'editor_height' => 100 ) );
// Material
echo '<br><hr><h4>' . __( 'Material', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_custom_material', true );
wp_editor( $value, '_custom_material', array( 'editor_height' => 100 ) );
// Size
echo '<br><hr><h4>' . __( 'Size', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_custom_size', true );
wp_editor( $value, '_custom_size', array( 'editor_height' => 100 ) );
// Nonce field (for security)
echo '<input type="hidden" name="additional_product_tabs_nonce" value="' . wp_create_nonce() . '">';
}
// Save product data
function action_save_post_product( $post_id, $post, $update ) {
// Security check
if ( ! isset( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
return $post_id;
}
// Verify that the nonce is valid.
if ( ! wp_verify_nonce( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
if ( ! current_user_can( 'edit_product', $post_id ) ) {
return $post_id;
}
// Sanitize user input and save the post meta fields values
if ( isset( $_POST[ '_custom_shipping' ] ) )
update_post_meta( $post_id, '_custom_shipping', wp_kses_post( $_POST[ '_custom_shipping' ] ) );
if ( isset( $_POST[ '_custom_color' ] ) )
update_post_meta( $post_id, '_custom_color', wp_kses_post( $_POST[ '_custom_color' ] ) );
if ( isset( $_POST[ '_custom_material' ] ) )
update_post_meta( $post_id, '_custom_material', wp_kses_post( $_POST[ '_custom_material' ] ) );
if ( isset( $_POST[ '_custom_size' ] ) )
update_post_meta( $post_id, '_custom_size', wp_kses_post( $_POST[ '_custom_size' ] ) );
}
add_action( 'save_post_product', 'action_save_post_product', 10, 3 );
Then your biggest mistake is using $product_tabs = apply_filters( 'woocommerce_product_tabs', array() );. This is because not only your call is executed but also the default call of WooCommerce. That's why these are shown twice.
The solution is to simply add your custom tabs via an array that is separate from the default WooCommerce functionality.
So you get:
// Removing DEFAULT tabs
function filter_woocommerce_product_tabs( $tabs ) {
// Remove the description tab
unset( $tabs['description'] );
// Remove the additional information tab
unset( $tabs['additional_information'] );
return $tabs;
}
add_filter( 'woocommerce_product_tabs', 'filter_woocommerce_product_tabs', 100, 1 );
function my_custom_tabs() {
// Initialize
$tabs = array();
// Adds Shipping Tab
$tabs['custom_shipping_tab'] = array(
'title' => __( 'Shipping', 'woocommerce' ),
'priority' => 10,
'callback' => 'woo_custom_shipping_tab_content'
);
// Adds Color Tab
$tabs['custom_color_tab'] = array(
'title' => __( 'Color', 'woocommerce' ),
'priority' => 20,
'callback' => 'woo_custom_color_tab_content'
);
// Adds Material Tab
$tabs['custom_material_tab'] = array(
'title' => __( 'Material', 'woocommerce' ),
'priority' => 30,
'callback' => 'woo_custom_material_tab_content'
);
// Adds Size Tab
$tabs['custom_size_tab'] = array(
'title' => __( 'Size', 'woocommerce' ),
'priority' => 40,
'callback' => 'woo_custom_size_tab_content'
);
return $tabs;
}
function woo_custom_shipping_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_custom_shipping' ) . '</p></div>';
}
function woo_custom_color_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_custom_color' ) . '</p></div>';
}
function woo_custom_material_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_custom_material' ) . '</p></div>';
}
function woo_custom_size_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_custom_size' ) . '</p></div>';
}
function action_woocommerce_share() {
// Call your custom tabs
$product_tabs = my_custom_tabs();
// NOT empty
if ( ! empty( $product_tabs ) ) : ?>
<div class="woocommerce-tabs wc-tabs-wrapper">
<ul class="tabs wc-tabs" role="tablist">
<?php foreach ( $product_tabs as $key => $product_tab ) : ?>
<li class="<?php echo esc_attr( $key ); ?>_tab" id="tab-title-<?php echo esc_attr( $key ); ?>" role="tab" aria-controls="tab-<?php echo esc_attr( $key ); ?>">
<a href="#tab-<?php echo esc_attr( $key ); ?>">
<?php echo wp_kses_post( apply_filters( 'woocommerce_product_' . $key . '_tab_title', $product_tab['title'], $key ) ); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php foreach ( $product_tabs as $key => $product_tab ) : ?>
<div class="woocommerce-Tabs-panel woocommerce-Tabs-panel--<?php echo esc_attr( $key ); ?> panel entry-content wc-tab" id="tab-<?php echo esc_attr( $key ); ?>" role="tabpanel" aria-labelledby="tab-title-<?php echo esc_attr( $key ); ?>">
<?php
if ( isset( $product_tab['callback'] ) ) {
call_user_func( $product_tab['callback'], $key, $product_tab );
}
?>
</div>
<?php endforeach; ?>
<?php do_action( 'woocommerce_product_after_tabs' ); ?>
</div>
<?php endif;
}
add_action( 'woocommerce_share', 'action_woocommerce_share' );
Note: displaying the tabs horizontally or vertically is then a matter of applying CSS, this is theme related. Optionally you can add extra classes to the output of these tabs.
Thanks to these two posts I have come up with this solution for adding multiple tabs to Woocommerce product detail page.
Editing Custom product tab content in Woocommerce Admin product pages
Adding multiple tabs to WooCommerce single product pages
However, I am still having trouble saving the data and can't figure out how to make each meta_box save. I thought of a foreach statement but I'm not that well versed in PHP to know how the syntax is.
Here is my code. I have 6 tabs I added which show up on the page, and the meta boxes show up in the admin panel but they won't save any input. I only have one that is trying to save right now and I feel like the problem is in the save function.
add_action( 'add_meta_boxes', 'create_custom_meta_box' );
if ( ! function_exists( 'create_custom_meta_box' ) )
{
function create_custom_meta_box()
{
add_meta_box(
'custom_product_cost_field',
__( 'Cost and Performance Tab', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
add_meta_box(
'custom_product_environment_field',
__( 'Environment Tab', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
add_meta_box(
'custom_product_dilution_field',
__( 'Dilution Directions Tab', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
add_meta_box(
'custom_product_packaging_field',
__( 'Packaging and Handling', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
add_meta_box(
'custom_product_application_field',
__( 'Use and Application Tab', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
add_meta_box(
'custom_product_specification_field',
__( 'Product Specification Tab', 'woocommerce' ),
'add_custom_content_meta_box',
'product',
'normal',
'high'
);
}
}
// Custom metabox content in admin product pages
if ( ! function_exists( 'add_custom_content_meta_box' ) )
{
function add_custom_content_meta_box( $post )
{
$value = get_post_meta( $post->ID, 'cost_performance_tab', true ) ? get_post_meta( $post->ID, 'cost_performance_tab', true ) : '';
wp_editor( $value, 'custom_cost_performance_tab', array( 'editor_height' => 100 ) );
echo '<input type="hidden" name="custom_product_field_nonce" value="' . wp_create_nonce() . '">';
}
}
//Save the data of the Meta field
add_action( 'save_post', 'save_custom_content_meta_box', 10, 1 );
if ( ! function_exists( 'save_custom_content_meta_box' ) )
{
function save_custom_content_meta_box( $post_id ) {
// We need to verify this with the proper authorization (security stuff).
// Check if our nonce is set.
if ( ! isset( $_POST[ 'custom_product_field_nonce' ] ) ) {
return $post_id;
}
$nonce = $_REQUEST[ 'custom_product_field_nonce' ];
//Verify that the nonce is valid.
if ( ! wp_verify_nonce( $nonce ) ) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// Check the user's permissions.
if ( 'page' == $_POST[ 'post_type' ] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return $post_id;
}
} else {
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
}
// --- Its safe for us to save the data ! --- //
// Sanitize user input and update the meta field in the database.
update_post_meta( $post_id, 'cost_performance_tab', wp_kses_post($_POST[ 'custom_cost_performance_tab' ]) );
}
}
add_filter( 'woocommerce_product_tabs', 'woo_custom_product_tabs' );
function woo_custom_product_tabs( $tabs ) {
// 1) Removing tabs
unset( $tabs['description'] ); // Remove the description tab
// unset( $tabs['reviews'] ); // Remove the reviews tab
unset( $tabs['additional_information'] ); // Remove the additional information tab
// 2 Adding new tabs and set the right order
//Attribute Cost and Performance tab
$tabs['cost_performance_tab'] = array(
'title' => __( 'Cost + Performance', 'woocommerce' ),
'priority' => 100,
'callback' => 'woo_cost_performance_tab_content'
);
// Adds the environment tab
$tabs['environment_tab'] = array(
'title' => __( 'Environment', 'woocommerce' ),
'priority' => 110,
'callback' => 'woo_environment_tab_content'
);
// Adds the dilution tab
$tabs['dilution_tab'] = array(
'title' => __( 'Suggested Dilution Directions', 'woocommerce' ),
'priority' => 120,
'callback' => 'woo_dilution_tab_content'
);
// Adds the packaging tab
$tabs['packaging_tab'] = array(
'title' => __( 'Packaging + Handling', 'woocommerce' ),
'priority' => 120,
'callback' => 'woo_packaging_tab_content'
);
// Adds the application tab
$tabs['application_tab'] = array(
'title' => __( 'Use + Application', 'woocommerce' ),
'priority' => 120,
'callback' => 'woo_application_tab_content'
);
// Adds the application tab
$tabs['specification_tab'] = array(
'title' => __( 'Product Specification', 'woocommerce' ),
'priority' => 120,
'callback' => 'woo_specification_tab_content'
);
return $tabs;
}
function woo_cost_performance_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'cost_performance_tab' ,true ).'</p></div>';
}
function woo_environment_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'environment_tab' ,true ).'</p></div>';
}
function woo_dilution_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'dilution_tab' ,true ).'</p></div>';
}
function woo_packaging_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'packaging_tab' ,true ).'</p></div>';
}
function woo_application_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'application_tab' ,true ).'</p></div>';
}
function woo_specification_tab_content() {
// The new tab content
$prod_id = get_the_ID();
echo'<div><p>'.get_post_meta( get_the_ID(), 'specification_tab' ,true ).'</p></div>';
}
You don't need 6 metaboxes in admin product edit pages and there is a lot of mistakes… Try the following instead:
// Add a custom metabox
add_action( 'add_meta_boxes', 'additional_product_tabs_metabox' );
function additional_product_tabs_metabox()
{
add_meta_box(
'add_product_metabox_additional_tabs',
__( 'Additional product Tabs', 'woocommerce' ),
'additional_product_tabs_metabox_content',
'product',
'normal',
'high'
);
}
// Add custom metabox content
function additional_product_tabs_metabox_content( $post )
{
// Cost and Performance
echo '<h4>' . __( 'Cost and Performance', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_cost_performance', true );
wp_editor( $value, '_cost_performance', array( 'editor_height' => 100 ) );
// Environment
echo '<br><hr><h4>' . __( 'Environment', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_environment', true );
wp_editor( $value, '_environment', array( 'editor_height' => 100 ) );
// Dilution Directions
echo '<br><hr><h4>' . __( 'Dilution Directions', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_dilution_directions', true );
wp_editor( $value, '_dilution_directions', array( 'editor_height' => 100 ) );
// Environment
echo '<br><hr><h4>' . __( 'Packaging and Handling', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_packaging_and_handling', true );
wp_editor( $value, '_packaging_and_handling', array( 'editor_height' => 100 ) );
// Use and Application
echo '<br><hr><h4>' . __( 'Use and Application', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_use_and_application', true );
wp_editor( $value, '_use_and_application', array( 'editor_height' => 100 ) );
// Environment
echo '<br><hr><h4>' . __( 'Specification', 'woocommerce' ) . '</h4>';
$value = get_post_meta( $post->ID, '_specification', true );
wp_editor( $value, '_specification', array( 'editor_height' => 100 ) );
// Nonce field (for security)
echo '<input type="hidden" name="additional_product_tabs_nonce" value="' . wp_create_nonce() . '">';
}
// Save product data
add_action( 'save_post_product', 'save_additional_product_tabs', 10, 1 );
function save_additional_product_tabs( $post_id ) {
// Security check
if ( ! isset( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
return $post_id;
}
//Verify that the nonce is valid.
if ( ! wp_verify_nonce( $_POST[ 'additional_product_tabs_nonce' ] ) ) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
if ( ! current_user_can( 'edit_product', $post_id ) ) {
return $post_id;
}
// Sanitize user input and save the post meta fields values.
if( isset($_POST[ '_cost_performance' ]) )
update_post_meta( $post_id, '_cost_performance', wp_kses_post($_POST[ '_cost_performance' ]) );
if( isset($_POST[ '_environment' ]) )
update_post_meta( $post_id, '_environment', wp_kses_post($_POST[ '_environment' ]) );
if( isset($_POST[ '_dilution_directions' ]) )
update_post_meta( $post_id, '_dilution_directions', wp_kses_post($_POST[ '_dilution_directions' ]) );
if( isset($_POST[ '_packaging_and_handling' ]) )
update_post_meta( $post_id, '_packaging_and_handling', wp_kses_post($_POST[ '_packaging_and_handling' ]) );
if( isset($_POST[ '_use_and_application' ]) )
update_post_meta( $post_id, '_use_and_application', wp_kses_post($_POST[ '_use_and_application' ]) );
if( isset($_POST[ '_specification' ]) )
update_post_meta( $post_id, '_specification', wp_kses_post($_POST[ '_specification' ]) );
}
add_filter( 'woocommerce_product_tabs', 'woo_custom_product_tabs' );
function woo_custom_product_tabs( $tabs ) {
// 1) Removing tabs
unset( $tabs['description'] ); // Remove the description tab
unset( $tabs['additional_information'] ); // Remove the additional information tab
// 2 Adding new tabs and set the right order
//Attribute Cost and Performance tab
$tabs['cost_performance_tab'] = array(
'title' => __( 'Cost + Performance', 'woocommerce' ),
'priority' => 10,
'callback' => 'woo_cost_performance_tab_content'
);
// Adds the environment tab
$tabs['environment_tab'] = array(
'title' => __( 'Environment', 'woocommerce' ),
'priority' => 20,
'callback' => 'woo_environment_tab_content'
);
// Adds the dilution tab
$tabs['dilution_tab'] = array(
'title' => __( 'Suggested Dilution Directions', 'woocommerce' ),
'priority' => 30,
'callback' => 'woo_dilution_tab_content'
);
// Adds the packaging tab
$tabs['packaging_tab'] = array(
'title' => __( 'Packaging + Handling', 'woocommerce' ),
'priority' => 40,
'callback' => 'woo_packaging_tab_content'
);
// Adds the application tab
$tabs['application_tab'] = array(
'title' => __( 'Use + Application', 'woocommerce' ),
'priority' => 60,
'callback' => 'woo_application_tab_content'
);
// Adds the specification tab
$tabs['specification_tab'] = array(
'title' => __( 'Specification', 'woocommerce' ),
'priority' => 70,
'callback' => 'woo_specification_tab_content'
);
$tabs['reviews']['priority'] = 80;
return $tabs;
}
function woo_cost_performance_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_cost_performance' ) . '</p></div>';
}
function woo_environment_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_environment' ) . '</p></div>';
}
function woo_dilution_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_dilution_directions' ) . '</p></div>';
}
function woo_packaging_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_packaging_and_handling' ) . '</p></div>';
}
function woo_application_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_use_and_application' ) . '</p></div>';
}
function woo_specification_tab_content() {
global $product;
echo'<div><p>'. $product->get_meta( '_specification' ) . '</p></div>';
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.
I am working on my WordPress / Woocommerce website.
How can I add a constant value, which would always be the first value in the drop down list which consists of times (hour:minute). This constant value at the top should say "As soon as possible".
Here is the code which generates the form itself:
public function time_select( $checkout ) {
echo '<div id="local-pickup-time-select"><h2>' . __( 'Delivery Time', $this->plugin_slug ) . '</h2>';
woocommerce_form_field( 'local_pickup_time_select', array(
'type' => 'select',
'class' => array( 'local-pickup-time-select-field form-row-wide' ),
'label' => __( 'Delivery Time', $this->plugin_slug ),
'required' => true,
'options' => self::create_hour_options()
), $checkout->get_value( 'local_pickup_time_select' ));
self::create_hour_options();
echo '</div>';
}
public function pickup_time_select_translatable( $value ) {
$value = preg_replace('/(\d)_(\d)/','$1:$2', $value);
$value = explode('_', $value);
$return = __( $value[0], $this->plugin_slug ). ' ' .$value[1];
return $return;
}
public function create_hour_options() {
// Make sure we have a time zone set
$offset = get_option( 'gmt_offset' );
$timezone_setting = get_option( 'timezone_string' );
if ( $timezone_setting ) {
date_default_timezone_set( get_option( 'timezone_string', 'America/New_York' ) );
}
else {
$timezone = timezone_name_from_abbr( null, $offset * 3600, true );
if( $timezone === false ) $timezone = timezone_name_from_abbr( null, $offset * 3600, false );
date_default_timezone_set( $timezone );
}
// Get days closed textarea from settings, explode into an array
$closing_days_raw = trim( get_option( 'local_pickup_hours_closings' ) );
$closing_days = explode( "\n", $closing_days_raw );
$closing_days = array_filter( $closing_days, 'trim' );
// Get delay, interval, and number of days ahead settings
$delay_minutes = get_option( 'local_pickup_delay_minutes', 60 );
$interval = get_option( 'local_pickup_hours_interval', 30 );
$num_days_allowed = get_option( 'local_pickup_days_ahead', 1 );
// Setup time variables for calculations
$today_name = strtolower( date( 'l' ) );
$today_date = date( 'm/d/Y' );
// Create an empty array for our dates
$pickup_options = array();
//Translateble days
__( 'Monday', $this->plugin_slug );
__( 'Tuesday', $this->plugin_slug );
__( 'Wednesday', $this->plugin_slug );
__( 'Thursday', $this->plugin_slug );
__( 'Friday', $this->plugin_slug );
__( 'Saturday', $this->plugin_slug );
__( 'Sunday', $this->plugin_slug );
// Add empty option
$pickup_options[''] = __( 'Select time', $this->plugin_slug );
// Loop through all days ahead and add the pickup time options to the array
for ( $i = 0; $i < $num_days_allowed; $i++ ) {
// Get the date of current iteration
$current_day_name = date( 'l', strtotime( "+$i days" ) );
$current_day_name_lower = strtolower( $current_day_name );
// Get the day's opening and closing times
$open_time = get_option( 'local_pickup_hours_' . $current_day_name_lower . '_start', '10:00' );
$close_time = get_option( 'local_pickup_hours_' . $current_day_name_lower . '_end', '19:00' );
// Today
$tStart = strtotime( $open_time );
$tEnd = strtotime( $close_time );
$tNow = $tStart;
$current_time = time();
// Date format based on user settings
$date_format = get_option('time_format');
$date_format_key = preg_replace("/[^\w]+/", "_", $date_format);
// If Closed today or today's pickup times are over, don't allow a pickup option
if ( ( in_array( $today_date, $closing_days ) || ( $current_time >= $tEnd ) ) && $num_days_allowed == 1 ) {
// Set drop down text to let user know store is closed
$pickup_options['closed_today'] = __( 'Closed today, please check back tomorrow!', $this->plugin_slug );
// Hide Order Review so user doesn't order anything today
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_order_review', 10 );
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_checkout_payment', 20 );
}
else {
// Create array of time options to return to woocommerce_form_field
// Today
if ( $i == 0) {
// Check if it's not too late for pickup
if ( $current_time < $tEnd ) {
// Fix tNow if is pickup possible today
if ( $i == 0 ) {
$todayStart = $tStart;
$delayStart = strtotime("+$delay_minutes minutes", $current_time);
while ( $todayStart <= $delayStart ) {
$todayStart = strtotime("+$interval minutes", $todayStart);
}
$tNow = $todayStart;
}
while ( $tNow <= $tEnd ) {
$day_name = __( 'Today', $this->plugin_slug );
$option_key = $current_day_name . date( $date_format_key, $tNow );
$option_value = $day_name . ' ' . date( $date_format, $tNow );
$pickup_options[$option_key] = $option_value;
$tNow = strtotime( "+$interval minutes", $tNow );
}
}
// Other days
} else {
if ( !empty($open_time) && !empty($close_time )) {
while ( $tNow <= $tEnd ) {
$day_name = __( $current_day_name, $this->plugin_slug );
$option_key = $current_day_name . date( $date_format_key, $tNow );
$option_value = $day_name . ' ' . date( $date_format, $tNow );
$pickup_options[$option_key] = $option_value;
$tNow = strtotime( "+$interval minutes", $tNow );
}
}
}
}
} // end for loop
if ( count($pickup_options) == 1) {
// Set drop down text to let user know store is closed
$pickup_options['closed_today'] = __( 'Closed today, please check back tomorrow!', $this->plugin_slug );
// Hide Order Review so user doesn't order anything today
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_order_review', 10 );
remove_action( 'woocommerce_checkout_order_review', 'woocommerce_checkout_payment', 20 );
}
return $pickup_options;
}
The final result would look something like this Drop-down list:
As soon as possible
Tuesday 7:30 pm
Tuesday 8:00 pm
Tuesday 8:30 pm
There is many ways to do it depending if the key value you want for "As soon as possible" choice has to be dynamic. This is done in your first function with array_merge() this way:
public function time_select( $checkout ) {
echo '<div id="local-pickup-time-select"><h2>' . __( 'Delivery Time', $this->plugin_slug ) . '</h2>';
// The default empty value and your translatable sentence to be included
$array_to_insert = array(
'' => __( 'Select your delivery time', $this->plugin_slug ),
'as_soon' => __( 'As soon as possible', $this->plugin_slug )
);
// Getting your calculated hours options array
$options = self::create_hour_options();
// Merging both arrays in one
$options = array_merge( $array_to_insert, $options );
woocommerce_form_field( 'local_pickup_time_select', array(
'type' => 'select',
'class' => array( 'local-pickup-time-select-field form-row-wide' ),
'label' => __( 'Delivery Time', $this->plugin_slug ),
'required' => true,
'options' => $options,
), $checkout->get_value( 'local_pickup_time_select' ));
echo '</div>';
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works. you will get that:
I have noticed in your code that your //Translateble days (monday to sunday) are not set in individual variables or in an array…
I am trying to add a widget to Woocommerce to Filter Products by Quantity with a slider. I got this far by changing the open source code of woocommerce for the price filter slider. It print no errors once it's on the website but it does not filter the results. The output on the URL is also as expected. The slider does not work but it's fine if I cannot fix it. As of now it has two type-in fields: max and min stock quantity. Please help. I am sure others will benefit from this. I need it because the website is for wholesale and if a product is not available is a min quantity that a client wants, they can filter it out.
// Register and load the widget
function my_stock_widget() {
register_widget( 'WC_Widget_Stock_Filter' );
}
add_action( 'widgets_init', 'my_stock_widget' );
class WC_Widget_Stock_Filter extends WC_Widget {
/**
* Constructor.
*/
public function __construct() {
$this->widget_cssclass = 'woocommerce widget_stock_filter';
$this->widget_description = __( 'Shows a stock filter slider in a widget which lets you narrow down the list of shown products when viewing product categories.', 'woocommerce' );
$this->widget_id = 'woocommerce_stock_filter';
$this->widget_name = __( 'WooCommerce stock filter', 'woocommerce' );
$this->settings = array(
'title' => array(
'type' => 'text',
'std' => __( 'Filter by stock', 'woocommerce' ),
'label' => __( 'Title', 'woocommerce' ),
),
);
$suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
wp_register_script( 'accounting', WC()->plugin_url() . '/assets/js/accounting/accounting' . $suffix . '.js', array( 'jquery' ), '0.4.2' );
wp_register_script( 'wc-jquery-ui-touchpunch', WC()->plugin_url() . '/assets/js/jquery-ui-touch-punch/jquery-ui-touch-punch' . $suffix . '.js', array( 'jquery-ui-slider' ), WC_VERSION, true );
wp_register_script( 'wc-stock-slider', WC()->plugin_url() . '/assets/js/frontend/price-slider' . $suffix . '.js', array( 'jquery-ui-slider', 'wc-jquery-ui-touchpunch', 'accounting' ), WC_VERSION, true );
wp_localize_script( 'wc-stock-slider', 'woocommerce_stock_slider_params', array(
'min_stock' => isset( $_GET['min_stock'] ) ? esc_attr( $_GET['min_stock'] ) : '',
'max_stock' => isset( $_GET['max_stock'] ) ? esc_attr( $_GET['max_stock'] ) : '',
'currency_format_num_decimals' => 0,
// 'currency_format_symbol' => get_woocommerce_currency_symbol(),
'currency_format_decimal_sep' => esc_attr( wc_get_price_decimal_separator() ),
'currency_format_thousand_sep' => esc_attr( wc_get_price_thousand_separator() ),
// 'currency_format' => esc_attr( str_replace( array( '%1$s', '%2$s' ), array( '%s', '%v' ), get_woocommerce_stock_format() ) ),
) );
parent::__construct();
}
/**
* Output widget.
*
* #see WP_Widget
*
* #param array $args
* #param array $instance
*/
public function widget( $args, $instance ) {
global $wp, $wp_the_query;
if ( ! is_post_type_archive( 'product' ) && ! is_tax( get_object_taxonomies( 'product' ) ) ) {
return;
}
if ( ! $wp_the_query->post_count ) {
return;
}
$min_stock = isset( $_GET['min_stock'] ) ? esc_attr( $_GET['min_stock'] ) : '';
$max_stock = isset( $_GET['max_stock'] ) ? esc_attr( $_GET['max_stock'] ) : '';
wp_enqueue_script( 'wc-stock-slider' );
// Find min and max stock in current result set
$stocks = $this->get_filtered_stock();
$min = floor( $stocks->min_stock );
$max = ceil( $stocks->max_stock );
if ( $min === $max ) {
return;
}
$this->widget_start( $args, $instance );
if ( '' === get_option( 'permalink_structure' ) ) {
$form_action = remove_query_arg( array( 'page', 'paged' ), add_query_arg( $wp->query_string, '', home_url( $wp->request ) ) );
} else {
$form_action = preg_replace( '%\/page/[0-9]+%', '', home_url( trailingslashit( $wp->request ) ) );
}
/**
* Adjust max if the store taxes are not displayed how they are stored.
* Min is left alone because the product may not be taxable.
* Kicks in when stocks excluding tax are displayed including tax.
*
if ( wc_tax_enabled() && 'incl' === get_option( 'woocommerce_tax_display_shop' ) && ! wc_stocks_include_tax() ) {
$tax_classes = array_merge( array( '' ), WC_Tax::get_tax_classes() );
$class_max = $max;
foreach ( $tax_classes as $tax_class ) {
if ( $tax_rates = WC_Tax::get_rates( $tax_class ) ) {
$class_max = $max + WC_Tax::get_tax_total( WC_Tax::calc_exclusive_tax( $max, $tax_rates ) );
}
}
$max = $class_max;
}*/
echo '<form method="get" action="' . esc_url( $form_action ) . '">
<div class="stock_slider_wrapper">
<div class="stock_slider" style="display:none;"></div>
<div class="stock_slider_amount">
<input type="text" id="min_stock" name="min_stock" value="' . esc_attr( $min_stock ) . '" data-min="' . esc_attr( apply_filters( 'woocommerce_stock_filter_widget_min_amount', $min ) ) . '" placeholder="' . esc_attr__( 'Min stock', 'woocommerce' ) . '" />
<input type="text" id="max_stock" name="max_stock" value="' . esc_attr( $max_stock ) . '" data-max="' . esc_attr( apply_filters( 'woocommerce_stock_filter_widget_max_amount', $max ) ) . '" placeholder="' . esc_attr__( 'Max stock', 'woocommerce' ) . '" />
<button type="submit" class="button">' . esc_html__( 'Filter', 'woocommerce' ) . '</button>
<div class="stock_label" style="display:none;">
' . esc_html__( 'Stock:', 'woocommerce' ) . ' <span class="from"></span> — <span class="to"></span>
</div>
' . wc_query_string_form_fields( null, array( 'min_stock', 'max_stock' ), '', true ) . '
<div class="clear"></div>
</div>
</div>
</form>';
$this->widget_end( $args );
}
/**
* Get filtered min stock for current products.
* #return int
*/
protected function get_filtered_stock() {
global $wpdb, $wp_the_query;
$args = $wp_the_query->query_vars;
$tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
$meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
if ( ! is_post_type_archive( 'product' ) && ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) {
$tax_query[] = array(
'taxonomy' => $args['taxonomy'],
'terms' => array( $args['term'] ),
'field' => 'slug',
);
}
foreach ( $meta_query + $tax_query as $key => $query ) {
if ( ! empty( $query['stock_filter'] ) || ! empty( $query['rating_filter'] ) ) {
unset( $meta_query[ $key ] );
}
}
$meta_query = new WP_Meta_Query( $meta_query );
$tax_query = new WP_Tax_Query( $tax_query );
$meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
$tax_query_sql = $tax_query->get_sql( $wpdb->posts, 'ID' );
$sql = "SELECT min( FLOOR( stock_meta.meta_value ) ) as min_stock, max( CEILING( stock_meta.meta_value ) ) as max_stock FROM {$wpdb->posts} ";
$sql .= " LEFT JOIN {$wpdb->postmeta} as stock_meta ON {$wpdb->posts}.ID = stock_meta.post_id " . $tax_query_sql['join'] . $meta_query_sql['join'];
$sql .= " WHERE {$wpdb->posts}.post_type IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_stock_filter_meta_keys', array( 'product' ) ) ) ) . "')
AND {$wpdb->posts}.post_status = 'publish'
AND stock_meta.meta_key IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_stock_filter_meta_keys', array( '_stock' ) ) ) ) . "')
AND stock_meta.meta_value > '' ";
$sql .= $tax_query_sql['where'] . $meta_query_sql['where'];
if ( $search = WC_Query::get_main_search_query_sql() ) {
$sql .= ' AND ' . $search;
}
return $wpdb->get_row( $sql );
}
I need this filter to only be added/triggered on a specific post id.
add_filter( 'woocommerce_get_item_data', 'woocommerce_cart_item_product', 10, 3 );
function woocommerce_cart_item_product( $item_data, $cart_item){
if ( ! empty( $cart_item['booking'] ) ) {
$date_format = apply_filters( 'woocommerce_bookings_date_format', wc_date_format() );
$time_format = apply_filters( 'woocommerce_bookings_time_format', ', ' . wc_time_format() );
$end_date = apply_filters( 'woocommerce_bookings_get_end_date_with_time', date_i18n( $date_format, $cart_item['booking']['_end_date'] ) );
$item_data[] = array(
'key' => __( 'for the week of', 'your-textdomain' ),
'value' => $cart_item['booking']['_end_date'],
'display' => $end_date,
);
}
return $item_data;
}
$cart_item argument have all the details you want about the product that is being added to cart.
$cart_item[ 'product_id' ] // Product Id ( the product that is being added to cart )
$cart_item[ 'variation_id' ] // Variable product's id ( if that product is a variable )
$cart_item[ 'variation' ] // Variation array ( if that product is a variable )
$cart_item[ 'quantity' ] // Line Item quantity
$cart_item[ 'data' ] // Post object of the product that is being added
So your code should look like this.
add_filter( 'woocommerce_get_item_data', 'woocommerce_cart_item_product', 10, 2 );
function woocommerce_cart_item_product( $item_data, $cart_item ) {
if ( !empty( $cart_item['booking'] ) && $cart_item["product_id"] == "Your Product Id" ) {
$date_format = apply_filters( 'woocommerce_bookings_date_format', wc_date_format() );
$time_format = apply_filters( 'woocommerce_bookings_time_format', ', ' . wc_time_format() );
$end_date = apply_filters( 'woocommerce_bookings_get_end_date_with_time', date_i18n( $date_format, $cart_item['booking']['_end_date'] ) );
$item_data[] = array(
'key' => __( 'for the week of', 'your-textdomain' ),
'value' => $cart_item['booking']['_end_date'],
'display' => $end_date,
);
}
return $item_data;
}
Replace that "Your Product Id" with your specific post id.
Depending on where this code is executed this should work:
add_filter( 'woocommerce_get_item_data', 'woocommerce_cart_item_product', 10, 3 );
function woocommerce_cart_item_product( $item_data, $cart_item) {
global $post;
if ( ! empty( $cart_item['booking'] ) && $post->ID == YOURUNIQUEIDHERE ) {
$date_format = apply_filters( 'woocommerce_bookings_date_format', wc_date_format() );
$time_format = apply_filters( 'woocommerce_bookings_time_format', ', ' . wc_time_format() );
$end_date = apply_filters( 'woocommerce_bookings_get_end_date_with_time', date_i18n( $date_format, $cart_item['booking']['_end_date'] ) );
$item_data[] = array(
'key' => __( 'for the week of', 'your-textdomain' ),
'value' => $cart_item['booking']['_end_date'],
'display' => $end_date,
);
}
return $item_data;
}
I've added an extra check for the Post ID in your if-statement. Here you can replace YOURUNIQUEIDHERE with the ID of any post you want. Hope this helps you out!