How To

REST API On This Day

Extending the existing API to do another thing.

After making a simple REST API output that showed the date (and time since) the last death listed on a site, I had an idea. What if I could list everyone who died on a specific day? I had that data after all, so why not.

A Word About Evolution of Code A Word About Evolution of Code

Over time, the code behind my “Bury Your Characters” plugin evolved a great deal. I went from unique function names to singletons to one aspect and now to two. The design changed a lot in the middle as well. I unpacked the parsing of data from being on the data driven site and moved that to the site running the plugin.

The evolution of all this was for a simple reason. I wanted the JSON output to be generated as fast as possible, grabbed, and parsed locally. If the data takes less time to generate on my end, then the speed becomes more of a factor of how fast can the end-user’s site run. That would allow more people to use my plugin.

A secondary bonus reason was that I hate repeating myself in code. If I only have one place to update my code that generates the list of dead characters, for example, then there are fewer odds I’ll screw up and only edit one of the six places it gets used.

This means that the code I posted last week doesn’t look at all like that anymore.

Top ↑

On My Site (aka The Service) On My Site (aka The Service)

In a file called bury-your-queers.php (yes, this is for that site) I have a class called LWTV_BYQ_JSON.

In that class I have a constructor that calls the rest_api_init and that’s where I define my URLs. I already had the last-death set, so now I’ve added in two more for on-this-day:

	public function rest_api_init() {
		register_rest_route( 'lwtv/v1', '/last-death', array(
			'methods' => 'GET',
			'callback' => array( $this, 'last_death_rest_api_callback' ),
		) );
		register_rest_route( 'lwtv/v1', '/on-this-day/', array(
			'methods' => 'GET',
			'callback' => array( $this, 'on_this_day_rest_api_callback' ),
		) );
		register_rest_route( 'lwtv/v1', '/on-this-day/(?P<date>[\d]{2}-[\d]{2})', array(
			'methods' => 'GET',
			'callback' => array( $this, 'on_this_day_rest_api_callback' ),
		) );

The reason I have two for my new route is that I wanted both the main URL and the sub URL to work. That is /lwtv/v1/on-this-day/ and /lwtv/v1/on-this-day/03-03/ both work. They both call the same callback which checks what was passed to it. If the params for date are empty, it assumes today:

	public function on_this_day_rest_api_callback( $data ) {
		$params = $data->get_params();
		$this_day = ( $params['date'] !== '' )? $params['date'] : 'today';
		$response = $this->on_this_day( $this_day );
		return $response;

The callback grabs the function on_this_day(), passing the date through to it. Now this is the first BIG change. I pulled the code to generate the list of all the dead out of the function for last_death because it’s called twice. Now it calls LWTV_Loops::post_meta_query which is just a class for all my common loops that get reused a lot. They’re no faster than making the query the regular way, they’re just neater and tidier.

	public static function on_this_day( $this_day = 'today' ) {

		if ( $this_day == 'today' ) {
			$this_day = date('m-d');

		// Get all our dead queers
		$dead_chars_loop  = LWTV_Loops::post_meta_query( 'post_type_characters', 'lezchars_death_year', '', 'EXISTS' );
		$dead_chars_query = wp_list_pluck( $dead_chars_loop->posts, 'ID' );
		$death_list_array = self::list_of_dead_characters( $dead_chars_query, $dead_chars_loop );

		$died_today_array = array();

		foreach ( $death_list_array as $the_dead ) {
			if ( $this_day == date('m-d', $the_dead['died'] ) ) {
				$died_today_array[ $the_dead['slug'] ] = array(
					'slug' => $the_dead['slug'],
					'name' => $the_dead['name'],
					'url'  => $the_dead['url'],
					'died' => date( 'Y', $the_dead['died'] ),

		if ( empty( $died_today_array ) ) {
			$died_today_array[ 'none' ] = array(
				'slug' => 'none',
				'name' => 'No One',
				'url'  => site_url( '/cliche/dead/' ),
				'died' => date('m-d'),

		$return = $died_today_array;
		return $return;

Output Output

And all that works to output this (if you pick 03-03):

{"alisa-davies":{"slug":"alisa-davies","name":"Alisa Davies","url":"https:\/\/\/character\/alisa-davies\/","died":"2010"},"lexa":{"slug":"lexa","name":"Lexa","url":"https:\/\/\/character\/lexa\/","died":"2016"}}

or this (if you pick a date where no one died):

{"none":{"slug":"none","name":"No One","url":"https:\/\/\/cliche\/dead\/","died":"02-19"}}

Unlike what I did for ‘last death’, here I’m only reporting the year. The reason is that’s all I care about just now. I’m passing the date through, so I don’t need that information anymore.

Top ↑

On Your Site (aka The Plugin) On Your Site (aka The Plugin)

The plugin for this has three classes. The first is the master class to build out the widgets and shortcodes and also to parse the data. The other two are for the widgets.

Parsing the data is what we’re going to talk about today.

The function is straightforward. You pass the date to the function, it grabs the data for the date (defaulting to ‘today’ if none is provided) and spit out the resulting data:

	public static function on_this_day( $this_day = 'today' ) {
		$echo_day = ( $this_day == 'today' )? time() : strtotime( date('Y').'-'.$this_day );
		$json_day = ( $this_day == 'today' )? '' : $this_day.'/' ;

		$request  = wp_remote_get( ''.$json_day );
		$response = wp_remote_retrieve_body( $request );
		$response = json_decode($response, true);

		$count = ( key($response) == 'none' )? 0 : count($response) ;
		$how_many = __('no characters died!', 'bury-your-queers');
		$the_dead = '';

		if ( $count > 0 ) {
			$how_many = sprintf( _n( '%s character died:', '%s queer female characters died:', $count, 'bury-your-queers' ), $count );

			$the_dead = '<ul class="byq-otd">';
			foreach ( $response as $dead_character ) {
				$the_dead .= '<li><a href="'.$dead_character['url'].'">'.$dead_character['name'].'</a> - '.$dead_character['died'] .'</li>';
			$the_dead .= '</ul>';

		$onthisday = '<p>'. sprintf( __( 'On %s, %s', 'bury-your-queers'), date('F jS', $echo_day ), $how_many ).'</p>';
		$return = $onthisday.$the_dead;

		return $return;

I picked paragraphs and un-ordered lists, since I feel those would be easily formatted by most people.