特定のタームにパスワードをかける方法

先日、個人事業のサイトが完成しました。
たくさんの方にいろいろと教えていただき、なんとか思ったとおりのサイトを作ることができました。

屋号はアカリホノカニと言います。
http://akarihonokani.com/

今後、このサイトの作り方を、テーマ編・プラグイン編などとして投稿していこうかと思います。
今回はピックアップした感じになりますが、とても感動した「特定のタームにパスワードをかける方法」をポストします。たぶん、困ってる方いるんじゃないかと思うので…。

[公開一時間後 追記:記事を見てここはこうしたほうがいいよーといった意見をいただきました。今後調べて追記していきます。
・フィードに対応していない、・リダイレクトはwp_redirectまたはauth_redirectを使ったほうがいい、などです。]

[2014/08/12 追記:いろいろなご指摘・ご意見をいただきましたので、togetterでまとめました。また、それを参考にコードを書き直しましたので、一番最後に追記しています。]

特定のカテゴリーにパスワードをかけるプラグインはAllow Categoriesというものがあるようですが、タームにというのは見つけられませんでした。
困っていたところ、「失恋.jp」のカイトさん@ixkaitoに、こうやってコードを書けば大丈夫だよと教えていただきました。本当にありがとうございます!!

これによって、アカリホノカニでは「制作実績」のタームである「非公開実績」の記事や、「非公開実績」のアーカイブページを見るときにはWordPressのログイン画面に飛ぶようになりました。

fanctions.phpに次のコードを書く

function require_login_for_private_works() {
	if ( ( is_singular( 'works' ) && has_term( 'private', 'works_cat' ) || is_tax( 'works_cat', 'private' ) ) && ! is_user_logged_in() ) {
		header( 'Location: ' . wp_login_url( get_home_url ( null, esc_attr( $_SERVER['REQUEST_URI'] ) ) ) );
		exit;
	}
}
add_action( 'get_header', 'require_login_for_private_works', 1 );

require_login_for_private_worksはお好きなお名前に変更して下さい。

is_singular( ‘works’ )はカスタム投稿タイプ「works」の投稿を見ている時。

has_term( ‘private’, ‘works_cat’ )は現在の投稿がカスタムタクソノミー「works_cat」のターム「private」が付いている投稿かチェックする。

is_tax( ‘works_cat’, ‘private’ )はカスタムタクソノミー「works_cat」でターム「private」のアーカイブページを見ている時。

is_user_logged_in()は現在の訪問者がログインしているかチェックする。

&&||!は演算子です。&&は前と後ろが共に。||は前または後ろのどちらかが、という意味です。優先順位は&&のが上です。()の中を先に計算するというのは小学校でもやったと思いますがこれもそうです。!は後ろを否定しています。

is singular -WordPress Codex 日本語版
has_term -WordPress Codex 日本語版
is_tax -WordPress Codex 日本語版
is_user_logged_in -WordPress Codex 日本語版
論理演算子 -PHPマニュアル

頭こんがらがりますね…。
あ、そしてこれはif文なので、ここまでをつなげて言葉にすると、
”カスタム投稿タイプの「制作実績」の投稿で「非公開実績」のタームの記事、もしくは「非公開実績」のタームのアーカイブページを見ているとき、現在の訪問者がログインしていなかったとしたら…”
ということになります。

はい、していなかったとしたら…どうなるんでしょう。
すいませんここから調べてもよくわからず曖昧です…。
「していなかったとしたらログイン画面に行き、ログイン後はトップページではなく、その見ようと思っていたページにちゃんとリダイレクトする。」という処理になるはずですが、ちょっとどの記述でログイン画面に行くのかよくわかりません。わかる方教えていただけると嬉しいです…(>_<)

header( ‘Location: ‘ . wp_login_url( get_home_url ( null, esc_attr( $_SERVER[‘REQUEST_URI’] ) ) ) );
exit;

header()関数でリダイレクトさせてるんですよね…?wp_login_urlテンプレートタグでログインURLを取得してリダイレクト。これもリダイレクト。うーん…。

