Skip Navigation

[Resolved] Membership Site – Update Status of User Posts when User Role is Changed

This thread is resolved. Here is a description of the problem and solution.

Problem: I would like to programmatically change the post status of all posts by the current User in a PHP hook I have set up to handle User role changes.

Solution: You can use the WordPress get_posts function to query all the author's posts, then update each of the posts as needed with wp_update_post. Here is a basic example:

...
$user->set_role( 'tsn_bronze' );
 
// get all the published Voyage posts by the current user
$args = array(
    'post_type' => 'voyage',
    'post_status' => 'publish',
    'author' => $user_id,
    'posts_per_page' => -1);
$posts_array = get_posts($args);
 
// loop over those posts and update each one to status "pending"
foreach ($posts_array as $the_post) {
    $update_post = array(
        'ID' => $the_post->ID,
        'post_status' => 'pending'
    );
    wp_update_post( $update_post );
}

If you want to use the same code to update posts of more than one custom post type, modify the 'post_type' argument to use an array instead of a single string:

$args = array(
    'post_type' => array('voyage','deck-event'),

Relevant Documentation:
https://codex.wordpress.org/Template_Tags/get_posts
https://codex.wordpress.org/Function_Reference/wp_update_post
https://codex.wordpress.org/Class_Reference/WP_Query#Type_Parameters

This support ticket is created 6 years, 9 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Our next available supporter will start replying to tickets in about 0.74 hours from now. Thank you for your understanding.

Sun Mon Tue Wed Thu Fri Sat
8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 - -
13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 - -

Supporter timezone: America/New_York (GMT-04:00)

Author
Posts
#613375

I have a membership site setup as per your documentation that has 3 custom user roles (Bronze, Silver, Gold).

Bronze users can publishing edit custom posts of the types Organisations, Events, Series, Appearances and Vessels.

Silver users can publish and edit all of the above as well as the post types Posts and Opportunities

Gold users can publish and edit all of the above the above as well as the post types Voyages and Deck Events

Using the Access plugin I have made sure that users can only publish the appropriate content types based on their role.

My issue is, if a user Downgrades I need any of their existing posts of restricted CPTs to have their statuses changed from 'Published' to 'Pending Review'. This does not currently happen when downgrading user roles.

For example, if a Gold user downgrades their account to Silver, any of the Voyage or Deck Event posts they have created must have their statuses changed to 'Pending Review'.

I am already using custom php to manage user roles (see https://toolset.com/forums/topic/date-field-calculations-changing-user-role-based-on-user-custom-field-value/page/2/#post-611573) and as a part of that, I have set up a CRON job that loops through users of a specific Role and updates their Role based on the value of a User Custom Field (below).

// Check Gold User Account Renewal Status and Update User Role Accordingly - WORKING

add_action( 'check_gold_user_role_valid_cron_hook', 'check_gold_user_role_valid' );


if ( ! wp_next_scheduled( 'check_gold_user_role_valid_cron_hook' ) ) {
    wp_schedule_event( time(), 'hourly', 'check_gold_user_role_valid_cron_hook' );
}


  function check_gold_user_role_valid() {
 
     // The Query
	$user_query = new WP_User_Query( array( 'role' => 'tsn_gold', 'fields' => 'all' ) );
	$today = date("U");

     // User Loop
	if ( ! empty( $user_query->get_results() ) ) {
		foreach ( $user_query->get_results() as $user ) {

			$alr = types_render_usermeta( "account-last-renewed", array( "user_id" => "$user->ID", "output" => "raw" ) );
			$validuntil = types_render_usermeta( "account-valid-until", array( "user_id" => "$user->ID", "output" => "raw" ) );

			$user_id = $user->ID;

			// If both Account Last Renewed and Valid Until are in the future
			if ( ( $validuntil > $today ) && ( $alr > $today ) ) {
				update_user_meta( $user_id, 'wpcf-test-user-valid', 'User Account Remains Valid as Gold' );
			}

			// If Both Account Last Renewed and Valid Until are in the past
			if ( ( $validuntil < $today ) && ( $alr < $today ) ) {
				update_user_meta( $user_id, 'wpcf-test-user-valid', 'User Account Was Downgraded Gold to Bronze' );
				
				$user = get_userdata( $user_id );
        			$user->set_role( 'tsn_bronze' );
			}
		}
	} 
}

At the point where the user role is set to tsn_bronze, would it be possible to get the posts of that user in a specific CPT (voyages, deck-events) and change the post_status for each of them?

I've spent a while searching to find examples of such a function online but haven't yet found anything that works.

Could you advise on any possible solution?

Thanks in Advance!

#613516

Sure, you can use the WordPress get_posts function to query all the author's posts, then update each of the posts as needed with wp_update_post. Here is a basic example:

...
$user->set_role( 'tsn_bronze' );

// get all the published Voyage posts by the current user
$args = array(
    'post_type' => 'voyage',
    'post_status' => 'publish',
    'author' => $user_id,
    'posts_per_page' => -1);
$posts_array = get_posts($args);

// loop over those posts and update each one to status "pending"
foreach ($posts_array as $the_post) {
    $update_post = array(
        'ID' => $the_post->ID,
        'post_status' => 'pending'
    );
    wp_update_post( $update_post );
}

If you want to use the same code to update posts of more than one custom post type, modify the 'post_type' argument to use an array instead of a single string:

$args = array(
    'post_type' => array('voyage','deck-event'),

More info about these APIs:
https://codex.wordpress.org/Template_Tags/get_posts
https://codex.wordpress.org/Function_Reference/wp_update_post
https://codex.wordpress.org/Class_Reference/WP_Query#Type_Parameters

#615552

Thanks Christian, it looks like that's done the trick!