芝麻web文件管理V1.00
编辑当前文件:/home/felaukpo/public_html/wp-content/plugins/cartflows/classes/class-cartflows-update.php
logger_files(); if ( version_compare( $saved_version, '1.1.22', '<' ) ) { update_option( 'wcf_setup_skipped', true ); } if ( version_compare( $saved_version, '1.2.0', '<' ) ) { $this->changed_wp_templates(); } /* Add legacy admin option */ if ( version_compare( $saved_version, '1.6.0', '<' ) ) { update_option( 'cartflows-old-ui-user', true ); update_option( 'cartflows-legacy-admin', true ); update_option( 'cartflows-legacy-meta-show-design-options', true ); } /* Updating meta for global checkout migration & Permalinks */ if ( version_compare( $saved_version, '1.10.0', '<' ) ) { $global_checkout = \Cartflows_Helper::get_common_setting( 'global_checkout' ); if ( $global_checkout ) { $flow_id = wcf()->utils->get_flow_id_from_step_id( $global_checkout ); if ( $flow_id ) { update_option( '_cartflows_store_checkout', $flow_id ); update_option( '_cartflows_old_global_checkout', $global_checkout ); delete_post_meta( $global_checkout, 'wcf-checkout-products' ); } } update_option( 'cartflows_show_weekly_report_email_notice', 'yes' ); $permalink_settings = Cartflows_Helper::get_admin_settings_option( '_cartflows_permalink', false, false ); if ( ! $permalink_settings ) { $default_settings = array( 'permalink' => CARTFLOWS_STEP_POST_TYPE, 'permalink_flow_base' => CARTFLOWS_FLOW_POST_TYPE, 'permalink_structure' => '', ); Cartflows_Helper::update_admin_settings_option( '_cartflows_permalink', $default_settings ); } } // Update required license key to lowercase. Can be removed after 3 major update. if ( version_compare( $saved_version, '1.11.1', '<' ) && _is_cartflows_pro() ) { $api_key = get_option( 'wc_am_client_CartFlows_api_key' ); $api_key_data = get_option( 'wc_am_client_CartFlows' ); // Take backup of options. update_option( 'cartflows_license_backup_data', array( 'wc_am_client_cartflows_api_key' => $api_key, 'wc_am_client_cartflows' => $api_key_data, ) ); delete_option( 'wc_am_client_CartFlows_api_key' ); delete_option( 'wc_am_client_CartFlows' ); // Delete the cached value for old user ( before v1.11.0 and after v1.11.0 ) so WP can add new value. wp_cache_flush(); if ( $api_key_data ) { $new_data = array( 'wc_am_client_cartflows_api_key' => isset( $api_key_data['wc_am_client_CartFlows_api_key'] ) ? $api_key_data['wc_am_client_CartFlows_api_key'] : $api_key_data['wc_am_client_cartflows_api_key'], ); update_option( 'wc_am_client_cartflows', $new_data ); } if ( $api_key ) { update_option( 'wc_am_client_cartflows_api_key', $api_key ); } } // Set default page builder to "Other" for those who have set it as "DIVI". if ( version_compare( $saved_version, '2.0.0', '<' ) ) { $common_settings = get_option( '_cartflows_common', array() ); if ( is_array( $common_settings ) && 'divi' === $common_settings['default_page_builder'] ) { $common_settings['default_page_builder'] = 'elementor'; update_option( '_cartflows_common', $common_settings ); } } // Migrate old combined custom script meta to separate JS and CSS meta fields. if ( version_compare( $saved_version, '2.2.2', '<' ) ) { $this->migrate_custom_scripts(); } // Update auto saved version number. update_option( 'cartflows-version', CARTFLOWS_VER ); // Update cartflows asset version to regenerate the dynamic css. We are using the time() function to add the random number. update_option( 'cartflows-assets-version', time() ); do_action( 'cartflows_update_after' ); } /** * Loading logger files. * * @since 1.0.0 * @return void */ public function logger_files() { if ( ! defined( 'CARTFLOWS_LOG_DIR' ) ) { $upload_dir = wp_upload_dir( null, false ); define( 'CARTFLOWS_LOG_DIR', $upload_dir['basedir'] . '/cartflows-logs/' ); } wcf()->create_files(); } /** * Set script migration status. * * @param string $status Migration status value. * @since 2.2.2 * @return void */ public function set_script_migration_status( $status ) { update_option( 'cartflows_script_migration_status', $status ); } /** * Determine if the migration notice should be shown. * * Returns false if migration is completed or accepted. * Returns false if status is 'skipped' and 7 days have not yet passed. * Returns false if no old script values exist (auto-sets status to 'completed'). * * @since 2.2.2 * @return bool */ public function should_show_migration_notice() { $status = \CartFlows_Helper::get_script_migration_status(); if ( 'completed' === $status || 'accepted' === $status ) { return false; } if ( 'skipped' === $status ) { $skip_timestamp = (int) get_option( 'cartflows_script_migration_skip_timestamp', 0 ); // Show again only after 7 days have passed since last skip. if ( ( time() - $skip_timestamp ) < WEEK_IN_SECONDS ) { return false; } } // Check cached result first to avoid running the meta query on every page load. $has_old_scripts = get_option( 'cartflows_has_old_custom_scripts', '' ); if ( '' === $has_old_scripts ) { // First time check — run the query once and cache the result. $has_old_scripts = $this->has_old_custom_scripts() ? 'yes' : 'no'; update_option( 'cartflows_has_old_custom_scripts', $has_old_scripts, true ); } // If no old script values exist, auto-complete migration and enable the code editor. if ( 'yes' !== $has_old_scripts ) { $this->set_script_migration_status( 'completed' ); return false; } return true; } /** * Check if any posts have old combined custom script meta values. * * Queries the database for any cartflows_step or cartflows_flow posts * that have non-empty 'wcf-custom-script' or 'wcf-flow-custom-script' meta. * * @since 2.2.3 * @return bool True if old script data exists, false otherwise. */ public function has_old_custom_scripts() { global $wpdb; $result = $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->prepare( "SELECT 1 FROM {$wpdb->postmeta} pm INNER JOIN {$wpdb->posts} p ON pm.post_id = p.ID WHERE p.post_type IN (%s, %s) AND pm.meta_key IN (%s, %s) AND pm.meta_value != '' LIMIT 1", 'cartflows_step', 'cartflows_flow', 'wcf-custom-script', 'wcf-flow-custom-script' ) ); return ( null !== $result ); } /** * Get current migration skip count. * * @since 2.2.2 * @return int */ public function get_migration_skip_count() { return (int) get_option( 'cartflows_script_migration_skip_count', 0 ); } /** * Increment migration skip count and record the skip timestamp. * * @since 2.2.2 * @return void */ public function increment_migration_skip_count() { $count = $this->get_migration_skip_count(); update_option( 'cartflows_script_migration_skip_count', $count + 1 ); update_option( 'cartflows_script_migration_skip_timestamp', time() ); } /** * Run on-demand migration of custom scripts triggered by user action. * * Unlike migrate_custom_scripts() which runs during version updates, * this method is called only when the user explicitly clicks "Migrate Data" * in the admin notice. It returns a count of migrated posts and updates * the migration status to 'completed'. * * @since 2.2.2 * @return int Number of posts that had data migrated. */ public function migrate_custom_scripts_on_demand() { $migrated_count = 0; // Migrate step-level custom scripts. $migrated_count += $this->migrate_post_type_scripts_counted( 'cartflows_step', 'wcf-custom-script', 'wcf-step-custom-js', 'wcf-step-custom-css' ); // Migrate flow-level custom scripts. $migrated_count += $this->migrate_post_type_scripts_counted( 'cartflows_flow', 'wcf-flow-custom-script', 'wcf-flow-custom-js', 'wcf-flow-custom-css' ); $this->set_script_migration_status( 'completed' ); return $migrated_count; } /** * Migrate custom scripts for a specific post type and return the count of migrated posts. * * @param string $post_type The post type to query. * @param string $old_meta_key The old combined script meta key. * @param string $new_js_meta_key The new JS-only meta key. * @param string $new_css_meta_key The new CSS-only meta key. * * @since 2.2.2 * @return int Number of posts migrated. */ public function migrate_post_type_scripts_counted( $post_type, $old_meta_key, $new_js_meta_key, $new_css_meta_key ) { global $wpdb; $results = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->prepare( "SELECT p.ID, pm.meta_value FROM {$wpdb->posts} p INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE p.post_type = %s AND pm.meta_key = %s AND pm.meta_value != '' LIMIT 500", $post_type, $old_meta_key ) ); if ( empty( $results ) || ! is_array( $results ) ) { return 0; } $migrated = 0; foreach ( $results as $row ) { $post_id = $row->ID; $old_value = $row->meta_value; // Skip if the new meta fields already have values (don't overwrite manual entries). $existing_js = get_post_meta( $post_id, $new_js_meta_key, true ); $existing_css = get_post_meta( $post_id, $new_css_meta_key, true ); if ( ! empty( $existing_js ) || ! empty( $existing_css ) ) { continue; } // Decode HTML entities first since the old value was stored encoded. $decoded = html_entity_decode( $old_value, ENT_QUOTES, 'UTF-8' ); // Extract CSS and JS from the combined script. $parsed = $this->parse_combined_script( $decoded ); $did_migrate = false; if ( ! empty( $parsed['css'] ) ) { update_post_meta( $post_id, $new_css_meta_key, htmlentities( $parsed['css'] ) ); $did_migrate = true; } if ( ! empty( $parsed['js'] ) ) { update_post_meta( $post_id, $new_js_meta_key, htmlentities( $parsed['js'] ) ); $did_migrate = true; } if ( $did_migrate ) { ++$migrated; } } return $migrated; } /** * Migrate old combined custom script meta to separate JS and CSS meta fields. * * Previously, a single textarea accepted both JS and CSS with blocks * - Bare JS code (no tags, treated as JS) * * @param string $content The combined script content (decoded). * @return array Associative array with 'js' and 'css' keys. * * @since 2.2.2 */ public function parse_combined_script( $content ) { $css = ''; $js = ''; // Extract all blocks as CSS. if ( preg_match_all( '/ and blocks from the content. $remaining = preg_replace( '/