投稿の一部を非表示にする

概要

公開投稿に私的なメモを残せるようにするため、投稿の一部を管理者以外には表示しない仕組みを実装する。

詳細

非表示開始&終了タグ

投稿の最後にメモが残せればよいので、「非表示開始タグ」のようなものを文中に置き、それ以降を非表示とすればよい。ただ文中にコメントを残したい場合もあるかもしれないので、「終了タグ」も設けて開始タグと終了タグに挟まれた部分を非表示にする仕様とする。

編集時にはブロックエディタ (Gutenberg) の標準的な機能で使えて、表示時にはコアの誤動作を招かないようなタグとして、「HTML段落を書き出すショートコード」をタグとして利用することにした。

ブロックエディタで、非表示にしたいブロック群を [ lf_hidecontent start] と [ lf_hidecontent end] で挟んでおくと、管理人以外に対しては非表示となるが、管理人に対しては “↓ HIDE START” と “↓ HIDE END” で囲まれたうえで表示されるイメージ。

define( 'LF_HIDE_START', '<p class="lf-hide">↓ HIDE START</p>' );
define( 'LF_HIDE_END',   '<p class="lf-hide">↑ HIDE END</p>' );

add_shortcode( 'lf_hidecontent', 'lf_hidecontent' );
function lf_hidecontent( $args ) {
	$tag = '';
	if( isset( $args[0]) ) {
		if( 'start' == $args[0] ) {
			$tag = LF_HIDE_START;
		} else if( 'end' == $args[0] ) {
			$tag = LF_HIDE_END;
		}
	}
	return $tag;
}

タグの有無及び位置関係による表示の整理

開始タグと終了タグの有無、その前後関係を整理して、使用頻度の多い順に並べてみた。下記の5パターンがある。

(1) ◆ - C - ◇
→ C
(2) ◆ - C1 - 開始タグ - C2 - ◇
→ C1
(3) ◆ - C1 - 開始タグ ~ 終了タグ - C2 - ◇
→ C1+C2
(4) ◆ - C1 - 終了タグ - C2 - ◇
→ C2
(5) ◆ - C1 - 終了タグ - CX - 開始タグ - C2 - ◇
→ CX
  1. 非表示領域がない、通常の投稿。
  2. 開始タグのみを付けてC2を隠す。C1が表示される。
  3. 文中に非表示領域を設ける場合。C1とC2が表示される。
  4. 文頭にコメントを付す場合。C2が表示される。
  5. 文頭と文末にコメントを付す。CXが表示される。

非表示処理

// (1) コアの処理を優先させるために優先順位21以下で呼び出す
add_filter( 'the_content', 'lf_filter_hidecontent', 21 );
function lf_filter_hidecontent( $content ) {

	 /
/ (2) 管理者は素通し
	if( current_user_can( 'administrator' ) ) {
		return $content;
	}

	$content1 = $content2 = '';

	// (3) 開始タグが存在
	if( false !== $startpos = strpos( $content, LF_HIDE_START ) ) {
		// (4) 先頭から開始タグの前まで取得
		$content1 = substr( $content, 0, $startpos );
	}

	// (5) 終了タグが存在
	if( false !== $endpos = strpos( $content, LF_HIDE_END ) ) {

		// (6) 開始タグ → 終了タグ(通常パターン)。開始タグがない場合もここ
		if( $startpos < $endpos) {
			// (7) 終了タグの次からコンテンツの最後までを取得し、$content1 に追加する
			$content2 = substr( $content, $endpos + strlen(LF_HIDE_END) );
		// (8) 終了タグ → 開始タグ
		} else {
			// (9) $content1(先に取得した、投稿の先頭から開始タグまでの部分)から、終了タグの次以降だけを取り出す
			$content1 = substr( $content1, $endpos + strlen(LF_HIDE_END) );
		}
	}

	// (10) $content1.$content2 に値が入っていなかった(つまり開始タグも終了タグもなかった)なら何もせずリターン
	$content = $content1.$content2 ?: $content;

	return $content;
}
  1. Query Monitor(プラグイン)で見ると、the_content にフックされたコアの処理のうち優先順位の最も低いものは20だったので、その次の21とした
  2. 管理者には識別タグ(pタグ)を含めてすべてのコンテンツを返す。ソースには表れないが、lf-hide クラスに背景色を付けて見やすくしている。
  3. このif文が偽ならパターン1かパターン2(10で決定される)
  4. $conetnt1が空ならパターン4、さもなくばパターン3
  5. パターン5
  6. パターン2~5、さもなくばパターン1

注意点

  • 管理者がAという件名の投稿の非表示領域にBという語句を書いた場合、一般ユーザーがBを検索すると検索結果の投稿一覧にはAも表示される。基本的にはメモの位置づけなので検索機能のカスタマイズは行っていない。投稿を開いても読むことはできないが留意が必要。

タグ

(Page info for admin)

📅

 👤

 📁