plugin updates
This commit is contained in:
@@ -149,7 +149,7 @@ if ( ! class_exists( 'WC_Admin_Assets', false ) ) :
|
||||
wp_register_script( 'wc-shipping-zone-methods', WC()->plugin_url() . '/assets/js/admin/wc-shipping-zone-methods' . $suffix . '.js', array( 'jquery', 'wp-util', 'underscore', 'backbone', 'jquery-ui-sortable', 'wc-backbone-modal' ), $version );
|
||||
wp_register_script( 'wc-shipping-classes', WC()->plugin_url() . '/assets/js/admin/wc-shipping-classes' . $suffix . '.js', array( 'jquery', 'wp-util', 'underscore', 'backbone', 'wc-backbone-modal' ), $version, array( 'in_footer' => false ) );
|
||||
wp_register_script( 'wc-clipboard', WC()->plugin_url() . '/assets/js/admin/wc-clipboard' . $suffix . '.js', array( 'jquery' ), $version );
|
||||
wp_register_script( 'select2', WC()->plugin_url() . '/assets/js/select2/select2.full' . $suffix . '.js', array( 'jquery' ), '4.0.3' );
|
||||
wp_register_script( 'select2', WC()->plugin_url() . '/assets/js/select2/select2.full' . $suffix . '.js', array( 'jquery' ), '4.0.3', array( 'in_footer' => false ) );
|
||||
wp_register_script( 'selectWoo', WC()->plugin_url() . '/assets/js/selectWoo/selectWoo.full' . $suffix . '.js', array( 'jquery' ), '1.0.6' );
|
||||
wp_register_script( 'wc-enhanced-select', WC()->plugin_url() . '/assets/js/admin/wc-enhanced-select' . $suffix . '.js', array( 'jquery', 'selectWoo' ), $version );
|
||||
wp_register_script( 'js-cookie', WC()->plugin_url() . '/assets/js/js-cookie/js.cookie' . $suffix . '.js', array(), '2.1.4', true );
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?php
|
||||
<?php //phpcs:ignore Generic.PHP.RequireStrictTypes.MissingDeclaration
|
||||
/**
|
||||
* Init WooCommerce data importers.
|
||||
*
|
||||
@@ -34,6 +34,7 @@ class WC_Admin_Importers {
|
||||
add_action( 'admin_head', array( $this, 'hide_from_menus' ) );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
|
||||
add_action( 'wp_ajax_woocommerce_do_ajax_product_import', array( $this, 'do_ajax_product_import' ) );
|
||||
add_action( 'in_admin_footer', array( $this, 'track_importer_exporter_view' ) );
|
||||
|
||||
// Register WooCommerce importers.
|
||||
$this->importers['product_importer'] = array(
|
||||
@@ -96,10 +97,15 @@ class WC_Admin_Importers {
|
||||
*/
|
||||
public function product_importer() {
|
||||
if ( Constants::is_defined( 'WP_LOAD_IMPORTERS' ) ) {
|
||||
wp_safe_redirect( admin_url( 'edit.php?post_type=product&page=product_importer' ) );
|
||||
wp_safe_redirect( admin_url( 'edit.php?post_type=product&page=product_importer&source=wordpress-importer' ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
// phpcs:ignore
|
||||
if ( isset( $_GET['source'] ) && 'wordpress-importer' === sanitize_text_field( wp_unslash( $_GET['source'] ) ) ) {
|
||||
wc_admin_record_tracks_event( 'product_importer_view_from_wp_importer' );
|
||||
}
|
||||
|
||||
include_once WC_ABSPATH . 'includes/import/class-wc-product-csv-importer.php';
|
||||
include_once WC_ABSPATH . 'includes/admin/importers/class-wc-product-csv-importer-controller.php';
|
||||
|
||||
@@ -132,7 +138,9 @@ class WC_Admin_Importers {
|
||||
}
|
||||
}
|
||||
|
||||
require dirname( __FILE__ ) . '/importers/class-wc-tax-rate-importer.php';
|
||||
wc_admin_record_tracks_event( 'tax_rates_importer_view_from_wp_importer' );
|
||||
|
||||
require __DIR__ . '/importers/class-wc-tax-rate-importer.php';
|
||||
|
||||
$importer = new WC_Tax_Rate_Importer();
|
||||
$importer->dispatch();
|
||||
@@ -182,7 +190,9 @@ class WC_Admin_Importers {
|
||||
// Register the taxonomy now so that the import works!
|
||||
register_taxonomy(
|
||||
$term['domain'],
|
||||
// phpcs:ignore
|
||||
apply_filters( 'woocommerce_taxonomy_objects_' . $term['domain'], array( 'product' ) ),
|
||||
// phpcs:ignore
|
||||
apply_filters(
|
||||
'woocommerce_taxonomy_args_' . $term['domain'],
|
||||
array(
|
||||
@@ -205,113 +215,34 @@ class WC_Admin_Importers {
|
||||
* Ajax callback for importing one batch of products from a CSV.
|
||||
*/
|
||||
public function do_ajax_product_import() {
|
||||
global $wpdb;
|
||||
|
||||
check_ajax_referer( 'wc-product-import', 'security' );
|
||||
|
||||
if ( ! $this->import_allowed() || ! isset( $_POST['file'] ) ) { // PHPCS: input var ok.
|
||||
if ( ! $this->import_allowed() ) {
|
||||
wp_send_json_error( array( 'message' => __( 'Insufficient privileges to import products.', 'woocommerce' ) ) );
|
||||
}
|
||||
|
||||
include_once WC_ABSPATH . 'includes/admin/importers/class-wc-product-csv-importer-controller.php';
|
||||
include_once WC_ABSPATH . 'includes/import/class-wc-product-csv-importer.php';
|
||||
WC_Product_CSV_Importer_Controller::dispatch_ajax();
|
||||
}
|
||||
|
||||
$file = wc_clean( wp_unslash( $_POST['file'] ) ); // PHPCS: input var ok.
|
||||
$params = array(
|
||||
'delimiter' => ! empty( $_POST['delimiter'] ) ? wc_clean( wp_unslash( $_POST['delimiter'] ) ) : ',', // PHPCS: input var ok.
|
||||
'start_pos' => isset( $_POST['position'] ) ? absint( $_POST['position'] ) : 0, // PHPCS: input var ok.
|
||||
'mapping' => isset( $_POST['mapping'] ) ? (array) wc_clean( wp_unslash( $_POST['mapping'] ) ) : array(), // PHPCS: input var ok.
|
||||
'update_existing' => isset( $_POST['update_existing'] ) ? (bool) $_POST['update_existing'] : false, // PHPCS: input var ok.
|
||||
'character_encoding' => isset( $_POST['character_encoding'] ) ? wc_clean( wp_unslash( $_POST['character_encoding'] ) ) : '',
|
||||
/**
|
||||
* Track importer/exporter view.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function track_importer_exporter_view() {
|
||||
$screen = get_current_screen();
|
||||
|
||||
/**
|
||||
* Batch size for the product import process.
|
||||
*
|
||||
* @param int $size Batch size.
|
||||
*
|
||||
* @since
|
||||
*/
|
||||
'lines' => apply_filters( 'woocommerce_product_import_batch_size', 30 ),
|
||||
'parse' => true,
|
||||
);
|
||||
|
||||
// Log failures.
|
||||
if ( 0 !== $params['start_pos'] ) {
|
||||
$error_log = array_filter( (array) get_user_option( 'product_import_error_log' ) );
|
||||
} else {
|
||||
$error_log = array();
|
||||
if ( ! isset( $screen->id ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$importer = WC_Product_CSV_Importer_Controller::get_importer( $file, $params );
|
||||
$results = $importer->import();
|
||||
$percent_complete = $importer->get_percent_complete();
|
||||
$error_log = array_merge( $error_log, $results['failed'], $results['skipped'] );
|
||||
// Don't track if we're in a specific import screen.
|
||||
// phpcs:ignore
|
||||
if ( isset( $_GET['import'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
update_user_option( get_current_user_id(), 'product_import_error_log', $error_log );
|
||||
|
||||
if ( 100 === $percent_complete ) {
|
||||
// @codingStandardsIgnoreStart.
|
||||
$wpdb->delete( $wpdb->postmeta, array( 'meta_key' => '_original_id' ) );
|
||||
$wpdb->delete( $wpdb->posts, array(
|
||||
'post_type' => 'product',
|
||||
'post_status' => 'importing',
|
||||
) );
|
||||
$wpdb->delete( $wpdb->posts, array(
|
||||
'post_type' => 'product_variation',
|
||||
'post_status' => 'importing',
|
||||
) );
|
||||
// @codingStandardsIgnoreEnd.
|
||||
|
||||
// Clean up orphaned data.
|
||||
$wpdb->query(
|
||||
"
|
||||
DELETE {$wpdb->posts}.* FROM {$wpdb->posts}
|
||||
LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->posts}.post_parent
|
||||
WHERE wp.ID IS NULL AND {$wpdb->posts}.post_type = 'product_variation'
|
||||
"
|
||||
);
|
||||
$wpdb->query(
|
||||
"
|
||||
DELETE {$wpdb->postmeta}.* FROM {$wpdb->postmeta}
|
||||
LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->postmeta}.post_id
|
||||
WHERE wp.ID IS NULL
|
||||
"
|
||||
);
|
||||
// @codingStandardsIgnoreStart.
|
||||
$wpdb->query( "
|
||||
DELETE tr.* FROM {$wpdb->term_relationships} tr
|
||||
LEFT JOIN {$wpdb->posts} wp ON wp.ID = tr.object_id
|
||||
LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
|
||||
WHERE wp.ID IS NULL
|
||||
AND tt.taxonomy IN ( '" . implode( "','", array_map( 'esc_sql', get_object_taxonomies( 'product' ) ) ) . "' )
|
||||
" );
|
||||
// @codingStandardsIgnoreEnd.
|
||||
|
||||
// Send success.
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'position' => 'done',
|
||||
'percentage' => 100,
|
||||
'url' => add_query_arg( array( '_wpnonce' => wp_create_nonce( 'woocommerce-csv-importer' ) ), admin_url( 'edit.php?post_type=product&page=product_importer&step=done' ) ),
|
||||
'imported' => is_countable( $results['imported'] ) ? count( $results['imported'] ) : 0,
|
||||
'imported_variations' => is_countable( $results['imported_variations'] ) ? count( $results['imported_variations'] ) : 0,
|
||||
'failed' => is_countable( $results['failed'] ) ? count( $results['failed'] ) : 0,
|
||||
'updated' => is_countable( $results['updated'] ) ? count( $results['updated'] ) : 0,
|
||||
'skipped' => is_countable( $results['skipped'] ) ? count( $results['skipped'] ) : 0,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'position' => $importer->get_file_position(),
|
||||
'percentage' => $percent_complete,
|
||||
'imported' => is_countable( $results['imported'] ) ? count( $results['imported'] ) : 0,
|
||||
'imported_variations' => is_countable( $results['imported_variations'] ) ? count( $results['imported_variations'] ) : 0,
|
||||
'failed' => is_countable( $results['failed'] ) ? count( $results['failed'] ) : 0,
|
||||
'updated' => is_countable( $results['updated'] ) ? count( $results['updated'] ) : 0,
|
||||
'skipped' => is_countable( $results['skipped'] ) ? count( $results['skipped'] ) : 0,
|
||||
)
|
||||
);
|
||||
if ( 'import' === $screen->id || 'export' === $screen->id ) {
|
||||
wc_admin_record_tracks_event( 'wordpress_' . $screen->id . '_view' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,8 +219,8 @@ class WC_Admin_Marketplace_Promotions {
|
||||
/**
|
||||
* From the array of promotions, select those of a given format.
|
||||
*
|
||||
* @param ? array $promotions Array of data about promotions of all formats.
|
||||
* @param ? string $format Format we want to filter for.
|
||||
* @param ?array $promotions Array of data about promotions of all formats.
|
||||
* @param ?string $format Format we want to filter for.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
|
||||
@@ -176,7 +176,7 @@ if ( ! class_exists( 'WC_Admin_Profile', false ) ) :
|
||||
</th>
|
||||
<td>
|
||||
<?php if ( ! empty( $field['type'] ) && 'select' === $field['type'] ) : ?>
|
||||
<select name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" class="<?php echo esc_attr( $field['class'] ); ?>" style="width: 25em;">
|
||||
<select name="<?php echo esc_attr( $key ); ?>" id="<?php echo esc_attr( $key ); ?>" class="<?php echo isset( $field['class'] ) ? esc_attr( $field['class'] ) : ''; ?>" style="width: 25em;">
|
||||
<?php
|
||||
$selected = esc_attr( get_user_meta( $user->ID, $key, true ) );
|
||||
foreach ( $field['options'] as $option_key => $option_value ) :
|
||||
|
||||
@@ -53,7 +53,11 @@ if ( ! class_exists( 'WC_Admin_Settings', false ) ) :
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-products.php';
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-tax.php';
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-shipping.php';
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-payment-gateways.php';
|
||||
if ( \Automattic\WooCommerce\Admin\Features\Features::is_enabled( 'reactify-classic-payments-settings' ) ) {
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-payment-gateways-react.php';
|
||||
} else {
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-payment-gateways.php';
|
||||
}
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-accounts.php';
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-emails.php';
|
||||
$settings[] = include __DIR__ . '/settings/class-wc-settings-integrations.php';
|
||||
|
||||
@@ -27,7 +27,19 @@ class WC_Helper_Admin {
|
||||
* @return void
|
||||
*/
|
||||
public static function load() {
|
||||
add_filter( 'woocommerce_admin_shared_settings', array( __CLASS__, 'add_marketplace_settings' ) );
|
||||
global $pagenow;
|
||||
|
||||
if ( is_admin() ) {
|
||||
$is_in_app_marketplace = ( 'admin.php' === $pagenow
|
||||
&& isset( $_GET['page'] ) && 'wc-admin' === $_GET['page'] //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
&& isset( $_GET['path'] ) && '/extensions' === $_GET['path'] //phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
);
|
||||
|
||||
if ( $is_in_app_marketplace ) {
|
||||
add_filter( 'woocommerce_admin_shared_settings', array( __CLASS__, 'add_marketplace_settings' ) );
|
||||
}
|
||||
}
|
||||
|
||||
add_filter( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,8 @@ class WC_Helper_Subscriptions_API {
|
||||
*/
|
||||
public static function refresh() {
|
||||
WC_Helper::refresh_helper_subscriptions();
|
||||
WC_Helper::get_subscriptions();
|
||||
WC_Helper::get_product_usage_notice_rules();
|
||||
self::get_subscriptions();
|
||||
}
|
||||
|
||||
|
||||
@@ -259,8 +259,13 @@ class WC_Helper_Updater {
|
||||
// Extract product ID from the response.
|
||||
$product_id = preg_replace( '/[^0-9]/', '', $response->id );
|
||||
|
||||
$installed_or_unconnected = array_merge(
|
||||
WC_Helper::get_installed_subscriptions(),
|
||||
WC_Helper::get_unconnected_subscriptions()
|
||||
);
|
||||
|
||||
// Product subscriptions.
|
||||
$subscriptions = wp_list_filter( WC_Helper::get_installed_subscriptions(), array( 'product_id' => $product_id ) );
|
||||
$subscriptions = wp_list_filter( $installed_or_unconnected, array( 'product_id' => $product_id ) );
|
||||
if ( empty( $subscriptions ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1007,6 +1007,7 @@ class WC_Helper {
|
||||
self::_flush_authentication_cache();
|
||||
self::_flush_subscriptions_cache();
|
||||
self::_flush_updates_cache();
|
||||
self::flush_product_usage_notice_rules_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1334,6 +1335,34 @@ class WC_Helper {
|
||||
return $installed_subscriptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's unconnected subscriptions.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function get_unconnected_subscriptions() {
|
||||
static $unconnected_subscriptions = null;
|
||||
|
||||
// Cache unconnected_subscriptions in the current request.
|
||||
if ( is_null( $unconnected_subscriptions ) ) {
|
||||
$auth = WC_Helper_Options::get( 'auth' );
|
||||
$site_id = isset( $auth['site_id'] ) ? absint( $auth['site_id'] ) : 0;
|
||||
if ( 0 === $site_id ) {
|
||||
$unconnected_subscriptions = array();
|
||||
return $unconnected_subscriptions;
|
||||
}
|
||||
|
||||
$unconnected_subscriptions = array_filter(
|
||||
self::get_subscriptions(),
|
||||
function ( $subscription ) use ( $site_id ) {
|
||||
return empty( $subscription['connections'] );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return $unconnected_subscriptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get subscription state of a given product ID.
|
||||
*
|
||||
@@ -1561,6 +1590,7 @@ class WC_Helper {
|
||||
'product-usage-notice-rules',
|
||||
array(
|
||||
'authenticated' => false,
|
||||
'timeout' => 2,
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1835,8 +1865,22 @@ class WC_Helper {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there are multiple subscriptions, but no active subscriptions, then mark the first one as installed.
|
||||
$product_subscription = array_shift( $product_subscriptions );
|
||||
// Find subscriptions that can be activated.
|
||||
$product_subscriptions_without_maxed_connections = wp_list_filter(
|
||||
$product_subscriptions,
|
||||
array(
|
||||
'maxed' => false,
|
||||
)
|
||||
);
|
||||
|
||||
if ( 0 < count( $product_subscriptions_without_maxed_connections ) ) {
|
||||
// Pick the first subscription available for activation.
|
||||
$product_subscription = array_shift( $product_subscriptions_without_maxed_connections );
|
||||
} else {
|
||||
// If there are multiple subscriptions, but no active subscriptions, then mark the first one as installed.
|
||||
$product_subscription = array_shift( $product_subscriptions );
|
||||
}
|
||||
|
||||
if ( $product_subscription['product_key'] === $subscription['product_key'] ) {
|
||||
return true;
|
||||
}
|
||||
@@ -2172,6 +2216,13 @@ class WC_Helper {
|
||||
delete_transient( '_woocommerce_helper_subscriptions' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush product-usage-notice-rules cache.
|
||||
*/
|
||||
public static function flush_product_usage_notice_rules_cache() {
|
||||
delete_transient( '_woocommerce_helper_product_usage_notice_rules' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush auth cache.
|
||||
*/
|
||||
@@ -2271,6 +2322,7 @@ class WC_Helper {
|
||||
|
||||
self::_flush_subscriptions_cache();
|
||||
self::_flush_updates_cache();
|
||||
self::flush_product_usage_notice_rules_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2360,6 +2412,7 @@ class WC_Helper {
|
||||
|
||||
self::_flush_subscriptions_cache();
|
||||
self::_flush_updates_cache();
|
||||
self::flush_product_usage_notice_rules_cache();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -103,6 +103,56 @@ class WC_Product_CSV_Importer_Controller {
|
||||
return wc_is_file_valid_csv( $file, $check_path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs before controller actions to check that the file used during the import is valid.
|
||||
*
|
||||
* @since 9.3.0
|
||||
*
|
||||
* @param string $path Path to test.
|
||||
*
|
||||
* @throws \Exception When file validation fails.
|
||||
*/
|
||||
protected static function check_file_path( string $path ): void {
|
||||
$is_valid_file = false;
|
||||
|
||||
if ( ! empty( $path ) ) {
|
||||
$path = realpath( $path );
|
||||
$is_valid_file = false !== $path;
|
||||
}
|
||||
|
||||
// File must be readable.
|
||||
$is_valid_file = $is_valid_file && is_readable( $path );
|
||||
|
||||
// Check that file is within an allowed location.
|
||||
if ( $is_valid_file ) {
|
||||
$in_valid_location = false;
|
||||
$valid_locations = array();
|
||||
$valid_locations[] = ABSPATH;
|
||||
|
||||
$upload_dir = wp_get_upload_dir();
|
||||
if ( false === $upload_dir['error'] ) {
|
||||
$valid_locations[] = $upload_dir['basedir'];
|
||||
}
|
||||
|
||||
foreach ( $valid_locations as $valid_location ) {
|
||||
if ( 0 === stripos( $path, trailingslashit( realpath( $valid_location ) ) ) ) {
|
||||
$in_valid_location = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$is_valid_file = $in_valid_location;
|
||||
}
|
||||
|
||||
if ( ! $is_valid_file ) {
|
||||
throw new \Exception( esc_html__( 'File path provided for import is invalid.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
if ( ! self::is_file_valid_csv( $path ) ) {
|
||||
throw new \Exception( esc_html__( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all the valid filetypes for a CSV file.
|
||||
*
|
||||
@@ -263,17 +313,151 @@ class WC_Product_CSV_Importer_Controller {
|
||||
* Dispatch current step and show correct view.
|
||||
*/
|
||||
public function dispatch() {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
if ( ! empty( $_POST['save_step'] ) && ! empty( $this->steps[ $this->step ]['handler'] ) ) {
|
||||
call_user_func( $this->steps[ $this->step ]['handler'], $this );
|
||||
$output = '';
|
||||
|
||||
try {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
if ( ! empty( $_POST['save_step'] ) && ! empty( $this->steps[ $this->step ]['handler'] ) ) {
|
||||
if ( is_callable( $this->steps[ $this->step ]['handler'] ) ) {
|
||||
call_user_func( $this->steps[ $this->step ]['handler'], $this );
|
||||
}
|
||||
}
|
||||
|
||||
ob_start();
|
||||
|
||||
if ( is_callable( $this->steps[ $this->step ]['view'] ) ) {
|
||||
call_user_func( $this->steps[ $this->step ]['view'], $this );
|
||||
}
|
||||
|
||||
$output = ob_get_clean();
|
||||
} catch ( \Exception $e ) {
|
||||
$this->add_error( $e->getMessage() );
|
||||
}
|
||||
|
||||
$this->output_header();
|
||||
$this->output_steps();
|
||||
$this->output_errors();
|
||||
call_user_func( $this->steps[ $this->step ]['view'], $this );
|
||||
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- output is HTML we've generated ourselves.
|
||||
$this->output_footer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes AJAX requests related to a product CSV import.
|
||||
*
|
||||
* @since 9.3.0
|
||||
*/
|
||||
public static function dispatch_ajax() {
|
||||
global $wpdb;
|
||||
|
||||
check_ajax_referer( 'wc-product-import', 'security' );
|
||||
|
||||
try {
|
||||
$file = wc_clean( wp_unslash( $_POST['file'] ?? '' ) ); // PHPCS: input var ok.
|
||||
self::check_file_path( $file );
|
||||
|
||||
$params = array(
|
||||
'delimiter' => ! empty( $_POST['delimiter'] ) ? wc_clean( wp_unslash( $_POST['delimiter'] ) ) : ',', // PHPCS: input var ok.
|
||||
'start_pos' => isset( $_POST['position'] ) ? absint( $_POST['position'] ) : 0, // PHPCS: input var ok.
|
||||
'mapping' => isset( $_POST['mapping'] ) ? (array) wc_clean( wp_unslash( $_POST['mapping'] ) ) : array(), // PHPCS: input var ok.
|
||||
'update_existing' => isset( $_POST['update_existing'] ) ? (bool) $_POST['update_existing'] : false, // PHPCS: input var ok.
|
||||
'character_encoding' => isset( $_POST['character_encoding'] ) ? wc_clean( wp_unslash( $_POST['character_encoding'] ) ) : '',
|
||||
|
||||
/**
|
||||
* Batch size for the product import process.
|
||||
*
|
||||
* @param int $size Batch size.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*/
|
||||
'lines' => apply_filters( 'woocommerce_product_import_batch_size', 1 ),
|
||||
'parse' => true,
|
||||
);
|
||||
|
||||
// Log failures.
|
||||
if ( 0 !== $params['start_pos'] ) {
|
||||
$error_log = array_filter( (array) get_user_option( 'product_import_error_log' ) );
|
||||
} else {
|
||||
$error_log = array();
|
||||
}
|
||||
|
||||
include_once WC_ABSPATH . 'includes/import/class-wc-product-csv-importer.php';
|
||||
|
||||
$importer = self::get_importer( $file, $params );
|
||||
$results = $importer->import();
|
||||
$percent_complete = $importer->get_percent_complete();
|
||||
$error_log = array_merge( $error_log, $results['failed'], $results['skipped'] );
|
||||
|
||||
update_user_option( get_current_user_id(), 'product_import_error_log', $error_log );
|
||||
|
||||
if ( 100 === $percent_complete ) {
|
||||
// @codingStandardsIgnoreStart.
|
||||
$wpdb->delete( $wpdb->postmeta, array( 'meta_key' => '_original_id' ) );
|
||||
$wpdb->delete( $wpdb->posts, array(
|
||||
'post_type' => 'product',
|
||||
'post_status' => 'importing',
|
||||
) );
|
||||
$wpdb->delete( $wpdb->posts, array(
|
||||
'post_type' => 'product_variation',
|
||||
'post_status' => 'importing',
|
||||
) );
|
||||
// @codingStandardsIgnoreEnd.
|
||||
|
||||
// Clean up orphaned data.
|
||||
$wpdb->query(
|
||||
"
|
||||
DELETE {$wpdb->posts}.* FROM {$wpdb->posts}
|
||||
LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->posts}.post_parent
|
||||
WHERE wp.ID IS NULL AND {$wpdb->posts}.post_type = 'product_variation'
|
||||
"
|
||||
);
|
||||
$wpdb->query(
|
||||
"
|
||||
DELETE {$wpdb->postmeta}.* FROM {$wpdb->postmeta}
|
||||
LEFT JOIN {$wpdb->posts} wp ON wp.ID = {$wpdb->postmeta}.post_id
|
||||
WHERE wp.ID IS NULL
|
||||
"
|
||||
);
|
||||
// @codingStandardsIgnoreStart.
|
||||
$wpdb->query( "
|
||||
DELETE tr.* FROM {$wpdb->term_relationships} tr
|
||||
LEFT JOIN {$wpdb->posts} wp ON wp.ID = tr.object_id
|
||||
LEFT JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
|
||||
WHERE wp.ID IS NULL
|
||||
AND tt.taxonomy IN ( '" . implode( "','", array_map( 'esc_sql', get_object_taxonomies( 'product' ) ) ) . "' )
|
||||
" );
|
||||
// @codingStandardsIgnoreEnd.
|
||||
|
||||
// Send success.
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'position' => 'done',
|
||||
'percentage' => 100,
|
||||
'url' => add_query_arg( array( '_wpnonce' => wp_create_nonce( 'woocommerce-csv-importer' ) ), admin_url( 'edit.php?post_type=product&page=product_importer&step=done' ) ),
|
||||
'imported' => is_countable( $results['imported'] ) ? count( $results['imported'] ) : 0,
|
||||
'imported_variations' => is_countable( $results['imported_variations'] ) ? count( $results['imported_variations'] ) : 0,
|
||||
'failed' => is_countable( $results['failed'] ) ? count( $results['failed'] ) : 0,
|
||||
'updated' => is_countable( $results['updated'] ) ? count( $results['updated'] ) : 0,
|
||||
'skipped' => is_countable( $results['skipped'] ) ? count( $results['skipped'] ) : 0,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
wp_send_json_success(
|
||||
array(
|
||||
'position' => $importer->get_file_position(),
|
||||
'percentage' => $percent_complete,
|
||||
'imported' => is_countable( $results['imported'] ) ? count( $results['imported'] ) : 0,
|
||||
'imported_variations' => is_countable( $results['imported_variations'] ) ? count( $results['imported_variations'] ) : 0,
|
||||
'failed' => is_countable( $results['failed'] ) ? count( $results['failed'] ) : 0,
|
||||
'updated' => is_countable( $results['updated'] ) ? count( $results['updated'] ) : 0,
|
||||
'skipped' => is_countable( $results['skipped'] ) ? count( $results['skipped'] ) : 0,
|
||||
)
|
||||
);
|
||||
}
|
||||
} catch ( \Exception $e ) {
|
||||
wp_send_json_error( array( 'message' => $e->getMessage() ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output information about the uploading process.
|
||||
*/
|
||||
@@ -314,60 +498,20 @@ class WC_Product_CSV_Importer_Controller {
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing -- Nonce already verified in WC_Product_CSV_Importer_Controller::upload_form_handler()
|
||||
$file_url = isset( $_POST['file_url'] ) ? wc_clean( wp_unslash( $_POST['file_url'] ) ) : '';
|
||||
|
||||
if ( empty( $file_url ) ) {
|
||||
if ( ! isset( $_FILES['import'] ) ) {
|
||||
return new WP_Error( 'woocommerce_product_csv_importer_upload_file_empty', __( 'File is empty. Please upload something more substantial. This error could also be caused by uploads being disabled in your php.ini or by post_max_size being defined as smaller than upload_max_filesize in php.ini.', 'woocommerce' ) );
|
||||
try {
|
||||
if ( ! empty( $file_url ) ) {
|
||||
$path = ABSPATH . $file_url;
|
||||
self::check_file_path( $path );
|
||||
} else {
|
||||
$csv_import_util = wc_get_container()->get( Automattic\WooCommerce\Internal\Admin\ImportExport\CSVUploadHelper::class );
|
||||
$upload = $csv_import_util->handle_csv_upload( 'product', 'import', self::get_valid_csv_filetypes() );
|
||||
$path = $upload['file'];
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
|
||||
if ( ! self::is_file_valid_csv( wc_clean( wp_unslash( $_FILES['import']['name'] ) ), false ) ) {
|
||||
return new WP_Error( 'woocommerce_product_csv_importer_upload_file_invalid', __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
$overrides = array(
|
||||
'test_form' => false,
|
||||
'mimes' => self::get_valid_csv_filetypes(),
|
||||
);
|
||||
$import = $_FILES['import']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash
|
||||
$upload = wp_handle_upload( $import, $overrides );
|
||||
|
||||
if ( isset( $upload['error'] ) ) {
|
||||
return new WP_Error( 'woocommerce_product_csv_importer_upload_error', $upload['error'] );
|
||||
}
|
||||
|
||||
// Construct the object array.
|
||||
$object = array(
|
||||
'post_title' => basename( $upload['file'] ),
|
||||
'post_content' => $upload['url'],
|
||||
'post_mime_type' => $upload['type'],
|
||||
'guid' => $upload['url'],
|
||||
'context' => 'import',
|
||||
'post_status' => 'private',
|
||||
);
|
||||
|
||||
// Save the data.
|
||||
$id = wp_insert_attachment( $object, $upload['file'] );
|
||||
|
||||
/*
|
||||
* Schedule a cleanup for one day from now in case of failed
|
||||
* import or missing wp_import_cleanup() call.
|
||||
*/
|
||||
wp_schedule_single_event( time() + DAY_IN_SECONDS, 'importer_scheduled_cleanup', array( $id ) );
|
||||
|
||||
return $upload['file'];
|
||||
} elseif (
|
||||
( 0 === stripos( realpath( ABSPATH . $file_url ), ABSPATH ) ) &&
|
||||
file_exists( ABSPATH . $file_url )
|
||||
) {
|
||||
if ( ! self::is_file_valid_csv( ABSPATH . $file_url ) ) {
|
||||
return new WP_Error( 'woocommerce_product_csv_importer_upload_file_invalid', __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
return ABSPATH . $file_url;
|
||||
return $path;
|
||||
} catch ( \Exception $e ) {
|
||||
return new \WP_Error( 'woocommerce_product_csv_importer_upload_invalid_file', $e->getMessage() );
|
||||
}
|
||||
// phpcs:enable
|
||||
|
||||
return new WP_Error( 'woocommerce_product_csv_importer_upload_invalid_file', __( 'Please upload or provide the link to a valid CSV file.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -375,6 +519,8 @@ class WC_Product_CSV_Importer_Controller {
|
||||
*/
|
||||
protected function mapping_form() {
|
||||
check_admin_referer( 'woocommerce-csv-importer' );
|
||||
self::check_file_path( $this->file );
|
||||
|
||||
$args = array(
|
||||
'lines' => 1,
|
||||
'delimiter' => $this->delimiter,
|
||||
@@ -412,18 +558,7 @@ class WC_Product_CSV_Importer_Controller {
|
||||
// Displaying this page triggers Ajax action to run the import with a valid nonce,
|
||||
// therefore this page needs to be nonce protected as well.
|
||||
check_admin_referer( 'woocommerce-csv-importer' );
|
||||
|
||||
if ( ! self::is_file_valid_csv( $this->file ) ) {
|
||||
$this->add_error( __( 'Invalid file type. The importer supports CSV and TXT file formats.', 'woocommerce' ) );
|
||||
$this->output_errors();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! is_file( $this->file ) ) {
|
||||
$this->add_error( __( 'The file does not exist, please try again.', 'woocommerce' ) );
|
||||
$this->output_errors();
|
||||
return;
|
||||
}
|
||||
self::check_file_path( $this->file );
|
||||
|
||||
if ( ! empty( $_POST['map_from'] ) && ! empty( $_POST['map_to'] ) ) {
|
||||
$mapping_from = wc_clean( wp_unslash( $_POST['map_from'] ) );
|
||||
|
||||
@@ -32,7 +32,8 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
array(
|
||||
'id' => '_global_unique_id',
|
||||
'value' => $product_object->get_global_unique_id( 'edit' ),
|
||||
'label' => __( 'GTIN, UPC, EAN or ISBN', 'woocommerce' ),
|
||||
// translators: %1$s GTIN %2$s UPC %3$s EAN %4$s ISBN.
|
||||
'label' => sprintf( __( '%1$s, %2$s, %3$s, or %4$s', 'woocommerce' ), '<abbr title="' . esc_attr__( 'Global Trade Item Number', 'woocommerce' ) . '">' . esc_html__( 'GTIN', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'Universal Product Code', 'woocommerce' ) . '">' . esc_html__( 'UPC', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'European Article Number', 'woocommerce' ) . '">' . esc_html__( 'EAN', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'International Standard Book Number', 'woocommerce' ) . '">' . esc_html__( 'ISBN', 'woocommerce' ) . '</abbr>' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Enter a barcode or any other identifier unique to this product. It can help you list this product on other channels or marketplaces.', 'woocommerce' ),
|
||||
)
|
||||
|
||||
@@ -32,9 +32,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
$selected_value = 'yes' === ( isset( $option['default'] ) ? $option['default'] : 'no' );
|
||||
}
|
||||
?>
|
||||
<label for="<?php echo esc_attr( $option['id'] ); ?>" class="<?php echo esc_attr( $option['wrapper_class'] ); ?> tips" data-tip="<?php echo esc_attr( $option['description'] ); ?>">
|
||||
<?php echo esc_html( $option['label'] ); ?>:
|
||||
<label for="<?php echo esc_attr( $option['id'] ); ?>" class="<?php echo esc_attr( $option['wrapper_class'] ); ?> tips has-checkbox" data-tip="<?php echo esc_attr( $option['description'] ); ?>">
|
||||
<input type="checkbox" name="<?php echo esc_attr( $option['id'] ); ?>" id="<?php echo esc_attr( $option['id'] ); ?>" data-product-type-option-id="<?php echo esc_attr( $option['id'] ); ?>" <?php echo checked( $selected_value, true, false ); ?> />
|
||||
<?php echo esc_html( $option['label'] ); ?>
|
||||
</label>
|
||||
<?php endforeach; ?>
|
||||
</span>
|
||||
|
||||
@@ -98,7 +98,8 @@ defined( 'ABSPATH' ) || exit;
|
||||
'name' => "variable_global_unique_id[{$loop}]",
|
||||
'value' => $variation_object->get_global_unique_id( 'edit' ),
|
||||
'placeholder' => $variation_object->get_global_unique_id(),
|
||||
'label' => __( 'GTIN, UPC, EAN or ISBN', 'woocommerce' ),
|
||||
// translators: %1$s GTIN %2$s UPC %3$s EAN %4$s ISBN.
|
||||
'label' => sprintf( __( '%1$s, %2$s, %3$s, or %4$s', 'woocommerce' ), '<abbr title="' . esc_attr__( 'Global Trade Item Number', 'woocommerce' ) . '">' . esc_html__( 'GTIN', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'Universal Product Code', 'woocommerce' ) . '">' . esc_html__( 'UPC', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'European Article Number', 'woocommerce' ) . '">' . esc_html__( 'EAN', 'woocommerce' ) . '</abbr>', '<abbr title="' . esc_attr__( 'International Standard Book Number', 'woocommerce' ) . '">' . esc_html__( 'ISBN', 'woocommerce' ) . '</abbr>' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Enter a barcode or any other identifier unique to this product. It can help you list this product on other channels or marketplaces.', 'woocommerce' ),
|
||||
'wrapper_class' => 'form-row',
|
||||
|
||||
@@ -38,13 +38,19 @@ class WC_Settings_Advanced extends WC_Settings_Page {
|
||||
* @return array
|
||||
*/
|
||||
protected function get_own_sections() {
|
||||
return array(
|
||||
$sections = array(
|
||||
'' => __( 'Page setup', 'woocommerce' ),
|
||||
'keys' => __( 'REST API', 'woocommerce' ),
|
||||
'webhooks' => __( 'Webhooks', 'woocommerce' ),
|
||||
'legacy_api' => __( 'Legacy API', 'woocommerce' ),
|
||||
'woocommerce_com' => __( 'WooCommerce.com', 'woocommerce' ),
|
||||
);
|
||||
|
||||
if ( Features::is_enabled( 'blueprint' ) ) {
|
||||
$sections['blueprint'] = __( 'Blueprint', 'woocommerce' );
|
||||
}
|
||||
|
||||
return $sections;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,6 +432,27 @@ class WC_Settings_Advanced extends WC_Settings_Page {
|
||||
return apply_filters( 'woocommerce_settings_rest_api', $settings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get settings for the Blueprint section.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_settings_for_blueprint_section() {
|
||||
$settings =
|
||||
array(
|
||||
array(
|
||||
'title' => esc_html__( 'Blueprint', 'woocommerce' ),
|
||||
'type' => 'title',
|
||||
),
|
||||
array(
|
||||
'id' => 'wc_settings_blueprint_slotfill',
|
||||
'type' => 'slotfill_placeholder',
|
||||
),
|
||||
);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form method.
|
||||
*
|
||||
|
||||
@@ -130,19 +130,6 @@ class WC_Settings_Emails extends WC_Settings_Page {
|
||||
'desc_tip' => true,
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Footer text', 'woocommerce' ),
|
||||
/* translators: %s: Available placeholders for use */
|
||||
'desc' => __( 'The text to appear in the footer of all WooCommerce emails.', 'woocommerce' ) . ' ' . sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '{site_title} {site_url}' ),
|
||||
'id' => 'woocommerce_email_footer_text',
|
||||
'css' => 'width:400px; height: 75px;',
|
||||
'placeholder' => __( 'N/A', 'woocommerce' ),
|
||||
'type' => 'textarea',
|
||||
'default' => '{site_title} — Built with {WooCommerce}',
|
||||
'autoload' => false,
|
||||
'desc_tip' => true,
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Base color', 'woocommerce' ),
|
||||
/* translators: %s: default color */
|
||||
@@ -191,6 +178,31 @@ class WC_Settings_Emails extends WC_Settings_Page {
|
||||
'desc_tip' => true,
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Footer text', 'woocommerce' ),
|
||||
/* translators: %s: Available placeholders for use */
|
||||
'desc' => __( 'The text to appear in the footer of all WooCommerce emails.', 'woocommerce' ) . ' ' . sprintf( __( 'Available placeholders: %s', 'woocommerce' ), '{site_title} {site_url}' ),
|
||||
'id' => 'woocommerce_email_footer_text',
|
||||
'css' => 'width:400px; height: 75px;',
|
||||
'placeholder' => __( 'N/A', 'woocommerce' ),
|
||||
'type' => 'textarea',
|
||||
'default' => '{site_title} — Built with {WooCommerce}',
|
||||
'autoload' => false,
|
||||
'desc_tip' => true,
|
||||
),
|
||||
|
||||
array(
|
||||
'title' => __( 'Footer text color', 'woocommerce' ),
|
||||
/* translators: %s: footer default color */
|
||||
'desc' => sprintf( __( 'The footer text color. Default %s.', 'woocommerce' ), '<code>#3c3c3c</code>' ),
|
||||
'id' => 'woocommerce_email_footer_text_color',
|
||||
'type' => 'color',
|
||||
'css' => 'width:6em;',
|
||||
'default' => '#3c3c3c',
|
||||
'autoload' => false,
|
||||
'desc_tip' => true,
|
||||
),
|
||||
|
||||
array(
|
||||
'type' => 'sectionend',
|
||||
'id' => 'email_template_options',
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
declare( strict_types = 1);
|
||||
|
||||
// @codingStandardsIgnoreLine.
|
||||
/**
|
||||
* WooCommerce Checkout Settings
|
||||
*
|
||||
* @package WooCommerce\Admin
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( class_exists( 'WC_Settings_Payment_Gateways_React', false ) ) {
|
||||
return new WC_Settings_Payment_Gateways_React();
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Settings_Payment_Gateways_React.
|
||||
*/
|
||||
class WC_Settings_Payment_Gateways_React extends WC_Settings_Page {
|
||||
|
||||
/**
|
||||
* Get the whitelist of sections to render using React.
|
||||
*
|
||||
* @return array List of section identifiers.
|
||||
*/
|
||||
private function get_reactify_render_sections() {
|
||||
$sections = array(
|
||||
'offline',
|
||||
'woocommerce_payments',
|
||||
'main',
|
||||
);
|
||||
|
||||
/**
|
||||
* Filters the list of payment settings sections to be rendered using React.
|
||||
*
|
||||
* @since 9.3.0
|
||||
*
|
||||
* @param array $sections List of section identifiers.
|
||||
*/
|
||||
return apply_filters( 'experimental_woocommerce_admin_payment_reactify_render_sections', $sections );
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->id = 'checkout';
|
||||
$this->label = _x( 'Payments', 'Settings tab label', 'woocommerce' );
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the settings.
|
||||
*/
|
||||
public function output() {
|
||||
//phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||
global $current_section;
|
||||
|
||||
// Load gateways so we can show any global options they may have.
|
||||
$payment_gateways = WC()->payment_gateways->payment_gateways();
|
||||
|
||||
if ( $this->should_render_react_section( $current_section ) ) {
|
||||
$this->render_react_section( $current_section );
|
||||
} elseif ( $current_section ) {
|
||||
$this->render_classic_gateway_settings_page( $payment_gateways, $current_section );
|
||||
} else {
|
||||
$this->render_react_section( 'main' );
|
||||
}
|
||||
|
||||
parent::output();
|
||||
//phpcs:enable
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given section should be rendered using React.
|
||||
*
|
||||
* @param string $section The section to check.
|
||||
* @return bool Whether the section should be rendered using React.
|
||||
*/
|
||||
private function should_render_react_section( $section ) {
|
||||
return in_array( $section, $this->get_reactify_render_sections(), true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the React section.
|
||||
*
|
||||
* @param string $section The section to render.
|
||||
*/
|
||||
private function render_react_section( $section ) {
|
||||
global $hide_save_button;
|
||||
$hide_save_button = true;
|
||||
echo '<div id="experimental_wc_settings_payments_' . esc_attr( $section ) . '"></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the classic gateway settings page.
|
||||
*
|
||||
* @param array $payment_gateways The payment gateways.
|
||||
* @param string $current_section The current section.
|
||||
*/
|
||||
private function render_classic_gateway_settings_page( $payment_gateways, $current_section ) {
|
||||
foreach ( $payment_gateways as $gateway ) {
|
||||
if ( in_array( $current_section, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
|
||||
if ( isset( $_GET['toggle_enabled'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
$enabled = $gateway->get_option( 'enabled' );
|
||||
|
||||
if ( $enabled ) {
|
||||
$gateway->settings['enabled'] = wc_string_to_bool( $enabled ) ? 'no' : 'yes';
|
||||
}
|
||||
}
|
||||
$this->run_gateway_admin_options( $gateway );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the 'admin_options' method on a given gateway.
|
||||
* This method exists to easy unit testing.
|
||||
*
|
||||
* @param object $gateway The gateway object to run the method on.
|
||||
*/
|
||||
protected function run_gateway_admin_options( $gateway ) {
|
||||
$gateway->admin_options();
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't show any section links.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_sections() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings.
|
||||
*/
|
||||
public function save() {
|
||||
global $current_section;
|
||||
|
||||
$wc_payment_gateways = WC_Payment_Gateways::instance();
|
||||
|
||||
$this->save_settings_for_current_section();
|
||||
|
||||
if ( ! $current_section ) {
|
||||
// If section is empty, we're on the main settings page. This makes sure 'gateway ordering' is saved.
|
||||
$wc_payment_gateways->process_admin_options();
|
||||
$wc_payment_gateways->init();
|
||||
} else {
|
||||
// There is a section - this may be a gateway or custom section.
|
||||
foreach ( $wc_payment_gateways->payment_gateways() as $gateway ) {
|
||||
if ( in_array( $current_section, array( $gateway->id, sanitize_title( get_class( $gateway ) ) ), true ) ) {
|
||||
/**
|
||||
* Fires update actions for payment gateways.
|
||||
*
|
||||
* @since 3.4.0
|
||||
*
|
||||
* @param int $gateway->id Gateway ID.
|
||||
*/
|
||||
do_action( 'woocommerce_update_options_payment_gateways_' . $gateway->id );
|
||||
$wc_payment_gateways->init();
|
||||
}
|
||||
}
|
||||
|
||||
$this->do_update_options_action();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new WC_Settings_Payment_Gateways_React();
|
||||
@@ -8,7 +8,20 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<span><?php esc_html_e( 'Shipping zones', 'woocommerce' ); ?></span>
|
||||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&zone_id=new' ) ); ?>" class="page-title-action"><?php esc_html_e( 'Add zone', 'woocommerce' ); ?></a>
|
||||
</h2>
|
||||
<p class="wc-shipping-zone-heading-help-text"><?php echo esc_html_e( 'A shipping zone consists of the region(s) you\'d like to ship to and the shipping method(s) offered. A shopper can only be matched to one zone, and we\'ll use their shipping address to show them the methods available in their area.', 'woocommerce' ); ?></p>
|
||||
<p class="wc-shipping-zone-heading-help-text">
|
||||
<?php
|
||||
echo wp_kses_post(
|
||||
sprintf(
|
||||
/* translators: %s: URL to local pickup settings */
|
||||
__(
|
||||
"A shipping zone consists of the region(s) you'd like to ship to and the shipping method(s) offered. A shopper can only be matched to one zone, and we'll use their shipping address to show them the methods available in their area. To offer local pickup, configure your pickup locations in the <a href='%s'>local pickup settings</a>.",
|
||||
'woocommerce'
|
||||
),
|
||||
esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping§ion=pickup_location' ) )
|
||||
)
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<table class="wc-shipping-zones widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -56,14 +69,13 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<?php if ( 0 === $method_count ) : ?>
|
||||
<tr>
|
||||
<td class="wc-shipping-zones-blank-state" colspan="5">
|
||||
<p class="main"><?php _e( 'A shipping zone is a geographic region where a certain set of shipping methods and rates apply.', 'woocommerce' ); ?></p>
|
||||
<p><?php _e( 'For example:', 'woocommerce' ); ?></p>
|
||||
<p class="main"><?php esc_html_e( 'A shipping zone is a geographic region where a certain set of shipping methods and rates apply.', 'woocommerce' ); ?></p>
|
||||
<p><?php esc_html_e( 'For example:', 'woocommerce' ); ?></p>
|
||||
<ul>
|
||||
<li><?php _e( 'Local zone = California ZIP 90210 = Local pickup', 'woocommerce' ); ?>
|
||||
<li><?php _e( 'US domestic zone = All US states = Flat rate shipping', 'woocommerce' ); ?>
|
||||
<li><?php _e( 'Europe zone = Any country in Europe = Flat rate shipping', 'woocommerce' ); ?>
|
||||
<li><?php esc_html_e( 'US domestic zone = All US states = Flat rate shipping', 'woocommerce' ); ?>
|
||||
<li><?php esc_html_e( 'Europe zone = Any country in Europe = Flat rate shipping', 'woocommerce' ); ?>
|
||||
</ul>
|
||||
<p><?php _e( 'Add as many zones as you need – customers will only see the methods available for their address.', 'woocommerce' ); ?></p>
|
||||
<p><?php esc_html_e( 'Add as many zones as you need – customers will only see the methods available for their address.', 'woocommerce' ); ?></p>
|
||||
<a class="button button-primary wc-shipping-zone-add" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=shipping&zone_id=new' ) ); ?>"><?php _e( 'Add shipping zone', 'woocommerce' ); ?></a>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -95,9 +107,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
<div class="wc-backbone-modal-content">
|
||||
<section class="wc-backbone-modal-main" role="main">
|
||||
<header class="wc-backbone-modal-header">
|
||||
<h1><?php _e( 'Add shipping method', 'woocommerce' ); ?></h1>
|
||||
<h1><?php esc_html_e( 'Add shipping method', 'woocommerce' ); ?></h1>
|
||||
<button class="modal-close modal-close-link dashicons dashicons-no-alt">
|
||||
<span class="screen-reader-text"><?php _e( 'Close modal panel', 'woocommerce' ); ?></span>
|
||||
<span class="screen-reader-text"><?php esc_html_e( 'Close modal panel', 'woocommerce' ); ?></span>
|
||||
</button>
|
||||
</header>
|
||||
<article>
|
||||
|
||||
@@ -1060,6 +1060,12 @@ if ( 0 < $mu_plugins_count ) :
|
||||
</mark>
|
||||
<a href="https://woocommerce.com/document/fix-outdated-templates-woocommerce/" target="_blank">
|
||||
<?php esc_html_e( 'Learn how to update', 'woocommerce' ); ?>
|
||||
</a> |
|
||||
<mark class="info">
|
||||
<span class="dashicons dashicons-info"></span>
|
||||
</mark>
|
||||
<a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-status&tab=tools' ) ); ?>">
|
||||
<?php esc_html_e( 'Clear system status theme info cache', 'woocommerce' ); ?>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user