Wordpress Phone + Custom field Validation - wordpress

I'm a newbie in PHP, I use this PHP code that works like a charm. It's a custom form that sends to Woocommerce different fields. I want to add a "preg_match" check for each of those fields so the user can only enter:
function custom_multi_step_form_first_handler() {
$email = sanitize_text_field( strval( $_POST['email'] ) );
$first_name = sanitize_text_field( strval( $_POST['first_name'] ) );
$last_name = sanitize_text_field( strval( $_POST['last_name'] ) );
$phone = sanitize_text_field( strval( $_POST['phone'] ) );
$street = sanitize_text_field( strval( $_POST['street'] ) );
$city = sanitize_text_field( strval( $_POST['city'] ) );
$postcode = sanitize_text_field( strval( $_POST['postcode'] ) );
$person_id = sanitize_text_field( strval( $_POST['person_id'] ) );
$country = 'UK';
global $woocommerce;
$address = array(
'first_name' => $first_name,
'last_name' => $last_name,
'company' => '',
'email' => $email,
'phone' => $phone,
'address_1' => $street,
'city' => $city,
'state' => '',
'postcode' => $postcode,
'country' => $country,
);
$order = wc_create_order();
$order->set_address( $address, 'billing' );
$order->calculate_totals();
$_SESSION['current_order_id'] = $order->get_id();
update_post_meta( $order->get_id(), 'person_id', $person_id );
wp_die();
}
function custom_get_building_data_for_postcode( $postcode ) {
$building = get_page_by_title( $postcode, null, 'building' );
$building_meta = get_post_meta( $building->ID );
if ( is_null( $building ) ) {
return array();
}
return array(
'name' => get_post_meta( $building->ID, 'building_name', true ),
'city' => get_post_meta( $building->ID, 'building_city', true ),
'address' => get_post_meta( $building->ID, 'building_address', true ),
);
}
In the phone field: numbers, "+", spaces; (22 chars total)
In the postcode field: postcodes are contained in a custom post type "Buildings" with their titles as values. Only those values. How do I do that?

Related

How to create a Woo commerce Subscription order by function or custom code? [duplicate]

