E option_name=%s", $option_name ), ARRAY_A ); } if ( $careless_insert || ( ! $careless_update && empty( $result['option_id'] ) ) ) { $result = $wpdb->query( $wpdb->prepare( "INSERT INTO {$wpdb->prefix}options ( option_name, option_value, autoload ) VALUES ( %s, %s, %s )", array( $option_name, $option_value, 'no', ) ) ); return $result; } if ( $careless_update || ! empty( $result['option_id'] ) ) { $result = $wpdb->update( "{$wpdb->prefix}options", array( 'option_value' => $option_value, 'autoload' => 'no', ), array( 'option_name' => $option_name ) ); return $result !== false; } } public static function btl_update_autoload_option( $option_name, $autoload = false ) { global $wpdb; $result = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}options WHERE option_name=%s", $option_name ), ARRAY_A ); if ( ! empty( $result['option_id'] ) && ! empty( $result['option_value'] ) ) { if ( $autoload === false ) { $result = $wpdb->update( "{$wpdb->prefix}options", array( 'option_value' => $result['option_value'], 'autoload' => 'no', ), array( 'option_name' => $option_name ) ); } elseif ( $autoload === true ) { $result = $wpdb->update( "{$wpdb->prefix}options", array( 'option_value' => $result['option_value'], 'autoload' => 'yes', ), array( 'option_name' => $option_name ) ); } return $result !== false; } } public static function run_migration_for_ptrl_links_in_background( $installer, $links_count ) { global $wpdb; $per_page = 10000; $total_page = ceil( $links_count / $per_page ); for ( $page = 1; $page <= $total_page; $page++ ) { $offset = ( $page - 1 ) * $per_page; $links = $wpdb->get_col( "SELECT concat('prli_links-', ID) AS ID FROM {$wpdb->prefix}prli_links LIMIT $per_page OFFSET {$offset}", 0 ); $installer->data( $links )->save(); } $installer->data( array( 'betterlinks_ptl_links_migrated' ) )->save(); return $installer; } public static function run_migration_for_ptrl_clicks_in_background( $installer, $clicks_count ) { global $wpdb; $per_page = 10000; $total_page = ceil( $clicks_count / $per_page ); for ( $page = 1; $page <= $total_page; $page++ ) { $offset = ( $page - 1 ) * $per_page; $clicks = $wpdb->get_col( "SELECT concat('prli_clicks-', ID) AS ID FROM {$wpdb->prefix}prli_clicks LIMIT $per_page OFFSET {$offset}", 0 ); $installer->data( $clicks )->save(); } $installer->data( array( 'betterlinks_ptl_clicks_migrated' ) )->save(); return $installer; } public function generate_random_slug( $length = 3 ) { $characters = '0123456789abcdefghijklmnopqrstuvwxyz'; $random_string = ''; $characters_length = strlen( $characters ); for ( $i = 0; $i < $length; $i++ ) { $random_string .= $characters[ wp_rand( 0, $characters_length - 1 ) ]; } $random_num = wp_rand( 0, 10 ) . wp_rand( 0, 10 ) . wp_rand( 0, 10 ); return $random_string . $random_num; } public function get_betterlinks_prefix() { if ( BETTERLINKS_EXISTS_SETTINGS_JSON ) { $data = Cache::get_json_settings(); if ( empty( $data ) ) { $data = Cache::write_json_settings(); } $prefix = ! empty( $data['prefix'] ) ? $data['prefix'] . '/' : ''; return $prefix; } $betterlinks_links = get_option( 'betterlinks_links', array() ); if ( is_string( $betterlinks_links ) ) { $betterlinks_links = json_decode( $betterlinks_links, true ); } $prefix = ! empty( $betterlinks_links['prefix'] ) ? $betterlinks_links['prefix'] . '/' : ''; return $prefix; } public function fetch_target_url( $target_url ) { if ( empty( $target_url ) ) { return false; } $http = new WP_Http(); $result = $http->get( $target_url, array( 'sslverify' => false ) ); $title = ''; if ( ! is_wp_error( $result ) && ! empty( $result['body'] ) && preg_match( '/(.*)<\/title>/siU', $result['body'], $title_matches ) ) { $title = html_entity_decode( $title_matches[1] ); } return $title; } public static function insert_new_category( $slug ) { if ( ! ! intval( $slug ) ) { return $slug; } // Check if category exists and get its ID for AI $existing_term = self::get_term_by_slug( self::make_slug( $slug ), 'category' ); if ( ! empty( $existing_term ) && is_array( $existing_term ) && count( $existing_term ) > 0 ) { // Category exists, return its ID return $existing_term[0]['ID']; } // Category doesn't exist, create it $insert_id = self::insert_term( array( 'term_name' => $slug, 'term_slug' => self::make_slug( $slug ), 'term_type' => 'category', ) ); if ( $insert_id ) { self::clear_query_cache(); return $insert_id; } return $slug; } public static function isJson( $string ) { json_decode( $string ); return json_last_error() === JSON_ERROR_NONE; } public static function get_migratable_plugins() { return [ 'simple301redirects' => defined('SIMPLE301REDIRECTS_VERSION'), 'thirstyaffiliates' => class_exists('ThirstyAffiliates'), 'prettylinks' => defined('PRLI_VERSION'), ]; } public static function init_tracking( $data, $utils ) { global $betterlinks; $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; // phpcs:ignore $dd = new DeviceDetector( $user_agent ); $dd->parse(); $data['is_bot'] = $dd->isBot(); if ( empty( $data['target_url'] ) || ! apply_filters( 'betterlinks/pre_before_redirect', $data ) ) { // password protection logics if( empty( $data['skip_password_protection'] ) ){ do_action( 'betterlinkspro/admin/check_password_protection', $data['short_url'], $data ); } if ( empty( $data['target_url'] ) || ! apply_filters( 'betterlinks/pre_before_redirect', $data ) ) { // phpcs:ignore return false; } } $data = apply_filters( 'betterlinks/link/before_dispatch_redirect', $data ); // phpcs:ignore. if ( empty( $data ) ) { return false; } do_action( 'betterlinks/before_redirect', $data ); // phpcs:ignore. $comparable_url = rtrim( preg_replace( '/https?\:\/\//', '', site_url( '/' ) ), '/' ) . '/' . $data['short_url']; $destination_url = rtrim( preg_replace( '/https?\:\/\//', '', $data['target_url'] ), '/' ); $comparable_url = rtrim( preg_replace( '/^www\.?/', '', $comparable_url ), '/' ); $destination_url = rtrim( preg_replace( '/^www\.?/', '', $destination_url ), '/' ); if ( ! $data || $comparable_url === $destination_url ) { return; } if ( filter_var( $data['track_me'], FILTER_VALIDATE_BOOLEAN ) ) { $data = apply_filters( 'betterlinks/extra_tracking_data', $data, $dd ); $data['os'] = OperatingSystem::getOsFamily( $dd->getOs( 'name' ) ); $data['browser'] = Browser::getBrowserFamily( $dd->getClient( 'name' ) ); $data['device'] = $dd->getDeviceName(); if ( isset( $betterlinks['disablebotclicks'] ) && $betterlinks['disablebotclicks'] ) { if ( ! $dd->isBot() ) { $utils->start_trakcing( $data ); } } else { $utils->start_trakcing( $data ); } } } /** * Rebuild links JSON from database * Useful when JSON file is corrupted or completely out of sync * * @since 2.6.0 * @return bool True if rebuild successful */ public static function rebuild_links_json() { if ( ! BETTERLINKS_EXISTS_LINKS_JSON ) { return false; } $formattedArray = self::get_links_for_json(); $json_file = trailingslashit( BETTERLINKS_UPLOAD_DIR_PATH ) . 'links.json'; return (bool) file_put_contents( $json_file, wp_json_encode( $formattedArray ) ); } /** * Sync all missing links from database to JSON file * Checks if all database links exist in JSON and adds missing ones * Called when admin page loads to ensure complete synchronization * * @since 2.6.2 * @return array Results: ['total' => count, 'synced' => count] */ public static function sync_all_missing_links_to_json() { if ( ! BETTERLINKS_EXISTS_LINKS_JSON ) { return array( 'total' => 0, 'synced' => 0 ); } if ( ! function_exists( 'file_get_contents' ) || ! function_exists( 'file_put_contents' ) ) { return array( 'total' => 0, 'synced' => 0 ); } $json_file = trailingslashit( BETTERLINKS_UPLOAD_DIR_PATH ) . 'links.json'; // Read JSON file if ( ! file_exists( $json_file ) ) { // JSON doesn't exist, rebuild from scratch self::rebuild_links_json(); return array( 'total' => 0, 'synced' => 0 ); } $json_content = file_get_contents( $json_file ); $json_data = json_decode( $json_content, true ); // If JSON is corrupted, rebuild if ( ! is_array( $json_data ) ) { self::rebuild_links_json(); return array( 'total' => 0, 'synced' => 0 ); } // Get all published links from database global $wpdb; $all_db_links = $wpdb->get_results( "SELECT ID, short_url, wildcards FROM {$wpdb->prefix}betterlinks WHERE link_status = 'publish'", ARRAY_A ); $synced_count = 0; $total_links = count( $all_db_links ); // Check each database link and add if missing from JSON foreach ( $all_db_links as $db_link ) { $short_url = $db_link['short_url']; $link_id = $db_link['ID']; $is_wildcard = isset( $db_link['wildcards'] ) && $db_link['wildcards']; // Determine where to look $target_section = $is_wildcard ? 'wildcards' : 'links'; // Check if link exists in JSON $link_exists = false; if ( isset( $json_data[ $target_section ] ) && is_array( $json_data[ $target_section ] ) ) { if ( isset( $json_data[ $target_section ][ $short_url ] ) ) { $link_exists = true; } } // If missing, add it if ( ! $link_exists ) { $full_link_data = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}betterlinks WHERE ID = %d", $link_id ), ARRAY_A ); if ( $full_link_data ) { $formatted_link = self::json_link_formatter( $full_link_data ); if ( $formatted_link ) { // Ensure target section exists if ( ! isset( $json_data[ $target_section ] ) ) { $json_data[ $target_section ] = array(); } // Add missing link to JSON $json_data[ $target_section ][ $short_url ] = $formatted_link; $synced_count++; } } } } // Write back to file if any links were synced if ( $synced_count > 0 ) { file_put_contents( $json_file, wp_json_encode( $json_data ) ); } return array( 'total' => $total_links, 'synced' => $synced_count, ); } }