From ded4b7404da974b12a9e60eeb53ebbf64f210364 Mon Sep 17 00:00:00 2001 From: Mike Jolley Date: Wed, 4 Jun 2014 11:16:19 +0100 Subject: [PATCH] Admin changes for #5046 - Removed post type classes. Since they were always loaded, there was no benefit having them split up. Combined meaning less hooked in methods. - Stopped loading some function files and sessions in the admin area. They are not needed there. - Made a few admin page classes static as they are stateless --- includes/admin/class-wc-admin-addons.php | 10 +- includes/admin/class-wc-admin-attributes.php | 18 +- includes/admin/class-wc-admin-menus.php | 14 +- .../class-wc-admin-meta-boxes.php | 0 includes/admin/class-wc-admin-notices.php | 3 +- .../class-wc-admin-permalink-settings.php | 4 +- includes/admin/class-wc-admin-post-types.php | 1851 ++++++++++++++++- includes/admin/class-wc-admin-status.php | 30 +- includes/admin/class-wc-admin-taxonomies.php | 15 + includes/admin/class-wc-admin.php | 13 +- .../class-wc-meta-box-coupon-data.php | 0 .../class-wc-meta-box-order-actions.php | 0 .../class-wc-meta-box-order-data.php | 0 .../class-wc-meta-box-order-downloads.php | 0 .../class-wc-meta-box-order-items.php | 0 .../class-wc-meta-box-order-notes.php | 0 .../class-wc-meta-box-order-reviews.php | 0 .../class-wc-meta-box-order-totals.php | 0 .../class-wc-meta-box-product-data.php | 0 .../class-wc-meta-box-product-images.php | 0 ...-wc-meta-box-product-short-description.php | 0 .../views/html-order-download-permission.php | 0 .../meta-boxes/views/html-order-fee.php | 0 .../meta-boxes/views/html-order-item.php | 0 .../meta-boxes/views/html-order-shipping.php | 0 .../meta-boxes/views/html-order-tax.php | 0 .../views/html-product-download.php | 0 .../views/html-product-variation-download.php | 0 .../meta-boxes/views/html-variation-admin.php | 0 .../post-types/class-wc-admin-cpt-product.php | 1205 ----------- .../class-wc-admin-cpt-shop_coupon.php | 232 --- .../class-wc-admin-cpt-shop_order.php | 724 ------- .../admin/post-types/class-wc-admin-cpt.php | 50 - .../views/html-admin-page-status-report.php | 6 +- .../admin/views/html-admin-page-status.php | 6 +- includes/class-wc-ajax.php | 12 +- includes/class-wc-post-data.php | 47 + includes/wc-core-functions.php | 28 +- woocommerce.php | 32 +- 39 files changed, 1996 insertions(+), 2304 deletions(-) rename includes/admin/{post-types => }/class-wc-admin-meta-boxes.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-coupon-data.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-order-actions.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-order-data.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-order-downloads.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-order-items.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-order-notes.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-order-reviews.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-order-totals.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-product-data.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-product-images.php (100%) rename includes/admin/{post-types => }/meta-boxes/class-wc-meta-box-product-short-description.php (100%) rename includes/admin/{post-types => }/meta-boxes/views/html-order-download-permission.php (100%) rename includes/admin/{post-types => }/meta-boxes/views/html-order-fee.php (100%) rename includes/admin/{post-types => }/meta-boxes/views/html-order-item.php (100%) rename includes/admin/{post-types => }/meta-boxes/views/html-order-shipping.php (100%) rename includes/admin/{post-types => }/meta-boxes/views/html-order-tax.php (100%) rename includes/admin/{post-types => }/meta-boxes/views/html-product-download.php (100%) rename includes/admin/{post-types => }/meta-boxes/views/html-product-variation-download.php (100%) rename includes/admin/{post-types => }/meta-boxes/views/html-variation-admin.php (100%) delete mode 100644 includes/admin/post-types/class-wc-admin-cpt-product.php delete mode 100644 includes/admin/post-types/class-wc-admin-cpt-shop_coupon.php delete mode 100644 includes/admin/post-types/class-wc-admin-cpt-shop_order.php delete mode 100644 includes/admin/post-types/class-wc-admin-cpt.php diff --git a/includes/admin/class-wc-admin-addons.php b/includes/admin/class-wc-admin-addons.php index b11321467dc..255dedd02b8 100644 --- a/includes/admin/class-wc-admin-addons.php +++ b/includes/admin/class-wc-admin-addons.php @@ -10,8 +10,6 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly -if ( ! class_exists( 'WC_Admin_Addons' ) ) : - /** * WC_Admin_Addons Class */ @@ -20,7 +18,7 @@ class WC_Admin_Addons { /** * Handles output of the reports page in admin. */ - public function output() { + public static function output() { if ( false === ( $addons = get_transient( 'woocommerce_addons_data' ) ) ) { $addons_json = wp_remote_get( 'http://d3t0oesq8995hv.cloudfront.net/woocommerce-addons.json', array( 'user-agent' => 'WooCommerce Addons Page' ) ); @@ -36,8 +34,4 @@ class WC_Admin_Addons { include_once( 'views/html-admin-page-addons.php' ); } -} - -endif; - -return new WC_Admin_Addons(); \ No newline at end of file +} \ No newline at end of file diff --git a/includes/admin/class-wc-admin-attributes.php b/includes/admin/class-wc-admin-attributes.php index 507d32bfbc4..c856cce8a0a 100644 --- a/includes/admin/class-wc-admin-attributes.php +++ b/includes/admin/class-wc-admin-attributes.php @@ -12,8 +12,6 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly -if ( ! class_exists( 'WC_Admin_Attributes' ) ) : - /** * WC_Admin_Attributes Class */ @@ -25,7 +23,7 @@ class WC_Admin_Attributes { * Shows the created attributes and lets you add new ones or edit existing ones. * The added attributes are stored in the database and can be used for layered navigation. */ - public function output() { + public static function output() { global $wpdb, $woocommerce; // Action to perform: add, edit, delete or none @@ -206,9 +204,9 @@ class WC_Admin_Attributes { // Show admin interface if ( ! empty( $_GET['edit'] ) ) - $this->edit_attribute(); + self::edit_attribute(); else - $this->add_attribute(); + self::add_attribute(); } /** @@ -216,7 +214,7 @@ class WC_Admin_Attributes { * * Shows the interface for changing an attributes type between select and text */ - public function edit_attribute() { + public static function edit_attribute() { global $wpdb; $edit = absint( $_GET['edit'] ); @@ -292,7 +290,7 @@ class WC_Admin_Attributes { * * Shows the interface for adding new attributes */ - public function add_attribute() { + public static function add_attribute() { ?>

@@ -423,8 +421,4 @@ class WC_Admin_Attributes {
output(); + WC_Admin_Attributes::output(); } /** * Init the status page */ public function status_page() { - $page = include( 'class-wc-admin-status.php' ); - $page->output(); + WC_Admin_Status::output(); } /** * Init the addons page */ public function addons_page() { - $page = include( 'class-wc-admin-addons.php' ); - $page->output(); + WC_Admin_Addons::output(); } } diff --git a/includes/admin/post-types/class-wc-admin-meta-boxes.php b/includes/admin/class-wc-admin-meta-boxes.php similarity index 100% rename from includes/admin/post-types/class-wc-admin-meta-boxes.php rename to includes/admin/class-wc-admin-meta-boxes.php diff --git a/includes/admin/class-wc-admin-notices.php b/includes/admin/class-wc-admin-notices.php index c3c5246e166..0f0fd615889 100644 --- a/includes/admin/class-wc-admin-notices.php +++ b/includes/admin/class-wc-admin-notices.php @@ -99,8 +99,7 @@ class WC_Admin_Notices { return; } - $status = include( 'class-wc-admin-status.php' ); - $core_templates = $status->scan_template_files( WC()->plugin_path() . '/templates' ); + $core_templates = WC_Admin_Status::scan_template_files( WC()->plugin_path() . '/templates' ); $outdated = false; foreach ( $core_templates as $file ) { diff --git a/includes/admin/class-wc-admin-permalink-settings.php b/includes/admin/class-wc-admin-permalink-settings.php index 493284bae62..acb7a43fa15 100644 --- a/includes/admin/class-wc-admin-permalink-settings.php +++ b/includes/admin/class-wc-admin-permalink-settings.php @@ -21,8 +21,8 @@ class WC_Admin_Permalink_Settings { * Hook in tabs. */ public function __construct() { - add_action( 'admin_init', array( $this, 'settings_init' ) ); - add_action( 'admin_init', array( $this, 'settings_save' ) ); + $this->settings_init(); + $this->settings_save(); } /** diff --git a/includes/admin/class-wc-admin-post-types.php b/includes/admin/class-wc-admin-post-types.php index ae9dabd4313..12480d278e3 100644 --- a/includes/admin/class-wc-admin-post-types.php +++ b/includes/admin/class-wc-admin-post-types.php @@ -14,6 +14,8 @@ if ( ! class_exists( 'WC_Admin_Post_Types' ) ) : /** * WC_Admin_Post_Types Class + * + * Handles the edit posts views and some functionality on the edit post screen for WC post types. */ class WC_Admin_Post_Types { @@ -21,27 +23,1607 @@ class WC_Admin_Post_Types { * Constructor */ public function __construct() { - add_action( 'admin_init', array( $this, 'include_post_type_handlers' ) ); add_filter( 'post_updated_messages', array( $this, 'post_updated_messages' ) ); add_action( 'admin_print_scripts', array( $this, 'disable_autosave' ) ); + // WP List table columns. Defined here so they are always available for events such as inline editing. + add_filter( 'manage_edit-product_columns', array( $this, 'product_columns' ) ); + add_filter( 'manage_edit-shop_coupon_columns', array( $this, 'shop_coupon_columns' ) ); + add_filter( 'manage_edit-shop_order_columns', array( $this, 'shop_order_columns' ) ); + + add_action( 'manage_product_posts_custom_column', array( $this, 'render_product_columns' ), 2 ); + add_action( 'manage_shop_coupon_posts_custom_column', array( $this, 'render_shop_coupon_columns' ), 2 ); + add_action( 'manage_shop_order_posts_custom_column', array( $this, 'render_shop_order_columns' ), 2 ); + + add_filter( 'manage_edit-product_sortable_columns', array( $this, 'product_sortable_columns' ) ); + add_filter( 'manage_edit-shop_coupon_sortable_columns', array( $this, 'shop_coupon_sortable_columns' ) ); + add_filter( 'manage_edit-shop_order_sortable_columns', array( $this, 'shop_order_sortable_columns' ) ); + + add_filter( 'bulk_actions-edit-shop_order', array( $this, 'shop_order_bulk_actions' ) ); + + add_filter( 'views_edit-product', array( $this, 'product_sorting_link' ) ); + + // Bulk / quick edit + add_action( 'bulk_edit_custom_box', array( $this, 'bulk_edit' ), 10, 2 ); + add_action( 'quick_edit_custom_box', array( $this, 'quick_edit' ), 10, 2 ); + add_action( 'save_post', array( $this, 'bulk_and_quick_edit_save_post' ), 10, 2 ); + add_action( 'admin_footer', array( $this, 'bulk_admin_footer' ), 10 ); + add_action( 'load-edit.php', array( $this, 'bulk_action' ) ); + add_action( 'admin_notices', array( $this, 'bulk_admin_notices' ) ); + + // Order Search + add_filter( 'get_search_query', array( $this, 'shop_order_search_label' ) ); + add_filter( 'query_vars', array( $this, 'add_custom_query_var' ) ); + add_action( 'parse_query', array( $this, 'shop_order_search_custom_fields' ) ); + + // Filters + add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) ); + add_filter( 'request', array( $this, 'request_query' ) ); + add_filter( 'parse_query', array( $this, 'product_filters_query' ) ); + add_filter( 'posts_search', array( $this, 'product_search' ) ); + // Status transitions add_action( 'delete_post', array( $this, 'delete_post' ) ); add_action( 'wp_trash_post', array( $this, 'trash_post' ) ); add_action( 'untrash_post', array( $this, 'untrash_post' ) ); + add_action( 'before_delete_post', array( $this, 'delete_order_items' ) ); + + // Edit post screens + add_filter( 'media_view_strings', array( $this, 'media_view_strings' ), 10, 2 ); + add_filter( 'enter_title_here', array( $this, 'enter_title_here' ), 1, 2 ); + add_action( 'edit_form_after_title', array( $this, 'edit_form_after_title' ) ); + add_filter( 'media_view_strings', array( $this, 'change_insert_into_post' ) ); + add_action( 'post_submitbox_misc_actions', array( $this, 'product_data_visibility' ) ); + + $this->change_featured_image_text(); + + // Uploads + add_filter( 'upload_dir', array( $this, 'upload_dir' ) ); + add_action( 'media_upload_downloadable_product', array( $this, 'media_upload_downloadable_product' ) ); + + if ( ! function_exists( 'duplicate_post_plugin_activation' ) ) { + include( 'class-wc-admin-duplicate-product.php' ); + } + + include_once( 'class-wc-admin-meta-boxes.php' ); + + // Download permissions + add_action( 'woocommerce_process_product_file_download_paths', array( $this, 'process_product_file_download_paths' ), 10, 3 ); } /** - * Conditonally load classes and functions only needed when viewing a post type. + * Define custom columns for products + * @param array $existing_columns + * @return array */ - public function include_post_type_handlers() { - include( 'post-types/class-wc-admin-meta-boxes.php' ); - include( 'post-types/class-wc-admin-cpt-product.php' ); - include( 'post-types/class-wc-admin-cpt-shop_order.php' ); - include( 'post-types/class-wc-admin-cpt-shop_coupon.php' ); + public function product_columns( $existing_columns ) { + if ( empty( $existing_columns ) && ! is_array( $existing_columns ) ) { + $existing_columns = array(); + } - if ( ! function_exists( 'duplicate_post_plugin_activation' ) ) - include( 'class-wc-admin-duplicate-product.php' ); + unset( $existing_columns['title'], $existing_columns['comments'], $existing_columns['date'] ); + + $columns = array(); + $columns['cb'] = ''; + $columns['thumb'] = '' . __( 'Image', 'woocommerce' ) . ''; + $columns['name'] = __( 'Name', 'woocommerce' ); + + if ( wc_product_sku_enabled() ) { + $columns['sku'] = __( 'SKU', 'woocommerce' ); + } + + if ( 'yes' == get_option( 'woocommerce_manage_stock' ) ) { + $columns['is_in_stock'] = __( 'Stock', 'woocommerce' ); + } + + $columns['price'] = __( 'Price', 'woocommerce' ); + $columns['product_cat'] = __( 'Categories', 'woocommerce' ); + $columns['product_tag'] = __( 'Tags', 'woocommerce' ); + $columns['featured'] = '' . __( 'Featured', 'woocommerce' ) . ''; + $columns['product_type'] = '' . __( 'Type', 'woocommerce' ) . ''; + $columns['date'] = __( 'Date', 'woocommerce' ); + + return array_merge( $columns, $existing_columns ); + } + + /** + * Define custom columns for coupons + * @param array $existing_columns + * @return array + */ + public function shop_coupon_columns( $existing_columns ) { + $columns = array(); + $columns["cb"] = ""; + $columns["coupon_code"] = __( 'Code', 'woocommerce' ); + $columns["type"] = __( 'Coupon type', 'woocommerce' ); + $columns["amount"] = __( 'Coupon amount', 'woocommerce' ); + $columns["description"] = __( 'Description', 'woocommerce' ); + $columns["products"] = __( 'Product IDs', 'woocommerce' ); + $columns["usage"] = __( 'Usage / Limit', 'woocommerce' ); + $columns["expiry_date"] = __( 'Expiry date', 'woocommerce' ); + + return $columns; + } + + /** + * Define custom columns for orders + * @param array $existing_columns + * @return array + */ + public function shop_order_columns( $existing_columns ) { + $columns = array(); + $columns['cb'] = ''; + $columns['order_status'] = '' . esc_attr__( 'Status', 'woocommerce' ) . ''; + $columns['order_title'] = __( 'Order', 'woocommerce' ); + $columns['order_items'] = __( 'Purchased', 'woocommerce' ); + $columns['shipping_address'] = __( 'Ship to', 'woocommerce' ); + $columns['customer_message'] = '' . esc_attr__( 'Customer Message', 'woocommerce' ) . ''; + $columns['order_notes'] = '' . esc_attr__( 'Order Notes', 'woocommerce' ) . ''; + $columns['order_date'] = __( 'Date', 'woocommerce' ); + $columns['order_total'] = __( 'Total', 'woocommerce' ); + $columns['order_actions'] = __( 'Actions', 'woocommerce' ); + + return $columns; + } + + /** + * Ouput custom columns for products + * @param string $column + */ + public function render_product_columns( $column ) { + global $post, $woocommerce, $the_product; + + if ( empty( $the_product ) || $the_product->id != $post->ID ) { + $the_product = get_product( $post ); + } + + switch ( $column ) { + case 'thumb' : + echo '' . $the_product->get_image() . ''; + break; + case 'name' : + $edit_link = get_edit_post_link( $post->ID ); + $title = _draft_or_post_title(); + $post_type_object = get_post_type_object( $post->post_type ); + $can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID ); + + echo '' . $title.''; + + _post_states( $post ); + + echo ''; + + if ( $post->post_parent > 0 ) { + echo '  ← '. get_the_title( $post->post_parent ) .''; + } + + // Excerpt view + if ( isset( $_GET['mode'] ) && 'excerpt' == $_GET['mode'] ) { + echo apply_filters( 'the_excerpt', $post->post_excerpt ); + } + + // Get actions + $actions = array(); + + $actions['id'] = 'ID: ' . $post->ID; + + if ( $can_edit_post && 'trash' != $post->post_status ) { + $actions['edit'] = '' . __( 'Edit', 'woocommerce' ) . ''; + $actions['inline hide-if-no-js'] = '' . __( 'Quick Edit', 'woocommerce' ) . ''; + } + if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) { + if ( 'trash' == $post->post_status ) { + $actions['untrash'] = '' . __( 'Restore', 'woocommerce' ) . ''; + } elseif ( EMPTY_TRASH_DAYS ) { + $actions['trash'] = '' . __( 'Trash', 'woocommerce' ) . ''; + } + + if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) { + $actions['delete'] = '' . __( 'Delete Permanently', 'woocommerce' ) . ''; + } + } + if ( $post_type_object->public ) { + if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) { + if ( $can_edit_post ) + $actions['view'] = '' . __( 'Preview', 'woocommerce' ) . ''; + } elseif ( 'trash' != $post->post_status ) { + $actions['view'] = '' . __( 'View', 'woocommerce' ) . ''; + } + } + + $actions = apply_filters( 'post_row_actions', $actions, $post ); + + echo '
'; + + $i = 0; + $action_count = sizeof($actions); + + foreach ( $actions as $action => $link ) { + ++$i; + ( $i == $action_count ) ? $sep = '' : $sep = ' | '; + echo '' . $link . $sep . ''; + } + echo '
'; + + get_inline_data( $post ); + + /* Custom inline data for woocommerce */ + echo ' + + '; + + break; + case 'sku' : + echo $the_product->get_sku() ? $the_product->get_sku() : ''; + break; + case 'product_type' : + if ( 'grouped' == $the_product->product_type ) { + echo ''; + } elseif ( 'external' == $the_product->product_type ) { + echo ''; + } elseif ( 'simple' == $the_product->product_type ) { + + if ( $the_product->is_virtual() ) { + echo ''; + } elseif ( $the_product->is_downloadable() ) { + echo ''; + } else { + echo ''; + } + + } elseif ( 'variable' == $the_product->product_type ) { + echo ''; + } else { + // Assuming that we have other types in future + echo ''; + } + break; + case 'price' : + echo $the_product->get_price_html() ? $the_product->get_price_html() : ''; + break; + case 'product_cat' : + case 'product_tag' : + if ( ! $terms = get_the_terms( $post->ID, $column ) ) { + echo ''; + } else { + foreach ( $terms as $term ) { + $termlist[] = '' . $term->name . ''; + } + + echo implode( ', ', $termlist ); + } + break; + case 'featured' : + $url = wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_feature_product&product_id=' . $post->ID ), 'woocommerce-feature-product' ); + echo ''; + if ( $the_product->is_featured() ) { + echo '' . __( 'Yes', 'woocommerce' ) . ''; + } else { + echo '' . __( 'No', 'woocommerce' ) . ''; + } + echo ''; + break; + case 'is_in_stock' : + + if ( $the_product->is_in_stock() ) { + echo '' . __( 'In stock', 'woocommerce' ) . ''; + } else { + echo '' . __( 'Out of stock', 'woocommerce' ) . ''; + } + + if ( $the_product->managing_stock() ) { + echo ' × ' . $the_product->get_total_stock(); + } + + break; + + default : + break; + } + } + + /** + * Output custom columns for coupons + * @param string $column + */ + public function render_shop_coupon_columns( $column ) { + global $post, $woocommerce; + + switch ( $column ) { + case "coupon_code" : + $edit_link = get_edit_post_link( $post->ID ); + $title = _draft_or_post_title(); + $post_type_object = get_post_type_object( $post->post_type ); + $can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID ); + + echo '
' . esc_html( $title ). '
'; + + _post_states( $post ); + + // Get actions + $actions = array(); + + if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) { + if ( 'trash' == $post->post_status ) + $actions['untrash'] = "ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore', 'woocommerce' ) . ""; + elseif ( EMPTY_TRASH_DAYS ) + $actions['trash'] = "" . __( 'Trash', 'woocommerce' ) . ""; + if ( 'trash' == $post->post_status || !EMPTY_TRASH_DAYS ) + $actions['delete'] = "" . __( 'Delete Permanently', 'woocommerce' ) . ""; + } + + $actions = apply_filters( 'post_row_actions', $actions, $post ); + + echo '
'; + + $i = 0; + $action_count = sizeof($actions); + + foreach ( $actions as $action => $link ) { + ++$i; + ( $i == $action_count ) ? $sep = '' : $sep = ' | '; + echo "$link$sep"; + } + echo '
'; + + break; + case "type" : + echo esc_html( wc_get_coupon_type( get_post_meta( $post->ID, 'discount_type', true ) ) ); + break; + case "amount" : + echo esc_html( get_post_meta( $post->ID, 'coupon_amount', true ) ); + break; + case "products" : + $product_ids = get_post_meta( $post->ID, 'product_ids', true ); + $product_ids = $product_ids ? array_map( 'absint', explode( ',', $product_ids ) ) : array(); + if ( sizeof( $product_ids ) > 0 ) + echo esc_html( implode( ', ', $product_ids ) ); + else + echo '–'; + break; + case "usage_limit" : + $usage_limit = get_post_meta( $post->ID, 'usage_limit', true ); + + if ( $usage_limit ) + echo esc_html( $usage_limit ); + else + echo '–'; + break; + case "usage" : + $usage_count = absint( get_post_meta( $post->ID, 'usage_count', true ) ); + $usage_limit = esc_html( get_post_meta($post->ID, 'usage_limit', true) ); + + if ( $usage_limit ) + printf( __( '%s / %s', 'woocommerce' ), $usage_count, $usage_limit ); + else + printf( __( '%s / ∞', 'woocommerce' ), $usage_count ); + break; + case "expiry_date" : + $expiry_date = get_post_meta($post->ID, 'expiry_date', true); + + if ( $expiry_date ) + echo esc_html( date_i18n( 'F j, Y', strtotime( $expiry_date ) ) ); + else + echo '–'; + break; + case "description" : + echo wp_kses_post( $post->post_excerpt ); + break; + } + } + + /** + * Output custom columns for coupons + * @param string $column + */ + public function render_shop_order_columns( $column ) { + global $post, $woocommerce, $the_order; + + if ( empty( $the_order ) || $the_order->id != $post->ID ) { + $the_order = new WC_Order( $post->ID ); + } + + switch ( $column ) { + case 'order_status' : + + printf( '%s', sanitize_title( $the_order->get_status() ), wc_get_order_status_name( $the_order->get_status() ), wc_get_order_status_name( $the_order->get_status() ) ); + + break; + case 'order_date' : + + if ( '0000-00-00 00:00:00' == $post->post_date ) { + $t_time = $h_time = __( 'Unpublished', 'woocommerce' ); + } else { + $t_time = get_the_time( __( 'Y/m/d g:i:s A', 'woocommerce' ), $post ); + $gmt_time = strtotime( $post->post_date_gmt . ' UTC' ); + $time_diff = current_time( 'timestamp', 1 ) - $gmt_time; + $h_time = get_the_time( __( 'Y/m/d', 'woocommerce' ), $post ); + } + + echo '' . esc_html( apply_filters( 'post_date_column_time', $h_time, $post ) ) . ''; + + break; + case 'customer_message' : + + if ( $the_order->customer_message ) + echo '' . __( 'Yes', 'woocommerce' ) . ''; + else + echo ''; + + break; + case 'billing_address' : + if ( $the_order->get_formatted_billing_address() ) + echo '' . esc_html( preg_replace( '##i', ', ', $the_order->get_formatted_billing_address() ) ) .''; + else + echo '–'; + + if ( $the_order->payment_method_title ) + echo '' . __( 'Via', 'woocommerce' ) . ' ' . esc_html( $the_order->payment_method_title ) . ''; + break; + case 'order_items' : + + printf( '' . _n( '%d item', '%d items', sizeof( $the_order->get_items() ), 'woocommerce' ) . '', sizeof( $the_order->get_items() ) ); + + if ( sizeof( $the_order->get_items() ) > 0 ) { + + echo ''; + + foreach ( $the_order->get_items() as $item ) { + $_product = apply_filters( 'woocommerce_order_item_product', $the_order->get_product_from_item( $item ), $item ); + $item_meta = new WC_Order_Item_Meta( $item['item_meta'] ); + $item_meta_html = $item_meta->display( true, true ); + ?> + + + + + '; + + } else echo '–'; + break; + case 'shipping_address' : + if ( $the_order->get_formatted_shipping_address() ) + echo ''. esc_html( preg_replace( '##i', ', ', $the_order->get_formatted_shipping_address() ) ) .''; + else + echo '–'; + + if ( $the_order->get_shipping_method() ) + echo '' . __( 'Via', 'woocommerce' ) . ' ' . esc_html( $the_order->get_shipping_method() ) . ''; + + break; + case 'order_notes' : + + if ( $post->comment_count ) { + + // check the status of the post + ( $post->post_status !== 'trash' ) ? $status = '' : $status = 'post-trashed'; + + $latest_notes = get_comments( array( + 'post_id' => $post->ID, + 'number' => 1, + 'status' => $status + ) ); + + $latest_note = current( $latest_notes ); + + if ( $post->comment_count == 1 ) { + echo '' . __( 'Yes', 'woocommerce' ) . ''; + } else { + $note_tip = isset( $latest_note->comment_content ) ? esc_attr( $latest_note->comment_content . '' . sprintf( _n( 'plus %d other note', 'plus %d other notes', ( $post->comment_count - 1 ), 'woocommerce' ), ( $post->comment_count - 1 ) ) . '' ) : sprintf( _n( '%d note', '%d notes', $post->comment_count, 'woocommerce' ), $post->comment_count ); + + echo '' . __( 'Yes', 'woocommerce' ) . ''; + } + + } else { + echo ''; + } + + break; + case 'order_total' : + echo esc_html( strip_tags( $the_order->get_formatted_order_total() ) ); + + if ( $the_order->payment_method_title ) { + echo '' . __( 'Via', 'woocommerce' ) . ' ' . esc_html( $the_order->payment_method_title ) . ''; + } + break; + case 'order_title' : + + $customer_tip = ''; + + if ( $address = $the_order->get_formatted_billing_address() ) { + $customer_tip .= __( 'Billing:', 'woocommerce' ) . ' ' . $address . '

