Wonderful! WordPress

コメントの編集機能、nonceで作り直してプラグイン

Page No.2

これも大事な部分。
コメントが削除された時にeditkey も削除する関数とプラグインがアンインストールされた時にoption と保存してある全てのeditkey を削除する処理。
尚、プラグインがアンインストールされたときの静的な関数を使う処理はここのサイト【WordPressプラグインの仕組みとクラスを利用したより実践的な解説】からまる写しで学ばせていただきました。とても勉強になったありがたいサイトです。誠にありがとうございました。

※2019/12/5 追記
プラグインがアンインストールされた時に、オプション値を同時に削除する件において、上記のごとく静的な関数を使う手法を下記のように使っていたのですが、php が7となり、次のようなDeprecate が出るようになりました。
Deprecated: Non-static method Simplistic_Comment_User_Editable::at_uninstall() should not be called statically in /home/users/1/main.jp-strix/web/tns/wp-includes/class-wp-hook.php on line 288
いずれは廃止されてしまう手法のようなので、これはuninstall.php のファイルを使用する手法へと変更しました。ということで、下記の12~14行、23~26行は使用していません。実際は消してしまっています。

<?php
		// class 続き↓
		//コメントが削除された時にeditkeyも削除する関数
		public function delete_editkey( $comment_id ) {
			delete_comment_meta( $comment_id, 'my_comment_editkey' );
		}

		/*
		プラグインがアンインストールされたときに
		optionを消去する関数を呼び出す外部から呼ばれる関数
		*/
		/*public function at_uninstall() {
			self::remove_option();
		}*/

		/*
		↓この関数を呼び出すat_uninstallはregister_uninstall_hookから呼び出されるが、
		このフックは特殊な関数で呼ばれており、その時点ではこのプラグインクラスはコールされておらず、
		疑似変数$thisを使ったり、クラス内のグローバル変数を利用できない。
		それ故にオプション名に変数を使うことが出来ず、このremove_optionをstaticにして
		静的にat_uninstallから呼び出す必要がある。
		*/
		/*private static function remove_option() {
			delete_metadata( 'comment', null, 'my_comment_editkey', '', true );
			delete_option( 'smplstc_commedt_option' );
		}*/
		// ↓class続く
?>
PHP
CopyExpand

編集および削除ボタンが押されてページが再読み込みされた時の処理の分岐のための関数。
プラグインの動作を決めるメインの関数といえます。
押されたボタンによって処理を分岐させ、editkey での認証、分岐されたそれぞれの処理でのhtml の表示や実際のコメントの更新、削除という事になります。
尚、この関数はアクションフック wp にてフックして呼び出しています。アクションフック wp はWP のオブジェクトが全てセットされ、条件分岐タグが最初に使えるアクションフックです。
ちなみにコメントを削除するwp_delete_comment() は二つ目のパラメータにtrue を指定しなければ、ゴミ箱に移動させるだけです。管理者はゴミ箱を見ればどういった内容のコメントが削除されたのか確認することが出来ます。しかし、編集の方はもともとどういった内容だったのかは確認することができないので、元の内容と新しい内容を本文にしてメールして通知するようにしています。

