Skip to content

Instantly share code, notes, and snippets.

@kvignos
Last active May 8, 2017 05:50
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kvignos/fe24201fa2f972dde67e to your computer and use it in GitHub Desktop.
Save kvignos/fe24201fa2f972dde67e to your computer and use it in GitHub Desktop.
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": "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&#8217;s a mammoth show, spanning many days and multiple hotels and convention floors. But it&#8217;s not just pure digital chaos; it&#8217;s also something of a kitschy circus of humanity. People walk the floor, hoping to try the latest hot new things&#8230;and then fall asleep on the pavement outside the show. A big and beautiful neon mess, one that&#8217;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