'; + } + + if ( $the_order->billing_phone ) { + $customer_tip .= __( 'Tel:', 'woocommerce' ) . ' ' . $the_order->billing_phone; + } + + echo '
'; + + if ( $the_order->user_id ) { + $user_info = get_userdata( $the_order->user_id ); + } + + if ( ! empty( $user_info ) ) { + + $username = ''; + + if ( $user_info->first_name || $user_info->last_name ) { + $username .= esc_html( ucfirst( $user_info->first_name ) . ' ' . ucfirst( $user_info->last_name ) ); + } else { + $username .= esc_html( ucfirst( $user_info->display_name ) ); + } + + $username .= ''; + + } else { + if ( $the_order->billing_first_name || $the_order->billing_last_name ) { + $username = trim( $the_order->billing_first_name . ' ' . $the_order->billing_last_name ); + } else { + $username = __( 'Guest', 'woocommerce' ); + } + } + + printf( __( '%s by %s', 'woocommerce' ), '' . esc_attr( $the_order->get_order_number() ) . '', $username ); + + if ( $the_order->billing_email ) { + echo ''; + } + + echo '
'; + + break; + case 'order_actions' : + + ?>

+ has_status( array( 'pending', 'on-hold' ) ) ) { + $actions['processing'] = array( + 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_processing&order_id=' . $post->ID ), 'woocommerce-mark-order-processing' ), + 'name' => __( 'Processing', 'woocommerce' ), + 'action' => "processing" + ); + } + + if ( $the_order->has_status( array( 'pending', 'on-hold', 'processing' ) ) ) { + $actions['complete'] = array( + 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_complete&order_id=' . $post->ID ), 'woocommerce-mark-order-complete' ), + 'name' => __( 'Complete', 'woocommerce' ), + 'action' => "complete" + ); + } + + $actions['view'] = array( + 'url' => admin_url( 'post.php?post=' . $post->ID . '&action=edit' ), + 'name' => __( 'View', 'woocommerce' ), + 'action' => "view" + ); + + $actions = apply_filters( 'woocommerce_admin_order_actions', $actions, $the_order ); + + foreach ( $actions as $action ) { + printf( '%s', esc_attr( $action['action'] ), esc_url( $action['url'] ), esc_attr( $action['name'] ), esc_attr( $action['name'] ) ); + } + + do_action( 'woocommerce_admin_order_actions_end', $the_order ); + ?> +

