2013-11-12 12:01:05 +00:00
< ? php
2014-05-28 13:52:50 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
exit ; // Exit if accessed directly
}
2013-11-12 12:01:05 +00:00
/**
2015-11-03 13:31:20 +00:00
* Post Data .
2013-11-12 12:01:05 +00:00
*
* Standardises certain post data on save .
*
* @ class WC_Post_Data
2014-05-28 13:52:50 +00:00
* @ version 2.2 . 0
2013-11-12 12:01:05 +00:00
* @ package WooCommerce / Classes / Data
* @ category Class
* @ author WooThemes
*/
class WC_Post_Data {
2016-01-06 15:24:47 +00:00
/**
* Editing term .
*
* @ var object
*/
2014-05-28 13:52:50 +00:00
private static $editing_term = null ;
2013-11-12 20:25:23 +00:00
2013-11-12 12:01:05 +00:00
/**
2015-11-03 13:31:20 +00:00
* Hook in methods .
2013-11-12 12:01:05 +00:00
*/
2014-05-28 13:52:50 +00:00
public static function init () {
2016-11-09 12:26:46 +00:00
add_action ( 'woocommerce_deferred_product_sync' , array ( __CLASS__ , 'deferred_product_sync' ), 10 , 1 );
2014-06-19 11:25:07 +00:00
add_action ( 'set_object_terms' , array ( __CLASS__ , 'set_object_terms' ), 10 , 6 );
add_action ( 'transition_post_status' , array ( __CLASS__ , 'transition_post_status' ), 10 , 3 );
add_action ( 'woocommerce_product_set_stock_status' , array ( __CLASS__ , 'delete_product_query_transients' ) );
add_action ( 'woocommerce_product_set_visibility' , array ( __CLASS__ , 'delete_product_query_transients' ) );
2014-05-28 13:52:50 +00:00
add_action ( 'edit_term' , array ( __CLASS__ , 'edit_term' ), 10 , 3 );
add_action ( 'edited_term' , array ( __CLASS__ , 'edited_term' ), 10 , 3 );
add_filter ( 'update_order_item_metadata' , array ( __CLASS__ , 'update_order_item_metadata' ), 10 , 5 );
add_filter ( 'update_post_metadata' , array ( __CLASS__ , 'update_post_metadata' ), 10 , 5 );
2014-06-04 10:16:19 +00:00
add_filter ( 'wp_insert_post_data' , array ( __CLASS__ , 'wp_insert_post_data' ) );
2016-11-16 12:17:00 +00:00
// Status transitions
add_action ( 'delete_post' , array ( __CLASS__ , 'delete_post' ) );
add_action ( 'wp_trash_post' , array ( __CLASS__ , 'trash_post' ) );
2016-11-18 11:14:09 +00:00
add_action ( 'untrashed_post' , array ( __CLASS__ , 'untrash_post' ) );
2016-11-16 12:17:00 +00:00
add_action ( 'before_delete_post' , array ( __CLASS__ , 'delete_order_items' ) );
add_action ( 'before_delete_post' , array ( __CLASS__ , 'delete_order_downloadable_permissions' ) );
2016-11-09 12:26:46 +00:00
}
/**
* Sync a product .
* @ param int $product_id
*/
public static function deferred_product_sync ( $product_id ) {
$product = wc_get_product ( $product_id );
if ( is_callable ( array ( $product , 'sync' ) ) ) {
$product -> sync ( $product );
}
2013-11-12 12:01:05 +00:00
}
2014-06-19 11:25:07 +00:00
/**
2015-11-03 13:31:20 +00:00
* Delete transients when terms are set .
2014-06-19 11:25:07 +00:00
*/
public static function set_object_terms ( $object_id , $terms , $tt_ids , $taxonomy , $append , $old_tt_ids ) {
foreach ( array_merge ( $tt_ids , $old_tt_ids ) as $id ) {
delete_transient ( 'wc_ln_count_' . md5 ( sanitize_key ( $taxonomy ) . sanitize_key ( $id ) ) );
}
}
/**
2015-11-03 13:31:20 +00:00
* When a post status changes .
2014-06-19 11:25:07 +00:00
*/
2014-06-19 15:32:52 +00:00
public static function transition_post_status ( $new_status , $old_status , $post ) {
2014-06-19 11:25:07 +00:00
if ( ( 'publish' === $new_status || 'publish' === $old_status ) && in_array ( $post -> post_type , array ( 'product' , 'product_variation' ) ) ) {
self :: delete_product_query_transients ();
}
}
/**
* Delete product view transients when needed e . g . when post status changes , or visibility / stock status is modified .
*/
public static function delete_product_query_transients () {
2014-07-03 11:59:54 +00:00
// Increments the transient version to invalidate cache
WC_Cache_Helper :: get_transient_version ( 'product_query' , true );
2014-06-19 11:25:07 +00:00
2014-07-03 11:59:54 +00:00
// If not using an external caching system, we can clear the transients out manually and avoid filling our DB
if ( ! wp_using_ext_object_cache () ) {
global $wpdb ;
2014-06-19 11:25:07 +00:00
2014-07-03 11:59:54 +00:00
$wpdb -> query ( "
2014-09-20 18:54:33 +00:00
DELETE FROM `$wpdb->options`
WHERE `option_name` LIKE ( '\_transient\_wc\_uf\_pid\_%' )
2014-07-03 11:59:54 +00:00
OR `option_name` LIKE ( '\_transient\_timeout\_wc\_uf\_pid\_%' )
OR `option_name` LIKE ( '\_transient\_wc\_products\_will\_display\_%' )
OR `option_name` LIKE ( '\_transient\_timeout\_wc\_products\_will\_display\_%' )
" );
}
2014-06-19 11:25:07 +00:00
}
2013-11-12 20:25:23 +00:00
/**
2015-11-03 13:31:20 +00:00
* When editing a term , check for product attributes .
2013-11-12 20:25:23 +00:00
* @ param id $term_id
* @ param id $tt_id
* @ param string $taxonomy
*/
2014-05-28 13:52:50 +00:00
public static function edit_term ( $term_id , $tt_id , $taxonomy ) {
2013-11-12 20:25:23 +00:00
if ( strpos ( $taxonomy , 'pa_' ) === 0 ) {
2014-05-28 13:52:50 +00:00
self :: $editing_term = get_term_by ( 'id' , $term_id , $taxonomy );
2013-11-12 20:25:23 +00:00
} else {
2014-05-28 13:52:50 +00:00
self :: $editing_term = null ;
2013-11-12 20:25:23 +00:00
}
}
/**
2015-11-03 13:31:20 +00:00
* When a term is edited , check for product attributes and update variations .
2013-11-12 20:25:23 +00:00
* @ param id $term_id
* @ param id $tt_id
* @ param string $taxonomy
*/
2014-05-28 13:52:50 +00:00
public static function edited_term ( $term_id , $tt_id , $taxonomy ) {
if ( ! is_null ( self :: $editing_term ) && strpos ( $taxonomy , 'pa_' ) === 0 ) {
2013-11-12 20:25:23 +00:00
$edited_term = get_term_by ( 'id' , $term_id , $taxonomy );
2014-05-28 13:52:50 +00:00
if ( $edited_term -> slug !== self :: $editing_term -> slug ) {
2013-11-12 20:25:23 +00:00
global $wpdb ;
2014-05-28 13:52:50 +00:00
$wpdb -> query ( $wpdb -> prepare ( " UPDATE { $wpdb -> postmeta } SET meta_value = %s WHERE meta_key = %s AND meta_value = %s; " , $edited_term -> slug , 'attribute_' . sanitize_title ( $taxonomy ), self :: $editing_term -> slug ) );
2013-11-12 20:25:23 +00:00
}
} else {
2014-05-28 13:52:50 +00:00
self :: $editing_term = null ;
2013-11-12 20:25:23 +00:00
}
}
2013-11-12 17:43:30 +00:00
/**
2015-11-03 13:31:20 +00:00
* Ensure floats are correctly converted to strings based on PHP locale .
2014-09-20 18:54:33 +00:00
*
2013-11-12 17:43:30 +00:00
* @ param null $check
* @ param int $object_id
* @ param string $meta_key
* @ param mixed $meta_value
* @ param mixed $prev_value
* @ return null | bool
*/
2014-05-28 13:52:50 +00:00
public static function update_order_item_metadata ( $check , $object_id , $meta_key , $meta_value , $prev_value ) {
2013-11-12 17:43:30 +00:00
if ( ! empty ( $meta_value ) && is_float ( $meta_value ) ) {
// Convert float to string
$meta_value = wc_float_to_string ( $meta_value );
// Update meta value with new string
update_metadata ( 'order_item' , $object_id , $meta_key , $meta_value , $prev_value );
// Return
return true ;
}
return $check ;
}
2013-11-12 12:01:05 +00:00
/**
2015-11-03 13:31:20 +00:00
* Ensure floats are correctly converted to strings based on PHP locale .
2014-09-20 18:54:33 +00:00
*
2013-11-12 12:01:05 +00:00
* @ param null $check
* @ param int $object_id
* @ param string $meta_key
* @ param mixed $meta_value
* @ param mixed $prev_value
* @ return null | bool
*/
2014-05-28 13:52:50 +00:00
public static function update_post_metadata ( $check , $object_id , $meta_key , $meta_value , $prev_value ) {
2014-07-11 11:43:42 +00:00
if ( ! empty ( $meta_value ) && is_float ( $meta_value ) && in_array ( get_post_type ( $object_id ), array_merge ( wc_get_order_types (), array ( 'shop_coupon' , 'product' , 'product_variation' ) ) ) ) {
2013-11-12 12:01:05 +00:00
// Convert float to string
2013-11-12 17:43:30 +00:00
$meta_value = wc_float_to_string ( $meta_value );
2013-11-12 12:01:05 +00:00
// Update meta value with new string
update_metadata ( 'post' , $object_id , $meta_key , $meta_value , $prev_value );
// Return
return true ;
}
return $check ;
}
2014-06-04 10:16:19 +00:00
2015-07-27 18:04:08 +00:00
/**
2015-11-03 13:31:20 +00:00
* When setting stock level , ensure the stock status is kept in sync .
2015-07-27 18:04:08 +00:00
* @ param int $meta_id
* @ param int $object_id
* @ param string $meta_key
2016-11-09 12:26:46 +00:00
* @ param mixed $meta_value
* @ deprecated
2015-07-27 18:04:08 +00:00
*/
2016-11-09 12:26:46 +00:00
public static function sync_product_stock_status ( $meta_id , $object_id , $meta_key , $meta_value ) {}
2015-07-27 18:04:08 +00:00
2014-06-04 10:16:19 +00:00
/**
* Forces the order posts to have a title in a certain format ( containing the date ) .
* Forces certain product data based on the product ' s type , e . g . grouped products cannot have a parent .
*
* @ param array $data
* @ return array
*/
public static function wp_insert_post_data ( $data ) {
if ( 'shop_order' === $data [ 'post_type' ] && isset ( $data [ 'post_date' ] ) ) {
$order_title = 'Order' ;
if ( $data [ 'post_date' ] ) {
2016-08-27 06:07:42 +00:00
$order_title .= ' – ' . date_i18n ( 'F j, Y @ h:i A' , strtotime ( $data [ 'post_date' ] ) );
2014-06-04 10:16:19 +00:00
}
$data [ 'post_title' ] = $order_title ;
2016-09-02 03:15:49 +00:00
} elseif ( 'product' === $data [ 'post_type' ] && isset ( $_POST [ 'product-type' ] ) ) {
2014-06-04 10:16:19 +00:00
$product_type = stripslashes ( $_POST [ 'product-type' ] );
switch ( $product_type ) {
case 'grouped' :
case 'variable' :
$data [ 'post_parent' ] = 0 ;
break ;
}
}
return $data ;
2014-09-20 18:54:33 +00:00
}
2016-11-16 12:17:00 +00:00
/**
* Removes variations etc belonging to a deleted post , and clears transients .
*
* @ param mixed $id ID of post being deleted
*/
public static function delete_post ( $id ) {
global $woocommerce , $wpdb ;
if ( ! current_user_can ( 'delete_posts' ) ) {
return ;
}
if ( $id > 0 ) {
$post_type = get_post_type ( $id );
switch ( $post_type ) {
case 'product' :
$child_product_variations = get_children ( 'post_parent=' . $id . '&post_type=product_variation' );
if ( ! empty ( $child_product_variations ) ) {
foreach ( $child_product_variations as $child ) {
wp_delete_post ( $child -> ID , true );
}
}
$child_products = get_children ( 'post_parent=' . $id . '&post_type=product' );
if ( ! empty ( $child_products ) ) {
foreach ( $child_products as $child ) {
$child_post = array ();
$child_post [ 'ID' ] = $child -> ID ;
$child_post [ 'post_parent' ] = 0 ;
wp_update_post ( $child_post );
}
}
if ( $parent_id = wp_get_post_parent_id ( $id ) ) {
wc_delete_product_transients ( $parent_id );
}
break ;
case 'product_variation' :
wc_delete_product_transients ( wp_get_post_parent_id ( $id ) );
break ;
case 'shop_order' :
$refunds = $wpdb -> get_results ( $wpdb -> prepare ( " SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d " , $id ) );
if ( ! is_null ( $refunds ) ) {
foreach ( $refunds as $refund ) {
wp_delete_post ( $refund -> ID , true );
}
}
break ;
}
}
}
/**
* woocommerce_trash_post function .
*
* @ param mixed $id
*/
public static function trash_post ( $id ) {
global $wpdb ;
if ( $id > 0 ) {
$post_type = get_post_type ( $id );
if ( in_array ( $post_type , wc_get_order_types ( 'order-count' ) ) ) {
$refunds = $wpdb -> get_results ( $wpdb -> prepare ( " SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d " , $id ) );
foreach ( $refunds as $refund ) {
$wpdb -> update ( $wpdb -> posts , array ( 'post_status' => 'trash' ), array ( 'ID' => $refund -> ID ) );
}
delete_transient ( 'woocommerce_processing_order_count' );
wc_delete_shop_order_transients ( $id );
}
}
}
/**
* woocommerce_untrash_post function .
*
* @ param mixed $id
*/
public static function untrash_post ( $id ) {
global $wpdb ;
if ( $id > 0 ) {
$post_type = get_post_type ( $id );
if ( in_array ( $post_type , wc_get_order_types ( 'order-count' ) ) ) {
$refunds = $wpdb -> get_results ( $wpdb -> prepare ( " SELECT ID FROM $wpdb->posts WHERE post_type = 'shop_order_refund' AND post_parent = %d " , $id ) );
foreach ( $refunds as $refund ) {
$wpdb -> update ( $wpdb -> posts , array ( 'post_status' => 'wc-completed' ), array ( 'ID' => $refund -> ID ) );
}
delete_transient ( 'woocommerce_processing_order_count' );
wc_delete_shop_order_transients ( $id );
} elseif ( 'product' === $post_type ) {
// Check if SKU is valid before untrash the product.
$sku = get_post_meta ( $id , '_sku' , true );
if ( ! empty ( $sku ) ) {
if ( ! wc_product_has_unique_sku ( $id , $sku ) ) {
update_post_meta ( $id , '_sku' , '' );
}
}
}
}
}
/**
* Remove item meta on permanent deletion .
*/
public static function delete_order_items ( $postid ) {
global $wpdb ;
if ( in_array ( get_post_type ( $postid ), wc_get_order_types () ) ) {
do_action ( 'woocommerce_delete_order_items' , $postid );
$wpdb -> query ( "
DELETE { $wpdb -> prefix } woocommerce_order_items , { $wpdb -> prefix } woocommerce_order_itemmeta
FROM { $wpdb -> prefix } woocommerce_order_items
JOIN { $wpdb -> prefix } woocommerce_order_itemmeta ON { $wpdb -> prefix } woocommerce_order_items . order_item_id = { $wpdb -> prefix } woocommerce_order_itemmeta . order_item_id
WHERE { $wpdb -> prefix } woocommerce_order_items . order_id = '{$postid}' ;
" );
do_action ( 'woocommerce_deleted_order_items' , $postid );
}
}
/**
* Remove downloadable permissions on permanent order deletion .
*/
public static function delete_order_downloadable_permissions ( $postid ) {
global $wpdb ;
if ( in_array ( get_post_type ( $postid ), wc_get_order_types () ) ) {
do_action ( 'woocommerce_delete_order_downloadable_permissions' , $postid );
$wpdb -> query ( $wpdb -> prepare ( "
DELETE FROM { $wpdb -> prefix } woocommerce_downloadable_product_permissions
WHERE order_id = % d
" , $postid ) );
do_action ( 'woocommerce_deleted_order_downloadable_permissions' , $postid );
}
}
2013-11-12 12:01:05 +00:00
}
2014-09-20 18:54:33 +00:00
WC_Post_Data :: init ();