I want to create an order (programmatically) of a Subscription Product. I found code from this question: Programmatically creating new order in Woocommerce, which I used to try make it work.
I was not able to make it work neither with a "Simple Subscription" nor a "Simple Product".
function create_vip_order() {
global $woocommerce;
$product_id = 123;
$address = array(
'first_name' => '111Joe',
'last_name' => 'Conlin',
'company' => 'Speed Society',
'email' => 'joe#testing.com',
'phone' => '760-555-1212',
'address_1' => '123 Main st.',
'address_2' => '104',
'city' => 'San Diego',
'state' => 'Ca',
'postcode' => '92121',
'country' => 'US'
);
// Now we create the order
$order = wc_create_order();
// The add_product() function below is located in /plugins/woocommerce/includes/abstracts/abstract_wc_order.php
$order->add_product( get_product( $product_id ), 1 ); // This is an existing SIMPLE product
$order->set_address( $address, 'billing' );
//
$order->calculate_totals();
$order->update_status("Completed", 'Imported order', TRUE);
}
add_action( 'woocommerce_checkout_process', 'create_vip_order' );
If you have any solution I would really appreciate it. :)
Best Regards, Ledung
EDIT: It seem the way my Product were set up was causing the function not to work. I am currently using a Simple Subscription Product, with the "Virtual" parameter checked and a subscription length of 3 months.
Here you can see the current code that work with my setup:
function create_test_sub() {
$email = 'test#test.se';
$start_date = date( "Y-m-d H:i:s", strtotime( "now" ) );
$address = array(
'first_name' => 'Firstname',
'last_name' => 'Secondname',
'company' => 'Company',
'email' => $email,
'phone' => '',
'address_1' => 'Streetname 123',
'address_2' => '',
'city' => 'City',
'postcode' => '12345',
'country' => 'Country'
);
$default_password = wp_generate_password();
if ( ! $user = get_user_by( 'login', $email ) ) $user = wp_create_user( $email, $default_password, $email );
// I've used one product with multiple variations
$parent_product = wc_get_product( 3901 );
$args = array(
'attribute_billing-period' => 'Yearly',
'attribute_subscription-type' => 'Both'
);
$product_variation = $parent_product->get_matching_variation( $args );
$product = wc_get_product( $product_variation );
$product_month_length = $parent_product->subscription_length;
$end_date = date( "Y-m-d H:i:s", strtotime( $product_month_length . "months" ) );
$quantity = 1;
// As far as I can see, you need to create the order first, then the sub
$order = wc_create_order( array( 'customer_id' => $user->id ) );
$order->add_product( $parent_product, $quantity, $args );
$order->set_address( $address, 'billing' );
$order->set_address( $address, 'shipping' );
$order->calculate_totals();
$order->update_status( "completed", 'Imported order', TRUE );
// Order created, now create sub attached to it -- optional if you're not creating a subscription, obvs
// Each variation has a different subscription period
$period = WC_Subscriptions_Product::get_period( $parent_product );
$interval = WC_Subscriptions_Product::get_interval( $product );
$sub = wcs_create_subscription( array( 'status' => 'active', 'order_id' => $order->id, 'billing_period' => $period, 'billing_interval' => $interval, 'start_date' => $start_date, 'end' => $end_date ) );
if ( ! is_wp_error( $sub ) ){
$sub->add_product( $parent_product, $quantity, $args );
$sub->set_address( $address, 'billing' );
$sub->set_address( $address, 'shipping' );
$dates = array(
'end' => $end_date,
);
$sub->update_dates( $dates );
$sub->calculate_totals();
}
WC_Subscriptions_Manager::activate_subscriptions_for_order( $order );
print "<a href='/wp-admin/post.php?post=" . $sub->id . "&action=edit'>Sub created! Click here to edit</a>";
$returnarray = array(
'subscription_id' => $sub->id,
'order_id' => $order->id,
);
return $returnarray;
}
$test = create_test_sub();
Here's my custom function I built based on all the answers I found on SO and digging through subscriptions code base.
Tested with
WordPress 5.2.5
WooCommerce 3.8.0
WooCommerce Subscriptions 2.6.1
https://gist.github.com/tripflex/a3123052f36daf18f7cb05391d752223
function give_user_subscription( $product, $user_id, $note = '' ){
// First make sure all required functions and classes exist
if( ! function_exists( 'wc_create_order' ) || ! function_exists( 'wcs_create_subscription' ) || ! class_exists( 'WC_Subscriptions_Product' ) ){
return false;
}
$order = wc_create_order( array( 'customer_id' => $user_id ) );
if( is_wp_error( $order ) ){
return false;
}
$user = get_user_by( 'ID', $user_id );
$fname = $user->first_name;
$lname = $user->last_name;
$email = $user->user_email;
$address_1 = get_user_meta( $user_id, 'billing_address_1', true );
$address_2 = get_user_meta( $user_id, 'billing_address_2', true );
$city = get_user_meta( $user_id, 'billing_city', true );
$postcode = get_user_meta( $user_id, 'billing_postcode', true );
$country = get_user_meta( $user_id, 'billing_country', true );
$state = get_user_meta( $user_id, 'billing_state', true );
$address = array(
'first_name' => $fname,
'last_name' => $lname,
'email' => $email,
'address_1' => $address_1,
'address_2' => $address_2,
'city' => $city,
'state' => $state,
'postcode' => $postcode,
'country' => $country,
);
$order->set_address( $address, 'billing' );
$order->set_address( $address, 'shipping' );
$order->add_product( $product, 1 );
$sub = wcs_create_subscription(array(
'order_id' => $order->get_id(),
'status' => 'pending', // Status should be initially set to pending to match how normal checkout process goes
'billing_period' => WC_Subscriptions_Product::get_period( $product ),
'billing_interval' => WC_Subscriptions_Product::get_interval( $product )
));
if( is_wp_error( $sub ) ){
return false;
}
// Modeled after WC_Subscriptions_Cart::calculate_subscription_totals()
$start_date = gmdate( 'Y-m-d H:i:s' );
// Add product to subscription
$sub->add_product( $product, 1 );
$dates = array(
'trial_end' => WC_Subscriptions_Product::get_trial_expiration_date( $product, $start_date ),
'next_payment' => WC_Subscriptions_Product::get_first_renewal_payment_date( $product, $start_date ),
'end' => WC_Subscriptions_Product::get_expiration_date( $product, $start_date ),
);
$sub->update_dates( $dates );
$sub->calculate_totals();
// Update order status with custom note
$note = ! empty( $note ) ? $note : __( 'Programmatically added order and subscription.' );
$order->update_status( 'completed', $note, true );
// Also update subscription status to active from pending (and add note)
$sub->update_status( 'active', $note, true );
return $sub;
}

Woocommerce custom_fields(Shipping and Billing) in email_order_meta_fields

I'm trying to store custom shipping and billing fields in order and then to be print in emails ( admin & customer ) but with no success , is there anyone with big heart to help me ?
So as you can see i removed some fields , added other fields in Shipping & Billing then i try to store data of order and at the last i try to send my extra fields in order_email .
Here is my code in functions.php
// Replace billing_email with shipping_email " This because custome don recieve email notification if don't ask invoice "
add_action('woocommerce_checkout_update_order_meta', 'set_billing_email_from_shipping_email', 50, 2 );
function set_billing_email_from_shipping_email( $order_id, $data ) {
// Get customer shipping email
$email = get_post_meta( $order_id, '_shipping_email', true );
// Set billing email from shipping email
update_post_meta( $order_id, '_billing_email', $email );
}
// Remove fields
add_filter( 'woocommerce_checkout_fields', 'wc_remove_checkout_fields' );
function wc_remove_checkout_fields( $fields ) {
// Billing fields
unset( $fields['billing']['billing_first_name'] );
unset( $fields['billing']['billing_last_name'] );
unset( $fields['billing']['billing_address_2'] );
// Shipping fields
unset( $fields['shipping']['shipping_address_2'] );
unset( $fields['shipping']['shipping_company'] );
// Order fields
unset( $fields['order']['order_comments'] );
return $fields;
}
//Add custom fields
add_filter( 'woocommerce_shipping_fields' , 'custom_shipping_fields' );
function custom_shipping_fields( $fields ) {
$fields['shipping_email'] = array(
'label' => __( 'Email', 'woocommerce' ),
'required' =>true,
'class' => array( 'form-row-last' ),
'validate' => array( 'email' ),
);
$fields['shipping_phone'] = array(
'label' => __( 'Telefono', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-first' ),
'clear' => true,
'validate' => array( 'phone' ),
);
$fields['shipping_invoice'] =array(
'type' => 'checkbox',
'class' => array('form-row-four'),
'label' => __(' Fattura ?'),
'label_class' => array('woocommerce-form__label l_checkbox'),
'input_class' => array('woocommerce-form__input woocommerce-form__input-checkbox i_checkbox'),
);
return $fields;
}
add_filter( 'woocommerce_billing_fields' , 'custom_billing_fields' );
function custom_billing_fields( $fields ) {
$fields['billing_vat'] = array(
'label' => __( 'P.Iva/CF', 'woocommerce' ),
'required' =>false,
'class' => array( 'form-row-last' ),
);
return $fields;
};
function custom_shipping_save_extra_checkout_fields( $order_id, $posted ){
if( isset( $posted['custom_shipping_fields'] ) ) {
update_post_meta( $order_id, '_custom_shipping_fields', sanitize_text_field( $posted['_custom_shipping_fields'] ) );
}
}
function custom_billing_save_extra_checkout_fields( $order_id, $posted ){
if( isset( $posted['custom_shipping_fields'] ) ) {
update_post_meta( $order_id, '_custom_shipping_fields', sanitize_text_field( $posted['_custom_shipping_fields'] ) );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'custom_save_extra_checkout_fields', 10, 2 );
function custom_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
$fields['custom_shipping_fields'] = array(
'label' => __( 'Custom Siping Fields' ),
'value' => get_post_meta( $order->id, '_custom_shipping_fields', true ),
);
return $fields;
}
add_filter('woocommerce_email_order_meta_fields', 'custom_email_order_meta_fields', 10, 3 );
Thank you!

Display product category on the WooCommerce checkout page

I'm trying to add the product category to the below (working) code but I'm not sure how to go about it.
I've tried using product_cat but as I'm not that experienced with php, I'm just guessing how to achieve this.
add_filter( 'woocommerce_get_item_data', 'display_custom_product_field_data', 10, 2 );
function display_custom_product_field_data( $cart_data, $cart_item ) {
$meta_keys = array('time','date');
$dictionary = array('time'=>'Time:','date'=>'Date:' );
$product_id = $cart_item['product_id'];
foreach($meta_keys as $key=>$meta_key){
$meta_value = get_post_meta( $product_id, $meta_key, true );
if( !empty( $cart_data ) ) $custom_items = $cart_data;
if( !empty($meta_value) ) {
$custom_items[] = array(
'key' => __( $dictionary[$meta_key] , 'woocommerce'), //or user $meta_key
'value' => $meta_value,
'display' => $meta_value,
);
}
}
return $custom_items;
}
Following code will also display the product categories on the WooCommerce checkout page
function display_custom_product_field_data( $cart_item_data, $cart_item ) {
// Product ID
$product_id = $cart_item['product_id'];
// Get post meta
$time = get_post_meta( $product_id, 'time', true );
// NOT empty
if( ! empty( $time ) ) {
$cart_item_data[] = array(
'key' => __( 'Time', 'woocommerce'),
'value' => $time,
);
}
// Get terms
$term_names = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'names' ) );
if( ! empty( $term_names ) ) {
$cart_item_data[] = array(
'key' => __( 'Categories', 'woocommerce'),
'value' => implode( ", ", $term_names )
);
}
// Get post meta
$date = get_post_meta( $product_id, 'date', true );
// NOT empty
if( ! empty( $date ) ) {
$cart_item_data[] = array(
'key' => __( 'Date', 'woocommerce'),
'value' => $date,
);
}
return $cart_item_data;
}
add_filter( 'woocommerce_get_item_data', 'display_custom_product_field_data', 10, 2 );