'price', + 'featured' => 'featured', + 'sku' => 'sku', + 'name' => 'title' + ); + return wp_parse_args( $custom, $columns ); + } + + /** + * Make columns sortable - https://gist.github.com/906872 + * + * @param array $columns + * @return array + */ + public function shop_coupon_sortable_columns( $columns ) { + return $columns; + } + + /** + * Make columns sortable - https://gist.github.com/906872 + * + * @param array $columns + * @return array + */ + public function shop_order_sortable_columns( $columns ) { + $custom = array( + 'order_title' => 'ID', + 'order_total' => 'order_total', + 'order_date' => 'date' + ); + unset( $columns['comments'] ); + + return wp_parse_args( $custom, $columns ); + } + + /** + * Remove edit from the bulk actions. + * + * @param array $actions + * @return array + */ + public function shop_order_bulk_actions( $actions ) { + if ( isset( $actions['edit'] ) ) { + unset( $actions['edit'] ); + } + return $actions; + } + + /** + * Product sorting link + * + * Based on Simple Page Ordering by 10up (http://wordpress.org/extend/plugins/simple-page-ordering/) + * + * @param array $views + * @return array + */ + public function product_sorting_link( $views ) { + global $post_type, $wp_query; + + if ( ! current_user_can('edit_others_pages') ) { + return $views; + } + + $class = ( isset( $wp_query->query['orderby'] ) && $wp_query->query['orderby'] == 'menu_order title' ) ? 'current' : ''; + $query_string = remove_query_arg(array( 'orderby', 'order' )); + $query_string = add_query_arg( 'orderby', urlencode('menu_order title'), $query_string ); + $query_string = add_query_arg( 'order', urlencode('ASC'), $query_string ); + $views['byorder'] = '' . __( 'Sort Products', 'woocommerce' ) . ''; + + return $views; + } + + + /** + * Custom bulk edit - form + * + * @access public + * @param mixed $column_name + * @param mixed $post_type + */ + public function bulk_edit( $column_name, $post_type ) { + if ( 'price' != $column_name || 'product' != $post_type ) { + return; + } + + include( WC()->plugin_path() . '/includes/admin/views/html-bulk-edit-product.php' ); + } + + /** + * Custom quick edit - form + * + * @access public + * @param mixed $column_name + * @param mixed $post_type + */ + public function quick_edit( $column_name, $post_type ) { + if ( 'price' != $column_name || 'product' != $post_type ) { + return; + } + + include( WC()->plugin_path() . '/includes/admin/views/html-quick-edit-product.php' ); + } + + /** + * Quick and bulk edit saving + * + * @access public + * @param int $post_id + * @param WP_Post $post + * @return int + */ + public function bulk_and_quick_edit_save_post( $post_id, $post ) { + // If this is an autosave, our form has not been submitted, so we don't want to do anything. + if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { + return $post_id; + } + + // Don't save revisions and autosaves + if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) { + return $post_id; + } + + // Check post type is product + if ( 'product' != $post->post_type ) { + return $post_id; + } + + // Check user permission + if ( ! current_user_can( 'edit_post', $post_id ) ) { + return $post_id; + } + + // Check nonces + if ( ! isset( $_REQUEST['woocommerce_quick_edit_nonce'] ) && ! isset( $_REQUEST['woocommerce_bulk_edit_nonce'] ) ) { + return $post_id; + } + if ( isset( $_REQUEST['woocommerce_quick_edit_nonce'] ) && ! wp_verify_nonce( $_REQUEST['woocommerce_quick_edit_nonce'], 'woocommerce_quick_edit_nonce' ) ) { + return $post_id; + } + if ( isset( $_REQUEST['woocommerce_bulk_edit_nonce'] ) && ! wp_verify_nonce( $_REQUEST['woocommerce_bulk_edit_nonce'], 'woocommerce_bulk_edit_nonce' ) ) { + return $post_id; + } + + // Get the product and save + $product = get_product( $post ); + + if ( ! empty( $_REQUEST['woocommerce_quick_edit'] ) ) { + $this->quick_edit_save( $post_id, $product ); + } else { + $this->bulk_edit_save( $post_id, $product ); + } + + // Clear transient + wc_delete_product_transients( $post_id ); + + return $post_id; + } + + /** + * Quick edit + */ + private function quick_edit_save( $post_id, $product ) { + global $wpdb; + + $old_regular_price = $product->regular_price; + $old_sale_price = $product->sale_price; + + // Save fields + if ( isset( $_REQUEST['_sku'] ) ) { + $sku = get_post_meta( $post_id, '_sku', true ); + $new_sku = wc_clean( stripslashes( $_REQUEST['_sku'] ) ); + + if ( $new_sku !== $sku ) { + if ( ! empty( $new_sku ) ) { + $sku_exists = $wpdb->get_var( $wpdb->prepare(" + SELECT $wpdb->posts.ID + FROM $wpdb->posts + LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) + WHERE $wpdb->posts.post_type = 'product' + AND $wpdb->posts.post_status = 'publish' + AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s' + ", $new_sku ) ); + + if ( ! $sku_exists ) { + update_post_meta( $post_id, '_sku', $new_sku ); + } + } else { + update_post_meta( $post_id, '_sku', '' ); + } + } + } + + if ( isset( $_REQUEST['_weight'] ) ) { + update_post_meta( $post_id, '_weight', wc_clean( $_REQUEST['_weight'] ) ); + } + + if ( isset( $_REQUEST['_length'] ) ) { + update_post_meta( $post_id, '_length', wc_clean( $_REQUEST['_length'] ) ); + } + + if ( isset( $_REQUEST['_width'] ) ) { + update_post_meta( $post_id, '_width', wc_clean( $_REQUEST['_width'] ) ); + } + + if ( isset( $_REQUEST['_height'] ) ) { + update_post_meta( $post_id, '_height', wc_clean( $_REQUEST['_height'] ) ); + } + + if ( isset( $_REQUEST['_visibility'] ) ) { + update_post_meta( $post_id, '_visibility', wc_clean( $_REQUEST['_visibility'] ) ); + } + + if ( isset( $_REQUEST['_featured'] ) ) { + update_post_meta( $post_id, '_featured', 'yes' ); + } else { + update_post_meta( $post_id, '_featured', 'no' ); + } + + if ( isset( $_REQUEST['_tax_status'] ) ) { + update_post_meta( $post_id, '_tax_status', wc_clean( $_REQUEST['_tax_status'] ) ); + } + + if ( isset( $_REQUEST['_tax_class'] ) ) { + update_post_meta( $post_id, '_tax_class', wc_clean( $_REQUEST['_tax_class'] ) ); + } + + if ( $product->is_type('simple') || $product->is_type('external') ) { + + if ( isset( $_REQUEST['_regular_price'] ) ) { + $new_regular_price = $_REQUEST['_regular_price'] === '' ? '' : wc_format_decimal( $_REQUEST['_regular_price'] ); + update_post_meta( $post_id, '_regular_price', $new_regular_price ); + } else { + $new_regular_price = null; + } + if ( isset( $_REQUEST['_sale_price'] ) ) { + $new_sale_price = $_REQUEST['_sale_price'] === '' ? '' : wc_format_decimal( $_REQUEST['_sale_price'] ); + update_post_meta( $post_id, '_sale_price', $new_sale_price ); + } else { + $new_sale_price = null; + } + + // Handle price - remove dates and set to lowest + $price_changed = false; + + if ( ! is_null( $new_regular_price ) && $new_regular_price != $old_regular_price ) { + $price_changed = true; + } elseif ( ! is_null( $new_sale_price ) && $new_sale_price != $old_sale_price ) { + $price_changed = true; + } + + if ( $price_changed ) { + update_post_meta( $post_id, '_sale_price_dates_from', '' ); + update_post_meta( $post_id, '_sale_price_dates_to', '' ); + + if ( ! is_null( $new_sale_price ) && $new_sale_price !== '' ) { + update_post_meta( $post_id, '_price', $new_sale_price ); + } else { + update_post_meta( $post_id, '_price', $new_regular_price ); + } + } + } + + // Handle stock status + if ( isset( $_REQUEST['_stock_status'] ) ) { + wc_update_product_stock_status( $post_id, wc_clean( $_REQUEST['_stock_status'] ) ); + } + + // Handle stock + if ( ! $product->is_type('grouped') ) { + if ( isset( $_REQUEST['_manage_stock'] ) ) { + update_post_meta( $post_id, '_manage_stock', 'yes' ); + wc_update_product_stock( $post_id, intval( $_REQUEST['_stock'] ) ); + } else { + update_post_meta( $post_id, '_manage_stock', 'no' ); + wc_update_product_stock( $post_id, 0 ); + } + + if ( ! empty( $_REQUEST['_backorders'] ) ) { + update_post_meta( $post_id, '_backorders', wc_clean( $_REQUEST['_backorders'] ) ); + } + } + + do_action( 'woocommerce_product_quick_edit_save', $product ); + } + + /** + * Bulk edit + */ + public function bulk_edit_save( $post_id, $product ) { + + $old_regular_price = $product->regular_price; + $old_sale_price = $product->sale_price; + + // Save fields + if ( ! empty( $_REQUEST['change_weight'] ) && isset( $_REQUEST['_weight'] ) ) { + update_post_meta( $post_id, '_weight', wc_clean( stripslashes( $_REQUEST['_weight'] ) ) ); + } + + if ( ! empty( $_REQUEST['change_dimensions'] ) ) { + if ( isset( $_REQUEST['_length'] ) ) { + update_post_meta( $post_id, '_length', wc_clean( stripslashes( $_REQUEST['_length'] ) ) ); + } + if ( isset( $_REQUEST['_width'] ) ) { + update_post_meta( $post_id, '_width', wc_clean( stripslashes( $_REQUEST['_width'] ) ) ); + } + if ( isset( $_REQUEST['_height'] ) ) { + update_post_meta( $post_id, '_height', wc_clean( stripslashes( $_REQUEST['_height'] ) ) ); + } + } + + if ( ! empty( $_REQUEST['_tax_status'] ) ) { + update_post_meta( $post_id, '_tax_status', wc_clean( $_REQUEST['_tax_status'] ) ); + } + + if ( ! empty( $_REQUEST['_tax_class'] ) ) { + $tax_class = wc_clean( $_REQUEST['_tax_class'] ); + if ( 'standard' == $tax_class ) { + $tax_class = ''; + } + update_post_meta( $post_id, '_tax_class', $tax_class ); + } + + if ( ! empty( $_REQUEST['_stock_status'] ) ) { + wc_update_product_stock_status( $post_id, wc_clean( $_REQUEST['_stock_status'] ) ); + } + + if ( ! empty( $_REQUEST['_visibility'] ) ) { + update_post_meta( $post_id, '_visibility', stripslashes( $_REQUEST['_visibility'] ) ); + } + + if ( ! empty( $_REQUEST['_featured'] ) ) { + update_post_meta( $post_id, '_featured', stripslashes( $_REQUEST['_featured'] ) ); + } + + // Sold Individually + if ( ! empty( $_REQUEST['_sold_individually'] ) ) { + if ( $_REQUEST['_sold_individually'] == 'yes' ) { + update_post_meta( $post_id, '_sold_individually', 'yes' ); + } + else { + update_post_meta( $post_id, '_sold_individually', '' ); + } + } + + // Handle price - remove dates and set to lowest + if ( $product->is_type( 'simple' ) || $product->is_type( 'external' ) ) { + + $price_changed = false; + + if ( ! empty( $_REQUEST['change_regular_price'] ) ) { + + $change_regular_price = absint( $_REQUEST['change_regular_price'] ); + $regular_price = esc_attr( stripslashes( $_REQUEST['_regular_price'] ) ); + + switch ( $change_regular_price ) { + case 1 : + $new_price = $regular_price; + break; + case 2 : + if ( strstr( $regular_price, '%' ) ) { + $percent = str_replace( '%', '', $regular_price ) / 100; + $new_price = $old_regular_price + ( round( $old_regular_price * $percent, absint( get_option( 'woocommerce_price_num_decimals' ) ) ) ); + } else { + $new_price = $old_regular_price + $regular_price; + } + break; + case 3 : + if ( strstr( $regular_price, '%' ) ) { + $percent = str_replace( '%', '', $regular_price ) / 100; + $new_price = $old_regular_price - ( round ( $old_regular_price * $percent, absint( get_option( 'woocommerce_price_num_decimals' ) ) ) ); + } else { + $new_price = $old_regular_price - $regular_price; + } + break; + + default : + break; + } + + if ( isset( $new_price ) && $new_price != $old_regular_price ) { + $price_changed = true; + $new_price = round( $new_price, absint( get_option( 'woocommerce_price_num_decimals' ) ) ); + update_post_meta( $post_id, '_regular_price', $new_price ); + $product->regular_price = $new_price; + } + } + + if ( ! empty( $_REQUEST['change_sale_price'] ) ) { + + $change_sale_price = absint( $_REQUEST['change_sale_price'] ); + $sale_price = esc_attr( stripslashes( $_REQUEST['_sale_price'] ) ); + + switch ( $change_sale_price ) { + case 1 : + $new_price = $sale_price; + break; + case 2 : + if ( strstr( $sale_price, '%' ) ) { + $percent = str_replace( '%', '', $sale_price ) / 100; + $new_price = $old_sale_price + ( $old_sale_price * $percent ); + } else { + $new_price = $old_sale_price + $sale_price; + } + break; + case 3 : + if ( strstr( $sale_price, '%' ) ) { + $percent = str_replace( '%', '', $sale_price ) / 100; + $new_price = $old_sale_price - ( $old_sale_price * $percent ); + } else { + $new_price = $old_sale_price - $sale_price; + } + break; + case 4 : + if ( strstr( $sale_price, '%' ) ) { + $percent = str_replace( '%', '', $sale_price ) / 100; + $new_price = $product->regular_price - ( $product->regular_price * $percent ); + } else { + $new_price = $product->regular_price - $sale_price; + } + break; + + default : + break; + } + + if ( isset( $new_price ) && $new_price != $old_sale_price ) { + $price_changed = true; + $new_price = round( $new_price, absint( get_option( 'woocommerce_price_num_decimals' ) ) ); + update_post_meta( $post_id, '_sale_price', $new_price ); + $product->sale_price = $new_price; + } + } + + if ( $price_changed ) { + update_post_meta( $post_id, '_sale_price_dates_from', '' ); + update_post_meta( $post_id, '_sale_price_dates_to', '' ); + + if ( $product->regular_price < $product->sale_price ) { + $product->sale_price = ''; + update_post_meta( $post_id, '_sale_price', '' ); + } + + if ( $product->sale_price ) { + update_post_meta( $post_id, '_price', $product->sale_price ); + } else { + update_post_meta( $post_id, '_price', $product->regular_price ); + } + } + } + + // Handle stock + if ( ! $product->is_type( 'grouped' ) ) { + + if ( ! empty( $_REQUEST['change_stock'] ) ) { + update_post_meta( $post_id, '_manage_stock', 'yes' ); + wc_update_product_stock( $post_id, intval( $_REQUEST['_stock'] ) ); + } + + if ( ! empty( $_REQUEST['_manage_stock'] ) ) { + + if ( $_REQUEST['_manage_stock'] == 'yes' ) { + update_post_meta( $post_id, '_manage_stock', 'yes' ); + } else { + update_post_meta( $post_id, '_manage_stock', 'no' ); + wc_update_product_stock( $post_id, 0 ); + } + } + + if ( ! empty( $_REQUEST['_backorders'] ) ) { + update_post_meta( $post_id, '_backorders', wc_clean( $_REQUEST['_backorders'] ) ); + } + + } + + do_action( 'woocommerce_product_bulk_edit_save', $product ); + } + + /** + * Add extra bulk action options to mark orders as complete or processing + * + * Using Javascript until WordPress core fixes: http://core.trac.wordpress.org/ticket/16031 + * + * @access public + * @return void + */ + public function bulk_admin_footer() { + global $post_type; + + if ( 'shop_order' == $post_type ) { + ?> + + current_action(); + + switch ( $action ) { + case 'mark_completed': + $new_status = 'completed'; + $report_action = 'marked_complete'; + break; + case 'mark_processing': + $new_status = 'processing'; + $report_action = 'marked_processing'; + break; + case 'mark_on-hold' : + $new_status = 'on-hold'; + $report_action = 'marked_on-hold'; + break; + break; + default: + return; + } + + $changed = 0; + + $post_ids = array_map( 'absint', (array) $_REQUEST['post'] ); + + foreach ( $post_ids as $post_id ) { + $order = new WC_Order( $post_id ); + $order->update_status( $new_status, __( 'Order status changed by bulk edit:', 'woocommerce' ) ); + $changed++; + } + + $sendback = add_query_arg( array( 'post_type' => 'shop_order', $report_action => true, 'changed' => $changed, 'ids' => join( ',', $post_ids ) ), '' ); + wp_redirect( $sendback ); + exit(); + } + + /** + * Show confirmation message that order status changed for number of orders + * + * @access public + * @return void + */ + public function bulk_admin_notices() { + global $post_type, $pagenow; + + if ( isset( $_REQUEST['marked_complete'] ) || isset( $_REQUEST['marked_processing'] ) || isset( $_REQUEST['marked_on-hold'] ) ) { + $number = isset( $_REQUEST['changed'] ) ? absint( $_REQUEST['changed'] ) : 0; + + if ( 'edit.php' == $pagenow && 'shop_order' == $post_type ) { + $message = sprintf( _n( 'Order status changed.', '%s order statuses changed.', $number, 'woocommerce' ), number_format_i18n( $number ) ); + echo '

' . $message . '

'; + } + } + } + + + /** + * Search custom fields as well as content. + * + * @access public + * @param WP_Query $wp + * @return void + */ + public function shop_order_search_custom_fields( $wp ) { + global $pagenow, $wpdb; + + if ( 'edit.php' != $pagenow || empty( $wp->query_vars['s'] ) || $wp->query_vars['post_type'] != 'shop_order' ) { + return; + } + + $search_fields = array_map( 'wc_clean', apply_filters( 'woocommerce_shop_order_search_fields', array( + '_order_key', + '_billing_company', + '_billing_address_1', + '_billing_address_2', + '_billing_city', + '_billing_postcode', + '_billing_country', + '_billing_state', + '_billing_email', + '_billing_phone', + '_shipping_address_1', + '_shipping_address_2', + '_shipping_city', + '_shipping_postcode', + '_shipping_country', + '_shipping_state' + ) ) ); + + $search_order_id = str_replace( 'Order #', '', $_GET['s'] ); + if ( ! is_numeric( $search_order_id ) ) { + $search_order_id = 0; + } + + // Search orders + $post_ids = array_unique( array_merge( + $wpdb->get_col( + $wpdb->prepare( " + SELECT p1.post_id + FROM {$wpdb->postmeta} p1 + INNER JOIN {$wpdb->postmeta} p2 ON p1.post_id = p2.post_id + WHERE + ( p1.meta_key = '_billing_first_name' AND p2.meta_key = '_billing_last_name' AND CONCAT(p1.meta_value, ' ', p2.meta_value) LIKE '%%%s%%' ) + OR + ( p1.meta_key = '_shipping_first_name' AND p2.meta_key = '_shipping_last_name' AND CONCAT(p1.meta_value, ' ', p2.meta_value) LIKE '%%%s%%' ) + OR + ( p1.meta_key IN ('" . implode( "','", $search_fields ) . "') AND p1.meta_value LIKE '%%%s%%' ) + ", + esc_attr( $_GET['s'] ), esc_attr( $_GET['s'] ), esc_attr( $_GET['s'] ) + ) + ), + $wpdb->get_col( + $wpdb->prepare( " + SELECT order_id + FROM {$wpdb->prefix}woocommerce_order_items as order_items + WHERE order_item_name LIKE '%%%s%%' + ", + esc_attr( $_GET['s'] ) + ) + ), + array( $search_order_id ) + ) ); + + // Remove s - we don't want to search order name + unset( $wp->query_vars['s'] ); + + // so we know we're doing this + $wp->query_vars['shop_order_search'] = true; + + // Search by found posts + $wp->query_vars['post__in'] = $post_ids; + } + + /** + * Change the label when searching orders. + * + * @access public + * @param mixed $query + * @return string + */ + public function shop_order_search_label( $query ) { + global $pagenow, $typenow; + + if ( 'edit.php' != $pagenow ) { + return $query; + } + + if ( $typenow != 'shop_order' ) { + return $query; + } + + if ( ! get_query_var( 'shop_order_search' ) ) { + return $query; + } + + return wp_unslash( $_GET['s'] ); + } + + /** + * Query vars for custom searches. + * + * @access public + * @param mixed $public_query_vars + * @return array + */ + public function add_custom_query_var( $public_query_vars ) { + $public_query_vars[] = 'sku'; + $public_query_vars[] = 'shop_order_search'; + + return $public_query_vars; + } + + /** + * Filters for post types + */ + public function restrict_manage_posts() { + global $typenow, $wp_query; + + switch ( $typenow ) { + case 'product' : + $this->product_filters(); + break; + case 'product' : + $this->shop_coupon_filters(); + break; + case 'product' : + $this->shop_order_filters(); + break; + } + } + + /** + * Show a category filter box + */ + public function product_filters() { + global $wp_query; + + // Category Filtering + wc_product_dropdown_categories(); + + // Type filtering + $terms = get_terms( 'product_type' ); + $output = ''; + + echo apply_filters( 'woocommerce_product_filters', $output ); + } + + /** + * Show custom filters to filter coupons by type. + */ + public function shop_coupon_filters() { + ?> + + + + '_price', + 'orderby' => 'meta_value_num' + ) ); + } + if ( 'featured' == $vars['orderby'] ) { + $vars = array_merge( $vars, array( + 'meta_key' => '_featured', + 'orderby' => 'meta_value' + ) ); + } + if ( 'sku' == $vars['orderby'] ) { + $vars = array_merge( $vars, array( + 'meta_key' => '_sku', + 'orderby' => 'meta_value' + ) ); + } + } + + } elseif ( 'shop_coupon' === $typenow ) { + + if ( ! empty( $_GET['coupon_type'] ) ) { + $vars['meta_key'] = 'discount_type'; + $vars['meta_value'] = wc_clean( $_GET['coupon_type'] ); + } + + } elseif ( 'shop_order' === $typenow ) { + // Filter the orders by the posted customer. + if ( isset( $_GET['_customer_user'] ) && $_GET['_customer_user'] > 0 ) { + $vars['meta_key'] = '_customer_user'; + $vars['meta_value'] = (int) $_GET['_customer_user']; + } + + // Sorting + if ( isset( $vars['orderby'] ) ) { + if ( 'order_total' == $vars['orderby'] ) { + $vars = array_merge( $vars, array( + 'meta_key' => '_order_total', + 'orderby' => 'meta_value_num' + ) ); + } + } + } + + return $vars; + } + + /** + * Filter the products in admin based on options + * + * @param mixed $query + */ + public function product_filters_query( $query ) { + global $typenow, $wp_query; + + if ( 'product' == $typenow ) { + + if ( isset( $query->query_vars['product_type'] ) ) { + // Subtypes + if ( 'downloadable' == $query->query_vars['product_type'] ) { + $query->query_vars['product_type'] = ''; + $query->query_vars['meta_value'] = 'yes'; + $query->query_vars['meta_key'] = '_downloadable'; + } elseif ( 'virtual' == $query->query_vars['product_type'] ) { + $query->query_vars['product_type'] = ''; + $query->query_vars['meta_value'] = 'yes'; + $query->query_vars['meta_key'] = '_virtual'; + } + } + + // Categories + if ( isset( $_GET['product_cat'] ) && '0' == $_GET['product_cat'] ) { + $query->query_vars['tax_query'][] = array( + 'taxonomy' => 'product_cat', + 'field' => 'id', + 'terms' => get_terms( 'product_cat', array( 'fields' => 'ids' ) ), + 'operator' => 'NOT IN' + ); + } + } + } + + /** + * Search by SKU or ID for products. + * @param string $where + * @return string + */ + public function product_search( $where ) { + global $pagenow, $wpdb, $wp; + + if ( 'edit.php' != $pagenow || ! is_search() || ! isset( $wp->query_vars['s'] ) || 'product' != $wp->query_vars['post_type'] ) { + return $where; + } + + $search_ids = array(); + $terms = explode( ',', $wp->query_vars['s'] ); + + foreach ( $terms as $term ) { + if ( is_numeric( $term ) ) { + $search_ids[] = $term; + } + // Attempt to get a SKU + $sku_to_id = $wpdb->get_col( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='_sku' AND meta_value LIKE '%%%s%%';", wc_clean( $term ) ) ); + + if ( $sku_to_id && sizeof( $sku_to_id ) > 0 ) { + $search_ids = array_merge( $search_ids, $sku_to_id ); + } + } + + $search_ids = array_filter( array_map( 'absint', $search_ids ) ); + + if ( sizeof( $search_ids ) > 0 ) { + $where = str_replace( ')))', ") OR ({$wpdb->posts}.ID IN (" . implode( ',', $search_ids ) . "))))", $where ); + } + + return $where; } /** @@ -223,8 +1805,257 @@ class WC_Admin_Post_Types { } } + + /** + * Remove item meta on permanent deletion + * + * @access public + * @return void + **/ + public function delete_order_items( $postid ) { + global $wpdb; + + if ( get_post_type( $postid ) == 'shop_order' ) { + do_action( 'woocommerce_delete_order_items', $postid ); + + $wpdb->query( " + DELETE {$wpdb->prefix}woocommerce_order_items, {$wpdb->prefix}woocommerce_order_itemmeta + FROM {$wpdb->prefix}woocommerce_order_items + JOIN {$wpdb->prefix}woocommerce_order_itemmeta ON {$wpdb->prefix}woocommerce_order_items.order_item_id = {$wpdb->prefix}woocommerce_order_itemmeta.order_item_id + WHERE {$wpdb->prefix}woocommerce_order_items.order_id = '{$postid}'; + " ); + + do_action( 'woocommerce_deleted_order_items', $postid ); + } + } + + /** + * Change text without slow getext filter + */ + public function change_featured_image_text() { + global $l10n; + if ( isset( $l10n['default'] ) && isset( $l10n['default']->entries ) ) { + foreach ( $l10n['default']->entries as $entry_key => $entries ) { + foreach ( $entries->translations as $key => $value ) { + if ( 'Featured Image' == $value ) { + $l10n['default']->entries[ $entry_key ]->translations[ $key ] = __( 'Product Image', 'woocommerce' ); + } elseif ( 'Remove featured image' == $value ) { + $l10n['default']->entries[ $entry_key ]->translations[ $key ] = __( 'Remove product image', 'woocommerce' ); + } elseif ( 'Set featured image' == $value ) { + $l10n['default']->entries[ $entry_key ]->translations[ $key ] = __( 'Set product image', 'woocommerce' ); + } + } + } + } + } + + /** + * Change "Featured Image" to "Product Image" throughout media modals. + * @param array $strings Array of strings to translate. + * @param object $post + * @return array + */ + public function media_view_strings( $strings = array(), $post = null ) { + $strings['setFeaturedImageTitle'] = __( 'Set product image', 'woocommerce' ); + $strings['setFeaturedImage'] = __( 'Set product image', 'woocommerce' ); + return $strings; + } + + /** + * Change title boxes in admin. + * @param string $text + * @param object $post + * @return string + */ + public function enter_title_here( $text, $post ) { + switch ( $post->post_type ) { + case 'product' : + return __( 'Product name', 'woocommerce' ); + break; + case 'shop_coupon' : + return __( 'Coupon code', 'woocommerce' ); + break; + } + return $text; + } + + /** + * Print coupon description textarea field + * @param WP_Post $post + */ + public function edit_form_after_title( $post ) { + if ( 'shop_coupon' === $post->post_type ) { + ?> + + labels->singular_name ); + $strings['uploadedToThisPost'] = sprintf( __( 'Uploaded to this %s', 'woocommerce' ), $obj->labels->singular_name ); + } + + return $strings; + } + + /** + * Output product visibility options. + * + * @access public + * @return void + */ + public function product_data_visibility() { + global $post; + + if ( 'product' != $post->post_type ) { + return; + } + + $current_visibility = ( $current_visibility = get_post_meta( $post->ID, '_visibility', true ) ) ? $current_visibility : 'visible'; + $current_featured = ( $current_featured = get_post_meta( $post->ID, '_featured', true ) ) ? $current_featured : 'no'; + + $visibility_options = apply_filters( 'woocommerce_product_visibility_options', array( + 'visible' => __( 'Catalog/search', 'woocommerce' ), + 'catalog' => __( 'Catalog', 'woocommerce' ), + 'search' => __( 'Search', 'woocommerce' ), + 'hidden' => __( 'Hidden', 'woocommerce' ) + ) ); + ?> +
+ + + + +
+ + + + + ' . __( 'Define the loops this product should be visible in. The product will still be accessible directly.', 'woocommerce' ) . '

'; + + foreach ( $visibility_options as $name => $label ) { + echo '
'; + } + + echo '

' . __( 'Enable this option to feature this product.', 'woocommerce' ) . '

'; + + echo '
'; + ?> +

+ + +

+
+
+ get_files() ); + $updated_download_ids = array_keys( (array) $downloadable_files ); + + $new_download_ids = array_filter( array_diff( $updated_download_ids, $existing_download_ids ) ); + $removed_download_ids = array_filter( array_diff( $existing_download_ids, $updated_download_ids ) ); + + if ( $new_download_ids || $removed_download_ids ) { + // determine whether downloadable file access has been granted via the typical order completion, or via the admin ajax method + $existing_permissions = $wpdb->get_results( $wpdb->prepare( "SELECT * from {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE product_id = %d GROUP BY order_id", $product_id ) ); + + foreach ( $existing_permissions as $existing_permission ) { + $order = new WC_Order( $existing_permission->order_id ); + + if ( $order->id ) { + // Remove permissions + if ( $removed_download_ids ) { + foreach ( $removed_download_ids as $download_id ) { + if ( apply_filters( 'woocommerce_process_product_file_download_paths_remove_access_to_old_file', true, $download_id, $product_id, $order ) ) { + $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE order_id = %d AND product_id = %d AND download_id = %s", $order->id, $product_id, $download_id ) ); + } + } + } + // Add permissions + if ( $new_download_ids ) { + foreach ( $new_download_ids as $download_id ) { + if ( apply_filters( 'woocommerce_process_product_file_download_paths_grant_access_to_new_file', true, $download_id, $product_id, $order ) ) { + // grant permission if it doesn't already exist + if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT 1 FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE order_id = %d AND product_id = %d AND download_id = %s", $order->id, $product_id, $download_id ) ) ) { + wc_downloadable_file_permission( $download_id, $product_id, $order ); + } + } + } + } + } + } + } + } } endif; -return new WC_Admin_Post_Types(); \ No newline at end of file +new WC_Admin_Post_Types(); \ No newline at end of file diff --git a/includes/admin/class-wc-admin-status.php b/includes/admin/class-wc-admin-status.php index b0eba013f23..4eb2f7427f6 100644 --- a/includes/admin/class-wc-admin-status.php +++ b/includes/admin/class-wc-admin-status.php @@ -10,8 +10,6 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly -if ( ! class_exists( 'WC_Admin_Status' ) ) : - /** * WC_Admin_Status Class */ @@ -20,7 +18,7 @@ class WC_Admin_Status { /** * Handles output of the reports page in admin. */ - public function output() { + public static function output() { $current_tab = ! empty( $_REQUEST['tab'] ) ? sanitize_title( $_REQUEST['tab'] ) : 'status'; include_once( 'views/html-admin-page-status.php' ); @@ -29,7 +27,7 @@ class WC_Admin_Status { /** * Handles output of report */ - public function status_report() { + public static function status_report() { global $wpdb; include_once( 'views/html-admin-page-status-report.php' ); } @@ -37,10 +35,10 @@ class WC_Admin_Status { /** * Handles output of tools */ - public function status_tools() { + public static function status_tools() { global $woocommerce, $wpdb; - $tools = $this->get_tools(); + $tools = self::get_tools(); if ( ! empty( $_GET['action'] ) && ! empty( $_REQUEST['_wpnonce'] ) && wp_verify_nonce( $_REQUEST['_wpnonce'], 'debug_action' ) ) { @@ -168,7 +166,7 @@ class WC_Admin_Status { * * @return array of tools */ - public function get_tools() { + public static function get_tools() { return apply_filters( 'woocommerce_debug_tools', array( 'clear_transients' => array( 'name' => __( 'WC Transients','woocommerce'), @@ -211,8 +209,8 @@ class WC_Admin_Status { /** * Show the logs page */ - public function status_logs() { - $logs = $this->scan_log_files(); + public static function status_logs() { + $logs = self::scan_log_files(); if ( ! empty( $_POST['log_file'] ) && isset( $logs[ sanitize_title( $_POST['log_file'] ) ] ) ) { $viewed_log = $logs[ sanitize_title( $_POST['log_file'] ) ]; } elseif ( $logs ) { @@ -228,7 +226,7 @@ class WC_Admin_Status { * @param string $file Path to the file * @param array $all_headers List of headers, in the format array('HeaderKey' => 'Header Name') */ - public function get_file_version( $file ) { + public static function get_file_version( $file ) { // We don't need to write to the file, so just open for reading. $fp = fopen( $file, 'r' ); @@ -254,14 +252,14 @@ class WC_Admin_Status { * @param string $template_path * @return array */ - public function scan_template_files( $template_path ) { + public static function scan_template_files( $template_path ) { $files = scandir( $template_path ); $result = array(); if ( $files ) { foreach ( $files as $key => $value ) { if ( ! in_array( $value, array( ".",".." ) ) ) { if ( is_dir( $template_path . DIRECTORY_SEPARATOR . $value ) ) { - $sub_files = $this->scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value ); + $sub_files = self::scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value ); foreach ( $sub_files as $sub_file ) { $result[] = $value . DIRECTORY_SEPARATOR . $sub_file; } @@ -279,7 +277,7 @@ class WC_Admin_Status { * * @return array */ - public function scan_log_files() { + public static function scan_log_files() { $files = @scandir( WC_LOG_DIR ); $result = array(); if ( $files ) { @@ -293,8 +291,4 @@ class WC_Admin_Status { } return $result; } -} - -endif; - -return new WC_Admin_Status(); +} \ No newline at end of file diff --git a/includes/admin/class-wc-admin-taxonomies.php b/includes/admin/class-wc-admin-taxonomies.php index 5a65f9b5e7d..0097db8aa57 100644 --- a/includes/admin/class-wc-admin-taxonomies.php +++ b/includes/admin/class-wc-admin-taxonomies.php @@ -36,6 +36,9 @@ class WC_Admin_Taxonomies { // Taxonomy page descriptions add_action( 'product_cat_pre_add_form', array( $this, 'product_cat_description' ) ); add_action( 'product_shipping_class_pre_add_form', array( $this, 'shipping_class_description' ) ); + + // Maintain hierarchy of terms + add_filter( 'wp_terms_checklist_args', array( $this, 'disable_checked_ontop' ) ); } /** @@ -328,6 +331,18 @@ class WC_Admin_Taxonomies { return $columns; } + + /** + * Maintain term hierarchy when editing a product. + * @param array $args + * @return array + */ + public function disable_checked_ontop( $args ) { + if ( 'product_cat' == $args['taxonomy'] ) { + $args['checked_ontop'] = false; + } + return $args; + } } new WC_Admin_Taxonomies(); diff --git a/includes/admin/class-wc-admin.php b/includes/admin/class-wc-admin.php index cbe1541f03d..fa3d20a111f 100644 --- a/includes/admin/class-wc-admin.php +++ b/includes/admin/class-wc-admin.php @@ -21,7 +21,6 @@ class WC_Admin { add_action( 'init', array( $this, 'includes' ) ); add_action( 'current_screen', array( $this, 'conditonal_includes' ) ); add_action( 'admin_init', array( $this, 'prevent_admin_access' ) ); - add_action( 'wp_ajax_page_slurp', array( 'WC_Gateway_Mijireh', 'page_slurp' ) ); add_action( 'admin_init', array( $this, 'preview_emails' ) ); add_action( 'admin_footer', 'wc_print_js', 25 ); } @@ -38,22 +37,23 @@ class WC_Admin { include_once( 'class-wc-admin-post-types.php' ); include_once( 'class-wc-admin-taxonomies.php' ); - // Classes we only need if the ajax is not-ajax + // Classes we only need during non-ajax requests if ( ! is_ajax() ) { include( 'class-wc-admin-menus.php' ); include( 'class-wc-admin-welcome.php' ); include( 'class-wc-admin-notices.php' ); include( 'class-wc-admin-assets.php' ); - include( 'class-wc-admin-permalink-settings.php' ); // Help - if ( apply_filters( 'woocommerce_enable_admin_help_tab', true ) ) + if ( apply_filters( 'woocommerce_enable_admin_help_tab', true ) ) { include( 'class-wc-admin-help.php' ); + } } // Importers - if ( defined( 'WP_LOAD_IMPORTERS' ) ) + if ( defined( 'WP_LOAD_IMPORTERS' ) ) { include( 'class-wc-admin-importers.php' ); + } } /** @@ -66,6 +66,9 @@ class WC_Admin { case 'dashboard' : include( 'class-wc-admin-dashboard.php' ); break; + case 'options-permalink' : + include( 'class-wc-admin-permalink-settings.php' ); + break; case 'users' : case 'user' : case 'profile' : diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-coupon-data.php b/includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-coupon-data.php rename to includes/admin/meta-boxes/class-wc-meta-box-coupon-data.php diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-order-actions.php b/includes/admin/meta-boxes/class-wc-meta-box-order-actions.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-order-actions.php rename to includes/admin/meta-boxes/class-wc-meta-box-order-actions.php diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-order-data.php b/includes/admin/meta-boxes/class-wc-meta-box-order-data.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-order-data.php rename to includes/admin/meta-boxes/class-wc-meta-box-order-data.php diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-order-downloads.php b/includes/admin/meta-boxes/class-wc-meta-box-order-downloads.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-order-downloads.php rename to includes/admin/meta-boxes/class-wc-meta-box-order-downloads.php diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-order-items.php b/includes/admin/meta-boxes/class-wc-meta-box-order-items.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-order-items.php rename to includes/admin/meta-boxes/class-wc-meta-box-order-items.php diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-order-notes.php b/includes/admin/meta-boxes/class-wc-meta-box-order-notes.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-order-notes.php rename to includes/admin/meta-boxes/class-wc-meta-box-order-notes.php diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-order-reviews.php b/includes/admin/meta-boxes/class-wc-meta-box-order-reviews.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-order-reviews.php rename to includes/admin/meta-boxes/class-wc-meta-box-order-reviews.php diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-order-totals.php b/includes/admin/meta-boxes/class-wc-meta-box-order-totals.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-order-totals.php rename to includes/admin/meta-boxes/class-wc-meta-box-order-totals.php diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-product-data.php b/includes/admin/meta-boxes/class-wc-meta-box-product-data.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-product-data.php rename to includes/admin/meta-boxes/class-wc-meta-box-product-data.php diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-product-images.php b/includes/admin/meta-boxes/class-wc-meta-box-product-images.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-product-images.php rename to includes/admin/meta-boxes/class-wc-meta-box-product-images.php diff --git a/includes/admin/post-types/meta-boxes/class-wc-meta-box-product-short-description.php b/includes/admin/meta-boxes/class-wc-meta-box-product-short-description.php similarity index 100% rename from includes/admin/post-types/meta-boxes/class-wc-meta-box-product-short-description.php rename to includes/admin/meta-boxes/class-wc-meta-box-product-short-description.php diff --git a/includes/admin/post-types/meta-boxes/views/html-order-download-permission.php b/includes/admin/meta-boxes/views/html-order-download-permission.php similarity index 100% rename from includes/admin/post-types/meta-boxes/views/html-order-download-permission.php rename to includes/admin/meta-boxes/views/html-order-download-permission.php diff --git a/includes/admin/post-types/meta-boxes/views/html-order-fee.php b/includes/admin/meta-boxes/views/html-order-fee.php similarity index 100% rename from includes/admin/post-types/meta-boxes/views/html-order-fee.php rename to includes/admin/meta-boxes/views/html-order-fee.php diff --git a/includes/admin/post-types/meta-boxes/views/html-order-item.php b/includes/admin/meta-boxes/views/html-order-item.php similarity index 100% rename from includes/admin/post-types/meta-boxes/views/html-order-item.php rename to includes/admin/meta-boxes/views/html-order-item.php diff --git a/includes/admin/post-types/meta-boxes/views/html-order-shipping.php b/includes/admin/meta-boxes/views/html-order-shipping.php similarity index 100% rename from includes/admin/post-types/meta-boxes/views/html-order-shipping.php rename to includes/admin/meta-boxes/views/html-order-shipping.php diff --git a/includes/admin/post-types/meta-boxes/views/html-order-tax.php b/includes/admin/meta-boxes/views/html-order-tax.php similarity index 100% rename from includes/admin/post-types/meta-boxes/views/html-order-tax.php rename to includes/admin/meta-boxes/views/html-order-tax.php diff --git a/includes/admin/post-types/meta-boxes/views/html-product-download.php b/includes/admin/meta-boxes/views/html-product-download.php similarity index 100% rename from includes/admin/post-types/meta-boxes/views/html-product-download.php rename to includes/admin/meta-boxes/views/html-product-download.php diff --git a/includes/admin/post-types/meta-boxes/views/html-product-variation-download.php b/includes/admin/meta-boxes/views/html-product-variation-download.php similarity index 100% rename from includes/admin/post-types/meta-boxes/views/html-product-variation-download.php rename to includes/admin/meta-boxes/views/html-product-variation-download.php diff --git a/includes/admin/post-types/meta-boxes/views/html-variation-admin.php b/includes/admin/meta-boxes/views/html-variation-admin.php similarity index 100% rename from includes/admin/post-types/meta-boxes/views/html-variation-admin.php rename to includes/admin/meta-boxes/views/html-variation-admin.php diff --git a/includes/admin/post-types/class-wc-admin-cpt-product.php b/includes/admin/post-types/class-wc-admin-cpt-product.php deleted file mode 100644 index 17125719888..00000000000 --- a/includes/admin/post-types/class-wc-admin-cpt-product.php +++ /dev/null @@ -1,1205 +0,0 @@ -type = 'product'; - - // Post title fields - add_filter( 'enter_title_here', array( $this, 'enter_title_here' ), 1, 2 ); - - // Featured image text - add_filter( 'gettext', array( $this, 'featured_image_gettext' ) ); - add_filter( 'media_view_strings', array( $this, 'media_view_strings' ), 10, 2 ); - - // Visibility option - add_action( 'post_submitbox_misc_actions', array( $this, 'product_data_visibility' ) ); - - // Before data updates - add_action( 'pre_post_update', array( $this, 'pre_post_update' ) ); - add_filter( 'wp_insert_post_data', array( $this, 'wp_insert_post_data' ) ); - - // Admin Columns - add_filter( 'manage_edit-product_columns', array( $this, 'edit_columns' ) ); - add_action( 'manage_product_posts_custom_column', array( $this, 'custom_columns' ), 2 ); - add_filter( 'manage_edit-product_sortable_columns', array( $this, 'custom_columns_sort' ) ); - add_filter( 'request', array( $this, 'custom_columns_orderby' ) ); - - // Sort link - add_filter( 'views_edit-product', array( $this, 'default_sorting_link' ) ); - - // Prouct filtering - add_action( 'restrict_manage_posts', array( $this, 'product_filters' ) ); - add_filter( 'parse_query', array( $this, 'product_filters_query' ) ); - - // Enhanced search - add_filter( 'posts_search', array( $this, 'product_search' ) ); - - // Maintain hierarchy of terms - add_filter( 'wp_terms_checklist_args', array( $this, 'disable_checked_ontop' ) ); - - // Bulk / quick edit - add_action( 'bulk_edit_custom_box', array( $this, 'bulk_edit' ), 10, 2 ); - add_action( 'quick_edit_custom_box', array( $this, 'quick_edit' ), 10, 2 ); - add_action( 'save_post', array( $this, 'bulk_and_quick_edit_save_post' ), 10, 2 ); - - // Uploads - add_filter( 'upload_dir', array( $this, 'upload_dir' ) ); - add_action( 'media_upload_downloadable_product', array( $this, 'media_upload_downloadable_product' ) ); - add_filter( 'mod_rewrite_rules', array( $this, 'ms_protect_download_rewite_rules' ) ); - - // Download permissions - add_action( 'woocommerce_process_product_file_download_paths', array( $this, 'process_product_file_download_paths' ), 10, 3 ); - - // Call WC_Admin_CPT constructor - parent::__construct(); - } - - /** - * Check if we're editing or adding a product - * @return boolean - */ - private function is_editing_product() { - if ( ! empty( $_GET['post_type'] ) && 'product' == $_GET['post_type'] ) { - return true; - } - if ( ! empty( $_GET['post'] ) && 'product' == get_post_type( $_GET['post'] ) ) { - return true; - } - if ( ! empty( $_REQUEST['post_id'] ) && 'product' == get_post_type( $_REQUEST['post_id'] ) ) { - return true; - } - return false; - } - - /** - * Replace 'Featured' when editing a product. Adapted from https://gist.github.com/tw2113/c7fd8da782232ce90176 - * @param string $string string being translated - * @return string after manipulation - */ - public function featured_image_gettext( $string = '' ) { - if ( 'Featured Image' == $string && $this->is_editing_product() ) { - $string = __( 'Product Image', 'woocommerce' ); - } elseif ( 'Remove featured image' == $string && $this->is_editing_product() ) { - $string = __( 'Remove product image', 'woocommerce' ); - } elseif ( 'Set featured image' == $string && $this->is_editing_product() ) { - $string = __( 'Set product image', 'woocommerce' ); - } - return $string; - } - - /** - * Change "Featured Image" to "Product Image" throughout media modals. - * @param array $strings Array of strings to translate. - * @param object $post - * @return array - */ - public function media_view_strings( $strings = array(), $post = null ) { - if ( is_object( $post ) ) { - if ( 'product' == $post->post_type ) { - $strings['setFeaturedImageTitle'] = __( 'Set product image', 'woocommerce' ); - $strings['setFeaturedImage'] = __( 'Set product image', 'woocommerce' ); - } - } - return $strings; - } - - /** - * Change title boxes in admin. - * @param string $text - * @param object $post - * @return string - */ - public function enter_title_here( $text, $post ) { - if ( $post->post_type == 'product' ) { - return __( 'Product name', 'woocommerce' ); - } - - return $text; - } - - /** - * Output product visibility options. - * - * @access public - * @return void - */ - public function product_data_visibility() { - global $post; - - if ( 'product' != $post->post_type ) { - return; - } - - $current_visibility = ( $current_visibility = get_post_meta( $post->ID, '_visibility', true ) ) ? $current_visibility : 'visible'; - $current_featured = ( $current_featured = get_post_meta( $post->ID, '_featured', true ) ) ? $current_featured : 'no'; - - $visibility_options = apply_filters( 'woocommerce_product_visibility_options', array( - 'visible' => __( 'Catalog/search', 'woocommerce' ), - 'catalog' => __( 'Catalog', 'woocommerce' ), - 'search' => __( 'Search', 'woocommerce' ), - 'hidden' => __( 'Hidden', 'woocommerce' ) - ) ); - ?> -
- - - - -
- - - - - ' . __( 'Define the loops this product should be visible in. The product will still be accessible directly.', 'woocommerce' ) . '

'; - - foreach ( $visibility_options as $name => $label ) { - echo '
'; - } - - echo '

' . __( 'Enable this option to feature this product.', 'woocommerce' ) . '

'; - - echo '
'; - ?> -

- - -

-
-
- '; - $columns['thumb'] = '' . __( 'Image', 'woocommerce' ) . ''; - - $columns['name'] = __( 'Name', 'woocommerce' ); - - if ( wc_product_sku_enabled() ) { - $columns['sku'] = __( 'SKU', 'woocommerce' ); - } - - if ( 'yes' == get_option( 'woocommerce_manage_stock' ) ) { - $columns['is_in_stock'] = __( 'Stock', 'woocommerce' ); - } - - $columns['price'] = __( 'Price', 'woocommerce' ); - - $columns['product_cat'] = __( 'Categories', 'woocommerce' ); - $columns['product_tag'] = __( 'Tags', 'woocommerce' ); - $columns['featured'] = '' . __( 'Featured', 'woocommerce' ) . ''; - $columns['product_type'] = '' . __( 'Type', 'woocommerce' ) . ''; - $columns['date'] = __( 'Date', 'woocommerce' ); - - return array_merge( $columns, $existing_columns ); - } - - /** - * Define our custom columns shown in admin. - * @param string $column - */ - public function custom_columns( $column ) { - global $post, $woocommerce, $the_product; - - if ( empty( $the_product ) || $the_product->id != $post->ID ) { - $the_product = get_product( $post ); - } - - switch ( $column ) { - case 'thumb' : - echo '' . $the_product->get_image() . ''; - break; - case 'name' : - $edit_link = get_edit_post_link( $post->ID ); - $title = _draft_or_post_title(); - $post_type_object = get_post_type_object( $post->post_type ); - $can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID ); - - echo '' . $title.''; - - _post_states( $post ); - - echo ''; - - if ( $post->post_parent > 0 ) { - echo '  ← '. get_the_title( $post->post_parent ) .''; - } - - // Excerpt view - if ( isset( $_GET['mode'] ) && 'excerpt' == $_GET['mode'] ) { - echo apply_filters( 'the_excerpt', $post->post_excerpt ); - } - - // Get actions - $actions = array(); - - $actions['id'] = 'ID: ' . $post->ID; - - if ( $can_edit_post && 'trash' != $post->post_status ) { - $actions['edit'] = '' . __( 'Edit', 'woocommerce' ) . ''; - $actions['inline hide-if-no-js'] = '' . __( 'Quick Edit', 'woocommerce' ) . ''; - } - if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) { - if ( 'trash' == $post->post_status ) { - $actions['untrash'] = '' . __( 'Restore', 'woocommerce' ) . ''; - } elseif ( EMPTY_TRASH_DAYS ) { - $actions['trash'] = '' . __( 'Trash', 'woocommerce' ) . ''; - } - - if ( 'trash' == $post->post_status || ! EMPTY_TRASH_DAYS ) { - $actions['delete'] = '' . __( 'Delete Permanently', 'woocommerce' ) . ''; - } - } - if ( $post_type_object->public ) { - if ( in_array( $post->post_status, array( 'pending', 'draft', 'future' ) ) ) { - if ( $can_edit_post ) - $actions['view'] = '' . __( 'Preview', 'woocommerce' ) . ''; - } elseif ( 'trash' != $post->post_status ) { - $actions['view'] = '' . __( 'View', 'woocommerce' ) . ''; - } - } - - $actions = apply_filters( 'post_row_actions', $actions, $post ); - - echo '
'; - - $i = 0; - $action_count = sizeof($actions); - - foreach ( $actions as $action => $link ) { - ++$i; - ( $i == $action_count ) ? $sep = '' : $sep = ' | '; - echo '' . $link . $sep . ''; - } - echo '
'; - - get_inline_data( $post ); - - /* Custom inline data for woocommerce */ - echo ' - - '; - - break; - case 'sku' : - echo $the_product->get_sku() ? $the_product->get_sku() : ''; - break; - case 'product_type' : - if ( 'grouped' == $the_product->product_type ) { - echo ''; - } elseif ( 'external' == $the_product->product_type ) { - echo ''; - } elseif ( 'simple' == $the_product->product_type ) { - - if ( $the_product->is_virtual() ) { - echo ''; - } elseif ( $the_product->is_downloadable() ) { - echo ''; - } else { - echo ''; - } - - } elseif ( 'variable' == $the_product->product_type ) { - echo ''; - } else { - // Assuming that we have other types in future - echo ''; - } - break; - case 'price' : - echo $the_product->get_price_html() ? $the_product->get_price_html() : ''; - break; - case 'product_cat' : - case 'product_tag' : - if ( ! $terms = get_the_terms( $post->ID, $column ) ) { - echo ''; - } else { - foreach ( $terms as $term ) { - $termlist[] = '' . $term->name . ''; - } - - echo implode( ', ', $termlist ); - } - break; - case 'featured' : - $url = wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_feature_product&product_id=' . $post->ID ), 'woocommerce-feature-product' ); - echo ''; - if ( $the_product->is_featured() ) { - echo '' . __( 'Yes', 'woocommerce' ) . ''; - } else { - echo '' . __( 'No', 'woocommerce' ) . ''; - } - echo ''; - break; - case 'is_in_stock' : - - if ( $the_product->is_in_stock() ) { - echo '' . __( 'In stock', 'woocommerce' ) . ''; - } else { - echo '' . __( 'Out of stock', 'woocommerce' ) . ''; - } - - if ( $the_product->managing_stock() ) { - echo ' × ' . $the_product->get_total_stock(); - } - - break; - - default : - break; - } - } - - /** - * Make product columns sortable - * - * https://gist.github.com/906872 - * - * @access public - * @param mixed $columns - * @return array - */ - public function custom_columns_sort( $columns ) { - $custom = array( - 'price' => 'price', - 'featured' => 'featured', - 'sku' => 'sku', - 'name' => 'title' - ); - return wp_parse_args( $custom, $columns ); - } - - /** - * Product column orderby - * - * http://scribu.net/wordpress/custom-sortable-columns.html#comment-4732 - * - * @access public - * @param mixed $vars - * @return array - */ - public function custom_columns_orderby( $vars ) { - if ( isset( $vars['orderby'] ) ) { - if ( 'price' == $vars['orderby'] ) { - $vars = array_merge( $vars, array( - 'meta_key' => '_price', - 'orderby' => 'meta_value_num' - ) ); - } - if ( 'featured' == $vars['orderby'] ) { - $vars = array_merge( $vars, array( - 'meta_key' => '_featured', - 'orderby' => 'meta_value' - ) ); - } - if ( 'sku' == $vars['orderby'] ) { - $vars = array_merge( $vars, array( - 'meta_key' => '_sku', - 'orderby' => 'meta_value' - ) ); - } - } - - return $vars; - } - - /** - * Product sorting link - * - * Based on Simple Page Ordering by 10up (http://wordpress.org/extend/plugins/simple-page-ordering/) - * - * @param array $views - * @return array - */ - public function default_sorting_link( $views ) { - global $post_type, $wp_query; - - if ( ! current_user_can('edit_others_pages') ) { - return $views; - } - - $class = ( isset( $wp_query->query['orderby'] ) && $wp_query->query['orderby'] == 'menu_order title' ) ? 'current' : ''; - $query_string = remove_query_arg(array( 'orderby', 'order' )); - $query_string = add_query_arg( 'orderby', urlencode('menu_order title'), $query_string ); - $query_string = add_query_arg( 'order', urlencode('ASC'), $query_string ); - $views['byorder'] = '' . __( 'Sort Products', 'woocommerce' ) . ''; - - return $views; - } - - /** - * Show a category filter box - */ - public function product_filters() { - global $typenow, $wp_query; - - if ( 'product' != $typenow ) { - return; - } - - // Category Filtering - wc_product_dropdown_categories(); - - // Type filtering - $terms = get_terms( 'product_type' ); - $output = ''; - - echo apply_filters( 'woocommerce_product_filters', $output ); - } - - /** - * Filter the products in admin based on options - * - * @param mixed $query - */ - public function product_filters_query( $query ) { - global $typenow, $wp_query; - - if ( 'product' == $typenow ) { - - if ( isset( $query->query_vars['product_type'] ) ) { - // Subtypes - if ( 'downloadable' == $query->query_vars['product_type'] ) { - $query->query_vars['product_type'] = ''; - $query->query_vars['meta_value'] = 'yes'; - $query->query_vars['meta_key'] = '_downloadable'; - } elseif ( 'virtual' == $query->query_vars['product_type'] ) { - $query->query_vars['product_type'] = ''; - $query->query_vars['meta_value'] = 'yes'; - $query->query_vars['meta_key'] = '_virtual'; - } - } - - // Categories - if ( isset( $_GET['product_cat'] ) && '0' == $_GET['product_cat'] ) { - $query->query_vars['tax_query'][] = array( - 'taxonomy' => 'product_cat', - 'field' => 'id', - 'terms' => get_terms( 'product_cat', array( 'fields' => 'ids' ) ), - 'operator' => 'NOT IN' - ); - } - } - } - - /** - * Search by SKU or ID for products. - * @param string $where - * @return string - */ - public function product_search( $where ) { - global $pagenow, $wpdb, $wp; - - if ( 'edit.php' != $pagenow || ! is_search() || ! isset( $wp->query_vars['s'] ) || 'product' != $wp->query_vars['post_type'] ) { - return $where; - } - - $search_ids = array(); - $terms = explode( ',', $wp->query_vars['s'] ); - - foreach ( $terms as $term ) { - if ( is_numeric( $term ) ) { - $search_ids[] = $term; - } - // Attempt to get a SKU - $sku_to_id = $wpdb->get_col( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key='_sku' AND meta_value LIKE '%%%s%%';", wc_clean( $term ) ) ); - - if ( $sku_to_id && sizeof( $sku_to_id ) > 0 ) { - $search_ids = array_merge( $search_ids, $sku_to_id ); - } - } - - $search_ids = array_filter( array_map( 'absint', $search_ids ) ); - - if ( sizeof( $search_ids ) > 0 ) { - $where = str_replace( ')))', ") OR ({$wpdb->posts}.ID IN (" . implode( ',', $search_ids ) . "))))", $where ); - } - - return $where; - } - - /** - * Maintain term hierarchy when editing a product. - * @param array $args - * @return array - */ - public function disable_checked_ontop( $args ) { - if ( 'product_cat' == $args['taxonomy'] ) { - $args['checked_ontop'] = false; - } - - return $args; - } - - /** - * Custom bulk edit - form - * - * @access public - * @param mixed $column_name - * @param mixed $post_type - */ - public function bulk_edit( $column_name, $post_type ) { - if ( 'price' != $column_name || 'product' != $post_type ) { - return; - } - - include( WC()->plugin_path() . '/includes/admin/views/html-bulk-edit-product.php' ); - } - - /** - * Custom quick edit - form - * - * @access public - * @param mixed $column_name - * @param mixed $post_type - */ - public function quick_edit( $column_name, $post_type ) { - if ( 'price' != $column_name || 'product' != $post_type ) { - return; - } - - include( WC()->plugin_path() . '/includes/admin/views/html-quick-edit-product.php' ); - } - - /** - * Quick and bulk edit saving - * - * @access public - * @param int $post_id - * @param WP_Post $post - * @return int - */ - public function bulk_and_quick_edit_save_post( $post_id, $post ) { - // If this is an autosave, our form has not been submitted, so we don't want to do anything. - if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { - return $post_id; - } - - // Don't save revisions and autosaves - if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) { - return $post_id; - } - - // Check post type is product - if ( 'product' != $post->post_type ) { - return $post_id; - } - - // Check user permission - if ( ! current_user_can( 'edit_post', $post_id ) ) { - return $post_id; - } - - // Check nonces - if ( ! isset( $_REQUEST['woocommerce_quick_edit_nonce'] ) && ! isset( $_REQUEST['woocommerce_bulk_edit_nonce'] ) ) { - return $post_id; - } - if ( isset( $_REQUEST['woocommerce_quick_edit_nonce'] ) && ! wp_verify_nonce( $_REQUEST['woocommerce_quick_edit_nonce'], 'woocommerce_quick_edit_nonce' ) ) { - return $post_id; - } - if ( isset( $_REQUEST['woocommerce_bulk_edit_nonce'] ) && ! wp_verify_nonce( $_REQUEST['woocommerce_bulk_edit_nonce'], 'woocommerce_bulk_edit_nonce' ) ) { - return $post_id; - } - - // Get the product and save - $product = get_product( $post ); - - if ( ! empty( $_REQUEST['woocommerce_quick_edit'] ) ) { - $this->quick_edit_save( $post_id, $product ); - } else { - $this->bulk_edit_save( $post_id, $product ); - } - - // Clear transient - wc_delete_product_transients( $post_id ); - - return $post_id; - } - - /** - * Quick edit - */ - private function quick_edit_save( $post_id, $product ) { - global $wpdb; - - $old_regular_price = $product->regular_price; - $old_sale_price = $product->sale_price; - - // Save fields - if ( isset( $_REQUEST['_sku'] ) ) { - $sku = get_post_meta( $post_id, '_sku', true ); - $new_sku = wc_clean( stripslashes( $_REQUEST['_sku'] ) ); - - if ( $new_sku !== $sku ) { - if ( ! empty( $new_sku ) ) { - $sku_exists = $wpdb->get_var( $wpdb->prepare(" - SELECT $wpdb->posts.ID - FROM $wpdb->posts - LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) - WHERE $wpdb->posts.post_type = 'product' - AND $wpdb->posts.post_status = 'publish' - AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s' - ", $new_sku ) ); - - if ( ! $sku_exists ) { - update_post_meta( $post_id, '_sku', $new_sku ); - } - } else { - update_post_meta( $post_id, '_sku', '' ); - } - } - } - - if ( isset( $_REQUEST['_weight'] ) ) { - update_post_meta( $post_id, '_weight', wc_clean( $_REQUEST['_weight'] ) ); - } - - if ( isset( $_REQUEST['_length'] ) ) { - update_post_meta( $post_id, '_length', wc_clean( $_REQUEST['_length'] ) ); - } - - if ( isset( $_REQUEST['_width'] ) ) { - update_post_meta( $post_id, '_width', wc_clean( $_REQUEST['_width'] ) ); - } - - if ( isset( $_REQUEST['_height'] ) ) { - update_post_meta( $post_id, '_height', wc_clean( $_REQUEST['_height'] ) ); - } - - if ( isset( $_REQUEST['_visibility'] ) ) { - update_post_meta( $post_id, '_visibility', wc_clean( $_REQUEST['_visibility'] ) ); - } - - if ( isset( $_REQUEST['_featured'] ) ) { - update_post_meta( $post_id, '_featured', 'yes' ); - } else { - update_post_meta( $post_id, '_featured', 'no' ); - } - - if ( isset( $_REQUEST['_tax_status'] ) ) { - update_post_meta( $post_id, '_tax_status', wc_clean( $_REQUEST['_tax_status'] ) ); - } - - if ( isset( $_REQUEST['_tax_class'] ) ) { - update_post_meta( $post_id, '_tax_class', wc_clean( $_REQUEST['_tax_class'] ) ); - } - - if ( $product->is_type('simple') || $product->is_type('external') ) { - - if ( isset( $_REQUEST['_regular_price'] ) ) { - $new_regular_price = $_REQUEST['_regular_price'] === '' ? '' : wc_format_decimal( $_REQUEST['_regular_price'] ); - update_post_meta( $post_id, '_regular_price', $new_regular_price ); - } else { - $new_regular_price = null; - } - if ( isset( $_REQUEST['_sale_price'] ) ) { - $new_sale_price = $_REQUEST['_sale_price'] === '' ? '' : wc_format_decimal( $_REQUEST['_sale_price'] ); - update_post_meta( $post_id, '_sale_price', $new_sale_price ); - } else { - $new_sale_price = null; - } - - // Handle price - remove dates and set to lowest - $price_changed = false; - - if ( ! is_null( $new_regular_price ) && $new_regular_price != $old_regular_price ) { - $price_changed = true; - } elseif ( ! is_null( $new_sale_price ) && $new_sale_price != $old_sale_price ) { - $price_changed = true; - } - - if ( $price_changed ) { - update_post_meta( $post_id, '_sale_price_dates_from', '' ); - update_post_meta( $post_id, '_sale_price_dates_to', '' ); - - if ( ! is_null( $new_sale_price ) && $new_sale_price !== '' ) { - update_post_meta( $post_id, '_price', $new_sale_price ); - } else { - update_post_meta( $post_id, '_price', $new_regular_price ); - } - } - } - - // Handle stock status - if ( isset( $_REQUEST['_stock_status'] ) ) { - wc_update_product_stock_status( $post_id, wc_clean( $_REQUEST['_stock_status'] ) ); - } - - // Handle stock - if ( ! $product->is_type('grouped') ) { - if ( isset( $_REQUEST['_manage_stock'] ) ) { - update_post_meta( $post_id, '_manage_stock', 'yes' ); - wc_update_product_stock( $post_id, intval( $_REQUEST['_stock'] ) ); - } else { - update_post_meta( $post_id, '_manage_stock', 'no' ); - wc_update_product_stock( $post_id, 0 ); - } - - if ( ! empty( $_REQUEST['_backorders'] ) ) { - update_post_meta( $post_id, '_backorders', wc_clean( $_REQUEST['_backorders'] ) ); - } - } - - do_action( 'woocommerce_product_quick_edit_save', $product ); - } - - /** - * Bulk edit - */ - public function bulk_edit_save( $post_id, $product ) { - - $old_regular_price = $product->regular_price; - $old_sale_price = $product->sale_price; - - // Save fields - if ( ! empty( $_REQUEST['change_weight'] ) && isset( $_REQUEST['_weight'] ) ) { - update_post_meta( $post_id, '_weight', wc_clean( stripslashes( $_REQUEST['_weight'] ) ) ); - } - - if ( ! empty( $_REQUEST['change_dimensions'] ) ) { - if ( isset( $_REQUEST['_length'] ) ) { - update_post_meta( $post_id, '_length', wc_clean( stripslashes( $_REQUEST['_length'] ) ) ); - } - if ( isset( $_REQUEST['_width'] ) ) { - update_post_meta( $post_id, '_width', wc_clean( stripslashes( $_REQUEST['_width'] ) ) ); - } - if ( isset( $_REQUEST['_height'] ) ) { - update_post_meta( $post_id, '_height', wc_clean( stripslashes( $_REQUEST['_height'] ) ) ); - } - } - - if ( ! empty( $_REQUEST['_tax_status'] ) ) { - update_post_meta( $post_id, '_tax_status', wc_clean( $_REQUEST['_tax_status'] ) ); - } - - if ( ! empty( $_REQUEST['_tax_class'] ) ) { - $tax_class = wc_clean( $_REQUEST['_tax_class'] ); - if ( 'standard' == $tax_class ) { - $tax_class = ''; - } - update_post_meta( $post_id, '_tax_class', $tax_class ); - } - - if ( ! empty( $_REQUEST['_stock_status'] ) ) { - wc_update_product_stock_status( $post_id, wc_clean( $_REQUEST['_stock_status'] ) ); - } - - if ( ! empty( $_REQUEST['_visibility'] ) ) { - update_post_meta( $post_id, '_visibility', stripslashes( $_REQUEST['_visibility'] ) ); - } - - if ( ! empty( $_REQUEST['_featured'] ) ) { - update_post_meta( $post_id, '_featured', stripslashes( $_REQUEST['_featured'] ) ); - } - - // Sold Individually - if ( ! empty( $_REQUEST['_sold_individually'] ) ) { - if ( $_REQUEST['_sold_individually'] == 'yes' ) { - update_post_meta( $post_id, '_sold_individually', 'yes' ); - } - else { - update_post_meta( $post_id, '_sold_individually', '' ); - } - } - - // Handle price - remove dates and set to lowest - if ( $product->is_type( 'simple' ) || $product->is_type( 'external' ) ) { - - $price_changed = false; - - if ( ! empty( $_REQUEST['change_regular_price'] ) ) { - - $change_regular_price = absint( $_REQUEST['change_regular_price'] ); - $regular_price = esc_attr( stripslashes( $_REQUEST['_regular_price'] ) ); - - switch ( $change_regular_price ) { - case 1 : - $new_price = $regular_price; - break; - case 2 : - if ( strstr( $regular_price, '%' ) ) { - $percent = str_replace( '%', '', $regular_price ) / 100; - $new_price = $old_regular_price + ( round( $old_regular_price * $percent, absint( get_option( 'woocommerce_price_num_decimals' ) ) ) ); - } else { - $new_price = $old_regular_price + $regular_price; - } - break; - case 3 : - if ( strstr( $regular_price, '%' ) ) { - $percent = str_replace( '%', '', $regular_price ) / 100; - $new_price = $old_regular_price - ( round ( $old_regular_price * $percent, absint( get_option( 'woocommerce_price_num_decimals' ) ) ) ); - } else { - $new_price = $old_regular_price - $regular_price; - } - break; - - default : - break; - } - - if ( isset( $new_price ) && $new_price != $old_regular_price ) { - $price_changed = true; - $new_price = round( $new_price, absint( get_option( 'woocommerce_price_num_decimals' ) ) ); - update_post_meta( $post_id, '_regular_price', $new_price ); - $product->regular_price = $new_price; - } - } - - if ( ! empty( $_REQUEST['change_sale_price'] ) ) { - - $change_sale_price = absint( $_REQUEST['change_sale_price'] ); - $sale_price = esc_attr( stripslashes( $_REQUEST['_sale_price'] ) ); - - switch ( $change_sale_price ) { - case 1 : - $new_price = $sale_price; - break; - case 2 : - if ( strstr( $sale_price, '%' ) ) { - $percent = str_replace( '%', '', $sale_price ) / 100; - $new_price = $old_sale_price + ( $old_sale_price * $percent ); - } else { - $new_price = $old_sale_price + $sale_price; - } - break; - case 3 : - if ( strstr( $sale_price, '%' ) ) { - $percent = str_replace( '%', '', $sale_price ) / 100; - $new_price = $old_sale_price - ( $old_sale_price * $percent ); - } else { - $new_price = $old_sale_price - $sale_price; - } - break; - case 4 : - if ( strstr( $sale_price, '%' ) ) { - $percent = str_replace( '%', '', $sale_price ) / 100; - $new_price = $product->regular_price - ( $product->regular_price * $percent ); - } else { - $new_price = $product->regular_price - $sale_price; - } - break; - - default : - break; - } - - if ( isset( $new_price ) && $new_price != $old_sale_price ) { - $price_changed = true; - $new_price = round( $new_price, absint( get_option( 'woocommerce_price_num_decimals' ) ) ); - update_post_meta( $post_id, '_sale_price', $new_price ); - $product->sale_price = $new_price; - } - } - - if ( $price_changed ) { - update_post_meta( $post_id, '_sale_price_dates_from', '' ); - update_post_meta( $post_id, '_sale_price_dates_to', '' ); - - if ( $product->regular_price < $product->sale_price ) { - $product->sale_price = ''; - update_post_meta( $post_id, '_sale_price', '' ); - } - - if ( $product->sale_price ) { - update_post_meta( $post_id, '_price', $product->sale_price ); - } else { - update_post_meta( $post_id, '_price', $product->regular_price ); - } - } - } - - // Handle stock - if ( ! $product->is_type( 'grouped' ) ) { - - if ( ! empty( $_REQUEST['change_stock'] ) ) { - update_post_meta( $post_id, '_manage_stock', 'yes' ); - wc_update_product_stock( $post_id, intval( $_REQUEST['_stock'] ) ); - } - - if ( ! empty( $_REQUEST['_manage_stock'] ) ) { - - if ( $_REQUEST['_manage_stock'] == 'yes' ) { - update_post_meta( $post_id, '_manage_stock', 'yes' ); - } else { - update_post_meta( $post_id, '_manage_stock', 'no' ); - wc_update_product_stock( $post_id, 0 ); - } - } - - if ( ! empty( $_REQUEST['_backorders'] ) ) { - update_post_meta( $post_id, '_backorders', wc_clean( $_REQUEST['_backorders'] ) ); - } - - } - - do_action( 'woocommerce_product_bulk_edit_save', $product ); - } - - /** - * Filter the directory for uploads. - * - * @param array $pathdata - * @return array - */ - public function upload_dir( $pathdata ) { - // Change upload dir for downloadable files - if ( isset( $_POST['type'] ) && 'downloadable_product' == $_POST['type'] ) { - if ( empty( $pathdata['subdir'] ) ) { - $pathdata['path'] = $pathdata['path'] . '/woocommerce_uploads'; - $pathdata['url'] = $pathdata['url']. '/woocommerce_uploads'; - $pathdata['subdir'] = '/woocommerce_uploads'; - } else { - $new_subdir = '/woocommerce_uploads' . $pathdata['subdir']; - - $pathdata['path'] = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['path'] ); - $pathdata['url'] = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['url'] ); - $pathdata['subdir'] = str_replace( $pathdata['subdir'], $new_subdir, $pathdata['subdir'] ); - } - } - - return $pathdata; - } - - /** - * Run a filter when uploading a downloadable product. - */ - public function woocommerce_media_upload_downloadable_product() { - do_action( 'media_upload_file' ); - } - - /** - * Protect downloads from ms-files.php in multisite - * - * @param mixed $rewrite - * @return string - */ - public function ms_protect_download_rewite_rules( $rewrite ) { - global $wp_rewrite; - - if ( ! is_multisite() || 'redirect' == get_option( 'woocommerce_file_download_method' ) ) { - return $rewrite; - } - - $rule = "\n# WooCommerce Rules - Protect Files from ms-files.php\n\n"; - $rule .= "\n"; - $rule .= "RewriteEngine On\n"; - $rule .= "RewriteCond %{QUERY_STRING} file=woocommerce_uploads/ [NC]\n"; - $rule .= "RewriteRule /ms-files.php$ - [F]\n"; - $rule .= "\n\n"; - - return $rule . $rewrite; - } - - /** - * Grant downloadable file access to any newly added files on any existing - * orders for this product that have previously been granted downloadable file access - * - * @param int $product_id product identifier - * @param int $variation_id optional product variation identifier - * @param array $downloadable_files newly set files - */ - public function process_product_file_download_paths( $product_id, $variation_id, $downloadable_files ) { - global $wpdb; - - if ( $variation_id ) { - $product_id = $variation_id; - } - - $product = get_product( $product_id ); - $existing_download_ids = array_keys( (array) $product->get_files() ); - $updated_download_ids = array_keys( (array) $downloadable_files ); - - $new_download_ids = array_filter( array_diff( $updated_download_ids, $existing_download_ids ) ); - $removed_download_ids = array_filter( array_diff( $existing_download_ids, $updated_download_ids ) ); - - if ( $new_download_ids || $removed_download_ids ) { - // determine whether downloadable file access has been granted via the typical order completion, or via the admin ajax method - $existing_permissions = $wpdb->get_results( $wpdb->prepare( "SELECT * from {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE product_id = %d GROUP BY order_id", $product_id ) ); - - foreach ( $existing_permissions as $existing_permission ) { - $order = new WC_Order( $existing_permission->order_id ); - - if ( $order->id ) { - // Remove permissions - if ( $removed_download_ids ) { - foreach ( $removed_download_ids as $download_id ) { - if ( apply_filters( 'woocommerce_process_product_file_download_paths_remove_access_to_old_file', true, $download_id, $product_id, $order ) ) { - $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE order_id = %d AND product_id = %d AND download_id = %s", $order->id, $product_id, $download_id ) ); - } - } - } - // Add permissions - if ( $new_download_ids ) { - foreach ( $new_download_ids as $download_id ) { - if ( apply_filters( 'woocommerce_process_product_file_download_paths_grant_access_to_new_file', true, $download_id, $product_id, $order ) ) { - // grant permission if it doesn't already exist - if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT 1 FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions WHERE order_id = %d AND product_id = %d AND download_id = %s", $order->id, $product_id, $download_id ) ) ) { - wc_downloadable_file_permission( $download_id, $product_id, $order ); - } - } - } - } - } - } - } - } -} - -endif; - -return new WC_Admin_CPT_Product(); diff --git a/includes/admin/post-types/class-wc-admin-cpt-shop_coupon.php b/includes/admin/post-types/class-wc-admin-cpt-shop_coupon.php deleted file mode 100644 index eb7720e8541..00000000000 --- a/includes/admin/post-types/class-wc-admin-cpt-shop_coupon.php +++ /dev/null @@ -1,232 +0,0 @@ -type = 'shop_coupon'; - - // Post title fields - add_filter( 'enter_title_here', array( $this, 'enter_title_here' ), 1, 2 ); - add_action( 'edit_form_after_title', array( $this, 'coupon_description_field' ) ); - - // Admin Columns - add_filter( 'manage_edit-shop_coupon_columns', array( $this, 'edit_columns' ) ); - add_action( 'manage_shop_coupon_posts_custom_column', array( $this, 'custom_columns' ), 2 ); - add_filter( 'request', array( $this, 'coupons_by_type_query' ) ); - - // Product filtering - add_action( 'restrict_manage_posts', array( $this, 'coupon_filters' ) ); - - // Call WC_Admin_CPT constructor - parent::__construct(); - } - - /** - * Change title boxes in admin. - * @param string $text - * @param object $post - * @return string - */ - public function enter_title_here( $text, $post ) { - if ( $post->post_type == 'shop_coupon' ) - return __( 'Coupon code', 'woocommerce' ); - - return $text; - } - - /** - * Print coupon description textarea field - * @param WP_Post $post - */ - public function coupon_description_field( $post ) { - if ( $post->post_type != 'shop_coupon' ) - return; - ?> - - "; - $columns["coupon_code"] = __( 'Code', 'woocommerce' ); - $columns["type"] = __( 'Coupon type', 'woocommerce' ); - $columns["amount"] = __( 'Coupon amount', 'woocommerce' ); - $columns["description"] = __( 'Description', 'woocommerce' ); - $columns["products"] = __( 'Product IDs', 'woocommerce' ); - $columns["usage"] = __( 'Usage / Limit', 'woocommerce' ); - $columns["expiry_date"] = __( 'Expiry date', 'woocommerce' ); - - return $columns; - } - - /** - * Define our custom columns shown in admin. - * @param string $column - */ - public function custom_columns( $column ) { - global $post, $woocommerce; - - switch ( $column ) { - case "coupon_code" : - $edit_link = get_edit_post_link( $post->ID ); - $title = _draft_or_post_title(); - $post_type_object = get_post_type_object( $post->post_type ); - $can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID ); - - echo '
' . esc_html( $title ). '
'; - - _post_states( $post ); - - // Get actions - $actions = array(); - - if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) { - if ( 'trash' == $post->post_status ) - $actions['untrash'] = "ID ) ), 'untrash-post_' . $post->ID ) . "'>" . __( 'Restore', 'woocommerce' ) . ""; - elseif ( EMPTY_TRASH_DAYS ) - $actions['trash'] = "" . __( 'Trash', 'woocommerce' ) . ""; - if ( 'trash' == $post->post_status || !EMPTY_TRASH_DAYS ) - $actions['delete'] = "" . __( 'Delete Permanently', 'woocommerce' ) . ""; - } - - $actions = apply_filters( 'post_row_actions', $actions, $post ); - - echo '
'; - - $i = 0; - $action_count = sizeof($actions); - - foreach ( $actions as $action => $link ) { - ++$i; - ( $i == $action_count ) ? $sep = '' : $sep = ' | '; - echo "$link$sep"; - } - echo '
'; - - break; - case "type" : - echo esc_html( wc_get_coupon_type( get_post_meta( $post->ID, 'discount_type', true ) ) ); - break; - case "amount" : - echo esc_html( get_post_meta( $post->ID, 'coupon_amount', true ) ); - break; - case "products" : - $product_ids = get_post_meta( $post->ID, 'product_ids', true ); - $product_ids = $product_ids ? array_map( 'absint', explode( ',', $product_ids ) ) : array(); - if ( sizeof( $product_ids ) > 0 ) - echo esc_html( implode( ', ', $product_ids ) ); - else - echo '–'; - break; - case "usage_limit" : - $usage_limit = get_post_meta( $post->ID, 'usage_limit', true ); - - if ( $usage_limit ) - echo esc_html( $usage_limit ); - else - echo '–'; - break; - case "usage" : - $usage_count = absint( get_post_meta( $post->ID, 'usage_count', true ) ); - $usage_limit = esc_html( get_post_meta($post->ID, 'usage_limit', true) ); - - if ( $usage_limit ) - printf( __( '%s / %s', 'woocommerce' ), $usage_count, $usage_limit ); - else - printf( __( '%s / ∞', 'woocommerce' ), $usage_count ); - break; - case "expiry_date" : - $expiry_date = get_post_meta($post->ID, 'expiry_date', true); - - if ( $expiry_date ) - echo esc_html( date_i18n( 'F j, Y', strtotime( $expiry_date ) ) ); - else - echo '–'; - break; - case "description" : - echo wp_kses_post( $post->post_excerpt ); - break; - } - } - - /** - * Filter the coupons by the type. - * - * @param array $vars - * @return array - */ - public function coupons_by_type_query( $vars ) { - global $typenow, $wp_query; - if ( $typenow == 'shop_coupon' && ! empty( $_GET['coupon_type'] ) ) { - - $vars['meta_key'] = 'discount_type'; - $vars['meta_value'] = wc_clean( $_GET['coupon_type'] ); - - } - - return $vars; - } - - /** - * Show custom filters to filter coupons by type. - */ - public function coupon_filters() { - global $woocommerce, $typenow, $wp_query; - - if ( $typenow != 'shop_coupon' ) - return; - - // Type - ?> - - type = 'shop_order'; - - // Before data updates - add_filter( 'wp_insert_post_data', array( $this, 'wp_insert_post_data' ) ); - - // Admin Columns - add_filter( 'manage_edit-' . $this->type . '_columns', array( $this, 'edit_columns' ) ); - add_action( 'manage_' . $this->type . '_posts_custom_column', array( $this, 'custom_columns' ), 2 ); - - // Views and filtering - add_filter( 'views_edit-shop_order', array( $this, 'custom_order_views' ) ); - add_filter( 'bulk_actions-edit-shop_order', array( $this, 'bulk_actions' ) ); - add_filter( 'post_row_actions', array( $this, 'remove_row_actions' ), 10, 1 ); - add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_orders' ) ); - add_filter( 'request', array( $this, 'orders_by_customer_query' ) ); - add_filter( "manage_edit-shop_order_sortable_columns", array( $this, 'custom_shop_order_sort' ) ); - add_filter( 'request', array( $this, 'custom_shop_order_orderby' ) ); - add_filter( 'get_search_query', array( $this, 'shop_order_search_label' ) ); - add_filter( 'query_vars', array( $this, 'add_custom_query_var' ) ); - add_action( 'parse_query', array( $this, 'shop_order_search_custom_fields' ) ); - add_action( 'before_delete_post', array( $this, 'delete_order_items' ) ); - - // Bulk edit - add_action( 'admin_footer', array( $this, 'bulk_admin_footer' ), 10 ); - add_action( 'load-edit.php', array( $this, 'bulk_action' ) ); - add_action( 'admin_notices', array( $this, 'bulk_admin_notices' ) ); - - // Call WC_Admin_CPT constructor - parent::__construct(); - } - - /** - * Forces the order posts to have a title in a certain format (containing the date) - * - * @param array $data - * @return array - */ - public function wp_insert_post_data( $data ) { - global $post; - - if ( $data['post_type'] == 'shop_order' && isset( $data['post_date'] ) ) { - - $order_title = 'Order'; - if ( $data['post_date'] ) { - $order_title.= ' – ' . date_i18n( 'F j, Y @ h:i A', strtotime( $data['post_date'] ) ); - } - - $data['post_title'] = $order_title; - } - - return $data; - } - - /** - * Change the columns shown in admin. - */ - public function edit_columns( $existing_columns ) { - $columns = array(); - - $columns['cb'] = ''; - $columns['order_status'] = '' . esc_attr__( 'Status', 'woocommerce' ) . ''; - $columns['order_title'] = __( 'Order', 'woocommerce' ); - $columns['order_items'] = __( 'Purchased', 'woocommerce' ); - $columns['shipping_address'] = __( 'Ship to', 'woocommerce' ); - - $columns['customer_message'] = '' . esc_attr__( 'Customer Message', 'woocommerce' ) . ''; - $columns['order_notes'] = '' . esc_attr__( 'Order Notes', 'woocommerce' ) . ''; - $columns['order_date'] = __( 'Date', 'woocommerce' ); - $columns['order_total'] = __( 'Total', 'woocommerce' ); - $columns['order_actions'] = __( 'Actions', 'woocommerce' ); - - return $columns; - } - - /** - * Define our custom columns shown in admin. - * @param string $column - */ - public function custom_columns( $column ) { - global $post, $woocommerce, $the_order; - - if ( empty( $the_order ) || $the_order->id != $post->ID ) { - $the_order = new WC_Order( $post->ID ); - } - - switch ( $column ) { - case 'order_status' : - - printf( '%s', sanitize_title( $the_order->get_status() ), wc_get_order_status_name( $the_order->get_status() ), wc_get_order_status_name( $the_order->get_status() ) ); - - break; - case 'order_date' : - - if ( '0000-00-00 00:00:00' == $post->post_date ) { - $t_time = $h_time = __( 'Unpublished', 'woocommerce' ); - } else { - $t_time = get_the_time( __( 'Y/m/d g:i:s A', 'woocommerce' ), $post ); - $gmt_time = strtotime( $post->post_date_gmt . ' UTC' ); - $time_diff = current_time( 'timestamp', 1 ) - $gmt_time; - $h_time = get_the_time( __( 'Y/m/d', 'woocommerce' ), $post ); - } - - echo '' . esc_html( apply_filters( 'post_date_column_time', $h_time, $post ) ) . ''; - - break; - case 'customer_message' : - - if ( $the_order->customer_message ) - echo '' . __( 'Yes', 'woocommerce' ) . ''; - else - echo ''; - - break; - case 'billing_address' : - if ( $the_order->get_formatted_billing_address() ) - echo '' . esc_html( preg_replace( '##i', ', ', $the_order->get_formatted_billing_address() ) ) .''; - else - echo '–'; - - if ( $the_order->payment_method_title ) - echo '' . __( 'Via', 'woocommerce' ) . ' ' . esc_html( $the_order->payment_method_title ) . ''; - break; - case 'order_items' : - - printf( '' . _n( '%d item', '%d items', sizeof( $the_order->get_items() ), 'woocommerce' ) . '', sizeof( $the_order->get_items() ) ); - - if ( sizeof( $the_order->get_items() ) > 0 ) { - - echo '
+ get_sku() ) echo $_product->get_sku() . ' - '; ?> + + [?] + +
'; - - foreach ( $the_order->get_items() as $item ) { - $_product = apply_filters( 'woocommerce_order_item_product', $the_order->get_product_from_item( $item ), $item ); - $item_meta = new WC_Order_Item_Meta( $item['item_meta'] ); - $item_meta_html = $item_meta->display( true, true ); - ?> - - - - - '; - - } else echo '–'; - break; - case 'shipping_address' : - if ( $the_order->get_formatted_shipping_address() ) - echo ''. esc_html( preg_replace( '##i', ', ', $the_order->get_formatted_shipping_address() ) ) .''; - else - echo '–'; - - if ( $the_order->get_shipping_method() ) - echo '' . __( 'Via', 'woocommerce' ) . ' ' . esc_html( $the_order->get_shipping_method() ) . ''; - - break; - case 'order_notes' : - - if ( $post->comment_count ) { - - // check the status of the post - ( $post->post_status !== 'trash' ) ? $status = '' : $status = 'post-trashed'; - - $latest_notes = get_comments( array( - 'post_id' => $post->ID, - 'number' => 1, - 'status' => $status - ) ); - - $latest_note = current( $latest_notes ); - - if ( $post->comment_count == 1 ) { - echo '' . __( 'Yes', 'woocommerce' ) . ''; - } else { - $note_tip = isset( $latest_note->comment_content ) ? esc_attr( $latest_note->comment_content . '' . sprintf( _n( 'plus %d other note', 'plus %d other notes', ( $post->comment_count - 1 ), 'woocommerce' ), ( $post->comment_count - 1 ) ) . '' ) : sprintf( _n( '%d note', '%d notes', $post->comment_count, 'woocommerce' ), $post->comment_count ); - - echo '' . __( 'Yes', 'woocommerce' ) . ''; - } - - } else { - echo ''; - } - - break; - case 'order_total' : - echo esc_html( strip_tags( $the_order->get_formatted_order_total() ) ); - - if ( $the_order->payment_method_title ) { - echo '' . __( 'Via', 'woocommerce' ) . ' ' . esc_html( $the_order->payment_method_title ) . ''; - } - break; - case 'order_title' : - - $customer_tip = ''; - - if ( $address = $the_order->get_formatted_billing_address() ) { - $customer_tip .= __( 'Billing:', 'woocommerce' ) . ' ' . $address . '

'; - } - - if ( $the_order->billing_phone ) { - $customer_tip .= __( 'Tel:', 'woocommerce' ) . ' ' . $the_order->billing_phone; - } - - echo '
'; - - if ( $the_order->user_id ) { - $user_info = get_userdata( $the_order->user_id ); - } - - if ( ! empty( $user_info ) ) { - - $username = ''; - - if ( $user_info->first_name || $user_info->last_name ) { - $username .= esc_html( ucfirst( $user_info->first_name ) . ' ' . ucfirst( $user_info->last_name ) ); - } else { - $username .= esc_html( ucfirst( $user_info->display_name ) ); - } - - $username .= ''; - - } else { - if ( $the_order->billing_first_name || $the_order->billing_last_name ) { - $username = trim( $the_order->billing_first_name . ' ' . $the_order->billing_last_name ); - } else { - $username = __( 'Guest', 'woocommerce' ); - } - } - - printf( __( '%s by %s', 'woocommerce' ), '' . esc_attr( $the_order->get_order_number() ) . '', $username ); - - if ( $the_order->billing_email ) { - echo ''; - } - - echo '
'; - - break; - case 'order_actions' : - - ?>

- has_status( array( 'pending', 'on-hold' ) ) ) { - $actions['processing'] = array( - 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_processing&order_id=' . $post->ID ), 'woocommerce-mark-order-processing' ), - 'name' => __( 'Processing', 'woocommerce' ), - 'action' => "processing" - ); - } - - if ( $the_order->has_status( array( 'pending', 'on-hold', 'processing' ) ) ) { - $actions['complete'] = array( - 'url' => wp_nonce_url( admin_url( 'admin-ajax.php?action=woocommerce_mark_order_complete&order_id=' . $post->ID ), 'woocommerce-mark-order-complete' ), - 'name' => __( 'Complete', 'woocommerce' ), - 'action' => "complete" - ); - } - - $actions['view'] = array( - 'url' => admin_url( 'post.php?post=' . $post->ID . '&action=edit' ), - 'name' => __( 'View', 'woocommerce' ), - 'action' => "view" - ); - - $actions = apply_filters( 'woocommerce_admin_order_actions', $actions, $the_order ); - - foreach ( $actions as $action ) { - printf( '%s', esc_attr( $action['action'] ), esc_url( $action['url'] ), esc_attr( $action['name'] ), esc_attr( $action['name'] ) ); - } - - do_action( 'woocommerce_admin_order_actions_end', $the_order ); - ?> -

- - 0 ) { - $vars['meta_key'] = '_customer_user'; - $vars['meta_value'] = (int) $_GET['_customer_user']; - } - - return $vars; - } - - /** - * Make order columns sortable. - * - * https://gist.github.com/906872 - * - * @access public - * @param mixed $columns - * @return array - */ - public function custom_shop_order_sort( $columns ) { - $custom = array( - 'order_title' => 'ID', - 'order_total' => 'order_total', - 'order_date' => 'date' - ); - unset( $columns['comments'] ); - - return wp_parse_args( $custom, $columns ); - } - - /** - * Order column orderby/request. - * - * @access public - * @param mixed $vars - * @return array - */ - public function custom_shop_order_orderby( $vars ) { - global $typenow, $wp_query; - - if ( 'shop_order' != $typenow ) { - return $vars; - } - - // Sorting - if ( isset( $vars['orderby'] ) ) { - if ( 'order_total' == $vars['orderby'] ) { - $vars = array_merge( $vars, array( - 'meta_key' => '_order_total', - 'orderby' => 'meta_value_num' - ) ); - } - } - - return $vars; - } - - /** - * Search custom fields as well as content. - * - * @access public - * @param WP_Query $wp - * @return void - */ - public function shop_order_search_custom_fields( $wp ) { - global $pagenow, $wpdb; - - if ( 'edit.php' != $pagenow || empty( $wp->query_vars['s'] ) || $wp->query_vars['post_type'] != 'shop_order' ) { - return; - } - - $search_fields = array_map( 'wc_clean', apply_filters( 'woocommerce_shop_order_search_fields', array( - '_order_key', - '_billing_company', - '_billing_address_1', - '_billing_address_2', - '_billing_city', - '_billing_postcode', - '_billing_country', - '_billing_state', - '_billing_email', - '_billing_phone', - '_shipping_address_1', - '_shipping_address_2', - '_shipping_city', - '_shipping_postcode', - '_shipping_country', - '_shipping_state' - ) ) ); - - $search_order_id = str_replace( 'Order #', '', $_GET['s'] ); - if ( ! is_numeric( $search_order_id ) ) { - $search_order_id = 0; - } - - // Search orders - $post_ids = array_unique( array_merge( - $wpdb->get_col( - $wpdb->prepare( " - SELECT p1.post_id - FROM {$wpdb->postmeta} p1 - INNER JOIN {$wpdb->postmeta} p2 ON p1.post_id = p2.post_id - WHERE - ( p1.meta_key = '_billing_first_name' AND p2.meta_key = '_billing_last_name' AND CONCAT(p1.meta_value, ' ', p2.meta_value) LIKE '%%%s%%' ) - OR - ( p1.meta_key = '_shipping_first_name' AND p2.meta_key = '_shipping_last_name' AND CONCAT(p1.meta_value, ' ', p2.meta_value) LIKE '%%%s%%' ) - OR - ( p1.meta_key IN ('" . implode( "','", $search_fields ) . "') AND p1.meta_value LIKE '%%%s%%' ) - ", - esc_attr( $_GET['s'] ), esc_attr( $_GET['s'] ), esc_attr( $_GET['s'] ) - ) - ), - $wpdb->get_col( - $wpdb->prepare( " - SELECT order_id - FROM {$wpdb->prefix}woocommerce_order_items as order_items - WHERE order_item_name LIKE '%%%s%%' - ", - esc_attr( $_GET['s'] ) - ) - ), - array( $search_order_id ) - ) ); - - // Remove s - we don't want to search order name - unset( $wp->query_vars['s'] ); - - // so we know we're doing this - $wp->query_vars['shop_order_search'] = true; - - // Search by found posts - $wp->query_vars['post__in'] = $post_ids; - } - - /** - * Change the label when searching orders. - * - * @access public - * @param mixed $query - * @return string - */ - public function shop_order_search_label( $query ) { - global $pagenow, $typenow; - - if ( 'edit.php' != $pagenow ) { - return $query; - } - - if ( $typenow != 'shop_order' ) { - return $query; - } - - if ( ! get_query_var( 'shop_order_search' ) ) { - return $query; - } - - return wp_unslash( $_GET['s'] ); - } - - /** - * Query vars for custom searches. - * - * @access public - * @param mixed $public_query_vars - * @return array - */ - public function add_custom_query_var( $public_query_vars ) { - $public_query_vars[] = 'sku'; - $public_query_vars[] = 'shop_order_search'; - - return $public_query_vars; - } - - /** - * Remove item meta on permanent deletion - * - * @access public - * @return void - **/ - public function delete_order_items( $postid ) { - global $wpdb; - - if ( get_post_type( $postid ) == 'shop_order' ) { - do_action( 'woocommerce_delete_order_items', $postid ); - - $wpdb->query( " - DELETE {$wpdb->prefix}woocommerce_order_items, {$wpdb->prefix}woocommerce_order_itemmeta - FROM {$wpdb->prefix}woocommerce_order_items - JOIN {$wpdb->prefix}woocommerce_order_itemmeta ON {$wpdb->prefix}woocommerce_order_items.order_item_id = {$wpdb->prefix}woocommerce_order_itemmeta.order_item_id - WHERE {$wpdb->prefix}woocommerce_order_items.order_id = '{$postid}'; - " ); - - do_action( 'woocommerce_deleted_order_items', $postid ); - } - } - - /** - * Add extra bulk action options to mark orders as complete or processing - * - * Using Javascript until WordPress core fixes: http://core.trac.wordpress.org/ticket/16031 - * - * @access public - * @return void - */ - public function bulk_admin_footer() { - global $post_type; - - if ( 'shop_order' == $post_type ) { - ?> - - current_action(); - - switch ( $action ) { - case 'mark_completed': - $new_status = 'completed'; - $report_action = 'marked_complete'; - break; - case 'mark_processing': - $new_status = 'processing'; - $report_action = 'marked_processing'; - break; - case 'mark_on-hold' : - $new_status = 'on-hold'; - $report_action = 'marked_on-hold'; - break; - break; - default: - return; - } - - $changed = 0; - - $post_ids = array_map( 'absint', (array) $_REQUEST['post'] ); - - foreach ( $post_ids as $post_id ) { - $order = new WC_Order( $post_id ); - $order->update_status( $new_status, __( 'Order status changed by bulk edit:', 'woocommerce' ) ); - $changed++; - } - - $sendback = add_query_arg( array( 'post_type' => 'shop_order', $report_action => true, 'changed' => $changed, 'ids' => join( ',', $post_ids ) ), '' ); - wp_redirect( $sendback ); - exit(); - } - - /** - * Show confirmation message that order status changed for number of orders - * - * @access public - * @return void - */ - public function bulk_admin_notices() { - global $post_type, $pagenow; - - if ( isset( $_REQUEST['marked_complete'] ) || isset( $_REQUEST['marked_processing'] ) || isset( $_REQUEST['marked_on-hold'] ) ) { - $number = isset( $_REQUEST['changed'] ) ? absint( $_REQUEST['changed'] ) : 0; - - if ( 'edit.php' == $pagenow && 'shop_order' == $post_type ) { - $message = sprintf( _n( 'Order status changed.', '%s order statuses changed.', $number, 'woocommerce' ), number_format_i18n( $number ) ); - echo '

' . $message . '

'; - } - } - } - -} - -endif; - -return new WC_Admin_CPT_Shop_Order(); diff --git a/includes/admin/post-types/class-wc-admin-cpt.php b/includes/admin/post-types/class-wc-admin-cpt.php deleted file mode 100644 index 3399e07d12e..00000000000 --- a/includes/admin/post-types/class-wc-admin-cpt.php +++ /dev/null @@ -1,50 +0,0 @@ -type ) { - $obj = get_post_type_object( $this->type ); - - $strings['insertIntoPost'] = sprintf( __( 'Insert into %s', 'woocommerce' ), $obj->labels->singular_name ); - $strings['uploadedToThisPost'] = sprintf( __( 'Uploaded to this %s', 'woocommerce' ), $obj->labels->singular_name ); - } - - return $strings; - } -} - -endif; \ No newline at end of file diff --git a/includes/admin/views/html-admin-page-status-report.php b/includes/admin/views/html-admin-page-status-report.php index f0fe8147314..376e1c3598d 100644 --- a/includes/admin/views/html-admin-page-status-report.php +++ b/includes/admin/views/html-admin-page-status-report.php @@ -452,7 +452,7 @@ $found_files = array(); foreach ( $template_paths as $plugin_name => $template_path ) { - $scanned_files[ $plugin_name ] = $this->scan_template_files( $template_path ); + $scanned_files[ $plugin_name ] = WC_Admin_Status::scan_template_files( $template_path ); } foreach ( $scanned_files as $plugin_name => $files ) { @@ -470,8 +470,8 @@ } if ( $theme_file ) { - $core_version = $this->get_file_version( WC()->plugin_path() . '/templates/' . $file ); - $theme_version = $this->get_file_version( $theme_file ); + $core_version = WC_Admin_Status::get_file_version( WC()->plugin_path() . '/templates/' . $file ); + $theme_version = WC_Admin_Status::get_file_version( $theme_file ); if ( $core_version && ( empty( $theme_version ) || version_compare( $theme_version, $core_version, '<' ) ) ) { $found_files[ $plugin_name ][] = sprintf( __( '%s version %s is out of date. The core version is %s', 'woocommerce' ), basename( $theme_file ), $theme_version ? $theme_version : '-', $core_version ); diff --git a/includes/admin/views/html-admin-page-status.php b/includes/admin/views/html-admin-page-status.php index 927fd93ad20..b26718a728d 100644 --- a/includes/admin/views/html-admin-page-status.php +++ b/includes/admin/views/html-admin-page-status.php @@ -16,13 +16,13 @@ status_tools(); + WC_Admin_Status::status_tools(); break; case "logs" : - $this->status_logs(); + WC_Admin_Status::status_logs(); break; default : - $this->status_report(); + WC_Admin_Status::status_report(); break; } ?> diff --git a/includes/class-wc-ajax.php b/includes/class-wc-ajax.php index 3b7da541f14..101e6a60612 100644 --- a/includes/class-wc-ajax.php +++ b/includes/class-wc-ajax.php @@ -67,6 +67,8 @@ class WC_AJAX { add_action( 'wp_ajax_nopriv_woocommerce_' . $ajax_event, array( __CLASS__, $ajax_event ) ); } } + + add_action( 'wp_ajax_page_slurp', array( 'WC_Gateway_Mijireh', 'page_slurp' ) ); } /** @@ -653,7 +655,7 @@ class WC_AJAX { $image_id = 0; $variation = get_post( $variation_id ); // Get the variation object - include( 'admin/post-types/meta-boxes/views/html-variation-admin.php' ); + include( 'admin/meta-boxes/views/html-variation-admin.php' ); } die(); @@ -888,7 +890,7 @@ class WC_AJAX { } else { $file_count = sprintf( __( 'File %d', 'woocommerce' ), $file_counter ); } - include( 'admin/post-types/meta-boxes/views/html-order-download-permission.php' ); + include( 'admin/meta-boxes/views/html-order-download-permission.php' ); } } } @@ -1000,7 +1002,7 @@ class WC_AJAX { $item = apply_filters( 'woocommerce_ajax_order_item', $item, $item_id ); - include( 'admin/post-types/meta-boxes/views/html-order-item.php' ); + include( 'admin/meta-boxes/views/html-order-item.php' ); // Quit out die(); @@ -1029,7 +1031,7 @@ class WC_AJAX { wc_add_order_item_meta( $item_id, '_line_tax', '' ); } - include( 'admin/post-types/meta-boxes/views/html-order-fee.php' ); + include( 'admin/meta-boxes/views/html-order-fee.php' ); // Quit out die(); @@ -1342,7 +1344,7 @@ class WC_AJAX { wc_add_order_item_meta( $item_id, 'shipping_tax_amount', $item['shipping_tax_amount'] ); } - include( 'admin/post-types/meta-boxes/views/html-order-tax.php' ); + include( 'admin/meta-boxes/views/html-order-tax.php' ); } $tax_row_html = ob_get_clean(); diff --git a/includes/class-wc-post-data.php b/includes/class-wc-post-data.php index e215741d1db..999f487b018 100644 --- a/includes/class-wc-post-data.php +++ b/includes/class-wc-post-data.php @@ -27,6 +27,8 @@ class WC_Post_Data { add_action( 'edited_term', array( __CLASS__, 'edited_term' ), 10, 3 ); add_filter( 'update_order_item_metadata', array( __CLASS__, 'update_order_item_metadata' ), 10, 5 ); add_filter( 'update_post_metadata', array( __CLASS__, 'update_post_metadata' ), 10, 5 ); + add_filter( 'wp_insert_post_data', array( __CLASS__, 'wp_insert_post_data' ) ); + add_action( 'pre_post_update', array( __CLASS__, 'pre_post_update' ) ); } /** @@ -112,6 +114,51 @@ class WC_Post_Data { } return $check; } + + /** + * Forces the order posts to have a title in a certain format (containing the date). + * Forces certain product data based on the product's type, e.g. grouped products cannot have a parent. + * + * @param array $data + * @return array + */ + public static function wp_insert_post_data( $data ) { + global $post; + + if ( 'shop_order' === $data['post_type'] && isset( $data['post_date'] ) ) { + $order_title = 'Order'; + if ( $data['post_date'] ) { + $order_title.= ' – ' . date_i18n( 'F j, Y @ h:i A', strtotime( $data['post_date'] ) ); + } + $data['post_title'] = $order_title; + } + + elseif ( 'product' === $data['post_type'] && isset( $_POST['product-type'] ) ) { + $product_type = stripslashes( $_POST['product-type'] ); + switch ( $product_type ) { + case 'grouped' : + case 'variable' : + $data['post_parent'] = 0; + break; + } + } + + return $data; + } + + /** + * Some functions, like the term recount, require the visibility to be set prior. Lets save that here. + * + * @param int $post_id + */ + public function pre_post_update( $post_id ) { + if ( isset( $_POST['_visibility'] ) ) { + update_post_meta( $post_id, '_visibility', stripslashes( $_POST['_visibility'] ) ); + } + if ( isset( $_POST['_stock_status'] ) ) { + wc_update_product_stock_status( $post_id, wc_clean( $_POST['_stock_status'] ) ); + } + } } WC_Post_Data::init(); \ No newline at end of file diff --git a/includes/wc-core-functions.php b/includes/wc-core-functions.php index c73abbb0dd3..d071c416c40 100644 --- a/includes/wc-core-functions.php +++ b/includes/wc-core-functions.php @@ -12,14 +12,12 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly -// Include core functions -include( 'wc-cart-functions.php' ); +// Include core functions (available in both admin and frontend) include( 'wc-conditional-functions.php' ); include( 'wc-coupon-functions.php' ); include( 'wc-user-functions.php' ); include( 'wc-deprecated-functions.php' ); include( 'wc-formatting-functions.php' ); -include( 'wc-notice-functions.php' ); include( 'wc-order-functions.php' ); include( 'wc-page-functions.php' ); include( 'wc-product-functions.php' ); @@ -452,3 +450,27 @@ function wc_fix_rewrite_rules( $rules ) { return $rules; } add_filter( 'rewrite_rules_array', 'wc_fix_rewrite_rules' ); + +/** + * Protect downloads from ms-files.php in multisite + * + * @param mixed $rewrite + * @return string + */ +function wc_ms_protect_download_rewite_rules( $rewrite ) { + global $wp_rewrite; + + if ( ! is_multisite() || 'redirect' == get_option( 'woocommerce_file_download_method' ) ) { + return $rewrite; + } + + $rule = "\n# WooCommerce Rules - Protect Files from ms-files.php\n\n"; + $rule .= "\n"; + $rule .= "RewriteEngine On\n"; + $rule .= "RewriteCond %{QUERY_STRING} file=woocommerce_uploads/ [NC]\n"; + $rule .= "RewriteRule /ms-files.php$ - [F]\n"; + $rule .= "\n\n"; + + return $rule . $rewrite; +} +add_filter( 'mod_rewrite_rules', 'wc_ms_protect_download_rewite_rules' ); \ No newline at end of file diff --git a/woocommerce.php b/woocommerce.php index 2af2b61a1d3..ae5f8f8878f 100644 --- a/woocommerce.php +++ b/woocommerce.php @@ -202,7 +202,7 @@ final class WooCommerce { } elseif ( strpos( $class, 'wc_shortcode_' ) === 0 ) { $path = $this->plugin_path() . '/includes/shortcodes/'; } elseif ( strpos( $class, 'wc_meta_box' ) === 0 ) { - $path = $this->plugin_path() . '/includes/admin/post-types/meta-boxes/'; + $path = $this->plugin_path() . '/includes/admin/meta-boxes/'; } elseif ( strpos( $class, 'wc_admin' ) === 0 ) { $path = $this->plugin_path() . '/includes/admin/'; } @@ -263,8 +263,6 @@ final class WooCommerce { include_once( 'includes/class-wc-download-handler.php' ); include_once( 'includes/class-wc-comments.php' ); include_once( 'includes/class-wc-post-data.php' ); - include_once( 'includes/abstracts/abstract-wc-session.php' ); - include_once( 'includes/class-wc-session-handler.php' ); if ( is_admin() ) { include_once( 'includes/admin/class-wc-admin.php' ); @@ -299,10 +297,6 @@ final class WooCommerce { include_once( 'includes/class-wc-countries.php' ); // Defines countries and states include_once( 'includes/class-wc-integrations.php' ); // Loads integrations include_once( 'includes/class-wc-cache-helper.php' ); // Cache Helper - include_once( 'includes/class-wc-https.php' ); // https Helper - - // Include template hooks in time for themes to remove/modify them - include_once( 'includes/wc-template-hooks.php' ); // Download/update languages include_once( 'includes/class-wc-language-pack-upgrader.php' ); @@ -319,6 +313,14 @@ final class WooCommerce { * Include required frontend files. */ public function frontend_includes() { + // Functions + include_once( 'includes/wc-cart-functions.php' ); + include_once( 'includes/wc-notice-functions.php' ); + + // Classes + include_once( 'includes/abstracts/abstract-wc-session.php' ); + include_once( 'includes/class-wc-session-handler.php' ); + include_once( 'includes/wc-template-hooks.php' ); include_once( 'includes/class-wc-template-loader.php' ); // Template Loader include_once( 'includes/class-wc-frontend-scripts.php' ); // Frontend Scripts include_once( 'includes/class-wc-form-handler.php' ); // Form Handlers @@ -326,13 +328,16 @@ final class WooCommerce { include_once( 'includes/class-wc-tax.php' ); // Tax class include_once( 'includes/class-wc-customer.php' ); // Customer class include_once( 'includes/class-wc-shortcodes.php' ); // Shortcodes class + include_once( 'includes/class-wc-https.php' ); // https Helper } /** * Function used to Init WooCommerce Template Functions - This makes them pluggable by plugins and themes. */ public function include_template_functions() { - include_once( 'includes/wc-template-functions.php' ); + if ( ! is_admin() || defined( 'DOING_AJAX' ) ) { + include_once( 'includes/wc-template-functions.php' ); + } } /** @@ -363,18 +368,18 @@ final class WooCommerce { // Set up localisation $this->load_plugin_textdomain(); - // Session class, handles session data for users - can be overwritten if custom handler is needed - $session_class = apply_filters( 'woocommerce_session_handler', 'WC_Session_Handler' ); - // Load class instances $this->product_factory = new WC_Product_Factory(); // Product Factory to create new product instances $this->countries = new WC_Countries(); // Countries class $this->integrations = new WC_Integrations(); // Integrations class - $this->session = new $session_class(); // Classes/actions loaded for the frontend and for ajax requests if ( ! is_admin() || defined( 'DOING_AJAX' ) ) { + // Session class, handles session data for users - can be overwritten if custom handler is needed + $session_class = apply_filters( 'woocommerce_session_handler', 'WC_Session_Handler' ); + // Class instances + $this->session = new $session_class(); $this->cart = new WC_Cart(); // Cart class, stores the cart contents $this->customer = new WC_Customer(); // Customer class, handles data such as customer location } @@ -394,8 +399,9 @@ final class WooCommerce { 'woocommerce_created_customer' ); - foreach ( $email_actions as $action ) + foreach ( $email_actions as $action ) { add_action( $action, array( $this, 'send_transactional_email' ), 10, 10 ); + } // Init action do_action( 'woocommerce_init' );
- get_sku() ) echo $_product->get_sku() . ' - '; ?> - - [?] - -