【WordPress】カスタム投稿やアーカイブに一括で共通のパスワードをつける。

<h2>要件</h2>

・パスワード認証画面は別途固定ページで作成する。

・閲覧ページ（パスワードをかけるページ）と認証ページのURLを関連づける。

・閲覧ページにアクセスしたとき、
　パスワード未認証なら関連づけられた固定ページに自動で飛ばす。

・パスワード認証後、関連づけられた閲覧ページに自動で飛ばす。
　（認証済みで認証用固定ページにアクセスした場合も同様。）

・認証済み情報をユーザーIDで管理。
　（今回のサイトが会員制サイトだったため）

・管理画面にパスワード管理ページを追加する。

<h2>パスワード管理ページの構築</h2>

管理画面にパスワード管理用のページを追加します。

```php:function.php
<?php
//パスワード管理
add_action( 'admin_menu', 'register_password_page' );
function register_password_page(){
	add_menu_page( 'パスワード管理', 'パスワード管理','manage_options', 'password_manager', 'password_page', '', 6 );
}
function password_page(){
	include '../wp-load.php';
	global $wpdb;
	if($_POST){
		echo "<h2>パスワード管理</h2>";
		echo "Loading...";
		if($_POST["del"]){
			//データベースの削除
			$where = array( 'seq' => $_POST["del"] );
			$wpdb->delete("wp_passwords", $where);
		}
		else{
			$datas = $wpdb->get_results("SELECT * FROM wp_passwords WHERE type = 'pageurl'");
			$datas = json_decode(json_encode($datas), true);
			foreach( $_POST as $key => $post ){
				$type = preg_replace( "/[0-9]/i", "",  $key);
				$no = preg_replace( "/[^0-9]/i", "",  $key);
				if( $type == "pageurl" ){
					$exist = false;
					foreach( $datas as $data ){
						if( $type ==  $data["type"] && $no == $data["seq"] ){
							$exist = true;
							break;
						}
					}
					$values = array('value' => $post , 'type' => $type );
					$where = array('seq' => $no , 'type' => $type );
					if( $exist ){
						//データベースの更新
						$wpdb->update("wp_passwords", $values, $where);
					}
					else{
						//データベースの追加
						$values +=array('seq' => $no );
						$wpdb->insert("wp_passwords", $values);
					}
				}
				else{
					$where = array('seq' => $no , 'type' => $type );
					$wpdb->delete("wp_passwords", $where);
					$pwdurls = explode( "n" , $post);
					foreach( $pwdurls as $pwdurl ){
						if( trim($pwdurl) == "" ){
							continue;
						}
						//データベースの追加
						$values = array('value' => $pwdurl , 'type' => $type , 'seq' => $no );
						$wpdb->insert("wp_passwords", $values);
					}
				}
			}
		}
	}
	$pwdurls = $wpdb->get_results("SELECT * FROM wp_passwords WHERE type = 'pwdurls' ORDER BY seq");
	$pwdurls = json_decode(json_encode($pwdurls), true);
	$pageurl = $wpdb->get_results("SELECT * FROM wp_passwords WHERE type = 'pageurl' ORDER BY seq");
	$pageurl = json_decode(json_encode($pageurl), true);
	echo "<div class='pwdpage'>";
	echo "<h2>パスワード管理</h2>"; 
	echo "<br>";
	echo "<form action='' method='post'>";
	echo "<table id='sets_table'>";
		echo "<tr><th>パスワード認証用の固定ページURL</th><th>カスタム投稿タイプ名</th><th class='del'>削除</th></tr>";
		foreach( $pageurl as $pu ){
			$urls = "";
			foreach( $pwdurls as $pwdurl ){
				if( $pwdurl["seq"] == $pu["seq"] ){
					$urls .= $pwdurl["value"]."n";
				}
			}
			echo "<tr><td><input type='text' name='pageurl{$pu["seq"]}' value='{$pu["value"]}'></td>";
			echo "<td><textarea name='pwdurls{$pu["seq"]}'>{$urls}</textarea></td>";
			echo "<td class='del'><button type='button' id='{$pu["seq"]}' onclick='delRow(this);'>削除</button></td></tr>";
		}
	echo "</table>";
	echo "<button type='button' onclick='addSet();'>行を追加する</button>";
	echo "<button class='save' type='submit'>全て保存する</button>";
	echo "</form>";
	echo "</div>";
}?>
```

<h2>パスワード認証時の判定</h2>

パスワード認証を行ったときの処理を書きます。

今回のシステムとは関係ない投稿や固定ページでの認証の場合は除外し、
初認証の場合は、ユーザーIDをデーターベースに追加します。

```php:function.php
function custom_auth_save() {
	include 'wp-load.php';
	global $wpdb;
	//パスワードの一致確認
	$postid = url_to_postid( wp_get_referer() );
	$pwds = $wpdb->get_results("SELECT * FROM wp_posts WHERE ID = '".$postid."'");
	//一致する場合、認証済み判定を行う
	if( $pwds[0]->post_password == $_POST['post_password'] ){
		$datas = $wpdb->get_results("SELECT * FROM wp_passwords ORDER BY seq");
		$seq = false;
		//今回のシステムでパスワードをかけたページかどうか判別
		foreach( $datas as $data ){
			if( $data->type == "pageurl" && strpos( $data->value , wp_get_referer() )  !==false ){
				$seq = $data->seq;
				break;
			}
		}
		//すでに認証済みか確認
		if( $seq ){
			foreach( $datas as $data ){
				$cu = wp_get_current_user();
				if( $data->type == "userauth" && $data->seq == $seq && $data->value == $cu->ID ){
					$seq = false;
					break;
				}
			}
		}
		//未認証ならユーザーIDを追加保存する。
		if( $seq ){
			//保存
			$values =array( 'seq' => $seq , 'type' => "userauth" , 'value' => $cu->ID );
			$wpdb->insert("wp_passwords", $values);
		}
	}
}
add_action( 'login_form_postpass', 'custom_auth_save' );
```

<h2>パスワード未認証時のページ自動遷移</h2>

閲覧ページにアクセスしたときに、
パスワード未認証なら、認証ページに飛ばす処理を書きます。

以下のコードを header.php の頭に追加します。

```php:header.php
<?php
	//パスワード管理（コンテンツにパスワードをかけて、未認証の場合、パスワードページに飛ばす）
	$datas = $wpdb->get_results("SELECT * FROM wp_passwords");
	$seq = false;
	//一致確認
	foreach( $datas as $data ){
		//データベースの閲覧ページURLを調整
		$dataurl = str_replace( "http://" , "" , $data->value );
		$dataurl = str_replace( "https://" , "" , $dataurl );
		$dataurl = trim($dataurl);
		//現在アクセスしているのURLを調整
		$pageurl = $_SERVER["HTTP_HOST"].$_SERVER["REQUEST_URI"];
		if( $data->type == "pwdurls" && strpos( urldecode($pageurl) , $dataurl ) !==false ){
			$seq = $data->seq;
			break;
		}
	}
	//認証済みかどうか確認する。
	if( $seq ){
		foreach( $datas as $data ){
			$cu = wp_get_current_user();
			if( $data->type == "userauth" && $data->seq == $seq && $data->value == $cu->ID ){
				$seq = false;
				break;
			}
		}
	}
	//未認証ならパスワード認証ページに飛ばす。
	if( $seq ){
		foreach( $datas as $data ){
			if( $data->type == "pageurl" && $data->seq == $seq){
				wp_redirect( $data->value );
				exit;
			}
		}
	}
?>
```