Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/woocommerce-jetpack/includes/admin/class-booster-onboarding.php
+++ b/woocommerce-jetpack/includes/admin/class-booster-onboarding.php
@@ -163,6 +163,7 @@
* Modal only appears on Booster admin pages (wcj-*) to be less intrusive.
*/
public function maybe_show_onboarding_modal() {
+ // phpcs:ignore WordPress.WP.Capabilities.Unknown
if ( ! current_user_can( 'manage_woocommerce' ) ) {
return;
}
@@ -322,6 +323,7 @@
public function ajax_apply_goal() {
check_ajax_referer( 'booster_onboarding_nonce', 'nonce' );
+ // phpcs:ignore WordPress.WP.Capabilities.Unknown
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'Insufficient permissions.', 'woocommerce-jetpack' ) );
}
@@ -351,6 +353,7 @@
public function ajax_undo_goal() {
check_ajax_referer( 'booster_onboarding_nonce', 'nonce' );
+ // phpcs:ignore WordPress.WP.Capabilities.Unknown
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_die( esc_html__( 'Insufficient permissions.', 'woocommerce-jetpack' ) );
}
@@ -433,6 +436,24 @@
update_option( $this->option_key, $onboarding_state );
+ $this->log_onboarding_event(
+ 'goal_applied',
+ array(
+ 'goal_id' => $goal_id,
+ 'modules_enabled' => array_column( $goal['modules'], 'id' ),
+ 'snapshot_created' => $create_snapshot,
+ )
+ );
+
+ $this->log_onboarding_event(
+ 'goal_completed',
+ array(
+ 'goal_id' => $goal_id,
+ 'is_first_goal' => $is_first_win,
+ 'first_win_check_met' => $this->check_first_win( $goal_id ),
+ )
+ );
+
$next_step_link = '';
if ( isset( $goal['next_step_link'] ) ) {
$next_step_link = admin_url( $goal['next_step_link'] . wp_create_nonce( 'wcj-cat-nonce' ) );
@@ -443,11 +464,78 @@
'message' => __( 'Goal applied successfully!', 'woocommerce-jetpack' ),
'next_step_text' => isset( $goal['next_step_text'] ) ? $goal['next_step_text'] : '',
'next_step_link' => $next_step_link,
+ 'next_steps' => $this->get_goal_next_steps( $goal_id ),
'first_win' => $is_first_win,
);
}
/**
+ * Get goal-specific next-step guidance for success states.
+ *
+ * @param string $goal_id Goal ID.
+ *
+ * @return array
+ */
+ private function get_goal_next_steps( $goal_id ) {
+ $steps = array(
+ 'grow_sales' => array(
+ __( 'Visit a product page to verify live sales notifications are visible.', 'woocommerce-jetpack' ),
+ __( 'Adjust notification timing and styling to match your brand.', 'woocommerce-jetpack' ),
+ ),
+ 'work_smarter' => array(
+ __( 'Open your orders list to confirm sequential numbering is enabled.', 'woocommerce-jetpack' ),
+ __( 'Set your preferred order number format and prefix.', 'woocommerce-jetpack' ),
+ ),
+ 'go_global' => array(
+ __( 'Add exchange rates for your target markets.', 'woocommerce-jetpack' ),
+ __( 'Test currency switching on storefront pages.', 'woocommerce-jetpack' ),
+ ),
+ 'professional_invoices' => array(
+ __( 'Generate a test order to confirm PDF invoices are attached.', 'woocommerce-jetpack' ),
+ __( 'Customize invoice logo and footer text for your store.', 'woocommerce-jetpack' ),
+ ),
+ 'boost_conversions_free' => array(
+ __( 'Enable add-ons on a top-selling product first.', 'woocommerce-jetpack' ),
+ __( 'Verify related products are showing on product pages.', 'woocommerce-jetpack' ),
+ ),
+ 'better_checkout_basics' => array(
+ __( 'Review checkout field labels and ordering for clarity.', 'woocommerce-jetpack' ),
+ __( 'Run a test checkout to confirm the updated flow.', 'woocommerce-jetpack' ),
+ ),
+ 'store_essentials_quick' => array(
+ __( 'Confirm new orders are using sequential numbering.', 'woocommerce-jetpack' ),
+ __( 'Add one global product tab with key purchase info.', 'woocommerce-jetpack' ),
+ ),
+ 'recover_lost_sales_goal' => array(
+ __( 'Review abandonment timing and email trigger settings.', 'woocommerce-jetpack' ),
+ __( 'Send a test recovery email and validate links.', 'woocommerce-jetpack' ),
+ ),
+ 'b2b_store' => array(
+ __( 'Validate role-based pricing and gateway rules with a test user.', 'woocommerce-jetpack' ),
+ __( 'Configure a first B2B-only coupon to confirm restrictions.', 'woocommerce-jetpack' ),
+ ),
+ 'intl_Store' => array(
+ __( 'Verify currency display by country selection in storefront.', 'woocommerce-jetpack' ),
+ __( 'Check exchange rates and update any market-specific values.', 'woocommerce-jetpack' ),
+ ),
+ 'merchant_getting_started' => array(
+ __( 'Add one required product input field to a sample product.', 'woocommerce-jetpack' ),
+ __( 'Confirm checkout custom info appears as expected.', 'woocommerce-jetpack' ),
+ ),
+ 'merchant_aov_increase' => array(
+ __( 'Generate a sample coupon and test URL coupon behavior.', 'woocommerce-jetpack' ),
+ __( 'Preview sale flash badges on discounted products.', 'woocommerce-jetpack' ),
+ ),
+ 'merchant_run_their_store_efficiently' => array(
+ __( 'Run a sample export to validate data columns.', 'woocommerce-jetpack' ),
+ __( 'Review admin product list columns for daily workflow fit.', 'woocommerce-jetpack' ),
+ ),
+ );
+
+ return isset( $steps[ $goal_id ] ) ? $steps[ $goal_id ] : array();
+ }
+
+ /**
* Create a snapshot of current settings before applying changes.
*
* @param string $goal The goal ID for which to create the snapshot.
@@ -574,8 +662,17 @@
* Create draft page for one page checkout
*/
private function create_one_page_checkout_draft() {
- $existing_page = get_page_by_title( 'Quick Checkout (Draft)', OBJECT, 'page' );
- if ( $existing_page ) {
+ $query = new WP_Query(
+ array(
+ 'post_type' => 'page',
+ 'title' => 'Quick Checkout (Draft)',
+ 'post_status' => array( 'publish', 'draft', 'pending', 'private' ),
+ 'posts_per_page' => 1,
+ 'fields' => 'ids',
+ )
+ );
+
+ if ( ! empty( $query->posts ) ) {
return;
}
@@ -751,6 +848,14 @@
update_option( $this->option_key, $onboarding_state );
+ $this->log_onboarding_event(
+ 'goal_undone',
+ array(
+ 'goal_id' => $goal_id,
+ 'snapshot_restored' => true,
+ )
+ );
+
return array(
'success' => true,
'message' => __( 'Goal undone successfully!', 'woocommerce-jetpack' ),
@@ -761,7 +866,19 @@
* Remove one page checkout draft page
*/
private function remove_one_page_checkout_draft() {
- $page = get_page_by_title( 'Quick Checkout (Draft)', OBJECT, 'page' );
+ $page = new WP_Query(
+ array(
+ 'post_type' => 'page',
+ 'title' => 'Quick Checkout (Draft)',
+ 'post_status' => array( 'publish', 'draft', 'pending', 'private' ),
+ 'posts_per_page' => 1,
+ 'fields' => 'ids',
+ )
+ );
+
+ if ( ! empty( $page->posts ) ) {
+ return;
+ }
if ( $page && 'draft' === $page->post_status ) {
wp_delete_post( $page->ID, true );
}
@@ -787,7 +904,19 @@
return 'yes' === get_option( 'wcj_sales_notifications_enabled', 'no' );
case 'one_page_checkout_draft_page_exists':
- $page = get_page_by_title( 'Quick Checkout (Draft)', OBJECT, 'page' );
+ $page = new WP_Query(
+ array(
+ 'post_type' => 'page',
+ 'title' => 'Quick Checkout (Draft)',
+ 'post_status' => array( 'publish', 'draft', 'pending', 'private' ),
+ 'posts_per_page' => 1,
+ 'fields' => 'ids',
+ )
+ );
+
+ if ( ! empty( $page->posts ) ) {
+ return;
+ }
return $page && 'draft' === $page->post_status;
case 'reviews_enabled':
@@ -796,6 +925,9 @@
case 'order_numbers_enabled':
return 'yes' === get_option( 'wcj_order_numbers_enabled', 'no' );
+ case 'wcj_order_numbers_enabled':
+ return 'yes' === get_option( 'wcj_order_numbers_enabled', 'no' );
+
case 'extra_currency_added':
$current_currency = get_woocommerce_currency();
return ( 'EUR' !== $current_currency && get_option( 'wcj_currency_EUR' ) ) ||
@@ -825,6 +957,10 @@
case 'wcj_export_enabled':
return 'yes' === get_option( 'wcj_export_enabled', 'no' );
+ case 'wcj_cart_abandonment_enabled':
+ case 'cart_abandonment_enabled':
+ return 'yes' === get_option( 'wcj_cart_abandonment_enabled', 'no' );
+
default:
return false;
}
@@ -836,6 +972,7 @@
public function ajax_apply_blueprint() {
check_ajax_referer( 'booster_onboarding_nonce', 'nonce' );
+ // phpcs:ignore WordPress.WP.Capabilities.Unknown
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( array( 'message' => __( 'Permission denied.', 'woocommerce-jetpack' ) ) );
}
@@ -951,6 +1088,7 @@
public function ajax_undo_blueprint() {
check_ajax_referer( 'booster_onboarding_nonce', 'nonce' );
+ // phpcs:ignore WordPress.WP.Capabilities.Unknown
if ( ! current_user_can( 'manage_woocommerce' ) ) {
wp_send_json_error( array( 'message' => __( 'Permission denied.', 'woocommerce-jetpack' ) ) );
}
--- a/woocommerce-jetpack/includes/admin/class-wcj-settings-manager.php
+++ b/woocommerce-jetpack/includes/admin/class-wcj-settings-manager.php
@@ -1,277 +1,277 @@
-<?php
-/**
- * Booster for WooCommerce - Settings Manager - Import / Export / Reset Booster's settings
- *
- * @version 7.1.0
- * @since 2.9.0
- * @author Pluggabl LLC.
- * @package Booster_For_WooCommerce/admin
- */
-
-if ( ! defined( 'ABSPATH' ) ) {
- exit; // Exit if accessed directly.
-}
-
-if ( ! class_exists( 'WCJ_Settings_Manager' ) ) :
- /**
- * WCJ_Settings_Manager.
- */
- class WCJ_Settings_Manager {
-
-
- /**
- * Constructor.
- *
- * @version 7.1.0
- * @since 2.9.0
- * @todo add options to import/export selected modules only
- */
- public function __construct() {
- if ( is_admin() ) {
- if ( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ) {
- return;
- }
- add_action( 'admin_post_wcj_save_general_settings', array( $this, 'wcj_manage_plugin_options' ) );
- }
- }
-
- /**
- * Manage_options.
- *
- * @version 7.1.0
- * @since 2.5.2
- */
- public function wcj_manage_plugin_options() {
- if ( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ) {
- return;
- }
- $msg = __( 'Your settings have been saved.', 'woocommerce-jetpack' );
-
- require_once ABSPATH . '/wp-admin/includes/file.php';
- global $wp_filesystem;
- WP_Filesystem();
- $file_name = 'booster_settings.txt';
- $file_path = wcj_get_wcj_uploads_dir() . DIRECTORY_SEPARATOR . $file_name;
- if ( $wp_filesystem->exists( $file_path ) ) {
- $wp_filesystem->delete( $file_path, true );
- }
- $wpnonce = isset( $_REQUEST['wcj-verify-manage-settings'] ) ? wp_verify_nonce( sanitize_key( $_REQUEST['wcj-verify-manage-settings'] ), 'wcj-verify-manage-settings' ) : false;
-
- if ( $wpnonce ) {
-
- if ( isset( $_POST['return_url'] ) ) {
- $return_url = sanitize_text_field( wp_unslash( $_POST['return_url'] ) ) . '&msg=' . $msg . '&wcj-cat-nonce=' . wp_create_nonce( 'wcj-cat-nonce' );
- } else {
- $return_url = admin_url( 'admin.php?page=wcj-plugins&wcj-cat-nonce=' . wp_create_nonce( 'wcj-cat-nonce' ) );
- }
-
- if ( isset( $_POST['booster_export_settings'] ) ) {
- $this->manage_options_export();
- }
-
- if ( isset( $_POST['booster_import_settings'] ) ) {
- $msg = $this->manage_options_import();
- $return_url .= '&msg=' . $msg;
- if ( isset( $_POST['wcj_quick_action'] ) ) {
- $return_url .= '#message';
- }
- wp_safe_redirect( $return_url );
- exit();
- }
-
- if ( isset( $_POST['booster_reset_settings'] ) ) {
- $msg = $this->manage_options_reset();
- $return_url .= '&msg=' . $msg;
- wp_safe_redirect( $return_url );
- exit();
- }
- if ( isset( $_POST['booster_reset_settings_meta'] ) ) {
- $msg = $this->manage_options_reset_meta();
- $return_url .= '&msg=' . $msg;
- wp_safe_redirect( $return_url );
- exit();
- }
-
- $general_setting_fields = array(
- 'wcj_autoload_options' => isset( $_POST['wcj_autoload_options'] ) ? sanitize_text_field( wp_unslash( $_POST['wcj_autoload_options'] ) ) : null,
- 'wcj_load_modules_on_init' => isset( $_POST['wcj_load_modules_on_init'] ) ? sanitize_text_field( wp_unslash( $_POST['wcj_load_modules_on_init'] ) ) : null,
- 'wcj_list_for_products' => isset( $_POST['wcj_list_for_products'] ) ? sanitize_text_field( wp_unslash( $_POST['wcj_list_for_products'] ) ) : null,
- 'wcj_list_for_products_cats' => isset( $_POST['wcj_list_for_products_cats'] ) ? sanitize_text_field( wp_unslash( $_POST['wcj_list_for_products_cats'] ) ) : null,
- 'wcj_list_for_products_tags' => isset( $_POST['wcj_list_for_products_tags'] ) ? sanitize_text_field( wp_unslash( $_POST['wcj_list_for_products_tags'] ) ) : null,
- );
-
- foreach ( $general_setting_fields as $setting_key => $setting_value ) {
- if ( ! empty( $setting_value ) && null !== $setting_value ) {
- update_option( $setting_key, $setting_value );
- }
- }
-
- if ( isset( $_POST['wcj_site_key'] ) ) {
- if ( class_exists( 'WCJ_Plus_Site_Key_Manager' ) ) {
- $site_key_manager = new WCJ_Plus_Site_Key_Manager();
- $site_key_manager->check_site_key();
- }
- }
-
- $return_url .= '&msg=' . $msg;
- wp_safe_redirect( $return_url );
- exit();
- }
- }
-
- /**
- * Manage_options_import.
- *
- * @version 7.1.0
- * @since 2.5.2
- */
- public function manage_options_import() {
- global $wcj_notice;
- if ( ! isset( $_FILES['booster_import_settings_file']['tmp_name'] ) || '' === $_FILES['booster_import_settings_file']['tmp_name'] ) {
- $wcj_notice .= __( 'Please upload a file to import!', 'woocommerce-jetpack' );
- $import_settings = array();
- $wpnonce = isset( $_REQUEST['wcj-verify-manage-settings'] ) ? wp_verify_nonce( sanitize_key( $_REQUEST['wcj-verify-manage-settings'] ), 'wcj-verify-manage-settings' ) : false;
- if ( $wpnonce ) {
- unset( $_POST['booster_import_settings'] );
- }
- return $wcj_notice;
- } else {
- require_once ABSPATH . '/wp-admin/includes/file.php';
- global $wp_filesystem;
- WP_Filesystem();
- $import_counter = 0;
- if (
- isset( $_POST['booster_import_nonce'] ) &&
- wp_verify_nonce(
- sanitize_text_field( wp_unslash( $_POST['booster_import_nonce'] ) ),
- 'booster_import_action'
- ) &&
- isset( $_FILES['booster_import_settings_file'] ) &&
- isset(
- $_FILES['booster_import_settings_file']['error'],
- $_FILES['booster_import_settings_file']['tmp_name']
- )
- ) {
-
- if ( UPLOAD_ERR_OK !== $_FILES['booster_import_settings_file']['error'] ) {
- $wcj_notice .= __( 'Upload failed!', 'woocommerce-jetpack' );
- return $wcj_notice;
- }
-
- $tmp_name = sanitize_text_field(
- wp_unslash( $_FILES['booster_import_settings_file']['tmp_name'] )
- );
-
- $import_settings = $wp_filesystem->get_contents( $tmp_name );
-
- }
- $bom = pack( 'H*', 'EFBBBF' );
- $import_settings = preg_replace( "/^$bom/", '', $import_settings );
- $import_settings = explode( PHP_EOL, preg_replace( '~(*BSR_ANYCRLF)R~', PHP_EOL, $import_settings ) );
- if ( ! is_array( $import_settings ) || 2 !== count( $import_settings ) ) {
- $wcj_notice .= __( 'Wrong file format!', 'woocommerce-jetpack' );
- return $wcj_notice;
- } else {
- $import_header = $import_settings[0];
- $required_header = 'Booster for WooCommerce';
- if ( substr( $import_header, 0, strlen( $required_header ) ) !== $required_header ) {
- $wcj_notice .= __( 'Wrong file format!', 'woocommerce-jetpack' );
- return $wcj_notice;
- } else {
- $import_settings = json_decode( $import_settings[1], true );
- foreach ( $import_settings as $import_key => $import_setting ) {
- if ( strlen( $import_key ) > 4 && 'wcj_' === substr( $import_key, 0, 4 ) ) {
- update_option( $import_key, $import_setting );
- ++$import_counter;
- }
- }
- /* translators: %d: translation added */
- $wcj_notice .= sprintf( __( '%d options successfully imported.', 'woocommerce-jetpack' ), $import_counter );
- return $wcj_notice;
- }
- }
- }
- }
-
- /**
- * Manage_options_export.
- *
- * @version 7.0.0
- * @since 2.5.2
- * @see http://php.net/manual/en/function.header.php
- */
- public function manage_options_export() {
- require_once ABSPATH . '/wp-admin/includes/file.php';
- global $wp_filesystem;
- WP_Filesystem();
- $export_settings = array();
- $export_counter = array();
- $wpnonce = isset( $_REQUEST['wcj-verify-manage-settings'] ) ? wp_verify_nonce( sanitize_key( $_REQUEST['wcj-verify-manage-settings'] ), 'wcj-verify-manage-settings' ) : false;
- foreach ( w_c_j()->modules as $module ) {
- $values = $module->get_settings();
- foreach ( $values as $value ) {
- if ( isset( $value['default'] ) && isset( $value['id'] ) ) {
- if ( isset( $_POST['booster_export_settings'] ) ) {
- $export_settings[ $value['id'] ] = wcj_get_option( $value['id'], $value['default'] );
- if ( ! isset( $export_counter[ $module->short_desc ] ) ) {
- $export_counter[ $module->short_desc ] = 0;
- }
- ++$export_counter[ $module->short_desc ];
- }
- }
- }
- }
- $export_settings = wp_json_encode( $export_settings );
- $export_settings = 'Booster for WooCommerce v' . wcj_get_option( WCJ_VERSION_OPTION, 'NA' ) . PHP_EOL . $export_settings;
- $file_name = 'booster_settings.txt';
- $file_path = wcj_get_wcj_uploads_dir() . DIRECTORY_SEPARATOR . $file_name;
- $wp_filesystem->put_contents( $file_path, $export_settings, FS_CHMOD_FILE );
- WC_Download_Handler::download_file_force( $file_path, $file_name );
- die();
- }
-
- /**
- * Manage_options_reset_meta.
- *
- * @version 7.0.0
- * @since 3.4.0
- * @todo order items meta
- * @todo `... LIKE 'wcj_%'`
- */
- public function manage_options_reset_meta() {
- global $wpdb, $wcj_notice;
- $delete_counter_meta = 0;
- $plugin_meta = $wpdb->get_results( "SELECT * FROM $wpdb->postmeta WHERE meta_key LIKE '_wcj_%'" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
- foreach ( $plugin_meta as $meta ) {
- delete_post_meta( $meta->post_id, $meta->meta_key );
- ++$delete_counter_meta;
- }
- /* translators: %d: translation added */
- $wcj_notice .= sprintf( __( '%d meta successfully deleted.', 'woocommerce-jetpack' ), $delete_counter_meta );
- return $wcj_notice;
- }
-
- /**
- * Manage_options_reset.
- *
- * @version 7.0.0
- * @since 2.5.2
- */
- public function manage_options_reset() {
- global $wpdb, $wcj_notice;
- $delete_counter_options = 0;
- $plugin_options = $wpdb->get_results( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE 'wcj_%'" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
- foreach ( $plugin_options as $option ) {
- delete_option( $option->option_name );
- delete_site_option( $option->option_name );
- ++$delete_counter_options;
- }
- /* translators: %d: translation added */
- $wcj_notice .= sprintf( __( '%d options successfully deleted.', 'woocommerce-jetpack' ), $delete_counter_options );
- return $wcj_notice;
- }
- }
-
-endif;
-
-return new WCJ_Settings_Manager();
+<?php
+/**
+ * Booster for WooCommerce - Settings Manager - Import / Export / Reset Booster's settings
+ *
+ * @version 7.1.0
+ * @since 2.9.0
+ * @author Pluggabl LLC.
+ * @package Booster_For_WooCommerce/admin
+ */
+
+if ( ! defined( 'ABSPATH' ) ) {
+ exit; // Exit if accessed directly.
+}
+
+if ( ! class_exists( 'WCJ_Settings_Manager' ) ) :
+ /**
+ * WCJ_Settings_Manager.
+ */
+ class WCJ_Settings_Manager {
+
+
+ /**
+ * Constructor.
+ *
+ * @version 7.1.0
+ * @since 2.9.0
+ * @todo add options to import/export selected modules only
+ */
+ public function __construct() {
+ if ( is_admin() ) {
+ if ( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ) {
+ return;
+ }
+ add_action( 'admin_post_wcj_save_general_settings', array( $this, 'wcj_manage_plugin_options' ) );
+ }
+ }
+
+ /**
+ * Manage_options.
+ *
+ * @version 7.1.0
+ * @since 2.5.2
+ */
+ public function wcj_manage_plugin_options() {
+ if ( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ) {
+ return;
+ }
+ $msg = __( 'Your settings have been saved.', 'woocommerce-jetpack' );
+
+ require_once ABSPATH . '/wp-admin/includes/file.php';
+ global $wp_filesystem;
+ WP_Filesystem();
+ $file_name = 'booster_settings.txt';
+ $file_path = wcj_get_wcj_uploads_dir() . DIRECTORY_SEPARATOR . $file_name;
+ if ( $wp_filesystem->exists( $file_path ) ) {
+ $wp_filesystem->delete( $file_path, true );
+ }
+ $wpnonce = isset( $_REQUEST['wcj-verify-manage-settings'] ) ? wp_verify_nonce( sanitize_key( $_REQUEST['wcj-verify-manage-settings'] ), 'wcj-verify-manage-settings' ) : false;
+
+ if ( $wpnonce ) {
+
+ if ( isset( $_POST['return_url'] ) ) {
+ $return_url = sanitize_text_field( wp_unslash( $_POST['return_url'] ) ) . '&msg=' . $msg . '&wcj-cat-nonce=' . wp_create_nonce( 'wcj-cat-nonce' );
+ } else {
+ $return_url = admin_url( 'admin.php?page=wcj-plugins&wcj-cat-nonce=' . wp_create_nonce( 'wcj-cat-nonce' ) );
+ }
+
+ if ( isset( $_POST['booster_export_settings'] ) ) {
+ $this->manage_options_export();
+ }
+
+ if ( isset( $_POST['booster_import_settings'] ) ) {
+ $msg = $this->manage_options_import();
+ $return_url .= '&msg=' . $msg;
+ if ( isset( $_POST['wcj_quick_action'] ) ) {
+ $return_url .= '#message';
+ }
+ wp_safe_redirect( $return_url );
+ exit();
+ }
+
+ if ( isset( $_POST['booster_reset_settings'] ) ) {
+ $msg = $this->manage_options_reset();
+ $return_url .= '&msg=' . $msg;
+ wp_safe_redirect( $return_url );
+ exit();
+ }
+ if ( isset( $_POST['booster_reset_settings_meta'] ) ) {
+ $msg = $this->manage_options_reset_meta();
+ $return_url .= '&msg=' . $msg;
+ wp_safe_redirect( $return_url );
+ exit();
+ }
+
+ $general_setting_fields = array(
+ 'wcj_autoload_options' => isset( $_POST['wcj_autoload_options'] ) ? sanitize_text_field( wp_unslash( $_POST['wcj_autoload_options'] ) ) : null,
+ 'wcj_load_modules_on_init' => isset( $_POST['wcj_load_modules_on_init'] ) ? sanitize_text_field( wp_unslash( $_POST['wcj_load_modules_on_init'] ) ) : null,
+ 'wcj_list_for_products' => isset( $_POST['wcj_list_for_products'] ) ? sanitize_text_field( wp_unslash( $_POST['wcj_list_for_products'] ) ) : null,
+ 'wcj_list_for_products_cats' => isset( $_POST['wcj_list_for_products_cats'] ) ? sanitize_text_field( wp_unslash( $_POST['wcj_list_for_products_cats'] ) ) : null,
+ 'wcj_list_for_products_tags' => isset( $_POST['wcj_list_for_products_tags'] ) ? sanitize_text_field( wp_unslash( $_POST['wcj_list_for_products_tags'] ) ) : null,
+ );
+
+ foreach ( $general_setting_fields as $setting_key => $setting_value ) {
+ if ( ! empty( $setting_value ) && null !== $setting_value ) {
+ update_option( $setting_key, $setting_value );
+ }
+ }
+
+ if ( isset( $_POST['wcj_site_key'] ) ) {
+ if ( class_exists( 'WCJ_Plus_Site_Key_Manager' ) ) {
+ $site_key_manager = new WCJ_Plus_Site_Key_Manager();
+ $site_key_manager->check_site_key();
+ }
+ }
+
+ $return_url .= '&msg=' . $msg;
+ wp_safe_redirect( $return_url );
+ exit();
+ }
+ }
+
+ /**
+ * Manage_options_import.
+ *
+ * @version 7.1.0
+ * @since 2.5.2
+ */
+ public function manage_options_import() {
+ global $wcj_notice;
+ if ( ! isset( $_FILES['booster_import_settings_file']['tmp_name'] ) || '' === $_FILES['booster_import_settings_file']['tmp_name'] ) {
+ $wcj_notice .= __( 'Please upload a file to import!', 'woocommerce-jetpack' );
+ $import_settings = array();
+ $wpnonce = isset( $_REQUEST['wcj-verify-manage-settings'] ) ? wp_verify_nonce( sanitize_key( $_REQUEST['wcj-verify-manage-settings'] ), 'wcj-verify-manage-settings' ) : false;
+ if ( $wpnonce ) {
+ unset( $_POST['booster_import_settings'] );
+ }
+ return $wcj_notice;
+ } else {
+ require_once ABSPATH . '/wp-admin/includes/file.php';
+ global $wp_filesystem;
+ WP_Filesystem();
+ $import_counter = 0;
+ if (
+ isset( $_POST['booster_import_nonce'] ) &&
+ wp_verify_nonce(
+ sanitize_text_field( wp_unslash( $_POST['booster_import_nonce'] ) ),
+ 'booster_import_action'
+ ) &&
+ isset( $_FILES['booster_import_settings_file'] ) &&
+ isset(
+ $_FILES['booster_import_settings_file']['error'],
+ $_FILES['booster_import_settings_file']['tmp_name']
+ )
+ ) {
+
+ if ( UPLOAD_ERR_OK !== $_FILES['booster_import_settings_file']['error'] ) {
+ $wcj_notice .= __( 'Upload failed!', 'woocommerce-jetpack' );
+ return $wcj_notice;
+ }
+
+ $tmp_name = sanitize_text_field(
+ wp_unslash( $_FILES['booster_import_settings_file']['tmp_name'] )
+ );
+
+ $import_settings = $wp_filesystem->get_contents( $tmp_name );
+
+ }
+ $bom = pack( 'H*', 'EFBBBF' );
+ $import_settings = preg_replace( "/^$bom/", '', $import_settings );
+ $import_settings = explode( PHP_EOL, preg_replace( '~(*BSR_ANYCRLF)R~', PHP_EOL, $import_settings ) );
+ if ( ! is_array( $import_settings ) || 2 !== count( $import_settings ) ) {
+ $wcj_notice .= __( 'Wrong file format!', 'woocommerce-jetpack' );
+ return $wcj_notice;
+ } else {
+ $import_header = $import_settings[0];
+ $required_header = 'Booster for WooCommerce';
+ if ( substr( $import_header, 0, strlen( $required_header ) ) !== $required_header ) {
+ $wcj_notice .= __( 'Wrong file format!', 'woocommerce-jetpack' );
+ return $wcj_notice;
+ } else {
+ $import_settings = json_decode( $import_settings[1], true );
+ foreach ( $import_settings as $import_key => $import_setting ) {
+ if ( strlen( $import_key ) > 4 && 'wcj_' === substr( $import_key, 0, 4 ) ) {
+ update_option( $import_key, $import_setting );
+ ++$import_counter;
+ }
+ }
+ /* translators: %d: translation added */
+ $wcj_notice .= sprintf( __( '%d options successfully imported.', 'woocommerce-jetpack' ), $import_counter );
+ return $wcj_notice;
+ }
+ }
+ }
+ }
+
+ /**
+ * Manage_options_export.
+ *
+ * @version 7.0.0
+ * @since 2.5.2
+ * @see http://php.net/manual/en/function.header.php
+ */
+ public function manage_options_export() {
+ require_once ABSPATH . '/wp-admin/includes/file.php';
+ global $wp_filesystem;
+ WP_Filesystem();
+ $export_settings = array();
+ $export_counter = array();
+ $wpnonce = isset( $_REQUEST['wcj-verify-manage-settings'] ) ? wp_verify_nonce( sanitize_key( $_REQUEST['wcj-verify-manage-settings'] ), 'wcj-verify-manage-settings' ) : false;
+ foreach ( w_c_j()->modules as $module ) {
+ $values = $module->get_settings();
+ foreach ( $values as $value ) {
+ if ( isset( $value['default'] ) && isset( $value['id'] ) ) {
+ if ( isset( $_POST['booster_export_settings'] ) ) {
+ $export_settings[ $value['id'] ] = wcj_get_option( $value['id'], $value['default'] );
+ if ( ! isset( $export_counter[ $module->short_desc ] ) ) {
+ $export_counter[ $module->short_desc ] = 0;
+ }
+ ++$export_counter[ $module->short_desc ];
+ }
+ }
+ }
+ }
+ $export_settings = wp_json_encode( $export_settings );
+ $export_settings = 'Booster for WooCommerce v' . wcj_get_option( WCJ_VERSION_OPTION, 'NA' ) . PHP_EOL . $export_settings;
+ $file_name = 'booster_settings.txt';
+ $file_path = wcj_get_wcj_uploads_dir() . DIRECTORY_SEPARATOR . $file_name;
+ $wp_filesystem->put_contents( $file_path, $export_settings, FS_CHMOD_FILE );
+ WC_Download_Handler::download_file_force( $file_path, $file_name );
+ die();
+ }
+
+ /**
+ * Manage_options_reset_meta.
+ *
+ * @version 7.0.0
+ * @since 3.4.0
+ * @todo order items meta
+ * @todo `... LIKE 'wcj_%'`
+ */
+ public function manage_options_reset_meta() {
+ global $wpdb, $wcj_notice;
+ $delete_counter_meta = 0;
+ $plugin_meta = $wpdb->get_results( "SELECT * FROM $wpdb->postmeta WHERE meta_key LIKE '_wcj_%'" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
+ foreach ( $plugin_meta as $meta ) {
+ delete_post_meta( $meta->post_id, $meta->meta_key );
+ ++$delete_counter_meta;
+ }
+ /* translators: %d: translation added */
+ $wcj_notice .= sprintf( __( '%d meta successfully deleted.', 'woocommerce-jetpack' ), $delete_counter_meta );
+ return $wcj_notice;
+ }
+
+ /**
+ * Manage_options_reset.
+ *
+ * @version 7.0.0
+ * @since 2.5.2
+ */
+ public function manage_options_reset() {
+ global $wpdb, $wcj_notice;
+ $delete_counter_options = 0;
+ $plugin_options = $wpdb->get_results( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE 'wcj_%'" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
+ foreach ( $plugin_options as $option ) {
+ delete_option( $option->option_name );
+ delete_site_option( $option->option_name );
+ ++$delete_counter_options;
+ }
+ /* translators: %d: translation added */
+ $wcj_notice .= sprintf( __( '%d options successfully deleted.', 'woocommerce-jetpack' ), $delete_counter_options );
+ return $wcj_notice;
+ }
+ }
+
+endif;
+
+return new WCJ_Settings_Manager();
--- a/woocommerce-jetpack/includes/admin/onboarding-map.php
+++ b/woocommerce-jetpack/includes/admin/onboarding-map.php
@@ -205,6 +205,8 @@
),
),
'first_win_check' => 'wcj_cart_abandonment_enabled',
+ 'next_step_text' => __( 'Configure cart recovery emails', 'woocommerce-jetpack' ),
+ 'next_step_link' => 'admin.php?page=wcj-plugins&tab=jetpack&wcj-cat=cart_and_checkout§ion=cart_abandonment&wcj-cat-nonce=',
),
'b2b_store' => array(
'title' => __( 'B2B Store', 'woocommerce-jetpack' ),
--- a/woocommerce-jetpack/includes/admin/views/onboarding-modal.php
+++ b/woocommerce-jetpack/includes/admin/views/onboarding-modal.php
@@ -29,7 +29,7 @@
</button>
</div>
- <div class="booster-progress-indicator" aria-label="<?php esc_attr_e( 'Progress', 'woocommerce-jetpack' ); ?>">
+ <div class="booster-progress-indicator" role="progressbar" aria-label="<?php esc_attr_e( 'Progress', 'woocommerce-jetpack' ); ?>" aria-valuenow="1" aria-valuemin="1" aria-valuemax="3">
<div class="progress-step active" data-step="choose">
<span class="step-number">1</span>
<span class="step-label"><?php esc_html_e( 'Choose', 'woocommerce-jetpack' ); ?></span>
@@ -67,7 +67,7 @@
</div>
<div class="booster-goals-grid">
<?php foreach ( $onboarding_map as $goal_id => $goal ) : ?>
- <div class="booster-goal-tile booster-tile" data-goal="<?php echo esc_attr( $goal_id ); ?>">
+ <div class="booster-goal-tile booster-tile" data-goal="<?php echo esc_attr( $goal_id ); ?>" role="button" tabindex="0" aria-pressed="false" aria-label="<?php echo esc_attr( $goal['title'] ); ?>">
<div class="goal-icon tile-icon">
<?php echo wp_kses_post( $goal['svg_icon'] ); ?>
</div>
@@ -111,7 +111,7 @@
foreach ( $blueprints as $blueprint_id => $blueprint ) :
?>
- <div class="booster-blueprint-tile booster-tile" data-blueprint="<?php echo esc_attr( $blueprint_id ); ?>">
+ <div class="booster-blueprint-tile booster-tile" data-blueprint="<?php echo esc_attr( $blueprint_id ); ?>" role="button" tabindex="0" aria-pressed="false" aria-label="<?php echo esc_attr( $blueprint['title'] ); ?>">
<div class="blueprint-icon tile-icon">
<?php echo wp_kses_post( $blueprint['svg_icon'] ); ?>
</div>
--- a/woocommerce-jetpack/includes/admin/wcj-settings-dashboard.php
+++ b/woocommerce-jetpack/includes/admin/wcj-settings-dashboard.php
@@ -29,10 +29,24 @@
WCJ_Presets::apply_preset( $preset_id );
}
// Redirect to remove query params.
- wp_safe_redirect( remove_query_arg( array( 'apply_preset', '_wpnonce' ) ) );
+ // wp_safe_redirect( remove_query_arg( array( 'apply_preset', '_wpnonce' ) ) );
+ // Redirect to remove query params.
+ wp_safe_redirect( add_query_arg( 'wcj_preset_applied', $preset_id, remove_query_arg( array( 'apply_preset', '_wpnonce' ) ) ) );
exit;
}
+// Display success notice if a preset was applied.
+if ( isset( $_GET['wcj_preset_applied'] ) && ! empty( $_GET['wcj_preset_applied'] ) ) {
+ $preset_id = sanitize_key( $_GET['wcj_preset_applied'] );
+ $preset_title = '';
+ if ( class_exists( 'WCJ_Presets' ) ) {
+ $presets = WCJ_Presets::get_presets();
+ $preset_title = isset( $presets[ $preset_id ] ) ? $presets[ $preset_id ]['title'] : $preset_id;
+ }
+ /* translators: %s: Preset title */
+ echo wp_kses_post( '<div id="message" class="updated notice is-dismissible" style="margin: 20px 0;"><p><strong>' . sprintf( esc_html__( '%s preset applied successfully!', 'woocommerce-jetpack' ), $preset_title ) . '</strong></p></div>' );
+}
+
// Render Getting Started Hub (P6) at top of dashboard.
if ( isset( $GLOBALS['wcj_getting_started_hub'] ) ) {
$GLOBALS['wcj_getting_started_hub']->render();
--- a/woocommerce-jetpack/includes/class-wcj-checkout-files-upload.php
+++ b/woocommerce-jetpack/includes/class-wcj-checkout-files-upload.php
@@ -1,1363 +1,1363 @@
-<?php
-/**
- * Booster for WooCommerce - Module - Checkout Files Upload
- *
- * @version 7.2.5
- * @since 2.4.5
- * @author Pluggabl LLC.
- * @package Booster_For_WooCommerce/includes
- */
-
-if ( ! defined( 'ABSPATH' ) ) {
- exit;
-}
-
-if ( ! class_exists( 'WCJ_Checkout_Files_Upload' ) ) :
- /**
- * WCJ_Checkout_Customization.
- *
- * @version 7.1.6
- */
- class WCJ_Checkout_Files_Upload extends WCJ_Module {
-
-
- /**
- * The module checkout_files_upload_notice_type
- *
- * @var varchar $checkout_files_upload_notice_type Module.
- */
- public $checkout_files_upload_notice_type;
- /**
- * The module additional_admin_emails_settings
- *
- * @var varchar $additional_admin_emails_settings Module.
- */
- public $additional_admin_emails_settings;
- /**
- * The module templates_settings
- *
- * @var varchar $templates_settings Module.
- */
- public $templates_settings;
- /**
- * Constructor.
- *
- * @version 5.6.2
- * @since 2.4.5
- * @todo styling options
- */
- public function __construct() {
-
- $this->id = 'checkout_files_upload';
- $this->short_desc = __( 'Checkout Files Upload', 'woocommerce-jetpack' );
- $this->desc = __( 'Let customers upload files on (or after) the checkout (1 file allowed in free version).', 'woocommerce-jetpack' );
- $this->desc_pro = __( 'Let customers upload files on (or after) the checkout.', 'woocommerce-jetpack' );
- $this->link_slug = 'woocommerce-checkout-files-upload';
- parent::__construct();
-
- if ( $this->is_enabled() ) {
- $this->init_settings();
- add_action( 'add_meta_boxes', array( $this, 'add_file_admin_order_meta_box' ) );
- add_action( 'init', array( $this, 'process_checkout_files_upload' ) );
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_remove_on_empty_cart', 'no' ) ) {
- add_action( 'woocommerce_cart_item_removed', array( $this, 'remove_files_on_empty_cart' ), PHP_INT_MAX, 2 );
- }
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
- for ( $i = 1; $i <= $total_number; $i++ ) {
- $the_hook = wcj_get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' );
- if ( 'disable' !== ( $the_hook ) ) {
- add_action( $the_hook, array( $this, 'add_files_upload_form_to_checkout_frontend' ), wcj_get_option( 'wcj_checkout_files_upload_hook_priority_' . $i, 10 ) );
- }
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_add_to_thankyou_' . $i, 'no' ) ) {
- add_action( 'woocommerce_thankyou', array( $this, 'add_files_upload_form_to_thankyou_and_myaccount_page' ), PHP_INT_MAX, 1 );
- }
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_add_to_myaccount_' . $i, 'no' ) ) {
- add_action( 'woocommerce_view_order', array( $this, 'add_files_upload_form_to_thankyou_and_myaccount_page' ), PHP_INT_MAX, 1 );
- }
- }
- add_action( 'woocommerce_checkout_order_processed', array( $this, 'add_files_to_order' ), PHP_INT_MAX, 2 );
- add_action( 'woocommerce_after_checkout_validation', array( $this, 'validate_on_checkout' ) );
- add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_files_to_order_display' ), PHP_INT_MAX );
- add_action( 'woocommerce_email_after_order_table', array( $this, 'add_files_to_order_display' ), PHP_INT_MAX );
- add_filter( 'woocommerce_email_attachments', array( $this, 'add_files_to_email_attachments' ), PHP_INT_MAX, 3 );
-
- add_filter( 'woocommerce_get_return_url', array( $this, 'wcj_customize_get_return_url' ), PHP_INT_MAX, 2 );
- add_filter( 'woocommerce_get_checkout_order_received_url', array( $this, 'wcj_customize_get_return_url' ), PHP_INT_MAX, 2 );
- }
- }
-
- /**
- * Init_settings.
- *
- * @version 3.9.0
- * @since 3.8.0
- * @todo (dev) (maybe) init settings on demand only
- */
- public function init_settings() {
- $this->templates_settings = wcj_get_option( 'wcj_checkout_files_upload_templates', array() );
- $this->templates_settings = wp_parse_args(
- $this->templates_settings,
- array(
- 'order_before' => '',
- /* translators: %s: search term */
- 'order_item' => sprintf( __( 'File: %s', 'woocommerce-jetpack' ), '%file_name%' ) . '<br>',
- 'order_after' => '',
- 'order_image_style' => 'width:64px;',
- 'email_before' => '',
- /* translators: %s: search term */
- 'email_item' => sprintf( __( 'File: %s', 'woocommerce-jetpack' ), '%file_name%' ) . '<br>',
- 'email_after' => '',
- )
- );
- $this->additional_admin_emails_settings = wcj_get_option( 'wcj_checkout_files_upload_additional_admin_emails', array() );
- $this->additional_admin_emails_settings = wp_parse_args(
- $this->additional_admin_emails_settings,
- array(
- 'actions' => array(),
- 'do_attach' => 'yes',
- )
- );
- $this->checkout_files_upload_notice_type = wcj_get_option( 'wcj_checkout_files_upload_notice_type', 'wc_add_notice' );
- }
-
- /**
- * Verify_checkout_files_upload_form_nonce.
- *
- * @version 7.2.6
- * @since 7.2.6
- * @param int $i Field index.
- * @param int $order_id Order id.
- * @return bool
- */
- private function verify_checkout_files_upload_form_nonce( $i, $order_id = 0 ) {
- $nonce_name = 'wcj_checkout_files_upload_nonce_' . $i;
- if ( ! isset( $_POST[ $nonce_name ] ) ) {
- // Backward compatibility with cached/older forms.
- return true;
- }
- $nonce_value = sanitize_text_field( wp_unslash( $_POST[ $nonce_name ] ) );
- $nonce_action = ( 0 !== (int) $order_id ? 'wcj_checkout_files_upload_order_' . (int) $order_id . '_' . $i : 'wcj_checkout_files_upload_session_' . $i );
- return ( '' !== $nonce_value && false !== wp_verify_nonce( $nonce_value, $nonce_action ) );
- }
-
- /**
- * Can_current_user_manage_order_checkout_file.
- *
- * @version 7.2.6
- * @since 7.2.6
- * @param WC_Order $order Order object.
- * @param string $order_key Order key.
- * @return bool
- */
- private function can_current_user_manage_order_checkout_file( $order, $order_key = '' ) {
- if ( ! $order || false === $order ) {
- return false;
- }
-
- if ( wcj_current_user_can( 'manage_woocommerce' ) || wcj_current_user_can( 'edit_shop_orders' ) || wcj_is_user_role( 'administrator' ) || is_shop_manager() ) {
- return true;
- }
-
- $customer_id = (int) $order->get_customer_id();
- if ( wcj_is_user_logged_in() && 0 !== $customer_id && (int) wcj_get_current_user_id() === $customer_id ) {
- return true;
- }
-
- return ( '' !== $order_key && $order->key_is_valid( $order_key ) );
- }
-
- /**
- * Get_checkout_files_upload_real_path.
- *
- * @version 7.2.6
- * @since 7.2.6
- * @param string $file_name File name.
- * @return string|bool
- */
- private function get_checkout_files_upload_real_path( $file_name ) {
- if ( ! is_string( $file_name ) || '' === $file_name ) {
- return false;
- }
-
- $base_path = wcj_get_wcj_uploads_dir( 'checkout_files_upload' );
- $tmp_file_name = $base_path . '/' . sanitize_file_name( wp_unslash( $file_name ) );
- $real_file_path = realpath( $tmp_file_name );
- $real_base_path = realpath( $base_path );
-
- if ( false === $real_file_path || false === $real_base_path ) {
- return false;
- }
-
- $real_base_path = trailingslashit( wp_normalize_path( $real_base_path ) );
- $real_file_path = wp_normalize_path( $real_file_path );
- return ( 0 === strpos( $real_file_path, $real_base_path ) ? $real_file_path : false );
- }
-
- /**
- * Add_files_to_email_attachments.
- *
- * @version 7.1.4
- * @since 2.5.5
- * @param array $attachments defines the attachments.
- * @param bool | string $status defines the status.
- * @param string | int $order defines the order.
- */
- public function add_files_to_email_attachments( $attachments, $status, $order ) {
- if (
- ( 'new_order' === $status && 'yes' === wcj_get_option( 'wcj_checkout_files_upload_attach_to_admin_new_order', 'yes' ) ) ||
- ( 'customer_processing_order' === $status && 'yes' === wcj_get_option( 'wcj_checkout_files_upload_attach_to_customer_processing_order', 'yes' ) )
- ) {
- if ( true === wcj_is_hpos_enabled() ) {
- $total_files = $order->get_meta( '_wcj_checkout_files_total_files' );
- for ( $i = 1; $i <= $total_files; $i++ ) {
- $attachments[] = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order->get_meta( '_wcj_checkout_files_upload_' . $i );
- }
- } else {
- $total_files = get_post_meta( wcj_get_order_id( $order ), '_wcj_checkout_files_total_files', true );
- for ( $i = 1; $i <= $total_files; $i++ ) {
- $attachments[] = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( wcj_get_order_id( $order ), '_wcj_checkout_files_upload_' . $i, true );
- }
- }
- }
- return $attachments;
- }
-
- /**
- * Add_files_to_order_display.
- *
- * @version 7.1.4
- * @since 2.4.7
- * @todo (maybe) somehow add `%image%` to emails also
- * @param string | int $order defines the order.
- */
- public function add_files_to_order_display( $order ) {
- $order_id = wcj_get_order_id( $order );
- $html = '';
- if ( true === wcj_is_hpos_enabled() ) {
- $total_files = $order->get_meta( '_wcj_checkout_files_total_files' );
- } else {
- $total_files = get_post_meta( $order_id, '_wcj_checkout_files_total_files', true );
- }
- $do_add_img = false;
- if ( 'woocommerce_email_after_order_table' === current_filter() ) {
- $template_before = $this->templates_settings['email_before'];
- $template_after = $this->templates_settings['email_after'];
- $template = $this->templates_settings['email_item'];
- } else {
- $template_before = $this->templates_settings['order_before'];
- $template_after = $this->templates_settings['order_after'];
- $template = $this->templates_settings['order_item'];
- $do_add_img = ( false !== strpos( $template, '%image%' ) );
- if ( $do_add_img ) {
- $img_style = $this->templates_settings['order_image_style'];
- }
- }
- for ( $i = 1; $i <= $total_files; $i++ ) {
- if ( true === wcj_is_hpos_enabled() ) {
- $real_file_name = $order->get_meta( '_wcj_checkout_files_upload_real_name_' . $i );
- } else {
- $real_file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i, true );
- }
- if ( '' !== $real_file_name ) {
- $img = '';
- if ( $do_add_img ) {
- if ( true === wcj_is_hpos_enabled() ) {
- $order_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order->get_meta( '_wcj_checkout_files_upload_' . $i );
- } else {
- $order_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i, true );
- }
- if ( is_array( getimagesize( $order_file_name ) ) ) {
- $link = esc_url(
- add_query_arg(
- array(
- 'wcj_download_checkout_file' => $i,
- '_wpnonce' => wp_create_nonce( 'wcj_download_checkout_file' ),
- 'wcj_download_checkout_file_order_id' => $order_id,
- )
- )
- );
- $img = '<img style="' . $img_style . '" src="' . $link . '"> ';
- }
- }
- $html .= wcj_handle_replacements(
- array(
- '%file_name%' => $real_file_name,
- '%image%' => $img,
- ),
- $template
- );
- }
- }
- if ( '' !== $html ) {
- echo wp_kses_post( $template_before . $html . $template_after );
- }
- }
-
- /**
- * Add_notice.
- *
- * @version 3.9.0
- * @since 3.9.0
- * @param string $message defines the message.
- * @param string $notice_type defines the notice_type.
- */
- public function add_notice( $message, $notice_type = 'success' ) {
- if ( 'wc_add_notice' === $this->checkout_files_upload_notice_type ) {
- wc_add_notice( $message, $notice_type );
- } elseif ( 'wc_print_notice' === $this->checkout_files_upload_notice_type ) {
- wc_print_notice( $message, $notice_type );
- }
- }
-
- /**
- * Validate_on_checkout.
- *
- * @version 7.2.5
- * @since 2.4.5
- * @param string $posted defines the posted.
- */
- public function validate_on_checkout( $posted ) {
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
- for ( $i = 1; $i <= $total_number; $i++ ) {
- if (
- 'yes' === wcj_get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) &&
- $this->is_visible( $i ) &&
- 'disable' !== wcj_get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' )
- ) {
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_required_' . $i, 'no' ) && null === wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
- // Is required.
- $this->add_notice( wcj_get_option( 'wcj_checkout_files_upload_notice_required_' . $i, __( 'File is required!', 'woocommerce-jetpack' ) ), 'error' );
- }
- if ( null === wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
- continue;
- }
- $file_name = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
- $file_name = $file_name['name'];
- $file_type = '.' . pathinfo( $file_name, PATHINFO_EXTENSION );
- $file_accept = wcj_get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' );
- if ( '' !== $file_accept && null !== $file_accept ) {
- // Validate file type.
- $file_accept = explode( ',', $file_accept );
- if ( is_array( $file_accept ) && ! empty( $file_accept ) ) {
- if ( ! in_array( $file_type, $file_accept, true ) ) {
- $this->add_notice(
- sprintf(
- wcj_get_option(
- 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
- /* translators: %s: search term */
- __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' )
- ),
- $file_name
- ),
- 'error'
- );
- }
- }
- }
- if ( $this->is_extension_blocked( $file_type, $file_name ) ) {
- $this->add_notice(
- sprintf(
- wcj_get_option(
- 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
- /* translators: %s: search term */
- __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' )
- ),
- $file_name
- ),
- 'error'
- );
- }
- }
- }
- }
-
- /**
- * Add_file_admin_order_meta_box.
- *
- * @version 7.1.4
- * @since 2.4.5
- */
- public function add_file_admin_order_meta_box() {
- if ( true === wcj_is_hpos_enabled() ) {
- $screen = 'woocommerce_page_wc-orders';
- $context = 'side';
- $priority = 'high';
- add_meta_box(
- 'wc-jetpack-' . $this->id,
- __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Uploaded Files', 'woocommerce-jetpack' ),
- array( $this, 'create_file_admin_order_meta_box_hpos' ),
- $screen,
- $context,
- $priority
- );
- } else {
- $screen = 'shop_order';
- $context = 'side';
- $priority = 'high';
- add_meta_box(
- 'wc-jetpack-' . $this->id,
- __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Uploaded Files', 'woocommerce-jetpack' ),
- array( $this, 'create_file_admin_order_meta_box' ),
- $screen,
- $context,
- $priority
- );
-
- }
- }
-
- /**
- * Create_file_admin_order_meta_box.
- *
- * @version 7.2.5
- * @since 2.4.5
- */
- public function create_file_admin_order_meta_box() {
- $order_id = get_the_ID();
- $html = '';
- $total_files = get_post_meta( $order_id, '_wcj_checkout_files_total_files', true );
- $files_exists = false;
- for ( $i = 1; $i <= $total_files; $i++ ) {
- $order_file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i, true );
- $real_file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i, true );
- if ( '' !== $order_file_name && null !== $order_file_name ) {
- $files_exists = true;
- $html .= '<p><a href="' . add_query_arg(
- array(
- 'wcj_download_checkout_file_admin' => $order_file_name,
- 'wcj_checkout_file_number' => $i,
- 'wcj_download_checkout_file_admin_nonce' => wp_create_nonce( 'wcj_download_checkout_file_admin_nonce' ),
- )
- ) . '">' . $real_file_name . '</a></p>';
- }
- }
- if ( ! $files_exists ) {
- $html .= '<p><em>' . __( 'No files uploaded.', 'woocommerce-jetpack' ) . '</em></p>';
- } else {
- $html .= '<p><a style="color:#a00;" href="' . add_query_arg(
- array(
- 'wcj_download_checkout_file_admin_delete_all' => $order_id,
- 'wcj_download_checkout_file_admin_delete_all_nonce' => wp_create_nonce( 'wcj_download_checkout_file_admin_delete_all_nonce' ),
- )
- ) . '"' . wcj_get_js_confirmation() . '>' .
- __( 'Delete all files', 'woocommerce-jetpack' ) . '</a></p>';
- }
- $allowed_tags = wp_kses_allowed_html( 'post' );
- $allowed_tags['a']['onclick'] = true;
- echo wp_kses( $html, $allowed_tags );
- }
-
-
- /**
- * Create_file_admin_order_meta_box_hpos.
- *
- * @version 7.2.5
- * @since 1.0.0
- */
- public function create_file_admin_order_meta_box_hpos() {
- $order_id = isset( $_REQUEST['id'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['id'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification
- $order = wcj_get_order( $order_id );
- if ( $order && false !== $order ) {
- $html = '';
- $total_files = $order->get_meta( '_wcj_checkout_files_total_files' );
- $files_exists = false;
- for ( $i = 1; $i <= $total_files; $i++ ) {
- $order_file_name = $order->get_meta( '_wcj_checkout_files_upload_' . $i );
- $real_file_name = $order->get_meta( '_wcj_checkout_files_upload_real_name_' . $i );
- if ( '' !== $order_file_name && null !== $order_file_name ) {
- $files_exists = true;
- $html .= '<p><a href="' . esc_url(
- add_query_arg(
- array(
- 'wcj_download_checkout_file_admin' => $order_file_name,
- 'wcj_checkout_file_number' => $i,
- 'wcj_download_checkout_file_admin_nonce' => wp_create_nonce( 'wcj_download_checkout_file_admin_nonce' ),
- )
- )
- ) . '">' . $real_file_name . '</a></p>';
- }
- }
- if ( ! $files_exists ) {
- $html .= '<p><em>' . __( 'No files uploaded.', 'woocommerce-jetpack' ) . '</em></p>';
- } else {
- $html .= '<p><a style="color:#a00;" href="' . esc_url(
- add_query_arg(
- array(
- 'wcj_download_checkout_file_admin_delete_all' => $order_id,
- 'wcj_download_checkout_file_admin_delete_all_nonce' => wp_create_nonce( 'wcj_download_checkout_file_admin_delete_all_nonce' ),
- )
- )
- ) . '"' . wcj_get_js_confirmation() . '>' .
- __( 'Delete all files', 'woocommerce-jetpack' ) . '</a></p>';
- }
- $allowed_tags = wp_kses_allowed_html( 'post' );
- $allowed_tags['a']['onclick'] = true;
- echo wp_kses( $html, $allowed_tags );
- }
- }
-
- /**
- * Is_extension_blocked.
- *
- * @version 7.2.5
- * @since 3.2.3
- * @param string $ext defines the ext.
- * @param string $file_name defines the file name.
- */
- public function is_extension_blocked( $ext, $file_name ) {
- $is_extension_blocked = false;
- if ( 'no' === wcj_get_option( 'wcj_checkout_files_upload_block_files_enabled', 'yes' ) ) {
- return false;
- }
- $ext = strtolower( $ext );
- if ( strlen( $ext ) > 0 && '.' === $ext[0] ) {
- $ext = substr( $ext, 1 );
- }
- $blocked_file_exts = wcj_get_option(
- 'wcj_checkout_files_upload_block_files_exts',
- 'bat|exe|cmd|sh|php|php0|php1|php2|php3|php4|php5|php6|php7|php8|php9|ph|ph0|ph1|ph2|ph3|ph4|ph5|ph6|ph7|ph8|ph9|pl|cgi|386|dll|com|torrent|js|app|jar|pif|vb|vbscript|wsf|asp|cer|csr|jsp|drv|sys|ade|adp|bas|chm|cpl|crt|csh|fxp|hlp|hta|inf|ins|isp|jse|htaccess|htpasswd|ksh|lnk|mdb|mde|mdt|mdw|msc|msi|msp|mst|ops|pcd|prg|reg|scr|sct|shb|shs|url|vbe|vbs|wsc|wsf|wsh|html|htm'
- );
- $blocked_file_exts = explode( '|', $blocked_file_exts );
- if ( in_array( $ext, $blocked_file_exts, true ) ) {
- return true;
- }
-
- $validate = wp_check_filetype( $file_name );
- if ( false === $validate['type'] ) {
- return true;
- }
- }
-
- /**
- * Add_files_to_order.
- *
- * @version 7.2.5
- * @since 2.4.5
- * @param int $order_id defines the order_id.
- * @param string $posted defines the posted.
- */
- public function add_files_to_order( $order_id, $posted ) {
- $order = wcj_get_order( $order_id );
- require_once ABSPATH . '/wp-admin/includes/file.php';
- global $wp_filesystem;
- WP_Filesystem();
-
- $upload_dir = wcj_get_wcj_uploads_dir( 'checkout_files_upload' );
- if ( ! file_exists( $upload_dir ) ) {
- wp_mkdir_p( $upload_dir, 0755, true );
- }
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
- for ( $i = 1; $i <= $total_number; $i++ ) {
- if ( null !== wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
- $file_name = $session_data['name'];
- $ext = pathinfo( $file_name, PATHINFO_EXTENSION );
- $download_file_name = $order_id . '_' . $i . '.' . $ext;
- $file_path = $upload_dir . '/' . $download_file_name;
- $tmp_file_name = $session_data['tmp_name'];
- $file_data = $wp_filesystem->get_contents( $tmp_file_name );
- if ( ! $this->is_extension_blocked( $ext, $file_path ) ) { // should already be validated earlier, but just in case...
- $wp_filesystem->put_contents( $file_path, $file_data, FS_CHMOD_FILE );
- }
- wp_delete_file( $tmp_file_name );
- wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
- if ( true === wcj_is_hpos_enabled() && $order && false !== $order ) {
- $order->update_meta_data( '_wcj_checkout_files_upload_' . $i, $download_file_name );
- $order->update_meta_data( '_wcj_checkout_files_upload_real_name_' . $i, $file_name );
- } else {
- update_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i, $download_file_name );
- update_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i, $file_name );
- }
- }
- }
- if ( true === wcj_is_hpos_enabled() && $order && false !== $order ) {
- $order->update_meta_data( '_wcj_checkout_files_total_files', $total_number );
- $order->save();
- } else {
- update_post_meta( $order_id, '_wcj_checkout_files_total_files', $total_number );
- }
- }
-
- /**
- * Remove_files_on_empty_cart.
- *
- * @version 5.6.2
- * @since 3.6.0
- * @param string $cart_item_key defines the cart_item_key.
- * @param string | array $cart defines the cart.
- */
- public function remove_files_on_empty_cart( $cart_item_key, $cart ) {
- if ( $cart->is_empty() ) {
- wcj_session_maybe_start();
- $any_files_removed = false;
- $wcj_checkout_files_upload_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
- for ( $i = 1; $i <= $wcj_checkout_files_upload_total_number; $i++ ) {
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
- if ( null !== $session_data && '' !== $session_data ) {
- $any_files_removed = true;
- if ( isset( $session_data['tmp_name'] ) ) {
- wp_delete_file( $session_data['tmp_name'] );
- }
- wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
- }
- }
- if ( $any_files_removed && 'yes' === wcj_get_option( 'wcj_checkout_files_upload_remove_on_empty_cart_add_notice', 'no' ) ) {
- $this->add_notice( wcj_get_option( 'wcj_checkout_files_upload_notice_remove_on_empty_cart', __( 'Files were successfully removed.', 'woocommerce-jetpack' ) ) );
- }
- }
- }
-
- /**
- * Get_order_full_file_name.
- *
- * @version 7.1.4
- * @since 3.8.0
- * @todo use where needed
- * @param int $order_id defines the order_id.
- * @param string | int $file_num defines the file_num.
- */
- public function get_order_full_file_name( $order_id, $file_num ) {
- $order = wcj_get_order( $order_id );
- if ( true === wcj_is_hpos_enabled() && $order && false !== $order ) {
- return wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order->get_meta( '_wcj_checkout_files_upload_' . $file_num );
- } else {
- return wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( $order_id, '_wcj_checkout_files_upload_' . $file_num, true );
- }
- }
-
- /**
- * Process_checkout_files_upload.
- *
- * @version 7.2.5
- * @since 2.4.5
- * @todo add option for admin to delete files one by one (i.e. not all at once)
- * @todo `$this->additional_admin_emails_settings` - more customization options, e.g.: admin email, subject, content, from
- */
- public function process_checkout_files_upload() {
- wcj_session_maybe_start();
- $admin_email = wcj_ge