こんにちは、プログラマーの山本です。

今回は企業様から以下のようなシステム依頼を受けました。

  • WordPressのカスタム投稿タイプで作成した記事やアーカイブを、
    カスタム投稿タイプごとに、まとめて同じパスワードをかけたい。
  • 1度パスワード認証を行ったら、同じカスタム投稿タイプの記事やアーカイブでは
    パスワードを要求せずに閲覧できるようにしたい。
  • パスワードの設定はコードをいじらずに管理画面から行いたい。

上記を満たすシステムを制作・導入しました。

設計・制作の流れ

以下のように設計し、作成しました。

  • オリジナルのパスワード管理用データベースを新規作成する。
    (今回は wp_passwords としました。)
  • パスワード認証画面は別途固定ページで作成する。
  • 閲覧ページ(パスワードをかけるページ)と認証ページのURLを関連づける。
  • 閲覧ページにアクセスしたとき、
    パスワード未認証なら関連づけられた固定ページに自動で飛ばす。
  • パスワード認証後、関連づけられた閲覧ページに自動で飛ばす。
    (認証済みで認証用固定ページにアクセスした場合も同様。)
  • 認証済み情報をユーザーIDで管理。
    (今回システムを導入するwordpressサイトが会員制サイトだったため)
  • 管理画面にパスワード管理ページを追加する。

管理画面にパスワード管理ページを作成する

管理画面への新規ページ追加

まずは、管理画面に新しくページを作成する方法を説明します。

といっても、すごく簡単で、function.phpに以下のコードを書きます。

<?php
//パスワード管理
add_action( 'admin_menu', '[関数A]' );
function [関数A](){
	add_menu_page( '[ページタイトル]', '[メニュー名]','manage_options', '[ページのスラッグ]', '[関数B]', '', [表示位置] );
}
function [関数B](){
	//ここにページを構成するHTMLやPHPを書く。
}?>
[]で囲っている部分は、任意の値に変更してください。

今回はパスワード管理ページを作成するので、以下のようにしました。

[関数A]       ・・・ register_password_page
[ページタイトル]  ・・・ パスワード管理
[メニュー名]    ・・・ パスワード管理
[ページのスラッグ] ・・・ password_manager
[関数B]       ・・・ password_page
[表示位置]     ・・・ 6

パスワード管理ページの構築

上記のコードを編集・追加して、管理ページを構築します。

<?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>";
}?>

システムには関係ありませんが、
一応CSSも公開しておきます。以下のようにしました。

デザインはお好みに合わせて変更すると良いでしょう。

		table#sets_table{
			border-collapse:collapse;
		}
		table#sets_table td{
			border: 1px solid;
			padding: 0px;
			width:300px;
		}
		table#sets_table th{
			border: 1px solid;
			padding: 5px 0px;
			width:300px;
		}
		table#sets_table th {
			background-color:#ccc;
		}
		.pwdpage button{
			padding: 10px 40px;
			margin-right: 20px;
			margin-top: 20px;
			background-color: #ccc;
			border: 1px solid;
		}
		.pwdpage button.save{
			font-weight:bold;
		}
		.pwdpage td textarea{
			width:800px;
		}
		.pwdpage td input{
			width:300px;
		}
		th.del, td.del{
			width:50px !important;
			text-align:center;
		}
		td.del button{
    		margin: 0px;
			padding: 5px;
			background-color: #ccc;
		}

パスワード認証時の判定

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

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

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' );

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

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

以下のコードを 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;
			}
		}
	}
?>

これで一通りの実装が完了しました。

まとめ

今回はカスタム投稿タイプにパスワードをつけたいとのご希望でしたが、
同じシステムで、既存のアーカイブページやカテゴリーページなどにも
好きなパスワードをつけることが出来ます。

どのページに、どんなパスワードをつけるかは、
全て管理画面で設定できるようにしているので、管理が簡単です。

同じようなシステムを導入したいという方は参考にしていただければと思います。

この記事を見ても自分で実装するのは難しそうだという方や、
もう少し違ったシステムを実装したいといったご要望の方は、
ご相談いただければと思います。

制作の依頼はこちら

今回ご紹介したシステムなど、
WEB上にシステムを実装したい場合は弊社におまかせください。

簡単なシステムなら1件¥3,000(税別)から承ります。

相場よりも費用を抑えて対応させていただくことが可能ですので、
以下のフォームから相談内容を記入して気軽にご連絡ください。

    必須 お名前

    必須 メールアドレス

    任意 サイトのURL

    必須 ご依頼内容や相談内容

    ※出来るだけ具体的に記載していただけると進行がスムーズになります。

    任意 画像やPDF

    ※必要があれば添付してください。





    原則2営業日以内に、ご返信させていただきます。