How to append taxonomy terms to six most recent published custom post types

Alicia St Rose
Alicia St Rose used Ask the Experts™
on
Okay here is my scenario:

I'm using the Memberpress plugin and I need to allow a certain number of custom post types (chapters) to be available for different membership levels. These would be the most recent chapters.

There's:

Tier 1 (2 chapters)
Tier 2 (4 chapters)
Tier 3 (6 chapters)

I've created a taxonomy called Member Type and added the tiers as terms. I will be adding the terms to the most recent 6 Chapters. I need this to happen automatically because I'll be designating that content as paid subscription content depending on the level. I can target content by taxonomy in MemberPress.

I've got some code working that will add all three tiers to any new chapter. But, what I really need it for these terms to be only limited to the most recent 6 chapters in this way:

Most recent 6 chapters have terms: Tier 1, Tier 2, Tier 3
Most recent 4 chapters have terms: Tier 1, Tier 2
Most recent 2 chapters have term: Tier 1

I have NO idea how to make this happen. Well, maybe a teeny bit, because I've been googling for hours! Can anyone set me in the right direction?

Here's the code I have:

add_action( 'save_post_chapter', 'myprefix_set_default_object_terms', 11, 2 );
function myprefix_set_default_object_terms( $post_id, $post ) {
	if ( 'publish' === $post->post_status ) {
		// Change here your custom taxonomy slugs and term slugs
		$defaults = array(
			'member-type' => array( 'tier-1', 'tier-2', 'tier-3' )
		);
		$taxonomies = get_object_taxonomies( $post->post_type );
		foreach ( (array) $taxonomies as $taxonomy ) {
			$terms = wp_get_post_terms( $post_id, $taxonomy );
			$append = ! empty( $terms );

			if ( array_key_exists( $taxonomy, $defaults ) ) {
				// usage: wp_set_object_terms( $object_id, $terms, $taxonomy, $append );
				$term_taxonomy_ids = wp_set_object_terms( $post_id, $defaults[$taxonomy], $taxonomy, $append );

				if ( is_wp_error( $term_taxonomy_ids ) ) {
					// There was an error somewhere and the terms couldn't be set.
				} else {
					// Success! These terms were added to the post.
				}					
			}
		}
	}
}

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Let me try and understand.

When a chapter is added it gets tier1
As soon as it moves to position 3 (i.e. after two more chapters are added) it gets tier2
Then after it moves to position 5 (an additional 2 chapters are added) it gets tier3

Is that correct?
Alicia St RoseOwner & Principle Developer/Designer

Author

Commented:
Yikes! I can see where I may have screwed it up in my initial post. It looks like I really want oldest, not most recent. So, new one's get term: Tier 3.

Tier 3 can see all 6  latest chapters: Newest to Oldest

Tier 2 can only see 4 of the latest chapters: 4 Oldest

Tier 1 can only see 2 of the latest chapters: 2 Oldest

A chapter is released everyday for 6 days. Tier 1 has to wait an additional 4 days to see all six.

So let's say there are 10 chapters already published once it's launched.

Tier 1 can only see 6 (1 - 6)
Tier 2 can only see 8 (1 - 8)
Tier 3 can see all 10 (1 - 10)

When a new one is published:

Tier 1 can see 7 Chapters
Tier 2 can see 9 Chapters
Tier 3 can see 11Chapters

The latest six should have terms as such:

Chapter 6: Tier 1, Tier 2, Tier 3
Chapter 7: Tier 1, Tier 2, Tier 3
Chapter 8: Tier 2, Tier 3
Chapter 9: Tier 2, Tier 3
Chapter 10: Tier 3
Chapter 11: Tier 3

The Chapters work their way through the gamut starting with Tier 3, having the other terms appended, then losing them all when 6 chapters are published after they've appeared.  

Does that make more sense or did I just make it so much more complicated?
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
I understand
Tier 1 can see 7 Chapters
The six it could see before + the new 1?

Tier 2 can see 9 Chapters
So Tier 2 is not restricted to 8 chapters they can always see ALL chapters except the 2 most recent ones?
Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

Alicia St RoseOwner & Principle Developer/Designer

Author

Commented:
Tier 1 can see 7 Chapters
The six it could see before + the new 1?
Yes

So Tier 2 is not restricted to 8 chapters they can always see ALL chapters except the 2 most recent ones?
Yes! :)
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
What you need to do is keep the trigger on the publish - you then need to iterate over all chapters in date order

$position = 1;
$posts = // query posts that are chapters in descending publish date order
foreach($posts as $post) {
   clearExistingTaxonomyAssignments();
  // add Tier 1
   if ($postion >2) {
        // add tier 2
   } 
   if ($postion > 4) {
      // add tier 3
   }

   $postion++;
}

Open in new window


A more complicated solution would be to add / remove specific tiers rather than clearing and re-assiging but that might end up being overly complicated - a simple clear and re-assign is the simplest approach.
Alicia St RoseOwner & Principle Developer/Designer

Author

Commented:
Okay.

I've tried to incorporate the code into my existing code and clearly I'm doing it wrong. My foreach loops may not be nested properly, if they should be nested at all. Here's what I've got:

function myprefix_set_default_object_terms( $post_id, $post ) {
	if ( 'publish' === $post->post_status ) {
		$position = 1;
		$args = array( 'post_type' => 'chapter', 'order' => 'DESC', 'orderby' => 'date');
		$posts = get_posts( $args )// query posts that are chapters in descending publish date order
		foreach($posts as $post) {
		   clearExistingTaxonomyAssignments();
		  $defaults = array(
					'member-type' => array('tier-1' )
				);
				
		   if ($postion >2) {
		      $defaults = array(
					'member-type' => array('tier-2' )
				);
		   } 
		   if ($postion > 4) {
		      $defaults = array(
					'member-type' => array('tier-3' )
				);
		   }
			
		   $postion++;
		   
		   $taxonomies = get_object_taxonomies( $post->post_type );
				foreach ( (array) $taxonomies as $taxonomy ) {
					$terms = wp_get_post_terms( $post_id, $taxonomy );
					$append = ! empty( $terms );
		
					if ( array_key_exists( $taxonomy, $defaults ) ) {
						// usage: wp_set_object_terms( $object_id, $terms, $taxonomy, $append );
						$term_taxonomy_ids = wp_set_object_terms( $post_id, $defaults[$taxonomy], $taxonomy, $append );
		
						if ( is_wp_error( $term_taxonomy_ids ) ) {
							// There was an error somewhere and the terms couldn't be set.
						} else {
							// Success! These terms were added to the post.
						}					
					}
				}
			}
		}
	}

Open in new window

Alicia St RoseOwner & Principle Developer/Designer

Author

Commented:
UPDATE:

I was missing a semicolon right before first foreach. So now going to see if this code works...🤓
Alicia St RoseOwner & Principle Developer/Designer

Author

Commented:
Not working.

I'm getting "Publishing failed" and "Updating failed" error messages.

Sooo.... I'll just hang out to see what I did wrong here.
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Probably because of this line
clearExistingTaxonomyAssignments();

Open in new window

You need to define this function / code - what I posted was pseudo code to paint a general picture of the approach.
I have not worked much with taxonomies but I am guessing you use this function
wp_delete_object_term_relationships().

Probably something like this (untested)
wp_delete_object_term_relationships($post->ID, ['tier1','tier2','tier3']);

Open in new window

Alicia St RoseOwner & Principle Developer/Designer

Author

Commented:
O.M.G. Wow!

I really need to systematically dig through WordPress hooks, actions and functions. There's something for everything!

Of course, I'm at the stage where I can't discern pseudo code from real code, but I had my suspicions about that line. LOL!

Okay, I'm going to play around with this!
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Of course, I'm at the stage where I can't discern pseudo code from real code
That was my fault - rushed answer I should have explained a bit more.
Alicia St RoseOwner & Principle Developer/Designer

Author

Commented:
No Worries!

Okay, So I played around with the code.

This is what I have:

add_action( 'save_post_chapter', 'myprefix_set_default_object_terms', 11, 2 );

function myprefix_set_default_object_terms( $post_id, $post ) {
	if ( 'publish' === $post->post_status ) {
		$position = 1;
		$args = array( 'post_type' => 'chapter', 'order' => 'DESC', 'orderby' => 'date');
		$posts = get_posts( $args );// query posts that are chapters in descending publish date order
		foreach($posts as $post) {
		 wp_delete_object_term_relationships($post->ID, 'member-type');
		  
		  $defaults = array(
					'member-type' => array('tier-1')
				);
		   if ($postion > 2) {
		      $defaults = array(
					'member-type' => array('tier-2')
				);
		   } 
		    
		   if ($postion > 4) {
		      $defaults = array(
					'member-type' => array('tier-3')
				);
		   }
			
		   $postion++;
		   
		   $taxonomies = get_object_taxonomies( $post->post_type );
				foreach ( (array) $taxonomies as $taxonomy ) {
					$terms = wp_get_post_terms( $post_id, $taxonomy );
					//$append = ! empty( $terms );
		
					if ( array_key_exists( $taxonomy, $defaults ) ) {
						// usage: wp_set_object_terms( $object_id, $terms, $taxonomy, $append );
						$term_taxonomy_ids = wp_set_object_terms( $post_id, $defaults[$taxonomy], $taxonomy);
		
						if ( is_wp_error( $term_taxonomy_ids ) ) {
							// There was an error somewhere and the terms couldn't be set.
						} else {
							// Success! These terms were added to the post.
						}					
					}
				}
			}
		}
	}

Open in new window


I've concluded:

1. I don't want to append the terms. I want it this way:

Most recent two: tier 3
2nd recent two: tier 2
least recent two: tier 1

The rest are no term

How the tiers should look in admin
I can't seem to get tier 3 to show up no matter what I do. And when i refresh the admin, the terms disappear.
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Change your if's to if elses

