WIRED Day of REST 2016 Conference Presentation - Code Snippets
// Author: Ross Patton (abbreviated by KV) | |
// Link to WIRED json feed | |
var apiUrl = 'http://' + location.host + '/wp-json/wp/v2/posts/'; | |
// Fallback if OBR not available | |
if ( typeof OBR === 'undefined' ) { | |
$( getAll('poweredByOutbrain') ).remove(); | |
return $.getJSON( apiUrl, function(res) { | |
if ( elementId === 'we-recommend' ) { | |
return smart.rec( get('we-recommend') ); | |
} | |
} | |
} |
// Authors: Ross Patton, Kathleen Vignos, Tony Vongprachanh (abbreviated by KV) | |
smart = (function() { | |
/** | |
* @description functionality for latest news smart cards | |
*/ | |
var mostRecent = function( target ) { | |
var apiUrl = 'http://' + location.host + '/wp-json/wp/v2/posts/?_embed'; | |
function render( res ) { | |
var frag = document.createDocumentFragment(); | |
var data = res.slice( 0, 5 ); | |
data.forEach(function( value, i ) { | |
var currLi = document.createElement('li'); | |
var currAnchor = document.createElement('a'); | |
var currImg = document.createElement('img'); | |
var currAuth = document.createElement('span'); | |
var currTitle = document.createElement('h5'); | |
var postWrap = document.createElement('div'); | |
var currHr = document.createElement('hr'); | |
currLi.setAttribute( 'height', '108' ); | |
currLi.className = 'story-' + i; | |
// hides final 2 li if ad is tall | |
if ( i > 2 ) { | |
currLi.className += ' squish-hide'; | |
currHr.className += ' squish-hide'; | |
} | |
// create the anchor tag | |
currAnchor.setAttribute( 'href', value.link ); | |
currAnchor.className = 'clearfix pad'; | |
// create the img node | |
currImg.setAttribute( 'height', '75' ); | |
currImg.setAttribute( 'width', '75' ); | |
currImg.setAttribute( 'aria-hidden', 'true' ); | |
currImg.setAttribute( 'role', 'presentation' ); | |
currImg.className = 'thumb col mob-col-6 med-col-6 big-col-6'; | |
postWrap.className = 'col mob-col-12 med-col-12 big-col-12'; | |
currAuth.className = 'byline marg-b-micro'; | |
currAuth.appendChild( | |
document.createTextNode( value._embedded.author[0].name ) | |
); | |
currTitle.className = 'title exchange-sm'; | |
currTitle.innerHTML = value.title.rendered; | |
// currTime.className = 'marg-t-sm'; | |
// currTime.insertAdjacentHTML( 'beforeend', value.date_gmt ); | |
// append all these things together into the li | |
currLi.appendChild( currAnchor ); | |
currAnchor.appendChild( currImg ); | |
currAnchor.appendChild( postWrap ); | |
postWrap.appendChild( currAuth ); | |
postWrap.appendChild( currTitle ); | |
currHr.className = 'story-' + i; | |
// append everything to the frag | |
frag.appendChild( currLi ); | |
frag.appendChild( currHr ); | |
}); | |
// append frag to the dom | |
return target.appendChild( frag ); | |
} | |
return $.getJSON( apiUrl, render ); | |
}; | |
// expose | |
return { | |
rec: mostRecent | |
}; | |
}()); |
{ | |
"role": "container", | |
"style": { | |
"backgroundColor": "#e1e1e1" | |
}, | |
"layout": "fullNoMarginIgnore", | |
"components": [ | |
{ | |
"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." | |
}, | |
{ | |
"path": "http://www.wired.com/wp-content/uploads/2016/01/CES_08-NEW-NEW2.jpg", | |
"URL": "bundle://CES_08-NEW-NEW2.jpg", | |
"caption": "CES's infamous \"booth babes\" were, of course, back for 2016." | |
} | |
] | |
} | |
] | |
}, |
{ | |
"role": "container", | |
"style": { | |
"backgroundColor": "#e1e1e1" | |
}, | |
"layout": "fullNoMarginIgnore", | |
"components": [ | |
{ | |
"role": "container", | |
"style": { | |
"backgroundColor": "#FFFFFF" | |
}, | |
"layout": "textBgContainerLayout", | |
"components": [ | |
{ | |
"role": "divider", | |
"layout": "thickTopDividerLayout", | |
"stroke": { | |
"color": "#000000", | |
"width": 25 | |
} | |
}, | |
{ | |
"role": "body", | |
"identifier": "textContainerWrap3", | |
"layout": "textContainerLayout", | |
"text": " You have to see CES to believe it. It's a mammoth show, spanning many days and multiple hotels and convention floors. But it's not just pure digital chaos; it's also something of a kitschy circus of humanity. People walk the floor, hoping to try the latest hot new things...and then fall asleep on the pavement outside the show. A big and beautiful neon mess, one that's better understood visually.", | |
"format": "markdown" | |
} | |
] | |
} | |
] | |
}, |
"content": { | |
"rendered": "<p>You have to see CES to believe it. It’s a mammoth show, spanning many days and multiple hotels and convention floors. But it’s not just pure digital chaos; it’s also something of a kitschy circus of humanity. People walk the floor, hoping to try the latest hot new things…and then fall asleep on the pavement outside the show. A big and beautiful neon mess, one that’s better understood visually.</p>\n" | |
}, |
<?php | |
// Authors: Jake Spurlock and Kathleen Vignos (abbreviated by KV) | |
/** | |
* Register the Apple News endpoints | |
*/ | |
public function register_production_routes( $routes ) { | |
// Download a zip of all of the article assets. | |
register_rest_route( 'apple-news/v2', '/post/(?P<post_id>[\w-]+)/zip', array( | |
'methods' => WP_REST_Server::READABLE, | |
'callback' => array( $this, 'rest_download_zip' ), | |
'args' => array( | |
'post_id', | |
), | |
) ); | |
// Rendered post info for Apple News | |
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', | |
), | |
) ); | |
// Get the article from Apple. This is the full data representation. | |
register_rest_route( 'apple-news/v2', '/article/(?P<post_id>[\w-]+)', array( | |
'methods' => WP_REST_Server::READABLE, | |
'callback' => array( $this, 'rest_get_article' ), | |
'args' => array( | |
'post_id', | |
), | |
) ); | |
} |
<?php | |
// Author: Zack Tollman (abbreviated by KV) | |
// **USES JSON REST API V1, written in late 2014 *** | |
public function __construct() { | |
// Push late to make sure all updates have executed | |
add_action( 'wp_insert_post', array( $this, 'notify_beta_site_post' ), 100, 3 ); | |
} | |
/** | |
* Notify the beta site that a data change has been made. | |
*/ | |
public function notify_beta_site_post( $post_id, $post, $update ) { | |
// Check the user's permissions. | |
if ( isset( $_POST['post_type'] ) && 'page' == $_POST['post_type'] ) { | |
if ( ! current_user_can( 'edit_page', $post_id ) ) { | |
return; | |
} | |
} else { | |
if ( ! current_user_can( 'edit_post', $post_id ) ) { | |
return; | |
} | |
} | |
$this->update_object( $post_id, 'post' ); | |
} | |
/** | |
* Make the request to update the post. | |
* | |
*/ | |
public function update_object( $post_id, $object ) { | |
$this->make_request( $post_id, $object ); | |
} | |
/** | |
* Make a request to prompt data scraping. | |
*/ | |
public function make_request( $id, $object ) { | |
// Get the request URL | |
// example: 'http://www.wired.com/?beta-push=1'; | |
$request_url = $this->get_request_url(); | |
// Prepare the arguments for the request | |
$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, | |
); | |
// Post the request | |
$result = wp_remote_post( | |
$request_url, | |
$request_args | |
); | |
} |
<?php | |
// Author: Zack Tollman (abbreviated by KV) | |
// **USES JSON REST API V1, written in late 2014 *** | |
public function __construct() { | |
add_action( 'init', array( $this, 'route_pull_request' ), 11 ); | |
} | |
/** | |
* Monitor for a request to pull data. | |
*/ | |
public function route_pull_request() { | |
if ( ! $this->validate_request() ) { | |
return; | |
} | |
// Get the data needed to pull data | |
$id = $this->get_request_id(); | |
$object = $this->get_request_object(); | |
$data = $this->get_data( $id, 'post' ); | |
$result = $this->save_response_post( $id, $data ); | |
exit(); | |
} | |
/** | |
* Get the ID of the object being requested. | |
* | |
* @return int The post ID requesting a pull. | |
*/ | |
public function get_request_id() { | |
// Get the content of the request | |
$body = $this->$this->body; | |
return (int) $body['id']; | |
} | |
/** | |
* Get the type of object being requested. | |
* | |
* @return string The object type requesting a pull. | |
*/ | |
public function get_request_object() { | |
// Get the content of the request | |
$body = $this->$this->body; | |
return $body['object']; | |
} | |
/** | |
* Validate that a request for a pull has been received. | |
* | |
* @return bool True if the request is for a pull; false if it is not. | |
*/ | |
public function validate_request() { | |
if ( isset( $_GET['beta-push'] ) && 1 === (int) $_GET['beta-push'] ) { | |
$headers = getallheaders(); | |
$headers_present = false !== $headers; | |
$authed = isset( $headers['api-key'], $headers['api-secret'] ) && ( DATA_PUSH_API_KEY === $headers['api-key'] ) && ( DATA_PUSH_API_SECRET === $headers['api-secret'] ); | |
if ( $headers_present && $authed ) { | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* Make a request to grab data for an object. | |
* | |
* @param int $id The ID of the object to get. | |
* @param string $object The type of the object to get. | |
* @return array The data for the request. | |
*/ | |
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 | |
// Make the JSON request | |
$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 right | |
if ( isset( $body['ID'], $body['title'] ) ) { | |
$data = $body; | |
} | |
} | |
return $data; | |
} | |
/** | |
* Save the data for the post. | |
*/ | |
public function save_response_post( $id, $data ) { | |
$existing_post = get_post( $id ); | |
$prepared_data = $this->prepare_post_data( $data, $id ); | |
// Now, save the post itself | |
if ( empty( $existing_post ) ) { | |
// If the "ID" value is set, the method will think it's an update | |
if ( isset( $prepared_data['ID'] ) ) { | |
unset( $prepared_data['ID'] ); | |
} | |
$result = wp_insert_post( $prepared_data ); | |
} else { | |
// Update an existing post | |
$result = wp_update_post( $prepared_data ); | |
} | |
// Save the post meta | |
if ( is_int( $result ) && $result > 0 ) { | |
if ( isset( $data['post_meta'] ) ) { | |
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; | |
} | |
/** | |
* Map JSON data to what is expected in wp_insert_post and wp_update_post. | |
*/ | |
public function prepare_post_data( $data, $id = 0 ) { | |
// Prepare the data to insert | |
$postarr = array( | |
// Defaults | |
'post_status' => $data['status'], | |
'post_type' => $data['type'], | |
'post_author' => $data['author']['ID'], | |
'ping_status' => $data['ping_status'], | |
'post_parent' => $data['parent'], | |
'menu_order' => $data['menu_order'], | |
'guid' => $data['guid'], | |
'post_excerpt' => $this->$data['excerpt_raw'], | |
'post_content' => $this->$data['content_raw'], | |
'post_title' => $data['title'], | |
'context' => '', | |
// Non-defaults | |
'post_name' => $data['slug'], | |
'post_date' => date_create( $data['date'] )->format( 'Y-m-d H:i:s' ), | |
'post_date_gmt' => date_create( $data['date_gmt'] )->format( 'Y-m-d H:i:s' ), | |
'comment_status' => $data['comment_status'], | |
); | |
// Append the post ID if it was passed | |
if ( absint( $id ) > 0 ) { | |
$postarr['ID'] = absint( $id ); | |
$postarr['import_id'] = absint( $id ); | |
} | |
return $postarr; | |
} |
// Author: Zack Tollman (abbreviated by KV) | |
/** | |
* Send request to add a post to WordPress. | |
*/ | |
var addPost = function(preparedMessage, authorID) { | |
return new Promise( function(resolve, reject) { | |
// 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 | |
} | |
} | |
), | |
function(err, httpResponse, body) { | |
if (err) { | |
log.info(err); | |
reject(err); | |
} else if (httpResponse.statusCode === 201 && body.id) { | |
log.info('Added post ' + body.id); | |
resolve(body.id); | |
} | |
reject(body); | |
} | |
); | |
}); | |
}; |
<?php | |
// Author: Zack Tollman (abbreviated by KV) | |
public function __construct() { | |
add_action( 'rest_api_init', array( $this, 'register_routes' ) ); | |
} | |
/** | |
* Register the API routes for the liveblogs. | |
*/ | |
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 objects | |
register_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', | |
), | |
) ); | |
} | |
/** | |
* Get the individual posts associated with a liveblog. | |
*/ | |
public function get_liveblog_posts( $post_id ) { | |
$clean_posts = array(); | |
$liveblog_meta = get_post_meta( $post_id, '_liveblog', true ); | |
$channel = ( ! empty( $liveblog_meta['slack-channel-name'] ) ) ? $liveblog_meta['slack-channel-name'] : ''; | |
if ( ! empty( $channel ) ) { | |
// Query for the posts | |
$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' => $channel, | |
) | |
) | |
) ); | |
if ( $query->have_posts() ) { | |
while ( $query->have_posts() ) { | |
$query->the_post(); | |
$img_url = ''; | |
$thumb_id = get_post_thumbnail_id( get_the_ID() ); | |
if ( $thumb_id ) { | |
$img = wp_get_attachment_image_src( $thumb_id, '660-single-full' ); | |
if ( ! empty( $img[0] ) ) { | |
$img_url = esc_url( $img[0] ); | |
} | |
} | |
$clean_posts[] = array( | |
'id' => get_the_ID(), | |
'body' => apply_filters( 'the_content', get_the_content() ), | |
'author' => esc_attr( wp_strip_all_tags( $this->get_liveblog_byline( get_the_ID(), $post_id ) ) ), | |
'caption' => '', | |
'text' => '', // Likely can remove this | |
'source' => '', | |
'embed' => '', | |
'imgSrc' => esc_url( $img_url ), | |
'date' => get_the_date( 'm-d-Y' ), | |
'time' => get_the_date( 'h:i:s' ), | |
'zone' => 'PDT', | |
); | |
} | |
} | |
wp_reset_postdata(); | |
} | |
return $clean_posts; | |
} | |
/** | |
* Return the posts. | |
*/ | |
public function posts_callback( $request ) { | |
$posts = ''; | |
$params = $request->get_params(); | |
$post_id = ( isset( $params['post_id'] ) ) ? absint( $params['post_id'] ) : 0; | |
$liveblog_meta = get_post_meta( $post_id, '_liveblog', true ); | |
$posts = array( | |
'version' => time(), | |
'posts' => $this->get_liveblog_posts( $post_id ) | |
); | |
return $posts; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment