Invalid value posted for <variation> in Woocommerce - wordpress

I tried to change the variation on a product from select option to radio inputs. I duplicated on my child theme and updated the file variable.php. Made some changes, but when I try to add to cart, I have the error:
Invalid value posted for Size
This is the HTML from the Select version:
<select id="size" class="" name="attribute_size" data-attribute_name="attribute_size" data-show_option_none="yes">
<option value="">Choose an option</option>
<option value="15" class="attached enabled">15</option>
<option value="15.5" class="attached enabled">15.5</option>
<option value="16" class="attached enabled">16</option>
</select>
And this is the HTML with the radio inputs:
<ul class="product-size">
<li class="size">
<div>
<input style="display:none" type="radio" data-attribute-name="attribute_size" name="attribute_size" value="15" id="size_v_15">
<label for="size_v_15">15</label>
</div>
</li>
<li class="size">
<div>
<input style="display:none" type="radio" data-attribute-name="attribute_size" name="attribute_size" value="15.5" id="size_v_15.5" checked="checked">
<label for="size_v_15.5">15.5</label>
</div>
</li>
<li class="size">
<div>
<input style="display:none" type="radio" data-attribute-name="attribute_size" name="attribute_size" value="16" id="size_v_16">
<label for="size_v_16">16</label>
</div>
</li>
</ul>
As you can see, both name and value are the same in those two versions. However, I get the above error. In case you need the code I change in variable.php file, here it is:
<?php
function print_attribute_radio($checked_value, $value, $label, $name)
{
$checked = sanitize_title($checked_value) === $checked_value ? checked($checked_value, sanitize_title($value) , false) : checked($checked_value, $value, false);
$input_name = 'attribute_' . esc_attr($name);
$esc_value = esc_attr($value);
$id = esc_attr($name . '_v_' . $value);
$filtered_label = apply_filters('woocommerce_variation_option_name', $label);
printf('<div><input style="display:none" type="radio" data-attribute-name="%1$s" name="%1$s" value="%2$s" id="%3$s" %4$s><label for="%3$s">%5$s</label></div>', $input_name, $esc_value, $id, $checked, $filtered_label);
}
if (sanitize_title($attribute_name) == 'size'):
$sanitized_name = sanitize_title($attribute_name);
if (isset($_REQUEST['attribute_' . $sanitized_name])) {
$checked_value = $_REQUEST['attribute_' . $sanitized_name];
}
elseif (isset($selected_attributes[$sanitized_name])) {
$checked_value = $selected_attributes[$sanitized_name];
}
else {
$checked_value = '';
}
?>
<h3>Choose Your Size</h3>
<ul class="product-size">
<?php
foreach($options as $option) {
echo '<li class="size">';
print_attribute_radio($checked_value, $option, $option, $sanitized_name);
echo '</li>';
} ?>
</ul>
<script type="text/javascript">
jQuery('.product-size > li').click(function(e) {
jQuery('.product-size > li').removeClass('size-selected');
jQuery(this).addClass('size-selected');
var option_id = jQuery(this).find("input").attr("checked",true);
});
</script>
<?php endif; ?>

I add your code to standard woocommerce template variable.php
The main goal here is to take request parametrs that woocommece standard select give to variations_form and replace it with our custom parametrs in hidden inputs.
It a dirty trick, cos some standart woocommerce behavior will be not work and you need more code to return it, but you already can properly add product to your cart.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $product;
// get arr as varition id - value and vaiation attr name - key
$product_variations_arr = $product->get_available_variations();
$varitions_id_value_arr = [];
foreach ($product_variations_arr as $variation_arr) {
$varitions_id_value_arr[ current( $variation_arr['attributes'] ) ] = $variation_arr['variation_id'];
}
$attribute_keys = array_keys( $attributes );
do_action( 'woocommerce_before_add_to_cart_form' ); ?>
<?php
function print_attribute_radio($checked_value, $value, $label, $name, $varitions_id_value_arr)
{
$checked = sanitize_title($checked_value) === $checked_value ? checked($checked_value, sanitize_title($value) , false) : checked($checked_value, $value, false);
$input_name = 'attribute_' . esc_attr($name);
$esc_value = esc_attr($value);
$id = esc_attr($name . '_v_' . $value);
$filtered_label = apply_filters('woocommerce_variation_option_name', $label);
printf('<div><input type="radio" data-variation-id="%6$s" data-attribute-name="%1$s" name="%1$s" value="%2$s" id="%3$s" %4$s><label for="%3$s">%5$s</label></div>', $input_name, $esc_value, $id, $checked, $filtered_label, $varitions_id_value_arr[$value]);
}
?>
<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo absint( $product->get_id() ); ?>" data-product_variations="<?php echo htmlspecialchars( wp_json_encode( $available_variations ) ) ?>">
<?php do_action( 'woocommerce_before_variations_form' ); ?>
<?php if ( empty( $available_variations ) && false !== $available_variations ) : ?>
<p class="stock out-of-stock"><?php _e( 'This product is currently out of stock and unavailable.', 'woocommerce' ); ?></p>
<?php else : ?>
<?php foreach ( $attributes as $attribute_name => $options ) :
if (sanitize_title($attribute_name) == 'pa_test'):
$sanitized_name = sanitize_title($attribute_name);
if (isset($_REQUEST['attribute_' . $sanitized_name])) {
$checked_value = $_REQUEST['attribute_' . $sanitized_name];
}
elseif (isset($selected_attributes[$sanitized_name])) {
$checked_value = $selected_attributes[$sanitized_name];
}
else {
$checked_value = '';
}
?>
<h3>Choose Your Size</h3>
<ul class="product-size">
<?php
foreach($options as $option) {
echo '<li class="size">';
print_attribute_radio($checked_value, $option, $option, $sanitized_name, $varitions_id_value_arr);
echo '</li>';
}
?>
</ul>
<input type="hidden" name="attribute_pa_test" value="">
<script type="text/javascript">
jQuery('.product-size > li').click(function(e) {
jQuery('.product-size > li').removeClass('size-selected');
jQuery(this).addClass('size-selected');
var option_id = jQuery(this).find("input").attr("checked", true);
var variation_value = jQuery(this).find("input").attr("checked", true).val();
var variation_id = jQuery(this).find("input").attr("checked", true).attr('data-variation-id')
// set choosen variation in hiden inputs
jQuery('input[name=variation_id]').val( variation_id );
jQuery('input[name=attribute_pa_test]').val( variation_value );
});
</script>
<?php endif; ?>
<table class="variations" cellspacing="0">
<tbody>
<tr>
<td class="label"><label for="<?php echo sanitize_title( $attribute_name ); ?>"><?php echo wc_attribute_label( $attribute_name ); ?></label></td>
<td class="value">
<?php
//$selected = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( stripslashes( urldecode( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ) ) : $product->get_variation_default_attribute( $attribute_name );
//wc_dropdown_variation_attribute_options( array( 'options' => $options, 'attribute' => $attribute_name, 'product' => $product, 'selected' => $selected ) );
//echo end( $attribute_keys ) === $attribute_name ? apply_filters( 'woocommerce_reset_variations_link', '<a class="reset_variations" href="#">' . esc_html__( 'Clear', 'woocommerce' ) . '</a>' ) : '';
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php do_action( 'woocommerce_before_add_to_cart_button' ); ?>
<div class="single_variation_wrap">
<?php
/**
* woocommerce_before_single_variation Hook.
*/
do_action( 'woocommerce_before_single_variation' );
/**
* woocommerce_single_variation hook. Used to output the cart button and placeholder for variation data.
* #since 2.4.0
* #hooked woocommerce_single_variation - 10 Empty div for variation data.
* #hooked woocommerce_single_variation_add_to_cart_button - 20 Qty and cart button.
*/
do_action( 'woocommerce_single_variation' );
/**
* woocommerce_after_single_variation Hook.
*/
do_action( 'woocommerce_after_single_variation' );
?>
</div>
<?php do_action( 'woocommerce_after_add_to_cart_button' ); ?>
<?php endif; ?>
<?php do_action( 'woocommerce_after_variations_form' ); ?>
</form>
<?php
do_action( 'woocommerce_after_add_to_cart_form' );