if (position <= 2) {
  $defaults = ['member-type' => ['tier-3']];
} else if (position <= 4) {
  $defaults = ['member-type' => ['tier-2']];
} else {
  $defaults = ['member-type' => ['tier-1']];
}

Open in new window

The above will assign tier-3 only to the newest 2 chapters, tier-2 to the next newest 2 and tier-1 to everything else.
Alicia St RoseOwner & Principle Developer/Designer

Author

Commented:
I'm getting Tier 3 for everything when I update. And when I refresh the page, position 1, 3, 4, 5 lose their terms.
I added taxonomy to the query arguments to see if that would help because there are two taxonomies connected to the post type. It didn't.

function myprefix_set_default_object_terms( $post_id, $post ) {
	if ( 'publish' === $post->post_status ) {
		$position = 1;
		$args = array( 'post_type' => 'chapter', 'order' => 'DESC', 'orderby' => 'date', 'taxonomy' => 'member-type');
		$posts = get_posts( $args );// query posts that are chapters in descending publish date order
		foreach($posts as $post) {
		 wp_delete_object_term_relationships($post->ID, 'member-type');
		  
		  if ($position <= 2) {
			  $defaults = ['member-type' => ['tier-3']];
			} else if ($position <= 4) {
			  $defaults = ['member-type' => ['tier-2']];
			} else {
			  $defaults = ['member-type' => ['tier-1']];
			}
			
		   $postion++;
		   
		   $taxonomies = get_object_taxonomies( $post->post_type );
				foreach ( (array) $taxonomies as $taxonomy ) {
					$terms = wp_get_post_terms( $post_id, $taxonomy );
					//$append = ! empty( $terms );
		
					if ( array_key_exists( $taxonomy, $defaults ) ) {
						// usage: wp_set_object_terms( $object_id, $terms, $taxonomy, $append );
						$term_taxonomy_ids = wp_set_object_terms( $post_id, $defaults[$taxonomy], $taxonomy);
		
						if ( is_wp_error( $term_taxonomy_ids ) ) {
							// There was an error somewhere and the terms couldn't be set.
						} else {
							// Success! These terms were added to the post.
						}					
					}
				}
			}
		}
	}

Open in new window

Most Valuable Expert 2017
Distinguished Expert 2018
Commented:
Some advice - when you get code from a forum that is not specifically advertised as working code then don't do a cut and paste. Look at what the code is trying to do and then implement it by typing it in.
What happened here is that the postion++ has a typo - so the position you were using was never getting incremented.

Having said that - I decided to put some working code together and this works
add_action( 'save_post_chapter', 'myprefix_set_default_object_terms', 11, 2 );
function myprefix_set_default_object_terms( $post_id, $post ) {
  if ( 'publish' === $post->post_status) {
    $position = 1;
    $args = [
      'numberposts' => -1,
      'order' => 'DESC',
      'orderby' => 'date',
      'post_type' => 'chapter',
      'taxonomy' => 'member_type'
    ];
    $posts = get_posts( $args );// query posts that are chapters in descending publish date order
    foreach($posts as $post) {
      if ($position <= 2) {
        wp_set_object_terms($post->ID, 'tier-3', 'member_type', false);
      } else if ($position <= 4) {
        wp_set_object_terms($post->ID, 'tier-2', 'member_type', false);
      } else {
        wp_set_object_terms($post->ID, 'tier-1', 'member_type', false);
      }
      
      $taxonomies = get_object_taxonomies( $post->post_type );
      
      $position++;
     }
  }
}

Open in new window

You will notice that I have removed the line
wp_delete_object_term_relationships($post->ID, 'member-type');

Open in new window

This is because the last parameter of
wp_set_object_terms($post->ID, 'tier-3', 'member_type', false);

Open in new window

Tells WP to replace ALL terms with the new ones you are submitting.
I have also removed the last few lines of your function in favour of calling wp_set_object_terms in the if statement directly.
Alicia St RoseOwner & Principle Developer/Designer

Author

Commented:
What happened here is that the postion++ has a typo

Oh geesh! I looked at that over and over again, too. I like the idea of typing it out. Maybe I can figure out what I'm doing along the way!

The code works really well and I even edited the "member_type" to "member-type". That's how I set up the taxonomy. I think I will lean towards underscores in the future.  AND...I was also able to add a free level for all chapters beyond 6!

I've got to do this for another project, except it's the opposite scenario, the latest 10 podcasts are public, but the archive is behind a paywall. I'll see if I can work this code and make that happen. It should be fairly easy. I need to add the term "premium" to every thing beyond 10.

I'll start another thread if I get stuck. LOL!
Alicia St RoseOwner & Principle Developer/Designer

Author

Commented:
One of the best Experts on EE. You consistently provide solutions that save the day! And I learn from each one! Thank you!
Most Valuable Expert 2017
Distinguished Expert 2018

Commented:
Thank you - and you are most welcome.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial