Run Query within Wordpress - php

I need to run this query every time my client uploads a product, so how do I run this query within Wordpress? I want to tie it to an action in the functions.php
UPDATE wp_postmeta
JOIN wp_posts ON wp_posts.id = wp_postmeta.post_id
SET wp_postmeta.meta_value = 'no'
WHERE (wp_posts.post_title = '4x6' AND wp_postmeta.meta_key = '_virtual')

Add this code in your functions.php:
function on_product_publish( $new_status, $old_status, $post ) {
global $post;
if ( 'publish' !== $new_status or 'publish' === $old_status ) return;
$wpdb->query("UPDATE wp_postmeta
JOIN wp_posts ON wp_posts.id = wp_postmeta.post_id
SET wp_postmeta.meta_value = 'no'
WHERE (wp_posts.post_title = '4x6' AND wp_postmeta.meta_key = '_virtual')");
}
add_action( 'transition_post_status', 'on_product_publish', 10, 3 );

Related

Display total revenue of a product id in WooCommerce shortcode

I am trying to display the total revenue of a given product ID from WooCommerce via a shortcode. I have code this far with the code however I cannot seem to get it to work correctly by selecting the individual ID, at the moment it is showing it for the whole store.
function get_total_sales( $atts ) {
$atts = shortcode_atts( array(
'id' => ''), $atts );
global $wpdb;
$order_totals = apply_filters( 'woocommerce_reports_sales_overview_order_totals', $wpdb->get_row( "
SELECT SUM(meta.meta_value), ['id'], AS total_sales, COUNT(posts.ID) AS total_orders FROM {$wpdb->posts} AS posts
LEFT JOIN {$wpdb->postmeta} AS meta ON posts.ID = meta.post_id
LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID=rel.object_ID
LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id )
LEFT JOIN {$wpdb->terms} AS term USING( term_id )
WHERE meta.meta_key = '_order_total'
AND posts.post_type = 'shop_order'
AND posts.post_status IN ( 'wc-" . implode( "','wc-", apply_filters( 'woocommerce_reports_order_statuses', array( 'completed','on-hold', 'processing' ) ) ) . "' )
" ) );
return $order_totals->total_sales;
}
add_shortcode('sales', 'get_total_sales');
I am struggling to find how I can made it specific to the ID and have tried to implement an ID attribute, but it seems to be ignored.
Thank you in advance!
If you just want to get all total sales there is a meta that you can use. This method doesnt check by order statuses.
function get_total_sales_by_product_id( $atts ) {
return get_post_meta($atts['id'], 'total_sales', true);
}
add_shortcode('sales', 'get_total_sales_by_product_id');
To get total sales by list of order statuses try this
function get_total_sales_by_product_id( $atts ){
$atts = shortcode_atts( array(
'id' => ''), $atts );
$product_id = $atts['id'];
if(empty($product_id)) return;
//Add remove order statuses
$order_status = array( 'wc-completed', 'wc-processing' );
global $wpdb;
$order_ids = $wpdb->get_col("
SELECT order_items.order_id
FROM {$wpdb->prefix}woocommerce_order_items as order_items
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
LEFT JOIN {$wpdb->posts} AS posts ON order_items.order_id = posts.ID
WHERE posts.post_type = 'shop_order'
AND posts.post_status IN ( '" . implode( "','", $order_status ) . "' )
AND order_items.order_item_type = 'line_item'
AND order_item_meta.meta_key = '_product_id'
AND order_item_meta.meta_value = '$product_id'
");
$unique_order_ids = array_unique($order_ids);
$total_sales = 0;
foreach ($unique_order_ids as $order_id) {
$order = wc_get_order($order_id);
foreach ($order->get_items() as $item_key => $item ) {
if ($item->get_product()->get_id() == $product_id) {
$total_sales = $total_sales + $item->get_quantity();
}
}
}
return $total_sales;
}
add_shortcode('sales', 'get_total_sales_by_product_id');

Remove product image when deleting product WooCommerce

I'm deleting all of my out of stock products automatically with an sql statement (I saw the example at another question here on StackOverFlow).
This deletes the product from the database but leaves the image in the media library.
Is there a way to delete the image aswell?
Code:
function remove_out_of_stock_status(){
global $wpdb;
$results = $wpdb->get_results( "
DELETE p FROM {$wpdb->prefix}posts p
join {$wpdb->prefix}postmeta pm
on p.ID = pm.post_id
WHERE p.post_type = 'product'
and pm.meta_key = '_stock_status'
and pm.meta_value = 'outofstock'
" );
}
add_action( 'init', 'remove_out_of_stock_status', 10, 1 );
You can use before_delete_post hook to delete product image, If product get permanently deleted.
add_action('before_delete_post', 'delete_thumbnail_before_delete_post');
function delete_thumbnail_before_delete_post($post_id) {
$post = get_post($post_id);
if ($post->post_type === 'product') {
$thumb_id = get_post_thumbnail_id($post_id);
if ($thumb_id) {
wp_delete_attachment($thumb_id, true);
}
}
}
Above code work fine for me!

How can I combine two SQL queries using INNER JOIN?

I have 2 SQL queries as below:
$results2 = $wpdb->get_results("SELECT * FROM `wp_posts` WHERE id IN (".implode(",", $product_ids).")");
$getprice = $wpdb->get_results("SELECT * FROM `wp_postmeta` WHERE meta_key='_regular_price' AND post_id IN (".implode(",", $product_ids).")");
I have combined them as below query:
$yeni = $wpdb->get_results("SELECT wp_posts.id, wp_posts.post_title, wp_postmeta.meta_value
FROM wp_posts
INNER JOIN wp_postmeta ON wp_posts.id = wp_postmeta.post_id
WHERE meta_key = '_regular_price'
WHERE wp_posts.id IN (".implode(",", $product_ids).")");
After combining the queries, it's giving an empty result. I can't find the issue with the updated query.
Try this sql.
I have replace this WHERE meta_key = '_regular_price'
$yeni = $wpdb->get_results("SELECT wp_posts.id, wp_posts.post_title, wp_postmeta.meta_value FROM wp_posts INNER JOIN wp_postmeta ON wp_posts.id = wp_postmeta.post_id WHERE wp_posts.id IN (".implode(",", $product_ids).") and wp_postmeta.meta_key = '_regular_price'");
I don't understand why you don't use the native Wordpress features via OOP procedure.
Your simple query, it can be translated like this:
<?php
$loop = new WP_Query(
array(
'post_type' => 'page', // post type: page, post, attachment etc..
'post__in' => $productIds, // array[]
)
);
// after that, you can use a standard wordpress loop
if($loop->have_posts()) {
while($loop->have_posts()) {
: $loop->the_post();
the_title();
print "<br>";
// access to meta key _regular_price
print get_post_meta(get_the_ID(), '_regular_price', true);
}
}
This is the right way.
Cheers
Class reference here: https://developer.wordpress.org/reference/classes/wp_query/

Wordpress wp_query orderby not working

I am trying to get ordering working in wp_query, but posts are still being ordered with default settings (just tag__in is working). SQL query for posts looks like this:
string(379) "SELECT SQL_CALC_FOUND_ROWS wp_posts.ID FROM wp_posts INNER JOIN wp_term_relationships ON (wp_posts.ID = wp_term_relationships.object_id) WHERE 1=1 AND ( wp_term_relationships.term_taxonomy_id IN (81) ) AND wp_posts.post_type = 'post' AND (wp_posts.post_status = 'publish' OR wp_posts.post_status = 'private') GROUP BY wp_posts.ID ORDER BY wp_posts.post_date DESC LIMIT 0, 3"
Here is code snippet:
remove_all_filters('posts_orderby');
$tag = get_term_by('name', 'title_post', 'post_tag');
$args=array(
'order'=>'ID',
'orderby'=>'ASC',
'tag__in' => $tag,
'posts_per_page'=>3, // Number of related posts to display.
'caller_get_posts'=>1
);
$my_query = new wp_query( $args );
var_dump($my_query->request);
Thanks!
I have checked your code you have to pass wrong arguments.
Can you please check below code?
Wrong
'order'=>'ID',
'orderby'=>'ASC',
Right
'order'=>'ASC',
'orderby'=>'ID',
Ok, I switched order and orderby ...
So, correct arguments are 'orderby'=>'ID','order'=>'ASC',

How to activate the price filter woocommerce without passing min_price and max_price URL

I changed the core query of woocommerce and trying to show products based on custom query string pro_type_sws=32
Now when I supplied whole querystring it works
wp/?min_price=35&max_price=120&post_type=product&pro_type_sws=32
but when I just use
localhost/wp/?post_type=product&pro_type_sws=32
it does not work, I don't know how can I activate the pricefilter code without using widget FILTER button.
In short I want to apply filter over products page so it shows only those products which are related to custom product data types of woocommerce.
Code Changed in : class-wc-query.php
if (( isset( $_GET['max_price'] ) && isset( $_GET['min_price'] )) or isset( $_GET['pro_type_sws'])) {
$matched_products = array();
$min = floatval( $_GET['min_price'] );
$max = floatval( $_GET['max_price'] );
$pro_type = $_GET['pro_type_sws'];
/*
Applying Filter based on product type query string
* If Product type query string set then render only those products which are related to given product data type.
*/
if (isset( $pro_type ) ){
// Query Update : Product type based filter applied through $pro_type query string
$matched_products_query = apply_filters( 'woocommerce_price_filter_results', $wpdb->get_results( $wpdb->prepare("
SELECT DISTINCT ID, post_parent, post_type FROM $wpdb->posts
INNER JOIN $wpdb->postmeta ON ID = post_id
LEFT JOIN wp_term_relationships AS rel ON object_id = post_id
WHERE post_type IN ( 'product', 'product_variation' ) AND post_status = 'publish' AND meta_key = %s AND meta_value BETWEEN %d AND %d AND rel.term_taxonomy_id = %d
", '_price', $min, $max, $pro_type ), OBJECT_K ), $min, $max );
}
else{
$matched_products_query = apply_filters( 'woocommerce_price_filter_results', $wpdb->get_results( $wpdb->prepare("
SELECT DISTINCT ID, post_parent, post_type FROM $wpdb->posts
INNER JOIN $wpdb->postmeta ON ID = post_id
WHERE post_type IN ( 'product', 'product_variation' ) AND post_status = 'publish' AND meta_key = %s AND meta_value BETWEEN %d AND %d
", '_price', $min, $max ), OBJECT_K ), $min, $max );
}
if ( $matched_products_query ) {
foreach ( $matched_products_query as $product ) {
if ( $product->post_type == 'product' )
$matched_products[] = $product->ID;
if ( $product->post_parent > 0 && ! in_array( $product->post_parent, $matched_products ) )
$matched_products[] = $product->post_parent;
}
}
Changing core files is never a good idea, at each update (and WC has many per year) you'll have to apply your mods again.
Try hooking on the same filter (on a custom plugin or the theme's functions.php) and doing your stuff:
add_filter( 'loop_shop_post_in', function(){
if (
( isset( $_GET['max_price'] ) && isset( $_GET['min_price'] ) )
or isset( $_GET['pro_type_sws'] )
){
// do your thing
// adjust the issets to integrate to WC behavior
// etc
}
});

Categories