Related

Plugin to set out of stock product image doesn't work

I'm creating a plugin to set a different image for each out of stock product everything is displayed in the dashboard only if you set an image it doesn't work can someone help me solve the problem in the code, I would be very grateful
<?php
/**
* Plugin Name: Out of Stock Image Changer for WooCommerce
* Plugin URI:
* Description: Automatically changes the product image when it goes out of stock in WooCommerce
* Version: 1.0.0
* Author:
* Author URI:
* License:
*/
add_action( 'admin_menu', 'register_product_image_changer_page' );
function register_product_image_changer_page() {
add_submenu_page( 'edit.php?post_type=product', 'Out of stock images', 'Out of stock images', 'manage_options', 'out-of-stock-images', 'render_product_image_changer_page' );
}
function render_product_image_changer_page() {
global $wpdb;
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( __( 'You do not have sufficient permissions to access this page.', 'woocommerce' ) );
}
if ( ! empty( $_POST ) && check_admin_referer( 'update_out_of_stock_images' ) ) {
$product_ids = isset( $_POST['product_id'] ) ? $_POST['product_id'] : array();
$out_of_stock_images = isset( $_POST['out_of_stock_image'] ) ? $_POST['out_of_stock_image'] : array();
foreach ( $product_ids as $index => $product_id ) {
update_post_meta( $product_id, 'out_of_stock_image', $out_of_stock_images[ $index ] );
}
}
$results = $wpdb->get_results( "SELECT ID, post_title FROM $wpdb->posts WHERE post_type = 'product' AND post_status = 'publish'" );
?>
<div class="wrap">
<h1><?php _e( 'Out of stock images', 'woocommerce' ); ?></h1>
<form method="post">
<?php wp_nonce_field( 'update_out_of_stock_images' ); ?>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e( 'Product', 'woocommerce' ); ?></th>
<th><?php _e( 'Out of stock image URL', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ( $results as $result ) : ?>
<tr>
<td><?php echo $result->post_title; ?></td>
<td>
<input type="hidden" name="product_id[]" value="<?php echo $result->ID; ?>">
<input type="text" name="out_of_stock_image[]" value="<?php echo get_post_meta( $result->ID, 'out_of_stock_image', true ); ?>" class="widefat">
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p class="submit">
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e( 'Save Changes', 'woocommerce' ); ?>">
</p>
</form>
</div>
<?php
}
add_action( 'woocommerce_before_single_product_summary', 'maybe_change_product_image', 9 );
function maybe_change_product_image() {
global $product;
if ( ! $product->is_in_stock() ) {
$out_of_stock_image = get_post_meta( get_the_ID(), 'out_of_stock_image', true );
if ( ! empty( $out_of_stock_image ) ) {
remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20 );
add_action( 'woocommerce_before_single_product_summary', 'show_out_of_stock_image', 20 );
}
}
}
function show_out_of_stock_image() {
global $product;
$out_of_stock_image = get_post_meta( get_the_ID(), 'out_of_stock_image', true );
if ( ! empty( $out_of_stock_image ) ) {
echo '<img src="' . esc_url( $out_of_stock_image ) . '" class="attachment-shop_single size-shop_single wp-post-image" alt="">';
}
}
everything works in the dashboard, but if an image is set it is not displayed
this code worked for me.
/**
* Plugin Name: Out of Stock Image Changer for WooCommerce
* Plugin URI:
* Description: Automatically changes the product image when it goes out of stock in WooCommerce
* Version: 1.0.0
* Author:
* Author URI:
* License:
*/
add_action( 'admin_menu', 'register_product_image_changer_page' );
function register_product_image_changer_page() {
add_submenu_page( 'edit.php?post_type=product', 'Out of stock images', 'Out of stock images', 'manage_options', 'out-of-stock-images', 'render_product_image_changer_page' );
}
function render_product_image_changer_page() {
global $wpdb;
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( __( 'You do not have sufficient permissions to access this page.', 'woocommerce' ) );
}
if ( ! empty( $_POST ) && check_admin_referer( 'update_out_of_stock_images' ) ) {
$product_ids = isset( $_POST['product_id'] ) ? $_POST['product_id'] : array();
$out_of_stock_images = isset( $_POST['out_of_stock_image'] ) ? $_POST['out_of_stock_image'] : array();
foreach ( $product_ids as $index => $product_id ) {
update_post_meta( $product_id, 'out_of_stock_image', $out_of_stock_images[ $index ] );
}
}
$results = $wpdb->get_results( "SELECT ID, post_title FROM $wpdb->posts WHERE post_type = 'product' AND post_status = 'publish'" );
?>
<div class="wrap">
<h1><?php _e( 'Out of stock images', 'woocommerce' ); ?></h1>
<form method="post">
<?php wp_nonce_field( 'update_out_of_stock_images' ); ?>
<table class="wp-list-table widefat fixed striped">
<thead>
<tr>
<th><?php _e( 'Product', 'woocommerce' ); ?></th>
<th><?php _e( 'Out of stock image URL', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ( $results as $result ) : ?>
<tr>
<td><?php echo $result->post_title; ?></td>
<td>
<input type="hidden" name="product_id[]" value="<?php echo $result->ID; ?>">
<input type="text" name="out_of_stock_image[]" value="<?php echo get_post_meta( $result->ID, 'out_of_stock_image', true ); ?>" class="widefat">
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p class="submit">
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e( 'Save Changes', 'woocommerce' ); ?>">
</p>
</form>
</div>
<?php
}
add_action( 'woocommerce_before_single_product', 'maybe_change_product_image', 9 );
function maybe_change_product_image() {
global $product;
if ( ! $product->is_in_stock() ) {
$out_of_stock_image = get_post_meta( $product->get_id(), 'out_of_stock_image', true );
if ( ! empty( $out_of_stock_image ) ) {
remove_action( 'woocommerce_before_single_product_summary', 'woocommerce_show_product_images', 20 );
add_action( 'woocommerce_before_single_product_summary', 'show_out_of_stock_image', 20 );
}
}
}
function show_out_of_stock_image() {
global $product;
$out_of_stock_image = get_post_meta( $product->get_id(), 'out_of_stock_image', true );
if ( ! empty( $out_of_stock_image ) ) {
echo '<img src="' . esc_url( $out_of_stock_image ) . '" class="attachment-shop_single size-shop_single wp-post-image" alt="">';
}
}

Adding woocommerce shipping calculator to front end page with shortcode

I am looking to add woocommerce shipping calculator to my delivery policy page with a simple short code. I found a plugin to do that but it's hasn't been updated in 5-7 years and it's filled with bugs and conflict. Can someone look at this code and help me figure out what's wrong with it.
Thanks.
global $shortcode_times;
add_action( 'wp', 'ss_woo_shipping_calculator_ajax' );
function ss_woo_shipping_calculator_ajax() {
if( $_POST["action"] != "ss_woo_shipping_calculator")
return false;
$result = array();
try {
WC()->shipping->load_shipping_methods();
WC()->shipping->reset_shipping();
$country = wc_clean( $_POST['country'] );
$state = wc_clean( isset( $_POST['state'] ) ? $_POST['state'] : '' );
$postcode = apply_filters( 'woocommerce_shipping_calculator_enable_postcode', true ) ? wc_clean( $_POST['postcode'] ) : '';
$city = apply_filters( 'woocommerce_shipping_calculator_enable_city', false ) ? wc_clean( $_POST['city'] ) : '';
if ( $postcode && ! WC_Validation::is_postcode( $postcode, $country ) ) {
throw new Exception( __( 'Please enter a valid postcode / ZIP.', 'woocommerce' ) );
} elseif ( $postcode ) {
$postcode = wc_format_postcode( $postcode, $country );
}
if ( $country ) {
WC()->customer->set_location( $country, $state, $postcode, $city );
WC()->customer->set_shipping_location( $country, $state, $postcode, $city );
} else {
WC()->customer->set_to_base();
WC()->customer->set_shipping_to_base();
}
WC()->customer->set_calculated_shipping( true );
WC()->customer->save();
do_action( 'woocommerce_calculated_shipping' );
$cu = get_woocommerce_currency_symbol();
WC()->shipping->calculate_shipping( WC()->cart->get_shipping_packages() );
$packages = WC()->shipping->get_packages();
if(count($packages ) > 0){
$result["result"] = 1;
$message = "<ul>";
foreach ( $packages as $i => $package ) {
if(count($package['rates']) > 0){
foreach($package['rates'] as $k => $v){
$message .= "<li>".$v->label." <span> - ".$cu." ".$v->cost."</span></li>";
}
}
}
$result["message"] = $message ;
}
} catch ( Exception $e ) {
$result["result"] = 0;
$result["message"] = $e->getMessage() ;
}
echo json_encode($result);
die();
}
function ss_woo_shipping_calculator_shortcode() {
global $shortcode_times;
$shortcode_times++;
if($shortcode_times > 1){
return "";
}
wp_enqueue_script( 'wc-cart' );
ob_start();
do_action( 'woocommerce_before_shipping_calculator' );
?>
<form>
<section class="shipping-calculator-form-shortcode" >
<p class="form-row form-row-wide" id="calc_shipping_country_field">
<select name="calc_shipping_country" id="calc_shipping_country" class="country_to_state" rel="calc_shipping_state">
<option value=""><?php _e( 'Select a country…', 'woocommerce' ); ?></option>
<?php
foreach ( WC()->countries->get_shipping_countries() as $key => $value )
echo '<option value="' . esc_attr( $key ) . '"' . selected( WC()->customer->get_shipping_country(), esc_attr( $key ), false ) . '>' . esc_html( $value ) . '</option>';
?>
</select>
</p>
<p class="form-row form-row-wide" id="calc_shipping_state_field">
<?php
$current_cc = WC()->customer->get_shipping_country();
$current_r = WC()->customer->get_shipping_state();
$states = WC()->countries->get_states( $current_cc );
// Hidden Input
if ( is_array( $states ) && empty( $states ) ) {
?><input type="hidden" name="calc_shipping_state" id="calc_shipping_state" placeholder="<?php esc_attr_e( 'State / County', 'woocommerce' ); ?>" /><?php
// Dropdown Input
} elseif ( is_array( $states ) ) {
?><span>
<select name="calc_shipping_state" id="calc_shipping_state" placeholder="<?php esc_attr_e( 'State / County', 'woocommerce' ); ?>">
<option value=""><?php esc_html_e( 'Select a state…', 'woocommerce' ); ?></option>
<?php
foreach ( $states as $ckey => $cvalue )
echo '<option value="' . esc_attr( $ckey ) . '" ' . selected( $current_r, $ckey, false ) . '>' . esc_html( $cvalue ) . '</option>';
?>
</select>
</span><?php
// Standard Input
} else {
?><input type="text" class="input-text" value="<?php echo esc_attr( $current_r ); ?>" placeholder="<?php esc_attr_e( 'State / County', 'woocommerce' ); ?>" name="calc_shipping_state" id="calc_shipping_state" /><?php
}
?>
</p>
<?php if ( apply_filters( 'woocommerce_shipping_calculator_enable_city', false ) ) : ?>
<p class="form-row form-row-wide" id="calc_shipping_city_field">
<input type="text" class="input-text" value="<?php echo esc_attr( WC()->customer->get_shipping_city() ); ?>" placeholder="<?php esc_attr_e( 'City', 'woocommerce' ); ?>" name="calc_shipping_city" id="calc_shipping_city" />
</p>
<?php endif; ?>
<?php if ( apply_filters( 'woocommerce_shipping_calculator_enable_postcode', true ) ) : ?>
<p class="form-row form-row-wide" id="calc_shipping_postcode_field">
<input type="text" class="input-text" value="<?php echo esc_attr( WC()->customer->get_shipping_postcode() ); ?>" placeholder="<?php esc_attr_e( 'Postcode / ZIP', 'woocommerce' ); ?>" name="calc_shipping_postcode" id="calc_shipping_postcode" />
</p>
<?php endif; ?>
<p><button value="1" class="button ss-woo-shipping-calculator"><?php _e( 'Update totals', 'woocommerce' ); ?></button><span id="ss-woo-shipping-calculator-loading" style="display:none"><img src='<?php echo plugins_url( '/default.gif', __FILE__ ) ?>' /></span></p>
<?php wp_nonce_field( 'woocommerce-cart' ); ?>
<div id="ss-woo-shipping-result">
</div>
</section>
</form>
<script type="text/javascript">
var $s = jQuery.noConflict();
$s(document).ready(function($) {
$(".ss-woo-shipping-calculator").click(function(){
var ajaxurl = "<?php echo admin_url('admin-ajax.php'); ?>";
var country = $(this).parent().parent().find("#calc_shipping_country").val();
var state = $(this).parent().parent().find("#calc_shipping_state").val();
var city = $(this).parent().parent().find("#calc_shipping_city").val();
var postcode = $(this).parent().parent().find("#calc_shipping_postcode").val();
$("#ss-woo-shipping-calculator-loading").show();
var data = {'action': 'ss_woo_shipping_calculator','country': country,'state': state,'city': city,'postcode': postcode};
$.post("<?php echo get_home_url(); ?>", data, function(response) {
$("#ss-woo-shipping-calculator-loading").hide();
response = JSON.parse(response);
if(response.result == 1){
$("#ss-woo-shipping-result").html(response.message);
}else{
alert(response.message);
$("#ss-woo-shipping-result").html("");
}
return false;
});
return false;
});
});
</script>
<?php
do_action( 'woocommerce_after_shipping_calculator' );
$out = ob_get_contents();
ob_end_clean();
return $out;
}
add_shortcode('ss_woo_shipping_calculator', 'ss_woo_shipping_calculator_shortcode');
I need help cleaning the code out and also making it not conflict especially with Elementor.