Woocommerce Product list by IDs return only one product instead multiple selected

WooCommerce featured product widget with selected id's but only one product return.
My goal is I have some product ids like 1202,125,2152,885,1254 I need to display them as a list
I make a metabox where i select product and get the ids and store them as $featured
where $featured returned the output like 1202,125,2152,885,1254.
I use $query_args['post__in'] = array($featured); but the result output only one product instead of selected 5 products.
Can any one help me with is ?
Full code
<?php
defined( 'ABSPATH' ) || exit;
class FPW_Widget_Featured_Products extends WC_Widget {
public function __construct() {
$this->widget_cssclass = 'woocommerce widget_products';
$this->widget_description = __( "A list of your store's products.", 'woocommerce' );
$this->widget_id = 'fpw_widget_featured_products';
$this->widget_name = __( 'FPW Featured Product', 'woocommerce' );
$this->settings = array(
'title' => array(
'type' => 'text',
'std' => __( 'Featured Product', 'woocommerce' ),
'label' => __( 'Title', 'woocommerce' ),
),
'number' => array(
'type' => 'number',
'step' => 1,
'min' => 1,
'max' => 10,
'std' => 5,
'label' => __( 'Number of products to show from selected', 'woocommerce' ),
),
);
parent::__construct();
}
/**
* Query the products and return them.
*
* #param array $args Arguments.
* #param array $instance Widget instance.
*
* #return WP_Query
*/
public function get_products( $args, $instance ) {
global $post;
$featured = get_post_meta($post->ID, '_blog_feature_product',true);
$number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : $this->settings['number']['std'];
$product_term_ids = wc_get_product_visibility_term_ids();
$query_args = array(
'posts_per_page' => $number,
'post_status' => 'publish',
'post_type' => 'product',
'meta_query' => array(),
'tax_query' => array(
'relation' => 'AND',
),
); // WPCS: slow query ok.
if ( 'yes' === get_option( 'woocommerce_hide_out_of_stock_items' ) ) {
$query_args['tax_query'][] = array(
array(
'taxonomy' => 'product_visibility',
'field' => 'term_taxonomy_id',
'terms' => $product_term_ids['outofstock'],
'operator' => 'NOT IN',
),
); // WPCS: slow query ok.
}
if ( ! empty( $featured ) && is_array( $featured ) ) {
$featured = implode( ',', array_map( 'absint', $featured ) );
$query_args['post__in'] = array($featured);
}else{
$query_args['post__in'] = '';
}
return new WP_Query($query_args);
}
/**
* Output widget.
*
* #param array $args Arguments.
* #param array $instance Widget instance.
*
* #see WP_Widget
*/
public function widget( $args, $instance ) {
if ( $this->get_cached_widget( $args ) ) {
return;
}
ob_start();
$products = $this->get_products( $args, $instance );
if ( $products && $products->have_posts() ) {
$this->widget_start( $args, $instance );
echo wp_kses_post( apply_filters( 'woocommerce_before_widget_product_list', '<ul class="product_list_widget">' ) );
$template_args = array(
'widget_id' => $args['widget_id'],
'show_rating' => true,
);
while ( $products->have_posts() ) {
$products->the_post();
wc_get_template( 'content-widget-product.php', $template_args );
}
echo wp_kses_post( apply_filters( 'woocommerce_after_widget_product_list', '</ul>' ) );
$this->widget_end( $args );
}
wp_reset_postdata();
echo $this->cache_widget( $args, ob_get_clean() ); // WPCS: XSS ok.
}
}
function fpw_register_featured_products_widgets() {
register_widget( 'FPW_Widget_Featured_Products' );
}
add_action( 'widgets_init', 'fpw_register_featured_products_widgets' );
If you are passing the values to $featured variable as an array when using $featured = get_post_meta($post->ID, '_blog_feature_product',true);
Then you don't need to use this
$featured = implode( ',', array_map( 'absint', $featured ) );
$query_args['post__in'] = array($featured);
Instead simply use this:
$query_args['post__in'] = $featured;
And if the values passes to $featured as comma separated i.e $featured = "1,2,3,4,5";
Then use this
$query_args['post__in'] = explode( ",", $featured);
This should work fine now.

