Last active
November 13, 2025 19:46
-
-
Save petertwise/cae97f0165709d11549faa9c3f3f30b4 to your computer and use it in GitHub Desktop.
GiveWP Auto-connect existing WP users to GiveWP Donors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| // Add this snippet to your theme code, or integrate it into a plugin. | |
| // Exit if accessed directly | |
| if ( ! defined( 'ABSPATH' ) ) { | |
| exit; | |
| } | |
| // Bail if GiveWP is not active | |
| if ( ! class_exists( 'Give' ) ) { | |
| return; | |
| } | |
| // GIVEWP - AUTO-LINK DONORS TO EXISTING WordPress USERS | |
| // This solves an issue where GiveWP sometimes creates donor records without properly linking them to existing WP users | |
| /** | |
| * Link a GiveWP donor record to an existing WordPress user by email address | |
| * | |
| * This function searches for a donor record with the given email that has user_id = 0, | |
| * and if found, links it to the corresponding WordPress user. It also grants the | |
| * 'give_donor' capability to the user if they don't already have it. | |
| * | |
| * @since 1.0.0 | |
| * | |
| * @param string $email The email address to search for. | |
| * | |
| * @return bool True if a donor was successfully linked, false otherwise. | |
| */ | |
| function squarecandy_give_auto_link_donor_to_user( $email ) { | |
| global $wpdb; | |
| // Validate email. | |
| if ( empty( $email ) || ! is_email( $email ) ) { | |
| return false; | |
| } | |
| // Look for existing WordPress user with this email. | |
| $user = get_user_by( 'email', $email ); | |
| if ( ! $user ) { | |
| return false; | |
| } | |
| // Look for existing donor record with same email and user_id = 0. | |
| $donor = $wpdb->get_row( | |
| $wpdb->prepare( | |
| "SELECT * FROM {$wpdb->prefix}give_donors WHERE email = %s AND user_id = 0", | |
| ) | |
| ); | |
| if ( ! $donor ) { | |
| return false; | |
| } | |
| // Link the donor record to the user. | |
| $update_result = $wpdb->update( | |
| $wpdb->prefix . 'give_donors', | |
| array( 'user_id' => $user->ID ), | |
| array( 'id' => $donor->id ), | |
| array( '%d' ), | |
| array( '%d' ) | |
| ); | |
| if ( false === $update_result ) { | |
| // Database update failed. | |
| give_record_log( | |
| 'GiveWP Auto-Link Donor Failed', | |
| sprintf( | |
| // translators: 1: donor ID, 2: user ID, 3: email. | |
| __( 'Failed to link donor ID %1$d to user ID %2$d (email: %3$s)', 'give' ), | |
| $donor->id, | |
| $user->ID, | |
| ), | |
| 0, | |
| 'error' | |
| ); | |
| return false; | |
| } | |
| // Add give_donor capability if they don't have it. | |
| if ( ! user_can( $user->ID, 'give_donor' ) ) { | |
| $user->add_cap( 'give_donor' ); | |
| } | |
| // Log the successful linking. | |
| give_record_log( | |
| 'GiveWP Auto-Link Donor Success - ' . $email, | |
| sprintf( | |
| // translators: 1: donor ID, 2: user ID, 3: email. | |
| __( 'Successfully linked donor ID %1$d to user ID %2$d (email: %3$s)', 'give' ), | |
| $donor->id, | |
| $user->ID, | |
| ), | |
| 0, | |
| 'sale' // Using 'sale' as the log type because it maps to INFO in GiveWP's log system (not error). | |
| ); | |
| // Clear any cached donor data. | |
| Give_Cache::delete_group( $donor->id, 'give-donors' ); | |
| return true; | |
| } | |
| /** | |
| * Automatically link donor to existing user when a new donation is processed | |
| * | |
| * This function runs on the 'give_insert_payment' hook to ensure that | |
| * donors are linked to existing WordPress users at the time of donation. | |
| * | |
| * @since 1.0.0 | |
| * | |
| * @param int $payment_id The ID of the payment. | |
| * @param array $payment_data The payment data. | |
| * | |
| * @return void | |
| */ | |
| function squarecandy_give_auto_link_donor_on_donation( $payment_id, $payment_data ) { | |
| // Get the donor email from payment data. | |
| $email = isset( $payment_data['user_info']['email'] ) ? $payment_data['user_info']['email'] : ''; | |
| if ( empty( $email ) ) { | |
| return; | |
| } | |
| // Attempt to link the donor to an existing user. | |
| squarecandy_give_auto_link_donor_to_user( $email ); | |
| } | |
| add_action( 'give_insert_payment', 'squarecandy_give_auto_link_donor_on_donation', 10, 2 ); | |
| /** | |
| * Daily cron job to scan all donors and link them to existing WordPress users | |
| * | |
| * This function searches for all donor records with user_id = 0 and attempts | |
| * to link them to existing WordPress users by email address. | |
| * | |
| * @since 1.0.0 | |
| * | |
| * @return void | |
| */ | |
| function squarecandy_give_auto_link_all_donors_cron() { | |
| global $wpdb; | |
| // Get all donors with user_id = 0, empty, or null. | |
| $unlinked_donors = $wpdb->get_results( | |
| "SELECT id, email FROM {$wpdb->prefix}give_donors WHERE user_id = 0 OR user_id IS NULL OR user_id = ''" | |
| ); | |
| if ( empty( $unlinked_donors ) ) { | |
| return; | |
| } | |
| $linked_count = 0; | |
| foreach ( $unlinked_donors as $donor ) { | |
| // Attempt to link this donor to an existing user. | |
| $result = squarecandy_give_auto_link_donor_to_user( $donor->email ); | |
| if ( $result ) { | |
| $linked_count++; | |
| } | |
| } | |
| // Log the results of the cron job. | |
| if ( $linked_count > 0 ) { | |
| give_record_log( | |
| 'GiveWP Auto-Link Donors Cron', | |
| sprintf( | |
| // translators: 1: number of donors linked, 2: total number of unlinked donors. | |
| __( 'Cron job linked %1$d of %2$d unlinked donors to existing WordPress users.', 'give' ), | |
| $linked_count, | |
| count( $unlinked_donors ) | |
| ), | |
| 0, | |
| 'sale' // Using 'sale' as the log type because it maps to INFO in GiveWP's log system (not error). | |
| ); | |
| } | |
| } | |
| add_action( 'squarecandy_give_auto_link_donors_cron', 'squarecandy_give_auto_link_all_donors_cron' ); | |
| /** | |
| * Schedule the daily cron job for auto-linking donors | |
| * | |
| * @since 1.0.0 | |
| * | |
| * @return void | |
| */ | |
| function squarecandy_give_schedule_auto_link_cron() { | |
| if ( ! wp_next_scheduled( 'squarecandy_give_auto_link_donors_cron' ) ) { | |
| wp_schedule_event( time(), 'daily', 'squarecandy_give_auto_link_donors_cron' ); | |
| } | |
| } | |
| add_action( 'after_setup_theme', 'squarecandy_give_schedule_auto_link_cron' ); | |
| /** | |
| * Unschedule the cron job when deactivating or switching themes | |
| * | |
| * @since 1.0.0 | |
| * | |
| * @return void | |
| */ | |
| function squarecandy_give_unschedule_auto_link_cron() { | |
| $timestamp = wp_next_scheduled( 'squarecandy_give_auto_link_donors_cron' ); | |
| if ( $timestamp ) { | |
| wp_unschedule_event( $timestamp, 'squarecandy_give_auto_link_donors_cron' ); | |
| } | |
| } | |
| add_action( 'switch_theme', 'squarecandy_give_unschedule_auto_link_cron' ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment