initial commit
This commit is contained in:
393
includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php
Normal file
393
includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php
Normal file
@ -0,0 +1,393 @@
|
||||
<?php
|
||||
/**
|
||||
* Coupon Data
|
||||
*
|
||||
* Display the coupon data meta box.
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce\Admin\Meta Boxes
|
||||
* @version 2.1.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Meta_Box_Coupon_Data Class.
|
||||
*/
|
||||
class WC_Meta_Box_Coupon_Data {
|
||||
|
||||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );
|
||||
|
||||
$coupon_id = absint( $post->ID );
|
||||
$coupon = new WC_Coupon( $coupon_id );
|
||||
|
||||
?>
|
||||
|
||||
<style type="text/css">
|
||||
#edit-slug-box, #minor-publishing-actions { display:none }
|
||||
</style>
|
||||
<div id="coupon_options" class="panel-wrap coupon_data">
|
||||
|
||||
<div class="wc-tabs-back"></div>
|
||||
|
||||
<ul class="coupon_data_tabs wc-tabs" style="display:none;">
|
||||
<?php
|
||||
$coupon_data_tabs = apply_filters(
|
||||
'woocommerce_coupon_data_tabs',
|
||||
array(
|
||||
'general' => array(
|
||||
'label' => __( 'General', 'woocommerce' ),
|
||||
'target' => 'general_coupon_data',
|
||||
'class' => 'general_coupon_data',
|
||||
),
|
||||
'usage_restriction' => array(
|
||||
'label' => __( 'Usage restriction', 'woocommerce' ),
|
||||
'target' => 'usage_restriction_coupon_data',
|
||||
'class' => '',
|
||||
),
|
||||
'usage_limit' => array(
|
||||
'label' => __( 'Usage limits', 'woocommerce' ),
|
||||
'target' => 'usage_limit_coupon_data',
|
||||
'class' => '',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $coupon_data_tabs as $key => $tab ) :
|
||||
?>
|
||||
<li class="<?php echo $key; ?>_options <?php echo $key; ?>_tab <?php echo implode( ' ', (array) $tab['class'] ); ?>">
|
||||
<a href="#<?php echo $tab['target']; ?>">
|
||||
<span><?php echo esc_html( $tab['label'] ); ?></span>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<div id="general_coupon_data" class="panel woocommerce_options_panel">
|
||||
<?php
|
||||
|
||||
// Type.
|
||||
woocommerce_wp_select(
|
||||
array(
|
||||
'id' => 'discount_type',
|
||||
'label' => __( 'Discount type', 'woocommerce' ),
|
||||
'options' => wc_get_coupon_types(),
|
||||
'value' => $coupon->get_discount_type( 'edit' ),
|
||||
)
|
||||
);
|
||||
|
||||
// Amount.
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => 'coupon_amount',
|
||||
'label' => __( 'Coupon amount', 'woocommerce' ),
|
||||
'placeholder' => wc_format_localized_price( 0 ),
|
||||
'description' => __( 'Value of the coupon.', 'woocommerce' ),
|
||||
'data_type' => 'percent' === $coupon->get_discount_type( 'edit' ) ? 'decimal' : 'price',
|
||||
'desc_tip' => true,
|
||||
'value' => $coupon->get_amount( 'edit' ),
|
||||
)
|
||||
);
|
||||
|
||||
// Free Shipping.
|
||||
if ( wc_shipping_enabled() ) {
|
||||
woocommerce_wp_checkbox(
|
||||
array(
|
||||
'id' => 'free_shipping',
|
||||
'label' => __( 'Allow free shipping', 'woocommerce' ),
|
||||
'description' => sprintf( __( 'Check this box if the coupon grants free shipping. A <a href="%s" target="_blank">free shipping method</a> must be enabled in your shipping zone and be set to require "a valid free shipping coupon" (see the "Free Shipping Requires" setting).', 'woocommerce' ), 'https://docs.woocommerce.com/document/free-shipping/' ),
|
||||
'value' => wc_bool_to_string( $coupon->get_free_shipping( 'edit' ) ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Expiry date.
|
||||
$expiry_date = $coupon->get_date_expires( 'edit' ) ? $coupon->get_date_expires( 'edit' )->date( 'Y-m-d' ) : '';
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => 'expiry_date',
|
||||
'value' => esc_attr( $expiry_date ),
|
||||
'label' => __( 'Coupon expiry date', 'woocommerce' ),
|
||||
'placeholder' => 'YYYY-MM-DD',
|
||||
'description' => __( 'The coupon will expire at 00:00:00 of this date.', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
'class' => 'date-picker',
|
||||
'custom_attributes' => array(
|
||||
'pattern' => apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
do_action( 'woocommerce_coupon_options', $coupon->get_id(), $coupon );
|
||||
|
||||
?>
|
||||
</div>
|
||||
<div id="usage_restriction_coupon_data" class="panel woocommerce_options_panel">
|
||||
<?php
|
||||
|
||||
echo '<div class="options_group">';
|
||||
|
||||
// minimum spend.
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => 'minimum_amount',
|
||||
'label' => __( 'Minimum spend', 'woocommerce' ),
|
||||
'placeholder' => __( 'No minimum', 'woocommerce' ),
|
||||
'description' => __( 'This field allows you to set the minimum spend (subtotal) allowed to use the coupon.', 'woocommerce' ),
|
||||
'data_type' => 'price',
|
||||
'desc_tip' => true,
|
||||
'value' => $coupon->get_minimum_amount( 'edit' ),
|
||||
)
|
||||
);
|
||||
|
||||
// maximum spend.
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => 'maximum_amount',
|
||||
'label' => __( 'Maximum spend', 'woocommerce' ),
|
||||
'placeholder' => __( 'No maximum', 'woocommerce' ),
|
||||
'description' => __( 'This field allows you to set the maximum spend (subtotal) allowed when using the coupon.', 'woocommerce' ),
|
||||
'data_type' => 'price',
|
||||
'desc_tip' => true,
|
||||
'value' => $coupon->get_maximum_amount( 'edit' ),
|
||||
)
|
||||
);
|
||||
|
||||
// Individual use.
|
||||
woocommerce_wp_checkbox(
|
||||
array(
|
||||
'id' => 'individual_use',
|
||||
'label' => __( 'Individual use only', 'woocommerce' ),
|
||||
'description' => __( 'Check this box if the coupon cannot be used in conjunction with other coupons.', 'woocommerce' ),
|
||||
'value' => wc_bool_to_string( $coupon->get_individual_use( 'edit' ) ),
|
||||
)
|
||||
);
|
||||
|
||||
// Exclude Sale Products.
|
||||
woocommerce_wp_checkbox(
|
||||
array(
|
||||
'id' => 'exclude_sale_items',
|
||||
'label' => __( 'Exclude sale items', 'woocommerce' ),
|
||||
'description' => __( 'Check this box if the coupon should not apply to items on sale. Per-item coupons will only work if the item is not on sale. Per-cart coupons will only work if there are items in the cart that are not on sale.', 'woocommerce' ),
|
||||
'value' => wc_bool_to_string( $coupon->get_exclude_sale_items( 'edit' ) ),
|
||||
)
|
||||
);
|
||||
|
||||
echo '</div><div class="options_group">';
|
||||
|
||||
// Product ids.
|
||||
?>
|
||||
<p class="form-field">
|
||||
<label><?php _e( 'Products', 'woocommerce' ); ?></label>
|
||||
<select class="wc-product-search" multiple="multiple" style="width: 50%;" name="product_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations">
|
||||
<?php
|
||||
$product_ids = $coupon->get_product_ids( 'edit' );
|
||||
|
||||
foreach ( $product_ids as $product_id ) {
|
||||
$product = wc_get_product( $product_id );
|
||||
if ( is_object( $product ) ) {
|
||||
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<?php echo wc_help_tip( __( 'Products that the coupon will be applied to, or that need to be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
|
||||
</p>
|
||||
|
||||
<?php // Exclude Product ids. ?>
|
||||
<p class="form-field">
|
||||
<label><?php _e( 'Exclude products', 'woocommerce' ); ?></label>
|
||||
<select class="wc-product-search" multiple="multiple" style="width: 50%;" name="exclude_product_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations">
|
||||
<?php
|
||||
$product_ids = $coupon->get_excluded_product_ids( 'edit' );
|
||||
|
||||
foreach ( $product_ids as $product_id ) {
|
||||
$product = wc_get_product( $product_id );
|
||||
if ( is_object( $product ) ) {
|
||||
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<?php echo wc_help_tip( __( 'Products that the coupon will not be applied to, or that cannot be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
|
||||
</p>
|
||||
<?php
|
||||
|
||||
echo '</div><div class="options_group">';
|
||||
|
||||
// Categories.
|
||||
?>
|
||||
<p class="form-field">
|
||||
<label for="product_categories"><?php _e( 'Product categories', 'woocommerce' ); ?></label>
|
||||
<select id="product_categories" name="product_categories[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'Any category', 'woocommerce' ); ?>">
|
||||
<?php
|
||||
$category_ids = $coupon->get_product_categories( 'edit' );
|
||||
$categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
|
||||
|
||||
if ( $categories ) {
|
||||
foreach ( $categories as $cat ) {
|
||||
echo '<option value="' . esc_attr( $cat->term_id ) . '"' . wc_selected( $cat->term_id, $category_ids ) . '>' . esc_html( $cat->name ) . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select> <?php echo wc_help_tip( __( 'Product categories that the coupon will be applied to, or that need to be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
|
||||
</p>
|
||||
|
||||
<?php // Exclude Categories. ?>
|
||||
<p class="form-field">
|
||||
<label for="exclude_product_categories"><?php _e( 'Exclude categories', 'woocommerce' ); ?></label>
|
||||
<select id="exclude_product_categories" name="exclude_product_categories[]" style="width: 50%;" class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No categories', 'woocommerce' ); ?>">
|
||||
<?php
|
||||
$category_ids = $coupon->get_excluded_product_categories( 'edit' );
|
||||
$categories = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
|
||||
|
||||
if ( $categories ) {
|
||||
foreach ( $categories as $cat ) {
|
||||
echo '<option value="' . esc_attr( $cat->term_id ) . '"' . wc_selected( $cat->term_id, $category_ids ) . '>' . esc_html( $cat->name ) . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<?php echo wc_help_tip( __( 'Product categories that the coupon will not be applied to, or that cannot be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
|
||||
</p>
|
||||
</div>
|
||||
<div class="options_group">
|
||||
<?php
|
||||
// Customers.
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => 'customer_email',
|
||||
'label' => __( 'Allowed emails', 'woocommerce' ),
|
||||
'placeholder' => __( 'No restrictions', 'woocommerce' ),
|
||||
'description' => __( 'List of allowed billing emails to check against when an order is placed. Separate email addresses with commas. You can also use an asterisk (*) to match parts of an email. For example "*@gmail.com" would match all gmail addresses.', 'woocommerce' ),
|
||||
'value' => implode( ', ', (array) $coupon->get_email_restrictions( 'edit' ) ),
|
||||
'desc_tip' => true,
|
||||
'type' => 'email',
|
||||
'class' => '',
|
||||
'custom_attributes' => array(
|
||||
'multiple' => 'multiple',
|
||||
),
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<?php do_action( 'woocommerce_coupon_options_usage_restriction', $coupon->get_id(), $coupon ); ?>
|
||||
</div>
|
||||
<div id="usage_limit_coupon_data" class="panel woocommerce_options_panel">
|
||||
<div class="options_group">
|
||||
<?php
|
||||
// Usage limit per coupons.
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => 'usage_limit',
|
||||
'label' => __( 'Usage limit per coupon', 'woocommerce' ),
|
||||
'placeholder' => esc_attr__( 'Unlimited usage', 'woocommerce' ),
|
||||
'description' => __( 'How many times this coupon can be used before it is void.', 'woocommerce' ),
|
||||
'type' => 'number',
|
||||
'desc_tip' => true,
|
||||
'class' => 'short',
|
||||
'custom_attributes' => array(
|
||||
'step' => 1,
|
||||
'min' => 0,
|
||||
),
|
||||
'value' => $coupon->get_usage_limit( 'edit' ) ? $coupon->get_usage_limit( 'edit' ) : '',
|
||||
)
|
||||
);
|
||||
|
||||
// Usage limit per product.
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => 'limit_usage_to_x_items',
|
||||
'label' => __( 'Limit usage to X items', 'woocommerce' ),
|
||||
'placeholder' => esc_attr__( 'Apply to all qualifying items in cart', 'woocommerce' ),
|
||||
'description' => __( 'The maximum number of individual items this coupon can apply to when using product discounts. Leave blank to apply to all qualifying items in cart.', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
'class' => 'short',
|
||||
'type' => 'number',
|
||||
'custom_attributes' => array(
|
||||
'step' => 1,
|
||||
'min' => 0,
|
||||
),
|
||||
'value' => $coupon->get_limit_usage_to_x_items( 'edit' ) ? $coupon->get_limit_usage_to_x_items( 'edit' ) : '',
|
||||
)
|
||||
);
|
||||
|
||||
// Usage limit per users.
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => 'usage_limit_per_user',
|
||||
'label' => __( 'Usage limit per user', 'woocommerce' ),
|
||||
'placeholder' => esc_attr__( 'Unlimited usage', 'woocommerce' ),
|
||||
'description' => __( 'How many times this coupon can be used by an individual user. Uses billing email for guests, and user ID for logged in users.', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
'class' => 'short',
|
||||
'type' => 'number',
|
||||
'custom_attributes' => array(
|
||||
'step' => 1,
|
||||
'min' => 0,
|
||||
),
|
||||
'value' => $coupon->get_usage_limit_per_user( 'edit' ) ? $coupon->get_usage_limit_per_user( 'edit' ) : '',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<?php do_action( 'woocommerce_coupon_options_usage_limit', $coupon->get_id(), $coupon ); ?>
|
||||
</div>
|
||||
<?php do_action( 'woocommerce_coupon_data_panels', $coupon->get_id(), $coupon ); ?>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta box data.
|
||||
*
|
||||
* @param int $post_id
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public static function save( $post_id, $post ) {
|
||||
// Check for dupe coupons.
|
||||
$coupon_code = wc_format_coupon_code( $post->post_title );
|
||||
$id_from_code = wc_get_coupon_id_by_code( $coupon_code, $post_id );
|
||||
|
||||
if ( $id_from_code ) {
|
||||
WC_Admin_Meta_Boxes::add_error( __( 'Coupon code already exists - customers will use the latest coupon with this code.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
$product_categories = isset( $_POST['product_categories'] ) ? (array) $_POST['product_categories'] : array();
|
||||
$exclude_product_categories = isset( $_POST['exclude_product_categories'] ) ? (array) $_POST['exclude_product_categories'] : array();
|
||||
|
||||
$coupon = new WC_Coupon( $post_id );
|
||||
$coupon->set_props(
|
||||
array(
|
||||
'code' => $post->post_title,
|
||||
'discount_type' => wc_clean( $_POST['discount_type'] ),
|
||||
'amount' => wc_format_decimal( $_POST['coupon_amount'] ),
|
||||
'date_expires' => wc_clean( $_POST['expiry_date'] ),
|
||||
'individual_use' => isset( $_POST['individual_use'] ),
|
||||
'product_ids' => isset( $_POST['product_ids'] ) ? array_filter( array_map( 'intval', (array) $_POST['product_ids'] ) ) : array(),
|
||||
'excluded_product_ids' => isset( $_POST['exclude_product_ids'] ) ? array_filter( array_map( 'intval', (array) $_POST['exclude_product_ids'] ) ) : array(),
|
||||
'usage_limit' => absint( $_POST['usage_limit'] ),
|
||||
'usage_limit_per_user' => absint( $_POST['usage_limit_per_user'] ),
|
||||
'limit_usage_to_x_items' => absint( $_POST['limit_usage_to_x_items'] ),
|
||||
'free_shipping' => isset( $_POST['free_shipping'] ),
|
||||
'product_categories' => array_filter( array_map( 'intval', $product_categories ) ),
|
||||
'excluded_product_categories' => array_filter( array_map( 'intval', $exclude_product_categories ) ),
|
||||
'exclude_sale_items' => isset( $_POST['exclude_sale_items'] ),
|
||||
'minimum_amount' => wc_format_decimal( $_POST['minimum_amount'] ),
|
||||
'maximum_amount' => wc_format_decimal( $_POST['maximum_amount'] ),
|
||||
'email_restrictions' => array_filter( array_map( 'trim', explode( ',', wc_clean( $_POST['customer_email'] ) ) ) ),
|
||||
)
|
||||
);
|
||||
$coupon->save();
|
||||
do_action( 'woocommerce_coupon_options_save', $post_id, $coupon );
|
||||
}
|
||||
}
|
178
includes/admin/meta-boxes/class-wc-meta-box-order-actions.php
Normal file
178
includes/admin/meta-boxes/class-wc-meta-box-order-actions.php
Normal file
@ -0,0 +1,178 @@
|
||||
<?php
|
||||
/**
|
||||
* Order Actions
|
||||
*
|
||||
* Functions for displaying the order actions meta box.
|
||||
*
|
||||
* @package WooCommerce\Admin\Meta Boxes
|
||||
* @version 2.1.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Meta_Box_Order_Actions Class.
|
||||
*/
|
||||
class WC_Meta_Box_Order_Actions {
|
||||
|
||||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
global $theorder;
|
||||
|
||||
// This is used by some callbacks attached to hooks such as woocommerce_order_actions which rely on the global to determine if actions should be displayed for certain orders.
|
||||
// Avoid using this global with the `woocommerce_order_actions` filter, instead use the $order filter arg.
|
||||
if ( ! is_object( $theorder ) ) {
|
||||
$theorder = wc_get_order( $post->ID );
|
||||
}
|
||||
|
||||
$theorder = $theorder instanceof WC_Order ? $theorder : null;
|
||||
$order_actions = self::get_available_order_actions_for_order( $theorder );
|
||||
?>
|
||||
<ul class="order_actions submitbox">
|
||||
|
||||
<?php do_action( 'woocommerce_order_actions_start', $post->ID ); ?>
|
||||
|
||||
<li class="wide" id="actions">
|
||||
<select name="wc_order_action">
|
||||
<option value=""><?php esc_html_e( 'Choose an action...', 'woocommerce' ); ?></option>
|
||||
<?php foreach ( $order_actions as $action => $title ) { ?>
|
||||
<option value="<?php echo esc_attr( $action ); ?>"><?php echo esc_html( $title ); ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<button class="button wc-reload"><span><?php esc_html_e( 'Apply', 'woocommerce' ); ?></span></button>
|
||||
</li>
|
||||
|
||||
<li class="wide">
|
||||
<div id="delete-action">
|
||||
<?php
|
||||
if ( current_user_can( 'delete_post', $post->ID ) ) {
|
||||
|
||||
if ( ! EMPTY_TRASH_DAYS ) {
|
||||
$delete_text = __( 'Delete permanently', 'woocommerce' );
|
||||
} else {
|
||||
$delete_text = __( 'Move to Trash', 'woocommerce' );
|
||||
}
|
||||
?>
|
||||
<a class="submitdelete deletion" href="<?php echo esc_url( get_delete_post_link( $post->ID ) ); ?>"><?php echo esc_html( $delete_text ); ?></a>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="button save_order button-primary" name="save" value="<?php echo 'auto-draft' === $post->post_status ? esc_attr__( 'Create', 'woocommerce' ) : esc_attr__( 'Update', 'woocommerce' ); ?>"><?php echo 'auto-draft' === $post->post_status ? esc_html__( 'Create', 'woocommerce' ) : esc_html__( 'Update', 'woocommerce' ); ?></button>
|
||||
</li>
|
||||
|
||||
<?php do_action( 'woocommerce_order_actions_end', $post->ID ); ?>
|
||||
|
||||
</ul>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta box data.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param WP_Post $post Post Object.
|
||||
*/
|
||||
public static function save( $post_id, $post ) {
|
||||
// Order data saved, now get it so we can manipulate status.
|
||||
$order = wc_get_order( $post_id );
|
||||
|
||||
// Handle button actions.
|
||||
if ( ! empty( $_POST['wc_order_action'] ) ) { // @codingStandardsIgnoreLine
|
||||
|
||||
$action = wc_clean( wp_unslash( $_POST['wc_order_action'] ) ); // @codingStandardsIgnoreLine
|
||||
|
||||
if ( 'send_order_details' === $action ) {
|
||||
do_action( 'woocommerce_before_resend_order_emails', $order, 'customer_invoice' );
|
||||
|
||||
// Send the customer invoice email.
|
||||
WC()->payment_gateways();
|
||||
WC()->shipping();
|
||||
WC()->mailer()->customer_invoice( $order );
|
||||
|
||||
// Note the event.
|
||||
$order->add_order_note( __( 'Order details manually sent to customer.', 'woocommerce' ), false, true );
|
||||
|
||||
do_action( 'woocommerce_after_resend_order_email', $order, 'customer_invoice' );
|
||||
|
||||
// Change the post saved message.
|
||||
add_filter( 'redirect_post_location', array( __CLASS__, 'set_email_sent_message' ) );
|
||||
|
||||
} elseif ( 'send_order_details_admin' === $action ) {
|
||||
|
||||
do_action( 'woocommerce_before_resend_order_emails', $order, 'new_order' );
|
||||
|
||||
WC()->payment_gateways();
|
||||
WC()->shipping();
|
||||
add_filter( 'woocommerce_new_order_email_allows_resend', '__return_true' );
|
||||
WC()->mailer()->emails['WC_Email_New_Order']->trigger( $order->get_id(), $order, true );
|
||||
remove_filter( 'woocommerce_new_order_email_allows_resend', '__return_true' );
|
||||
|
||||
do_action( 'woocommerce_after_resend_order_email', $order, 'new_order' );
|
||||
|
||||
// Change the post saved message.
|
||||
add_filter( 'redirect_post_location', array( __CLASS__, 'set_email_sent_message' ) );
|
||||
|
||||
} elseif ( 'regenerate_download_permissions' === $action ) {
|
||||
|
||||
$data_store = WC_Data_Store::load( 'customer-download' );
|
||||
$data_store->delete_by_order_id( $post_id );
|
||||
wc_downloadable_product_permissions( $post_id, true );
|
||||
|
||||
} else {
|
||||
|
||||
if ( ! did_action( 'woocommerce_order_action_' . sanitize_title( $action ) ) ) {
|
||||
do_action( 'woocommerce_order_action_' . sanitize_title( $action ), $order );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the correct message ID.
|
||||
*
|
||||
* @param string $location Location.
|
||||
* @since 2.3.0
|
||||
* @static
|
||||
* @return string
|
||||
*/
|
||||
public static function set_email_sent_message( $location ) {
|
||||
return add_query_arg( 'message', 11, $location );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the available order actions for a given order.
|
||||
*
|
||||
* @since 5.8.0
|
||||
*
|
||||
* @param WC_Order|null $order The order object or null if no order is available.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function get_available_order_actions_for_order( $order ) {
|
||||
$actions = array(
|
||||
'send_order_details' => __( 'Email invoice / order details to customer', 'woocommerce' ),
|
||||
'send_order_details_admin' => __( 'Resend new order notification', 'woocommerce' ),
|
||||
'regenerate_download_permissions' => __( 'Regenerate download permissions', 'woocommerce' ),
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter: woocommerce_order_actions
|
||||
* Allows filtering of the available order actions for an order.
|
||||
*
|
||||
* @since 2.1.0 Filter was added.
|
||||
* @since 5.8.0 The $order param was added.
|
||||
*
|
||||
* @param array $actions The available order actions for the order.
|
||||
* @param WC_Order|null $order The order object or null if no order is available.
|
||||
*/
|
||||
return apply_filters( 'woocommerce_order_actions', $actions, $order );
|
||||
}
|
||||
}
|
637
includes/admin/meta-boxes/class-wc-meta-box-order-data.php
Normal file
637
includes/admin/meta-boxes/class-wc-meta-box-order-data.php
Normal file
@ -0,0 +1,637 @@
|
||||
<?php
|
||||
/**
|
||||
* Order Data
|
||||
*
|
||||
* Functions for displaying the order data meta box.
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce\Admin\Meta Boxes
|
||||
* @version 2.2.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Meta_Box_Order_Data Class.
|
||||
*/
|
||||
class WC_Meta_Box_Order_Data {
|
||||
|
||||
/**
|
||||
* Billing fields.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $billing_fields = array();
|
||||
|
||||
/**
|
||||
* Shipping fields.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $shipping_fields = array();
|
||||
|
||||
/**
|
||||
* Init billing and shipping fields we display + save.
|
||||
*/
|
||||
public static function init_address_fields() {
|
||||
|
||||
self::$billing_fields = apply_filters(
|
||||
'woocommerce_admin_billing_fields',
|
||||
array(
|
||||
'first_name' => array(
|
||||
'label' => __( 'First name', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'last_name' => array(
|
||||
'label' => __( 'Last name', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'company' => array(
|
||||
'label' => __( 'Company', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'address_1' => array(
|
||||
'label' => __( 'Address line 1', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'address_2' => array(
|
||||
'label' => __( 'Address line 2', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'city' => array(
|
||||
'label' => __( 'City', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'postcode' => array(
|
||||
'label' => __( 'Postcode / ZIP', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'country' => array(
|
||||
'label' => __( 'Country / Region', 'woocommerce' ),
|
||||
'show' => false,
|
||||
'class' => 'js_field-country select short',
|
||||
'type' => 'select',
|
||||
'options' => array( '' => __( 'Select a country / region…', 'woocommerce' ) ) + WC()->countries->get_allowed_countries(),
|
||||
),
|
||||
'state' => array(
|
||||
'label' => __( 'State / County', 'woocommerce' ),
|
||||
'class' => 'js_field-state select short',
|
||||
'show' => false,
|
||||
),
|
||||
'email' => array(
|
||||
'label' => __( 'Email address', 'woocommerce' ),
|
||||
),
|
||||
'phone' => array(
|
||||
'label' => __( 'Phone', 'woocommerce' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
self::$shipping_fields = apply_filters(
|
||||
'woocommerce_admin_shipping_fields',
|
||||
array(
|
||||
'first_name' => array(
|
||||
'label' => __( 'First name', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'last_name' => array(
|
||||
'label' => __( 'Last name', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'company' => array(
|
||||
'label' => __( 'Company', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'address_1' => array(
|
||||
'label' => __( 'Address line 1', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'address_2' => array(
|
||||
'label' => __( 'Address line 2', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'city' => array(
|
||||
'label' => __( 'City', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'postcode' => array(
|
||||
'label' => __( 'Postcode / ZIP', 'woocommerce' ),
|
||||
'show' => false,
|
||||
),
|
||||
'country' => array(
|
||||
'label' => __( 'Country / Region', 'woocommerce' ),
|
||||
'show' => false,
|
||||
'type' => 'select',
|
||||
'class' => 'js_field-country select short',
|
||||
'options' => array( '' => __( 'Select a country / region…', 'woocommerce' ) ) + WC()->countries->get_shipping_countries(),
|
||||
),
|
||||
'state' => array(
|
||||
'label' => __( 'State / County', 'woocommerce' ),
|
||||
'class' => 'js_field-state select short',
|
||||
'show' => false,
|
||||
),
|
||||
'phone' => array(
|
||||
'label' => __( 'Phone', 'woocommerce' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
global $theorder;
|
||||
|
||||
if ( ! is_object( $theorder ) ) {
|
||||
$theorder = wc_get_order( $post->ID );
|
||||
}
|
||||
|
||||
$order = $theorder;
|
||||
|
||||
self::init_address_fields();
|
||||
|
||||
if ( WC()->payment_gateways() ) {
|
||||
$payment_gateways = WC()->payment_gateways->payment_gateways();
|
||||
} else {
|
||||
$payment_gateways = array();
|
||||
}
|
||||
|
||||
$payment_method = $order->get_payment_method();
|
||||
|
||||
$order_type_object = get_post_type_object( $post->post_type );
|
||||
wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );
|
||||
?>
|
||||
<style type="text/css">
|
||||
#post-body-content, #titlediv { display:none }
|
||||
</style>
|
||||
<div class="panel-wrap woocommerce">
|
||||
<input name="post_title" type="hidden" value="<?php echo empty( $post->post_title ) ? __( 'Order', 'woocommerce' ) : esc_attr( $post->post_title ); ?>" />
|
||||
<input name="post_status" type="hidden" value="<?php echo esc_attr( $post->post_status ); ?>" />
|
||||
<div id="order_data" class="panel woocommerce-order-data">
|
||||
<h2 class="woocommerce-order-data__heading">
|
||||
<?php
|
||||
|
||||
/* translators: 1: order type 2: order number */
|
||||
printf(
|
||||
esc_html__( '%1$s #%2$s details', 'woocommerce' ),
|
||||
esc_html( $order_type_object->labels->singular_name ),
|
||||
esc_html( $order->get_order_number() )
|
||||
);
|
||||
|
||||
?>
|
||||
</h2>
|
||||
<p class="woocommerce-order-data__meta order_number">
|
||||
<?php
|
||||
|
||||
$meta_list = array();
|
||||
|
||||
if ( $payment_method && 'other' !== $payment_method ) {
|
||||
/* translators: %s: payment method */
|
||||
$payment_method_string = sprintf(
|
||||
__( 'Payment via %s', 'woocommerce' ),
|
||||
esc_html( isset( $payment_gateways[ $payment_method ] ) ? $payment_gateways[ $payment_method ]->get_title() : $payment_method )
|
||||
);
|
||||
|
||||
if ( $transaction_id = $order->get_transaction_id() ) {
|
||||
if ( isset( $payment_gateways[ $payment_method ] ) && ( $url = $payment_gateways[ $payment_method ]->get_transaction_url( $order ) ) ) {
|
||||
$payment_method_string .= ' (<a href="' . esc_url( $url ) . '" target="_blank">' . esc_html( $transaction_id ) . '</a>)';
|
||||
} else {
|
||||
$payment_method_string .= ' (' . esc_html( $transaction_id ) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
$meta_list[] = $payment_method_string;
|
||||
}
|
||||
|
||||
if ( $order->get_date_paid() ) {
|
||||
/* translators: 1: date 2: time */
|
||||
$meta_list[] = sprintf(
|
||||
__( 'Paid on %1$s @ %2$s', 'woocommerce' ),
|
||||
wc_format_datetime( $order->get_date_paid() ),
|
||||
wc_format_datetime( $order->get_date_paid(), get_option( 'time_format' ) )
|
||||
);
|
||||
}
|
||||
|
||||
if ( $ip_address = $order->get_customer_ip_address() ) {
|
||||
/* translators: %s: IP address */
|
||||
$meta_list[] = sprintf(
|
||||
__( 'Customer IP: %s', 'woocommerce' ),
|
||||
'<span class="woocommerce-Order-customerIP">' . esc_html( $ip_address ) . '</span>'
|
||||
);
|
||||
}
|
||||
|
||||
echo wp_kses_post( implode( '. ', $meta_list ) );
|
||||
|
||||
?>
|
||||
</p>
|
||||
<div class="order_data_column_container">
|
||||
<div class="order_data_column">
|
||||
<h3><?php esc_html_e( 'General', 'woocommerce' ); ?></h3>
|
||||
|
||||
<p class="form-field form-field-wide">
|
||||
<label for="order_date"><?php _e( 'Date created:', 'woocommerce' ); ?></label>
|
||||
<input type="text" class="date-picker" name="order_date" maxlength="10" value="<?php echo esc_attr( date_i18n( 'Y-m-d', strtotime( $post->post_date ) ) ); ?>" pattern="<?php echo esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ); ?>" />@
|
||||
‎
|
||||
<input type="number" class="hour" placeholder="<?php esc_attr_e( 'h', 'woocommerce' ); ?>" name="order_date_hour" min="0" max="23" step="1" value="<?php echo esc_attr( date_i18n( 'H', strtotime( $post->post_date ) ) ); ?>" pattern="([01]?[0-9]{1}|2[0-3]{1})" />:
|
||||
<input type="number" class="minute" placeholder="<?php esc_attr_e( 'm', 'woocommerce' ); ?>" name="order_date_minute" min="0" max="59" step="1" value="<?php echo esc_attr( date_i18n( 'i', strtotime( $post->post_date ) ) ); ?>" pattern="[0-5]{1}[0-9]{1}" />
|
||||
<input type="hidden" name="order_date_second" value="<?php echo esc_attr( date_i18n( 's', strtotime( $post->post_date ) ) ); ?>" />
|
||||
</p>
|
||||
|
||||
<p class="form-field form-field-wide wc-order-status">
|
||||
<label for="order_status">
|
||||
<?php
|
||||
_e( 'Status:', 'woocommerce' );
|
||||
if ( $order->needs_payment() ) {
|
||||
printf(
|
||||
'<a href="%s">%s</a>',
|
||||
esc_url( $order->get_checkout_payment_url() ),
|
||||
__( 'Customer payment page →', 'woocommerce' )
|
||||
);
|
||||
}
|
||||
?>
|
||||
</label>
|
||||
<select id="order_status" name="order_status" class="wc-enhanced-select">
|
||||
<?php
|
||||
$statuses = wc_get_order_statuses();
|
||||
foreach ( $statuses as $status => $status_name ) {
|
||||
echo '<option value="' . esc_attr( $status ) . '" ' . selected( $status, 'wc-' . $order->get_status( 'edit' ), false ) . '>' . esc_html( $status_name ) . '</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</p>
|
||||
|
||||
<p class="form-field form-field-wide wc-customer-user">
|
||||
<!--email_off--> <!-- Disable CloudFlare email obfuscation -->
|
||||
<label for="customer_user">
|
||||
<?php
|
||||
_e( 'Customer:', 'woocommerce' );
|
||||
if ( $order->get_user_id( 'edit' ) ) {
|
||||
$args = array(
|
||||
'post_status' => 'all',
|
||||
'post_type' => 'shop_order',
|
||||
'_customer_user' => $order->get_user_id( 'edit' ),
|
||||
);
|
||||
printf(
|
||||
'<a href="%s">%s</a>',
|
||||
esc_url( add_query_arg( $args, admin_url( 'edit.php' ) ) ),
|
||||
' ' . __( 'View other orders →', 'woocommerce' )
|
||||
);
|
||||
printf(
|
||||
'<a href="%s">%s</a>',
|
||||
esc_url( add_query_arg( 'user_id', $order->get_user_id( 'edit' ), admin_url( 'user-edit.php' ) ) ),
|
||||
' ' . __( 'Profile →', 'woocommerce' )
|
||||
);
|
||||
}
|
||||
?>
|
||||
</label>
|
||||
<?php
|
||||
$user_string = '';
|
||||
$user_id = '';
|
||||
if ( $order->get_user_id() ) {
|
||||
$user_id = absint( $order->get_user_id() );
|
||||
$user = get_user_by( 'id', $user_id );
|
||||
/* translators: 1: user display name 2: user ID 3: user email */
|
||||
$user_string = sprintf(
|
||||
esc_html__( '%1$s (#%2$s – %3$s)', 'woocommerce' ),
|
||||
$user->display_name,
|
||||
absint( $user->ID ),
|
||||
$user->user_email
|
||||
);
|
||||
}
|
||||
?>
|
||||
<select class="wc-customer-search" id="customer_user" name="customer_user" data-placeholder="<?php esc_attr_e( 'Guest', 'woocommerce' ); ?>" data-allow_clear="true">
|
||||
<option value="<?php echo esc_attr( $user_id ); ?>" selected="selected"><?php echo htmlspecialchars( wp_kses_post( $user_string ) ); // htmlspecialchars to prevent XSS when rendered by selectWoo. ?></option>
|
||||
</select>
|
||||
<!--/email_off-->
|
||||
</p>
|
||||
<?php do_action( 'woocommerce_admin_order_data_after_order_details', $order ); ?>
|
||||
</div>
|
||||
<div class="order_data_column">
|
||||
<h3>
|
||||
<?php esc_html_e( 'Billing', 'woocommerce' ); ?>
|
||||
<a href="#" class="edit_address"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a>
|
||||
<span>
|
||||
<a href="#" class="load_customer_billing" style="display:none;"><?php esc_html_e( 'Load billing address', 'woocommerce' ); ?></a>
|
||||
</span>
|
||||
</h3>
|
||||
<div class="address">
|
||||
<?php
|
||||
|
||||
// Display values.
|
||||
if ( $order->get_formatted_billing_address() ) {
|
||||
echo '<p>' . wp_kses( $order->get_formatted_billing_address(), array( 'br' => array() ) ) . '</p>';
|
||||
} else {
|
||||
echo '<p class="none_set"><strong>' . __( 'Address:', 'woocommerce' ) . '</strong> ' . __( 'No billing address set.', 'woocommerce' ) . '</p>';
|
||||
}
|
||||
|
||||
foreach ( self::$billing_fields as $key => $field ) {
|
||||
if ( isset( $field['show'] ) && false === $field['show'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field_name = 'billing_' . $key;
|
||||
|
||||
if ( isset( $field['value'] ) ) {
|
||||
$field_value = $field['value'];
|
||||
} elseif ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
|
||||
$field_value = $order->{"get_$field_name"}( 'edit' );
|
||||
} else {
|
||||
$field_value = $order->get_meta( '_' . $field_name );
|
||||
}
|
||||
|
||||
if ( 'billing_phone' === $field_name ) {
|
||||
$field_value = wc_make_phone_clickable( $field_value );
|
||||
} elseif ( 'billing_email' === $field_name ) {
|
||||
$field_value = '<a href="' . esc_url( 'mailto:' . $field_value ) . '">' . $field_value . '</a>';
|
||||
} else {
|
||||
$field_value = make_clickable( esc_html( $field_value ) );
|
||||
}
|
||||
|
||||
if ( $field_value ) {
|
||||
echo '<p><strong>' . esc_html( $field['label'] ) . ':</strong> ' . wp_kses_post( $field_value ) . '</p>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="edit_address">
|
||||
<?php
|
||||
|
||||
// Display form.
|
||||
foreach ( self::$billing_fields as $key => $field ) {
|
||||
if ( ! isset( $field['type'] ) ) {
|
||||
$field['type'] = 'text';
|
||||
}
|
||||
if ( ! isset( $field['id'] ) ) {
|
||||
$field['id'] = '_billing_' . $key;
|
||||
}
|
||||
|
||||
$field_name = 'billing_' . $key;
|
||||
|
||||
if ( ! isset( $field['value'] ) ) {
|
||||
if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
|
||||
$field['value'] = $order->{"get_$field_name"}( 'edit' );
|
||||
} else {
|
||||
$field['value'] = $order->get_meta( '_' . $field_name );
|
||||
}
|
||||
}
|
||||
|
||||
switch ( $field['type'] ) {
|
||||
case 'select':
|
||||
woocommerce_wp_select( $field );
|
||||
break;
|
||||
default:
|
||||
woocommerce_wp_text_input( $field );
|
||||
break;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<p class="form-field form-field-wide">
|
||||
<label><?php esc_html_e( 'Payment method:', 'woocommerce' ); ?></label>
|
||||
<select name="_payment_method" id="_payment_method" class="first">
|
||||
<option value=""><?php esc_html_e( 'N/A', 'woocommerce' ); ?></option>
|
||||
<?php
|
||||
$found_method = false;
|
||||
|
||||
foreach ( $payment_gateways as $gateway ) {
|
||||
if ( 'yes' === $gateway->enabled ) {
|
||||
echo '<option value="' . esc_attr( $gateway->id ) . '" ' . selected( $payment_method, $gateway->id, false ) . '>' . esc_html( $gateway->get_title() ) . '</option>';
|
||||
if ( $payment_method == $gateway->id ) {
|
||||
$found_method = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $found_method && ! empty( $payment_method ) ) {
|
||||
echo '<option value="' . esc_attr( $payment_method ) . '" selected="selected">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
|
||||
} else {
|
||||
echo '<option value="other">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</p>
|
||||
<?php
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_transaction_id',
|
||||
'label' => __( 'Transaction ID', 'woocommerce' ),
|
||||
'value' => $order->get_transaction_id( 'edit' ),
|
||||
)
|
||||
);
|
||||
?>
|
||||
|
||||
</div>
|
||||
<?php do_action( 'woocommerce_admin_order_data_after_billing_address', $order ); ?>
|
||||
</div>
|
||||
<div class="order_data_column">
|
||||
<h3>
|
||||
<?php esc_html_e( 'Shipping', 'woocommerce' ); ?>
|
||||
<a href="#" class="edit_address"><?php esc_html_e( 'Edit', 'woocommerce' ); ?></a>
|
||||
<span>
|
||||
<a href="#" class="load_customer_shipping" style="display:none;"><?php esc_html_e( 'Load shipping address', 'woocommerce' ); ?></a>
|
||||
<a href="#" class="billing-same-as-shipping" style="display:none;"><?php esc_html_e( 'Copy billing address', 'woocommerce' ); ?></a>
|
||||
</span>
|
||||
</h3>
|
||||
<div class="address">
|
||||
<?php
|
||||
|
||||
// Display values.
|
||||
if ( $order->get_formatted_shipping_address() ) {
|
||||
echo '<p>' . wp_kses( $order->get_formatted_shipping_address(), array( 'br' => array() ) ) . '</p>';
|
||||
} else {
|
||||
echo '<p class="none_set"><strong>' . __( 'Address:', 'woocommerce' ) . '</strong> ' . __( 'No shipping address set.', 'woocommerce' ) . '</p>';
|
||||
}
|
||||
|
||||
if ( ! empty( self::$shipping_fields ) ) {
|
||||
foreach ( self::$shipping_fields as $key => $field ) {
|
||||
if ( isset( $field['show'] ) && false === $field['show'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field_name = 'shipping_' . $key;
|
||||
|
||||
if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
|
||||
$field_value = $order->{"get_$field_name"}( 'edit' );
|
||||
} else {
|
||||
$field_value = $order->get_meta( '_' . $field_name );
|
||||
}
|
||||
|
||||
if ( 'shipping_phone' === $field_name ) {
|
||||
$field_value = wc_make_phone_clickable( $field_value );
|
||||
}
|
||||
|
||||
if ( $field_value ) {
|
||||
echo '<p><strong>' . esc_html( $field['label'] ) . ':</strong> ' . wp_kses_post( $field_value ) . '</p>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( apply_filters( 'woocommerce_enable_order_notes_field', 'yes' == get_option( 'woocommerce_enable_order_comments', 'yes' ) ) && $post->post_excerpt ) {
|
||||
echo '<p class="order_note"><strong>' . __( 'Customer provided note:', 'woocommerce' ) . '</strong> ' . nl2br( esc_html( $post->post_excerpt ) ) . '</p>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="edit_address">
|
||||
<?php
|
||||
|
||||
// Display form.
|
||||
if ( ! empty( self::$shipping_fields ) ) {
|
||||
foreach ( self::$shipping_fields as $key => $field ) {
|
||||
if ( ! isset( $field['type'] ) ) {
|
||||
$field['type'] = 'text';
|
||||
}
|
||||
if ( ! isset( $field['id'] ) ) {
|
||||
$field['id'] = '_shipping_' . $key;
|
||||
}
|
||||
|
||||
$field_name = 'shipping_' . $key;
|
||||
|
||||
if ( is_callable( array( $order, 'get_' . $field_name ) ) ) {
|
||||
$field['value'] = $order->{"get_$field_name"}( 'edit' );
|
||||
} else {
|
||||
$field['value'] = $order->get_meta( '_' . $field_name );
|
||||
}
|
||||
|
||||
switch ( $field['type'] ) {
|
||||
case 'select':
|
||||
woocommerce_wp_select( $field );
|
||||
break;
|
||||
default:
|
||||
woocommerce_wp_text_input( $field );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( apply_filters( 'woocommerce_enable_order_notes_field', 'yes' == get_option( 'woocommerce_enable_order_comments', 'yes' ) ) ) :
|
||||
?>
|
||||
<p class="form-field form-field-wide">
|
||||
<label for="excerpt"><?php _e( 'Customer provided note', 'woocommerce' ); ?>:</label>
|
||||
<textarea rows="1" cols="40" name="excerpt" tabindex="6" id="excerpt" placeholder="<?php esc_attr_e( 'Customer notes about the order', 'woocommerce' ); ?>"><?php echo wp_kses_post( $post->post_excerpt ); ?></textarea>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_data_after_shipping_address', $order ); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta box data.
|
||||
*
|
||||
* @param int $order_id Order ID.
|
||||
*/
|
||||
public static function save( $order_id ) {
|
||||
self::init_address_fields();
|
||||
|
||||
// Ensure gateways are loaded in case they need to insert data into the emails.
|
||||
WC()->payment_gateways();
|
||||
WC()->shipping();
|
||||
|
||||
// Get order object.
|
||||
$order = wc_get_order( $order_id );
|
||||
$props = array();
|
||||
|
||||
// Create order key.
|
||||
if ( ! $order->get_order_key() ) {
|
||||
$props['order_key'] = wc_generate_order_key();
|
||||
}
|
||||
|
||||
// Update customer.
|
||||
$customer_id = isset( $_POST['customer_user'] ) ? absint( $_POST['customer_user'] ) : 0;
|
||||
if ( $customer_id !== $order->get_customer_id() ) {
|
||||
$props['customer_id'] = $customer_id;
|
||||
}
|
||||
|
||||
// Update billing fields.
|
||||
if ( ! empty( self::$billing_fields ) ) {
|
||||
foreach ( self::$billing_fields as $key => $field ) {
|
||||
if ( ! isset( $field['id'] ) ) {
|
||||
$field['id'] = '_billing_' . $key;
|
||||
}
|
||||
|
||||
if ( ! isset( $_POST[ $field['id'] ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( is_callable( array( $order, 'set_billing_' . $key ) ) ) {
|
||||
$props[ 'billing_' . $key ] = wc_clean( wp_unslash( $_POST[ $field['id'] ] ) );
|
||||
} else {
|
||||
$order->update_meta_data( $field['id'], wc_clean( wp_unslash( $_POST[ $field['id'] ] ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update shipping fields.
|
||||
if ( ! empty( self::$shipping_fields ) ) {
|
||||
foreach ( self::$shipping_fields as $key => $field ) {
|
||||
if ( ! isset( $field['id'] ) ) {
|
||||
$field['id'] = '_shipping_' . $key;
|
||||
}
|
||||
|
||||
if ( ! isset( $_POST[ $field['id'] ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( is_callable( array( $order, 'set_shipping_' . $key ) ) ) {
|
||||
$props[ 'shipping_' . $key ] = wc_clean( wp_unslash( $_POST[ $field['id'] ] ) );
|
||||
} else {
|
||||
$order->update_meta_data( $field['id'], wc_clean( wp_unslash( $_POST[ $field['id'] ] ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $_POST['_transaction_id'] ) ) {
|
||||
$props['transaction_id'] = wc_clean( wp_unslash( $_POST['_transaction_id'] ) );
|
||||
}
|
||||
|
||||
// Payment method handling.
|
||||
if ( $order->get_payment_method() !== wp_unslash( $_POST['_payment_method'] ) ) {
|
||||
$methods = WC()->payment_gateways->payment_gateways();
|
||||
$payment_method = wc_clean( wp_unslash( $_POST['_payment_method'] ) );
|
||||
$payment_method_title = $payment_method;
|
||||
|
||||
if ( isset( $methods ) && isset( $methods[ $payment_method ] ) ) {
|
||||
$payment_method_title = $methods[ $payment_method ]->get_title();
|
||||
}
|
||||
|
||||
if ( $payment_method == 'other') {
|
||||
$payment_method_title = esc_html__( 'Other', 'woocommerce' );
|
||||
}
|
||||
|
||||
$props['payment_method'] = $payment_method;
|
||||
$props['payment_method_title'] = $payment_method_title;
|
||||
}
|
||||
|
||||
// Update date.
|
||||
if ( empty( $_POST['order_date'] ) ) {
|
||||
$date = time();
|
||||
} else {
|
||||
$date = gmdate( 'Y-m-d H:i:s', strtotime( $_POST['order_date'] . ' ' . (int) $_POST['order_date_hour'] . ':' . (int) $_POST['order_date_minute'] . ':' . (int) $_POST['order_date_second'] ) );
|
||||
}
|
||||
|
||||
$props['date_created'] = $date;
|
||||
|
||||
// Set created via prop if new post.
|
||||
if ( isset( $_POST['original_post_status'] ) && $_POST['original_post_status'] === 'auto-draft' ) {
|
||||
$props['created_via'] = 'admin';
|
||||
}
|
||||
|
||||
// Save order data.
|
||||
$order->set_props( $props );
|
||||
$order->set_status( wc_clean( wp_unslash( $_POST['order_status'] ) ), '', true );
|
||||
$order->save();
|
||||
}
|
||||
}
|
106
includes/admin/meta-boxes/class-wc-meta-box-order-downloads.php
Normal file
106
includes/admin/meta-boxes/class-wc-meta-box-order-downloads.php
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/**
|
||||
* Order Downloads
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce\Admin\Meta Boxes
|
||||
* @version 2.1.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Meta_Box_Order_Downloads Class.
|
||||
*/
|
||||
class WC_Meta_Box_Order_Downloads {
|
||||
|
||||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
?>
|
||||
<div class="order_download_permissions wc-metaboxes-wrapper">
|
||||
|
||||
<div class="wc-metaboxes">
|
||||
<?php
|
||||
$data_store = WC_Data_Store::load( 'customer-download' );
|
||||
$download_permissions = $data_store->get_downloads(
|
||||
array(
|
||||
'order_id' => $post->ID,
|
||||
'orderby' => 'product_id',
|
||||
)
|
||||
);
|
||||
|
||||
$product = null;
|
||||
$loop = 0;
|
||||
$file_counter = 1;
|
||||
|
||||
if ( $download_permissions && sizeof( $download_permissions ) > 0 ) {
|
||||
foreach ( $download_permissions as $download ) {
|
||||
if ( ! $product || $product->get_id() !== $download->get_product_id() ) {
|
||||
$product = wc_get_product( $download->get_product_id() );
|
||||
$file_counter = 1;
|
||||
}
|
||||
|
||||
// don't show permissions to files that have since been removed.
|
||||
if ( ! $product || ! $product->exists() || ! $product->has_file( $download->get_download_id() ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Show file title instead of count if set.
|
||||
$file = $product->get_file( $download->get_download_id() );
|
||||
$file_count = isset( $file['name'] ) ? $file['name'] : sprintf( __( 'File %d', 'woocommerce' ), $file_counter );
|
||||
|
||||
include __DIR__ . '/views/html-order-download-permission.php';
|
||||
|
||||
$loop++;
|
||||
$file_counter++;
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="toolbar">
|
||||
<p class="buttons">
|
||||
<select id="grant_access_id" class="wc-product-search" name="grant_access_id[]" multiple="multiple" style="width: 400px;" data-placeholder="<?php esc_attr_e( 'Search for a downloadable product…', 'woocommerce' ); ?>" data-action="woocommerce_json_search_downloadable_products_and_variations"></select>
|
||||
<button type="button" class="button grant_access">
|
||||
<?php _e( 'Grant access', 'woocommerce' ); ?>
|
||||
</button>
|
||||
</p>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta box data.
|
||||
*
|
||||
* @param int $post_id
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public static function save( $post_id, $post ) {
|
||||
if ( isset( $_POST['permission_id'] ) ) {
|
||||
$permission_ids = $_POST['permission_id'];
|
||||
$downloads_remaining = $_POST['downloads_remaining'];
|
||||
$access_expires = $_POST['access_expires'];
|
||||
$max = max( array_keys( $permission_ids ) );
|
||||
|
||||
for ( $i = 0; $i <= $max; $i ++ ) {
|
||||
if ( ! isset( $permission_ids[ $i ] ) ) {
|
||||
continue;
|
||||
}
|
||||
$download = new WC_Customer_Download( $permission_ids[ $i ] );
|
||||
$download->set_downloads_remaining( wc_clean( $downloads_remaining[ $i ] ) );
|
||||
$download->set_access_expires( array_key_exists( $i, $access_expires ) && '' !== $access_expires[ $i ] ? strtotime( $access_expires[ $i ] ) : '' );
|
||||
$download->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
56
includes/admin/meta-boxes/class-wc-meta-box-order-items.php
Normal file
56
includes/admin/meta-boxes/class-wc-meta-box-order-items.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Order Data
|
||||
*
|
||||
* Functions for displaying the order items meta box.
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce\Admin\Meta Boxes
|
||||
* @version 2.1.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Meta_Box_Order_Items Class.
|
||||
*/
|
||||
class WC_Meta_Box_Order_Items {
|
||||
|
||||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
global $post, $thepostid, $theorder;
|
||||
|
||||
if ( ! is_int( $thepostid ) ) {
|
||||
$thepostid = $post->ID;
|
||||
}
|
||||
|
||||
if ( ! is_object( $theorder ) ) {
|
||||
$theorder = wc_get_order( $thepostid );
|
||||
}
|
||||
|
||||
$order = $theorder;
|
||||
$data = get_post_meta( $post->ID );
|
||||
|
||||
include __DIR__ . '/views/html-order-items.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta box data.
|
||||
*
|
||||
* @param int $post_id
|
||||
*/
|
||||
public static function save( $post_id ) {
|
||||
/**
|
||||
* This $_POST variable's data has been validated and escaped
|
||||
* inside `wc_save_order_items()` function.
|
||||
*/
|
||||
wc_save_order_items( $post_id, $_POST );
|
||||
}
|
||||
}
|
49
includes/admin/meta-boxes/class-wc-meta-box-order-notes.php
Normal file
49
includes/admin/meta-boxes/class-wc-meta-box-order-notes.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Order Notes
|
||||
*
|
||||
* @package WooCommerce\Admin\Meta Boxes
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Meta_Box_Order_Notes Class.
|
||||
*/
|
||||
class WC_Meta_Box_Order_Notes {
|
||||
|
||||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
global $post;
|
||||
|
||||
$args = array(
|
||||
'order_id' => $post->ID,
|
||||
);
|
||||
|
||||
$notes = wc_get_order_notes( $args );
|
||||
|
||||
include __DIR__ . '/views/html-order-notes.php';
|
||||
?>
|
||||
<div class="add_note">
|
||||
<p>
|
||||
<label for="add_order_note"><?php esc_html_e( 'Add note', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'Add a note for your reference, or add a customer note (the user will be notified).', 'woocommerce' ) ); ?></label>
|
||||
<textarea type="text" name="order_note" id="add_order_note" class="input-text" cols="20" rows="5"></textarea>
|
||||
</p>
|
||||
<p>
|
||||
<label for="order_note_type" class="screen-reader-text"><?php esc_html_e( 'Note type', 'woocommerce' ); ?></label>
|
||||
<select name="order_note_type" id="order_note_type">
|
||||
<option value=""><?php esc_html_e( 'Private note', 'woocommerce' ); ?></option>
|
||||
<option value="customer"><?php esc_html_e( 'Note to customer', 'woocommerce' ); ?></option>
|
||||
</select>
|
||||
<button type="button" class="add_note button"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
568
includes/admin/meta-boxes/class-wc-meta-box-product-data.php
Normal file
568
includes/admin/meta-boxes/class-wc-meta-box-product-data.php
Normal file
@ -0,0 +1,568 @@
|
||||
<?php
|
||||
/**
|
||||
* Product Data
|
||||
*
|
||||
* Displays the product data box, tabbed, with several panels covering price, stock etc.
|
||||
*
|
||||
* @package WooCommerce\Admin\Meta Boxes
|
||||
* @version 3.0.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Meta_Box_Product_Data Class.
|
||||
*/
|
||||
class WC_Meta_Box_Product_Data {
|
||||
|
||||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
global $thepostid, $product_object;
|
||||
|
||||
$thepostid = $post->ID;
|
||||
$product_object = $thepostid ? wc_get_product( $thepostid ) : new WC_Product();
|
||||
|
||||
wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );
|
||||
|
||||
include __DIR__ . '/views/html-product-data-panel.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Show tab content/settings.
|
||||
*/
|
||||
private static function output_tabs() {
|
||||
global $post, $thepostid, $product_object;
|
||||
|
||||
include __DIR__ . '/views/html-product-data-general.php';
|
||||
include __DIR__ . '/views/html-product-data-inventory.php';
|
||||
include __DIR__ . '/views/html-product-data-shipping.php';
|
||||
include __DIR__ . '/views/html-product-data-linked-products.php';
|
||||
include __DIR__ . '/views/html-product-data-attributes.php';
|
||||
include __DIR__ . '/views/html-product-data-advanced.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of product type options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function get_product_type_options() {
|
||||
return apply_filters(
|
||||
'product_type_options',
|
||||
array(
|
||||
'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',
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return array of tabs to show.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function get_product_data_tabs() {
|
||||
$tabs = apply_filters(
|
||||
'woocommerce_product_data_tabs',
|
||||
array(
|
||||
'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( 'show_if_variable' ),
|
||||
'priority' => 60,
|
||||
),
|
||||
'advanced' => array(
|
||||
'label' => __( 'Advanced', 'woocommerce' ),
|
||||
'target' => 'advanced_product_data',
|
||||
'class' => array(),
|
||||
'priority' => 70,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// Sort tabs based on priority.
|
||||
uasort( $tabs, array( __CLASS__, 'product_data_tabs_sort' ) );
|
||||
|
||||
return $tabs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to sort product data tabs on priority.
|
||||
*
|
||||
* @since 3.1.0
|
||||
* @param int $a First item.
|
||||
* @param int $b Second item.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function product_data_tabs_sort( $a, $b ) {
|
||||
if ( ! isset( $a['priority'], $b['priority'] ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( $a['priority'] === $b['priority'] ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $a['priority'] < $b['priority'] ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter callback for finding variation attributes.
|
||||
*
|
||||
* @param WC_Product_Attribute $attribute Product attribute.
|
||||
* @return bool
|
||||
*/
|
||||
private static function filter_variation_attributes( $attribute ) {
|
||||
return true === $attribute->get_variation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show options for the variable product type.
|
||||
*/
|
||||
public static function output_variations() {
|
||||
global $post, $wpdb, $product_object;
|
||||
|
||||
$variation_attributes = array_filter( $product_object->get_attributes(), array( __CLASS__, 'filter_variation_attributes' ) );
|
||||
$default_attributes = $product_object->get_default_attributes();
|
||||
$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 ) );
|
||||
$variations_per_page = absint( apply_filters( 'woocommerce_admin_meta_boxes_variations_per_page', 15 ) );
|
||||
$variations_total_pages = ceil( $variations_count / $variations_per_page );
|
||||
|
||||
include __DIR__ . '/views/html-product-data-variations.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare downloads for save.
|
||||
*
|
||||
* @param array $file_names File names.
|
||||
* @param array $file_urls File urls.
|
||||
* @param array $file_hashes File hashes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function prepare_downloads( $file_names, $file_urls, $file_hashes ) {
|
||||
$downloads = array();
|
||||
|
||||
if ( ! empty( $file_urls ) ) {
|
||||
$file_url_size = count( $file_urls );
|
||||
|
||||
for ( $i = 0; $i < $file_url_size; $i ++ ) {
|
||||
if ( ! empty( $file_urls[ $i ] ) ) {
|
||||
$downloads[] = array(
|
||||
'name' => wc_clean( $file_names[ $i ] ),
|
||||
'file' => wp_unslash( trim( $file_urls[ $i ] ) ),
|
||||
'download_id' => wc_clean( $file_hashes[ $i ] ),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $downloads;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare children for save.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function prepare_children() {
|
||||
return isset( $_POST['grouped_products'] ) ? array_filter( array_map( 'intval', (array) $_POST['grouped_products'] ) ) : array(); // phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare attributes for save.
|
||||
*
|
||||
* @param array $data Attribute data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function prepare_attributes( $data = false ) {
|
||||
$attributes = array();
|
||||
|
||||
if ( ! $data ) {
|
||||
$data = stripslashes_deep( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
}
|
||||
|
||||
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'];
|
||||
$attribute_names_max_key = max( array_keys( $attribute_names ) );
|
||||
|
||||
for ( $i = 0; $i <= $attribute_names_max_key; $i++ ) {
|
||||
if ( empty( $attribute_names[ $i ] ) || ! isset( $attribute_values[ $i ] ) ) {
|
||||
continue;
|
||||
}
|
||||
$attribute_id = 0;
|
||||
$attribute_name = wc_clean( esc_html( $attribute_names[ $i ] ) );
|
||||
|
||||
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 ] : '';
|
||||
|
||||
if ( is_array( $options ) ) {
|
||||
// Term ids sent as array.
|
||||
$options = wp_parse_id_list( $options );
|
||||
} else {
|
||||
// Terms or text sent in textarea.
|
||||
$options = 0 < $attribute_id ? wc_sanitize_textarea( esc_html( wc_sanitize_term_text_based( $options ) ) ) : wc_sanitize_textarea( esc_html( $options ) );
|
||||
$options = wc_get_text_attributes( $options );
|
||||
}
|
||||
|
||||
if ( empty( $options ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$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 ] ) );
|
||||
$attributes[] = apply_filters( 'woocommerce_admin_meta_boxes_prepare_attribute', $attribute, $data, $i );
|
||||
}
|
||||
}
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare attributes for a specific variation or defaults.
|
||||
*
|
||||
* @param array $all_attributes List of attribute keys.
|
||||
* @param string $key_prefix Attribute key prefix.
|
||||
* @param int $index Attribute array index.
|
||||
* @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 ) ) {
|
||||
$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
|
||||
} else {
|
||||
$value = isset( $_POST[ $key_prefix . $attribute_key ] ) ? wp_unslash( $_POST[ $key_prefix . $attribute_key ] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
}
|
||||
|
||||
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.
|
||||
}
|
||||
|
||||
$attributes[ $attribute_key ] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta box data.
|
||||
*
|
||||
* @param int $post_id WP post id.
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public static function save( $post_id, $post ) {
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
||||
// Process product type first so we have the correct class to run setters.
|
||||
$product_type = empty( $_POST['product-type'] ) ? WC_Product_Factory::get_product_type( $post_id ) : sanitize_title( wp_unslash( $_POST['product-type'] ) );
|
||||
$classname = WC_Product_Factory::get_product_classname( $post_id, $product_type ? $product_type : 'simple' );
|
||||
$product = new $classname( $post_id );
|
||||
$attributes = self::prepare_attributes();
|
||||
$stock = null;
|
||||
|
||||
// Handle stock changes.
|
||||
if ( isset( $_POST['_stock'] ) ) {
|
||||
if ( isset( $_POST['_original_stock'] ) && wc_stock_amount( $product->get_stock_quantity( 'edit' ) ) !== wc_stock_amount( wp_unslash( $_POST['_original_stock'] ) ) ) {
|
||||
/* 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' ) ) );
|
||||
} else {
|
||||
$stock = wc_stock_amount( wp_unslash( $_POST['_stock'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
|
||||
}
|
||||
}
|
||||
|
||||
$errors = $product->set_props(
|
||||
array(
|
||||
'sku' => isset( $_POST['_sku'] ) ? wc_clean( wp_unslash( $_POST['_sku'] ) ) : null,
|
||||
'purchase_note' => isset( $_POST['_purchase_note'] ) ? wp_kses_post( wp_unslash( $_POST['_purchase_note'] ) ) : '',
|
||||
'downloadable' => isset( $_POST['_downloadable'] ),
|
||||
'virtual' => isset( $_POST['_virtual'] ),
|
||||
'featured' => isset( $_POST['_featured'] ),
|
||||
'catalog_visibility' => isset( $_POST['_visibility'] ) ? wc_clean( wp_unslash( $_POST['_visibility'] ) ) : null,
|
||||
'tax_status' => isset( $_POST['_tax_status'] ) ? wc_clean( wp_unslash( $_POST['_tax_status'] ) ) : null,
|
||||
'tax_class' => isset( $_POST['_tax_class'] ) ? sanitize_title( wp_unslash( $_POST['_tax_class'] ) ) : null,
|
||||
'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,
|
||||
'sold_individually' => ! empty( $_POST['_sold_individually'] ),
|
||||
'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(),
|
||||
'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,
|
||||
'date_on_sale_from' => $date_on_sale_from,
|
||||
'date_on_sale_to' => $date_on_sale_to,
|
||||
'manage_stock' => ! empty( $_POST['_manage_stock'] ),
|
||||
'backorders' => isset( $_POST['_backorders'] ) ? wc_clean( wp_unslash( $_POST['_backorders'] ) ) : null,
|
||||
'stock_status' => isset( $_POST['_stock_status'] ) ? wc_clean( wp_unslash( $_POST['_stock_status'] ) ) : null,
|
||||
'stock_quantity' => $stock,
|
||||
'low_stock_amount' => isset( $_POST['_low_stock_amount'] ) && '' !== $_POST['_low_stock_amount'] ? wc_stock_amount( wp_unslash( $_POST['_low_stock_amount'] ) ) : '',
|
||||
'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.
|
||||
'downloads' => self::prepare_downloads(
|
||||
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
|
||||
),
|
||||
'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'] ) ) : '',
|
||||
'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_' ),
|
||||
)
|
||||
);
|
||||
|
||||
if ( is_wp_error( $errors ) ) {
|
||||
WC_Admin_Meta_Boxes::add_error( $errors->get_error_message() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set props before save.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
do_action( 'woocommerce_admin_process_product_object', $product );
|
||||
|
||||
$product->save();
|
||||
|
||||
if ( $product->is_type( 'variable' ) ) {
|
||||
$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 );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_process_product_meta_' . $product_type, $post_id );
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
}
|
||||
|
||||
/**
|
||||
* Save variation meta box data.
|
||||
*
|
||||
* @param int $post_id WP post id.
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public static function save_variations( $post_id, $post ) {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
||||
if ( isset( $_POST['variable_post_id'] ) ) {
|
||||
$parent = wc_get_product( $post_id );
|
||||
$parent->set_default_attributes( self::prepare_set_attributes( $parent->get_attributes(), 'default_attribute_' ) );
|
||||
$parent->save();
|
||||
|
||||
$max_loop = max( array_keys( wp_unslash( $_POST['variable_post_id'] ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$data_store = $parent->get_data_store();
|
||||
$data_store->sort_all_product_variations( $parent->get_id() );
|
||||
$new_variation_menu_order_id = ! empty( $_POST['new_variation_menu_order_id'] ) ? wc_clean( wp_unslash( $_POST['new_variation_menu_order_id'] ) ) : false;
|
||||
$new_variation_menu_order_value = ! empty( $_POST['new_variation_menu_order_value'] ) ? wc_clean( wp_unslash( $_POST['new_variation_menu_order_value'] ) ) : false;
|
||||
|
||||
// Only perform this operation if setting menu order via the prompt.
|
||||
if ( $new_variation_menu_order_id && $new_variation_menu_order_value ) {
|
||||
/*
|
||||
* We need to gather all the variations with menu order that is
|
||||
* equal or greater than the menu order that is newly set and
|
||||
* increment them by one so that we can correctly insert the updated
|
||||
* variation menu order.
|
||||
*/
|
||||
$wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"UPDATE {$wpdb->posts} SET menu_order = menu_order + 1 WHERE post_type = 'product_variation' AND post_parent = %d AND post_status = 'publish' AND menu_order >= %d AND ID != %d",
|
||||
$post_id,
|
||||
$new_variation_menu_order_value,
|
||||
$new_variation_menu_order_id
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
for ( $i = 0; $i <= $max_loop; $i++ ) {
|
||||
|
||||
if ( ! isset( $_POST['variable_post_id'][ $i ] ) ) {
|
||||
continue;
|
||||
}
|
||||
$variation_id = absint( $_POST['variable_post_id'][ $i ] );
|
||||
$variation = wc_get_product_object( 'variation', $variation_id );
|
||||
$stock = null;
|
||||
|
||||
// Handle stock changes.
|
||||
if ( isset( $_POST['variable_stock'], $_POST['variable_stock'][ $i ] ) ) {
|
||||
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 ] ) ) ) {
|
||||
/* 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' ) ) );
|
||||
} else {
|
||||
$stock = wc_stock_amount( wp_unslash( $_POST['variable_stock'][ $i ] ) );
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ) ); // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
|
||||
}
|
||||
}
|
||||
|
||||
$errors = $variation->set_props(
|
||||
array(
|
||||
'status' => isset( $_POST['variable_enabled'][ $i ] ) ? 'publish' : 'private',
|
||||
'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,
|
||||
'virtual' => isset( $_POST['variable_is_virtual'][ $i ] ),
|
||||
'downloadable' => isset( $_POST['variable_is_downloadable'][ $i ] ),
|
||||
'date_on_sale_from' => $date_on_sale_from,
|
||||
'date_on_sale_to' => $date_on_sale_to,
|
||||
'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.
|
||||
'downloads' => self::prepare_downloads(
|
||||
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
|
||||
),
|
||||
'manage_stock' => isset( $_POST['variable_manage_stock'][ $i ] ),
|
||||
'stock_quantity' => $stock,
|
||||
'low_stock_amount' => isset( $_POST['variable_low_stock_amount'][ $i ] ) && '' !== $_POST['variable_low_stock_amount'][ $i ] ? wc_stock_amount( wp_unslash( $_POST['variable_low_stock_amount'][ $i ] ) ) : '',
|
||||
'backorders' => isset( $_POST['variable_backorders'], $_POST['variable_backorders'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_backorders'][ $i ] ) ) : null,
|
||||
'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,
|
||||
'attributes' => self::prepare_set_attributes( $parent->get_attributes(), 'attribute_', $i ),
|
||||
'sku' => isset( $_POST['variable_sku'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_sku'][ $i ] ) ) : '',
|
||||
'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 ] ) ) : '',
|
||||
'shipping_class_id' => isset( $_POST['variable_shipping_class'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_shipping_class'][ $i ] ) ) : null,
|
||||
'tax_class' => isset( $_POST['variable_tax_class'][ $i ] ) ? wc_clean( wp_unslash( $_POST['variable_tax_class'][ $i ] ) ) : null,
|
||||
)
|
||||
);
|
||||
|
||||
if ( is_wp_error( $errors ) ) {
|
||||
WC_Admin_Meta_Boxes::add_error( $errors->get_error_message() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set variation props before save.
|
||||
*
|
||||
* @param object $variation WC_Product_Variation object.
|
||||
* @param int $i
|
||||
* @since 3.8.0
|
||||
*/
|
||||
do_action( 'woocommerce_admin_process_variation_object', $variation, $i );
|
||||
|
||||
$variation->save();
|
||||
do_action( 'woocommerce_save_product_variation', $variation_id, $i );
|
||||
}
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
}
|
||||
}
|
101
includes/admin/meta-boxes/class-wc-meta-box-product-images.php
Normal file
101
includes/admin/meta-boxes/class-wc-meta-box-product-images.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
/**
|
||||
* Product Images
|
||||
*
|
||||
* Display the product images meta box.
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce\Admin\Meta Boxes
|
||||
* @version 2.1.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Meta_Box_Product_Images Class.
|
||||
*/
|
||||
class WC_Meta_Box_Product_Images {
|
||||
|
||||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
global $thepostid, $product_object;
|
||||
|
||||
$thepostid = $post->ID;
|
||||
$product_object = $thepostid ? wc_get_product( $thepostid ) : new WC_Product();
|
||||
wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );
|
||||
?>
|
||||
<div id="product_images_container">
|
||||
<ul class="product_images">
|
||||
<?php
|
||||
$product_image_gallery = $product_object->get_gallery_image_ids( 'edit' );
|
||||
|
||||
$attachments = array_filter( $product_image_gallery );
|
||||
$update_meta = false;
|
||||
$updated_gallery_ids = array();
|
||||
|
||||
if ( ! empty( $attachments ) ) {
|
||||
foreach ( $attachments as $attachment_id ) {
|
||||
$attachment = wp_get_attachment_image( $attachment_id, 'thumbnail' );
|
||||
|
||||
// if attachment is empty skip.
|
||||
if ( empty( $attachment ) ) {
|
||||
$update_meta = true;
|
||||
continue;
|
||||
}
|
||||
?>
|
||||
<li class="image" data-attachment_id="<?php echo esc_attr( $attachment_id ); ?>">
|
||||
<?php echo $attachment; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<ul class="actions">
|
||||
<li><a href="#" class="delete tips" data-tip="<?php esc_attr_e( 'Delete image', 'woocommerce' ); ?>"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a></li>
|
||||
</ul>
|
||||
<?php
|
||||
// Allow for extra info to be exposed or extra action to be executed for this attachment.
|
||||
do_action( 'woocommerce_admin_after_product_gallery_item', $thepostid, $attachment_id );
|
||||
?>
|
||||
</li>
|
||||
<?php
|
||||
|
||||
// rebuild ids to be saved.
|
||||
$updated_gallery_ids[] = $attachment_id;
|
||||
}
|
||||
|
||||
// need to update product meta to set new gallery ids
|
||||
if ( $update_meta ) {
|
||||
update_post_meta( $post->ID, '_product_image_gallery', implode( ',', $updated_gallery_ids ) );
|
||||
}
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
|
||||
<input type="hidden" id="product_image_gallery" name="product_image_gallery" value="<?php echo esc_attr( implode( ',', $updated_gallery_ids ) ); ?>" />
|
||||
|
||||
</div>
|
||||
<p class="add_product_images hide-if-no-js">
|
||||
<a href="#" data-choose="<?php esc_attr_e( 'Add images to product gallery', 'woocommerce' ); ?>" data-update="<?php esc_attr_e( 'Add to gallery', 'woocommerce' ); ?>" data-delete="<?php esc_attr_e( 'Delete image', 'woocommerce' ); ?>" data-text="<?php esc_attr_e( 'Delete', 'woocommerce' ); ?>"><?php esc_html_e( 'Add product gallery images', 'woocommerce' ); ?></a>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta box data.
|
||||
*
|
||||
* @param int $post_id
|
||||
* @param WP_Post $post
|
||||
*/
|
||||
public static function save( $post_id, $post ) {
|
||||
$product_type = empty( $_POST['product-type'] ) ? WC_Product_Factory::get_product_type( $post_id ) : sanitize_title( stripslashes( $_POST['product-type'] ) );
|
||||
$classname = WC_Product_Factory::get_product_classname( $post_id, $product_type ? $product_type : 'simple' );
|
||||
$product = new $classname( $post_id );
|
||||
$attachment_ids = isset( $_POST['product_image_gallery'] ) ? array_filter( explode( ',', wc_clean( $_POST['product_image_gallery'] ) ) ) : array();
|
||||
|
||||
$product->set_gallery_image_ids( $attachment_ids );
|
||||
$product->save();
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Product Reviews
|
||||
*
|
||||
* Functions for displaying product reviews data meta box.
|
||||
*
|
||||
* @package WooCommerce\Admin\Meta Boxes
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* WC_Meta_Box_Product_Reviews
|
||||
*/
|
||||
class WC_Meta_Box_Product_Reviews {
|
||||
|
||||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param object $comment Comment being shown.
|
||||
*/
|
||||
public static function output( $comment ) {
|
||||
wp_nonce_field( 'woocommerce_save_data', 'woocommerce_meta_nonce' );
|
||||
|
||||
$current = get_comment_meta( $comment->comment_ID, 'rating', true );
|
||||
?>
|
||||
<select name="rating" id="rating">
|
||||
<?php
|
||||
for ( $rating = 1; $rating <= 5; $rating ++ ) {
|
||||
printf( '<option value="%1$s"%2$s>%1$s</option>', $rating, selected( $current, $rating, false ) ); // WPCS: XSS ok.
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Save meta box data
|
||||
*
|
||||
* @param mixed $data Data to save.
|
||||
* @return mixed
|
||||
*/
|
||||
public static function save( $data ) {
|
||||
// Not allowed, return regular value without updating meta.
|
||||
if ( ! isset( $_POST['woocommerce_meta_nonce'], $_POST['rating'] ) || ! wp_verify_nonce( wp_unslash( $_POST['woocommerce_meta_nonce'] ), 'woocommerce_save_data' ) ) { // WPCS: input var ok, sanitization ok.
|
||||
return $data;
|
||||
}
|
||||
|
||||
if ( $_POST['rating'] > 5 || $_POST['rating'] < 0 ) { // WPCS: input var ok.
|
||||
return $data;
|
||||
}
|
||||
|
||||
$comment_id = $data['comment_ID'];
|
||||
|
||||
update_comment_meta( $comment_id, 'rating', intval( wp_unslash( $_POST['rating'] ) ) ); // WPCS: input var ok.
|
||||
|
||||
// Return regular value after updating.
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Product Short Description
|
||||
*
|
||||
* Replaces the standard excerpt box.
|
||||
*
|
||||
* @package WooCommerce\Admin\Meta Boxes
|
||||
* @version 2.1.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* WC_Meta_Box_Product_Short_Description Class.
|
||||
*/
|
||||
class WC_Meta_Box_Product_Short_Description {
|
||||
|
||||
/**
|
||||
* Output the metabox.
|
||||
*
|
||||
* @param WP_Post $post Post object.
|
||||
*/
|
||||
public static function output( $post ) {
|
||||
|
||||
$settings = array(
|
||||
'textarea_name' => 'excerpt',
|
||||
'quicktags' => array( 'buttons' => 'em,strong,link' ),
|
||||
'tinymce' => array(
|
||||
'theme_advanced_buttons1' => 'bold,italic,strikethrough,separator,bullist,numlist,separator,blockquote,separator,justifyleft,justifycenter,justifyright,separator,link,unlink,separator,undo,redo,separator',
|
||||
'theme_advanced_buttons2' => '',
|
||||
),
|
||||
'editor_css' => '<style>#wp-excerpt-editor-container .wp-editor-area{height:175px; width:100%;}</style>',
|
||||
);
|
||||
|
||||
wp_editor( htmlspecialchars_decode( $post->post_excerpt, ENT_QUOTES ), 'excerpt', apply_filters( 'woocommerce_product_short_description_editor_settings', $settings ) );
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<div class="wc-metabox closed">
|
||||
<h3 class="fixed">
|
||||
<button type="button" data-permission_id="<?php echo esc_attr( $download->get_id() ); ?>" rel="<?php echo esc_attr( $download->get_product_id() ) . ',' . esc_attr( $download->get_download_id() ); ?>" class="revoke_access button"><?php esc_html_e( 'Revoke access', 'woocommerce' ); ?></button>
|
||||
<div class="handlediv" aria-label="<?php esc_attr_e( 'Click to toggle', 'woocommerce' ); ?>"></div>
|
||||
<strong>
|
||||
<?php
|
||||
printf(
|
||||
'#%s — %s — %s: %s — ',
|
||||
esc_html( $product->get_id() ),
|
||||
esc_html( apply_filters( 'woocommerce_admin_download_permissions_title', $product->get_name(), $download->get_product_id(), $download->get_order_id(), $download->get_order_key(), $download->get_download_id() ) ),
|
||||
esc_html( $file_count ),
|
||||
esc_html( wc_get_filename_from_url( $product->get_file_download_path( $download->get_download_id() ) ) )
|
||||
);
|
||||
printf( _n( 'Downloaded %s time', 'Downloaded %s times', $download->get_download_count(), 'woocommerce' ), esc_html( $download->get_download_count() ) )
|
||||
?>
|
||||
</strong>
|
||||
</h3>
|
||||
<table cellpadding="0" cellspacing="0" class="wc-metabox-content">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<label><?php esc_html_e( 'Downloads remaining', 'woocommerce' ); ?></label>
|
||||
<input type="hidden" name="permission_id[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $download->get_id() ); ?>" />
|
||||
<input type="number" step="1" min="0" class="short" name="downloads_remaining[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $download->get_downloads_remaining() ); ?>" placeholder="<?php esc_attr_e( 'Unlimited', 'woocommerce' ); ?>" />
|
||||
</td>
|
||||
<td>
|
||||
<label><?php esc_html_e( 'Access expires', 'woocommerce' ); ?></label>
|
||||
<input type="text" class="short date-picker" name="access_expires[<?php echo esc_attr( $loop ); ?>]" value="<?php echo ! is_null( $download->get_access_expires() ) ? esc_attr( date_i18n( 'Y-m-d', $download->get_access_expires()->getTimestamp() ) ) : ''; ?>" maxlength="10" placeholder="<?php esc_attr_e( 'Never', 'woocommerce' ); ?>" pattern="<?php echo esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ); ?>" />
|
||||
</td>
|
||||
<td>
|
||||
<label><?php esc_html_e( 'Customer download link', 'woocommerce' ); ?></label>
|
||||
<?php
|
||||
$download_link = add_query_arg(
|
||||
array(
|
||||
'download_file' => $download->get_product_id(),
|
||||
'order' => $download->get_order_key(),
|
||||
'email' => urlencode( $download->get_user_email() ),
|
||||
'key' => $download->get_download_id(),
|
||||
),
|
||||
trailingslashit( home_url() )
|
||||
);
|
||||
?>
|
||||
<a id="copy-download-link" class="button" href="<?php echo esc_url( $download_link ); ?>" data-tip="<?php esc_attr_e( 'Copied!', 'woocommerce' ); ?>" data-tip-failed="<?php esc_attr_e( 'Copying to clipboard failed. You should be able to right-click the button and copy.', 'woocommerce' ); ?>"><?php esc_html_e( 'Copy link', 'woocommerce' ); ?></a>
|
||||
</td>
|
||||
<td>
|
||||
<label><?php esc_html_e( 'Customer download log', 'woocommerce' ); ?></label>
|
||||
<?php
|
||||
$report_url = add_query_arg(
|
||||
'permission_id',
|
||||
rawurlencode( $download->get_id() ),
|
||||
admin_url( 'admin.php?page=wc-reports&tab=orders&report=downloads' )
|
||||
);
|
||||
echo '<a class="button" href="' . esc_url( $report_url ) . '">';
|
||||
esc_html_e( 'View report', 'woocommerce' );
|
||||
echo '</a>';
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
85
includes/admin/meta-boxes/views/html-order-fee.php
Normal file
85
includes/admin/meta-boxes/views/html-order-fee.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* Shows an order item fee
|
||||
*
|
||||
* @var object $item The item being displayed
|
||||
* @var int $item_id The id of the item being displayed
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<tr class="fee <?php echo ( ! empty( $class ) ) ? esc_attr( $class ) : ''; ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
|
||||
<td class="thumb"><div></div></td>
|
||||
|
||||
<td class="name">
|
||||
<div class="view">
|
||||
<?php echo esc_html( $item->get_name() ? $item->get_name() : __( 'Fee', 'woocommerce' ) ); ?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<input type="text" placeholder="<?php esc_attr_e( 'Fee name', 'woocommerce' ); ?>" name="order_item_name[<?php echo absint( $item_id ); ?>]" value="<?php echo ( $item->get_name() ) ? esc_attr( $item->get_name() ) : ''; ?>" />
|
||||
<input type="hidden" class="order_item_id" name="order_item_id[]" value="<?php echo esc_attr( $item_id ); ?>" />
|
||||
<input type="hidden" name="order_item_tax_class[<?php echo absint( $item_id ); ?>]" value="<?php echo esc_attr( $item->get_tax_class() ); ?>" />
|
||||
</div>
|
||||
<?php do_action( 'woocommerce_after_order_fee_item_name', $item_id, $item, null ); ?>
|
||||
</td>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_item_values', null, $item, absint( $item_id ) ); ?>
|
||||
|
||||
<td class="item_cost" width="1%"> </td>
|
||||
<td class="quantity" width="1%"> </td>
|
||||
|
||||
<td class="line_cost" width="1%">
|
||||
<div class="view">
|
||||
<?php
|
||||
echo wc_price( $item->get_total(), array( 'currency' => $order->get_currency() ) );
|
||||
|
||||
if ( $refunded = $order->get_total_refunded_for_item( $item_id, 'fee' ) ) {
|
||||
echo '<small class="refunded">-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<input type="text" name="line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" />
|
||||
</div>
|
||||
<div class="refund" style="display: none;">
|
||||
<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_total wc_input_price" />
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<?php
|
||||
if ( ( $tax_data = $item->get_taxes() ) && wc_tax_enabled() ) {
|
||||
foreach ( $order_taxes as $tax_item ) {
|
||||
$tax_item_id = $tax_item->get_rate_id();
|
||||
$tax_item_total = isset( $tax_data['total'][ $tax_item_id ] ) ? $tax_data['total'][ $tax_item_id ] : '';
|
||||
?>
|
||||
<td class="line_tax" width="1%">
|
||||
<div class="view">
|
||||
<?php
|
||||
echo ( '' !== $tax_item_total ) ? wc_price( wc_round_tax_total( $tax_item_total ), array( 'currency' => $order->get_currency() ) ) : '–';
|
||||
|
||||
if ( $refunded = $order->get_tax_refunded_for_item( $item_id, $tax_item_id, 'fee' ) ) {
|
||||
echo '<small class="refunded">-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<input type="text" name="line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo ( isset( $tax_item_total ) ) ? esc_attr( wc_format_localized_price( $tax_item_total ) ) : ''; ?>" class="line_tax wc_input_price" />
|
||||
</div>
|
||||
<div class="refund" style="display: none;">
|
||||
<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
|
||||
</div>
|
||||
</td>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
<td class="wc-order-edit-line-item">
|
||||
<?php if ( $order->is_editable() ) : ?>
|
||||
<div class="wc-order-edit-line-item-actions">
|
||||
<a class="edit-order-item" href="#"></a><a class="delete-order-item" href="#"></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
66
includes/admin/meta-boxes/views/html-order-item-meta.php
Normal file
66
includes/admin/meta-boxes/views/html-order-item-meta.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$hidden_order_itemmeta = apply_filters(
|
||||
'woocommerce_hidden_order_itemmeta',
|
||||
array(
|
||||
'_qty',
|
||||
'_tax_class',
|
||||
'_product_id',
|
||||
'_variation_id',
|
||||
'_line_subtotal',
|
||||
'_line_subtotal_tax',
|
||||
'_line_total',
|
||||
'_line_tax',
|
||||
'method_id',
|
||||
'cost',
|
||||
'_reduced_stock',
|
||||
'_restock_refunded_items',
|
||||
)
|
||||
);
|
||||
?><div class="view">
|
||||
<?php if ( $meta_data = $item->get_formatted_meta_data( '' ) ) : ?>
|
||||
<table cellspacing="0" class="display_meta">
|
||||
<?php
|
||||
foreach ( $meta_data as $meta_id => $meta ) :
|
||||
if ( in_array( $meta->key, $hidden_order_itemmeta, true ) ) {
|
||||
continue;
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<th><?php echo wp_kses_post( $meta->display_key ); ?>:</th>
|
||||
<td><?php echo wp_kses_post( force_balance_tags( $meta->display_value ) ); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<table class="meta" cellspacing="0">
|
||||
<tbody class="meta_items">
|
||||
<?php if ( $meta_data = $item->get_formatted_meta_data( '' ) ) : ?>
|
||||
<?php
|
||||
foreach ( $meta_data as $meta_id => $meta ) :
|
||||
if ( in_array( $meta->key, $hidden_order_itemmeta, true ) ) {
|
||||
continue;
|
||||
}
|
||||
?>
|
||||
<tr data-meta_id="<?php echo esc_attr( $meta_id ); ?>">
|
||||
<td>
|
||||
<input type="text" maxlength="255" placeholder="<?php esc_attr_e( 'Name (required)', 'woocommerce' ); ?>" name="meta_key[<?php echo esc_attr( $item_id ); ?>][<?php echo esc_attr( $meta_id ); ?>]" value="<?php echo esc_attr( $meta->key ); ?>" />
|
||||
<textarea placeholder="<?php esc_attr_e( 'Value (required)', 'woocommerce' ); ?>" name="meta_value[<?php echo esc_attr( $item_id ); ?>][<?php echo esc_attr( $meta_id ); ?>]"><?php echo esc_textarea( rawurldecode( $meta->value ) ); ?></textarea>
|
||||
</td>
|
||||
<td width="1%"><button class="remove_order_item_meta button">×</button></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="4"><button class="add_order_item_meta button"><?php esc_html_e( 'Add meta', 'woocommerce' ); ?></button></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
193
includes/admin/meta-boxes/views/html-order-item.php
Normal file
193
includes/admin/meta-boxes/views/html-order-item.php
Normal file
@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/**
|
||||
* Shows an order item
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
* @var object $item The item being displayed
|
||||
* @var int $item_id The id of the item being displayed
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
$product = $item->get_product();
|
||||
$product_link = $product ? admin_url( 'post.php?post=' . $item->get_product_id() . '&action=edit' ) : '';
|
||||
$thumbnail = $product ? apply_filters( 'woocommerce_admin_order_item_thumbnail', $product->get_image( 'thumbnail', array( 'title' => '' ), false ), $item_id, $item ) : '';
|
||||
$row_class = apply_filters( 'woocommerce_admin_html_order_item_class', ! empty( $class ) ? $class : '', $item, $order );
|
||||
?>
|
||||
<tr class="item <?php echo esc_attr( $row_class ); ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
|
||||
<td class="thumb">
|
||||
<?php echo '<div class="wc-order-item-thumbnail">' . wp_kses_post( $thumbnail ) . '</div>'; ?>
|
||||
</td>
|
||||
<td class="name" data-sort-value="<?php echo esc_attr( $item->get_name() ); ?>">
|
||||
<?php
|
||||
echo $product_link ? '<a href="' . esc_url( $product_link ) . '" class="wc-order-item-name">' . wp_kses_post( $item->get_name() ) . '</a>' : '<div class="wc-order-item-name">' . wp_kses_post( $item->get_name() ) . '</div>';
|
||||
|
||||
if ( $product && $product->get_sku() ) {
|
||||
echo '<div class="wc-order-item-sku"><strong>' . esc_html__( 'SKU:', 'woocommerce' ) . '</strong> ' . esc_html( $product->get_sku() ) . '</div>';
|
||||
}
|
||||
|
||||
if ( $item->get_variation_id() ) {
|
||||
echo '<div class="wc-order-item-variation"><strong>' . esc_html__( 'Variation ID:', 'woocommerce' ) . '</strong> ';
|
||||
if ( 'product_variation' === get_post_type( $item->get_variation_id() ) ) {
|
||||
echo esc_html( $item->get_variation_id() );
|
||||
} else {
|
||||
/* translators: %s: variation id */
|
||||
printf( esc_html__( '%s (No longer exists)', 'woocommerce' ), esc_html( $item->get_variation_id() ) );
|
||||
}
|
||||
echo '</div>';
|
||||
}
|
||||
?>
|
||||
<input type="hidden" class="order_item_id" name="order_item_id[]" value="<?php echo esc_attr( $item_id ); ?>" />
|
||||
<input type="hidden" name="order_item_tax_class[<?php echo absint( $item_id ); ?>]" value="<?php echo esc_attr( $item->get_tax_class() ); ?>" />
|
||||
|
||||
<?php do_action( 'woocommerce_before_order_itemmeta', $item_id, $item, $product ); ?>
|
||||
<?php require __DIR__ . '/html-order-item-meta.php'; ?>
|
||||
<?php do_action( 'woocommerce_after_order_itemmeta', $item_id, $item, $product ); ?>
|
||||
</td>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_item_values', $product, $item, absint( $item_id ) ); ?>
|
||||
|
||||
<td class="item_cost" width="1%" data-sort-value="<?php echo esc_attr( $order->get_item_subtotal( $item, false, true ) ); ?>">
|
||||
<div class="view">
|
||||
<?php
|
||||
echo wc_price( $order->get_item_subtotal( $item, false, true ), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
<td class="quantity" width="1%">
|
||||
<div class="view">
|
||||
<?php
|
||||
echo '<small class="times">×</small> ' . esc_html( $item->get_quantity() );
|
||||
|
||||
$refunded_qty = $order->get_qty_refunded_for_item( $item_id );
|
||||
|
||||
if ( $refunded_qty ) {
|
||||
echo '<small class="refunded">-' . esc_html( $refunded_qty * -1 ) . '</small>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
$step = apply_filters( 'woocommerce_quantity_input_step', '1', $product );
|
||||
|
||||
/**
|
||||
* Filter to change the product quantity stepping in the order editor of the admin area.
|
||||
*
|
||||
* @since 5.8.0
|
||||
* @param string $step The current step amount to be used in the quantity editor.
|
||||
* @param WC_Product $product The product that is being edited.
|
||||
* @param string $context The context in which the quantity editor is shown, 'edit' or 'refund'.
|
||||
*/
|
||||
$step_edit = apply_filters( 'woocommerce_quantity_input_step_admin', $step, $product, 'edit' );
|
||||
$step_refund = apply_filters( 'woocommerce_quantity_input_step_admin', $step, $product, 'refund' );
|
||||
|
||||
/**
|
||||
* Filter to change the product quantity minimum in the order editor of the admin area.
|
||||
*
|
||||
* @since 5.8.0
|
||||
* @param string $step The current minimum amount to be used in the quantity editor.
|
||||
* @param WC_Product $product The product that is being edited.
|
||||
* @param string $context The context in which the quantity editor is shown, 'edit' or 'refund'.
|
||||
*/
|
||||
$min_edit = apply_filters( 'woocommerce_quantity_input_min_admin', '0', $product, 'edit' );
|
||||
$min_refund = apply_filters( 'woocommerce_quantity_input_min_admin', '0', $product, 'refund' );
|
||||
?>
|
||||
<div class="edit" style="display: none;">
|
||||
<input type="number" step="<?php echo esc_attr( $step_edit ); ?>" min="<?php echo esc_attr( $min_edit ); ?>" autocomplete="off" name="order_item_qty[<?php echo absint( $item_id ); ?>]" placeholder="0" value="<?php echo esc_attr( $item->get_quantity() ); ?>" data-qty="<?php echo esc_attr( $item->get_quantity() ); ?>" size="4" class="quantity" />
|
||||
</div>
|
||||
<div class="refund" style="display: none;">
|
||||
<input type="number" step="<?php echo esc_attr( $step_refund ); ?>" min="<?php echo esc_attr( $min_refund ); ?>" max="<?php echo absint( $item->get_quantity() ); ?>" autocomplete="off" name="refund_order_item_qty[<?php echo absint( $item_id ); ?>]" placeholder="0" size="4" class="refund_order_item_qty" />
|
||||
</div>
|
||||
</td>
|
||||
<td class="line_cost" width="1%" data-sort-value="<?php echo esc_attr( $item->get_total() ); ?>">
|
||||
<div class="view">
|
||||
<?php
|
||||
echo wc_price( $item->get_total(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
|
||||
if ( $item->get_subtotal() !== $item->get_total() ) {
|
||||
/* translators: %s: discount amount */
|
||||
echo '<span class="wc-order-item-discount">' . sprintf( esc_html__( '%s discount', 'woocommerce' ), wc_price( wc_format_decimal( $item->get_subtotal() - $item->get_total(), '' ), array( 'currency' => $order->get_currency() ) ) ) . '</span>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
$refunded = $order->get_total_refunded_for_item( $item_id );
|
||||
|
||||
if ( $refunded ) {
|
||||
echo '<small class="refunded">-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<div class="split-input">
|
||||
<div class="input">
|
||||
<label><?php esc_attr_e( 'Before discount', 'woocommerce' ); ?></label>
|
||||
<input type="text" name="line_subtotal[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_subtotal() ) ); ?>" class="line_subtotal wc_input_price" data-subtotal="<?php echo esc_attr( wc_format_localized_price( $item->get_subtotal() ) ); ?>" />
|
||||
</div>
|
||||
<div class="input">
|
||||
<label><?php esc_attr_e( 'Total', 'woocommerce' ); ?></label>
|
||||
<input type="text" name="line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" data-tip="<?php esc_attr_e( 'After pre-tax discounts.', 'woocommerce' ); ?>" data-total="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="refund" style="display: none;">
|
||||
<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_total wc_input_price" />
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<?php
|
||||
$tax_data = wc_tax_enabled() ? $item->get_taxes() : false;
|
||||
|
||||
if ( $tax_data ) {
|
||||
foreach ( $order_taxes as $tax_item ) {
|
||||
$tax_item_id = $tax_item->get_rate_id();
|
||||
$tax_item_total = isset( $tax_data['total'][ $tax_item_id ] ) ? $tax_data['total'][ $tax_item_id ] : '';
|
||||
$tax_item_subtotal = isset( $tax_data['subtotal'][ $tax_item_id ] ) ? $tax_data['subtotal'][ $tax_item_id ] : '';
|
||||
|
||||
if ( '' !== $tax_item_subtotal ) {
|
||||
$round_at_subtotal = 'yes' === get_option( 'woocommerce_tax_round_at_subtotal' );
|
||||
$tax_item_total = wc_round_tax_total( $tax_item_total, $round_at_subtotal ? wc_get_rounding_precision() : null );
|
||||
$tax_item_subtotal = wc_round_tax_total( $tax_item_subtotal, $round_at_subtotal ? wc_get_rounding_precision() : null );
|
||||
}
|
||||
?>
|
||||
<td class="line_tax" width="1%">
|
||||
<div class="view">
|
||||
<?php
|
||||
if ( '' !== $tax_item_total ) {
|
||||
echo wc_price( wc_round_tax_total( $tax_item_total ), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
} else {
|
||||
echo '–';
|
||||
}
|
||||
|
||||
$refunded = $order->get_tax_refunded_for_item( $item_id, $tax_item_id );
|
||||
|
||||
if ( $refunded ) {
|
||||
echo '<small class="refunded">-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<div class="split-input">
|
||||
<div class="input">
|
||||
<label><?php esc_attr_e( 'Before discount', 'woocommerce' ); ?></label>
|
||||
<input type="text" name="line_subtotal_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $tax_item_subtotal ) ); ?>" class="line_subtotal_tax wc_input_price" data-subtotal_tax="<?php echo esc_attr( wc_format_localized_price( $tax_item_subtotal ) ); ?>" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
|
||||
</div>
|
||||
<div class="input">
|
||||
<label><?php esc_attr_e( 'Total', 'woocommerce' ); ?></label>
|
||||
<input type="text" name="line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $tax_item_total ) ); ?>" class="line_tax wc_input_price" data-total_tax="<?php echo esc_attr( wc_format_localized_price( $tax_item_total ) ); ?>" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="refund" style="display: none;">
|
||||
<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
|
||||
</div>
|
||||
</td>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
<td class="wc-order-edit-line-item" width="1%">
|
||||
<div class="wc-order-edit-line-item-actions">
|
||||
<?php if ( $order->is_editable() ) : ?>
|
||||
<a class="edit-order-item tips" href="#" data-tip="<?php esc_attr_e( 'Edit item', 'woocommerce' ); ?>"></a><a class="delete-order-item tips" href="#" data-tip="<?php esc_attr_e( 'Delete item', 'woocommerce' ); ?>"></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
478
includes/admin/meta-boxes/views/html-order-items.php
Normal file
478
includes/admin/meta-boxes/views/html-order-items.php
Normal file
@ -0,0 +1,478 @@
|
||||
<?php
|
||||
/**
|
||||
* Order items HTML for meta box.
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$payment_gateway = wc_get_payment_gateway_by_order( $order );
|
||||
$line_items = $order->get_items( apply_filters( 'woocommerce_admin_order_item_types', 'line_item' ) );
|
||||
$discounts = $order->get_items( 'discount' );
|
||||
$line_items_fee = $order->get_items( 'fee' );
|
||||
$line_items_shipping = $order->get_items( 'shipping' );
|
||||
|
||||
if ( wc_tax_enabled() ) {
|
||||
$order_taxes = $order->get_taxes();
|
||||
$tax_classes = WC_Tax::get_tax_classes();
|
||||
$classes_options = wc_get_product_tax_class_options();
|
||||
$show_tax_columns = count( $order_taxes ) === 1;
|
||||
}
|
||||
?>
|
||||
<div class="woocommerce_order_items_wrapper wc-order-items-editable">
|
||||
<table cellpadding="0" cellspacing="0" class="woocommerce_order_items">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="item sortable" colspan="2" data-sort="string-ins"><?php esc_html_e( 'Item', 'woocommerce' ); ?></th>
|
||||
<?php do_action( 'woocommerce_admin_order_item_headers', $order ); ?>
|
||||
<th class="item_cost sortable" data-sort="float"><?php esc_html_e( 'Cost', 'woocommerce' ); ?></th>
|
||||
<th class="quantity sortable" data-sort="int"><?php esc_html_e( 'Qty', 'woocommerce' ); ?></th>
|
||||
<th class="line_cost sortable" data-sort="float"><?php esc_html_e( 'Total', 'woocommerce' ); ?></th>
|
||||
<?php
|
||||
if ( ! empty( $order_taxes ) ) :
|
||||
foreach ( $order_taxes as $tax_id => $tax_item ) :
|
||||
$tax_class = wc_get_tax_class_by_tax_id( $tax_item['rate_id'] );
|
||||
$tax_class_name = isset( $classes_options[ $tax_class ] ) ? $classes_options[ $tax_class ] : __( 'Tax', 'woocommerce' );
|
||||
$column_label = ! empty( $tax_item['label'] ) ? $tax_item['label'] : __( 'Tax', 'woocommerce' );
|
||||
/* translators: %1$s: tax item name %2$s: tax class name */
|
||||
$column_tip = sprintf( esc_html__( '%1$s (%2$s)', 'woocommerce' ), $tax_item['name'], $tax_class_name );
|
||||
?>
|
||||
<th class="line_tax tips" data-tip="<?php echo esc_attr( $column_tip ); ?>">
|
||||
<?php echo esc_attr( $column_label ); ?>
|
||||
<input type="hidden" class="order-tax-id" name="order_taxes[<?php echo esc_attr( $tax_id ); ?>]" value="<?php echo esc_attr( $tax_item['rate_id'] ); ?>">
|
||||
<?php if ( $order->is_editable() ) : ?>
|
||||
<a class="delete-order-tax" href="#" data-rate_id="<?php echo esc_attr( $tax_id ); ?>"></a>
|
||||
<?php endif; ?>
|
||||
</th>
|
||||
<?php
|
||||
endforeach;
|
||||
endif;
|
||||
?>
|
||||
<th class="wc-order-edit-line-item" width="1%"> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="order_line_items">
|
||||
<?php
|
||||
foreach ( $line_items as $item_id => $item ) {
|
||||
do_action( 'woocommerce_before_order_item_' . $item->get_type() . '_html', $item_id, $item, $order );
|
||||
|
||||
include __DIR__ . '/html-order-item.php';
|
||||
|
||||
do_action( 'woocommerce_order_item_' . $item->get_type() . '_html', $item_id, $item, $order );
|
||||
}
|
||||
do_action( 'woocommerce_admin_order_items_after_line_items', $order->get_id() );
|
||||
?>
|
||||
</tbody>
|
||||
<tbody id="order_fee_line_items">
|
||||
<?php
|
||||
foreach ( $line_items_fee as $item_id => $item ) {
|
||||
include __DIR__ . '/html-order-fee.php';
|
||||
}
|
||||
do_action( 'woocommerce_admin_order_items_after_fees', $order->get_id() );
|
||||
?>
|
||||
</tbody>
|
||||
<tbody id="order_shipping_line_items">
|
||||
<?php
|
||||
$shipping_methods = WC()->shipping() ? WC()->shipping()->load_shipping_methods() : array();
|
||||
foreach ( $line_items_shipping as $item_id => $item ) {
|
||||
include __DIR__ . '/html-order-shipping.php';
|
||||
}
|
||||
do_action( 'woocommerce_admin_order_items_after_shipping', $order->get_id() );
|
||||
?>
|
||||
</tbody>
|
||||
<tbody id="order_refunds">
|
||||
<?php
|
||||
$refunds = $order->get_refunds();
|
||||
|
||||
if ( $refunds ) {
|
||||
foreach ( $refunds as $refund ) {
|
||||
include __DIR__ . '/html-order-refund.php';
|
||||
}
|
||||
do_action( 'woocommerce_admin_order_items_after_refunds', $order->get_id() );
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="wc-order-data-row wc-order-totals-items wc-order-items-editable">
|
||||
<?php
|
||||
$coupons = $order->get_items( 'coupon' );
|
||||
if ( $coupons ) :
|
||||
?>
|
||||
<div class="wc-used-coupons">
|
||||
<ul class="wc_coupon_list">
|
||||
<li><strong><?php esc_html_e( 'Coupon(s)', 'woocommerce' ); ?></strong></li>
|
||||
<?php
|
||||
foreach ( $coupons as $item_id => $item ) :
|
||||
$post_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish' LIMIT 1;", $item->get_code() ) ); // phpcs:disable WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
$class = $order->is_editable() ? 'code editable' : 'code';
|
||||
?>
|
||||
<li class="<?php echo esc_attr( $class ); ?>">
|
||||
<?php if ( $post_id ) : ?>
|
||||
<?php
|
||||
$post_url = apply_filters(
|
||||
'woocommerce_admin_order_item_coupon_url',
|
||||
add_query_arg(
|
||||
array(
|
||||
'post' => $post_id,
|
||||
'action' => 'edit',
|
||||
),
|
||||
admin_url( 'post.php' )
|
||||
),
|
||||
$item,
|
||||
$order
|
||||
);
|
||||
?>
|
||||
<a href="<?php echo esc_url( $post_url ); ?>" class="tips" data-tip="<?php echo esc_attr( wc_price( $item->get_discount(), array( 'currency' => $order->get_currency() ) ) ); ?>">
|
||||
<span><?php echo esc_html( $item->get_code() ); ?></span>
|
||||
</a>
|
||||
<?php else : ?>
|
||||
<span class="tips" data-tip="<?php echo esc_attr( wc_price( $item->get_discount(), array( 'currency' => $order->get_currency() ) ) ); ?>">
|
||||
<span><?php echo esc_html( $item->get_code() ); ?></span>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
<?php if ( $order->is_editable() ) : ?>
|
||||
<a class="remove-coupon" href="javascript:void(0)" aria-label="Remove" data-code="<?php echo esc_attr( $item->get_code() ); ?>"></a>
|
||||
<?php endif; ?>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<table class="wc-order-totals">
|
||||
<tr>
|
||||
<td class="label"><?php esc_html_e( 'Items Subtotal:', 'woocommerce' ); ?></td>
|
||||
<td width="1%"></td>
|
||||
<td class="total">
|
||||
<?php echo wc_price( $order->get_subtotal(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php if ( 0 < $order->get_total_discount() ) : ?>
|
||||
<tr>
|
||||
<td class="label"><?php esc_html_e( 'Coupon(s):', 'woocommerce' ); ?></td>
|
||||
<td width="1%"></td>
|
||||
<td class="total">-
|
||||
<?php echo wc_price( $order->get_total_discount(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<?php if ( 0 < $order->get_total_fees() ) : ?>
|
||||
<tr>
|
||||
<td class="label"><?php esc_html_e( 'Fees:', 'woocommerce' ); ?></td>
|
||||
<td width="1%"></td>
|
||||
<td class="total">
|
||||
<?php echo wc_price( $order->get_total_fees(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_totals_after_discount', $order->get_id() ); ?>
|
||||
|
||||
<?php if ( $order->get_shipping_methods() ) : ?>
|
||||
<tr>
|
||||
<td class="label"><?php esc_html_e( 'Shipping:', 'woocommerce' ); ?></td>
|
||||
<td width="1%"></td>
|
||||
<td class="total">
|
||||
<?php echo wc_price( $order->get_shipping_total(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_totals_after_shipping', $order->get_id() ); ?>
|
||||
|
||||
<?php if ( wc_tax_enabled() ) : ?>
|
||||
<?php foreach ( $order->get_tax_totals() as $code => $tax_total ) : ?>
|
||||
<tr>
|
||||
<td class="label"><?php echo esc_html( $tax_total->label ); ?>:</td>
|
||||
<td width="1%"></td>
|
||||
<td class="total">
|
||||
<?php
|
||||
// We use wc_round_tax_total here because tax may need to be round up or round down depending upon settings, whereas wc_price alone will always round it down.
|
||||
echo wc_price( wc_round_tax_total( $tax_total->amount ), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_totals_after_tax', $order->get_id() ); ?>
|
||||
|
||||
<tr>
|
||||
<td class="label"><?php esc_html_e( 'Order Total', 'woocommerce' ); ?>:</td>
|
||||
<td width="1%"></td>
|
||||
<td class="total">
|
||||
<?php echo wc_price( $order->get_total(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
<?php if ( in_array( $order->get_status(), array( 'processing', 'completed', 'refunded' ), true ) && ! empty( $order->get_date_paid() ) ) : ?>
|
||||
|
||||
<table class="wc-order-totals" style="border-top: 1px solid #999; margin-top:12px; padding-top:12px">
|
||||
<tr>
|
||||
<td class="<?php echo $order->get_total_refunded() ? 'label' : 'label label-highlight'; ?>"><?php esc_html_e( 'Paid', 'woocommerce' ); ?>: <br /></td>
|
||||
<td width="1%"></td>
|
||||
<td class="total">
|
||||
<?php echo wc_price( $order->get_total(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="description">
|
||||
<?php
|
||||
if ( $order->get_payment_method_title() ) {
|
||||
/* translators: 1: payment date. 2: payment method */
|
||||
echo esc_html( sprintf( __( '%1$s via %2$s', 'woocommerce' ), $order->get_date_paid()->date_i18n( get_option( 'date_format' ) ), $order->get_payment_method_title() ) );
|
||||
} else {
|
||||
echo esc_html( $order->get_date_paid()->date_i18n( get_option( 'date_format' ) ) );
|
||||
}
|
||||
?>
|
||||
</span>
|
||||
</td>
|
||||
<td colspan="2"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( $order->get_total_refunded() ) : ?>
|
||||
<table class="wc-order-totals" style="border-top: 1px solid #999; margin-top:12px; padding-top:12px">
|
||||
<tr>
|
||||
<td class="label refunded-total"><?php esc_html_e( 'Refunded', 'woocommerce' ); ?>:</td>
|
||||
<td width="1%"></td>
|
||||
<td class="total refunded-total">-<?php echo wc_price( $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
|
||||
</tr>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_totals_after_refunded', $order->get_id() ); ?>
|
||||
|
||||
<tr>
|
||||
<td class="label label-highlight"><?php esc_html_e( 'Net Payment', 'woocommerce' ); ?>:</td>
|
||||
<td width="1%"></td>
|
||||
<td class="total">
|
||||
<?php echo wc_price( $order->get_total() - $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="clear"></div>
|
||||
|
||||
<table class="wc-order-totals">
|
||||
<?php do_action( 'woocommerce_admin_order_totals_after_total', $order->get_id() ); ?>
|
||||
</table>
|
||||
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
<div class="wc-order-data-row wc-order-bulk-actions wc-order-data-row-toggle">
|
||||
<p class="add-items">
|
||||
<?php if ( $order->is_editable() ) : ?>
|
||||
<button type="button" class="button add-line-item"><?php esc_html_e( 'Add item(s)', 'woocommerce' ); ?></button>
|
||||
<?php if ( wc_coupons_enabled() ) : ?>
|
||||
<button type="button" class="button add-coupon"><?php esc_html_e( 'Apply coupon', 'woocommerce' ); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php else : ?>
|
||||
<span class="description"><?php echo wc_help_tip( __( 'To edit this order change the status back to "Pending payment"', 'woocommerce' ) ); ?> <?php esc_html_e( 'This order is no longer editable.', 'woocommerce' ); ?></span>
|
||||
<?php endif; ?>
|
||||
<?php if ( 0 < $order->get_total() - $order->get_total_refunded() || 0 < absint( $order->get_item_count() - $order->get_item_count_refunded() ) ) : ?>
|
||||
<button type="button" class="button refund-items"><?php esc_html_e( 'Refund', 'woocommerce' ); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
// Allow adding custom buttons.
|
||||
do_action( 'woocommerce_order_item_add_action_buttons', $order );
|
||||
?>
|
||||
<?php if ( $order->is_editable() ) : ?>
|
||||
<button type="button" class="button button-primary calculate-action"><?php esc_html_e( 'Recalculate', 'woocommerce' ); ?></button>
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
</div>
|
||||
<div class="wc-order-data-row wc-order-add-item wc-order-data-row-toggle" style="display:none;">
|
||||
<button type="button" class="button add-order-item"><?php esc_html_e( 'Add product(s)', 'woocommerce' ); ?></button>
|
||||
<button type="button" class="button add-order-fee"><?php esc_html_e( 'Add fee', 'woocommerce' ); ?></button>
|
||||
<button type="button" class="button add-order-shipping"><?php esc_html_e( 'Add shipping', 'woocommerce' ); ?></button>
|
||||
<?php if ( wc_tax_enabled() ) : ?>
|
||||
<button type="button" class="button add-order-tax"><?php esc_html_e( 'Add tax', 'woocommerce' ); ?></button>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
// Allow adding custom buttons.
|
||||
do_action( 'woocommerce_order_item_add_line_buttons', $order );
|
||||
?>
|
||||
<button type="button" class="button cancel-action"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>
|
||||
<button type="button" class="button button-primary save-action"><?php esc_html_e( 'Save', 'woocommerce' ); ?></button>
|
||||
</div>
|
||||
<?php if ( 0 < $order->get_total() - $order->get_total_refunded() || 0 < absint( $order->get_item_count() - $order->get_item_count_refunded() ) ) : ?>
|
||||
<div class="wc-order-data-row wc-order-refund-items wc-order-data-row-toggle" style="display: none;">
|
||||
<table class="wc-order-totals">
|
||||
<?php if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) : ?>
|
||||
<tr>
|
||||
<td class="label"><label for="restock_refunded_items"><?php esc_html_e( 'Restock refunded items', 'woocommerce' ); ?>:</label></td>
|
||||
<td class="total"><input type="checkbox" id="restock_refunded_items" name="restock_refunded_items" <?php checked( apply_filters( 'woocommerce_restock_refunded_items', true ) ); ?> /></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr>
|
||||
<td class="label"><?php esc_html_e( 'Amount already refunded', 'woocommerce' ); ?>:</td>
|
||||
<td class="total">-<?php echo wc_price( $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label"><?php esc_html_e( 'Total available to refund', 'woocommerce' ); ?>:</td>
|
||||
<td class="total"><?php echo wc_price( $order->get_total() - $order->get_total_refunded(), array( 'currency' => $order->get_currency() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label">
|
||||
<label for="refund_amount">
|
||||
<?php echo wc_help_tip( __( 'Refund the line items above. This will show the total amount to be refunded', 'woocommerce' ) ); ?>
|
||||
<?php esc_html_e( 'Refund amount', 'woocommerce' ); ?>:
|
||||
</label>
|
||||
</td>
|
||||
<td class="total">
|
||||
<input type="text" id="refund_amount" name="refund_amount" class="wc_input_price"
|
||||
<?php
|
||||
if ( wc_tax_enabled() ) {
|
||||
// If taxes are enabled, using this refund amount can cause issues due to taxes not being refunded also.
|
||||
// The refunds should be added to the line items, not the order as a whole.
|
||||
echo 'readonly';
|
||||
}
|
||||
?>
|
||||
/>
|
||||
<div class="clear"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label">
|
||||
<label for="refund_reason">
|
||||
<?php echo wc_help_tip( __( 'Note: the refund reason will be visible by the customer.', 'woocommerce' ) ); ?>
|
||||
<?php esc_html_e( 'Reason for refund (optional):', 'woocommerce' ); ?>
|
||||
</label>
|
||||
</td>
|
||||
<td class="total">
|
||||
<input type="text" id="refund_reason" name="refund_reason" />
|
||||
<div class="clear"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="clear"></div>
|
||||
<div class="refund-actions">
|
||||
<?php
|
||||
$refund_amount = '<span class="wc-order-refund-amount">' . wc_price( 0, array( 'currency' => $order->get_currency() ) ) . '</span>';
|
||||
$gateway_name = false !== $payment_gateway ? ( ! empty( $payment_gateway->method_title ) ? $payment_gateway->method_title : $payment_gateway->get_title() ) : __( 'Payment gateway', 'woocommerce' );
|
||||
|
||||
if ( false !== $payment_gateway && $payment_gateway->can_refund_order( $order ) ) {
|
||||
/* translators: refund amount, gateway name */
|
||||
echo '<button type="button" class="button button-primary do-api-refund">' . sprintf( esc_html__( 'Refund %1$s via %2$s', 'woocommerce' ), wp_kses_post( $refund_amount ), esc_html( $gateway_name ) ) . '</button>';
|
||||
}
|
||||
?>
|
||||
<?php /* translators: refund amount */ ?>
|
||||
<button type="button" class="button button-primary do-manual-refund tips" data-tip="<?php esc_attr_e( 'You will need to manually issue a refund through your payment gateway after using this.', 'woocommerce' ); ?>"><?php printf( esc_html__( 'Refund %s manually', 'woocommerce' ), wp_kses_post( $refund_amount ) ); ?></button>
|
||||
<button type="button" class="button cancel-action"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>
|
||||
<input type="hidden" id="refunded_amount" name="refunded_amount" value="<?php echo esc_attr( $order->get_total_refunded() ); ?>" />
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<script type="text/template" id="tmpl-wc-modal-add-products">
|
||||
<div class="wc-backbone-modal">
|
||||
<div class="wc-backbone-modal-content">
|
||||
<section class="wc-backbone-modal-main" role="main">
|
||||
<header class="wc-backbone-modal-header">
|
||||
<h1><?php esc_html_e( 'Add products', 'woocommerce' ); ?></h1>
|
||||
<button class="modal-close modal-close-link dashicons dashicons-no-alt">
|
||||
<span class="screen-reader-text">Close modal panel</span>
|
||||
</button>
|
||||
</header>
|
||||
<article>
|
||||
<form action="" method="post">
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php esc_html_e( 'Product', 'woocommerce' ); ?></th>
|
||||
<th><?php esc_html_e( 'Quantity', 'woocommerce' ); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php
|
||||
$row = '
|
||||
<td><select class="wc-product-search" name="item_id" data-allow_clear="true" data-display_stock="true" data-exclude_type="variable" data-placeholder="' . esc_attr__( 'Search for a product…', 'woocommerce' ) . '"></select></td>
|
||||
<td><input type="number" step="1" min="0" max="9999" autocomplete="off" name="item_qty" placeholder="1" size="4" class="quantity" /></td>';
|
||||
?>
|
||||
<tbody data-row="<?php echo esc_attr( $row ); ?>">
|
||||
<tr>
|
||||
<?php echo $row; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</article>
|
||||
<footer>
|
||||
<div class="inner">
|
||||
<button id="btn-ok" class="button button-primary button-large"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
|
||||
</div>
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wc-backbone-modal-backdrop modal-close"></div>
|
||||
</script>
|
||||
|
||||
<script type="text/template" id="tmpl-wc-modal-add-tax">
|
||||
<div class="wc-backbone-modal">
|
||||
<div class="wc-backbone-modal-content">
|
||||
<section class="wc-backbone-modal-main" role="main">
|
||||
<header class="wc-backbone-modal-header">
|
||||
<h1><?php esc_html_e( 'Add tax', 'woocommerce' ); ?></h1>
|
||||
<button class="modal-close modal-close-link dashicons dashicons-no-alt">
|
||||
<span class="screen-reader-text">Close modal panel</span>
|
||||
</button>
|
||||
</header>
|
||||
<article>
|
||||
<form action="" method="post">
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th> </th>
|
||||
<th><?php esc_html_e( 'Rate name', 'woocommerce' ); ?></th>
|
||||
<th><?php esc_html_e( 'Tax class', 'woocommerce' ); ?></th>
|
||||
<th><?php esc_html_e( 'Rate code', 'woocommerce' ); ?></th>
|
||||
<th><?php esc_html_e( 'Rate %', 'woocommerce' ); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php
|
||||
$rates = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates ORDER BY tax_rate_name LIMIT 100" );
|
||||
foreach ( $rates as $rate ) {
|
||||
echo '
|
||||
<tr>
|
||||
<td><input type="radio" id="add_order_tax_' . absint( $rate->tax_rate_id ) . '" name="add_order_tax" value="' . absint( $rate->tax_rate_id ) . '" /></td>
|
||||
<td><label for="add_order_tax_' . absint( $rate->tax_rate_id ) . '">' . esc_html( WC_Tax::get_rate_label( $rate ) ) . '</label></td>
|
||||
<td>' . ( isset( $classes_options[ $rate->tax_rate_class ] ) ? esc_html( $classes_options[ $rate->tax_rate_class ] ) : '-' ) . '</td>
|
||||
<td>' . esc_html( WC_Tax::get_rate_code( $rate ) ) . '</td>
|
||||
<td>' . esc_html( WC_Tax::get_rate_percent( $rate ) ) . '</td>
|
||||
</tr>
|
||||
';
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
<?php if ( absint( $wpdb->get_var( "SELECT COUNT(tax_rate_id) FROM {$wpdb->prefix}woocommerce_tax_rates;" ) ) > 100 ) : ?>
|
||||
<p>
|
||||
<label for="manual_tax_rate_id"><?php esc_html_e( 'Or, enter tax rate ID:', 'woocommerce' ); ?></label><br/>
|
||||
<input type="number" name="manual_tax_rate_id" id="manual_tax_rate_id" step="1" placeholder="<?php esc_attr_e( 'Optional', 'woocommerce' ); ?>" />
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</article>
|
||||
<footer>
|
||||
<div class="inner">
|
||||
<button id="btn-ok" class="button button-primary button-large"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
|
||||
</div>
|
||||
</footer>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wc-backbone-modal-backdrop modal-close"></div>
|
||||
</script>
|
48
includes/admin/meta-boxes/views/html-order-notes.php
Normal file
48
includes/admin/meta-boxes/views/html-order-notes.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* Order notes HTML for meta box.
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
?>
|
||||
<ul class="order_notes">
|
||||
<?php
|
||||
if ( $notes ) {
|
||||
foreach ( $notes as $note ) {
|
||||
$css_class = array( 'note' );
|
||||
$css_class[] = $note->customer_note ? 'customer-note' : '';
|
||||
$css_class[] = 'system' === $note->added_by ? 'system-note' : '';
|
||||
$css_class = apply_filters( 'woocommerce_order_note_class', array_filter( $css_class ), $note );
|
||||
?>
|
||||
<li rel="<?php echo absint( $note->id ); ?>" class="<?php echo esc_attr( implode( ' ', $css_class ) ); ?>">
|
||||
<div class="note_content">
|
||||
<?php echo wpautop( wptexturize( wp_kses_post( $note->content ) ) ); // @codingStandardsIgnoreLine ?>
|
||||
</div>
|
||||
<p class="meta">
|
||||
<abbr class="exact-date" title="<?php echo esc_attr( $note->date_created->date( 'Y-m-d H:i:s' ) ); ?>">
|
||||
<?php
|
||||
/* translators: %1$s: note date %2$s: note time */
|
||||
echo esc_html( sprintf( __( '%1$s at %2$s', 'woocommerce' ), $note->date_created->date_i18n( wc_date_format() ), $note->date_created->date_i18n( wc_time_format() ) ) );
|
||||
?>
|
||||
</abbr>
|
||||
<?php
|
||||
if ( 'system' !== $note->added_by ) :
|
||||
/* translators: %s: note author */
|
||||
echo esc_html( sprintf( ' ' . __( 'by %s', 'woocommerce' ), $note->added_by ) );
|
||||
endif;
|
||||
?>
|
||||
<a href="#" class="delete_note" role="button"><?php esc_html_e( 'Delete note', 'woocommerce' ); ?></a>
|
||||
</p>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
} else {
|
||||
?>
|
||||
<li class="no-items"><?php esc_html_e( 'There are no notes yet.', 'woocommerce' ); ?></li>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</ul>
|
79
includes/admin/meta-boxes/views/html-order-refund.php
Normal file
79
includes/admin/meta-boxes/views/html-order-refund.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
/**
|
||||
* Show order refund
|
||||
*
|
||||
* @var object $refund The refund object.
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
$who_refunded = new WP_User( $refund->get_refunded_by() );
|
||||
?>
|
||||
<tr class="refund <?php echo ( ! empty( $class ) ) ? esc_attr( $class ) : ''; ?>" data-order_refund_id="<?php echo esc_attr( $refund->get_id() ); ?>">
|
||||
<td class="thumb"><div></div></td>
|
||||
|
||||
<td class="name">
|
||||
<?php
|
||||
if ( $who_refunded->exists() ) {
|
||||
printf(
|
||||
/* translators: 1: refund id 2: refund date 3: username */
|
||||
esc_html__( 'Refund #%1$s - %2$s by %3$s', 'woocommerce' ),
|
||||
esc_html( $refund->get_id() ),
|
||||
esc_html( wc_format_datetime( $refund->get_date_created(), get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) ) ),
|
||||
sprintf(
|
||||
'<abbr class="refund_by" title="%1$s">%2$s</abbr>',
|
||||
/* translators: 1: ID who refunded */
|
||||
sprintf( esc_attr__( 'ID: %d', 'woocommerce' ), absint( $who_refunded->ID ) ),
|
||||
esc_html( $who_refunded->display_name )
|
||||
)
|
||||
);
|
||||
} else {
|
||||
printf(
|
||||
/* translators: 1: refund id 2: refund date */
|
||||
esc_html__( 'Refund #%1$s - %2$s', 'woocommerce' ),
|
||||
esc_html( $refund->get_id() ),
|
||||
esc_html( wc_format_datetime( $refund->get_date_created(), get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) ) )
|
||||
);
|
||||
}
|
||||
?>
|
||||
<?php if ( $refund->get_reason() ) : ?>
|
||||
<p class="description"><?php echo esc_html( $refund->get_reason() ); ?></p>
|
||||
<?php endif; ?>
|
||||
<input type="hidden" class="order_refund_id" name="order_refund_id[]" value="<?php echo esc_attr( $refund->get_id() ); ?>" />
|
||||
|
||||
<?php do_action( 'woocommerce_after_order_refund_item_name', $refund ); ?>
|
||||
</td>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_item_values', null, $refund, $refund->get_id() ); ?>
|
||||
|
||||
<td class="item_cost" width="1%"> </td>
|
||||
<td class="quantity" width="1%"> </td>
|
||||
|
||||
<td class="line_cost" width="1%">
|
||||
<div class="view">
|
||||
<?php
|
||||
echo wp_kses_post(
|
||||
wc_price( '-' . $refund->get_amount(), array( 'currency' => $refund->get_currency() ) )
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<?php
|
||||
if ( wc_tax_enabled() ) :
|
||||
$total_taxes = count( $order_taxes );
|
||||
?>
|
||||
<?php for ( $i = 0; $i < $total_taxes; $i++ ) : ?>
|
||||
<td class="line_tax" width="1%"></td>
|
||||
<?php endfor; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<td class="wc-order-edit-line-item">
|
||||
<div class="wc-order-edit-line-item-actions">
|
||||
<a class="delete_refund" href="#"></a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
116
includes/admin/meta-boxes/views/html-order-shipping.php
Normal file
116
includes/admin/meta-boxes/views/html-order-shipping.php
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
/**
|
||||
* Shows a shipping line
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*
|
||||
* @var object $item The item being displayed
|
||||
* @var int $item_id The id of the item being displayed
|
||||
*
|
||||
* @package WooCommerce\Admin\Views
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<tr class="shipping <?php echo ( ! empty( $class ) ) ? esc_attr( $class ) : ''; ?>" data-order_item_id="<?php echo esc_attr( $item_id ); ?>">
|
||||
<td class="thumb"><div></div></td>
|
||||
|
||||
<td class="name">
|
||||
<div class="view">
|
||||
<?php echo esc_html( $item->get_name() ? $item->get_name() : __( 'Shipping', 'woocommerce' ) ); ?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<input type="hidden" name="shipping_method_id[]" value="<?php echo esc_attr( $item_id ); ?>" />
|
||||
<input type="text" class="shipping_method_name" placeholder="<?php esc_attr_e( 'Shipping name', 'woocommerce' ); ?>" name="shipping_method_title[<?php echo esc_attr( $item_id ); ?>]" value="<?php echo esc_attr( $item->get_name() ); ?>" />
|
||||
<select class="shipping_method" name="shipping_method[<?php echo esc_attr( $item_id ); ?>]">
|
||||
<optgroup label="<?php esc_attr_e( 'Shipping method', 'woocommerce' ); ?>">
|
||||
<option value=""><?php esc_html_e( 'N/A', 'woocommerce' ); ?></option>
|
||||
<?php
|
||||
$found_method = false;
|
||||
|
||||
foreach ( $shipping_methods as $method ) {
|
||||
$is_active = $item->get_method_id() === $method->id;
|
||||
|
||||
echo '<option value="' . esc_attr( $method->id ) . '" ' . selected( true, $is_active, false ) . '>' . esc_html( $method->get_method_title() ) . '</option>';
|
||||
|
||||
if ( $is_active ) {
|
||||
$found_method = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $found_method && $item->get_method_id() ) {
|
||||
echo '<option value="' . esc_attr( $item->get_method_id() ) . '" selected="selected">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
|
||||
} else {
|
||||
echo '<option value="other">' . esc_html__( 'Other', 'woocommerce' ) . '</option>';
|
||||
}
|
||||
?>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<?php do_action( 'woocommerce_before_order_itemmeta', $item_id, $item, null ); ?>
|
||||
<?php require __DIR__ . '/html-order-item-meta.php'; ?>
|
||||
<?php do_action( 'woocommerce_after_order_itemmeta', $item_id, $item, null ); ?>
|
||||
</td>
|
||||
|
||||
<?php do_action( 'woocommerce_admin_order_item_values', null, $item, absint( $item_id ) ); ?>
|
||||
|
||||
<td class="item_cost" width="1%"> </td>
|
||||
<td class="quantity" width="1%"> </td>
|
||||
|
||||
<td class="line_cost" width="1%">
|
||||
<div class="view">
|
||||
<?php
|
||||
echo wp_kses_post( wc_price( $item->get_total(), array( 'currency' => $order->get_currency() ) ) );
|
||||
$refunded = $order->get_total_refunded_for_item( $item_id, 'shipping' );
|
||||
if ( $refunded ) {
|
||||
echo wp_kses_post( '<small class="refunded">-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>' );
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<input type="text" name="shipping_cost[<?php echo esc_attr( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo esc_attr( wc_format_localized_price( $item->get_total() ) ); ?>" class="line_total wc_input_price" />
|
||||
</div>
|
||||
<div class="refund" style="display: none;">
|
||||
<input type="text" name="refund_line_total[<?php echo absint( $item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_total wc_input_price" />
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<?php
|
||||
$tax_data = $item->get_taxes();
|
||||
if ( $tax_data && wc_tax_enabled() ) {
|
||||
foreach ( $order_taxes as $tax_item ) {
|
||||
$tax_item_id = $tax_item->get_rate_id();
|
||||
$tax_item_total = isset( $tax_data['total'][ $tax_item_id ] ) ? $tax_data['total'][ $tax_item_id ] : '';
|
||||
?>
|
||||
<td class="line_tax" width="1%">
|
||||
<div class="view">
|
||||
<?php
|
||||
echo wp_kses_post( ( '' !== $tax_item_total ) ? wc_price( $tax_item_total, array( 'currency' => $order->get_currency() ) ) : '–' );
|
||||
$refunded = $order->get_tax_refunded_for_item( $item_id, $tax_item_id, 'shipping' );
|
||||
if ( $refunded ) {
|
||||
echo wp_kses_post( '<small class="refunded">-' . wc_price( $refunded, array( 'currency' => $order->get_currency() ) ) . '</small>' );
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="edit" style="display: none;">
|
||||
<input type="text" name="shipping_taxes[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" value="<?php echo ( isset( $tax_item_total ) ) ? esc_attr( wc_format_localized_price( $tax_item_total ) ) : ''; ?>" class="line_tax wc_input_price" />
|
||||
</div>
|
||||
<div class="refund" style="display: none;">
|
||||
<input type="text" name="refund_line_tax[<?php echo absint( $item_id ); ?>][<?php echo esc_attr( $tax_item_id ); ?>]" placeholder="<?php echo esc_attr( wc_format_localized_price( 0 ) ); ?>" class="refund_line_tax wc_input_price" data-tax_id="<?php echo esc_attr( $tax_item_id ); ?>" />
|
||||
</div>
|
||||
</td>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
<td class="wc-order-edit-line-item">
|
||||
<?php if ( $order->is_editable() ) : ?>
|
||||
<div class="wc-order-edit-line-item-actions">
|
||||
<a class="edit-order-item" href="#"></a><a class="delete-order-item" href="#"></a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
89
includes/admin/meta-boxes/views/html-product-attribute.php
Normal file
89
includes/admin/meta-boxes/views/html-product-attribute.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<div data-taxonomy="<?php echo esc_attr( $attribute->get_taxonomy() ); ?>" class="woocommerce_attribute wc-metabox postbox closed <?php echo esc_attr( implode( ' ', $metabox_class ) ); ?>" rel="<?php echo esc_attr( $attribute->get_position() ); ?>">
|
||||
<h3>
|
||||
<a href="#" class="remove_row delete"><?php esc_html_e( 'Remove', 'woocommerce' ); ?></a>
|
||||
<div class="handlediv" title="<?php esc_attr_e( 'Click to toggle', 'woocommerce' ); ?>"></div>
|
||||
<div class="tips sort" data-tip="<?php esc_attr_e( 'Drag and drop to set admin attribute order', 'woocommerce' ); ?>"></div>
|
||||
<strong class="attribute_name"><?php echo wc_attribute_label( $attribute->get_name() ); ?></strong>
|
||||
</h3>
|
||||
<div class="woocommerce_attribute_data wc-metabox-content hidden">
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="attribute_name">
|
||||
<label><?php esc_html_e( 'Name', 'woocommerce' ); ?>:</label>
|
||||
|
||||
<?php if ( $attribute->is_taxonomy() ) : ?>
|
||||
<strong><?php echo wc_attribute_label( $attribute->get_name() ); ?></strong>
|
||||
<input type="hidden" name="attribute_names[<?php echo esc_attr( $i ); ?>]" value="<?php echo esc_attr( $attribute->get_name() ); ?>" />
|
||||
<?php else : ?>
|
||||
<input type="text" class="attribute_name" name="attribute_names[<?php echo esc_attr( $i ); ?>]" value="<?php echo esc_attr( $attribute->get_name() ); ?>" />
|
||||
<?php endif; ?>
|
||||
|
||||
<input type="hidden" name="attribute_position[<?php echo esc_attr( $i ); ?>]" class="attribute_position" value="<?php echo esc_attr( $attribute->get_position() ); ?>" />
|
||||
</td>
|
||||
<td rowspan="3">
|
||||
<label><?php esc_html_e( 'Value(s)', 'woocommerce' ); ?>:</label>
|
||||
<?php
|
||||
if ( $attribute->is_taxonomy() && $attribute_taxonomy = $attribute->get_taxonomy_object() ) {
|
||||
$attribute_types = wc_get_attribute_types();
|
||||
|
||||
if ( ! array_key_exists( $attribute_taxonomy->attribute_type, $attribute_types ) ) {
|
||||
$attribute_taxonomy->attribute_type = 'select';
|
||||
}
|
||||
|
||||
if ( 'select' === $attribute_taxonomy->attribute_type ) {
|
||||
?>
|
||||
<select multiple="multiple" data-placeholder="<?php esc_attr_e( 'Select terms', 'woocommerce' ); ?>" class="multiselect attribute_values wc-enhanced-select" name="attribute_values[<?php echo esc_attr( $i ); ?>][]">
|
||||
<?php
|
||||
$args = array(
|
||||
'orderby' => ! empty( $attribute_taxonomy->attribute_orderby ) ? $attribute_taxonomy->attribute_orderby : 'name',
|
||||
'hide_empty' => 0,
|
||||
);
|
||||
$all_terms = get_terms( $attribute->get_taxonomy(), apply_filters( 'woocommerce_product_attribute_terms', $args ) );
|
||||
if ( $all_terms ) {
|
||||
foreach ( $all_terms as $term ) {
|
||||
$options = $attribute->get_options();
|
||||
$options = ! empty( $options ) ? $options : array();
|
||||
echo '<option value="' . esc_attr( $term->term_id ) . '"' . wc_selected( $term->term_id, $options ) . '>' . esc_html( apply_filters( 'woocommerce_product_attribute_term_name', $term->name, $term ) ) . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<button class="button plus select_all_attributes"><?php esc_html_e( 'Select all', 'woocommerce' ); ?></button>
|
||||
<button class="button minus select_no_attributes"><?php esc_html_e( 'Select none', 'woocommerce' ); ?></button>
|
||||
<button class="button fr plus add_new_attribute"><?php esc_html_e( 'Add new', 'woocommerce' ); ?></button>
|
||||
<?php
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_product_option_terms', $attribute_taxonomy, $i, $attribute );
|
||||
} else {
|
||||
/* translators: %s: WC_DELIMITER */
|
||||
?>
|
||||
<textarea name="attribute_values[<?php echo esc_attr( $i ); ?>]" cols="5" rows="5" placeholder="<?php printf( esc_attr__( 'Enter some text, or some attributes by "%s" separating values.', 'woocommerce' ), WC_DELIMITER ); ?>"><?php echo esc_textarea( wc_implode_text_attributes( $attribute->get_options() ) ); ?></textarea>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<label><input type="checkbox" class="checkbox" <?php checked( $attribute->get_visible(), true ); ?> name="attribute_visibility[<?php echo esc_attr( $i ); ?>]" value="1" /> <?php esc_html_e( 'Visible on the product page', 'woocommerce' ); ?></label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="enable_variation show_if_variable">
|
||||
<label><input type="checkbox" class="checkbox" <?php checked( $attribute->get_variation(), true ); ?> name="attribute_variation[<?php echo esc_attr( $i ); ?>]" value="1" /> <?php esc_html_e( 'Used for variations', 'woocommerce' ); ?></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php do_action( 'woocommerce_after_product_attribute_settings', $attribute, $i ); ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<div id="advanced_product_data" class="panel woocommerce_options_panel hidden">
|
||||
|
||||
<div class="options_group hide_if_external hide_if_grouped">
|
||||
<?php
|
||||
woocommerce_wp_textarea_input(
|
||||
array(
|
||||
'id' => '_purchase_note',
|
||||
'value' => $product_object->get_purchase_note( 'edit' ),
|
||||
'label' => __( 'Purchase note', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Enter an optional note to send the customer after purchase.', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="options_group">
|
||||
<?php
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => 'menu_order',
|
||||
'value' => $product_object->get_menu_order( 'edit' ),
|
||||
'label' => __( 'Menu order', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Custom ordering position.', 'woocommerce' ),
|
||||
'type' => 'number',
|
||||
'custom_attributes' => array(
|
||||
'step' => '1',
|
||||
),
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php if ( post_type_supports( 'product', 'comments' ) ) : ?>
|
||||
<div class="options_group reviews">
|
||||
<?php
|
||||
woocommerce_wp_checkbox(
|
||||
array(
|
||||
'id' => 'comment_status',
|
||||
'value' => $product_object->get_reviews_allowed( 'edit' ) ? 'open' : 'closed',
|
||||
'label' => __( 'Enable reviews', 'woocommerce' ),
|
||||
'cbvalue' => 'open',
|
||||
)
|
||||
);
|
||||
do_action( 'woocommerce_product_options_reviews' );
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php do_action( 'woocommerce_product_options_advanced' ); ?>
|
||||
</div>
|
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<div id="product_attributes" class="panel wc-metaboxes-wrapper hidden">
|
||||
<div class="toolbar toolbar-top">
|
||||
<span class="expand-close">
|
||||
<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>
|
||||
</span>
|
||||
<select name="attribute_taxonomy" class="attribute_taxonomy">
|
||||
<option value=""><?php esc_html_e( 'Custom product attribute', 'woocommerce' ); ?></option>
|
||||
<?php
|
||||
global $wc_product_attributes;
|
||||
|
||||
// Array of defined attribute taxonomies.
|
||||
$attribute_taxonomies = wc_get_attribute_taxonomies();
|
||||
|
||||
if ( ! empty( $attribute_taxonomies ) ) {
|
||||
foreach ( $attribute_taxonomies as $tax ) {
|
||||
$attribute_taxonomy_name = wc_attribute_taxonomy_name( $tax->attribute_name );
|
||||
$label = $tax->attribute_label ? $tax->attribute_label : $tax->attribute_name;
|
||||
echo '<option value="' . esc_attr( $attribute_taxonomy_name ) . '">' . esc_html( $label ) . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<button type="button" class="button add_attribute"><?php esc_html_e( 'Add', 'woocommerce' ); ?></button>
|
||||
</div>
|
||||
<div class="product_attributes wc-metaboxes">
|
||||
<?php
|
||||
// Product attributes - taxonomies and custom, ordered, with visibility and variation attributes set.
|
||||
$attributes = $product_object->get_attributes( 'edit' );
|
||||
$i = -1;
|
||||
|
||||
foreach ( $attributes as $attribute ) {
|
||||
$i++;
|
||||
$metabox_class = array();
|
||||
|
||||
if ( $attribute->is_taxonomy() ) {
|
||||
$metabox_class[] = 'taxonomy';
|
||||
$metabox_class[] = $attribute->get_name();
|
||||
}
|
||||
|
||||
include __DIR__ . '/html-product-attribute.php';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<span class="expand-close">
|
||||
<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>
|
||||
</span>
|
||||
<button type="button" class="button save_attributes button-primary"><?php esc_html_e( 'Save attributes', 'woocommerce' ); ?></button>
|
||||
</div>
|
||||
<?php do_action( 'woocommerce_product_options_attributes' ); ?>
|
||||
</div>
|
189
includes/admin/meta-boxes/views/html-product-data-general.php
Normal file
189
includes/admin/meta-boxes/views/html-product-data-general.php
Normal file
@ -0,0 +1,189 @@
|
||||
<?php
|
||||
/**
|
||||
* Product general data panel.
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
?>
|
||||
<div id="general_product_data" class="panel woocommerce_options_panel">
|
||||
|
||||
<div class="options_group show_if_external">
|
||||
<?php
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_product_url',
|
||||
'value' => is_callable( array( $product_object, 'get_product_url' ) ) ? $product_object->get_product_url( 'edit' ) : '',
|
||||
'label' => __( 'Product URL', 'woocommerce' ),
|
||||
'placeholder' => 'https://',
|
||||
'description' => __( 'Enter the external URL to the product.', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_button_text',
|
||||
'value' => is_callable( array( $product_object, 'get_button_text' ) ) ? $product_object->get_button_text( 'edit' ) : '',
|
||||
'label' => __( 'Button text', 'woocommerce' ),
|
||||
'placeholder' => _x( 'Buy product', 'placeholder', 'woocommerce' ),
|
||||
'description' => __( 'This text will be shown on the button linking to the external product.', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
do_action( 'woocommerce_product_options_external' );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="options_group pricing show_if_simple show_if_external hidden">
|
||||
<?php
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_regular_price',
|
||||
'value' => $product_object->get_regular_price( 'edit' ),
|
||||
'label' => __( 'Regular price', 'woocommerce' ) . ' (' . get_woocommerce_currency_symbol() . ')',
|
||||
'data_type' => 'price',
|
||||
)
|
||||
);
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_sale_price',
|
||||
'value' => $product_object->get_sale_price( 'edit' ),
|
||||
'data_type' => 'price',
|
||||
'label' => __( 'Sale price', 'woocommerce' ) . ' (' . get_woocommerce_currency_symbol() . ')',
|
||||
'description' => '<a href="#" class="sale_schedule">' . __( 'Schedule', 'woocommerce' ) . '</a>',
|
||||
)
|
||||
);
|
||||
|
||||
$sale_price_dates_from_timestamp = $product_object->get_date_on_sale_from( 'edit' ) ? $product_object->get_date_on_sale_from( 'edit' )->getOffsetTimestamp() : false;
|
||||
$sale_price_dates_to_timestamp = $product_object->get_date_on_sale_to( 'edit' ) ? $product_object->get_date_on_sale_to( 'edit' )->getOffsetTimestamp() : false;
|
||||
|
||||
$sale_price_dates_from = $sale_price_dates_from_timestamp ? date_i18n( 'Y-m-d', $sale_price_dates_from_timestamp ) : '';
|
||||
$sale_price_dates_to = $sale_price_dates_to_timestamp ? date_i18n( 'Y-m-d', $sale_price_dates_to_timestamp ) : '';
|
||||
|
||||
echo '<p class="form-field sale_price_dates_fields">
|
||||
<label for="_sale_price_dates_from">' . esc_html__( 'Sale price dates', 'woocommerce' ) . '</label>
|
||||
<input type="text" class="short" name="_sale_price_dates_from" id="_sale_price_dates_from" value="' . esc_attr( $sale_price_dates_from ) . '" placeholder="' . esc_html( _x( 'From…', 'placeholder', 'woocommerce' ) ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
|
||||
<input type="text" class="short" name="_sale_price_dates_to" id="_sale_price_dates_to" value="' . esc_attr( $sale_price_dates_to ) . '" placeholder="' . esc_html( _x( 'To…', 'placeholder', 'woocommerce' ) ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
|
||||
<a href="#" class="description cancel_sale_schedule">' . esc_html__( 'Cancel', 'woocommerce' ) . '</a>' . wc_help_tip( __( 'The sale will start at 00:00:00 of "From" date and end at 23:59:59 of "To" date.', 'woocommerce' ) ) . '
|
||||
</p>';
|
||||
|
||||
do_action( 'woocommerce_product_options_pricing' );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="options_group show_if_downloadable hidden">
|
||||
<div class="form-field downloadable_files">
|
||||
<label><?php esc_html_e( 'Downloadable files', 'woocommerce' ); ?></label>
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="sort"> </th>
|
||||
<th><?php esc_html_e( 'Name', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the name of the download shown to the customer.', 'woocommerce' ) ); ?></th>
|
||||
<th colspan="2"><?php esc_html_e( 'File URL', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the URL or absolute path to the file which customers will get access to. URLs entered here should already be encoded.', 'woocommerce' ) ); ?></th>
|
||||
<th> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$downloadable_files = $product_object->get_downloads( 'edit' );
|
||||
if ( $downloadable_files ) {
|
||||
foreach ( $downloadable_files as $key => $file ) {
|
||||
include __DIR__ . '/html-product-download.php';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th colspan="5">
|
||||
<a href="#" class="button insert" data-row="
|
||||
<?php
|
||||
$key = '';
|
||||
$file = array(
|
||||
'file' => '',
|
||||
'name' => '',
|
||||
);
|
||||
ob_start();
|
||||
require __DIR__ . '/html-product-download.php';
|
||||
echo esc_attr( ob_get_clean() );
|
||||
?>
|
||||
"><?php esc_html_e( 'Add File', 'woocommerce' ); ?></a>
|
||||
</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_download_limit',
|
||||
'value' => -1 === $product_object->get_download_limit( 'edit' ) ? '' : $product_object->get_download_limit( 'edit' ),
|
||||
'label' => __( 'Download limit', 'woocommerce' ),
|
||||
'placeholder' => __( 'Unlimited', 'woocommerce' ),
|
||||
'description' => __( 'Leave blank for unlimited re-downloads.', 'woocommerce' ),
|
||||
'type' => 'number',
|
||||
'custom_attributes' => array(
|
||||
'step' => '1',
|
||||
'min' => '0',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_download_expiry',
|
||||
'value' => -1 === $product_object->get_download_expiry( 'edit' ) ? '' : $product_object->get_download_expiry( 'edit' ),
|
||||
'label' => __( 'Download expiry', 'woocommerce' ),
|
||||
'placeholder' => __( 'Never', 'woocommerce' ),
|
||||
'description' => __( 'Enter the number of days before a download link expires, or leave blank.', 'woocommerce' ),
|
||||
'type' => 'number',
|
||||
'custom_attributes' => array(
|
||||
'step' => '1',
|
||||
'min' => '0',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
do_action( 'woocommerce_product_options_downloads' );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php if ( wc_tax_enabled() ) : ?>
|
||||
<div class="options_group show_if_simple show_if_external show_if_variable">
|
||||
<?php
|
||||
woocommerce_wp_select(
|
||||
array(
|
||||
'id' => '_tax_status',
|
||||
'value' => $product_object->get_tax_status( 'edit' ),
|
||||
'label' => __( 'Tax status', 'woocommerce' ),
|
||||
'options' => array(
|
||||
'taxable' => __( 'Taxable', 'woocommerce' ),
|
||||
'shipping' => __( 'Shipping only', 'woocommerce' ),
|
||||
'none' => _x( 'None', 'Tax status', 'woocommerce' ),
|
||||
),
|
||||
'desc_tip' => 'true',
|
||||
'description' => __( 'Define whether or not the entire product is taxable, or just the cost of shipping it.', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
woocommerce_wp_select(
|
||||
array(
|
||||
'id' => '_tax_class',
|
||||
'value' => $product_object->get_tax_class( 'edit' ),
|
||||
'label' => __( 'Tax class', 'woocommerce' ),
|
||||
'options' => wc_get_product_tax_class_options(),
|
||||
'desc_tip' => 'true',
|
||||
'description' => __( 'Choose a tax class for this product. Tax classes are used to apply different tax rates specific to certain types of product.', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
do_action( 'woocommerce_product_options_tax' );
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php do_action( 'woocommerce_product_options_general_product_data' ); ?>
|
||||
</div>
|
131
includes/admin/meta-boxes/views/html-product-data-inventory.php
Normal file
131
includes/admin/meta-boxes/views/html-product-data-inventory.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
/**
|
||||
* Displays the inventory tab in the product data meta box.
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<div id="inventory_product_data" class="panel woocommerce_options_panel hidden">
|
||||
|
||||
<div class="options_group">
|
||||
<?php
|
||||
if ( wc_product_sku_enabled() ) {
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_sku',
|
||||
'value' => $product_object->get_sku( 'edit' ),
|
||||
'label' => '<abbr title="' . esc_attr__( 'Stock Keeping Unit', 'woocommerce' ) . '">' . esc_html__( 'SKU', 'woocommerce' ) . '</abbr>',
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'SKU refers to a Stock-keeping unit, a unique identifier for each distinct product and service that can be purchased.', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_product_options_sku' );
|
||||
|
||||
if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) {
|
||||
|
||||
woocommerce_wp_checkbox(
|
||||
array(
|
||||
'id' => '_manage_stock',
|
||||
'value' => $product_object->get_manage_stock( 'edit' ) ? 'yes' : 'no',
|
||||
'wrapper_class' => 'show_if_simple show_if_variable',
|
||||
'label' => __( 'Manage stock?', 'woocommerce' ),
|
||||
'description' => __( 'Enable stock management at product level', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
do_action( 'woocommerce_product_options_stock' );
|
||||
|
||||
echo '<div class="stock_fields show_if_simple show_if_variable">';
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_stock',
|
||||
'value' => wc_stock_amount( $product_object->get_stock_quantity( 'edit' ) ),
|
||||
'label' => __( 'Stock quantity', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Stock quantity. If this is a variable product this value will be used to control stock for all variations, unless you define stock at variation level.', 'woocommerce' ),
|
||||
'type' => 'number',
|
||||
'custom_attributes' => array(
|
||||
'step' => 'any',
|
||||
),
|
||||
'data_type' => 'stock',
|
||||
)
|
||||
);
|
||||
|
||||
echo '<input type="hidden" name="_original_stock" value="' . esc_attr( wc_stock_amount( $product_object->get_stock_quantity( 'edit' ) ) ) . '" />';
|
||||
|
||||
woocommerce_wp_select(
|
||||
array(
|
||||
'id' => '_backorders',
|
||||
'value' => $product_object->get_backorders( 'edit' ),
|
||||
'label' => __( 'Allow backorders?', 'woocommerce' ),
|
||||
'options' => wc_get_product_backorder_options(),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'If managing stock, this controls whether or not backorders are allowed. If enabled, stock quantity can go below 0.', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_low_stock_amount',
|
||||
'value' => $product_object->get_low_stock_amount( 'edit' ),
|
||||
'placeholder' => sprintf(
|
||||
/* translators: %d: Amount of stock left */
|
||||
esc_attr__( 'Store-wide threshold (%d)', 'woocommerce' ),
|
||||
esc_attr( get_option( 'woocommerce_notify_low_stock_amount' ) )
|
||||
),
|
||||
'label' => __( 'Low stock threshold', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'When product stock reaches this amount you will be notified by email. It is possible to define different values for each variation individually. The shop default value can be set in Settings > Products > Inventory.', 'woocommerce' ),
|
||||
'type' => 'number',
|
||||
'custom_attributes' => array(
|
||||
'step' => 'any',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
do_action( 'woocommerce_product_options_stock_fields' );
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
woocommerce_wp_select(
|
||||
array(
|
||||
'id' => '_stock_status',
|
||||
'value' => $product_object->get_stock_status( 'edit' ),
|
||||
'wrapper_class' => 'stock_status_field hide_if_variable hide_if_external hide_if_grouped',
|
||||
'label' => __( 'Stock status', 'woocommerce' ),
|
||||
'options' => wc_get_product_stock_status_options(),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Controls whether or not the product is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
do_action( 'woocommerce_product_options_stock_status' );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="options_group show_if_simple show_if_variable">
|
||||
<?php
|
||||
woocommerce_wp_checkbox(
|
||||
array(
|
||||
'id' => '_sold_individually',
|
||||
'value' => $product_object->get_sold_individually( 'edit' ) ? 'yes' : 'no',
|
||||
'wrapper_class' => 'show_if_simple show_if_variable',
|
||||
'label' => __( 'Sold individually', 'woocommerce' ),
|
||||
'description' => __( 'Enable this to only allow one of this item to be bought in a single order', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
do_action( 'woocommerce_product_options_sold_individually' );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php do_action( 'woocommerce_product_options_inventory_product_data' ); ?>
|
||||
</div>
|
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* Linked product options.
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
?>
|
||||
<div id="linked_product_data" class="panel woocommerce_options_panel hidden">
|
||||
|
||||
<div class="options_group show_if_grouped">
|
||||
<p class="form-field">
|
||||
<label for="grouped_products"><?php esc_html_e( 'Grouped products', 'woocommerce' ); ?></label>
|
||||
<select class="wc-product-search" multiple="multiple" style="width: 50%;" id="grouped_products" name="grouped_products[]" data-sortable="true" data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products" data-exclude="<?php echo intval( $post->ID ); ?>">
|
||||
<?php
|
||||
$product_ids = $product_object->is_type( 'grouped' ) ? $product_object->get_children( 'edit' ) : array();
|
||||
|
||||
foreach ( $product_ids as $product_id ) {
|
||||
$product = wc_get_product( $product_id );
|
||||
if ( is_object( $product ) ) {
|
||||
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select> <?php echo wc_help_tip( __( 'This lets you choose which products are part of this group.', 'woocommerce' ) ); // WPCS: XSS ok. ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="options_group">
|
||||
<p class="form-field">
|
||||
<label for="upsell_ids"><?php esc_html_e( 'Upsells', 'woocommerce' ); ?></label>
|
||||
<select class="wc-product-search" multiple="multiple" style="width: 50%;" id="upsell_ids" name="upsell_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-exclude="<?php echo intval( $post->ID ); ?>">
|
||||
<?php
|
||||
$product_ids = $product_object->get_upsell_ids( 'edit' );
|
||||
|
||||
foreach ( $product_ids as $product_id ) {
|
||||
$product = wc_get_product( $product_id );
|
||||
if ( is_object( $product ) ) {
|
||||
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select> <?php echo wc_help_tip( __( 'Upsells are products which you recommend instead of the currently viewed product, for example, products that are more profitable or better quality or more expensive.', 'woocommerce' ) ); // WPCS: XSS ok. ?>
|
||||
</p>
|
||||
|
||||
<p class="form-field hide_if_grouped hide_if_external">
|
||||
<label for="crosssell_ids"><?php esc_html_e( 'Cross-sells', 'woocommerce' ); ?></label>
|
||||
<select class="wc-product-search" multiple="multiple" style="width: 50%;" id="crosssell_ids" name="crosssell_ids[]" data-placeholder="<?php esc_attr_e( 'Search for a product…', 'woocommerce' ); ?>" data-action="woocommerce_json_search_products_and_variations" data-exclude="<?php echo intval( $post->ID ); ?>">
|
||||
<?php
|
||||
$product_ids = $product_object->get_cross_sell_ids( 'edit' );
|
||||
|
||||
foreach ( $product_ids as $product_id ) {
|
||||
$product = wc_get_product( $product_id );
|
||||
if ( is_object( $product ) ) {
|
||||
echo '<option value="' . esc_attr( $product_id ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</select> <?php echo wc_help_tip( __( 'Cross-sells are products which you promote in the cart, based on the current product.', 'woocommerce' ) ); // WPCS: XSS ok. ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php do_action( 'woocommerce_product_options_related' ); ?>
|
||||
</div>
|
57
includes/admin/meta-boxes/views/html-product-data-panel.php
Normal file
57
includes/admin/meta-boxes/views/html-product-data-panel.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* Product data meta box.
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<div class="panel-wrap product_data">
|
||||
|
||||
<span class="type_box hidden"> —
|
||||
<label for="product-type">
|
||||
<select id="product-type" name="product-type">
|
||||
<optgroup label="<?php esc_attr_e( 'Product Type', 'woocommerce' ); ?>">
|
||||
<?php foreach ( wc_get_product_types() as $value => $label ) : ?>
|
||||
<option value="<?php echo esc_attr( $value ); ?>" <?php echo selected( $product_object->get_type(), $value, false ); ?>><?php echo esc_html( $label ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</optgroup>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<?php
|
||||
foreach ( self::get_product_type_options() as $key => $option ) :
|
||||
if ( metadata_exists( 'post', $post->ID, '_' . $key ) ) {
|
||||
$selected_value = is_callable( array( $product_object, "is_$key" ) ) ? $product_object->{"is_$key"}() : 'yes' === get_post_meta( $post->ID, '_' . $key, true );
|
||||
} else {
|
||||
$selected_value = 'yes' === ( isset( $option['default'] ) ? $option['default'] : 'no' );
|
||||
}
|
||||
?>
|
||||
<label for="<?php echo esc_attr( $option['id'] ); ?>" class="<?php echo esc_attr( $option['wrapper_class'] ); ?> tips" data-tip="<?php echo esc_attr( $option['description'] ); ?>">
|
||||
<?php echo esc_html( $option['label'] ); ?>:
|
||||
<input type="checkbox" name="<?php echo esc_attr( $option['id'] ); ?>" id="<?php echo esc_attr( $option['id'] ); ?>" <?php echo checked( $selected_value, true, false ); ?> />
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</span>
|
||||
|
||||
<ul class="product_data_tabs wc-tabs">
|
||||
<?php foreach ( self::get_product_data_tabs() as $key => $tab ) : ?>
|
||||
<li class="<?php echo esc_attr( $key ); ?>_options <?php echo esc_attr( $key ); ?>_tab <?php echo esc_attr( isset( $tab['class'] ) ? implode( ' ', (array) $tab['class'] ) : '' ); ?>">
|
||||
<a href="#<?php echo esc_attr( $tab['target'] ); ?>"><span><?php echo esc_html( $tab['label'] ); ?></span></a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
<?php do_action( 'woocommerce_product_write_panel_tabs' ); ?>
|
||||
</ul>
|
||||
|
||||
<?php
|
||||
self::output_tabs();
|
||||
self::output_variations();
|
||||
do_action( 'woocommerce_product_data_panels' );
|
||||
wc_do_deprecated_action( 'woocommerce_product_write_panels', array(), '2.6', 'Use woocommerce_product_data_panels action instead.' );
|
||||
?>
|
||||
<div class="clear"></div>
|
||||
</div>
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<div id="shipping_product_data" class="panel woocommerce_options_panel hidden">
|
||||
<div class="options_group">
|
||||
<?php
|
||||
if ( wc_product_weight_enabled() ) {
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => '_weight',
|
||||
'value' => $product_object->get_weight( 'edit' ),
|
||||
'label' => __( 'Weight', 'woocommerce' ) . ' (' . get_option( 'woocommerce_weight_unit' ) . ')',
|
||||
'placeholder' => wc_format_localized_decimal( 0 ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Weight in decimal form', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'data_type' => 'decimal',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( wc_product_dimensions_enabled() ) {
|
||||
?>
|
||||
<p class="form-field dimensions_field">
|
||||
<?php /* translators: WooCommerce dimension unit*/ ?>
|
||||
<label for="product_length"><?php printf( __( 'Dimensions (%s)', 'woocommerce' ), get_option( 'woocommerce_dimension_unit' ) ); ?></label>
|
||||
<span class="wrap">
|
||||
<input id="product_length" placeholder="<?php esc_attr_e( 'Length', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="_length" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_length( 'edit' ) ) ); ?>" />
|
||||
<input id="product_width" placeholder="<?php esc_attr_e( 'Width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="_width" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_width( 'edit' ) ) ); ?>" />
|
||||
<input id="product_height" placeholder="<?php esc_attr_e( 'Height', 'woocommerce' ); ?>" class="input-text wc_input_decimal last" size="6" type="text" name="_height" value="<?php echo esc_attr( wc_format_localized_decimal( $product_object->get_height( 'edit' ) ) ); ?>" />
|
||||
</span>
|
||||
<?php echo wc_help_tip( __( 'LxWxH in decimal form', 'woocommerce' ) ); ?>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_product_options_dimensions' );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="options_group">
|
||||
<?php
|
||||
$args = array(
|
||||
'taxonomy' => 'product_shipping_class',
|
||||
'hide_empty' => 0,
|
||||
'show_option_none' => __( 'No shipping class', 'woocommerce' ),
|
||||
'name' => 'product_shipping_class',
|
||||
'id' => 'product_shipping_class',
|
||||
'selected' => $product_object->get_shipping_class_id( 'edit' ),
|
||||
'class' => 'select short',
|
||||
'orderby' => 'name',
|
||||
);
|
||||
?>
|
||||
<p class="form-field shipping_class_field">
|
||||
<label for="product_shipping_class"><?php esc_html_e( 'Shipping class', 'woocommerce' ); ?></label>
|
||||
<?php wp_dropdown_categories( $args ); ?>
|
||||
<?php echo wc_help_tip( __( 'Shipping classes are used by certain shipping methods to group similar products.', 'woocommerce' ) ); ?>
|
||||
</p>
|
||||
<?php
|
||||
|
||||
do_action( 'woocommerce_product_options_shipping' );
|
||||
?>
|
||||
</div>
|
||||
</div>
|
152
includes/admin/meta-boxes/views/html-product-data-variations.php
Normal file
152
includes/admin/meta-boxes/views/html-product-data-variations.php
Normal file
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/**
|
||||
* Product data variations
|
||||
*
|
||||
* @package WooCommerce\Admin\Metaboxes\Views
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<div id="variable_product_options" class="panel wc-metaboxes-wrapper hidden">
|
||||
<div id="variable_product_options_inner">
|
||||
|
||||
<?php if ( ! count( $variation_attributes ) ) : ?>
|
||||
|
||||
<div id="message" class="inline notice woocommerce-message">
|
||||
<p><?php echo wp_kses_post( __( 'Before you can add a variation you need to add some variation attributes on the <strong>Attributes</strong> tab.', 'woocommerce' ) ); ?></p>
|
||||
<p><a class="button-primary" href="<?php echo esc_url( apply_filters( 'woocommerce_docs_url', 'https://docs.woocommerce.com/document/variable-product/', 'product-variations' ) ); ?>" target="_blank"><?php esc_html_e( 'Learn more', 'woocommerce' ); ?></a></p>
|
||||
</div>
|
||||
|
||||
<?php else : ?>
|
||||
|
||||
<div class="toolbar toolbar-variations-defaults">
|
||||
<div class="variations-defaults">
|
||||
<strong><?php esc_html_e( 'Default Form Values', 'woocommerce' ); ?>: <?php echo wc_help_tip( __( 'These are the attributes that will be pre-selected on the frontend.', 'woocommerce' ) ); ?></strong>
|
||||
<?php
|
||||
foreach ( $variation_attributes as $attribute ) {
|
||||
$selected_value = isset( $default_attributes[ sanitize_title( $attribute->get_name() ) ] ) ? $default_attributes[ sanitize_title( $attribute->get_name() ) ] : '';
|
||||
?>
|
||||
<select name="default_attribute_<?php echo esc_attr( sanitize_title( $attribute->get_name() ) ); ?>" data-current="<?php echo esc_attr( $selected_value ); ?>">
|
||||
<?php /* translators: WooCommerce attribute label */ ?>
|
||||
<option value=""><?php echo esc_html( sprintf( __( 'No default %s…', 'woocommerce' ), wc_attribute_label( $attribute->get_name() ) ) ); ?></option>
|
||||
<?php if ( $attribute->is_taxonomy() ) : ?>
|
||||
<?php foreach ( $attribute->get_terms() as $option ) : ?>
|
||||
<option <?php selected( $selected_value, $option->slug ); ?> value="<?php echo esc_attr( $option->slug ); ?>"><?php echo esc_html( apply_filters( 'woocommerce_variation_option_name', $option->name, $option, $attribute->get_name(), $product_object ) ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<?php foreach ( $attribute->get_options() as $option ) : ?>
|
||||
<option <?php selected( $selected_value, $option ); ?> value="<?php echo esc_attr( $option ); ?>"><?php echo esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute->get_name(), $product_object ) ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<?php do_action( 'woocommerce_variable_product_before_variations' ); ?>
|
||||
|
||||
<div class="toolbar toolbar-top">
|
||||
<select id="field_to_edit" class="variation_actions">
|
||||
<option data-global="true" value="add_variation"><?php esc_html_e( 'Add variation', 'woocommerce' ); ?></option>
|
||||
<option data-global="true" value="link_all_variations"><?php esc_html_e( 'Create variations from all attributes', 'woocommerce' ); ?></option>
|
||||
<option value="delete_all"><?php esc_html_e( 'Delete all variations', 'woocommerce' ); ?></option>
|
||||
<optgroup label="<?php esc_attr_e( 'Status', 'woocommerce' ); ?>">
|
||||
<option value="toggle_enabled"><?php esc_html_e( 'Toggle "Enabled"', 'woocommerce' ); ?></option>
|
||||
<option value="toggle_downloadable"><?php esc_html_e( 'Toggle "Downloadable"', 'woocommerce' ); ?></option>
|
||||
<option value="toggle_virtual"><?php esc_html_e( 'Toggle "Virtual"', 'woocommerce' ); ?></option>
|
||||
</optgroup>
|
||||
<optgroup label="<?php esc_attr_e( 'Pricing', 'woocommerce' ); ?>">
|
||||
<option value="variable_regular_price"><?php esc_html_e( 'Set regular prices', 'woocommerce' ); ?></option>
|
||||
<option value="variable_regular_price_increase"><?php esc_html_e( 'Increase regular prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
|
||||
<option value="variable_regular_price_decrease"><?php esc_html_e( 'Decrease regular prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
|
||||
<option value="variable_sale_price"><?php esc_html_e( 'Set sale prices', 'woocommerce' ); ?></option>
|
||||
<option value="variable_sale_price_increase"><?php esc_html_e( 'Increase sale prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
|
||||
<option value="variable_sale_price_decrease"><?php esc_html_e( 'Decrease sale prices (fixed amount or percentage)', 'woocommerce' ); ?></option>
|
||||
<option value="variable_sale_schedule"><?php esc_html_e( 'Set scheduled sale dates', 'woocommerce' ); ?></option>
|
||||
</optgroup>
|
||||
<optgroup label="<?php esc_attr_e( 'Inventory', 'woocommerce' ); ?>">
|
||||
<option value="toggle_manage_stock"><?php esc_html_e( 'Toggle "Manage stock"', 'woocommerce' ); ?></option>
|
||||
<option value="variable_stock"><?php esc_html_e( 'Stock', 'woocommerce' ); ?></option>
|
||||
<option value="variable_stock_status_instock"><?php esc_html_e( 'Set Status - In stock', 'woocommerce' ); ?></option>
|
||||
<option value="variable_stock_status_outofstock"><?php esc_html_e( 'Set Status - Out of stock', 'woocommerce' ); ?></option>
|
||||
<option value="variable_stock_status_onbackorder"><?php esc_html_e( 'Set Status - On backorder', 'woocommerce' ); ?></option>
|
||||
<option value="variable_low_stock_amount"><?php esc_html_e( 'Low stock threshold', 'woocommerce' ); ?></option>
|
||||
</optgroup>
|
||||
<optgroup label="<?php esc_attr_e( 'Shipping', 'woocommerce' ); ?>">
|
||||
<option value="variable_length"><?php esc_html_e( 'Length', 'woocommerce' ); ?></option>
|
||||
<option value="variable_width"><?php esc_html_e( 'Width', 'woocommerce' ); ?></option>
|
||||
<option value="variable_height"><?php esc_html_e( 'Height', 'woocommerce' ); ?></option>
|
||||
<option value="variable_weight"><?php esc_html_e( 'Weight', 'woocommerce' ); ?></option>
|
||||
</optgroup>
|
||||
<optgroup label="<?php esc_attr_e( 'Downloadable products', 'woocommerce' ); ?>">
|
||||
<option value="variable_download_limit"><?php esc_html_e( 'Download limit', 'woocommerce' ); ?></option>
|
||||
<option value="variable_download_expiry"><?php esc_html_e( 'Download expiry', 'woocommerce' ); ?></option>
|
||||
</optgroup>
|
||||
<?php do_action( 'woocommerce_variable_product_bulk_edit_actions' ); ?>
|
||||
</select>
|
||||
<a class="button bulk_edit do_variation_action"><?php esc_html_e( 'Go', 'woocommerce' ); ?></a>
|
||||
|
||||
<div class="variations-pagenav">
|
||||
<?php /* translators: variations count */ ?>
|
||||
<span class="displaying-num"><?php echo esc_html( sprintf( _n( '%s item', '%s items', $variations_count, 'woocommerce' ), $variations_count ) ); ?></span>
|
||||
<span class="expand-close">
|
||||
(<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>)
|
||||
</span>
|
||||
<span class="pagination-links">
|
||||
<a class="first-page disabled" title="<?php esc_attr_e( 'Go to the first page', 'woocommerce' ); ?>" href="#">«</a>
|
||||
<a class="prev-page disabled" title="<?php esc_attr_e( 'Go to the previous page', 'woocommerce' ); ?>" href="#">‹</a>
|
||||
<span class="paging-select">
|
||||
<label for="current-page-selector-1" class="screen-reader-text"><?php esc_html_e( 'Select Page', 'woocommerce' ); ?></label>
|
||||
<select class="page-selector" id="current-page-selector-1" title="<?php esc_attr_e( 'Current page', 'woocommerce' ); ?>">
|
||||
<?php for ( $i = 1; $i <= $variations_total_pages; $i++ ) : ?>
|
||||
<option value="<?php echo $i; // WPCS: XSS ok. ?>"><?php echo $i; // WPCS: XSS ok. ?></option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
<?php echo esc_html_x( 'of', 'number of pages', 'woocommerce' ); ?> <span class="total-pages"><?php echo esc_html( $variations_total_pages ); ?></span>
|
||||
</span>
|
||||
<a class="next-page" title="<?php esc_attr_e( 'Go to the next page', 'woocommerce' ); ?>" href="#">›</a>
|
||||
<a class="last-page" title="<?php esc_attr_e( 'Go to the last page', 'woocommerce' ); ?>" href="#">»</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<div class="woocommerce_variations wc-metaboxes" data-attributes="<?php echo wc_esc_json( wp_json_encode( wc_list_pluck( $variation_attributes, 'get_data' ) ) ); // WPCS: XSS ok. ?>" data-total="<?php echo esc_attr( $variations_count ); ?>" data-total_pages="<?php echo esc_attr( $variations_total_pages ); ?>" data-page="1" data-edited="false"></div>
|
||||
|
||||
<div class="toolbar">
|
||||
<button type="button" class="button-primary save-variation-changes" disabled="disabled"><?php esc_html_e( 'Save changes', 'woocommerce' ); ?></button>
|
||||
<button type="button" class="button cancel-variation-changes" disabled="disabled"><?php esc_html_e( 'Cancel', 'woocommerce' ); ?></button>
|
||||
|
||||
<div class="variations-pagenav">
|
||||
<?php /* translators: variations count*/ ?>
|
||||
<span class="displaying-num"><?php echo esc_html( sprintf( _n( '%s item', '%s items', $variations_count, 'woocommerce' ), $variations_count ) ); ?></span>
|
||||
<span class="expand-close">
|
||||
(<a href="#" class="expand_all"><?php esc_html_e( 'Expand', 'woocommerce' ); ?></a> / <a href="#" class="close_all"><?php esc_html_e( 'Close', 'woocommerce' ); ?></a>)
|
||||
</span>
|
||||
<span class="pagination-links">
|
||||
<a class="first-page disabled" title="<?php esc_attr_e( 'Go to the first page', 'woocommerce' ); ?>" href="#">«</a>
|
||||
<a class="prev-page disabled" title="<?php esc_attr_e( 'Go to the previous page', 'woocommerce' ); ?>" href="#">‹</a>
|
||||
<span class="paging-select">
|
||||
<label for="current-page-selector-1" class="screen-reader-text"><?php esc_html_e( 'Select Page', 'woocommerce' ); ?></label>
|
||||
<select class="page-selector" id="current-page-selector-1" title="<?php esc_attr_e( 'Current page', 'woocommerce' ); ?>">
|
||||
<?php for ( $i = 1; $i <= $variations_total_pages; $i++ ) : ?>
|
||||
<option value="<?php echo $i; // WPCS: XSS ok. ?>"><?php echo $i; // WPCS: XSS ok. ?></option>
|
||||
<?php endfor; ?>
|
||||
</select>
|
||||
<?php echo esc_html_x( 'of', 'number of pages', 'woocommerce' ); ?> <span class="total-pages"><?php echo esc_html( $variations_total_pages ); ?></span>
|
||||
</span>
|
||||
<a class="next-page" title="<?php esc_attr_e( 'Go to the next page', 'woocommerce' ); ?>" href="#">›</a>
|
||||
<a class="last-page" title="<?php esc_attr_e( 'Go to the last page', 'woocommerce' ); ?>" href="#">»</a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
15
includes/admin/meta-boxes/views/html-product-download.php
Normal file
15
includes/admin/meta-boxes/views/html-product-download.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td class="sort"></td>
|
||||
<td class="file_name">
|
||||
<input type="text" class="input_text" placeholder="<?php esc_attr_e( 'File name', 'woocommerce' ); ?>" name="_wc_file_names[]" value="<?php echo esc_attr( $file['name'] ); ?>" />
|
||||
<input type="hidden" name="_wc_file_hashes[]" value="<?php echo esc_attr( $key ); ?>" />
|
||||
</td>
|
||||
<td class="file_url"><input type="text" class="input_text" placeholder="<?php esc_attr_e( 'http://', 'woocommerce' ); ?>" name="_wc_file_urls[]" value="<?php echo esc_attr( $file['file'] ); ?>" /></td>
|
||||
<td class="file_url_choose" width="1%"><a href="#" class="button upload_file_button" data-choose="<?php esc_attr_e( 'Choose file', 'woocommerce' ); ?>" data-update="<?php esc_attr_e( 'Insert file URL', 'woocommerce' ); ?>"><?php echo esc_html__( 'Choose file', 'woocommerce' ); ?></a></td>
|
||||
<td width="1%"><a href="#" class="delete"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a></td>
|
||||
</tr>
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td class="file_name">
|
||||
<input type="text" class="input_text" placeholder="<?php esc_attr_e( 'File name', 'woocommerce' ); ?>" name="_wc_variation_file_names[<?php echo esc_attr( $variation_id ); ?>][]" value="<?php echo esc_attr( $file['name'] ); ?>" />
|
||||
<input type="hidden" name="_wc_variation_file_hashes[<?php echo esc_attr( $variation_id ); ?>][]" value="<?php echo esc_attr( $key ); ?>" />
|
||||
</td>
|
||||
<td class="file_url"><input type="text" class="input_text" placeholder="<?php esc_attr_e( 'http://', 'woocommerce' ); ?>" name="_wc_variation_file_urls[<?php echo esc_attr( $variation_id ); ?>][]" value="<?php echo esc_attr( $file['file'] ); ?>" /></td>
|
||||
<td class="file_url_choose" width="1%"><a href="#" class="button upload_file_button" data-choose="<?php esc_attr_e( 'Choose file', 'woocommerce' ); ?>" data-update="<?php esc_attr_e( 'Insert file URL', 'woocommerce' ); ?>"><?php esc_html_e( 'Choose file', 'woocommerce' ); ?></a></td>
|
||||
<td width="1%"><a href="#" class="delete"><?php esc_html_e( 'Delete', 'woocommerce' ); ?></a></td>
|
||||
</tr>
|
489
includes/admin/meta-boxes/views/html-variation-admin.php
Normal file
489
includes/admin/meta-boxes/views/html-variation-admin.php
Normal file
@ -0,0 +1,489 @@
|
||||
<?php
|
||||
/**
|
||||
* Outputs a variation for editing.
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
* @var int $variation_id
|
||||
* @var WP_POST $variation
|
||||
* @var WC_Product_Variation $variation_object
|
||||
* @var array $variation_data array of variation data @deprecated 4.4.0.
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
?>
|
||||
<div class="woocommerce_variation wc-metabox closed">
|
||||
<h3>
|
||||
<a href="#" class="remove_variation delete" rel="<?php echo esc_attr( $variation_id ); ?>"><?php esc_html_e( 'Remove', 'woocommerce' ); ?></a>
|
||||
<div class="handlediv" aria-label="<?php esc_attr_e( 'Click to toggle', 'woocommerce' ); ?>"></div>
|
||||
<div class="tips sort" data-tip="<?php esc_attr_e( 'Drag and drop, or click to set admin variation order', 'woocommerce' ); ?>"></div>
|
||||
<strong>#<?php echo esc_html( $variation_id ); ?> </strong>
|
||||
<?php
|
||||
$attribute_values = $variation_object->get_attributes( 'edit' );
|
||||
|
||||
foreach ( $product_object->get_attributes( 'edit' ) as $attribute ) {
|
||||
if ( ! $attribute->get_variation() ) {
|
||||
continue;
|
||||
}
|
||||
$selected_value = isset( $attribute_values[ sanitize_title( $attribute->get_name() ) ] ) ? $attribute_values[ sanitize_title( $attribute->get_name() ) ] : '';
|
||||
?>
|
||||
<select name="attribute_<?php echo esc_attr( sanitize_title( $attribute->get_name() ) . "[{$loop}]" ); ?>">
|
||||
<option value="">
|
||||
<?php
|
||||
/* translators: %s: attribute label */
|
||||
printf( esc_html__( 'Any %s…', 'woocommerce' ), wc_attribute_label( $attribute->get_name() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
</option>
|
||||
<?php if ( $attribute->is_taxonomy() ) : ?>
|
||||
<?php foreach ( $attribute->get_terms() as $option ) : ?>
|
||||
<option <?php selected( $selected_value, $option->slug ); ?> value="<?php echo esc_attr( $option->slug ); ?>"><?php echo esc_html( apply_filters( 'woocommerce_variation_option_name', $option->name, $option, $attribute->get_name(), $product_object ) ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<?php foreach ( $attribute->get_options() as $option ) : ?>
|
||||
<option <?php selected( $selected_value, $option ); ?> value="<?php echo esc_attr( $option ); ?>"><?php echo esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute->get_name(), $product_object ) ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<input type="hidden" class="variable_post_id" name="variable_post_id[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $variation_id ); ?>" />
|
||||
<input type="hidden" class="variation_menu_order" name="variation_menu_order[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( $variation_object->get_menu_order( 'edit' ) ); ?>" />
|
||||
|
||||
<?php
|
||||
/**
|
||||
* Variations header action.
|
||||
*
|
||||
* @since 3.6.0
|
||||
*
|
||||
* @param WP_Post $variation Post data.
|
||||
*/
|
||||
do_action( 'woocommerce_variation_header', $variation );
|
||||
?>
|
||||
</h3>
|
||||
<div class="woocommerce_variable_attributes wc-metabox-content" style="display: none;">
|
||||
<div class="data">
|
||||
<p class="form-row form-row-first upload_image">
|
||||
<a href="#" class="upload_image_button tips <?php echo $variation_object->get_image_id( 'edit' ) ? 'remove' : ''; ?>" data-tip="<?php echo $variation_object->get_image_id( 'edit' ) ? esc_attr__( 'Remove this image', 'woocommerce' ) : esc_attr__( 'Upload an image', 'woocommerce' ); ?>" rel="<?php echo esc_attr( $variation_id ); ?>">
|
||||
<img src="<?php echo $variation_object->get_image_id( 'edit' ) ? esc_url( wp_get_attachment_thumb_url( $variation_object->get_image_id( 'edit' ) ) ) : esc_url( wc_placeholder_img_src() ); ?>" /><input type="hidden" name="upload_image_id[<?php echo esc_attr( $loop ); ?>]" class="upload_image_id" value="<?php echo esc_attr( $variation_object->get_image_id( 'edit' ) ); ?>" />
|
||||
</a>
|
||||
</p>
|
||||
<?php
|
||||
if ( wc_product_sku_enabled() ) {
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => "variable_sku{$loop}",
|
||||
'name' => "variable_sku[{$loop}]",
|
||||
'value' => $variation_object->get_sku( 'edit' ),
|
||||
'placeholder' => $variation_object->get_sku(),
|
||||
'label' => '<abbr title="' . esc_attr__( 'Stock Keeping Unit', 'woocommerce' ) . '">' . esc_html__( 'SKU', 'woocommerce' ) . '</abbr>',
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'SKU refers to a Stock-keeping unit, a unique identifier for each distinct product and service that can be purchased.', 'woocommerce' ),
|
||||
'wrapper_class' => 'form-row form-row-last',
|
||||
)
|
||||
);
|
||||
}
|
||||
?>
|
||||
<p class="form-row form-row-full options">
|
||||
<label>
|
||||
<?php esc_html_e( 'Enabled', 'woocommerce' ); ?>
|
||||
<input type="checkbox" class="checkbox" name="variable_enabled[<?php echo esc_attr( $loop ); ?>]" <?php checked( in_array( $variation_object->get_status( 'edit' ), array( 'publish', false ), true ), true ); ?> />
|
||||
</label>
|
||||
<label class="tips" data-tip="<?php esc_attr_e( 'Enable this option if access is given to a downloadable file upon purchase of a product', 'woocommerce' ); ?>">
|
||||
<?php esc_html_e( 'Downloadable', 'woocommerce' ); ?>
|
||||
<input type="checkbox" class="checkbox variable_is_downloadable" name="variable_is_downloadable[<?php echo esc_attr( $loop ); ?>]" <?php checked( $variation_object->get_downloadable( 'edit' ), true ); ?> />
|
||||
</label>
|
||||
<label class="tips" data-tip="<?php esc_attr_e( 'Enable this option if a product is not shipped or there is no shipping cost', 'woocommerce' ); ?>">
|
||||
<?php esc_html_e( 'Virtual', 'woocommerce' ); ?>
|
||||
<input type="checkbox" class="checkbox variable_is_virtual" name="variable_is_virtual[<?php echo esc_attr( $loop ); ?>]" <?php checked( $variation_object->get_virtual( 'edit' ), true ); ?> />
|
||||
</label>
|
||||
|
||||
<?php if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) : ?>
|
||||
<label class="tips" data-tip="<?php esc_attr_e( 'Enable this option to enable stock management at variation level', 'woocommerce' ); ?>">
|
||||
<?php esc_html_e( 'Manage stock?', 'woocommerce' ); ?>
|
||||
<input type="checkbox" class="checkbox variable_manage_stock" name="variable_manage_stock[<?php echo esc_attr( $loop ); ?>]" <?php checked( $variation_object->get_manage_stock(), true ); // Use view context so 'parent' is considered. ?> />
|
||||
</label>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php do_action( 'woocommerce_variation_options', $loop, $variation_data, $variation ); ?>
|
||||
</p>
|
||||
|
||||
<div class="variable_pricing">
|
||||
<?php
|
||||
$label = sprintf(
|
||||
/* translators: %s: currency symbol */
|
||||
__( 'Regular price (%s)', 'woocommerce' ),
|
||||
get_woocommerce_currency_symbol()
|
||||
);
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => "variable_regular_price_{$loop}",
|
||||
'name' => "variable_regular_price[{$loop}]",
|
||||
'value' => wc_format_localized_price( $variation_object->get_regular_price( 'edit' ) ),
|
||||
'label' => $label,
|
||||
'data_type' => 'price',
|
||||
'wrapper_class' => 'form-row form-row-first',
|
||||
'placeholder' => __( 'Variation price (required)', 'woocommerce' ),
|
||||
)
|
||||
);
|
||||
|
||||
$label = sprintf(
|
||||
/* translators: %s: currency symbol */
|
||||
__( 'Sale price (%s)', 'woocommerce' ),
|
||||
get_woocommerce_currency_symbol()
|
||||
);
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => "variable_sale_price{$loop}",
|
||||
'name' => "variable_sale_price[{$loop}]",
|
||||
'value' => wc_format_localized_price( $variation_object->get_sale_price( 'edit' ) ),
|
||||
'data_type' => 'price',
|
||||
'label' => $label . ' <a href="#" class="sale_schedule">' . esc_html__( 'Schedule', 'woocommerce' ) . '</a><a href="#" class="cancel_sale_schedule hidden">' . esc_html__( 'Cancel schedule', 'woocommerce' ) . '</a>',
|
||||
'wrapper_class' => 'form-row form-row-last',
|
||||
)
|
||||
);
|
||||
|
||||
$sale_price_dates_from_timestamp = $variation_object->get_date_on_sale_from( 'edit' ) ? $variation_object->get_date_on_sale_from( 'edit' )->getOffsetTimestamp() : false;
|
||||
$sale_price_dates_to_timestamp = $variation_object->get_date_on_sale_to( 'edit' ) ? $variation_object->get_date_on_sale_to( 'edit' )->getOffsetTimestamp() : false;
|
||||
|
||||
$sale_price_dates_from = $sale_price_dates_from_timestamp ? date_i18n( 'Y-m-d', $sale_price_dates_from_timestamp ) : '';
|
||||
$sale_price_dates_to = $sale_price_dates_to_timestamp ? date_i18n( 'Y-m-d', $sale_price_dates_to_timestamp ) : '';
|
||||
|
||||
echo '<div class="form-field sale_price_dates_fields hidden">
|
||||
<p class="form-row form-row-first">
|
||||
<label>' . esc_html__( 'Sale start date', 'woocommerce' ) . '</label>
|
||||
<input type="text" class="sale_price_dates_from" name="variable_sale_price_dates_from[' . esc_attr( $loop ) . ']" value="' . esc_attr( $sale_price_dates_from ) . '" placeholder="' . esc_attr_x( 'From…', 'placeholder', 'woocommerce' ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
|
||||
</p>
|
||||
<p class="form-row form-row-last">
|
||||
<label>' . esc_html__( 'Sale end date', 'woocommerce' ) . '</label>
|
||||
<input type="text" class="sale_price_dates_to" name="variable_sale_price_dates_to[' . esc_attr( $loop ) . ']" value="' . esc_attr( $sale_price_dates_to ) . '" placeholder="' . esc_attr_x( 'To…', 'placeholder', 'woocommerce' ) . ' YYYY-MM-DD" maxlength="10" pattern="' . esc_attr( apply_filters( 'woocommerce_date_input_html_pattern', '[0-9]{4}-(0[1-9]|1[012])-(0[1-9]|1[0-9]|2[0-9]|3[01])' ) ) . '" />
|
||||
</p>
|
||||
</div>';
|
||||
|
||||
/**
|
||||
* Variation options pricing action.
|
||||
*
|
||||
* @since 2.5.0
|
||||
*
|
||||
* @param int $loop Position in the loop.
|
||||
* @param array $variation_data Variation data.
|
||||
* @param WP_Post $variation Post data.
|
||||
*/
|
||||
do_action( 'woocommerce_variation_options_pricing', $loop, $variation_data, $variation );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php if ( 'yes' === get_option( 'woocommerce_manage_stock' ) ) : ?>
|
||||
<div class="show_if_variation_manage_stock" style="display: none;">
|
||||
<?php
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => "variable_stock{$loop}",
|
||||
'name' => "variable_stock[{$loop}]",
|
||||
'value' => wc_stock_amount( $variation_object->get_stock_quantity( 'edit' ) ),
|
||||
'label' => __( 'Stock quantity', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( "Enter a number to set stock quantity at the variation level. Use a variation's 'Manage stock?' check box above to enable/disable stock management at the variation level.", 'woocommerce' ),
|
||||
'type' => 'number',
|
||||
'custom_attributes' => array(
|
||||
'step' => 'any',
|
||||
),
|
||||
'data_type' => 'stock',
|
||||
'wrapper_class' => 'form-row form-row-first',
|
||||
)
|
||||
);
|
||||
|
||||
echo '<input type="hidden" name="variable_original_stock[' . esc_attr( $loop ) . ']" value="' . esc_attr( wc_stock_amount( $variation_object->get_stock_quantity( 'edit' ) ) ) . '" />';
|
||||
|
||||
woocommerce_wp_select(
|
||||
array(
|
||||
'id' => "variable_backorders{$loop}",
|
||||
'name' => "variable_backorders[{$loop}]",
|
||||
'value' => $variation_object->get_backorders( 'edit' ),
|
||||
'label' => __( 'Allow backorders?', 'woocommerce' ),
|
||||
'options' => wc_get_product_backorder_options(),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'If managing stock, this controls whether or not backorders are allowed. If enabled, stock quantity can go below 0.', 'woocommerce' ),
|
||||
'wrapper_class' => 'form-row form-row-last',
|
||||
)
|
||||
);
|
||||
|
||||
$low_stock_placeholder = ( $product_object->get_manage_stock() && '' !== $product_object->get_low_stock_amount() )
|
||||
? sprintf(
|
||||
/* translators: %d: Amount of stock left */
|
||||
esc_attr__( 'Parent product\'s threshold (%d)', 'woocommerce' ),
|
||||
esc_attr( $product_object->get_low_stock_amount() )
|
||||
)
|
||||
: sprintf(
|
||||
/* translators: %d: Amount of stock left */
|
||||
esc_attr__( 'Store-wide threshold (%d)', 'woocommerce' ),
|
||||
esc_attr( get_option( 'woocommerce_notify_low_stock_amount' ) )
|
||||
);
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => "variable_low_stock_amount{$loop}",
|
||||
'name' => "variable_low_stock_amount[{$loop}]",
|
||||
'value' => $variation_object->get_low_stock_amount( 'edit' ),
|
||||
'placeholder' => $low_stock_placeholder,
|
||||
'label' => __( 'Low stock threshold', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'When variation stock reaches this amount you will be notified by email. The default value for all variations can be set in the product Inventory tab. The shop default value can be set in Settings > Products > Inventory.', 'woocommerce' ),
|
||||
'type' => 'number',
|
||||
'custom_attributes' => array(
|
||||
'step' => 'any',
|
||||
),
|
||||
'wrapper_class' => 'form-row',
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Variation options inventory action.
|
||||
*
|
||||
* @since 2.5.0
|
||||
*
|
||||
* @param int $loop Position in the loop.
|
||||
* @param array $variation_data Variation data.
|
||||
* @param WP_Post $variation Post data.
|
||||
*/
|
||||
do_action( 'woocommerce_variation_options_inventory', $loop, $variation_data, $variation );
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div>
|
||||
<?php
|
||||
woocommerce_wp_select(
|
||||
array(
|
||||
'id' => "variable_stock_status{$loop}",
|
||||
'name' => "variable_stock_status[{$loop}]",
|
||||
'value' => $variation_object->get_stock_status( 'edit' ),
|
||||
'label' => __( 'Stock status', 'woocommerce' ),
|
||||
'options' => wc_get_product_stock_status_options(),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Controls whether or not the product is listed as "in stock" or "out of stock" on the frontend.', 'woocommerce' ),
|
||||
'wrapper_class' => 'form-row form-row-full variable_stock_status',
|
||||
)
|
||||
);
|
||||
|
||||
if ( wc_product_weight_enabled() ) {
|
||||
$label = sprintf(
|
||||
/* translators: %s: weight unit */
|
||||
__( 'Weight (%s)', 'woocommerce' ),
|
||||
esc_html( get_option( 'woocommerce_weight_unit' ) )
|
||||
);
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => "variable_weight{$loop}",
|
||||
'name' => "variable_weight[{$loop}]",
|
||||
'value' => wc_format_localized_decimal( $variation_object->get_weight( 'edit' ) ),
|
||||
'placeholder' => wc_format_localized_decimal( $product_object->get_weight() ),
|
||||
'label' => $label,
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Weight in decimal form', 'woocommerce' ),
|
||||
'type' => 'text',
|
||||
'data_type' => 'decimal',
|
||||
'wrapper_class' => 'form-row form-row-first hide_if_variation_virtual',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( wc_product_dimensions_enabled() ) {
|
||||
$parent_length = wc_format_localized_decimal( $product_object->get_length() );
|
||||
$parent_width = wc_format_localized_decimal( $product_object->get_width() );
|
||||
$parent_height = wc_format_localized_decimal( $product_object->get_height() );
|
||||
|
||||
?>
|
||||
<p class="form-field form-row dimensions_field hide_if_variation_virtual form-row-last">
|
||||
<label for="product_length">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: dimension unit */
|
||||
esc_html__( 'Dimensions (L×W×H) (%s)', 'woocommerce' ),
|
||||
esc_html( get_option( 'woocommerce_dimension_unit' ) )
|
||||
);
|
||||
?>
|
||||
</label>
|
||||
<?php echo wc_help_tip( __( 'Length x width x height in decimal form', 'woocommerce' ) ); ?>
|
||||
<span class="wrap">
|
||||
<input id="product_length" placeholder="<?php echo $parent_length ? esc_attr( $parent_length ) : esc_attr__( 'Length', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="variable_length[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_length( 'edit' ) ) ); ?>" />
|
||||
<input placeholder="<?php echo $parent_width ? esc_attr( $parent_width ) : esc_attr__( 'Width', 'woocommerce' ); ?>" class="input-text wc_input_decimal" size="6" type="text" name="variable_width[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_width( 'edit' ) ) ); ?>" />
|
||||
<input placeholder="<?php echo $parent_height ? esc_attr( $parent_height ) : esc_attr__( 'Height', 'woocommerce' ); ?>" class="input-text wc_input_decimal last" size="6" type="text" name="variable_height[<?php echo esc_attr( $loop ); ?>]" value="<?php echo esc_attr( wc_format_localized_decimal( $variation_object->get_height( 'edit' ) ) ); ?>" />
|
||||
</span>
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Variation options dimensions action.
|
||||
*
|
||||
* @since 2.5.0
|
||||
*
|
||||
* @param int $loop Position in the loop.
|
||||
* @param array $variation_data Variation data.
|
||||
* @param WP_Post $variation Post data.
|
||||
*/
|
||||
do_action( 'woocommerce_variation_options_dimensions', $loop, $variation_data, $variation );
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="form-row hide_if_variation_virtual form-row-full">
|
||||
<label><?php esc_html_e( 'Shipping class', 'woocommerce' ); ?></label>
|
||||
<?php
|
||||
wp_dropdown_categories(
|
||||
array(
|
||||
'taxonomy' => 'product_shipping_class',
|
||||
'hide_empty' => 0,
|
||||
'show_option_none' => __( 'Same as parent', 'woocommerce' ),
|
||||
'name' => 'variable_shipping_class[' . $loop . ']',
|
||||
'id' => '',
|
||||
'selected' => $variation_object->get_shipping_class_id( 'edit' ),
|
||||
)
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
|
||||
<?php
|
||||
if ( wc_tax_enabled() ) {
|
||||
woocommerce_wp_select(
|
||||
array(
|
||||
'id' => "variable_tax_class{$loop}",
|
||||
'name' => "variable_tax_class[{$loop}]",
|
||||
'value' => $variation_object->get_tax_class( 'edit' ),
|
||||
'label' => __( 'Tax class', 'woocommerce' ),
|
||||
'options' => array( 'parent' => __( 'Same as parent', 'woocommerce' ) ) + wc_get_product_tax_class_options(),
|
||||
'desc_tip' => 'true',
|
||||
'description' => __( 'Choose a tax class for this product. Tax classes are used to apply different tax rates specific to certain types of product.', 'woocommerce' ),
|
||||
'wrapper_class' => 'form-row form-row-full',
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Variation options tax action.
|
||||
*
|
||||
* @since 2.5.0
|
||||
*
|
||||
* @param int $loop Position in the loop.
|
||||
* @param array $variation_data Variation data.
|
||||
* @param WP_Post $variation Post data.
|
||||
*/
|
||||
do_action( 'woocommerce_variation_options_tax', $loop, $variation_data, $variation );
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div>
|
||||
<?php
|
||||
woocommerce_wp_textarea_input(
|
||||
array(
|
||||
'id' => "variable_description{$loop}",
|
||||
'name' => "variable_description[{$loop}]",
|
||||
'value' => $variation_object->get_description( 'edit' ),
|
||||
'label' => __( 'Description', 'woocommerce' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Enter an optional description for this variation.', 'woocommerce' ),
|
||||
'wrapper_class' => 'form-row form-row-full',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<div class="show_if_variation_downloadable" style="display: none;">
|
||||
<div class="form-row form-row-full downloadable_files">
|
||||
<label><?php esc_html_e( 'Downloadable files', 'woocommerce' ); ?></label>
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<div>
|
||||
<th><?php esc_html_e( 'Name', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the name of the download shown to the customer.', 'woocommerce' ) ); ?></th>
|
||||
<th colspan="2"><?php esc_html_e( 'File URL', 'woocommerce' ); ?> <?php echo wc_help_tip( __( 'This is the URL or absolute path to the file which customers will get access to. URLs entered here should already be encoded.', 'woocommerce' ) ); ?></th>
|
||||
<th> </th>
|
||||
</div>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$downloads = $variation_object->get_downloads( 'edit' );
|
||||
|
||||
if ( $downloads ) {
|
||||
foreach ( $downloads as $key => $file ) {
|
||||
include __DIR__ . '/html-product-variation-download.php';
|
||||
}
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<div>
|
||||
<th colspan="4">
|
||||
<a href="#" class="button insert" data-row="
|
||||
<?php
|
||||
$key = '';
|
||||
$file = array(
|
||||
'file' => '',
|
||||
'name' => '',
|
||||
);
|
||||
ob_start();
|
||||
require __DIR__ . '/html-product-variation-download.php';
|
||||
echo esc_attr( ob_get_clean() );
|
||||
?>
|
||||
"><?php esc_html_e( 'Add file', 'woocommerce' ); ?></a>
|
||||
</th>
|
||||
</div>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="show_if_variation_downloadable" style="display: none;">
|
||||
<?php
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => "variable_download_limit{$loop}",
|
||||
'name' => "variable_download_limit[{$loop}]",
|
||||
'value' => $variation_object->get_download_limit( 'edit' ) < 0 ? '' : $variation_object->get_download_limit( 'edit' ),
|
||||
'label' => __( 'Download limit', 'woocommerce' ),
|
||||
'placeholder' => __( 'Unlimited', 'woocommerce' ),
|
||||
'description' => __( 'Leave blank for unlimited re-downloads.', 'woocommerce' ),
|
||||
'type' => 'number',
|
||||
'desc_tip' => true,
|
||||
'custom_attributes' => array(
|
||||
'step' => '1',
|
||||
'min' => '0',
|
||||
),
|
||||
'wrapper_class' => 'form-row form-row-first',
|
||||
)
|
||||
);
|
||||
|
||||
woocommerce_wp_text_input(
|
||||
array(
|
||||
'id' => "variable_download_expiry{$loop}",
|
||||
'name' => "variable_download_expiry[{$loop}]",
|
||||
'value' => $variation_object->get_download_expiry( 'edit' ) < 0 ? '' : $variation_object->get_download_expiry( 'edit' ),
|
||||
'label' => __( 'Download expiry', 'woocommerce' ),
|
||||
'placeholder' => __( 'Never', 'woocommerce' ),
|
||||
'description' => __( 'Enter the number of days before a download link expires, or leave blank.', 'woocommerce' ),
|
||||
'type' => 'number',
|
||||
'desc_tip' => true,
|
||||
'custom_attributes' => array(
|
||||
'step' => '1',
|
||||
'min' => '0',
|
||||
),
|
||||
'wrapper_class' => 'form-row form-row-last',
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Variation options download action.
|
||||
*
|
||||
* @since 2.5.0
|
||||
*
|
||||
* @param int $loop Position in the loop.
|
||||
* @param array $variation_data Variation data.
|
||||
* @param WP_Post $variation Post data.
|
||||
*/
|
||||
do_action( 'woocommerce_variation_options_download', $loop, $variation_data, $variation );
|
||||
?>
|
||||
</div>
|
||||
<?php do_action( 'woocommerce_product_after_variable_attributes', $loop, $variation_data, $variation ); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Reference in New Issue
Block a user