経緯
WordPress の REST API で出力されるデータを GETリクエストのパラメータでフィルタリングすると、クライアント側で指定する URL がごちゃごちゃするので WordPress 側で制御できないかと考えました。
「REST API にアクセスされた際に、レスポンスデータを出力する直前」のタイミングという、そこそこカスタマイズのニーズがありそうなポイントではアクションフックが用意されていそうなので、「アクションフックで余計な出力が出ないように制限する」ということはできそうな気がします。
調査
調べてみたらあったのでこの方法で考えます。ついでにアクションフックは rest_prepare_post
が良さそうです。
実装
<?php
/*
Plugin Name: Filter REST
Description: REST API の出力結果をフィルタリングするプラグイン (パーマリンク設定は「基本」または「数字ベース」にしてください)
Version: 0.0.1
Author: アルム=バンド
*/
/**
* Filter REST : REST API の出力結果をフィルタリングするプラグイン
*/
class FilterREST
{
/**
* __construct : プラグイン有効時にメソッドを呼ぶ
*
*/
public function __construct() {
// 有効化の際に発動
add_action(
'rest_prepare_post',
[
$this,
'remove_data',
],
10,
3
);
}
/**
* remove_data : _links や不要な値を非出力にする
*
* @param {Object} $response : レスポンスとして返却するデータ
* @param {Object} $post :
* @param {Array} $request : リクレストデータ
*
* @return {Object} $response : レスポンスとして返却するデータ
*
*/
public function remove_data ( $response, $post, $request )
{
// embed用の要素の削除
unset( $response->data['type'] );
unset( $response->data['link'] );
unset( $response->data['excerpt'] );
unset( $response->data['author'] );
unset( $response->data['featured_media']); // アイキャッチだが即座に画僧のパスを取得できるものではないので削除
unset( $response->data['date_gmt'] );
unset( $response->data['modified_gmt'] );
unset( $response->data['guid'] );
unset( $response->data['excerpt'] );
unset( $response->data['comment_status'] );
unset( $response->data['ping_status'] );
unset( $response->data['sticky'] );
unset( $response->data['template'] );
unset( $response->data['format'] );
// _links の全要素を取得
$links = $response->get_links();
// 要素を foreach で全て削除
foreach ( $links as $key => $value ) {
$response->remove_link( $key );
}
return $response;
}
}
// instantiate
if( !is_admin() ) {
// 管理者画面以外
$filterrest = new FilterREST();
}
ブロックエディタは REST API を使用していますし、他のプラグインでも使用しているケースがあるので、ログインしていない場合のみ絞る方向で調整してみようかと。
それから、一応クラスにしてなるべくグローバルスコープを汚染しないようにしておきます。ついでにプラグインとして実装してみました。
応用
ついでに「本文内にある href
属性内の URL がサイト内部へのリンクだった場合は置換をする」ということもやってみます。
// 略
class FilterREST
{
/**
* __construct : プラグイン有効時にメソッドを呼ぶ
*
*/
public function __construct() {
// 有効化の際に発動
add_action(
'rest_prepare_post',
[
$this,
'remove_data',
],
10,
3
);
add_action(
'rest_prepare_post',
[
$this,
'url_replace',
],
11,
3
); // 追加
}
// 略
/**
* url_replace : content のリンクを書き換える
*
* @param {Object} $response : レスポンスとして返却するデータ
* @param {Object} $post :
* @param {Array} $request : リクレストデータ
*
* @return {Object} $response : レスポンスとして返却するデータ
*
*/
public function url_replace ( $response, $post, $request )
{
$search_pattern = '/href=\\"([^"]*?)\\"/i';
$response->data['content']['rendered'] = preg_replace_callback(
$search_pattern,
[
$this,
'replace_process',
],
$response->data['content']['rendered']
);
return $response;
}
/**
* replace_process : 外部サイトへのリンクはそのままで、それ以外は置換
*
* @param {string} $matches : url_replace で $search_pattern にマッチした文字列
*
* @return {string} : 置換された文字列
*
*/
public function replace_process ( $matches )
{
$siteurl = site_url();
$static_url = 'https://example.com/releasenote/'; // 何かしらの静的サイトの更新履歴の個別記事ページを想定
if( strpos( $matches[1], $siteurl ) === false ) {
// サイト外へのリンクならばリンク文字列をそのまま返す
return $matches[0];
}
else {
// サイト内リンクならば置換する
if( strpos( $matches[1], '?p=' ) !== false ) {
// 「基本」
$id = explode( '?p=', $matches[1] )[1];
return 'href="' . $static_url . $id . '"';
}
else if( strpos( $matches[1], 'archives/' ) !== false ) {
// 「数字ベース」
$id = explode( 'archives/', $matches[1] )[1];
return 'href="' . $static_url . $id . '"';
}
else {
// ルールに該当しない場合はブランク
return 'href="#"';
}
}
}
}
// 略
こんなことをすると、同じ WordPress の投稿記事のどれかの記事へのリンクは https://example.com/releasenote/{記事ID}
という形で置換されます。投稿を静的サイト側の JS でごにょごにょしたい……という場合には使えるかもしれません。
参考
WordPress の REST API
- WP REST API を使って独自エンドポイントを設定する。 – Qiita
- WordPressのREST API周りのfilter hook / action hook のまとめと、一部のREST APIを開放する方法 – Qiita
- WordPress REST APIについてまとめてみた | WebCraftLog
- WordPress 4.7以降でREST APIのレスポンスを加工する(ACFの値も追加可能) – Qiita
ブロックエディタは REST API を使用していますし、他のプラグインでも使用しているケースがあるので、ログインしていない場合のみ絞る方向で調整してみようかと。
なお、アクションフックとしては rest_api_init
, rest_endpoints
, rest_prepare_post
等がある模様。
不要な出力を削除
- WordPressのREST APIから「guid」など不要な項目を削除する | オレDEV.com
- WordPressのREST APIから「_links」を削除する | オレDEV.com
- WordPress 4.7以降でREST APIのレスポンスを加工する(ACFの値も追加可能) – Qiita
今回は使わなかったが今後使いそうなもの
カテゴリの詳細情報も取得
アイキャッチ画像の情報を取得
PHP
正規表現
- PHPで正規表現を使ってHTMLを強引にほじるコツ – Qiita
- 正規表現でhtml内のリンク名称とリンク先を取得 – Qiita
- [PHP] preg_replace 後方参照でちょっと悩んだ – 脱力系備忘録BloG
- PHP: preg_replace_callback – Manual
- カンマ区切りの文字列を正規表現で表す | クソざこCoding
正規表現や後方参照について。念のため。
一部に文字列を含むか
WordPress テンプレートタグ
たまにだと site_url()
か home_url()
か迷うので。