<?php
		// class 続き↓
		/*
		編集および削除ボタンが押されページが
		再読み込みされた時の処理の分岐関数
		*/
		public function branch_start() {
			$tmpcomid = 0;
			$tmpeditkey = '';
			$ignore_page = array();

			// 各option設定での各機能の起動の指定
			if ( '1' === $this->ret_option['only_single'] ) {
				if ( ! is_single() ) {
					$this->e_startup = 0;
				}
			}

			if ( '1' === $this->ret_option['disable_front'] ) {
				if ( is_front_page() ) {
					$this->e_startup = 0;
					$this->s_startup = 0;
				}
			}

			// ページidで指定してある起動させない固定ページでの指定
			if ( '' !== $this->ret_option['ignore_page'] ) {
				if ( false !== strpos( $this->ret_option['ignore_page'], ',' ) ) {
					$ignore_page = explode(',', $this->ret_option['ignore_page'] );
				} else {
					$ignore_page[] = $this->ret_option['ignore_page'];
				}
				foreach( $ignore_page as $val ) {
					if( is_page( intval( $val ) ) ) {
						$this->e_startup = 0;
						$this->s_startup = 0;
					}
				}
			}

			if ( '0' === $this->ret_option['en_def_spam'] ) {
				$this->s_startup = 0;
			}

			/*
			編集、削除ボタンが押されてページを再読み込みした時の処理の分岐
			editcom、delcomは編集、削除の指令
			editlast、dellastは最終的な編集、削除の命令
			*/
			if ( isset( $_POST['editcom'] ) or isset( $_POST['delcom'] ) ) {

				if ( isset( $_POST['comid'] ) and isset( $_POST['direditkey'] ) ) {
					$tmpcomid = intval( $_POST['comid'] );
					$tmpeditkey = trim($_POST['direditkey']);
					$opestr = 'e';

					if ( isset( $_POST['delcom'] ) ) {
						$opestr = 'd';
					}

					$tmpeditkey_hashed = md5( $tmpeditkey );
					$password_hashed = trim( get_comment_meta( $tmpcomid, 'my_comment_editkey', true ) );

					if ( $tmpeditkey_hashed === $password_hashed ) {

						//nonceを取得して認証を得る
						$my_nonce = isset( $_POST['my_nonce'] ) ? $_POST['my_nonce'] : null;
						if ( wp_verify_nonce( $my_nonce, wp_create_nonce( __FILE__ ) ) ) {
							$this->setvalue( $tmpcomid, $tmpeditkey, $opestr );
							$this->splstc_comedit_resist_script();
						} else {
							wp_die( 'Unfavorable situation has occurred' );
						}
					}
				}
			} elseif ( isset( $_POST['editlast'] ) or isset( $_POST['dellast'] ) ) {

				if ( isset( $_POST['lcomid'] ) and isset( $_POST['leditkey'] ) ) {
					$tmpcomid = intval( $_POST['lcomid'] );
					$tmpeditkey = trim($_POST['leditkey']);
					$opestr = 'e';
					$lastcon = '';

					if ( isset( $_POST['dellast'] ) ) {
						$opestr = 'd';
					}

					$tmpeditkey_hashed = md5( $tmpeditkey );
					$password_hashed = trim( get_comment_meta( $tmpcomid, 'my_comment_editkey', true ) );

					if ( $tmpeditkey_hashed === $password_hashed ) {

						//nonceを取得して認証を得る
						$my_nonce = isset( $_POST['com_nonce'] ) ? $_POST['com_nonce'] : null;
						if ( wp_verify_nonce( $my_nonce, wp_create_nonce( __FILE__ ) ) ) {
							$upcomres = 0;
							$sendstr = '';
							$author = isset( $_POST['lcomauth'] ) ? $_POST['lcomauth'] : 'no-data';
							$author = esc_attr( $author );

							if ( 'e' === $opestr ) {
								if ( isset( $_POST['lasthon'] ) ) {
									$upcont = $_POST['lasthon'];
									$lcomcont = isset( $_POST['lcomcont'] ) ? $_POST['lcomcont'] : 'no-data';
									$comarr = array(
										'comment_ID' => $tmpcomid,
										'comment_content' => $upcont,
									);
 
									$upcomres = wp_update_comment( $comarr );

									$sendstr="Edit comment - author : " . $author. " comment ID : " . $tmpcomid . "\n\n元:\n".$lcomcont."\n\n後:\n".$upcont;
								} else {
									wp_die( 'No data update comment content.' );
								}
							} elseif ( 'd' === $opestr ) {
								if ( '1' === $this->ret_option['en_delete'] ) {
									$upcomres = wp_delete_comment( $tmpcomid );
									$sendstr='Delete comment - author : ' . $author. ' comment ID : ' . $tmpcomid;
								}
							}
							if ( $upcomres ) {
								$admin_email = get_option( 'admin_email' );
								if ( '1' === $this->ret_option['en_notice_mail'] ) {
									wp_mail( $admin_email, 'Edit or Delete comment', $sendstr );
								}

							}
						} else {
							wp_die( 'Unfavorable situation has occurred.' );
						}
					}
				}
			}
		}
		// ↓class続く
