diff --git a/includes/admin/class-wc-admin-settings.php b/includes/admin/class-wc-admin-settings.php index 6e0043d7892..63f4ad5e019 100644 --- a/includes/admin/class-wc-admin-settings.php +++ b/includes/admin/class-wc-admin-settings.php @@ -606,7 +606,7 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) : $val ) { - echo ''; + echo ''; // WPCS: XSS ok. } } ?> @@ -722,7 +722,8 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) : } // Options to update will be stored here and saved later. - $update_options = array(); + $update_options = array(); + $autoload_options = array(); // Loop options and get values to save. foreach ( $options as $option ) { @@ -825,6 +826,8 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) : $update_options[ $option_name ] = $value; } + $autoload_options[ $option_name ] = isset( $option['autoload'] ) ? (bool) $option['autoload'] : true; + /** * Fire an action before saved. * @@ -835,7 +838,7 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) : // Save all options in our array. foreach ( $update_options as $name => $value ) { - update_option( $name, $value ); + update_option( $name, $value, $autoload_options[ $name ] ? 'yes' : 'no' ); } return true; diff --git a/includes/admin/settings/class-wc-settings-shipping.php b/includes/admin/settings/class-wc-settings-shipping.php index 43853e1a1b1..2075f86ffb9 100644 --- a/includes/admin/settings/class-wc-settings-shipping.php +++ b/includes/admin/settings/class-wc-settings-shipping.php @@ -2,377 +2,369 @@ /** * WooCommerce Shipping Settings * - * @author WooThemes - * @category Admin * @package WooCommerce/Admin * @version 2.6.0 */ -if ( ! defined( 'ABSPATH' ) ) { - exit; +defined( 'ABSPATH' ) || exit; + +if ( class_exists( 'WC_Settings_Shipping', false ) ) { + return new WC_Settings_Shipping(); } -if ( ! class_exists( 'WC_Settings_Shipping', false ) ) : +/** + * WC_Settings_Shipping. + */ +class WC_Settings_Shipping extends WC_Settings_Page { /** - * WC_Settings_Shipping. + * Constructor. */ - class WC_Settings_Shipping extends WC_Settings_Page { + public function __construct() { + $this->id = 'shipping'; + $this->label = __( 'Shipping', 'woocommerce' ); - /** - * Constructor. - */ - public function __construct() { - $this->id = 'shipping'; - $this->label = __( 'Shipping', 'woocommerce' ); + parent::__construct(); + } - parent::__construct(); - } + /** + * Add this page to settings. + * + * @param array $pages Current pages. + * @return array|mixed + */ + public function add_settings_page( $pages ) { + return wc_shipping_enabled() ? parent::add_settings_page( $pages ) : $pages; + } - /** - * Add this page to settings. - * - * @param array $pages - * - * @return array|mixed - */ - public function add_settings_page( $pages ) { - return wc_shipping_enabled() ? parent::add_settings_page( $pages ) : $pages; - } + /** + * Get sections. + * + * @return array + */ + public function get_sections() { + $sections = array( + '' => __( 'Shipping zones', 'woocommerce' ), + 'options' => __( 'Shipping options', 'woocommerce' ), + 'classes' => __( 'Shipping classes', 'woocommerce' ), + ); - /** - * Get sections. - * - * @return array - */ - public function get_sections() { - $sections = array( - '' => __( 'Shipping zones', 'woocommerce' ), - 'options' => __( 'Shipping options', 'woocommerce' ), - 'classes' => __( 'Shipping classes', 'woocommerce' ), - ); - - if ( ! defined( 'WC_INSTALLING' ) ) { - // Load shipping methods so we can show any global options they may have. - $shipping_methods = WC()->shipping->load_shipping_methods(); - - foreach ( $shipping_methods as $method ) { - if ( ! $method->has_settings() ) { - continue; - } - $title = empty( $method->method_title ) ? ucfirst( $method->id ) : $method->method_title; - $sections[ strtolower( $method->id ) ] = esc_html( $title ); - } - } - - return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections ); - } - - /** - * Get settings array. - * - * @param string $current_section - * - * @return array - */ - public function get_settings( $current_section = '' ) { - $settings = array(); - - if ( '' === $current_section ) { - $settings = apply_filters( - 'woocommerce_shipping_settings', array( - - array( - 'title' => __( 'Shipping options', 'woocommerce' ), - 'type' => 'title', - 'id' => 'shipping_options', - ), - - array( - 'title' => __( 'Calculations', 'woocommerce' ), - 'desc' => __( 'Enable the shipping calculator on the cart page', 'woocommerce' ), - 'id' => 'woocommerce_enable_shipping_calc', - 'default' => 'yes', - 'type' => 'checkbox', - 'checkboxgroup' => 'start', - 'autoload' => false, - ), - - array( - 'desc' => __( 'Hide shipping costs until an address is entered', 'woocommerce' ), - 'id' => 'woocommerce_shipping_cost_requires_address', - 'default' => 'no', - 'type' => 'checkbox', - 'checkboxgroup' => 'end', - 'autoload' => false, - ), - - array( - 'title' => __( 'Shipping destination', 'woocommerce' ), - 'desc' => __( 'This controls which shipping address is used by default.', 'woocommerce' ), - 'id' => 'woocommerce_ship_to_destination', - 'default' => 'billing', - 'type' => 'radio', - 'options' => array( - 'shipping' => __( 'Default to customer shipping address', 'woocommerce' ), - 'billing' => __( 'Default to customer billing address', 'woocommerce' ), - 'billing_only' => __( 'Force shipping to the customer billing address', 'woocommerce' ), - ), - 'autoload' => false, - 'desc_tip' => true, - 'show_if_checked' => 'option', - ), - - array( - 'title' => __( 'Debug mode', 'woocommerce' ), - 'desc' => __( 'Enable debug mode', 'woocommerce' ), - 'desc_tip' => __( 'Enable shipping debug mode to show matching shipping zones and to bypass shipping rate cache.', 'woocommerce' ), - 'id' => 'woocommerce_shipping_debug_mode', - 'default' => 'no', - 'type' => 'checkbox', - 'autoload' => false, - ), - - array( - 'type' => 'sectionend', - 'id' => 'shipping_options', - ), - - ) - ); - } - - return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section ); - } - - /** - * Output the settings. - */ - public function output() { - global $current_section, $hide_save_button; - - // Load shipping methods so we can show any global options they may have + if ( ! defined( 'WC_INSTALLING' ) ) { + // Load shipping methods so we can show any global options they may have. $shipping_methods = WC()->shipping->load_shipping_methods(); - if ( '' === $current_section ) { - $this->output_zones_screen(); - } elseif ( 'options' === $current_section ) { - $settings = $this->get_settings(); - WC_Admin_Settings::output_fields( $settings ); - } elseif ( 'classes' === $current_section ) { - $hide_save_button = true; - $this->output_shipping_class_screen(); - } else { - foreach ( $shipping_methods as $method ) { - if ( in_array( $current_section, array( $method->id, sanitize_title( get_class( $method ) ) ) ) && $method->has_settings() ) { - $method->admin_options(); - } + foreach ( $shipping_methods as $method ) { + if ( ! $method->has_settings() ) { + continue; + } + $title = empty( $method->method_title ) ? ucfirst( $method->id ) : $method->method_title; + $sections[ strtolower( $method->id ) ] = esc_html( $title ); + } + } + + return apply_filters( 'woocommerce_get_sections_' . $this->id, $sections ); + } + + /** + * Get settings array. + * + * @param string $current_section Current section. + * @return array + */ + public function get_settings( $current_section = '' ) { + $settings = array(); + + if ( '' === $current_section ) { + $settings = apply_filters( + 'woocommerce_shipping_settings', array( + + array( + 'title' => __( 'Shipping options', 'woocommerce' ), + 'type' => 'title', + 'id' => 'shipping_options', + ), + + array( + 'title' => __( 'Calculations', 'woocommerce' ), + 'desc' => __( 'Enable the shipping calculator on the cart page', 'woocommerce' ), + 'id' => 'woocommerce_enable_shipping_calc', + 'default' => 'yes', + 'type' => 'checkbox', + 'checkboxgroup' => 'start', + 'autoload' => false, + ), + + array( + 'desc' => __( 'Hide shipping costs until an address is entered', 'woocommerce' ), + 'id' => 'woocommerce_shipping_cost_requires_address', + 'default' => 'no', + 'type' => 'checkbox', + 'checkboxgroup' => 'end', + ), + + array( + 'title' => __( 'Shipping destination', 'woocommerce' ), + 'desc' => __( 'This controls which shipping address is used by default.', 'woocommerce' ), + 'id' => 'woocommerce_ship_to_destination', + 'default' => 'billing', + 'type' => 'radio', + 'options' => array( + 'shipping' => __( 'Default to customer shipping address', 'woocommerce' ), + 'billing' => __( 'Default to customer billing address', 'woocommerce' ), + 'billing_only' => __( 'Force shipping to the customer billing address', 'woocommerce' ), + ), + 'autoload' => false, + 'desc_tip' => true, + 'show_if_checked' => 'option', + ), + + array( + 'title' => __( 'Debug mode', 'woocommerce' ), + 'desc' => __( 'Enable debug mode', 'woocommerce' ), + 'desc_tip' => __( 'Enable shipping debug mode to show matching shipping zones and to bypass shipping rate cache.', 'woocommerce' ), + 'id' => 'woocommerce_shipping_debug_mode', + 'default' => 'no', + 'type' => 'checkbox', + ), + + array( + 'type' => 'sectionend', + 'id' => 'shipping_options', + ), + + ) + ); + } + + return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section ); + } + + /** + * Output the settings. + */ + public function output() { + global $current_section, $hide_save_button; + + // Load shipping methods so we can show any global options they may have. + $shipping_methods = WC()->shipping->load_shipping_methods(); + + if ( '' === $current_section ) { + $this->output_zones_screen(); + } elseif ( 'options' === $current_section ) { + $settings = $this->get_settings(); + WC_Admin_Settings::output_fields( $settings ); + } elseif ( 'classes' === $current_section ) { + $hide_save_button = true; + $this->output_shipping_class_screen(); + } else { + foreach ( $shipping_methods as $method ) { + if ( in_array( $current_section, array( $method->id, sanitize_title( get_class( $method ) ) ), true ) && $method->has_settings() ) { + $method->admin_options(); } } } - - /** - * Save settings. - */ - public function save() { - global $current_section; - - switch ( $current_section ) { - case 'options': - WC_Admin_Settings::save_fields( $this->get_settings() ); - break; - case 'classes': - case '': - break; - default: - $wc_shipping = WC_Shipping::instance(); - - foreach ( $wc_shipping->get_shipping_methods() as $method_id => $method ) { - if ( in_array( $current_section, array( $method->id, sanitize_title( get_class( $method ) ) ) ) ) { - do_action( 'woocommerce_update_options_' . $this->id . '_' . $method->id ); - } - } - break; - } - - if ( $current_section ) { - do_action( 'woocommerce_update_options_' . $this->id . '_' . $current_section ); - } - - // Increments the transient version to invalidate cache. - WC_Cache_Helper::get_transient_version( 'shipping', true ); - } - - /** - * Handles output of the shipping zones page in admin. - */ - protected function output_zones_screen() { - global $hide_save_button; - - if ( isset( $_REQUEST['zone_id'] ) ) { - $hide_save_button = true; - $this->zone_methods_screen( wc_clean( $_REQUEST['zone_id'] ) ); - } elseif ( isset( $_REQUEST['instance_id'] ) ) { - $this->instance_settings_screen( absint( $_REQUEST['instance_id'] ) ); - } else { - $hide_save_button = true; - $this->zones_screen(); - } - } - - /** - * Show method for a zone - * - * @param int $zone_id - */ - protected function zone_methods_screen( $zone_id ) { - if ( 'new' === $zone_id ) { - $zone = new WC_Shipping_Zone(); - } else { - $zone = WC_Shipping_Zones::get_zone( absint( $zone_id ) ); - } - - if ( ! $zone ) { - wp_die( __( 'Zone does not exist!', 'woocommerce' ) ); - } - - $allowed_countries = WC()->countries->get_allowed_countries(); - $wc_shipping = WC_Shipping::instance(); - $shipping_methods = $wc_shipping->get_shipping_methods(); - $continents = WC()->countries->get_continents(); - - // Prepare locations. - $locations = array(); - $postcodes = array(); - - foreach ( $zone->get_zone_locations() as $location ) { - if ( 'postcode' === $location->type ) { - $postcodes[] = $location->code; - } else { - $locations[] = $location->type . ':' . $location->code; - } - } - - wp_localize_script( - 'wc-shipping-zone-methods', 'shippingZoneMethodsLocalizeScript', array( - 'methods' => $zone->get_shipping_methods( false, 'json' ), - 'zone_name' => $zone->get_zone_name(), - 'zone_id' => $zone->get_id(), - 'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ), - 'strings' => array( - 'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ), - 'save_changes_prompt' => __( 'Do you wish to save your changes first? Your changed data will be discarded if you choose to cancel.', 'woocommerce' ), - 'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' ), - 'add_method_failed' => __( 'Shipping method could not be added. Please retry.', 'woocommerce' ), - 'yes' => __( 'Yes', 'woocommerce' ), - 'no' => __( 'No', 'woocommerce' ), - 'default_zone_name' => __( 'Zone', 'woocommerce' ), - ), - ) - ); - wp_enqueue_script( 'wc-shipping-zone-methods' ); - - include_once dirname( __FILE__ ) . '/views/html-admin-page-shipping-zone-methods.php'; - } - - /** - * Show zones - */ - protected function zones_screen() { - $allowed_countries = WC()->countries->get_allowed_countries(); - $continents = WC()->countries->get_continents(); - $method_count = wc_get_shipping_method_count(); - - wp_localize_script( - 'wc-shipping-zones', 'shippingZonesLocalizeScript', array( - 'zones' => WC_Shipping_Zones::get_zones(), - 'default_zone' => array( - 'zone_id' => 0, - 'zone_name' => '', - 'zone_order' => null, - ), - 'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ), - 'strings' => array( - 'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ), - 'delete_confirmation_msg' => __( 'Are you sure you want to delete this zone? This action cannot be undone.', 'woocommerce' ), - 'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' ), - 'no_shipping_methods_offered' => __( 'No shipping methods offered to this zone.', 'woocommerce' ), - ), - ) - ); - wp_enqueue_script( 'wc-shipping-zones' ); - - include_once dirname( __FILE__ ) . '/views/html-admin-page-shipping-zones.php'; - } - - /** - * Show instance settings - * - * @param int $instance_id - */ - protected function instance_settings_screen( $instance_id ) { - $zone = WC_Shipping_Zones::get_zone_by( 'instance_id', $instance_id ); - $shipping_method = WC_Shipping_Zones::get_shipping_method( $instance_id ); - - if ( ! $shipping_method ) { - wp_die( __( 'Invalid shipping method!', 'woocommerce' ) ); - } - if ( ! $zone ) { - wp_die( __( 'Zone does not exist!', 'woocommerce' ) ); - } - if ( ! $shipping_method->has_settings() ) { - wp_die( __( 'This shipping method does not have any settings to configure.', 'woocommerce' ) ); - } - - if ( ! empty( $_POST['save'] ) ) { - - if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-settings' ) ) { - echo '

' . __( 'Edit failed. Please try again.', 'woocommerce' ) . '

'; - } - - $shipping_method->process_admin_options(); - $shipping_method->display_errors(); - } - - include_once dirname( __FILE__ ) . '/views/html-admin-page-shipping-zones-instance.php'; - } - - /** - * Handles output of the shipping class settings screen. - */ - protected function output_shipping_class_screen() { - $wc_shipping = WC_Shipping::instance(); - wp_localize_script( - 'wc-shipping-classes', 'shippingClassesLocalizeScript', array( - 'classes' => $wc_shipping->get_shipping_classes(), - 'default_shipping_class' => array( - 'term_id' => 0, - 'name' => '', - 'description' => '', - ), - 'wc_shipping_classes_nonce' => wp_create_nonce( 'wc_shipping_classes_nonce' ), - 'strings' => array( - 'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ), - 'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' ), - ), - ) - ); - wp_enqueue_script( 'wc-shipping-classes' ); - - // Extendable columns to show on the shipping classes screen. - $shipping_class_columns = apply_filters( - 'woocommerce_shipping_classes_columns', array( - 'wc-shipping-class-name' => __( 'Shipping class', 'woocommerce' ), - 'wc-shipping-class-slug' => __( 'Slug', 'woocommerce' ), - 'wc-shipping-class-description' => __( 'Description', 'woocommerce' ), - 'wc-shipping-class-count' => __( 'Product count', 'woocommerce' ), - ) - ); - - include_once dirname( __FILE__ ) . '/views/html-admin-page-shipping-classes.php'; - } } -endif; + /** + * Save settings. + */ + public function save() { + global $current_section; + + switch ( $current_section ) { + case 'options': + WC_Admin_Settings::save_fields( $this->get_settings() ); + break; + case 'classes': + case '': + break; + default: + $wc_shipping = WC_Shipping::instance(); + + foreach ( $wc_shipping->get_shipping_methods() as $method_id => $method ) { + if ( in_array( $current_section, array( $method->id, sanitize_title( get_class( $method ) ) ), true ) ) { + do_action( 'woocommerce_update_options_' . $this->id . '_' . $method->id ); + } + } + break; + } + + if ( $current_section ) { + do_action( 'woocommerce_update_options_' . $this->id . '_' . $current_section ); + } + + // Increments the transient version to invalidate cache. + WC_Cache_Helper::get_transient_version( 'shipping', true ); + } + + /** + * Handles output of the shipping zones page in admin. + */ + protected function output_zones_screen() { + global $hide_save_button; + + if ( isset( $_REQUEST['zone_id'] ) ) { // WPCS: input var ok, CSRF ok. + $hide_save_button = true; + $this->zone_methods_screen( wc_clean( wp_unslash( $_REQUEST['zone_id'] ) ) ); // WPCS: input var ok, CSRF ok. + } elseif ( isset( $_REQUEST['instance_id'] ) ) { + $this->instance_settings_screen( absint( wp_unslash( $_REQUEST['instance_id'] ) ) ); // WPCS: input var ok, CSRF ok. + } else { + $hide_save_button = true; + $this->zones_screen(); + } + } + + /** + * Show method for a zone + * + * @param int $zone_id Zone ID. + */ + protected function zone_methods_screen( $zone_id ) { + if ( 'new' === $zone_id ) { + $zone = new WC_Shipping_Zone(); + } else { + $zone = WC_Shipping_Zones::get_zone( absint( $zone_id ) ); + } + + if ( ! $zone ) { + wp_die( esc_html__( 'Zone does not exist!', 'woocommerce' ) ); + } + + $allowed_countries = WC()->countries->get_allowed_countries(); + $wc_shipping = WC_Shipping::instance(); + $shipping_methods = $wc_shipping->get_shipping_methods(); + $continents = WC()->countries->get_continents(); + + // Prepare locations. + $locations = array(); + $postcodes = array(); + + foreach ( $zone->get_zone_locations() as $location ) { + if ( 'postcode' === $location->type ) { + $postcodes[] = $location->code; + } else { + $locations[] = $location->type . ':' . $location->code; + } + } + + wp_localize_script( + 'wc-shipping-zone-methods', 'shippingZoneMethodsLocalizeScript', array( + 'methods' => $zone->get_shipping_methods( false, 'json' ), + 'zone_name' => $zone->get_zone_name(), + 'zone_id' => $zone->get_id(), + 'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ), + 'strings' => array( + 'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ), + 'save_changes_prompt' => __( 'Do you wish to save your changes first? Your changed data will be discarded if you choose to cancel.', 'woocommerce' ), + 'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' ), + 'add_method_failed' => __( 'Shipping method could not be added. Please retry.', 'woocommerce' ), + 'yes' => __( 'Yes', 'woocommerce' ), + 'no' => __( 'No', 'woocommerce' ), + 'default_zone_name' => __( 'Zone', 'woocommerce' ), + ), + ) + ); + wp_enqueue_script( 'wc-shipping-zone-methods' ); + + include_once dirname( __FILE__ ) . '/views/html-admin-page-shipping-zone-methods.php'; + } + + /** + * Show zones + */ + protected function zones_screen() { + $allowed_countries = WC()->countries->get_allowed_countries(); + $continents = WC()->countries->get_continents(); + $method_count = wc_get_shipping_method_count(); + + wp_localize_script( + 'wc-shipping-zones', 'shippingZonesLocalizeScript', array( + 'zones' => WC_Shipping_Zones::get_zones(), + 'default_zone' => array( + 'zone_id' => 0, + 'zone_name' => '', + 'zone_order' => null, + ), + 'wc_shipping_zones_nonce' => wp_create_nonce( 'wc_shipping_zones_nonce' ), + 'strings' => array( + 'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ), + 'delete_confirmation_msg' => __( 'Are you sure you want to delete this zone? This action cannot be undone.', 'woocommerce' ), + 'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' ), + 'no_shipping_methods_offered' => __( 'No shipping methods offered to this zone.', 'woocommerce' ), + ), + ) + ); + wp_enqueue_script( 'wc-shipping-zones' ); + + include_once dirname( __FILE__ ) . '/views/html-admin-page-shipping-zones.php'; + } + + /** + * Show instance settings + * + * @param int $instance_id Shipping instance ID. + */ + protected function instance_settings_screen( $instance_id ) { + $zone = WC_Shipping_Zones::get_zone_by( 'instance_id', $instance_id ); + $shipping_method = WC_Shipping_Zones::get_shipping_method( $instance_id ); + + if ( ! $shipping_method ) { + wp_die( esc_html__( 'Invalid shipping method!', 'woocommerce' ) ); + } + if ( ! $zone ) { + wp_die( esc_html__( 'Zone does not exist!', 'woocommerce' ) ); + } + if ( ! $shipping_method->has_settings() ) { + wp_die( esc_html__( 'This shipping method does not have any settings to configure.', 'woocommerce' ) ); + } + + if ( ! empty( $_POST['save'] ) ) { // WPCS: input var ok, sanitization ok. + + if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( wp_unslash( $_REQUEST['_wpnonce'] ), 'woocommerce-settings' ) ) { // WPCS: input var ok, sanitization ok. + echo '

