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
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;
}
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!
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 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.
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?