?>
PHP
CopyExpand

あとまぁ、これはどうでもいいようなおまけな機能なのですが。
やはりメール入力が必須だとコメント送信の敷居が高くなるだろうなぁと思います。
かといってメールを必須ではなくし、メールボックスをなくしてしまっても、ということもあるので、ipアドレスからダミーなメールアドレスを作って入力するという機能です。
ここでちょっと迷ったのは、どこでコメントデータのemail アドレスを入れ込むかということです。いろいろやってみてフィルターフックpreprocess_comment が良さそうなので選択しました。このフックは wp-includes/comment.php のfunction wp_new_comment() のほぼ最初のところに記述してあります。

<?php
		// class 続き↓
		//mail addressにip addressから作ったダミーアドレスをセットする関数を登録
		public function set_dummy_mailaddress( $commentdata ) {
			$ipadrs = $_SERVER['REMOTE_ADDR'];
			$iptmp = explode('.', $ipadrs );
			$commentdata['comment_author_email'] = $iptmp[0] . $iptmp[1] . '@' . $iptmp[2] . '.' . $iptmp[3];
			return $commentdata;
		}
	}
	//↑classここまで
?>
PHP
CopyExpand

class Simplistic_Comment_User_Editable はここまでで終わり。
あとはこれだけ。

<?php
	//アンインストールした時にオプションを消去する関数の登録
	//この部分、uninstall.php ファイルを使用する方法に変更したため、もう使用していません
	/*if ( function_exists('register_uninstall_hook') ){
		register_uninstall_hook( __FILE__, array( 'Simplistic_Comment_User_Editable', 'at_uninstall' ) );
	}*/

	// class Simplistic_Comment_User_Editのインスタンスの生成
	$simplistic_comment_edit_start = new Simplistic_Comment_User_Editable();

	//↓管理画面のメニューにオプション設定ページを登録
	add_action( 'admin_menu', array( $simplistic_comment_edit_start, 'commedt_add_menu' ) );
?>
PHP
CopyExpand

このプラグインのjavascript とスタイルシート。
javascript : splstc_comedit.js

if ( 'undefined' === typeof smplstc_commedt ) {
	var smplstc_commedt = {};

	smplstc_commedt.doc = document;
	
	/*if ( null != smplstc_commedt.doc.getElementById( 'comment_check' ) ) {
		smplstc_commedt.doc.getElementById( 'comment_check' ).style.visibility = 'visible';
		smplstc_commedt.doc.getElementById( 'please_check' ).style.visibility = 'hidden';
	}*/
	
	if ( null != smplstc_commedt.doc.getElementById( 'erasecomfrm' ) ) {
		smplstc_commedt.doc.getElementById( 'erasecomfrm' ).onclick = function() {
			smplstc_commedt.doc.getElementById( 'comeditsec' ).style.display = 'none';
		}
	}
	
	if ( null != smplstc_commedt.doc.getElementById( 'comeditsec' ) ) {
		var colorclass = smplstc_commedt.doc.getElementById( 'comeditsec' ).getAttribute( 'class' );
		if ( 'gcolor' === colorclass ) {
			smplstc_commedt.doc.getElementById( 'comeditsec' ).style.background = 'linear-gradient(to right,#033001,#077C00,#ACF8A8,#077C00,#033001)';
		} else if ( 'ncolor' === colorclass ) {
			smplstc_commedt.doc.getElementById( 'comeditsec' ).style.background = 'linear-gradient(to right,#010314,#022ADF,#637BF5,#022ADF,#010314)';
		} else if ( 'wcolor' === colorclass ) {
			smplstc_commedt.doc.getElementById( 'comeditsec' ).style.background = 'linear-gradient(to right,#100009,#420027,#880355,#420027,#100009)';
		} else if ( 'bcolor' === colorclass ) {
			smplstc_commedt.doc.getElementById( 'comeditsec' ).style.background = 'linear-gradient(to right,#000000,#4E5050,#dbdbdb,#4E5050,#000000)';
		}
	}
	
	smplstc_commedt.classlist = smplstc_commedt.doc.getElementsByClassName( 'comeditorderbt' );
	smplstc_commedt.classlistnum = smplstc_commedt.classlist.length;
	for ( var i = 0; i < smplstc_commedt.classlistnum; i++ ) {
		smplstc_commedt.classlist[ i ].onclick = function() {
			smplstc_commedt.targetid = this.getAttribute( 'id' );
			smplstc_commedt.targetid = smplstc_commedt.targetid.replace( 'cmeditbt-', '' );
			smplstc_commedt.doc.dircomform.comid.value = smplstc_commedt.targetid;
			smplstc_commedt.result = prompt( 'Enter editkey' );
	
			if ( smplstc_commedt.result ) {
				smplstc_commedt.doc.dircomform.direditkey.value = smplstc_commedt.result;
				smplstc_commedt.doc.dircomform.submit();
			}
		}
	}
}
JavaScript
CopyExpand

