BuddyDev

Search

Discussion on dealing with buddypress inactive users or dead profiles

  • Participant
    Level: Guru
    Posts: 885
    Tosin on #49557

    Hello Brajesh,

    I have been thinking lately about the best way to deal with inactive buddypress members or dead profiles. digital dead profiles can lead to some issues like

    1. Profile hijacking / identity theft
    2. Misinformation and outdated content
    3. Difficulty in maintaining connections
    4. Privacy concerns
    5. Unattended messages and notifications
    6. Impact on data accuracy and user statistics

    I would suggest creating a plugin that can deal with the issue of cleaning up inactive members as the reality of life is people cant live forever.

    Possible plugin function can include:

    1. Firstly identifying and categorising inactive members: For example I have a custom role called (Ghost Member) now if users last active time is more than a year then the user should be added to the role (Ghost Member)

    2. Communicating with inactive members: Once a user has been classified as a (Ghost Member) at least 2 periodic emails should be sent to the inactive members encouraging them to login.
    Note If the inactive members logs in to site then remove member from (Ghost Member) role

    3. Reporting system: There should be a shortcode that can be added to a dedicated page where other users can report a user as being biologically dead.

    4. Automatic clean up of inactive members: A possible example could be if total (Ghost Member) count equal a specified number threshold the automatically delete all users that belong to the (Ghost Member) role.

    5. Dealing with content created by inactive members: There should be a settings pages to assign all specific post type content to a specific user. For example when auto deleting ghost members assign their post to another user called (site memorials) but delete their advert post type.

    This are my own suggestion but more suggestions are welcome

  • Participant
    Level: Guru
    Posts: 885
    Tosin on #49559

    This is example code for classifying user inactive for a year

     function check_inactive_users_and_assign_role() {
        $users = get_users(); // Get all users
    
        foreach ( $users as $user ) {
            $last_activity = bp_get_user_last_activity( $user->ID ); // Get the last activity timestamp
    
            if ( ! empty( $last_activity ) ) {
                $inactive_time = time() - strtotime( $last_activity ); // Calculate the time difference in seconds
    
                // Check if the user has been inactive for a year (31536000 seconds)
                if ( $inactive_time >= 31536000 ) {
                    $ghost_member_role = 'ghost_member'; // The role slug for Ghost Member
    
                    // Add the user to the Ghost Member role
                    $user_obj = new WP_User( $user->ID );
                    $user_obj->add_role( $ghost_member_role );
                }
            }
        }
    }
    add_action( 'bp_loaded', 'check_inactive_users_and_assign_role' );
     
  • Participant
    Level: Guru
    Posts: 885
    Tosin on #49560

    Now how will the code affect site performance if the site has a least one million registered members. If the site has a large number of registered members, iterating through all users using get_users() and checking their activity status can potentially impact site performance, especially if the operation is performed on every page load.

    Will this code be better

     function schedule_inactive_users_check() {
        if ( ! wp_next_scheduled( 'check_inactive_users_event' ) ) {
            wp_schedule_event( time(), 'daily', 'check_inactive_users_event' );
        }
    }
    add_action( 'bp_loaded', 'schedule_inactive_users_check' );
    
    function check_inactive_users_and_assign_role() {
        $users = get_users( array( 'number' => 100 ) ); // Get 100 users at a time
    
        foreach ( $users as $user ) {
            $last_activity = bp_get_user_last_activity( $user->ID ); // Get the last activity timestamp
    
            if ( ! empty( $last_activity ) ) {
                $inactive_time = time() - strtotime( $last_activity ); // Calculate the time difference in seconds
    
                // Check if the user has been inactive for a year (31536000 seconds)
                if ( $inactive_time >= 31536000 ) {
                    $ghost_member_role = 'ghost_member'; // The role slug for Ghost Member
    
                    // Add the user to the Ghost Member role
                    $user_obj = new WP_User( $user->ID );
                    $user_obj->add_role( $ghost_member_role );
                }
            }
        }
    }
    
    function run_inactive_users_check() {
        check_inactive_users_and_assign_role();
    
        // Check if there are more users to process
        if ( count( get_users() ) > 0 ) {
            wp_schedule_single_event( time() + 10, 'run_inactive_users_check' ); // Schedule the next batch after 10 seconds
        }
    }
    add_action( 'check_inactive_users_event', 'run_inactive_users_check' );
     
  • Keymaster
    (BuddyDev Team)
    Posts: 24231
    Brajesh Singh on #49574

    Hi Tosin,
    Thank you for the suggestions.
    This is interesting and we will add it to our list.

    1. Using get_users() has bad impact for large number of users. A better solution is to use get_users() but specify fields=ID, that is a lot more performing.

    2. If you are handling 100 users per request on a 1 million user site in 24 hours, it will take around 7 requests per minute which does not seem to be feasible with the logic.

    I believe a CLI based solution is more suitable for the use case as you don’t need to worry about the request timeout and can process continuously.

    Regards
    Brajesh

  • Participant
    Level: Guru
    Posts: 885
    Tosin on #49579

    Thanks for the feddback Brajesh

    Although I know nothing about CLI based solutions this is what I have now

    
    function check_inactive_users_and_assign_role() {
        // Check if the current page is the BuddyPress sitewide activity directory page
        if ( function_exists( 'bp_is_activity_directory' ) && bp_is_activity_directory() ) {
            // Check if user is logged in
            if ( is_user_logged_in() ) {
                $users = get_users(
                    array(
                        'fields'      => 'ID', // Only retrieve the user IDs for efficiency
                        'role__not_in' => array( 'administrator' ), // Exclude users with the 'administrator' role
                        'number'      => -1, // Retrieve all users at once
                    )
                );
    
                foreach ( $users as $user_id ) {
                    $last_activity = bp_get_user_last_activity( $user_id ); // Get the last activity timestamp
    
                    if ( ! empty( $last_activity ) ) {
                        $inactive_time = time() - strtotime( $last_activity ); // Calculate the time difference in seconds
    
                        // Check if the user has been inactive for a year (31536000 seconds)
                        if ( $inactive_time >= 31536000 ) {
                            $ghost_member_role = 'ghost_member'; // The role slug for Ghost Member
    
                            // Add the user to the Ghost Member role
                            $user_obj = new WP_User( $user_id );
                            $user_obj->add_role( $ghost_member_role );
                        }
                    }
                }
            }
        }
    }
    
    add_action( 'bp_loaded', 'check_inactive_users_and_assign_role' );
    
     
    

    Maybe running this first code once a week might be better

    
     /**
     * (Buddypress)- Remove users from the "Ghost Member" after login
    */
    function remove_ghost_member_role_on_login( $user_login, $user ) {
        $ghost_member_role = get_role( 'ghost_member' ); // Get the Ghost Member role object
    
        if ( $ghost_member_role && in_array( $ghost_member_role->name, $user->roles ) ) {
            $user_obj = new WP_User( $user->ID );
            $user_obj->remove_role( $ghost_member_role->name );
        }
    }
    add_action( 'wp_login', 'remove_ghost_member_role_on_login', 10, 2 );
     
    

    Since I dont have an efficient way for inactive user clean up without affecting site performance, maybe the method of cleanup should change, what would you suggest.

    1. Automatic cleanup via code
    2. Manual cleanup by clicking a button in admin area
    3. Community cleanup by community members reporting other inactive users
    4. Mix of both automatic cleanup and community clean up or the 3

    Personally I would have preferred automatic approach to save time

    what’s your opinion

    thanks

  • Keymaster
    (BuddyDev Team)
    Posts: 24231
    Brajesh Singh on #49587

    Please avoid running check on bp_loaded.
    It is a bad idea. Also, is_user_logged_in() will return false on bp_loaded as the user is not authenticated/initialised at that hook.

    Regards
    Brajesh

  • Participant
    Level: Guru
    Posts: 885
    Tosin on #49602

    Thanks Brajesh now im clueless.

    I hope other members can provide suggestions about this idea.

  • Participant
    Level: Guru
    Posts: 885
    Tosin on #50886

    I don’t want to give up on this so im trying another approach below

     // change the role of inactive members over 1 year to ghost member
    function update_site_ghost_members() {
        // Check if it's the activity directory page and the user is an admin
        if (bp_is_activity_directory() && current_user_can('administrator')) {
            $last_run_timestamp = get_user_meta(0, 'last_ghost_member_role_update', true);
    
            // Check if a month (2592000 seconds = 30 days) has passed since the last run
            if (!$last_run_timestamp || (time() - $last_run_timestamp) >= 2592000) {
                // Get users with specific roles (e.g., 'contributor' and 'subscriber')
                $users = get_users(array(
                    'fields' => 'ID',
                    'role__in' => array('contributor', 'subscriber'),
                ));
    
                foreach ($users as $user_id) {
                    // Check user's last activity using BuddyPress function
                    $last_activity = bp_get_user_last_activity($user_id);
    
                    // Calculate time difference
                    $inactive_time = strtotime('now') - strtotime($last_activity);
    
                    // If inactive for more than one year (31536000 seconds = 1 year)
                    if ($inactive_time > 31536000) {
                        // Assign 'Ghost Member' role to the user
                        $user = new WP_User($user_id);
                        $user->add_role('ghost_member');
                    }
                }
    
                // Update the timestamp to indicate the code ran
                update_user_meta(0, 'last_ghost_member_role_update', time());
            }
        }
    }
    add_action('template_redirect', 'update_site_ghost_members'); 

    running get_users would be awesome in batches

  • Keymaster
    (BuddyDev Team)
    Posts: 24231
    Brajesh Singh on #50904

    Hi Tosin,
    Thank you for posting.
    I am sorry, I have limited time available for assisting with custom code due to one of our high priority projects. I am unable to assist beyond our plugins for next 6-8 weeks. Will be glad to re-look at things after that.

    Regards
    Brajesh

You must be logged in to reply to this topic.

This topic is: not resolved