Database insert in order-details page of WooCommerce is not working

I am trying to do an insert to a MySQL database in WordPress using $wpdb->insert. It is just a simple log, but it is not working.
I am trying to save some basic items from an order I received after a purchase made in WooCommerce. The page to which I added the code is order-details.php and belongs to WooCommerce.
The code:
<?php
do_action( 'woocommerce_order_details_before_order_table_items', $order );
$fecha = date('Y-m-d H:i:s');
$creditos =0;
foreach ( $order_items as $item_id => $item ) {
$item_quantity = $item->get_quantity();
$product = $item->get_product();
$product_name = $product->get_name();
if( $product_name == "orián (paquete mínimo)"){
$creditos=15;
}
if( $product_name == "Andrómeda (paquete medio)"){
$creditos=30;
}
if( $product_name == "Lira (paquete básico)"){
$creditos=50;
}
if( $product_name == "Cisne (paquete real + 15 créditos)"){
$creditos=65;
}
if( $product_name == "Perseo (Paquete Premium + 30 créditos)"){
$creditos=120;
}
echo $item_quantity." ".$product_name." ".$creditos." ".$fecha." ".get_current_user_id();
$wpdb->insert(
'registrorden',
array(
'idusuario' => get_current_user_id(),
'paquete' => $product_name,
'cantidad' => $item_quantity,
'creditos' => $creditos
),
array(
'%d',
'%s',
'%d',
'%d'
)
);
wc_get_template( 'order/order-details-item.php', array(
'order' => $order,
'item_id' => $item_id,
'item' => $item,
'show_purchase_note' => $show_purchase_note,
'purchase_note' => $product ? $product->get_purchase_note() : '',
'product' => $product,
) );
}
do_action( 'woocommerce_order_details_after_order_table_items', $order );
?>
The code I added:
$wpdb->insert(
'registrorden',
array(
'idusuario' => get_current_user_id(),
'paquete' => $product_name,
'cantidad' => $item_quantity,
'creditos' => $creditos
),
array(
'%d',
'%s',
'%d',
'%d'
)
);
Here is a snapshot of the table, and here is the error.
What can I do to fix this?

Resources