In wordpress I'm using Contact Form 7. I want to create a order form. But the order quantity has to have a minimum of 2 products. When people order less then two products they have to get a message that it's not possible.
There are a total of 6 different products people can order. Each product can ben orderd as many as they like.
Any ideas how I can make this work?
I found a way. I've created a new filter for the Contact Form
Code below:
add_filter( 'wpcf7_validate_number*', 'custom_number_confirmation_validation_filter', 20, 2 );
function custom_number_confirmation_validation_filter( $result, $tag ) {
$tag = new WPCF7_Shortcode( $tag );
$var1 = isset( $_POST['your_number1'] ) ? trim( $_POST['your_number1'] ) : '';
$var2 = isset( $_POST['your_number2'] ) ? trim( $_POST['your_number2'] ) : '';
$var3 = isset( $_POST['your_number3'] ) ? trim( $_POST['your_number3'] ) : '';
$var4 = isset( $_POST['your_number4'] ) ? trim( $_POST['your_number4'] ) : '';
$var5 = isset( $_POST['your_number5'] ) ? trim( $_POST['your_number5'] ) : '';
$var6 = isset( $_POST['your_number6'] ) ? trim( $_POST['your_number6'] ) : '';
$varNumber = '2';
if ( $var1 + $var2 + $var3 + $var4 + $var5 + $var6 < $varNumber) {
$result->invalidate( $tag, "Order a minimum of 2!" );
}
return $result;}
Replace your_number# with the name of the field in Contact Form 7
Related
I need to secure a big SQL statement has a lot of conditions in its WHERE clause so I made an array for WHERE clause using $wpdb->prepare properly BUT an error happened while join this array together as a string in the final statement.
Here is some of my code .. Is that secure enough or it may cause an SQL injection?
P.S. I try to make another $wpdb->prepare in the last get_row function but the join function made quotes before and after WHERE clause so the statement generates an error.
foreach( $args as $field => $field_value ) {
if( ! is_null( $field_value ) ) {
switch( $field ) {
case 'id': {
if( is_numeric( $field_value ) && ( intval( $field_value ) > 0 ) ) {
$where[] = $wpdb->prepare( 'tbl_names.id = %d', $field_value );
}
} break;
case 'name': {
$where[] = $wpdb->prepare( 'tbl_names.name = %s', $field_value );
} break;
}
}
}
// NOT Working
return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$tbl_names} tbl_names WHERE %s", join( ' AND ', $where ) ), ARRAY_A );
// Working Good .. BUT Is it Safe??
return $wpdb->get_row( ( "SELECT * FROM {$tbl_names} tbl_names WHERE " . join( ' AND ', $where ) ), ARRAY_A );
Unfortunately, I think this will be the only answer for a while.
$count = 0;
$query = "SELECT * FROM {$tbl_names} tbl_names";
foreach( $args as $field => $field_value ) {
if( ! is_null( $field_value ) ) {
$count++;
$query .= ( 1 == $count ) ? ' WHERE ' : ' AND ';
switch( $field ) {
case 'id': {
$query .= $wpdb->prepare( 'tbl_names.id = %d', $field_value );
} break;
case 'name': {
$query .= $wpdb->prepare( 'tbl_names.name = %s', $field_value );
} break;
}
}
}
return $wpdb->get_row( $query, ARRAY_A );
I try to format some products price using a custom field (unit_price). My value is 3.2 (3,2) but the code doesn't recognize comma or dot and it shows only 3
Is there any way I could achieve showing the full value?
Any help is appreciated.
function cw_change_product_html( $price_html, $product )
{
$unit_price = get_post_meta( $product->id, 'unit_price', true );
if ( ! empty( $unit_price ) ) {
$price_html = '<span class="amount">' . wc_price( $unit_price ) . ' per kg</span>';
}
return $price_html;
}
add_filter( 'woocommerce_get_price_html', 'cw_change_product_html', 10, 2 );
function cw_change_product_price_cart( $price, $cart_item, $cart_item_key )
{
$unit_price = get_post_meta( $cart_item['product_id'], 'unit_price', true );
if ( ! empty( $unit_price ) )
{
$price = wc_price( $unit_price ) . ' per kg';
}
return $price;}
add_filter( 'woocommerce_cart_item_price', 'cw_change_product_price_cart', 10, 3 );`
Please try dumping the output(just for better understanding the variable) from $unit_price = get_post_meta( $product->id, 'unit_price', true ); as
var_dump($unit_price);
This will return string. Then all you have to convert string into float
$unit_price= floatval($unit_price);
Then you can use wc_price( $unit_price ).
Check documentation http://woocommerce.wp-a2z.org/oik_api/wc_price/ as $price is float value
I've got a webshop running with woocommerce. The webshop has products with variations. When I add the same product with the same variation, I want it to generate a new order_item_id, in stead of combining the two under the same order_item_id.
I can't seem to find the bit of code that is responsible for generating the order_item_id.
Could anyone tell me where this bit of code is located?
My goal is to make each product unique in stead of stacking items that are the same.
-EDIT
Ok, so I've narrowed it down to class-wc-cart.php
On line 782 the product ID is generated with the following code:
public function generate_cart_id( $product_id, $variation_id = '', $variation = '', $cart_item_data = array() ) {
$id_parts = array( $product_id );
if ( $variation_id ) $id_parts[] = $variation_id;
if ( is_array( $variation ) ) {
$variation_key = '';
foreach ( $variation as $key => $value ) {
$variation_key .= trim( $key ) . trim( $value );
}
$id_parts[] = $variation_key;
}
if ( is_array( $cart_item_data ) && ! empty( $cart_item_data ) ) {
$cart_item_data_key = '';
foreach ( $cart_item_data as $key => $value ) {
if ( is_array( $value ) ) $value = http_build_query( $value );
$cart_item_data_key .= trim($key) . trim($value);
}
$id_parts[] = $cart_item_data_key;
}
return md5( implode( '_', $id_parts ) );
}
Now all that is left is to edit in a unique ID via a timestamp or something.
Will keep you guys posted.
Solved it.
Open class-wc-cart.php, and add a timestamp, or anything else that is unique to $id_parts.
Just like in the following code:
public function generate_cart_id( $product_id, $variation_id = '', $variation = '', $cart_item_data = array() ) {
$id_parts = array( $product_id );
if ( $variation_id ) $id_parts[] = $variation_id.time();
if ( is_array( $variation ) ) {
$variation_key = '';
foreach ( $variation as $key => $value ) {
$variation_key .= trim( $key ) . trim( $value );
}
$id_parts[] = $variation_key.time();
}
if ( is_array( $cart_item_data ) && ! empty( $cart_item_data ) ) {
$cart_item_data_key = '';
foreach ( $cart_item_data as $key => $value ) {
if ( is_array( $value ) ) $value = http_build_query( $value );
$cart_item_data_key .= trim($key) . trim($value);
}
$id_parts[] = $cart_item_data_key.time();
}
return md5( implode( '_', $id_parts ) );
}
I followed this link and created my own custom query with pagination.. but I don't really understand how the offset works,
https://wordpress.stackexchange.com/questions/21626/pagination-with-custom-sql-query
the pagination does not work well. and I'm getting zero value for offset.
function spiciest(){
global $wpdb, $paged, $max_num_pages;
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$post_per_page = intval(get_query_var('posts_per_page')); //6
$offset = ($paged - 1)*$post_per_page;
/* Custom sql here. I left out the important bits and deleted the body
as it will be specific when you have your own. */
$sql = "
SELECT DISTINCT * FROM $wpdb->posts
INNER JOIN (SELECT *, SUBSTRING(name, 6) as 'post_ID',
votes_up AS votes_balance,
votes_up + votes_down AS votes_total
FROM thumbsup_items) AS thumbsup
ON $wpdb->posts.ID = thumbsup.post_ID
WHERE $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
AND $wpdb->posts.post_password = ''
ORDER BY votes_up DESC, votes_balance DESC
LIMIT ".$offset.", ".$post_per_page."; ";
$sql_result = $wpdb->get_results( $sql, OBJECT);
/* Determine the total of results found to calculate the max_num_pages
for next_posts_link navigation */
$sql_posts_total = $wpdb->get_var( "SELECT FOUND_ROWS();" );
$max_num_pages = ceil($sql_posts_total / $post_per_page);
print_r("offset ". $offset."\n") ;
print_r("\n"."sql_posts_total ". $sql_posts_total."\n") ;
print_r("\n"."max_num_pages ". $max_num_pages."\n") ;
return $sql_result;
}
Please see it live.. I have printed the vlues.. http://goo.gl/fZTck
It should have 7 pages with a total of 39 entries.
The problem here is the LIMIT, it'll just count the first page and not the entire query.
I had solved it by providing a secondary SQL query for counting the max pages. thanks for my friends for this tip.
here's the complete code.
function.php
function spiciest(){
global $wpdb, $paged, $max_num_pages;
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$post_per_page = intval(get_query_var('posts_per_page')); //6
$offset = ($paged - 1)*$post_per_page;
// query normal post
$query_spicy = "
SELECT DISTINCT * FROM $wpdb->posts
INNER JOIN (SELECT *, SUBSTRING(name, 6) as 'post_ID',
votes_up AS votes_balance,
votes_up + votes_down AS votes_total
FROM thumbsup_items) AS thumbsup
ON $wpdb->posts.ID = thumbsup.post_ID
WHERE $wpdb->posts.post_status = 'publish'
AND $wpdb->posts.post_type = 'post'
AND $wpdb->posts.post_password = ''
ORDER BY votes_up DESC, votes_balance DESC";
//query the posts with pagination
$spicy = $query_spicy . " LIMIT ".$offset.", ".$post_per_page."; ";
$spicy_results = $wpdb->get_results( $spicy, OBJECT);
// run query to count the result later
$total_result = $wpdb->get_results( $query_spicy, OBJECT);
$total_spicy_post = count($total_result);
$max_num_pages = ceil($total_spicy_post / $post_per_page);
return $spicy_results;
}
TEMPLATE CODES:
<?php
$spiciest = spiciest();
if ($spiciest):
global $post;
foreach ($spiciest as $post) :
setup_postdata($post);
?>
/**** PUT TEMPLATE TAGS HERE *****/
<?php
endforeach;
endif;
?>
and then the PAGINATION here, please note of the TOTAL in array.
global $wp_rewrite, $wp_query, $max_page, $page;
$wp_query->query_vars['paged'] > 1 ? $current = $wp_query->query_vars['paged'] : $current = 1;
$pagination = array(
'base' => #add_query_arg('page','%#%'),
'format' => '',
'total' => $max_num_pages,
'current' => $current,
'prev_text' => __('PREV'),
'next_text' => __('NEXT'),
'end_size' => 1,
'mid_size' => 2,
'show_all' => false,
'type' => 'list'
);
if ( $wp_rewrite->using_permalinks() )
$pagination['base'] = user_trailingslashit( trailingslashit( remove_query_arg( 's', get_pagenum_link( 1 ) ) ) . 'page/%#%/', 'paged' );
if ( !empty( $wp_query->query_vars['s'] ) )
$pagination['add_args'] = array( 's' => get_query_var( 's' ) );
echo paginate_links( $pagination );
Your variable $offset value is always the same.
So just replace
$offset = 1;
with:
$offset = ($paged - 1)*$post_per_page;
I have the below function in Wordpress.
However, the meta key product_price is duplicated each time a post is updated.
Like this image
Is there any way to prevent this?
function do_my_stuff($post_ID) {
global $post,$wpdb;
$tablename="wp_cart66_products";
if($post->post_type == "post" && strlen( get_post_meta($post_ID, 'price', true))>0 )
{
$id = $wpdb->get_var("SELECT id FROM ".$tablename." WHERE id=".$post_ID);
$cny = get_post_meta($post->ID, 'price', true);
/*Shipping rate */
if( $cny < 50 )
$shipping = 14.97;
else if( $cny >= 50 && $cny < 200 )
$shipping = 22.59;
else if( $cny >= 200 && $cny < 250 )
$shipping = 24.59;
else if( $cny >= 250 && $cny < 300 )
$shipping = 26.60;
else if( $cny >= 300 )
$shipping = 29.27;
/*Exchange rate CNY to EURO */
$cny_to_euro = 0.124;
$euro = $cny * $cny_to_euro ;
$price = $euro + $shipping;
$price = number_format($price,2);
$data=array(
'id'=>$post_ID,
'item_number'=>get_post_meta($post->ID, 'scode', true),
'name'=>$post->post_title,
'price'=>$price,
'options_1'=>get_post_meta($post->ID, 'variations', true),
'shipped'=>'1',
);
$where = array("id" => $post_ID);
// Possible format values: %s as string; %d as decimal number; and %f as float.
$format=array( '%d', '%s', '%s', '%s', '%s', '%d');
$where_format = array( '%d' );
if($id>0){
// update
$wpdb->update( $tablename,$data, $where, $format, $where_format);
}else{
// insert
$wpdb->insert( $tablename,$data,$format);
}
AddMetaPrice ( $post_ID ) ;
}
return $post_ID;
}
function AddMetaPrice ( $post_ID )
{
// init
global $post,$wpdb;
// We add the wordpress post ID and price to a meta tag
$metaKey = "product_price" ;
$tableName = "wp_cart66_products" ;
$metaQuery = "SELECT price FROM $tableName WHERE id='$post_ID'" ;
$metaValue = $wpdb->get_var( $metaQuery ) ;
$tableName = "wp_postmeta" ;
// Do we have this post already?
if ( $id > 0 )
{
// this already exists. we only need to update
// $metaQuery = "UPDATE $tableName SET meta_value='$metaValue' WHERE meta_key='$metaKey' AND post_id='$id'" ; // we use wordpress's method instead
$data = array ( "meta_value" => $metaValue ) ;
$where = array ( "meta_key" => $metaKey, "post_id" => $post_ID ) ;
$wpdb->update( $tableName, $data, $where ) ;
}
else
{
// this is not created, we need to create it now (insert)
// $metaQuery = "INSERT INTO $tableName (post_id, meta_key, meta_value) VALUES ('$id', '$metaKey', '$metaValue')" ; // we use wordpress's method instead
$data = array ( "post_id" => $post_ID, "meta_key" => $metaKey, "meta_value" => $metaValue ) ;
$wpdb->insert( $tableName, $data ) ;
}
}
add_action('publish_post', 'do_my_stuff');
I've read here that a ON DUPLICATE KEY statement exists. But i'm not sure if it can be implemented in the above code.
Try replacing that piece of code:
if ( $metaValue !== NULL )
{
update_post_meta($post_ID, $metaKey, $metaValue); // use built-in function instead
}
where it was:
// Do we have this post already?
if ( $id > 0 )
{
// this already exists. we only need to update
// $metaQuery = "UPDATE $tableName SET meta_value='$metaValue' WHERE meta_key='$metaKey' AND post_id='$id'" ; // we use wordpress's method instead
$data = array ( "meta_value" => $metaValue ) ;
$where = array ( "meta_key" => $metaKey, "post_id" => $post_ID ) ;
$wpdb->update( $tableName, $data, $where ) ;
}