スタイルシート : splstc_comedit_r.css

@charset "UTF-8";

#comment_check{
	visibility:visible;
}

#please_check{
	visibility:hidden;
}

#dircomfrm{
	padding:10px;
	border:4px double #A09E9E;
	border-radius: 10px;
}

#dircomfrm label{
	font-size:0.8em;
}

#dircomfrm input[type=submit]{
	display:inline;
}

#comid{
	width:80px;
}

#direditkey{
	width:160px;
}

#comeditsec{
	position:fixed;
	width:100%;
	height:100%;
	top:0px;
	left:0px;
	z-index:30;
	text-align:center;
	background:linear-gradient(to right,#2F0301,#7F2A28,#DF7C6C,#7F2A28,#2F0301);
}

#comeditfrm{
	position:relative;
	margin:3% auto;
	padding:20px;
	background-color:#f5f5f5;
	border:4px double #ebebeb;
	border-radius: 10px;
	box-shadow:0px 5px 5px 5px rgba(0,0,0,0.4);
}

@media screen and (min-width:770px){
	#comeditfrm{
		width:600px;
	}

	#dircomfrm input[type=text]{
		display:inline;
	}
}

@media screen and (max-width:770px){
	#comeditfrm{
		width:80%;
	}

	#dircomfrm input[type=text]{
		display:block;
	}
}

#comeditfrm textarea{
	width:80%;
}

#erasecomfrm{
	position:absolute;
	top:5px;
	right:10px;
	font-size:1.2em;
}

#erasecomfrm:hover{
	cursor:pointer;
}

.comeditorderbt{
	display:block;
	width:50px;
	padding:2px;
	color:#B8A329;
	text-align:center;
	background:linear-gradient(#ffffff 0%,#CCCACA 100%);
	border:solid 1px #aaa;
	border-radius:5px;
	text-shadow: 0 1px #fff;
	box-shadow:0px 1px 2px 2px rgba(50,50,50,0.2);
}

.comeditorderbt:hover{
	cursor:pointer;
	background-color:#01DFB3;
	background:linear-gradient(#ffffff 0%,#01DFB3 100%);
}
CSS
CopyExpand

以上です。
実際のプラグイン内包のファイルもほぼこれと同じですが、少し違うのはoption の説明やらフォームのラベルやらが英語表記できるようにちょっと変えてあります。ただし、入れてある英語はただそれらしい雰囲気の単語を並べただけのでたらめなもの。後々、ちゃんと直すつもりです。

とりあえずローカルな環境のWordPress とさくらにあるものとロリポップ(このサイト)にあるWordPress でテストしましたが問題無く動いています。

問題無く動くと思うんですけど。動かなかったらご勘弁ください。
何も起こりえないのですが、一応、決まり事を。
このプラグインを使用する場合は完全自己責任で行ってください。
何らかの損害が発生しても一切関知しません。
下のリンクからダウンロードできると思います。
※2019/12/5 にちょっと手を入れてversion1.1としています。
wordpress5.3PHP7.3 で確認済です。
※2021/7/21 現在、プラグインリニューアルアップデート中!

Sanbanse Funabashi

Top

スクロールさせるか画像をクリックすると元に戻ります。