WordPress x Vue.jsで公開済み記事の編集時プレビューを表示する(SPA実装)

表題の通りWordPressのフロントをSPAとして、RoutingをVue側で持った際に、公開済み投稿の編集プレビューを表示するのに迷った話です。  
結論としては、revisionsの最新を見にいくことで解決しました。  

## 開発環境について
* PHP 5.6
* WordPress 4.8
  * WP REST API 2.0-beta15


## WordPressにおける投稿statusの整理

<img width="358" alt="20170906214605.png" src="https://qiita-image-store.s3.amazonaws.com/0/8131/20ddee57-251c-6be3-be77-1acfd9e53e83.png">


WordPressにはデフォルトで[8つのステータス](https://wpdocs.osdn.jp/%E6%8A%95%E7%A8%BF%E3%82%B9%E3%83%86%E3%83%BC%E3%82%BF%E3%82%B9#.E3.83.87.E3.83.95.E3.82.A9.E3.83.AB.E3.83.88.E3.81.AE.E3.82.B9.E3.83.86.E3.83.BC.E3.82.BF.E3.82.B9)があります。  
表題の公開済み投稿の編集プレビューは、以下の"auto-draft"に該当します。

> **自動保存 (auto-draft)**  
> 編集中に WordPress が自動的に保存した リビジョン です。

## WP REST APIの認証について
SPAでの実装に置いて、インターフェースはHTTPを介しWP REST APIを利用します。  
WP REST APIは、WordPress上の投稿データを中心にタクソノミーやタグ、ユーザといった広範囲な情報をHTTPベースでAPIとして提供できる非常に便利なプラグインです。  
利用する上で、非公開投稿など権限が必要な情報についてはnonce[^1]をCookie経由で利用しています。  
具体的にはHTTPクライアントのリクエストヘッダに``` X-WP-Nonce```を追加することで実現しています。  

#### nonceの発行について
``` X-WP-Nonce```のValueは、WordPress php側で発行します。

###### header.php
```php
<?php wp_localize_script(
  'wp-api', 
  'WP_API_Settings', 
  array( 'root' => esc_url_raw( rest_url() ), 
  'nonce' => wp_create_nonce( 'wp_rest' ) ) ); ?>
```

ブラウザのCookieに保存されている```window.WP_API_Settings.nonce```を設定することで、現在のWordPressに対するユーザのログイン状態が適切に処理されて、認証が必要なAPIの値を取得することができます。  
もし認証が必要なAPIを利用する場合は、wp-adminからログインすることで、nonceの値がそのユーザの権限として変更されます。


#### VueでのHTTPクライアントについて
VueでのHTTPクライアントには[vue-resource](https://github.com/pagekit/vue-resource)を利用しています[^2]。  
[サンプル](https://github.com/pagekit/vue-resource/blob/develop/docs/http.md#interceptors)の通りリクエスト前に一度設定します。

```javascript
Vue.http.interceptors.push(function(request, next) {
  // modify headers
  request.headers.set('X-WP-Nonce', window.WP_API_Settings.nonce); // Cookieのnonceオブジェクトをセット

  // continue to next interceptor
  next();
});
```

## 通常のPostからの取得トライ
さて本題の投稿プレビューのアプローチですが、最初は通常のPostsからのStatus指定で試みました。  
http://domain.com/wp-json/wp/v2/posts?status=auto-draftの形ですね。  
注意点としては、ブラウザ直ではX-WP-Nonceリクエストヘッダがないのでレスポンスデータは見れないです。

```javascript
Vue.http
  .get('http://domain.com/wp-json/wp/v2/posts', {params: {status: 'auto-draft'}}, {})
  .then(response => {console.log(response)})
```

![20170907003942.png](https://qiita-image-store.s3.amazonaws.com/0/8131/9b19339c-c054-49f1-4fee-58e73ca12ac5.png)
 

一見、期待した動作をしていそうだったのですが編集中の投稿はこの中に含まれておらず、少し調査した限りですが一体何を取ってきているのか理解できませんでした...[^3]

## WP REST APIのリビジョンendpoint
方向性を変更して、リビジョンの最新を調査したところ  
[GET /wp/v2/posts/<parent_id>/revisions](http://v2.wp-api.org/reference/posts/revisions.html)


```javascript

Vue.http
  .get('http://domain.com/wp-json/wp/v2/posts/1234/revisions', {params: {status: 'auto-draft'}}, {})
  .then(response => {console.log(response)})

```

<img width="512" alt="20170907010309.png" src="https://qiita-image-store.s3.amazonaws.com/0/8131/37202da4-f4df-32f6-4b4b-a0e86a151bb1.png">


無事にとれました。

## その他注意点
revisionsには、ACFといったmeta系は含まれておらずこの辺りはPHP側で```register_rest_route```等、追加で実装が必要です。  

参考: [plugin利用する](https://support.advancedcustomfields.com/forums/topic/revisions-not-showing-custom-fields/), [自前サンプル](https://johnblackbourn.com/post-meta-revisions-wordpress/)  

[^1]: 暗号化技術のひとつ
[^2]: vue-resourceプラグインについては、[Vue.js公式推奨から外れています](https://jp.vuejs.org/2016/11/03/retiring-vue-resource/)
[^3]: WordPress, PHP側の実装バグであれば、ご指摘いただきたいです。この取り方が望ましいと思います。