I am trying to build a form where when a user enters their order ID and unique serial code in the elementor form their order status is changed to completed. Heres the code i have written but i keep getting an error. The form has 2 fields 'a' & 'b'. A= order id and B= serial code.
add_action( 'elementor_pro/forms/validation', function ( $record, $ajax_handler ) {
$fields = $record->get_field( [
'id' => 'b'
], ['cid' => 'a'
]);
if ( empty( $fields ) ) {
return;
}
$field = current( $fields );
if ( 1 !== strlen( $field['value'] ) < 13 ) {
$ajax_handler->add_error( $field['id'], 'Invalid Serial Code, Please enter the 13 Digit Code mentioned on your delivery letter' );
} else {
$output['result'] = get_post_meta( $field['cid'], $key = 'shp_tkn', $single = true );
}
if ($output == $field['id']){
$order = $field['cid'] ;
$order->update_status('completed');
} else {
$ajax_handler->add_error( $field['id'], 'Invalid Serial Code, Please try again' );
}
}, 10, 2 );
If anyone could tell me where I'm going wrong.
Related
I'm trying to add some form validations to a site I'm working on. I was able to get the validations to work on the fields that are required but as I'm trying to adjust the code for the non-required fields that still need to be validated when there is user-input I'm running into some issues.
This works pretty flawlessly if the field is required but when I make the field not required, the form doesn't submit and puts out an error message if I leave the field blank.
add_action( 'elementor_pro/forms/validation', function ( $record, $ajax_handler ) {
$fields = $record->get_field( [
'id' => 'dot',
] );
if ( empty( $fields ) ) {
return;
}
$field = current( $fields );
if ( 1 !== preg_match( '/[1-9]{1}[0-9]{5,7}/', $field['value'] ) || $field['value'] == '123456' || $field['value'] == '12345678' ) {
$ajax_handler->add_error( $field['id'], 'Invalid DOT#' );
}
}, 10, 2 );
I have a different kind of scenario then the typical custom fields (I suppose). I am not getting custom values (fields) from user in the form rather I have an implementation which adds:
ColorName
Size
City
These are from a custom product flow which adds custom attributes to the cart, here is how I am doing that:
add_action('wp_ajax_wdm_add_user_custom_data_options', 'wdm_add_user_custom_data_options_callback');
add_action('wp_ajax_nopriv_wdm_add_user_custom_data_options', 'wdm_add_user_custom_data_options_callback');
function wdm_add_user_custom_data_options_callback()
{
// print_r($_POST);
$productIDM = $_POST['product_id'];
// case swith
switch ($productIDM) {
case "Ace Dura Silk":
$productID = 3254;
break;
case "Ace Matt Finish":
$productID = 3232;
break;
case "Ace Plastic Emulsion":
$productID = 3276;
break;
case "Ace Weather Defender":
$productID = 2991;
break;
case "Overall Plasticoat":
$productID = 3112;
break;
}
$colorname = $_POST['colorname'];
$cityname = $_POST['cityname'];
$size = $_POST['size'];
$price = $_POST['price'];
global $woocommerce;
$woocommerce->cart->add_to_cart( $productID, 1 );
// die();
// echo 'I am in...';
$result = array(
'status' => true
);
echo json_encode($result);
}
add_filter('woocommerce_add_cart_item_data','wdm_add_item_data',1,10);
function wdm_add_item_data($cart_item_data, $product_id) {
global $woocommerce;
$new_value = array();
$new_value['_custom_options'] = $_POST['custom_options'];
if(empty($cart_item_data)) {
return $new_value;
} else {
return array_merge($cart_item_data, $new_value);
}
}
add_filter('woocommerce_get_cart_item_from_session', 'wdm_get_cart_items_from_session', 1, 3 );
function wdm_get_cart_items_from_session($item,$values,$key) {
if (array_key_exists( '_custom_options', $values ) ) {
$item['_custom_options'] = $values['_custom_options'];
}
return $item;
}
add_filter('woocommerce_cart_item_name','add_usr_custom_session',1,3);
function add_usr_custom_session($product_name, $values, $cart_item_key ) {
$return_string = $product_name . "<div class='cart_subitems_custom'><br /><small>".$values['_custom_options']['colorname']."</small><br /><small>".$values['_custom_options']['cityname']."</small><br /><small>".$values['_custom_options']['size']."</small></div>" ; //. "<br />" . print_r($values['_custom_options']);
return $return_string;
}
add_action('woocommerce_add_order_item_meta','wdm_add_values_to_order_item_meta',1,2);
function wdm_add_values_to_order_item_meta($item_id, $values) {
global $woocommerce,$wpdb;
wc_add_order_item_meta($item_id,'_colorname',$values['_custom_options']['colorname']);
wc_add_order_item_meta($item_id,'_cityname',$values['_custom_options']['cityname']);
wc_add_order_item_meta($item_id,'_size',$values['_custom_options']['size']);
}
add_action( 'woocommerce_before_calculate_totals', 'update_custom_price', 1, 1 );
function update_custom_price( $cart_object ) {
foreach ( $cart_object->cart_contents as $cart_item_key => $value ) {
// Version 2.x
//$value['data']->price = $value['_custom_options']['custom_price'];
// Version 3.x / 4.x
if($value['_custom_options']['price'] == null){
echo"";
}else{
$value['data']->set_price($value['_custom_options']['price']);
}
}
}
I am getting these custom values almost everywhere except Email Notification.
Here is what normal product order edit shows:
Here is how I am getting the custom product in order edit page:
I have tried all the solution I can possibly find (filter & action hooks) but nothing works for me.
I have tried first answer from this:
add_action( 'woocommerce_checkout_create_order_line_item', 'custom_checkout_create_order_line_item', 20, 4 );
function custom_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
if( isset( $values['colorname'] ) )
$item->add_meta_data( __('DCM Shade'), $values['_colorname'] );
}
Also the common method I found everywhere:
function custom_woocommerce_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
// Get meta
$color = $order->get_meta( 'colorname', true );
// NOT empty
if( ! empty( $color ) ) {
$fields['colorname'] = array(
'label' => __( 'Shade' ),
'value' => $color,
);
}
// Get (other) meta
$shipping_email = $order->get_meta( '_cityname', true );
// NOT empty
if ( ! empty( $shipping_email ) ) {
$fields['_cityname'] = array(
'label' => __( 'City' ),
'value' => $shipping_email,
);
}
return $fields;
}
add_filter( 'woocommerce_email_order_meta_fields', 'custom_woocommerce_email_order_meta_fields', 10, 3 );
But I can't get the custom fields.
What am I doing wrong can please anyone please guide me.
I'm trying to add meta data to each product when an order has been created by using the woocommerce_checkout_create_order_line_item.
However, I can't seem to access the ID of the order.
I've used print_r($order) and can see the order details in there but I can't see the ID of the order within the object. Is this because it hasn't been generated yet?
add_action('woocommerce_checkout_create_order_line_item', array($this, 'ticket_meta_to_line_item'), 20, 4 );
function ticket_meta_to_line_item( $item, $cart_item_key, $values, $order )
{
$_p = $item->get_product();
$key = 'Draw #';
$order_id = $order->id;
error_log( print_r( $order, true ) );
if ( false !== ( $value = $_p->get_meta( $key, true ) ) )
{
$numbers = $this->add_tickets_to_order_meta($order_id, $order->get_user_id(), $_p->id);
error_log( print_r( $numbers, true ) );
$item->add_meta_data( $key , 1 , true );
}
}
If you wondering to add meta data, then there is no need to find the Order_ID, from below code you can easily do so.
function _woocommerce_add_order_item_meta_new_ver($item,$cart_key,$values) {
//HERE product_meta is just a random key I have used here, you have to use your key here
if (isset ( $values ['product_meta'] )) {
foreach ( $values ['product_meta'] as $key => $val ) {
$order_val = stripslashes( $val );
if($val) {
if($key == 'your_cart_item_key') {
$item->add_meta_data('Your Key',$order_val);
}
}
}
}
}
//This will add "Your Key" in your order_item_meta, just make sure you have used the same key "your_cart_item_key" in your cart_item_meta key too.
You can access order id using below code.
$order_id = $order->get_order_number();
Tested and works well
I'm trying to implement a text field validation for field name VoucherNumber that requires the code to be in a certain pattern which is 'WWV-'followed by 4 numbers.
I was successfully able to implement this on google docs using the following expression ^[W]WV-[0-9][0-9][0-9][0-9].
I researched through various answers and attempted to add this code in functions.php but it didn't work. It would just show that the form is being sent (spinning wheel) but it would not be sent even after 5 minutes.
add_filter( 'wpcf7_validate_text*', 'validate_voucher_number', 20, 2 );
function validate_voucher_number( $result, $tag ) {
$tag = new WPCF7_FormTag( $tag );
if ( 'VoucherNumber' == $tag->name ) {
$VoucherNumber = isset( $_POST['VoucherNumber'] ) ? trim( $_POST['VoucherNumber'] ) : '';
if ( ! preg_match ( "^[W]WV-[0-9][0-9][0-9][0-9]" , $VoucherNumber) ){
$result->invalidate( $tag, "Voucher number is invalid" );
}
}
return $result;
}
Just make sure that your field name is VoucherNumber and try this code :
add_filter( 'wpcf7_validate_text', 'vouchervalidation', 20, 2 );
function vouchervalidation( $result, $tag ) {
if ( 'VoucherNumber' == $tag->name ) {
$VoucherNumber = isset( $_POST['VoucherNumber'] ) ? trim( $_POST['VoucherNumber'] ) : '';
if ( ! preg_match ( "^[W]WV-[0-9][0-9][0-9][0-9]" , $VoucherNumber) ){
$result->invalidate( $tag, "Voucher number is invalid" );
}
}
return $result;
}
I have been trying to create a custom validation hook for Gravity Forms plugin.
The validation checks that at least one field has been filled in from a set of fields.
Check out the code below, I just can't get it too work. I think it is something to do with the variables for the inputs, even if a field is filled in, the error still shows on each field?
add_filter( 'gform_field_validation_2', function ( $result, $value, $form, $field ) {
if ( $field->type == 'number') {
$a = rgar( $value, $field->id . '10' );
$b = rgar( $value, $field->id . '12' );
$c = rgar( $value, $field->id . '13' );
$d = rgar( $value, $field->id . '14' );
$e = rgar( $value, $field->id . '15' );
$f = rgar( $value, $field->id . '17' );
$g = rgar( $value, $field->id . '18' );
$h = rgar( $value, $field->id . '20' );
$i = rgar( $value, $field->id . '21' );
$j = rgar( $value, $field->id . '22' );
$k = rgar( $value, $field->id . '23' );
if ( !empty($a) || !empty($b) || !empty($c) || !empty($d) || !empty($e) || !empty($f) || !empty($g) || !empty($h) || !empty($i) || !empty($j) || !empty($k) ) {
$result['is_valid'] = true;
$result['message'] ='';
} else {
$result['is_valid'] = false;
$result['message'] = 'Please select a quantity of materials to order';
}
}
return $result;
}, 10, 4 );
I think you maybe should use a field of type "radio buttons".
Anyway, if your form has several "number" fields and you need to validate that at least one of them has been filled, then you should use the gform_validation filter since you're validating the whole form, not just a single field.
TIP: Add a custom css class to each field in the group to identify them. for example "validate-quantity".
add_filter('gform_validation_2', 'quantity_validation', 1, 4);
function quantity_validation($validation_result) {
if ($validation_result['is_valid']) {
$valid=false;
$form = $validation_result['form'];
foreach( $form['fields'] as &$field ) {
if ( strpos( $field->cssClass, 'validate-quantity' ) === false ) {
continue;
}
$field_value = rgpost( "input_{$field['id']}" );
if (!empty($field_value)) {
$valid=true;
break;
}
}
if (!$valid) {
$field["failed_validation"] = true;
$field["validation_message"] = 'Please select a quantity of materials to order';
$validation_result['form'] = $form;
}
}
return $validation_result;
}
So heres a working version (Thanks for the gform_validation hint Francisco R) - Went down a slightly different route, but works perfectly, incase anyone interested in future!
add_filter( 'gform_validation_2', 'custom_validation_2' );
function custom_validation_2( $validation_result ) {
// array of field IDs to be checked
$field_ids = array (10, 12, 13, 14, 15, 17, 18, 20, 21, 23, 22);
// get the form object from the validation result
$form = $validation_result['form'];
// counter to store how many fields have a value > 0 submitted
$number_of_fields = 0;
// loop through all the fields to be sure one has a value > 0
foreach ( $field_ids as $input ) {
// the rgpost string we are going to check
$input_id = 'input_' . intval( $input );
// the value that was submitted
$input_value = rgpost ( $input_id );
if ( $input_value > 0 ) {
// if any field in the array has a value, we can just continue
$number_of_fields++;
} // end if
else {
// no value for this input, so continue without incrementing the counter
continue;
} // end else
} // end foreach
// check the $number_of_fields and if it is 0 return a validation error
if ( $number_of_fields == 0 ){
// set the form validation to false
$validation_result['is_valid'] = false;
// mark all the fields with a validation error
foreach( $form['fields'] as &$field ) {
// add a validation error to *all* the inputs if none were submitted > 0
if ( in_array( $field->id, $field_ids ) ) {
$field->failed_validation = true;
$field->validation_message = 'Please select a quantity of materials to order from one or all of these fields.';
} // end if
} // end foreach
} // end if
// assign modified $form object back to the validation result
$validation_result['form'] = $form;
return $validation_result;
}
It looks you should change your if clause to:
if ( empty($a) || empty($b) || empty($c) || empty($d) || empty($e) || empty($f) || empty($g) || empty($h) || empty($i) || empty($j) || empty($k) ) {
to validate if at least one option is selected.
To skip not targeted fields add the following code before complex if above:
$target_fields = array('name_1', 'name_2');
if (!in_array($field, $target_fields)) {
$result['is_valid'] = true;
$result['message'] = '';
}