WordPress Media library not showing old images in Gridview, list view shows images

I have create one script to insert custom field image for all categories and database entry is fine.
Now, when I go to Media library it only loads my latest images, old images are not showing. Spinner continue rotation and Ajax call goes infinite.
There are many reasons to fail older image loads. Please turn on Debug Mode and check Debug Log and share the information here so we can help you.
<?php
add_action( 'business_add_form_fields', 'add_category_image', 10, 2 );
add_action( 'created_business', 'save_category_image', 10, 2 );
add_action( 'business_edit_form_fields','update_category_image', 10, 2 );
add_action( 'edited_business','updated_category_image', 10, 2 );
add_action( 'admin_enqueue_scripts', 'load_media');
add_action( 'admin_footer', 'add_script');
function load_media() {
if( ! isset( $_GET['taxonomy'] ) || $_GET['taxonomy'] != 'business' ) {
return;
}
wp_enqueue_media();
}
function add_category_image( $taxonomy ) { ?>
<div class="form-field term-group">
<label for="showcase-taxonomy-extra-detail-id"><?php _e( 'Business Extra Details', 'launchpm' ); ?></label>
<input type="text" id="showcase-taxonomy-extra-detail-id" name="showcase-taxonomy-extra-detail-id" class="" value="">
</div>
<div class="form-field term-group">
<label for="showcase-taxonomy-image-id"><?php _e( 'Image', 'launchpm' ); ?></label>
<input type="hidden" id="showcase-taxonomy-image-id" name="showcase-taxonomy-image-id" class="custom_media_url" value="">
<div id="category-image-wrapper"></div>
<p>
<input type="button" class="button button-secondary showcase_tax_media_button" id="showcase_tax_media_button" name="showcase_tax_media_button" value="<?php _e( 'Add Image', 'launchpm' ); ?>" />
<input type="button" class="button button-secondary showcase_tax_media_remove" id="showcase_tax_media_remove" name="showcase_tax_media_remove" value="<?php _e( 'Remove Image', 'launchpm' ); ?>" />
</p>
</div>
<?php }
/**
* Edit the form field
* #since 1.0.0
*/
function update_category_image( $term, $taxonomy ) { ?>
<tr class="form-field term-group-wrap">
<th scope="row">
<label for="showcase-taxonomy-extra-detail-id"><?php _e( 'Business Extra Details', 'launchpm' ); ?></label>
</th>
<td>
<?php $extra_detail = get_term_meta( $term->term_id, 'showcase-taxonomy-extra-detail-id', true ); ?>
<input type="text" id="showcase-taxonomy-extra-detail-id" name="showcase-taxonomy-extra-detail-id" value="<?php echo $extra_detail ; ?>">
</td>
</tr>
<tr class="form-field term-group-wrap">
<th scope="row">
<label for="showcase-taxonomy-image-id"><?php _e( 'Image', 'launchpm' ); ?></label>
</th>
<td>
<?php $image_id = get_term_meta( $term->term_id, 'showcase-taxonomy-image-id', true ); ?>
<input type="hidden" id="showcase-taxonomy-image-id" name="showcase-taxonomy-image-id" value="<?php echo esc_attr( $image_id ); ?>">
<div id="category-image-wrapper">
<?php if( $image_id ) { ?>
<?php echo wp_get_attachment_image( $image_id, 'thumbnail' ); ?>
<?php } ?>
</div>
<p>
<input type="button" class="button button-secondary showcase_tax_media_button" id="showcase_tax_media_button" name="showcase_tax_media_button" value="<?php _e( 'Add Image', 'showcase' ); ?>" />
<input type="button" class="button button-secondary showcase_tax_media_remove" id="showcase_tax_media_remove" name="showcase_tax_media_remove" value="<?php _e( 'Remove Image', 'showcase' ); ?>" />
</p>
</td>
</tr>
<?php }
/**
* Save the form field
* #since 1.0.0
*/
function save_category_image( $term_id, $tt_id ) {
if( isset( $_POST['showcase-taxonomy-image-id'] ) && '' !== $_POST['showcase-taxonomy-image-id'] ){
add_term_meta( $term_id, 'showcase-taxonomy-image-id', absint( $_POST['showcase-taxonomy-image-id'] ), true );
}
if( isset( $_POST['showcase-taxonomy-extra-detail-id'] ) && '' !== $_POST['showcase-taxonomy-extra-detail-id'] ){
add_term_meta( $term_id, 'showcase-taxonomy-extra-detail-id', $_POST['showcase-taxonomy-extra-detail-id'] , true );
}
}
/**
* Update the form field value
* #since 1.0.0
*/
function updated_category_image( $term_id, $tt_id ) {
if( isset( $_POST['showcase-taxonomy-image-id'] ) && '' !== $_POST['showcase-taxonomy-image-id'] ){
update_term_meta( $term_id, 'showcase-taxonomy-image-id', absint( $_POST['showcase-taxonomy-image-id'] ) );
} else {
update_term_meta( $term_id, 'showcase-taxonomy-image-id', '' );
}
if( isset( $_POST['showcase-taxonomy-extra-detail-id'] ) && '' !== $_POST['showcase-taxonomy-extra-detail-id'] ){
update_term_meta( $term_id, 'showcase-taxonomy-extra-detail-id', $_POST['showcase-taxonomy-extra-detail-id'] );
} else {
update_term_meta( $term_id, 'showcase-taxonomy-extra-detail-id', '' );
}
}
/**
* Enqueue styles and scripts
* #since 1.0.0
*/
function add_script() {
if( ! isset( $_GET['taxonomy'] ) || $_GET['taxonomy'] != 'business' ) {
return;
} ?>
<script> jQuery(document).ready( function($) {
_wpMediaViewsL10n.insertIntoPost = '<?php _e( "Insert", "showcase" ); ?>';
function ct_media_upload(button_class) {
var _custom_media = true, _orig_send_attachment = wp.media.editor.send.attachment;
$('body').on('click', button_class, function(e) {
var button_id = '#'+$(this).attr('id');
var send_attachment_bkp = wp.media.editor.send.attachment;
var button = $(button_id);
_custom_media = true;
wp.media.editor.send.attachment = function(props, attachment){
if( _custom_media ) {
$('#showcase-taxonomy-image-id').val(attachment.id);
$('#category-image-wrapper').html('<img class="custom_media_image" src="" style="margin:0;padding:0;max-height:100px;float:none;" />');
$( '#category-image-wrapper .custom_media_image' ).attr( 'src',attachment.url ).css( 'display','block' );
} else {
return _orig_send_attachment.apply( button_id, [props, attachment] );
}
}
wp.media.editor.open(button); return false;
});
}
ct_media_upload('.showcase_tax_media_button.button');
$('body').on('click','.showcase_tax_media_remove',function(){
$('#showcase-taxonomy-image-id').val('');
$('#category-image-wrapper').html('<img class="custom_media_image" src="" style="margin:0;padding:0;max-height:100px;float:none;" />');
});
$(document).ajaxComplete(function(event, xhr, settings) {
var queryStringArr = settings.data.split('&');
if( $.inArray('action=add-tag', queryStringArr) !== -1 ){
var xml = xhr.responseXML;
$response = $(xml).find('term_id').text();
if($response!=""){
// Clear the thumb image
$('#category-image-wrapper').html('');
}
}
});
});
</script>
<?php }

