connecting content silos: one cms, many sites with the wordpress rest api
TRANSCRIPT
@Josh412
Connecting Content Silos: One CMS, Many
Sites With The WordPress REST API
@Josh412
CalderaLabs.org
Hi I'm JoshLead Developer: CalderaWP
I make WordPress pluginsI teach about WordPressI wrote a book about the WordPress REST APII am core contributor to WordPressI am a member of The WPCrowd
@Josh412
CalderaLabs.org
Introduction:What Is The REST API?
And why do we care?
@Josh412
CalderaLabs.org
The WordPress REST API Is Two Things
@Josh412
REST API Infrastructure Tools for making REST APIs with WordPress
Included in WordPress 4.4+
The WordPress REST API
Default RoutesWordPress CRUD via REST API
for WordPress content
wordpress.org/plugins/rest-api
@Josh412
Using The REST API For Posts
yoursite.com/wp-json/wp/v2/postsFirst page of posts
yoursite.com/wp-json/wp/v2/posts?page=2Second page of post
yoursite.com/wp-json/wp/v2/posts/42Post 42
@Josh412
Learn More: Basics
Course:learn.JoshPress.net
Book:JPWP.me/rest-book
More:JoshPress.net/rest-api
@Josh412
CalderaLabs.org
Introduction:Strategies For
Combining CMSsWhy Do We Want To Do This?
@Josh412
Ways To Combine Posts
With REST API
Client-sideServer-side
Other Ways
RSSDatabase syncScrape content
@Josh412
CalderaLabs.org
Example One:JavaScript + Static
HTMLWhat If We Have No CMS?
@Josh412
CalderaLabs.org
Why Client-side?No database, no server-side-
scripting?No Problem!
@Josh412
CalderaLabs.org
Why Client-side?Local Storage!
@Josh412
var posts1, posts2, posts;
$.get( 'https://calderawp.com/wp-json/wp/v2/posts' ).done( function( r ){
posts1 = r;
});
$.get( 'https://IngotHQ.com/wp-json/wp/v2/posts' ).done( function( r ){
posts2 = r;
});
//errors are about to happen
posts = posts1.concat( posts2 );
console.log( posts );
Promises Will Be Needed!
@Josh412
Promises
$.when( //one or more functions that return a promise ).then( function(){
//stuff to do after all promises are resolved
});
@Josh412
Promises
var posts;
$.when(
$.get( 'https://calderawp.com/wp-json/wp/v2/posts' ).done( function( r ){
return r;
}),
$.get( 'https://IngotHQ.com/wp-json/wp/v2/posts' ).done( function( r ){
posts2 = r;
}) ).then( function( d1, d2 ) {
posts = d1[0].concat( d2[0] );
console.log( posts );
});
@Josh412
API For AJAX and Local Storage
function api( url ) {
var key = 'clCachez' + url.replace(/^https?\:\/\//i, "");
var local = localStorage.getItem( key );
//this line uses underscores.js!!
if ( ! _.isString( local ) || "null" == local ) {
return $.get( url ).then( function ( r ) {
localStorage.setItem( key, JSON.stringify( r ) );
return r;
} );
} else {
return JSON.parse( local );
}
};
@Josh412
Sorting
function merge( obj1, obj2 ) {
var merged;
a1 = _.toArray(obj1);
a2 = _.toArray(obj2);
merged = a1.concat(a2);
return merged;
};
function sort( list, sort ) {
var sorted = _.sortBy( list, sort );
return sorted.reverse();
};
@Josh412
Templating
<script type="text/html" id="tmpl--multiblog">
<article class="entry multi-blog-{{prefix}}">
<span class="image">
<img src="placeholder.png" alt="" class="img-{{prefix}}" data-media-id="{{featured_media}}" />
</span>
<a href="{{link}}" title="Read Full Post">
<h2>{{title.rendered}}</h2>
<div class="content">
<p>{{excerpt.rendered}}</p>
</div>
</a>
</article>
</script>
@Josh412
Templating
var posts;
$.when( getCWP(), getIngot() ).then( function( d1, d2 ) {
var all = merge( d1, d2 );
all = sort( all, 'date' );
_.templateSettings = {
interpolate: /\{\{(.+?)\}\}/g
};
var html = '';
var templateHTML = document.getElementById( 'tmpl--multiblog' ).innerHTML;
var template = _.template( templateHTML );
var item, templatedItem;
$.each( all, function ( i, post ) {
templatedItem = template( post );
html += templatedItem;
});
document.getElementById( 'posts' ).innerHTML = html;
});
@Josh412
Learn More: Client-Side Solution
All Example Code:jpwp.me/wpc-js-ex
Article:torquemag.io/2016/07/combine-wordpress-sites-rest-api/
See It In Action:CalderaLabs.org/blog.htmlgithub.com/CalderaWP/calderawp.github.io
@Josh412
CalderaLabs.org
Example TwoPHP + Server-Side
CachingWouldn't It Be Better To Cache Server Side?
@Josh412
Structure
-- plugin
---- Endpoint
---- MultiBlog
$caldera = new Endpoint( 'https://CalderaWP.com/wp-json/wp/v2/posts' );
$ingot = new Endpoint( 'https://IngotHQ.com/wp-json/wp/v2/posts' );
$multi = new MultiBlog( 1 );
$posts = $multi->get_posts();
@Josh412
Settings Up Endpoints
class Endpoint {
/** @var string */
protected $url;
/** @var array */
protected $posts = [];
public function __construct( $url ){
$this->url = $url;
$this->get_cache();
}
//REST OF THE CLASS…
}
@Josh412
Settings Up Endpoints
class Endpoint {
/** @var string */
protected $url;
/** @var array */
protected $posts = [];
public function __construct( $url ){
$this->url = $url;
$this->get_cache();
}
//REST OF THE CLASS…
}
@Josh412
Caching Responses
protected function set_cache(){
if ( ! empty( $this->posts ) ) {
set_transient( $this->cache_key(), $this->posts, DAY_IN_SECONDS );
}
}
protected function get_cache(){
if( is_array( $posts = get_transient( $this->cache_key() ) ) ){
$this->posts = $posts;
}
}
protected function cache_key(){
return md5( preg_replace( "(^https?://)", "", $this->url ) );
}
@Josh412
Querying Endpoints
public function get_posts( $page = 1){
if( isset( $this->posts[ $page ] ) ){
return $this->posts[ $page ];
}else{
$this->make_request( $page );
if( isset( $this->posts[ $page ] ) ) {
return $this->posts[ $page ];
}
}
return [];
}
protected function make_request( $page ){
$request = wp_remote_get( add_query_arg( 'page', (int) $page, $this->url ) );
if( ! is_wp_error( $request ) && 200 == wp_remote_retrieve_response_code( $request ) ){
$this->posts[ $page ] = json_decode( wp_remote_retrieve_body( $request ) );
}
}
@Josh412
Merging Our Endpoints
class MultiBlog {
/** @var array */
protected $posts = [];
/** @var array */
protected $endpoints = [];
/** @var bool */
protected $looped = false;
/** @var int */
protected $page;
public function __construct( $page = 1 ){
$this->page = 1;
}
public function add_endpoint( Endpoint $endpoint ){
$this->endpoints[] = $endpoint;
}
//REST OF CLASS…
}
@Josh412
Merging Our Endpoints
class MultiBlog {
/** @var array */
protected $posts = [];
/** @var array */
protected $endpoints = [];
/** @var bool */
protected $looped = false;
/** @var int */
protected $page;
public function __construct( $page = 1 ){
$this->page = 1;
}
public function add_endpoint( Endpoint $endpoint ){
$this->endpoints[] = $endpoint;
}
//REST OF CLASS…
}
@Josh412
Merging Our Endpoints
protected function merge(){
if( ! empty ( $this->endpoints ) ){
/** @var Endpoint $endpoint */
foreach ( $this->endpoints as $endpoint ){
$this->posts[] = $endpoint->get_posts( $this->page );
}
$this->posts = $this->sort( $this->posts );
}
}
protected function sort( array $data ){
usort( $data, function ( $a, $b ) {
return strtotime( $a->date ) - strtotime( $b->date );
} );
return array_reverse( $data );
}
@Josh412
Collecting The Posts
public function get_posts( $page = 1 ){
if( isset( $this->posts[ $page ] ) ){
return $this->posts[ $page ];
}else{
$this->merge();
if( ! empty( $this->posts ) ){
return $this->posts;
}
}
return [];
}
@Josh412
Putting It Together
function multiBlogPosts( $page ) {
$caldera = new Endpoint( 'https://CalderaWP.com/wp-json/wp/v2/posts' );
$ingot = new Endpoint( 'https://IngotHQ.com/wp-json/wp/v2/posts' );
$multi = new MultiBlog( 1 );
return $multi->get_posts( $page );
}
@Josh412
Learn More: Server-Side Solution
All Example Code:jpwp.me/wpc-ex-php
Article:torquemag.io/2016/07/combine-wordpress-sites-rest-api-php/
Widget To Show Remote Posts:github.com/Shelob9/remote-recent-posts
@Josh412
CalderaLabs.org
Thanks!Any questions?
@Josh412
CalderaLabs.org
Josh Pollock
JoshPress.net
CalderaLabs.orgCalderaWP.com
IngotHQ.com@Josh412