get_home_urlはサイトのホームURL(管理画面の「設定」→「一般」の「サイトのアドレス(URL)のこと)を取得。
( $_SERVER[‘REQUEST_URI’] )はページにアクセスするために指定されたURI。(例えばhttp://example.com/hoge.htmlなら「/hoge.html」)
これで見ようと思ってクリックしたページにリダイレクトしてくれます。ということはわかるんですけどね…。

ちなみに、なぜwp_login_url( get_permalink() ) と書かないのか、というと、シングルページやループ内であれば、これで問題ありませんが、アーカイブページ(今回は非公開実績の一覧ページ)などは、get_permalink()では現在ページのURLを取得できないから、とのことでした!

header -PHPマニュアル
wp_login_url -WordPress Codex
get home url -WordPress Codex 日本語版
$_SERVER -PHPマニュアル

次は
add_action( ‘get_header’, ‘require_login_for_private_works’, 1 );

get_headerというアクションフック(テンプレートが get_header() 関数を呼び出した際、header.phpファイルが読み込まれる直前に実行する。)に、一番最初に定義したrequire_login_for_private_works関数をフックします。1は関数が実行される優先順位です。真っ先に実行してほしいので1と書きます。

アクションフック一覧 -WordPress Codex 日本語版
add action -WordPress Codex 日本語版

カスタム投稿タイプアーカイブページとカスタムタクソノミーアーカイブページのテンプレートに次のコードを書く

カスタム投稿タイプアーカイブページ(今回は制作実績の一覧)とカスタムタクソノミーアーカイブページ(今回は非公開実績タームの一覧)のテンプレートのループ内にthe_content();と記述があると思いますが(テーマによってはそうじゃないかもしれませんが)、そこを次のコードに変えます。
(get_template_partで違うテンプレートを読み込んでいる時もあるので注意です)

<?php if ( has_term( 'private', 'works_cat' ) && ! is_user_logged_in() ) {
	echo '<p>非公開です。ログインしてください。</p>';
} else {
	the_content();
} ?>

has_termもis_user_logged_in()も先ほども出てきましたね。
現在の投稿がカスタムタクソノミー「works_cat」のターム「private」が付いている投稿かチェックし、もしログインしていないユーザーだったら「非公開です。ログインしてください。」とechoして表示させます。

この場合、一覧にタイトルは表示され、本文にこの文言が入ります。

キャプチャ画像

ログインしていないとき一覧に表示させたくないなら、ループの while ( have_posts() ) : the_post(); 直後を下記のようにするといいそうです。

<?php if ( has_term( 'private', 'works_cat' ) && ! is_user_logged_in() ) continue; ?>

ログインするしないかかわらず一覧に表示させたくないならループの while ( have_posts() ) : the_post(); 直後を下記のようにするといいそうです。

<?php if ( has_term( 'private', 'works_cat' ) ) continue; ?>

終わりに

途中ものすごくグダグダでしたが(;´Д`)、とにもかくにもこれで特定のタームの記事とターム一覧(アーカイブページ)にパスワードをかけることができました。(正しくはログインさせないと見れないようにした、ですね)
あとはログイン画面のWordPressマークを、サイトのロゴ画像にしたいなぁと思っています。

いつもいろいろググって調べますが、コピペはしても意味はわからないことが多いので、今回頑張って調べてみました。
これを応用すればたぶんカテゴリーにパスワードをかけることもできるだろうし、本当に勉強になりました。カイトさんありがとうございました!

アカリホノカニでは、ただいまお仕事募集中です。何か依頼してやろうかという方は、このブログでも事業サイトでも大丈夫ですので、お問い合わせフォームより、コンタクトをお願いいたします!

追記です!!

公開後、Twitterでいろいろご指摘いただきました。一番大きな問題はフィードや検索結果に丸見えになるぞ、というところかなと思います。
ご指摘いただいた@gatespace_kさん、@horike37さん、@jim0912さん、@HissyNCさん、本当にありがとうございました!
@gatespace_kさん、@HissyNCさんには実際にコードまで書いていただき…。みなさんほんと、めちゃくちゃお忙しい中感激です…(´;ω;`)ブワッ

@gatespace_kさんのコード

@HissyNCさんのコード

まとめたtogetterはこちらになります。ぜひご覧ください。
特定のタームにパスワードをかける(ログイン必須にする)方法のブログについてのご指摘

参考に私が書き直したコードはこちら

// リダイレクト
function require_login_for_private_works() {
    if ( ( is_singular( 'works' ) && has_term( 'private', 'works_cat' ) || is_tax( 'works_cat', 'private' ) ) && ! is_user_logged_in() ) {
    	$redirect_to = set_url_scheme( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
    	wp_safe_redirect( wp_login_url( $redirect_to ) );
        exit;
    }
}
add_action( 'template_redirect', 'require_login_for_private_works' );


// 記事のタイトルだけ見せて本文には下記定型文を入れる
function my_the_content_filter($content) {
 
	$loginflg = false;
 
	if ( has_term( 'private', 'works_cat' ) ) {
		$loginflg = true;
	}
	
	if ( !is_user_logged_in() && $loginflg ) {
		$content = '非公開実績です。ログインしてください。';
	}
 
	return $content;
}
add_filter( 'the_content', 'my_the_content_filter' );
add_filter( 'get_the_excerpt', 'my_the_content_filter' );
 

// フィードや検索結果も下記定型文を本文に表示
function my_content_feed( $content ) {
 
	if ( has_term( 'private', 'works_cat' ) ) {
		$content = '非公開実績です。ログインしてください。';
	}
	
	return $content;
}
add_filter('the_content_feed', 'my_content_feed', 10, 2);
add_filter('the_excerpt_rss', 'my_content_feed', 10, 2);


// おまけ。そもそもの話で、カスタム投稿タイプの記事も通常のフィードに表示させる
function mysite_feed_request($vars) {
    if ( isset( $vars['feed'] ) && !isset( $vars['post_type'] ) ) {
        $vars['post_type'] = array( 'post', 'works' );
    }
    return $vars;
}
add_filter( 'request', 'mysite_feed_request' );

@HissyNCさんと、@gatespace_kさんのコードを組み合わせて使用させていただきました。
おまけはそもそもカスタム投稿タイプは通常のフィードには表示されないので、それを表示させるコードです。
キタジマさんのこちらの記事を参考にしました。ありがとうございます。

巷でよく見かけるカスタム投稿タイプをRSSに反映させるコードはバグがあるので使ってはいけない|モンキーレンチ

やりたいことを実装するのにはいろんなやり方があり、最適な方法があること、WordPressのテンプレートタグやアクションフック、フィルターフックをもっと理解すれば、今後もいろいろと役に立つんだろうなぁということを身にしみて感じております。
私の記事がどなたかの助けになると幸いです!ではまた!