Get product custom attribute Woocommerce

I have a single product custom variation table template in functions.php and I'm trying to get product custom attribute. I have two them (date and location).
I'm found a lot of solutions, but none didn't work for me.
Woocommerce version 3.2.6.
With this code below I get
Notice: Only variables should be passed by reference.
And I get type 'Null' of $date.
<td class="date">
<?php
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id;
$date = array_shift( wc_get_product_terms( $product_id, 'pa_date', array( 'fields' => 'names' ) ) );
?>
</td>
This is my full product variation table code in function.php
function woocommerce_variable_add_to_cart(){
global $product, $post, $woocommerce;
$attributes = $product->get_attributes();
$variations = find_valid_variations();
// Check if the special 'price_grid' meta is set, if it is, load the default template:
if ( get_post_meta($post->ID, 'price_grid', true) ) {
wp_enqueue_script( 'wc-add-to-cart-variation' );
wc_get_template( 'single-product/add-to-cart/variable.php', array(
'available_variations' => $product->get_available_variations(),
'attributes' => $product->get_variation_attributes(),
'selected_attributes' => $product->get_variation_default_attributes()
) );
return;
}
?>
<table class="variations variations-grid" cellspacing="0">
<thead>
<tr>
<td> Date | Location </td>
<td> Price </td>
<td> Quantity </td>
<td> Availability </td>
<td> </td>
</tr>
</thead>
<tbody>
<?php
foreach ($variations as $key => $value) {
if( !$value['variation_is_visible'] ) continue;
?>
<tr>
<td class="date">
<?php
$product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->id; // Added WC 3+ support
$date = array_shift( wc_get_product_terms( $product_id, 'pa_date', array( 'fields' => 'names' ) ) );
?>
</td>
<td class="price">
<?php echo '<span>£</span>' . $product->get_price(); ?>
</td>
<td class="quantity">
<?php woocommerce_quantity_input(); ?>
</td>
<td class="stock">
<?php if (!$value['is_in_stock'] ) { ?>
<p class="stock out-of-stock"><?php _e( 'Places Not Available', 'woocommerce' ); ?></p>
<?php } else { ?>
<p class="stock in-stock"><?php _e( 'Places Available', 'woocommerce' ); ?></p>
</td>
<td class="add-to-cart">
<form class="cart" action="<?php echo esc_url( $product->add_to_cart_url() ); ?>" method="post" enctype='multipart/form-data'>
<?php
if(!empty($value['attributes'])){
foreach ($value['attributes'] as $attr_key => $attr_value) {
?>
<input type="hidden" name="<?php echo $attr_key?>" value="<?php echo $attr_value?>">
<?php
}
}
?>
<button type="submit" class="single_add_to_cart_button button alt"><span class="glyphicon glyphicon-tag"></span> Add to cart</button>
<input type="hidden" name="variation_id" value="<?php echo $value['variation_id']?>" />
<input type="hidden" name="product_id" value="<?php echo esc_attr( $post->ID ); ?>" />
<input type="hidden" name="add-to-cart" value="<?php echo esc_attr( $post->ID ); ?>" />
</form>
<?php } ?>
</td>
</tr>
<?php } ?>
</tbody>
</table>
<?php
}
function find_valid_variations() {
global $product;
$variations = $product->get_available_variations();
$attributes = $product->get_attributes();
$new_variants = array();
foreach( $variations as $variation ) {
// Peruse the attributes.
// 1. If both are explicitly set, this is a valid variation
// 2. If one is not set, that means any, and we must 'create' the rest.
$valid = true; // so far
foreach( $attributes as $slug => $args ) {
if( array_key_exists("attribute_$slug", $variation['attributes']) && !empty($variation['attributes']["attribute_$slug"]) ) {
// Exists
} else {
// Not exists, create
$valid = false; // it contains 'anys'
foreach( explode( '|', $attributes[$slug]['value']) as $attribute ) {
$attribute = trim( $attribute );
$new_variant = $variation;
$new_variant['attributes']["attribute_$slug"] = $attribute;
$new_variants[] = $new_variant;
}
}
}
// This contains ALL set attributes, and is itself a 'valid' variation.
if( $valid )
$new_variants[] = $variation;
}
return $new_variants;
}
UPDATE
I got this code working, but I get both attribute values (date location) in one tag.
How to seperate attributes?
<td>
<?php
foreach($value['attributes'] as $key => $val ) {
$val = str_replace(array('-','_'), ' ', $val);
printf( '<span class="attr attr-%s">%s</span>', $key, ucwords($val) );
}
?>
</td>
UPDATE
Finally I get date and location but with extra warnings, notices, and single characters.
Code
<?php
foreach($value as $date ) {
printf($date['attribute_date']);
}
?>
** SOLVED **
Maybe not the best method, but it's working.
<td class="date">
<?php
$i = 0;
foreach($value['attributes'] as $key => $val ) {
if($i == 0 ) {
echo $val;
}
$i++;
}
?>
</td>
<td class="location">
<?php
$i = 0;
foreach($value['attributes'] as $key => $val ) {
if($i !== 0) {
echo $val;
}
$i++;
}
?>
</td>
Use the method get_attributes() and function wc_get_product_terms() described here
<?php
// Get the attributes
$attributes = $product->get_attributes();
// Start the loop
foreach ( $attributes as $attribute ) : ?>
<?php
// Check and output, adopted from /templates/single-product/product-attributes.php
if ( $attribute['is_taxonomy'] ) {
$values = wc_get_product_terms( $product->id, $attribute['name'], array( 'fields' => 'names' ) );
echo apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values );
} else {
// Convert pipes to commas and display values
$values = array_map( 'trim', explode( WC_DELIMITER, $attribute['value'] ) );
echo apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values );
}
?>
<?php endforeach; ?>
If you look at the template \templates\single-product\product-attributes.php you can see how to get the individual attribute names.
if ( $attribute->is_taxonomy() ) {
$attribute_taxonomy = $attribute->get_taxonomy_object();
$attribute_values = wc_get_product_terms( $product->get_id(), $attribute->get_name(), array( 'fields' => 'all' ) );
foreach ( $attribute_values as $attribute_value ) {
$value_name = esc_html( $attribute_value->name );
if ( $attribute_taxonomy->attribute_public ) {
$values[] = '' . $value_name . '';
} else {
$values[] = $value_name;
}
}
}
Here's how to get specific Custom Attribute:
// Get the custom attribute
$svd_attribute = array_shift( wc_get_product_terms( $product->id, 'your_custom_attribute', array( 'fields' => 'names' ) ) );
// Display if String
if ( is_string( $svd_attribute ) ) {
echo wp_kses_post( "$svd_attribute" );
}
Just replace "your_custom_attribute"
Working on WooCommerce: 3.8.0

Wordpress User Upload Front End: Errors Illegal String off set, file is empty. Works on backend.

So having trouble getting a file uploaded via the front end and actually saving properly.
Funny thing is when I go through the back end user panel it works just fine.
Worth noting this is all on my localhost, running MAMP (apache).
I made sure to include the right files and declare the enctype for the form. I managed to get plain text fields to save just fine. I think I am messing up this part:
if ( !empty( $_POST['map_pdf'] ) )
update_user_meta( $current_user->ID, 'map_pdf', wp_handle_upload( $_POST['map_pdf'], array( 'test_form' => false ) ));
I have seen several other solutions but this is to be displayed in with the users information.
These are the errors I am running into:
Illegal string offset 'size' in /wp-admin/includes/file.php on line 272
File is empty. Please upload something more substantial.
This error could also be caused by uploads being disabled in your php.ini
or by post_max_size being defined as smaller than upload_max_filesize in php.ini.
Profile Page
<?php
/**
* Template Name: User Profile
*
* Allow users to update their profiles from Frontend.
*
*/
/* Get user info. */
global $current_user, $wp_roles;
get_currentuserinfo();
/* Load the registration file. */
require_once( ABSPATH . WPINC . '/registration.php' );
include_once ABSPATH . 'wp-admin/includes/media.php';
include_once ABSPATH . 'wp-admin/includes/file.php';
include_once ABSPATH . 'wp-admin/includes/image.php';
$error = array();
/* If profile was saved, update profile. */
if ( 'POST' == $_SERVER['REQUEST_METHOD'] && !empty( $_POST['action'] ) && $_POST['action'] == 'update-user' ) {
/* Update user password. */
if ( !empty($_POST['pass1'] ) && !empty( $_POST['pass2'] ) ) {
if ( $_POST['pass1'] == $_POST['pass2'] )
wp_update_user( array( 'ID' => $current_user->ID, 'user_pass' => esc_attr( $_POST['pass1'] ) ) );
else
$error[] = __('The passwords you entered do not match. Your password was not updated.', 'profile');
}
/* Update user information. */
if ( !empty( $_POST['url'] ) )
wp_update_user( array ('ID' => $current_user->ID, 'user_url' => esc_attr( $_POST['url'] )));
if ( !empty( $_POST['email'] ) ){
if (!is_email(esc_attr( $_POST['email'] )))
$error[] = __('The Email you entered is not valid. please try again.', 'profile');
elseif(email_exists(esc_attr( $_POST['email'] )) != $current_user->id )
$error[] = __('This email is already used by another user. try a different one.', 'profile');
else{
wp_update_user( array ('ID' => $current_user->ID, 'user_email' => esc_attr( $_POST['email'] )));
}
}
$r = get_user_meta( $user->ID, 'map_pdf', true );
if ( !empty( $_POST['first-name'] ) )
update_user_meta( $current_user->ID, 'first_name', esc_attr( $_POST['first-name'] ) );
if ( !empty( $_POST['last-name'] ) )
update_user_meta($current_user->ID, 'last_name', esc_attr( $_POST['last-name'] ) );
if ( !empty( $_POST['display_name'] ) )
wp_update_user(array('ID' => $current_user->ID, 'display_name' => esc_attr( $_POST['display_name'] )));
update_user_meta($current_user->ID, 'display_name' , esc_attr( $_POST['display_name'] ));
if ( !empty( $_POST['description'] ) )
update_user_meta( $current_user->ID, 'description', esc_attr( $_POST['description'] ) );
if ( !empty( $_POST['map_pdf'] ) )
update_user_meta( $current_user->ID, 'map_pdf', wp_handle_upload( $_POST['map_pdf'], array( 'test_form' => false ) ));
/* Redirect so the page will show updated info.*/
/*I am not Author of this Code- i dont know why but it worked for me after changing below line to if ( count($error) == 0 ){ */
if ( count($error) == 0 ) {
//action hook for plugins and extra fields saving
do_action('edit_user_profile_update', $current_user->ID);
wp_redirect( get_permalink().'?updated=true' ); exit;
}
}
?>
<?php get_template_part('templates/header'); ?>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<div class="contentarea tk-proxima-nova">
<div class="thecontent">
<h3>Update Information for "<?php echo $current_user->user_login ?>"</h3></br>
<?php if ( $_GET['updated'] == 'true' ) : ?> <div id="message" class="updated"><p>Your profile has been updated.</p></div> <?php endif; ?>
<?php if ( count($error) > 0 ) echo '<p class="error">' . implode("<br />", $error) . '</p>'; ?>
<div id="post-<?php the_ID(); ?>">
<div class="entry-content entry">
<?php the_content(); ?>
<?php if ( !is_user_logged_in() ) : ?>
<p class="warning">
<?php _e('You must be logged in to edit your profile.', 'profile'); ?>
</p><!-- .warning -->
<?php else : ?>
<?php if ( count($error) > 0 ) echo '<p class="error">' . implode("<br />", $error) . '</p>'; ?>
<form method="post" id="adduser" action="<?php the_permalink(); ?>">
<p class="form-username">
<label for="first-name"><?php _e('First Name', 'profile'); ?></label>
<input class="text-input" name="first-name" type="text" id="first-name" value="<?php the_author_meta( 'first_name', $current_user->ID ); ?>" />
</p><!-- .form-username -->
<p class="form-username">
<label for="last-name"><?php _e('Last Name', 'profile'); ?></label>
<input class="text-input" name="last-name" type="text" id="last-name" value="<?php the_author_meta( 'last_name', $current_user->ID ); ?>" />
</p><!-- .form-username -->
<p class="form-email">
<label for="email"><?php _e('E-mail *', 'profile'); ?></label>
<input class="text-input" name="email" type="text" id="email" value="<?php the_author_meta( 'user_email', $current_user->ID ); ?>" />
</p><!-- .form-email -->
<p class="form-url">
<label for="url"><?php _e('Website', 'profile'); ?></label>
<input class="text-input" name="url" type="text" id="url" value="<?php the_author_meta( 'user_url', $current_user->ID ); ?>" />
</p><!-- .form-url -->
<p class="form-password">
<label for="pass1"><?php _e('Password *', 'profile'); ?> </label>
<input class="text-input" name="pass1" type="password" id="pass1" />
</p><!-- .form-password -->
<p class="form-password">
<label for="pass2"><?php _e('Repeat Password *', 'profile'); ?></label>
<input class="text-input" name="pass2" type="password" id="pass2" />
</p><!-- .form-password -->
<p class="form-textarea">
<label for="description"><?php _e('Biographical Information', 'profile') ?></label>
<textarea name="description" id="description" rows="3" cols="50"><?php the_author_meta( 'description', $current_user->ID ); ?></textarea>
</p><!-- .form-textarea -->
<?php
//action hook for plugin and extra fields
do_action('edit_user_profile',$current_user);
?>
<p class="form-submit">
<?php echo $referer; ?>
<input name="updateuser" type="submit" id="updateuser" class="submit button" value="<?php _e('Update', 'profile'); ?>" />
<?php wp_nonce_field( 'update-user' ) ?>
<input name="action" type="hidden" id="action" value="update-user" />
</p><!-- .form-submit -->
</form><!-- #adduser -->
<?php endif; ?>
</div><!-- .entry-content -->
</div><!-- .hentry .post -->
</div><!-- .hentry .post -->
</div><!-- .hentry .post -->
<?php endwhile; ?>
<?php else: ?>
<p class="no-data">
<?php _e('Sorry, no page matched your criteria.', 'profile'); ?>
</p><!-- .no-data -->
<?php endif; ?>
<?php get_template_part('templates/footer'); ?>
And here is the functions.php
add_action( 'show_user_profile', 'extra_user_profile_fields' );
add_action( 'edit_user_profile', 'extra_user_profile_fields' );
function extra_user_profile_fields( $user ) {
$r = get_user_meta( $user->ID, 'map_pdf', true );
?>
<h3>file</h3>
<table class="form-table">
<tr>
<th scope="row">file</th>
<td><input type="file" name="map_pdf" value="" />
<?php //print_r($r);
if (!isset($r['error'])) {
$r = $r['url'];
echo $r;
} else {
$r = $r['error'];
echo $r;
}
?>
</td>
</tr>
</table>
<?php
}
add_action( 'personal_options_update', 'save_extra_user_profile_fields' );
add_action( 'edit_user_profile_update', 'save_extra_user_profile_fields' );
function save_extra_user_profile_fields( $user_id ) {
$_POST['action'] = 'wp_handle_upload';
if( $_FILES['map_pdf']['error'] === UPLOAD_ERR_OK ) {
$r = wp_handle_upload( $_FILES['map_pdf'] );
update_user_meta( $user_id, 'map_pdf', $r );
}
}
add_action('user_edit_form_tag', 'make_form_accept_uploads');
function make_form_accept_uploads() {
echo ' enctype="multipart/form-data"';
}
Any help is much appreciated. I have been looking everywhere and I have seen others with similar issues but none that are as specific as mine by pulling the userID and having it post back to the user page.
I have a problem with this line just checking exists(1) vs current_user->ID:
elseif(email_exists(esc_attr( $_POST['email'] )) != $current_user->id )
$error[] = __('This email is already used by another user. try a different one.', 'profile');
Would you want to do this?
$current_user_id = $current_user->ID;
$post_email = $_POST['email'];
$esc_email = esc_attr($post_email);
$email_exists = email_exists($esc_email);
$user_by_email = get_user_by( 'email', $esc_email );
$email_user_id = isset($user_by_email->data->ID) ? $user_by_email->data->ID : 0;
}elseif( $email_user_id && ($email_user_id != $current_user_id) ){
$error[] = __('This email is already used by another user. try a different one.', 'profile')

Resources