wired and the wp rest api
TRANSCRIPT
KATHLEEN VIGNOS@kathleencodes
WIRED and the WP REST API
IN THE LOOP? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
IN THE LOOP? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
IN THE LOOP? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
THIRD PARTY? CUSTOM JSON?
SYNCH’ING? EXTERNAL? SPA?
LATEST NEWS?
? ??
? ? ?
NOPE.IN THE LOOP?
IN THE LOOP? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
LATEST NEWS?
LATEST NEWS?
IN THE LOOP? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
Example: Latest News
• WIRED module used everywhere
• WP REST API req’d additional HTTP request
• needs deduping (sometimes)
LATEST NEWS?
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
YES. ELEMENTARY,
MY DEAR.THIRD PARTY?
GET REQUEST TO /POSTS/ ENDPOINT
WELL, SORT OF
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
Example:
• include vendor js • add outbrain data attributes
• fallback: WP REST API
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
var apiUrl = 'http://' + location.host + '/wp-json/wp/v2/posts/';
// Fallback if OBR not availableif ( typeof OBR === 'undefined' ) {
$( getAll('poweredByOutbrain') ).remove();
return $.getJSON( apiUrl, function(res) {if ( elementId === 'we-recommend' ) {
return smart.rec( get('we-recommend') );}
}}
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
smart = (function() {var mostRecent = function( target, apiUrl ) {
function render( res ) {var frag = document.createDocumentFragment();var data = res.slice( 0, 5 );
data.forEach(function( value, i ) {var currLi = document.createElement('li');....frag.appendChild( currLi );
});return target.appendChild( frag );
}return $.getJSON( apiUrl, render );
};return {
rec: mostRecent};
}());
YES, WITH MY CONDOLENCESCUSTOM JSON?
GET REQUEST TO CUSTOMENDPOINT
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?LATEST NEWS?
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
Example:
• Custom endpoint • Parse WP post content to markdown
• Output in Apple Native Format
LATEST NEWS?
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
register_rest_route( 'apple-news/v2', '/post/(?P<post_id>\w+)', array('methods' => WP_REST_Server::READABLE,'callback' => array( $this, 'rest_post_output' ),'args' => array(
'bundle','images','template',
),) );
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
Apple News Plugin ParserWP DB
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
Apple News Plugin Parser Apple News Custom JSON
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
Apple News Plugin Parser Apple News Custom JSON
{ "role": "gallery", "layout": "carouselLayoutNoTop", "items": [ { "path": "http://www.wired.com/wp-content/uploads/2016/01/CES_07-NEW-NEW2.jpg", "URL": "bundle://CES_07-NEW-NEW2.jpg", "caption": "Drones as far as the eye can see." }, { "path": "http://www.wired.com/wp-content/uploads/2016/01/CES_11-NEW-NEW2.jpg", "URL": "bundle://CES_11-NEW-NEW2.jpg", "caption": "There are still some old-school immersion tactics. This attendee is sitting through a pre-programmed routine to lower his heart rate and help him feel more relaxed." } ]}
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
Apple News Preview (simulators)Apple News Custom JSON
YEP, WE CAN AUTOMATE
THATSYNCH’ING?
POST REQUEST TO CREATE POSTS ON
PUBLISH HOOK
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?LATEST NEWS?
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
Example: Betta Beta Data Getta
• Publish/update hook • Make POST request via WP REST API with post_id
LIVE: www.wired.com
BETA: beta.wired.com
1. data-push
1
LATEST NEWS?
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
Example: Betta Beta Data Getta
• Validate request • Make GET request via WP REST API for post_id
• Create post
LIVE: www.wired.com
BETA: beta.wired.com
2. data-pull
2
LATEST NEWS?
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
public function __construct() {add_action( 'wp_insert_post', array( $this, 'notify_beta_site_post' ),
100, 3 );}
public function notify_beta_site_post( $post_id, $post, $update ) {$this->update_object( $post_id, 'post' );
}
public function update_object( $post_id, $object ) {$this->make_request( $post_id, $object );
}
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
public function make_request( $id, $object ) {// example: 'http://beta.wired.com/?beta-push=1';$request_url = $this->get_request_url();$request_args = array(
'body' => array('id' => absint( $id ),'object' => $object,
),'headers' => array(
'api-key' => DATA_PUSH_API_KEY,'api-secret' => DATA_PUSH_API_SECRET,
),'blocking' => false,
);$result = wp_remote_post(
$request_url,$request_args
);}
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
public function __construct() {add_action( 'init', array( $this, 'route_pull_request' ), 11 );
}
public function route_pull_request() {if ( ! $this->validate_request() ) {
return;}
$id = $this->get_request_id();$object = $this->get_request_object(); // ex: ‘post’$data = $this->get_data( $id, 'post' );$result = $this->save_response_post( $id, $data );exit();
}
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
public function get_data( $id, $object ) {$data = array();$request_url = get_request_url_post( $id );// example: https://www.wired.com/wp-json/posts/1234567?context=edit
$response = wp_remote_get($request_url,array_merge(
$args)
);if ( 200 === (int) wp_remote_retrieve_response_code( $response ) ) {
$body = json_decode( wp_remote_retrieve_body( $response ), true );// Check to make sure the data looks rightif ( isset( $body['ID'], $body['title'] ) ) {
$data = $body;}
}return $data;
}
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
public function save_response_post( $id, $data ) {$existing_post = get_post( $id );$prepared_data = $this->prepare_post_data( $data, $id );
if ( empty( $existing_post ) ) {$result = wp_insert_post( $prepared_data );
} else {$result = wp_update_post( $prepared_data );
}
foreach ( $data['post_meta'] as $meta ) {// Note that this will break serialized meta data. Our meta data
does not include serialized meta data.update_post_meta( $result, $meta['key'], $this->$meta['value'] );
}return $result;
}
SURE, LET’S GET CREATIVE!EXTERNAL?
POST REQUEST TO CREATE
POSTS WITH AUTH
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?LATEST NEWS?
IN THE LOOP? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
Example: • Node application listens for requests from Slack
• Bot invited to channel • Every comment or image creates a “liveblog update” post type via WP REST API
• WP template w/ React updates content
Liveblog
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
WP DBNode Serverslack
IN THE LOOP? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
var addPost = function(preparedMessage, authorID) { return function() { // example wpAPIUrl: http://www.wired.com/wp-json/ request( extend( requestBase, { method: 'POST', uri: config.wpAPIUrl() + '/liveblog', body: { type: 'liveblog', status: 'publish', title: preparedMessage.ts, content: preparedMessage.text, author: authorID, featured_image: (preparedMessage.featuredImageID) ? preparedMessage.featuredImageID : 0 } }...
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
public function __construct() {add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}public function register_routes() {
// example: http://www.wired.com/wp-json/wired/v2/liveblog/1949283/posts/
// React script hits this endpoint to grab the post objectsregister_rest_route( 'wired/v2', '/liveblog/(?P<post_id>\w+)/posts',
array('methods' => WP_REST_Server::READABLE,'callback' => array( $this, 'posts_callback' ),'args' => array(
'post_id',),
) );}
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
public function posts_callback( $request ) {$posts = '';$params = $request->get_params();$post_id = ( isset( $params['post_id'] ) ) ?
absint( $params['post_id'] ) : 0;$posts = array(
'version' => time(),'posts' => $this->get_liveblog_posts( $post_id )
);return $posts;
}
LATEST NEWS? THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
public function get_liveblog_posts( $post_id ) {$liveblog_meta = get_post_meta( $post_id, '_liveblog', true );$query = new WP_Query( array(
'posts_per_page' => 500,'post_type' => array( wired_get_liveblog_post()->post_type ),'tax_query' => array( array(
'taxonomy' => wired_get_liveblog_post()->taxonomy,'field' => 'name','terms' => $liveblog_meta['slack-channel-name'],
))) );if ( $query->have_posts() ) {
while ( $query->have_posts() ) {$query->the_post();$clean_posts[] = array(
'id' => get_the_ID(),...
);}}wp_reset_postdata();return $clean_posts;
}
YES, BECAUSE #NODEJSSPA? JSON OBJECTS
#FTW!
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?LATEST NEWS?
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?LATEST NEWS?
Example: Homepage Curator (in the future)
• Dashboard: Replace WP posts admin table ajax with SPA using React components
• Create custom WP REST API endpoint for homepage and all section fronts
• Front end: Build homepage and section fronts with React components
• Ability to swipe from section to section without reload
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?LATEST NEWS?
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?LATEST NEWS?
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?LATEST NEWS?
THIRD PARTY? CUSTOM JSON?
SYNCH’ING? EXTERNAL? SPA?
LATEST NEWS?
NOPE. WELL, SORT OF. YES, WITH MY CONDOLENCES
YEP, WE CAN AUTOMATE
THAT
SURE, LET’S GET CREATIVE!
YES, BECAUSE #NODEJS
THIRD PARTY? CUSTOM JSON? SYNCH’ING? EXTERNAL? SPA?
All Code Samples in this Gist:http://bit.ly/day-of-rest-2016-kv
Slides:http://www.slideshare.net/kvignos/wired-and-the-wp-rest-api
LATEST NEWS?
KATHLEEN VIGNOS@kathleencodes
THANK YOU!