芝麻web文件管理V1.00
编辑当前文件:/home/felaukpo/public_html/wp-content/plugins/cartflows-pro/classes/class-cartflows-pro-admin.php
include_refund_order_section(); } add_filter( 'get_user_option_meta-box-order_' . CARTFLOWS_STEP_POST_TYPE, array( $this, 'metabox_order' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'load_notice_script' ) ); add_action( 'wp_ajax_cartflows_migrate_order_bump', array( $this, 'migrate_order_bump' ) ); add_action( 'wp_ajax_cartflows_migrate_pre_checkout_offer_styles', array( $this, 'migrate_pre_checkout_styles' ) ); add_action( 'admin_notices', array( $this, 'migration_conditional_notices' ) ); add_filter( 'install_plugin_overwrite_comparison', array( $this, 'update_override_comparison_html' ), 10, 3 ); add_filter( 'cartflows_admin_exclude_import_meta_keys', array( $this, 'add_meta_keys_to_exclude_from_import' ) ); // Let WooCommerce know, CartFlows Pro is compatible with HPOS. add_action( 'before_woocommerce_init', array( $this, 'declare_woo_hpos_compatibility' ) ); add_action( 'wp_ajax_cartflows_dismiss_flow_analytics_notice', array( $this, 'dismiss_flow_analytics_notice' ) ); add_filter( 'cartflows_step_importer_args', array( $this, 'update_meta_before_import_json' ), 10, 1 ); add_filter( 'cartflows_template_import_meta_data', array( $this, 'update_meta_before_import_template' ), 10, 1 ); add_filter( 'cartflows_get_specific_stats', array( $this, 'get_cartflows_pro_stats' ), 10, 1 ); } /** * Remove ob product id from meta data. * * @param array $pre_post_data step data. * * @return array */ public function update_meta_before_import_json( $pre_post_data ) { if ( isset( $pre_post_data['meta_input'] ) ) { $step_meta_data = $pre_post_data['meta_input']; if ( isset( $step_meta_data['wcf-order-bumps'] ) && is_array( $step_meta_data['wcf-order-bumps'] ) ) { $order_bumps = $step_meta_data['wcf-order-bumps']; foreach ( $order_bumps as $key => $ob_data ) { if ( isset( $ob_data['product'] ) ) { unset( $order_bumps[ $key ]['product'] ); } } $pre_post_data['meta_input']['wcf-order-bumps'] = $order_bumps; } } return $pre_post_data; } /** * Remove ob product id from meta data. * * @param array $step_meta_data step meta data. * * @return array. */ public function update_meta_before_import_template( $step_meta_data ) { if ( ! empty( $step_meta_data ) && isset( $step_meta_data['wcf-order-bumps'] ) ) { $order_bumps = $step_meta_data['wcf-order-bumps'][0]; $is_serialize = is_serialized( $order_bumps, true ); if ( ! empty( $order_bumps ) ) { if ( $is_serialize ) { $order_bumps = maybe_unserialize( stripslashes( $order_bumps ) ); } elseif ( ! is_array( $order_bumps ) ) { $order_bumps = json_decode( stripslashes( $order_bumps ), true ); } if ( is_array( $order_bumps ) ) { foreach ( $order_bumps as $key => $ob_data ) { if ( isset( $ob_data['product'] ) ) { unset( $order_bumps[ $key ]['product'] ); } } } $step_meta_data['wcf-order-bumps'][0] = $is_serialize && is_array( $order_bumps ) ? maybe_serialize( $order_bumps ) : $order_bumps; } } return $step_meta_data; } /** * Declare the woo HPOS compatibility. */ public function declare_woo_hpos_compatibility() { if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) { \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', CARTFLOWS_PRO_FILE, true ); } } /** * Exclude meta keys for pro. * * @param array $meta_keys meta keys. */ public function add_meta_keys_to_exclude_from_import( $meta_keys ) { $pro_meta_keys = array( 'wcf-ab-test', 'wcf-yes-next-step', 'wcf-no-next-step', 'wcf-offer-product', 'wcf-order-bump-product', 'wcf-pre-checkout-offer-product', 'wcf-product-options-data', 'wcf-yes-next-step', 'wcf-no-next-step', 'wcf-checkout-rules', ); $meta_keys = array_merge( $meta_keys, $pro_meta_keys ); return $meta_keys; } /** * Show notice before downgrading to lower plan. * * @param string $table_html table html. * @param array $current_plugin current plugin data. * @param array $new_plugin new plugin data. * * @since x.x.x */ public function update_override_comparison_html( $table_html, $current_plugin, $new_plugin ) { if ( isset( $current_plugin['Name'] ) ) { if ( $current_plugin['Name'] === $new_plugin['Name'] ) { return $table_html; } if ( 'CartFlows Pro' === $current_plugin['Name'] ) { $table_html .= sprintf( /* translators: %1$s: HTML, %2$s: HTML */ __( '%1$sYou are installing the lower plan of the CartFlows compared to what currently you have, it will disable some pro features that you might be using. %2$s', 'cartflows-pro' ), '
', '
' ); } elseif ( 'CartFlows Plus' === $current_plugin['Name'] && 'CartFlows Starter' === $new_plugin['Name'] ) { $table_html .= sprintf( /* translators: %1$s: HTML, %2$s: HTML */ __( '%1$sYou are installing the lower plan of the CartFlows compared to what currently you have, it will disable some plus features that you might be using. %2$s', 'cartflows-pro' ), '
', '
' ); } } return $table_html; } /** * Show migration in process notice. * * @since 1.7.0 */ public function order_bump_migration_processing_notice() { $action_schedular_page_url = admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=cartflows' ); ?>
>', 'cartflows-pro' ); ?>
is_woo_active ) { return; } if ( ! $this->allowed_screen_for_notices() ) { return; } if ( ! current_user_can( 'cartflows_manage_flows_steps' ) ) { return; } if ( 'no' === get_option( 'wcf_order_bump_migrated', false ) ) { $this->migrate_order_bump_notice(); } elseif ( 'processing' === get_option( 'wcf_order_bump_migrated', false ) ) { $this->order_bump_migration_processing_notice(); } elseif ( 'done' === get_option( 'wcf_migration_complete_status', false ) ) { $this->migration_complete_notice(); } if ( 'no' === get_option( 'wcf_pre_checkout_offer_styles_migrated', false ) ) { $this->migrate_pre_checkout_styles_notice(); } elseif ( 'processing' === get_option( 'wcf_pre_checkout_offer_styles_migrated', false ) ) { $this->pre_checkout_offer_style_migration_processing_notice(); } elseif ( 'done' === get_option( 'wcf_pre_checkout_offer_styles_migration_complete_status', false ) ) { $this->pre_checkout_offer_migration_complete_notice(); } } /** * Show migration complete notice. * * @since 1.7.0 */ public function migration_complete_notice() { ?>
logger->migration_log( 'Initiating Order Bump migration process.' ); $response_data = array( 'success' => false, 'messsage' => __( 'Cannot schedule a migration. Action scheduler function not found.', 'cartflows-pro' ), ); if ( function_exists( 'as_enqueue_async_action' ) ) { as_enqueue_async_action( 'cartflows_migrate_order_bumps' ); update_option( 'wcf_order_bump_migrated', 'processing' ); $response_data = array( 'success' => true, 'messsage' => __( 'Order Bump 1st migration action scheduled successfully.', 'cartflows-pro' ), ); } wcf()->logger->migration_log( $response_data['messsage'] ); wp_send_json_success( $response_data ); } /** * New UI notice. * * @since 1.7.0 */ public function load_notice_script() { if ( ! $this->allowed_screen_for_notices() || ! current_user_can( 'cartflows_manage_flows_steps' ) ) { return; } // Loading Script file. wp_enqueue_script( 'cartflows-pro-notice', CARTFLOWS_PRO_URL . 'admin/assets/js/notices.js', array( 'jquery' ), CARTFLOWS_PRO_VER, false ); $action_schedular_page_url = admin_url( 'admin.php?page=wc-status&tab=action-scheduler&s=cartflows' ); $vars = array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'ob_migration_nonce' => wp_create_nonce( 'cartflows-migrate-order-bump' ), 'pre_checkout_offer_migration_nonce' => wp_create_nonce( 'cartflows-migrate-pre-checkout-offer-styles' ), /* translators: %1$1s: link html start, %2$12: link html end*/ 'ob_notice_text' => sprintf( __( 'CartFlows is migrating the old order bump to the new one in the background. The migration process may take a little while, so please be patient. %1$1s View Progress >> %2$2s', 'cartflows-pro' ), '
', '
' ), /* translators: %1$1s: link html start, %2$12: link html end*/ 'pre_checkout_offer_migration_notice' => sprintf( __( 'CartFlows is migrating the pre checkout offer styles in the background. The migration process may take a little while, so please be patient. %1$1s View Progress >> %2$2s', 'cartflows-pro' ), '
', '
' ), 'flow_analytics_dismiss_notice_nonce' => wp_create_nonce( 'cartflows-dismiss-flow-analytics-notice' ), ); wp_localize_script( 'cartflows-pro-notice', 'CartFlows_Pro_Common_Vars', $vars ); } /** * Migrate Order Bump notice. * * @since 1.7.0 */ public function migrate_order_bump_notice() { ?>
>', 'cartflows-pro' ); ?>
logger->migration_log( 'Initiating pre checkout offer migration process.' ); $response_data = array( 'success' => false, 'messsage' => __( 'Cannot schedule a migration. Action scheduler function not found.', 'cartflows-pro' ), ); if ( function_exists( 'as_enqueue_async_action' ) ) { as_enqueue_async_action( 'cartflows_migrate_pre_checkout_offer_styles' ); update_option( 'wcf_pre_checkout_offer_styles_migrated', 'processing' ); $response_data = array( 'success' => true, 'messsage' => __( '1st migration action scheduled successfully.', 'cartflows-pro' ), ); } wcf()->logger->migration_log( $response_data['messsage'] ); wp_send_json_success( $response_data ); } /** * Check allowed screen for notices. * * @since 1.7.0 * @return bool */ public function allowed_screen_for_notices() { $screen = get_current_screen(); $screen_id = $screen ? $screen->id : ''; $allowed_screens = array( 'toplevel_page_cartflows', 'dashboard', 'plugins', ); if ( in_array( $screen_id, $allowed_screens, true ) ) { return true; } return false; } /** * Metabox fixed orders. * * @param array $pro_metabox_order Metabox orders. * @return array */ public function metabox_order( $pro_metabox_order ) { if ( isset( $pro_metabox_order['side'] ) ) { $pro_metabox_order['side'] = str_replace( array( 'wcf-offer-settings', ), '', $pro_metabox_order['side'] ); } return $pro_metabox_order; } /** * License arguments for Rest API Request. * * @param array $defaults License arguments. * @return array License arguments. */ public function licence_args( $defaults ) { if ( ! class_exists( 'CartFlows_Pro_Licence' ) ) { return $defaults; } // Get license class instance. $cartflows_license_instance = cartflows_pro_license_instance(); $data = get_option( 'wc_am_client_' . $cartflows_license_instance->product_id . '_api_key', array() ); $licence_key = isset( $data['api_key'] ) ? esc_attr( $data['api_key'] ) : ''; $args = array( 'request' => 'status', 'product_id' => CARTFLOWS_PRO_PRODUCT_ID, 'instance' => $cartflows_license_instance->wc_am_instance_id, 'object' => $cartflows_license_instance->wc_am_domain, 'licence_key' => $licence_key, ); return apply_filters( 'cartflows_pro_licence_args', wp_parse_args( $args, $defaults ) ); } /** * Set default options for settings. * * @param array $settings settings data. * @since 1.0.0 */ public function set_default_settings( $settings ) { $settings['paypal_reference_transactions'] = 'disable'; $settings['pre_checkout_offer'] = 'disable'; return $settings; } /** * Hide order meta-data from order list backend. * * @param array $arr order meta data. * @return array * @since 1.0.0 */ public function custom_woocommerce_hidden_order_itemmeta( $arr ) { $arr[] = '_cartflows_step_id'; return $arr; } /** * Changing a meta title * * @param string $key The meta key. * @param WC_Meta_Data $meta The meta object. * @param WC_Order_Item $item The order item object. * @return string The title. */ public function change_order_item_meta_title( $key, $meta, $item ) { if ( '_cartflows_upsell' === $meta->key ) { $key = __( 'Upsell Offer', 'cartflows-pro' ); } elseif ( '_cartflows_downsell' === $meta->key ) { $key = __( 'Downsell Offer', 'cartflows-pro' ); } return $key; } /** * Admin body classes. * * Body classes to be added to tag in admin page * * @param String $classes body classes returned from the filter. * @return String body classes to be added to tag in admin page */ public static function add_admin_pro_body_class( $classes ) { $classes .= ' cartflows-pro-' . CARTFLOWS_PRO_VER; return $classes; } /** * Google analytics settings. * * @param array $google_analytics_settings_data settings. * * @return array $google_analytics_settings_data Modified settings. */ public function add_google_analytics_pro_events( $google_analytics_settings_data ) { $google_analytics_settings_data['enable_bump_order_add_to_cart'] = 'disable'; return $google_analytics_settings_data; } /** * Offer refund. */ public function include_refund_order_section() { /* Refund */ include_once CARTFLOWS_PRO_DIR . 'classes/class-cartflows-pro-refund.php'; } /** * Retrieves the statistics for dynamic offers. * * This function fetches the count of checkout steps where dynamic offers are enabled. * It queries the database to get the number of distinct checkout steps that have dynamic offers enabled. * The result is merged with default data to ensure all expected keys are present. * * @since x.x.x * @return array $all_step_count An array containing the count of checkout steps with dynamic offers enabled. */ public function get_dynamic_offers_stats() { // Default data. $default_data = array( 'checkout_steps_with_dynamic_offers' => 0, ); global $wpdb; // Prepare the database query to make get the order bump count and step cound having the order bumps. //phpcs:disable WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching // Reason: This is a direct database query which fetch only the number of steps where the order bump is enabled. $step_counts = $wpdb->get_results( $wpdb->prepare( "SELECT COUNT(DISTINCT p.ID) AS checkout_steps_with_dynamic_offers FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm1 ON p.ID = pm1.post_id JOIN {$wpdb->postmeta} pm2 ON p.ID = pm2.post_id WHERE p.post_type = %s AND p.post_status = %s AND pm1.meta_key = %s AND pm1.meta_value = %s AND pm2.meta_key = %s AND pm2.meta_value = %s", CARTFLOWS_STEP_POST_TYPE, 'publish', 'wcf-step-type', 'checkout', 'wcf-checkout-rules-option', 'yes' ), ARRAY_A ); //phpcs:enable WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching // Merge the updated counts with the defaults. $all_step_count = wp_parse_args( $step_counts[0], $default_data ); return $all_step_count; } /** * Retrieves the count of A/B tests enabled per step. * * This function queries the database to count the number of steps of each type (optin, landing, checkout, upsell, downsell, thankyou). * It returns an array with the count of A/B test enable counts. * * @return array $all_ab_step_count An array containing the count steps where the A/B test is enabled. */ public function get_ab_test_stats() { // Default data. $default_ab_step_data = array( 'optin' => 0, 'landing' => 0, 'checkout' => 0, 'upsell' => 0, 'downsell' => 0, 'thankyou' => 0, ); global $wpdb; // Prepare the database query to make get the step counts. //phpcs:disable WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching // Reason: This is a direct database query which fetch only the number of steps. $ab_step_counts = $wpdb->get_results( $wpdb->prepare( "SELECT JSON_OBJECTAGG(step_type, count) AS counts FROM ( SELECT step.meta_value AS step_type, COUNT(*) AS count FROM {$wpdb->posts} p INNER JOIN {$wpdb->postmeta} step ON p.ID = step.post_id AND step.meta_key = %s INNER JOIN {$wpdb->postmeta} ab_test ON p.ID = ab_test.post_id AND ab_test.meta_key = %s WHERE p.post_type = %s AND p.post_status = %s AND step.meta_value IN ('optin', 'landing', 'checkout', 'upsell', 'downsell', 'thankyou') AND ab_test.meta_value = %s GROUP BY step.meta_value ) AS subquery", 'wcf-step-type', 'wcf-ab-test', CARTFLOWS_STEP_POST_TYPE, 'publish', 'true' ), ARRAY_A ); //phpcs:enable WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching // Merge the updated counts with the defaults. $all_ab_step_count = wp_parse_args( (array) json_decode( $ab_step_counts[0]['counts'], true ), $default_ab_step_data ); return $all_ab_step_count; } /** * Retrieve the count of order bumps per checkout step and total order bumps created on the site. * * This function queries the database to count the number of steps of each type (optin, landing, checkout, upsell, downsell, thankyou). * It returns an array with the count of order bumps. * * @since x.x.x * @return array $all_step_count An array containing the count of order bumps per checkout step and total order bumps. */ public function get_order_bump_stats() { // Default data. $default_step_data = array( 'checkout_steps_with_order_bumps' => 0, 'total_order_bumps' => 0, ); global $wpdb; $meta_value_to_compaire = 's:2:"id";'; // Prepare the database query to make get the order bump count and step cound having the order bumps. //phpcs:disable WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching // Reason: This is a direct database query which fetch only the number of steps where the order bump is enabled. $step_counts = $wpdb->get_results( $wpdb->prepare( "SELECT COUNT(DISTINCT p.ID) AS checkout_steps_with_order_bumps, SUM( CAST( (CHAR_LENGTH(pm_bumps.meta_value) - CHAR_LENGTH(REPLACE(pm_bumps.meta_value, %s, ''))) / 9 AS UNSIGNED) ) AS total_order_bumps FROM {$wpdb->posts} p JOIN {$wpdb->postmeta} pm_step_type ON p.ID = pm_step_type.post_id JOIN {$wpdb->postmeta} pm_bumps ON p.ID = pm_bumps.post_id WHERE p.post_type = %s AND pm_step_type.meta_key = %s AND pm_step_type.meta_value = %s AND pm_bumps.meta_key = %s", $meta_value_to_compaire, CARTFLOWS_STEP_POST_TYPE, 'wcf-step-type', 'checkout', 'wcf-order-bumps' ), ARRAY_A ); //phpcs:enable WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.NoCaching // Merge the updated counts with the defaults. $all_step_count = wp_parse_args( $step_counts[0], $default_step_data ); return $all_step_count; } /** * Prepare the PRO features stats. * * @return array $pro_features The list of PRO features. */ public function get_the_pro_features_stats() { // Get the Order Bump Stats. $ob_data_stats = $this->get_order_bump_stats(); // Get A/B test step counts. $ab_test_stats = $this->get_ab_test_stats(); // Get the dynamic conditions step count. $dy_offers_stats = $this->get_dynamic_offers_stats(); // Default data. $pro_features = array( 'checkout_steps_with_order_bumps' => strval( $ob_data_stats['checkout_steps_with_order_bumps'] ), 'checkout_steps_with_dynamic_offers' => strval( $dy_offers_stats['checkout_steps_with_dynamic_offers'] ), 'total_order_bumps' => strval( $ob_data_stats['total_order_bumps'] ), 'ab_optin_step_count' => strval( $ab_test_stats['optin'] ), // Total count of 'optin' steps created. 'ab_landing_step_count' => strval( $ab_test_stats['landing'] ), // Total count of 'landing' steps created. 'ab_checkout_step_count' => strval( $ab_test_stats['checkout'] ), // Total count of 'checkout' steps created. 'ab_upsell_step_count' => strval( $ab_test_stats['upsell'] ), // Total count of 'upsell' steps created. 'ab_downsell_step_count' => strval( $ab_test_stats['downsell'] ), // Total count of 'downsell' steps created. 'ab_thankyou_step_count' => strval( $ab_test_stats['thankyou'] ), // Total count of 'thank' you steps created. ); return $pro_features; } /** * Retrieve CartFlows Pro statistics. * * This function retrieves and prepares statistics data specific to CartFlows Pro. * It includes information such as the plugin type, license status. * * @param array $stats_data The base statistics data to which CartFlows Pro data will be added. * @return array $stats_data The modified statistics data including CartFlows Pro specific information. */ public function get_cartflows_pro_stats( $stats_data ) { // Prepare the license stats. $cartflow_pro_data = array( 'pro-plugin-type' => defined( 'CARTFLOWS_PRO_PLUGIN_TYPE' ) ? CARTFLOWS_PRO_PLUGIN_TYPE : '', 'license-status' => CartFlows_Pro_Licence::get_instance()->activate_status, ); // Get the list of all Pro features that can be tracked. $pro_features_stats = $this->get_the_pro_features_stats(); $stats_data['plugin_data']['cartflows'] = array_merge( $stats_data['plugin_data']['cartflows'], $cartflow_pro_data ); $stats_data['plugin_data']['cartflows']['numeric_values'] = array_merge( $stats_data['plugin_data']['cartflows']['numeric_values'], $pro_features_stats ); return $stats_data; } } /** * Prepare if class 'Cartflows_Pro_Admin' exist. * Kicking this off by calling 'get_instance()' method */ Cartflows_Pro_Admin::get_instance();