2013-08-06 10:41:20 +00:00
< ? php
/**
2015-11-03 13:53:50 +00:00
* Product Data
2013-08-06 10:41:20 +00:00
*
* Displays the product data box , tabbed , with several panels covering price , stock etc .
*
2015-07-02 20:42:22 +00:00
* @ package WooCommerce / Admin / Meta Boxes
2017-03-15 16:36:53 +00:00
* @ version 3.0 . 0
2013-08-06 10:41:20 +00:00
*/
2014-06-27 13:08:39 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
2016-10-26 17:02:50 +00:00
exit ;
2014-06-27 13:08:39 +00:00
}
2013-08-06 10:41:20 +00:00
/**
2015-11-03 12:28:01 +00:00
* WC_Meta_Box_Product_Data Class .
2013-08-06 10:41:20 +00:00
*/
class WC_Meta_Box_Product_Data {
/**
2015-11-03 12:28:01 +00:00
* Output the metabox .
2016-01-04 21:31:36 +00:00
*
2019-02-19 17:41:14 +00:00
* @ param WP_Post $post Post object .
2013-08-06 10:41:20 +00:00
*/
public static function output ( $post ) {
2017-05-15 11:29:11 +00:00
global $thepostid , $product_object ;
2013-08-06 10:41:20 +00:00
2016-10-26 17:02:50 +00:00
$thepostid = $post -> ID ;
2018-03-05 18:59:17 +00:00
$product_object = $thepostid ? wc_get_product ( $thepostid ) : new WC_Product ();
2013-08-06 10:41:20 +00:00
2018-01-03 10:37:07 +00:00
wp_nonce_field ( 'woocommerce_save_data' , 'woocommerce_meta_nonce' );
2018-03-05 18:59:17 +00:00
include 'views/html-product-data-panel.php' ;
2016-10-27 13:08:16 +00:00
}
2014-08-31 07:18:21 +00:00
2016-10-27 13:08:16 +00:00
/**
* Show tab content / settings .
*/
private static function output_tabs () {
global $post , $thepostid , $product_object ;
2018-03-05 18:59:17 +00:00
include 'views/html-product-data-general.php' ;
include 'views/html-product-data-inventory.php' ;
include 'views/html-product-data-shipping.php' ;
include 'views/html-product-data-linked-products.php' ;
include 'views/html-product-data-attributes.php' ;
include 'views/html-product-data-advanced.php' ;
2016-10-27 13:08:16 +00:00
}
2013-08-06 10:41:20 +00:00
2016-10-27 13:08:16 +00:00
/**
* Return array of product type options .
2018-03-05 18:59:17 +00:00
*
2016-10-27 13:08:16 +00:00
* @ return array
*/
private static function get_product_type_options () {
2018-03-05 18:59:17 +00:00
return apply_filters (
2019-02-19 17:41:14 +00:00
'product_type_options' ,
array (
2018-03-05 18:59:17 +00:00
'virtual' => array (
'id' => '_virtual' ,
'wrapper_class' => 'show_if_simple' ,
'label' => __ ( 'Virtual' , 'woocommerce' ),
'description' => __ ( 'Virtual products are intangible and are not shipped.' , 'woocommerce' ),
'default' => 'no' ,
),
'downloadable' => array (
'id' => '_downloadable' ,
'wrapper_class' => 'show_if_simple' ,
'label' => __ ( 'Downloadable' , 'woocommerce' ),
'description' => __ ( 'Downloadable products give access to a file upon purchase.' , 'woocommerce' ),
'default' => 'no' ,
),
)
);
2016-10-27 13:08:16 +00:00
}
2013-08-06 10:41:20 +00:00
2016-10-27 13:08:16 +00:00
/**
* Return array of tabs to show .
2018-03-05 18:59:17 +00:00
*
2016-10-27 13:08:16 +00:00
* @ return array
*/
private static function get_product_data_tabs () {
2018-03-05 18:59:17 +00:00
$tabs = apply_filters (
2019-02-19 17:41:14 +00:00
'woocommerce_product_data_tabs' ,
array (
2018-03-05 18:59:17 +00:00
'general' => array (
'label' => __ ( 'General' , 'woocommerce' ),
'target' => 'general_product_data' ,
'class' => array ( 'hide_if_grouped' ),
'priority' => 10 ,
),
'inventory' => array (
'label' => __ ( 'Inventory' , 'woocommerce' ),
'target' => 'inventory_product_data' ,
'class' => array ( 'show_if_simple' , 'show_if_variable' , 'show_if_grouped' , 'show_if_external' ),
'priority' => 20 ,
),
'shipping' => array (
'label' => __ ( 'Shipping' , 'woocommerce' ),
'target' => 'shipping_product_data' ,
'class' => array ( 'hide_if_virtual' , 'hide_if_grouped' , 'hide_if_external' ),
'priority' => 30 ,
),
'linked_product' => array (
'label' => __ ( 'Linked Products' , 'woocommerce' ),
'target' => 'linked_product_data' ,
'class' => array (),
'priority' => 40 ,
),
'attribute' => array (
'label' => __ ( 'Attributes' , 'woocommerce' ),
'target' => 'product_attributes' ,
'class' => array (),
'priority' => 50 ,
),
'variations' => array (
'label' => __ ( 'Variations' , 'woocommerce' ),
'target' => 'variable_product_options' ,
'class' => array ( 'variations_tab' , 'show_if_variable' ),
'priority' => 60 ,
),
'advanced' => array (
'label' => __ ( 'Advanced' , 'woocommerce' ),
'target' => 'advanced_product_data' ,
'class' => array (),
'priority' => 70 ,
),
)
);
2017-02-21 07:34:43 +00:00
2017-04-04 14:40:02 +00:00
// Sort tabs based on priority.
2017-02-21 07:34:43 +00:00
uasort ( $tabs , array ( __CLASS__ , 'product_data_tabs_sort' ) );
return $tabs ;
}
/**
* Callback to sort product data tabs on priority .
2017-04-04 14:40:02 +00:00
*
* @ since 3.1 . 0
* @ param int $a First item .
* @ param int $b Second item .
*
* @ return bool
2017-02-21 07:34:43 +00:00
*/
private static function product_data_tabs_sort ( $a , $b ) {
2017-04-04 14:40:02 +00:00
if ( ! isset ( $a [ 'priority' ], $b [ 'priority' ] ) ) {
return - 1 ;
}
2019-02-19 17:41:14 +00:00
if ( $a [ 'priority' ] === $b [ 'priority' ] ) {
2017-04-04 14:40:02 +00:00
return 0 ;
}
2017-02-21 07:34:43 +00:00
return $a [ 'priority' ] < $b [ 'priority' ] ? - 1 : 1 ;
2016-10-27 13:08:16 +00:00
}
2013-08-06 10:41:20 +00:00
2016-10-27 13:08:16 +00:00
/**
* Filter callback for finding variation attributes .
2018-03-05 18:59:17 +00:00
*
2019-02-19 17:41:14 +00:00
* @ param WC_Product_Attribute $attribute Product attribute .
2016-10-27 13:08:16 +00:00
* @ return bool
*/
private static function filter_variation_attributes ( $attribute ) {
return true === $attribute -> get_variation ();
2013-08-06 10:41:20 +00:00
}
/**
2015-11-03 12:28:01 +00:00
* Show options for the variable product type .
2013-08-06 10:41:20 +00:00
*/
2013-09-24 15:21:12 +00:00
public static function output_variations () {
2016-10-27 13:08:16 +00:00
global $post , $wpdb , $product_object ;
2013-08-06 10:41:20 +00:00
2016-10-27 13:08:16 +00:00
$variation_attributes = array_filter ( $product_object -> get_attributes (), array ( __CLASS__ , 'filter_variation_attributes' ) );
$default_attributes = $product_object -> get_default_attributes ();
2018-08-16 07:28:48 +00:00
$variations_count = absint ( apply_filters ( 'woocommerce_admin_meta_boxes_variations_count' , $wpdb -> get_var ( $wpdb -> prepare ( " SELECT COUNT(ID) FROM $wpdb->posts WHERE post_parent = %d AND post_type = 'product_variation' AND post_status IN ('publish', 'private') " , $post -> ID ) ), $post -> ID ) );
2015-09-14 15:54:58 +00:00
$variations_per_page = absint ( apply_filters ( 'woocommerce_admin_meta_boxes_variations_per_page' , 15 ) );
2015-07-06 01:00:38 +00:00
$variations_total_pages = ceil ( $variations_count / $variations_per_page );
2016-10-27 13:08:16 +00:00
2018-03-05 18:59:17 +00:00
include 'views/html-product-data-variations.php' ;
2013-08-06 10:41:20 +00:00
}
/**
2016-10-26 17:02:50 +00:00
* Prepare downloads for save .
2017-05-15 11:50:52 +00:00
*
2019-02-19 17:41:14 +00:00
* @ param array $file_names File names .
* @ param array $file_urls File urls .
* @ param array $file_hashes File hashes .
2017-05-15 11:50:52 +00:00
*
2016-10-26 17:02:50 +00:00
* @ return array
2013-08-06 10:41:20 +00:00
*/
2016-11-18 19:29:37 +00:00
private static function prepare_downloads ( $file_names , $file_urls , $file_hashes ) {
2016-10-26 17:02:50 +00:00
$downloads = array ();
2016-11-02 18:50:42 +00:00
if ( ! empty ( $file_urls ) ) {
2019-02-19 17:41:14 +00:00
$file_url_size = count ( $file_urls );
2016-10-26 17:02:50 +00:00
for ( $i = 0 ; $i < $file_url_size ; $i ++ ) {
if ( ! empty ( $file_urls [ $i ] ) ) {
$downloads [] = array (
2018-03-05 18:59:17 +00:00
'name' => wc_clean ( $file_names [ $i ] ),
'file' => wp_unslash ( trim ( $file_urls [ $i ] ) ),
'download_id' => wc_clean ( $file_hashes [ $i ] ),
2016-10-26 17:02:50 +00:00
);
2013-08-06 10:41:20 +00:00
}
}
}
2016-10-26 17:02:50 +00:00
return $downloads ;
}
2014-08-31 07:18:21 +00:00
2016-10-26 17:02:50 +00:00
/**
* Prepare children for save .
2018-03-05 18:59:17 +00:00
*
2016-10-26 17:02:50 +00:00
* @ return array
*/
private static function prepare_children () {
2019-12-13 19:58:14 +00:00
return isset ( $_POST [ 'grouped_products' ] ) ? array_filter ( array_map ( 'intval' , ( array ) $_POST [ 'grouped_products' ] ) ) : array (); // phpcs:ignore WordPress.Security.NonceVerification.Missing
2016-10-26 17:02:50 +00:00
}
2013-08-06 10:41:20 +00:00
2016-10-26 17:02:50 +00:00
/**
* Prepare attributes for save .
2017-05-15 11:50:52 +00:00
*
2019-02-19 17:41:14 +00:00
* @ param array $data Attribute data .
2017-05-15 11:50:52 +00:00
*
2016-10-26 17:02:50 +00:00
* @ return array
*/
public static function prepare_attributes ( $data = false ) {
$attributes = array ();
2013-08-06 10:41:20 +00:00
2016-10-26 17:02:50 +00:00
if ( ! $data ) {
2019-12-13 19:58:14 +00:00
$data = stripslashes_deep ( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
2016-10-26 17:02:50 +00:00
}
2013-08-06 10:41:20 +00:00
2016-10-26 17:02:50 +00:00
if ( isset ( $data [ 'attribute_names' ], $data [ 'attribute_values' ] ) ) {
$attribute_names = $data [ 'attribute_names' ];
$attribute_values = $data [ 'attribute_values' ];
$attribute_visibility = isset ( $data [ 'attribute_visibility' ] ) ? $data [ 'attribute_visibility' ] : array ();
$attribute_variation = isset ( $data [ 'attribute_variation' ] ) ? $data [ 'attribute_variation' ] : array ();
$attribute_position = $data [ 'attribute_position' ];
2015-06-05 12:37:45 +00:00
$attribute_names_max_key = max ( array_keys ( $attribute_names ) );
2013-08-06 10:41:20 +00:00
2015-05-19 16:53:00 +00:00
for ( $i = 0 ; $i <= $attribute_names_max_key ; $i ++ ) {
2017-03-02 16:21:20 +00:00
if ( empty ( $attribute_names [ $i ] ) || ! isset ( $attribute_values [ $i ] ) ) {
2013-08-06 10:41:20 +00:00
continue ;
2014-06-27 13:08:39 +00:00
}
2017-05-03 19:30:50 +00:00
$attribute_id = 0 ;
2020-06-11 19:10:05 +00:00
$attribute_name = wc_clean ( esc_html ( $attribute_names [ $i ] ) );
2017-05-03 19:30:50 +00:00
if ( 'pa_' === substr ( $attribute_name , 0 , 3 ) ) {
$attribute_id = wc_attribute_taxonomy_id_by_name ( $attribute_name );
}
$options = isset ( $attribute_values [ $i ] ) ? $attribute_values [ $i ] : '' ;
2013-08-06 10:41:20 +00:00
2016-10-26 17:02:50 +00:00
if ( is_array ( $options ) ) {
// Term ids sent as array.
$options = wp_parse_id_list ( $options );
} else {
// Terms or text sent in textarea.
2020-06-11 19:10:05 +00:00
$options = 0 < $attribute_id ? wc_sanitize_textarea ( esc_html ( wc_sanitize_term_text_based ( $options ) ) ) : wc_sanitize_textarea ( esc_html ( $options ) );
2016-10-26 17:02:50 +00:00
$options = wc_get_text_attributes ( $options );
2016-03-09 20:12:19 +00:00
}
2013-08-06 10:41:20 +00:00
2017-03-02 16:21:20 +00:00
if ( empty ( $options ) ) {
continue ;
}
2016-10-26 17:02:50 +00:00
$attribute = new WC_Product_Attribute ();
$attribute -> set_id ( $attribute_id );
$attribute -> set_name ( $attribute_name );
$attribute -> set_options ( $options );
$attribute -> set_position ( $attribute_position [ $i ] );
$attribute -> set_visible ( isset ( $attribute_visibility [ $i ] ) );
$attribute -> set_variation ( isset ( $attribute_variation [ $i ] ) );
2017-11-17 15:43:02 +00:00
$attributes [] = apply_filters ( 'woocommerce_admin_meta_boxes_prepare_attribute' , $attribute , $data , $i );
2014-06-27 13:08:39 +00:00
}
2013-08-06 10:41:20 +00:00
}
2016-10-26 17:02:50 +00:00
return $attributes ;
}
2013-08-06 10:41:20 +00:00
2016-11-02 18:50:42 +00:00
/**
* Prepare attributes for a specific variation or defaults .
2018-03-05 18:59:17 +00:00
*
2019-02-19 17:41:14 +00:00
* @ param array $all_attributes List of attribute keys .
* @ param string $key_prefix Attribute key prefix .
* @ param int $index Attribute array index .
2016-11-02 18:50:42 +00:00
* @ return array
*/
private static function prepare_set_attributes ( $all_attributes , $key_prefix = 'attribute_' , $index = null ) {
$attributes = array ();
if ( $all_attributes ) {
foreach ( $all_attributes as $attribute ) {
if ( $attribute -> get_variation () ) {
$attribute_key = sanitize_title ( $attribute -> get_name () );
if ( ! is_null ( $index ) ) {
2019-12-13 19:58:14 +00:00
$value = isset ( $_POST [ $key_prefix . $attribute_key ][ $index ] ) ? wp_unslash ( $_POST [ $key_prefix . $attribute_key ][ $index ] ) : '' ; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2016-11-02 18:50:42 +00:00
} else {
2019-12-13 19:58:14 +00:00
$value = isset ( $_POST [ $key_prefix . $attribute_key ] ) ? wp_unslash ( $_POST [ $key_prefix . $attribute_key ] ) : '' ; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2017-11-20 20:51:32 +00:00
}
if ( $attribute -> is_taxonomy () ) {
// Don't use wc_clean as it destroys sanitized characters.
$value = sanitize_title ( $value );
} else {
$value = html_entity_decode ( wc_clean ( $value ), ENT_QUOTES , get_bloginfo ( 'charset' ) ); // WPCS: sanitization ok.
2016-11-02 18:50:42 +00:00
}
$attributes [ $attribute_key ] = $value ;
}
}
}
return $attributes ;
}
2016-10-26 17:02:50 +00:00
/**
* Save meta box data .
2017-05-15 11:50:52 +00:00
*
2019-02-19 17:41:14 +00:00
* @ param int $post_id WP post id .
* @ param WP_Post $post Post object .
2016-10-26 17:02:50 +00:00
*/
public static function save ( $post_id , $post ) {
2019-12-13 19:58:14 +00:00
// phpcs:disable WordPress.Security.NonceVerification.Missing
2016-10-26 17:02:50 +00:00
// Process product type first so we have the correct class to run setters.
2019-02-19 17:41:14 +00:00
$product_type = empty ( $_POST [ 'product-type' ] ) ? WC_Product_Factory :: get_product_type ( $post_id ) : sanitize_title ( wp_unslash ( $_POST [ 'product-type' ] ) );
2017-04-06 14:56:55 +00:00
$classname = WC_Product_Factory :: get_product_classname ( $post_id , $product_type ? $product_type : 'simple' );
2017-01-05 16:54:47 +00:00
$product = new $classname ( $post_id );
$attributes = self :: prepare_attributes ();
2017-06-27 20:22:46 +00:00
$stock = null ;
// Handle stock changes.
if ( isset ( $_POST [ '_stock' ] ) ) {
2019-02-19 17:41:14 +00:00
if ( isset ( $_POST [ '_original_stock' ] ) && wc_stock_amount ( $product -> get_stock_quantity ( 'edit' ) ) !== wc_stock_amount ( wp_unslash ( $_POST [ '_original_stock' ] ) ) ) {
2017-07-05 16:11:34 +00:00
/* translators: 1: product ID 2: quantity in stock */
WC_Admin_Meta_Boxes :: add_error ( sprintf ( __ ( 'The stock has not been updated because the value has changed since editing. Product %1$d has %2$d units in stock.' , 'woocommerce' ), $product -> get_id (), $product -> get_stock_quantity ( 'edit' ) ) );
2017-06-27 20:22:46 +00:00
} else {
2018-05-25 11:15:59 +00:00
$stock = wc_stock_amount ( wp_unslash ( $_POST [ '_stock' ] ) );
2017-06-27 20:22:46 +00:00
}
}
2019-03-08 13:36:55 +00:00
// Handle dates.
$date_on_sale_from = '' ;
$date_on_sale_to = '' ;
// Force date from to beginning of day.
if ( isset ( $_POST [ '_sale_price_dates_from' ] ) ) {
$date_on_sale_from = wc_clean ( wp_unslash ( $_POST [ '_sale_price_dates_from' ] ) );
if ( ! empty ( $date_on_sale_from ) ) {
$date_on_sale_from = date ( 'Y-m-d 00:00:00' , strtotime ( $date_on_sale_from ) );
}
}
// Force date to to the end of the day.
if ( isset ( $_POST [ '_sale_price_dates_to' ] ) ) {
$date_on_sale_to = wc_clean ( wp_unslash ( $_POST [ '_sale_price_dates_to' ] ) );
if ( ! empty ( $date_on_sale_to ) ) {
$date_on_sale_to = date ( 'Y-m-d 23:59:59' , strtotime ( $date_on_sale_to ) );
}
}
2018-03-05 18:59:17 +00:00
$errors = $product -> set_props (
array (
2018-05-25 11:15:59 +00:00
'sku' => isset ( $_POST [ '_sku' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_sku' ] ) ) : null ,
2019-03-14 22:48:47 +00:00
'purchase_note' => isset ( $_POST [ '_purchase_note' ] ) ? wp_kses_post ( wp_unslash ( $_POST [ '_purchase_note' ] ) ) : '' ,
2018-03-05 18:59:17 +00:00
'downloadable' => isset ( $_POST [ '_downloadable' ] ),
'virtual' => isset ( $_POST [ '_virtual' ] ),
'featured' => isset ( $_POST [ '_featured' ] ),
2019-03-14 22:48:47 +00:00
'catalog_visibility' => isset ( $_POST [ '_visibility' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_visibility' ] ) ) : null ,
2018-05-25 11:15:59 +00:00
'tax_status' => isset ( $_POST [ '_tax_status' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_tax_status' ] ) ) : null ,
'tax_class' => isset ( $_POST [ '_tax_class' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_tax_class' ] ) ) : null ,
2019-03-14 22:48:47 +00:00
'weight' => isset ( $_POST [ '_weight' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_weight' ] ) ) : null ,
'length' => isset ( $_POST [ '_length' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_length' ] ) ) : null ,
'width' => isset ( $_POST [ '_width' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_width' ] ) ) : null ,
'height' => isset ( $_POST [ '_height' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_height' ] ) ) : null ,
'shipping_class_id' => isset ( $_POST [ 'product_shipping_class' ] ) ? absint ( wp_unslash ( $_POST [ 'product_shipping_class' ] ) ) : null ,
2018-03-05 18:59:17 +00:00
'sold_individually' => ! empty ( $_POST [ '_sold_individually' ] ),
2018-05-25 11:15:59 +00:00
'upsell_ids' => isset ( $_POST [ 'upsell_ids' ] ) ? array_map ( 'intval' , ( array ) wp_unslash ( $_POST [ 'upsell_ids' ] ) ) : array (),
'cross_sell_ids' => isset ( $_POST [ 'crosssell_ids' ] ) ? array_map ( 'intval' , ( array ) wp_unslash ( $_POST [ 'crosssell_ids' ] ) ) : array (),
2019-03-14 22:48:47 +00:00
'regular_price' => isset ( $_POST [ '_regular_price' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_regular_price' ] ) ) : null ,
'sale_price' => isset ( $_POST [ '_sale_price' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_sale_price' ] ) ) : null ,
2019-03-08 13:36:55 +00:00
'date_on_sale_from' => $date_on_sale_from ,
'date_on_sale_to' => $date_on_sale_to ,
2018-03-05 18:59:17 +00:00
'manage_stock' => ! empty ( $_POST [ '_manage_stock' ] ),
2018-05-25 11:15:59 +00:00
'backorders' => isset ( $_POST [ '_backorders' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_backorders' ] ) ) : null ,
2019-03-14 22:48:47 +00:00
'stock_status' => isset ( $_POST [ '_stock_status' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_stock_status' ] ) ) : null ,
2018-03-05 18:59:17 +00:00
'stock_quantity' => $stock ,
2019-02-19 19:37:45 +00:00
'low_stock_amount' => isset ( $_POST [ '_low_stock_amount' ] ) && '' !== $_POST [ '_low_stock_amount' ] ? wc_stock_amount ( wp_unslash ( $_POST [ '_low_stock_amount' ] ) ) : '' ,
2019-03-14 22:48:47 +00:00
'download_limit' => isset ( $_POST [ '_download_limit' ] ) && '' !== $_POST [ '_download_limit' ] ? absint ( wp_unslash ( $_POST [ '_download_limit' ] ) ) : '' ,
'download_expiry' => isset ( $_POST [ '_download_expiry' ] ) && '' !== $_POST [ '_download_expiry' ] ? absint ( wp_unslash ( $_POST [ '_download_expiry' ] ) ) : '' ,
// Those are sanitized inside prepare_downloads.
2018-03-05 18:59:17 +00:00
'downloads' => self :: prepare_downloads (
2019-03-14 22:48:47 +00:00
isset ( $_POST [ '_wc_file_names' ] ) ? wp_unslash ( $_POST [ '_wc_file_names' ] ) : array (), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
isset ( $_POST [ '_wc_file_urls' ] ) ? wp_unslash ( $_POST [ '_wc_file_urls' ] ) : array (), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
isset ( $_POST [ '_wc_file_hashes' ] ) ? wp_unslash ( $_POST [ '_wc_file_hashes' ] ) : array () // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2018-03-05 18:59:17 +00:00
),
2019-03-14 22:48:47 +00:00
'product_url' => isset ( $_POST [ '_product_url' ] ) ? esc_url_raw ( wp_unslash ( $_POST [ '_product_url' ] ) ) : '' ,
'button_text' => isset ( $_POST [ '_button_text' ] ) ? wc_clean ( wp_unslash ( $_POST [ '_button_text' ] ) ) : '' ,
2019-02-19 17:41:14 +00:00
'children' => 'grouped' === $product_type ? self :: prepare_children () : null ,
'reviews_allowed' => ! empty ( $_POST [ 'comment_status' ] ) && 'open' === $_POST [ 'comment_status' ],
'attributes' => $attributes ,
'default_attributes' => self :: prepare_set_attributes ( $attributes , 'default_attribute_' ),
2018-03-05 18:59:17 +00:00
)
);
2013-08-06 10:41:20 +00:00
2016-10-26 17:02:50 +00:00
if ( is_wp_error ( $errors ) ) {
WC_Admin_Meta_Boxes :: add_error ( $errors -> get_error_message () );
2014-06-19 11:25:07 +00:00
}
2013-08-06 10:41:20 +00:00
2017-01-23 10:20:09 +00:00
/**
2019-02-19 17:41:14 +00:00
* Set props before save .
*
* @ since 3.0 . 0
2017-01-23 10:20:09 +00:00
*/
do_action ( 'woocommerce_admin_process_product_object' , $product );
2016-10-26 17:02:50 +00:00
$product -> save ();
2015-06-16 14:10:53 +00:00
2017-01-04 15:18:02 +00:00
if ( $product -> is_type ( 'variable' ) ) {
2019-03-14 22:48:47 +00:00
$original_post_title = isset ( $_POST [ 'original_post_title' ] ) ? wc_clean ( wp_unslash ( $_POST [ 'original_post_title' ] ) ) : '' ;
$post_title = isset ( $_POST [ 'post_title' ] ) ? wc_clean ( wp_unslash ( $_POST [ 'post_title' ] ) ) : '' ;
$product -> get_data_store () -> sync_variation_names ( $product , $original_post_title , $post_title );
2017-01-04 15:18:02 +00:00
}
2013-08-06 10:41:20 +00:00
do_action ( 'woocommerce_process_product_meta_' . $product_type , $post_id );
2019-12-13 19:58:14 +00:00
// phpcs:enable WordPress.Security.NonceVerification.Missing
2013-08-06 10:41:20 +00:00
}
/**
2019-02-19 17:41:14 +00:00
* Save variation meta box data .
2015-07-06 04:50:20 +00:00
*
2019-02-19 17:41:14 +00:00
* @ param int $post_id WP post id .
* @ param WP_Post $post Post object .
2013-08-06 10:41:20 +00:00
*/
public static function save_variations ( $post_id , $post ) {
2019-12-13 19:58:14 +00:00
// phpcs:disable WordPress.Security.NonceVerification.Missing
2016-11-02 18:50:42 +00:00
if ( isset ( $_POST [ 'variable_post_id' ] ) ) {
2018-03-05 18:59:17 +00:00
$parent = wc_get_product ( $post_id );
2016-12-13 20:03:00 +00:00
$parent -> set_default_attributes ( self :: prepare_set_attributes ( $parent -> get_attributes (), 'default_attribute_' ) );
$parent -> save ();
2019-03-14 22:48:47 +00:00
$max_loop = max ( array_keys ( wp_unslash ( $_POST [ 'variable_post_id' ] ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2016-12-08 14:28:51 +00:00
$data_store = $parent -> get_data_store ();
$data_store -> sort_all_product_variations ( $parent -> get_id () );
2013-08-06 10:41:20 +00:00
2019-03-14 22:48:47 +00:00
for ( $i = 0 ; $i <= $max_loop ; $i ++ ) {
2013-08-06 10:41:20 +00:00
2016-11-02 18:50:42 +00:00
if ( ! isset ( $_POST [ 'variable_post_id' ][ $i ] ) ) {
2013-08-06 10:41:20 +00:00
continue ;
2014-06-19 15:47:04 +00:00
}
2016-11-02 18:50:42 +00:00
$variation_id = absint ( $_POST [ 'variable_post_id' ][ $i ] );
2019-12-04 19:15:16 +00:00
$variation = wc_get_product_object ( 'variation' , $variation_id );
2017-06-27 20:22:46 +00:00
$stock = null ;
// Handle stock changes.
if ( isset ( $_POST [ 'variable_stock' ], $_POST [ 'variable_stock' ][ $i ] ) ) {
2019-02-19 17:41:14 +00:00
if ( isset ( $_POST [ 'variable_original_stock' ], $_POST [ 'variable_original_stock' ][ $i ] ) && wc_stock_amount ( $variation -> get_stock_quantity ( 'edit' ) ) !== wc_stock_amount ( wp_unslash ( $_POST [ 'variable_original_stock' ][ $i ] ) ) ) {
2017-07-05 16:11:34 +00:00
/* translators: 1: product ID 2: quantity in stock */
WC_Admin_Meta_Boxes :: add_error ( sprintf ( __ ( 'The stock has not been updated because the value has changed since editing. Product %1$d has %2$d units in stock.' , 'woocommerce' ), $variation -> get_id (), $variation -> get_stock_quantity ( 'edit' ) ) );
2017-06-27 20:22:46 +00:00
} else {
2019-02-19 17:41:14 +00:00
$stock = wc_stock_amount ( wp_unslash ( $_POST [ 'variable_stock' ][ $i ] ) );
2017-06-27 20:22:46 +00:00
}
}
2019-03-08 13:36:55 +00:00
// Handle dates.
$date_on_sale_from = '' ;
$date_on_sale_to = '' ;
// Force date from to beginning of day.
if ( isset ( $_POST [ 'variable_sale_price_dates_from' ][ $i ] ) ) {
$date_on_sale_from = wc_clean ( wp_unslash ( $_POST [ 'variable_sale_price_dates_from' ][ $i ] ) );
if ( ! empty ( $date_on_sale_from ) ) {
$date_on_sale_from = date ( 'Y-m-d 00:00:00' , strtotime ( $date_on_sale_from ) );
}
}
// Force date to to the end of the day.
if ( isset ( $_POST [ 'variable_sale_price_dates_to' ][ $i ] ) ) {
$date_on_sale_to = wc_clean ( wp_unslash ( $_POST [ 'variable_sale_price_dates_to' ][ $i ] ) );
if ( ! empty ( $date_on_sale_to ) ) {
$date_on_sale_to = date ( 'Y-m-d 23:59:59' , strtotime ( $date_on_sale_to ) );
}
}
2018-03-05 18:59:17 +00:00
$errors = $variation -> set_props (
array (
'status' => isset ( $_POST [ 'variable_enabled' ][ $i ] ) ? 'publish' : 'private' ,
2019-03-14 22:48:47 +00:00
'menu_order' => isset ( $_POST [ 'variation_menu_order' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variation_menu_order' ][ $i ] ) ) : null ,
'regular_price' => isset ( $_POST [ 'variable_regular_price' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_regular_price' ][ $i ] ) ) : null ,
'sale_price' => isset ( $_POST [ 'variable_sale_price' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_sale_price' ][ $i ] ) ) : null ,
2018-03-05 18:59:17 +00:00
'virtual' => isset ( $_POST [ 'variable_is_virtual' ][ $i ] ),
'downloadable' => isset ( $_POST [ 'variable_is_downloadable' ][ $i ] ),
2019-03-08 13:36:55 +00:00
'date_on_sale_from' => $date_on_sale_from ,
'date_on_sale_to' => $date_on_sale_to ,
2019-03-14 22:48:47 +00:00
'description' => isset ( $_POST [ 'variable_description' ][ $i ] ) ? wp_kses_post ( wp_unslash ( $_POST [ 'variable_description' ][ $i ] ) ) : null ,
'download_limit' => isset ( $_POST [ 'variable_download_limit' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_download_limit' ][ $i ] ) ) : null ,
'download_expiry' => isset ( $_POST [ 'variable_download_expiry' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_download_expiry' ][ $i ] ) ) : null ,
// Those are sanitized inside prepare_downloads.
2018-03-05 18:59:17 +00:00
'downloads' => self :: prepare_downloads (
2019-03-14 22:48:47 +00:00
isset ( $_POST [ '_wc_variation_file_names' ][ $variation_id ] ) ? wp_unslash ( $_POST [ '_wc_variation_file_names' ][ $variation_id ] ) : array (), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
isset ( $_POST [ '_wc_variation_file_urls' ][ $variation_id ] ) ? wp_unslash ( $_POST [ '_wc_variation_file_urls' ][ $variation_id ] ) : array (), // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
isset ( $_POST [ '_wc_variation_file_hashes' ][ $variation_id ] ) ? wp_unslash ( $_POST [ '_wc_variation_file_hashes' ][ $variation_id ] ) : array () // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
2018-03-05 18:59:17 +00:00
),
'manage_stock' => isset ( $_POST [ 'variable_manage_stock' ][ $i ] ),
'stock_quantity' => $stock ,
2019-02-19 17:41:14 +00:00
'backorders' => isset ( $_POST [ 'variable_backorders' ], $_POST [ 'variable_backorders' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_backorders' ][ $i ] ) ) : null ,
2019-03-14 22:48:47 +00:00
'stock_status' => isset ( $_POST [ 'variable_stock_status' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_stock_status' ][ $i ] ) ) : null ,
'image_id' => isset ( $_POST [ 'upload_image_id' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'upload_image_id' ][ $i ] ) ) : null ,
2018-03-05 18:59:17 +00:00
'attributes' => self :: prepare_set_attributes ( $parent -> get_attributes (), 'attribute_' , $i ),
2018-08-09 10:13:23 +00:00
'sku' => isset ( $_POST [ 'variable_sku' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_sku' ][ $i ] ) ) : '' ,
2019-02-19 17:41:14 +00:00
'weight' => isset ( $_POST [ 'variable_weight' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_weight' ][ $i ] ) ) : '' ,
'length' => isset ( $_POST [ 'variable_length' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_length' ][ $i ] ) ) : '' ,
'width' => isset ( $_POST [ 'variable_width' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_width' ][ $i ] ) ) : '' ,
'height' => isset ( $_POST [ 'variable_height' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_height' ][ $i ] ) ) : '' ,
2019-03-14 22:48:47 +00:00
'shipping_class_id' => isset ( $_POST [ 'variable_shipping_class' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_shipping_class' ][ $i ] ) ) : null ,
2019-02-19 17:41:14 +00:00
'tax_class' => isset ( $_POST [ 'variable_tax_class' ][ $i ] ) ? wc_clean ( wp_unslash ( $_POST [ 'variable_tax_class' ][ $i ] ) ) : null ,
2018-03-05 18:59:17 +00:00
)
);
2016-11-02 18:50:42 +00:00
if ( is_wp_error ( $errors ) ) {
WC_Admin_Meta_Boxes :: add_error ( $errors -> get_error_message () );
2014-06-27 13:08:39 +00:00
}
2013-10-01 16:54:29 +00:00
2019-10-29 17:50:52 +00:00
/**
* Set variation props before save .
*
* @ param object $variation WC_Product_Variation object .
2019-12-13 19:48:17 +00:00
* @ param int $i
2019-10-29 17:50:52 +00:00
* @ since 3.8 . 0
*/
do_action ( 'woocommerce_admin_process_variation_object' , $variation , $i );
2016-11-02 18:50:42 +00:00
$variation -> save ();
2013-08-06 10:41:20 +00:00
2013-10-21 11:37:27 +00:00
do_action ( 'woocommerce_save_product_variation' , $variation_id , $i );
2013-09-24 15:21:12 +00:00
}
2013-08-06 10:41:20 +00:00
}
2019-12-13 19:58:14 +00:00
// phpcs:enable WordPress.Security.NonceVerification.Missing
2013-08-06 10:41:20 +00:00
}
2014-03-27 23:37:00 +00:00
}