' . esc_html__( 'Edit failed. Please try again.', 'woocommerce' ) . '

'; + } + + $shipping_method->process_admin_options(); + $shipping_method->display_errors(); + } + + include_once dirname( __FILE__ ) . '/views/html-admin-page-shipping-zones-instance.php'; + } + + /** + * Handles output of the shipping class settings screen. + */ + protected function output_shipping_class_screen() { + $wc_shipping = WC_Shipping::instance(); + wp_localize_script( + 'wc-shipping-classes', 'shippingClassesLocalizeScript', array( + 'classes' => $wc_shipping->get_shipping_classes(), + 'default_shipping_class' => array( + 'term_id' => 0, + 'name' => '', + 'description' => '', + ), + 'wc_shipping_classes_nonce' => wp_create_nonce( 'wc_shipping_classes_nonce' ), + 'strings' => array( + 'unload_confirmation_msg' => __( 'Your changed data will be lost if you leave this page without saving.', 'woocommerce' ), + 'save_failed' => __( 'Your changes were not saved. Please retry.', 'woocommerce' ), + ), + ) + ); + wp_enqueue_script( 'wc-shipping-classes' ); + + // Extendable columns to show on the shipping classes screen. + $shipping_class_columns = apply_filters( + 'woocommerce_shipping_classes_columns', array( + 'wc-shipping-class-name' => __( 'Shipping class', 'woocommerce' ), + 'wc-shipping-class-slug' => __( 'Slug', 'woocommerce' ), + 'wc-shipping-class-description' => __( 'Description', 'woocommerce' ), + 'wc-shipping-class-count' => __( 'Product count', 'woocommerce' ), + ) + ); + + include_once dirname( __FILE__ ) . '/views/html-admin-page-shipping-classes.php'; + } +} return new WC_Settings_Shipping(); diff --git a/includes/admin/settings/views/settings-tax.php b/includes/admin/settings/views/settings-tax.php index f35cfeb59c5..f1289566824 100644 --- a/includes/admin/settings/views/settings-tax.php +++ b/includes/admin/settings/views/settings-tax.php @@ -1,8 +1,11 @@ 'woocommerce_tax_classes', 'css' => 'width:100%; height: 65px;', 'type' => 'textarea', + /* Translators: %s New line char. */ 'default' => sprintf( __( 'Reduced rate%sZero rate', 'woocommerce' ), PHP_EOL ), ), @@ -81,16 +85,15 @@ $settings = array( ), array( - 'title' => __( 'Display prices during cart and checkout', 'woocommerce' ), - 'id' => 'woocommerce_tax_display_cart', - 'default' => 'excl', - 'type' => 'select', - 'class' => 'wc-enhanced-select', - 'options' => array( + 'title' => __( 'Display prices during cart and checkout', 'woocommerce' ), + 'id' => 'woocommerce_tax_display_cart', + 'default' => 'excl', + 'type' => 'select', + 'class' => 'wc-enhanced-select', + 'options' => array( 'incl' => __( 'Including tax', 'woocommerce' ), 'excl' => __( 'Excluding tax', 'woocommerce' ), ), - 'autoload' => false, ), array( diff --git a/includes/class-wc-cart-session.php b/includes/class-wc-cart-session.php index ed9d87acf09..47054f95b29 100644 --- a/includes/class-wc-cart-session.php +++ b/includes/class-wc-cart-session.php @@ -91,8 +91,10 @@ final class WC_Cart_Session { if ( is_array( $cart ) ) { $cart_contents = array(); - update_meta_cache( 'post', wp_list_pluck( $cart, 'product_id' ) ); // Prime meta cache to reduce future queries. - update_object_term_cache( wp_list_pluck( $cart, 'product_id' ), 'product' ); + // Prime caches to reduce future queries. + if ( is_callable( '_prime_post_caches' ) ) { + _prime_post_caches( wp_list_pluck( $cart, 'product_id' ) ); + } foreach ( $cart as $key => $values ) { $product = wc_get_product( $values['variation_id'] ? $values['variation_id'] : $values['product_id'] ); diff --git a/includes/class-wc-cart-totals.php b/includes/class-wc-cart-totals.php index d56cb5fe456..bb2c384a113 100644 --- a/includes/class-wc-cart-totals.php +++ b/includes/class-wc-cart-totals.php @@ -481,6 +481,9 @@ final class WC_Cart_Totals { * @return array of taxes */ protected function get_item_tax_rates( $item ) { + if ( ! wc_tax_enabled() ) { + return array(); + } $tax_class = $item->product->get_tax_class(); return isset( $this->item_tax_rates[ $tax_class ] ) ? $this->item_tax_rates[ $tax_class ] : $this->item_tax_rates[ $tax_class ] = WC_Tax::get_rates( $item->product->get_tax_class(), $this->cart->get_customer() ); } diff --git a/includes/class-wc-install.php b/includes/class-wc-install.php index 5fd9002c092..898fe0cb198 100644 --- a/includes/class-wc-install.php +++ b/includes/class-wc-install.php @@ -436,6 +436,12 @@ class WC_Install { } } } + + // Define other defaults if not in setting screens. + add_option( 'woocommerce_single_image_width', '600', '', 'yes' ); + add_option( 'woocommerce_thumbnail_image_width', '300', '', 'yes' ); + add_option( 'woocommerce_checkout_highlight_required_fields', 'no', '', 'yes' ); + add_option( 'woocommerce_demo_store', 'no', '', 'no' ); } /** diff --git a/includes/class-wc-product-variable.php b/includes/class-wc-product-variable.php index c737207b5ad..5a148156983 100644 --- a/includes/class-wc-product-variable.php +++ b/includes/class-wc-product-variable.php @@ -20,21 +20,21 @@ class WC_Product_Variable extends WC_Product { * * @var array */ - protected $children = array(); + protected $children = null; /** * Array of visible children variation IDs. Determined by children. * * @var array */ - protected $visible_children = array(); + protected $visible_children = null; /** * Array of variation attributes IDs. Determined by children. * * @var array */ - protected $variation_attributes = array(); + protected $variation_attributes = null; /** * Get internal type. @@ -194,6 +194,8 @@ class WC_Product_Variable extends WC_Product { /** * Return a products child ids. * + * This is lazy loaded as it's not used often and does require several queries. + * * @param bool|string $visible_only Visible only. * @return array Children ids */ @@ -204,25 +206,43 @@ class WC_Product_Variable extends WC_Product { return $visible_only ? $this->get_visible_children() : $this->get_children(); } + if ( null === $this->children ) { + $children = $this->data_store->read_children( $this ); + $this->set_children( $children['all'] ); + $this->set_visible_children( $children['visible'] ); + } + return apply_filters( 'woocommerce_get_children', $this->children, $this, false ); } /** * Return a products child ids - visible only. * + * This is lazy loaded as it's not used often and does require several queries. + * * @since 3.0.0 * @return array Children ids */ public function get_visible_children() { + if ( null === $this->visible_children ) { + $children = $this->data_store->read_children( $this ); + $this->set_children( $children['all'] ); + $this->set_visible_children( $children['visible'] ); + } return apply_filters( 'woocommerce_get_children', $this->visible_children, $this, true ); } /** * Return an array of attributes used for variations, as well as their possible values. * + * This is lazy loaded as it's not used often and does require several queries. + * * @return array Attributes and their available values */ public function get_variation_attributes() { + if ( null === $this->variation_attributes ) { + $this->variation_attributes = $this->data_store->read_variation_attributes( $this ); + } return $this->variation_attributes; } diff --git a/includes/data-stores/class-wc-product-variable-data-store-cpt.php b/includes/data-stores/class-wc-product-variable-data-store-cpt.php index 1efa9eb1f2d..951a0dc97d3 100644 --- a/includes/data-stores/class-wc-product-variable-data-store-cpt.php +++ b/includes/data-stores/class-wc-product-variable-data-store-cpt.php @@ -105,12 +105,6 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple // Make sure data which does not apply to variables is unset. $product->set_regular_price( '' ); $product->set_sale_price( '' ); - - // Set directly since individual data needs changed at the WC_Product_Variation level -- these datasets just pull. - $children = $this->read_children( $product ); - $product->set_children( $children['all'] ); - $product->set_visible_children( $children['visible'] ); - $product->set_variation_attributes( $this->read_variation_attributes( $product ) ); } /** @@ -120,7 +114,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple * @param bool $force_read True to bypass the transient. * @return array */ - protected function read_children( &$product, $force_read = false ) { + public function read_children( &$product, $force_read = false ) { $children_transient_name = 'wc_product_children_' . $product->get_id(); $children = get_transient( $children_transient_name ); @@ -166,7 +160,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple * @param WC_Product $product Product object. * @return array */ - protected function read_variation_attributes( &$product ) { + public function read_variation_attributes( &$product ) { global $wpdb; $variation_attributes = array(); @@ -367,7 +361,7 @@ class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT imple protected function get_price_hash( &$product, $for_display = false ) { global $wp_filter; - $price_hash = $for_display ? array( get_option( 'woocommerce_tax_display_shop', 'excl' ), WC_Tax::get_rates() ) : array( false ); + $price_hash = $for_display && wc_tax_enabled() ? array( get_option( 'woocommerce_tax_display_shop', 'excl' ), WC_Tax::get_rates() ) : array( false ); $filter_names = array( 'woocommerce_variation_prices_price', 'woocommerce_variation_prices_regular_price', 'woocommerce_variation_prices_sale_price' ); foreach ( $filter_names as $filter_name ) { diff --git a/includes/shortcodes/class-wc-shortcode-products.php b/includes/shortcodes/class-wc-shortcode-products.php index ced110b1ac5..28b6ae3c856 100644 --- a/includes/shortcodes/class-wc-shortcode-products.php +++ b/includes/shortcodes/class-wc-shortcode-products.php @@ -574,9 +574,10 @@ class WC_Shortcode_Products { ob_start(); if ( $products && $products->ids ) { - // Prime meta cache to reduce future queries. - update_meta_cache( 'post', $products->ids ); - update_object_term_cache( $products->ids, 'product' ); + // Prime caches to reduce future queries. + if ( is_callable( '_prime_post_caches' ) ) { + _prime_post_caches( $products->ids ); + } // Setup the loop. wc_setup_loop( diff --git a/includes/wc-template-functions.php b/includes/wc-template-functions.php index 057402fbb2b..02ab08266d4 100644 --- a/includes/wc-template-functions.php +++ b/includes/wc-template-functions.php @@ -498,9 +498,6 @@ function wc_product_post_class( $classes, $class = '', $post_id = '' ) { if ( ! $product->get_default_attributes() ) { $classes[] = 'has-default-attributes'; } - if ( $product->has_child() ) { - $classes[] = 'has-children'; - } } }