I wanted to get a list of all TV shows where 100% of the listed characters were dead.
@Ipstenu … Did I just read that you’re using WordPress to compose a list of dead lesbians in media? I have to say, that’s kind of unique.
— Otto42
Yes, yes I am. Television media, excluding reality TV.
The problem is I store the information in two Custom Post Types (shows and characters). And while both shows and characters have a way to track if there are dead, getting that list was frustratingly complicated.
We wanted, originally, a way to mark a show as having death and a separate way to track each dead character. Since they were separate CPTs, we made two custom taxonomies: dead-character and death. Logically then, I could use WP Query to get a list of all shows with the cliche taxonomy field of ‘death’ checked:
$dead_shows_query = new WP_Query ( array( 'post_type' => 'post_type_shows', 'posts_per_page' => -1, 'post_status' => array( 'publish', 'draft' ), 'tax_query' => array( array( 'taxonomy' => 'cliches', 'field' => 'slug', 'terms' => 'death', ), ), ) );
I know I could use a different way to get terms, but I don’t want to since I need to count these shows:
$count_dead_shows = $dead_shows_query->post_count;
But I also need to continue processing. Once I have a list of shows with death, I need to get a list of all characters who are on the show. That data is stored as Custom Meta Data and those don’t have a quick and easy sort method. Worse, the shows are listed as an array.
Originally it was just a number representing the post ID for the show, and that was pretty easy to check. While we have posts in the dead show query, get a list of all characters with this ‘show ID’ which looks like this:
while ( $dead_shows_query->have_posts() ) { $dead_shows_query->the_post(); $show_id = $post->ID; $character_death_loop = new WP_Query( array( 'post_type' => 'post_type_characters', 'post_status' => array( 'publish', 'draft' ), 'orderby' => 'title', 'order' => 'ASC', 'posts_per_page' => '-1', 'meta_query' => array( array( 'key' => 'the_show', 'value' => $show_id, 'compare' => '=', ),), ) ); if ($character_death_loop->have_posts() ) { [... do all the magic here ...] wp_reset_query(); } }
The problem is that compare line. Once you stop looking for “Does 123 == 123” you have to use ‘IN’ or ‘LIKE’ and, since this is an array of show IDs, we need 'compare' => 'LIKE'
for this check. That sounds simple, but there’s one more small problem. If the show ID is 1, then every single show with a 1 in it shows up. In addition, I actually wanted to get a list of all the shows where some characters died, so I couldn’t just check for characters with the meta_query of the show and the tax_query of death.
My first step in all this was to convert the shows to an array:
if ( !is_array (get_post_meta($post->ID, 'lezchars_show', true)) ) { $shows_array = array( get_post_meta($post->ID, 'lezchars_show', true) ); } else { $shows_array = get_post_meta($post->ID, 'lezchars_show', true); }
Now I can process everything as an array and check if the show ID is really in the array. If it is, we’re going to record that there is a character in a show with death.
if ( in_array( $show_id, $shows_array ) ) { $chardeathcount++; }
Next we’re going to check if the character has the tag ‘dead-character’ (listed as a custom taxonomy for ‘show cliches’) or not and is in the show:
if ( has_term( 'dead-character', 'cliches', $post->ID ) && in_array( $show_id, $shows_array ) ) { $fulldeathcount++; }
Once we have that data, I need two arrays. The first is for shows where the count of all characters on the show is the same as the ones who are dead. The second is for shows where some characters are dead:
if ( $fulldeathcount == $chardeathcount ) { $fullshow_death_array[$show_id] = array( 'url' => get_permalink( $show_id ), 'name' => get_the_title( $show_id ), 'status' => get_post_status( $show_id ), ); } elseif ( $fulldeathcount > '0' && $fulldeathcount <= $chardeathcount ) { $someshow_death_array[$show_id] = array( 'url' => get_permalink( $show_id ), 'name' => get_the_title( $show_id ), 'status' => get_post_status( $show_id ), );
The full code for that magical snippage looks like this:
$fulldeathcount = 0; $chardeathcount = 0; while ($character_death_loop->have_posts()) { $character_death_loop->the_post(); if ( !is_array (get_post_meta($post->ID, 'lezchars_show', true)) ) { $shows_array = array( get_post_meta($post->ID, 'lezchars_show', true) ); } else { $shows_array = get_post_meta($post->ID, 'lezchars_show', true); } if ( in_array( $show_id, $shows_array ) ) { $chardeathcount++; } if ( has_term( 'dead', 'tropes', $post->ID ) && in_array( $show_id, $shows_array ) ) { $fulldeathcount++; } } if ( $fulldeathcount == $chardeathcount ) { $fullshow_death_array[$show_id] = array( 'url' => get_permalink( $show_id ), 'name' => get_the_title( $show_id ), 'status' => get_post_status( $show_id ), ); } elseif ( $fulldeathcount >= '1' && $fulldeathcount <= $chardeathcount ) { $someshow_death_array[$show_id] = array( 'url' => get_permalink( $show_id ), 'name' => get_the_title( $show_id ), 'status' => get_post_status( $show_id ), ); }
And yes, it works just fine.