tegalog

てがろぐにまいるどWEB拍手ぐれーと設置するためにPHP8用にカスタマイズした

以前、てがろぐにまいるどWEB拍手ぐれーと(試用版)をつけてみるメモという記事を作成したのですが、まいるどWEB拍手ぐれーと公式がPHP7以降に対応する予定がないと聞き、WEB拍手としてそのまま使えるし、まあいっか。みたいな感じで終わっていました。

が、カスタマイズしたら使えないかな?と思い、まいるどWEB拍手ぐれーとを買ってみました
この記事は試行錯誤しながらPHP8で動くようにカスタマイズしたよの記録になります。

お約束

誰かの役にたつかもしれませんが、全くたたないかもしれません。よろしゅう。

※「拍手(+メッセージ)が送れる、メール通知機能が動く」といった機能は確認していますが、すべての機能を確認したわけではないので、ご了承ください。(例:インポート機能はまあいっかなと思って確認してません)
※カスタマイズがうまくいってもシェアウェアスクリプトのため再配布はしません。自己責任でライセンス版を購入、プログラム修正をしてください。
※今回のカスタマイズをしてもお使いのサーバ、契約内容などによっては動かない可能性があります。動作補償はまったくできません。
※個別サポートなども行いません。多分。

前提

2024年8月時点の動作確認として以下の情報をご案内します。
・レンタルサーバはlolipopを使用
・PHP設定は8.3(モジュール版)を使用(※エラーを確認するため一時的に8.3CGI版に直しましたがどちらでも動きました)
・てがろぐはVer 4.4.0を使用(てがろぐ本体のアップデートをまとめた記事はこちら
・てがろぐにはいいねボタン・改を設置していましたが、一旦こちらの設定は削除しています(設置方法はこちら

また、設置場所は前回と同じく、まいるどWEB拍手ぐれーとをてがろぐのフォルダ内に設置するイメージで進めます。
てがろぐが設置されているフォルダ名をtegalogとすることにしましょう。
下記のような感じです。
https://example.com/tegalog/tegalog.cgi
その場合、てがろぐを設置したディレクトリは下記のようになります。
https://example.com/tegalog/mwhg/

修正箇所はめちゃくちゃ多い

PHP 8.1.0 以降、$GLOBALS 配列全体を書き換える操作はサポートされなくなりました。
参考:$GLOBALS

大まかな原因としては、$GLOBALSが使えなくなったことがプログラム全体に影響していました。
その他PHP8で非推奨、削除されたものなどが影響しているので、適宜修正していく。そんな感じです。

エラーが出た時。


おそらくPHP8以降に対応していない何かしらが原因で発生しています。そのエラーを動くまで潰していきます

原因を特定するためにエラーをブラウザに表示させます。
ロリポップでPHPのエラーの確認方法は別記事にしました
お使いのサーバを確認してください。

てがろぐのスキン修正

本来の設置完了までの流れとしては、まいるどWEB拍手ぐれーとの購入→まいるどWEB拍手ぐれーとの設置→てがろぐのスキン修正→まいるどWEB拍手ぐれーとの動作確認+プログラム修正、って感じなのですが、プログラムの修正が長いので、てがろぐのスキンの修正を先にやってしまって、そのあとてがろぐにまいるどWEB拍手ぐれーとの購入、設置、修正を紹介していきます。
また、配布ページの設置方法ページにある、拍手ボタン設置方法1(JavaScript)を使用します。

skin-cover.html

お使いのスキンのskin-cover.htmlのheadタグ内にjavascriptのコードを記述します。

<script type="text/javascript" src="https://example.com/tegalog/mwhm/js/jquery-1.9.1.min.js" charset="utf-8"></script>
<script type="text/javascript" src="https://example.com/tegalog/mwhm/js/jquery.mwhg.js" charset="utf-8"></script>

もしヘッダーにいれて動かなかったら、</body>直前でもいいかも…。また、他のjsとバッティングしないように注意してください。

skin-onelog.html

skin-onelog.htmlに下記のコードを記述します。

<div class="mwhg_point" id="★"></div>

★に任意のIDを指定します。半角英数字と_(アンダーバー)-(ハイフン)が使用可能です。複数設置する場合はID名が被らないように注意してください。
参考:マニュアル内より

記述された名前によって区別されるようなので、今回もてがろぐの投稿番号を利用します。

<div class="mwhg_point" id="[[POSTID]]"></div>

このへんにいれておきました。
※下のシェアボタンのソースコードはこっちの記事で設置したシェアボタンです。

修正したスキンをアップロードします。

まずは購入から。

まいるどWEB拍手ぐれーとを買ってください。話はそれからだ。
「ライセンス購入」ボタンをクリックして、必要な情報を送ります。そうすると管理者様より振込先情報をご連絡いただくので、お振込みします。
送った旨を返信するとスムーズかもしれません。

管理者様が振込が完了したことを確認された後、ダウンロード情報の案内が返信されるので、ダウンロードを完了します。

ダウンロードデータ

ダウンロードしたzipを解凍すると、「mwhg」というフォルダができます。
こちらを使用していきます。
mwhgフォルダのファイル構成はこんな感じ。

設置方法

配布ページの設置方法を参考に設置・パーミッションの変更をしていきます。

ファイルの修正


config.phpのパスワードを変更します。


js/jquery.mwhg.jsを開き、PHP設置先ディレクトリURLを変更します。

まいるどWEB拍手ぐれーとの設置URLはこんな感じになります。
https://example.com/tegalog/mwhg/

サーバーにアップロード

https://example.com/tegalog/以下に、mwhgのフォルダをごっそりアップロードします。
パーミッションの変更が必要なディレクトリ(フォルダ)とファイルは配布ページの設置方法のページを見ながら変更してください。

admin.phpにアクセス

admin.phpにアクセスして正常に表示されていれば設置成功です。
https://example.com/tegalog/mwhg/admin.php
多分、おそらく、きっと、エラーがでる。

common.phpの修正

Fatal error: $GLOBALS can only be modified using the $GLOBALS[$name] = $value syntax in /サーバ情報/mwhg/common.php on line 18

common.phpの18行目あたりでFatal errorをだしているようです。
JSONファイルを読み込んでその内容を$GLOBALSに直接設定しようとしていますが、PHP8ではこのような直接の操作がエラーになるようです。
グローバル変数を使わずに関数やクラスを使って設定データを管理する方がいいそうなので、下記を削除。

// 設定ファイル取得
$GLOBALS = json_decode(file_get_contents(DATADIR. CONFIGJSON), true);
$GLOBALS['system'] = json_decode(file_get_contents(DATADIR. SYSTEMJSON), true);

// 実行ファイル
$GLOBALS['script'] = basename($_SERVER['SCRIPT_NAME']);

さらに下記ConfigLoaderクラスを追加。

class ConfigLoader {
    private $config;
    private $system;
    private $script;
    private $configFile;
    private $systemFile;

    public function __construct($configFile, $systemFile) {
        if (!file_exists($configFile) || !file_exists($systemFile)) {
            throw new Exception('Configuration or system file does not exist.');
        }

        $this->configFile = $configFile;
        $this->systemFile = $systemFile;

        $this->config = $this->loadFile($configFile);
        $this->system = $this->loadFile($systemFile);

        $this->script = basename($_SERVER['SCRIPT_NAME']);
    }

    private function loadFile($file) {
        $data = json_decode(file_get_contents($file), true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            throw new Exception('Invalid JSON in file: ' . $file);
        }
        return $data;
    }

    public function getScript() {
        return $this->script;
    }

    public function setScript($script) {
        $this->script = $script;
    }

    public function getConfig($key = null) {
        return $key ? ($this->config[$key] ?? null) : $this->config;
    }

    public function setConfig($key, $value) {
        $this->config[$key] = $value;
    }
    
    public function saveConfig() {
        file_put_contents($this->configFile, json_encode($this->config, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    }

    public function getClapConfig() {
        return $this->config['clapConfig'] ?? [];
    }
    
    public function setClapConfig(array $clapConfig) {
        if (isset($this->config['clapConfig']) && is_array($clapConfig)) {
            $this->config['clapConfig'] = array_merge($this->config['clapConfig'], $clapConfig);
        } else {
            $this->config['clapConfig'] = $clapConfig;
        }
    }

    public function saveClapConfig() {
        if (isset($this->config['clapConfig'])) {
            $clapConfigData = json_encode(['clapConfig' => $this->config['clapConfig']], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
            if ($clapConfigData === false) {
                throw new RuntimeException('JSONエンコードエラー: ' . json_last_error_msg());
            }

            file_put_contents($this->configFile, $clapConfigData);
        } else {
            throw new RuntimeException('clapConfigが設定されていません');
        }
    }

    public function getSystem($key = null) {
        return $key ? ($this->system[$key] ?? null) : $this->system;
    }

    public function setSystem(array $systemConfig) {
        $this->system = $systemConfig;
    }

    public function saveSystem() {
        if (empty($this->systemFile)) {
            throw new ValueError('System file path cannot be empty.');
        }

        file_put_contents($this->systemFile, json_encode($this->system, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    }

    public function setSystemData(array $systemData) {
        $this->system = array_merge($this->system, $systemData);
    }

    public function saveConfigToFile($filePath) {
        if (empty($filePath)) {
            throw new ValueError('File path cannot be empty.');
        }

        $configData = array_merge($this->config, [
            'path' => $this->getConfig('path'),
        ]);

        file_put_contents($filePath, json_encode($configData, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    }
}

メソッドはそれぞれ拍手の設定を保存したり取り出したり、システム設定を保存したり取り出したりしています。

system.phpの修正

Fatal error: Uncaught Error: Call to undefined function get_magic_quotes_gpc() in /サーバ情報/mwhg/system.php:113 Stack trace: #0 /サーバ情報/mwhg/admin.php(1186): decode('5') #1 /サーバ情報/mwhg/admin.php(42): clapconfig() #2 {main} thrown in /サーバ情報/mwhg/system.php on line 113

さらに、system.phpの113行目にあるget_magic_quotes_gpcの行。

if (get_magic_quotes_gpc() == 1) $param = stripslashes($param);

get_magic_quotes_gpcはPHP8ではこの関数は存在しないため、削除します。

※エラーをだしている行番号はプログラムを修正していくにあたりここの記事とはズレていくかもしれませんので、お使いのファイルを適宜バックアップしたうえでエラーを確認しながら修正を進めてください。

mwhg.phpの修正

mwhg.phpでは主に$GLOBALSになっている箇所を修正していくことになります。

require_once('./common.php');

上記はcommon.phpを読み込むコードなので、その行の下に下記を追加します。

global $configLoader;
$configLoader = new ConfigLoader(DATADIR . CONFIGJSON, DATADIR . SYSTEMJSON);
global $clapConfig;
$clapConfig = $configLoader->getClapConfig();
function getClapConfig() {
	global $clapConfig;
	return $clapConfig;
}

また、$GLOBALSが使われている箇所の修正をしなければいけません。

message_write()

mwhg.php内をスクロールしていくと、こんな感じの場所があります。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ メッセージ書き込み
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function message_write() {
	global $PARAM;

上の場所を探したらglobal $PARAM;の上に追加

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ メッセージ書き込み
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function message_write() {
	global $configLoader;
	$configLoader = new ConfigLoader(DATADIR . CONFIGJSON, DATADIR . SYSTEMJSON);
	$clapConfig = $configLoader->getConfig('clapConfig');
	$system = $configLoader->getSystem();

	global $PARAM;

それから、message_write関数内の$GLOBALSが使われている箇所を探して修正していきます。

$CLAPCONFIG = array_merge($GLOBALS['clapConfig'], $CLAPDATA['config']);

上記を下に変更。

$CLAPCONFIG = array_merge($clapConfig, $CLAPDATA['config']);

次にいきます。

	// メール送信
	if ( ! empty($GLOBALS['system']['mailAddress'])) {
		if (($GLOBALS['system']['mailFlgMsg'] && ! empty($PARAM['message']))
			or ($GLOBALS['system']['mailFlgTkb'] && ! empty($PARAM['tkb']))
			or ($GLOBALS['system']['mailFlgName'] && ! empty($PARAM['name']))
			or ($GLOBALS['system']['mailFlgEval'] && ! empty($PARAM['eval']))) {
			$to = $GLOBALS['system']['mailAddress'];
			$fromadrs = $GLOBALS['system']['mailAddress'];
			$fromname = "まいるどWEB拍手ぐれーと";
			$subject = "【拍手通知】メッセージがありました";
			$body = "以下の内容で拍手メッセージがありました。\n\n".
								"---------------------------------------\n";
			if ( ! empty($PARAM['name'])) $body .= "【名前】". $PARAM['name']. "\n";
			if ( ! empty($PARAM['eval'])) $body .= "【評価】". $PARAM['eval']. "\n";
			if ( ! empty($PARAM['tkb'])) $body .= "【定形文】". $PARAM['tkb']. "\n";
			$body .= "【メッセージ】".  str_replace("<br />", "\n", $PARAM['message']). "\n".
								"【日時】". date("Y/m/d"). '('. week(time()). ') '. date("H:i"). "\n".
								"---------------------------------------\n";
			sendmail($to, $fromadrs, $fromname, $subject, $body);
		}
	}

上記を下に変更。

	// メール送信
	if (!empty($system['mailAddress'])) {
	    if (($system['mailFlgMsg'] && !empty($PARAM['message']))
	        || ($system['mailFlgTkb'] && !empty($PARAM['tkb']))
	        || ($system['mailFlgName'] && !empty($PARAM['name']))
	        || ($system['mailFlgEval'] && !empty($PARAM['eval']))) {
	        $to = $system['mailAddress'];
	        $fromadrs = $system['mailAddress'];
	        $fromname = "まいるどWEB拍手ぐれーと";
	        $subject = "【拍手通知】メッセージがありました";
	        $body = "以下の内容で拍手メッセージがありました。\n\n" .
	            "---------------------------------------\n";
	        if (!empty($PARAM['name'])) $body .= "【名前】" . $PARAM['name'] . "\n";
	        if (!empty($PARAM['eval'])) $body .= "【評価】" . $PARAM['eval'] . "\n";
	        if (!empty($PARAM['tkb'])) $body .= "【定形文】" . $PARAM['tkb'] . "\n";
	        $body .= "【メッセージ】" . str_replace("<br />", "\n", $PARAM['message']) . "\n" .
	            "【日時】" . date("Y/m/d") . '(' . week(time()) . ') ' . date("H:i") . "\n" .
	            "---------------------------------------\n";
	        sendmail($to, $fromadrs, $fromname, $subject, $body);
	    }
	}

clap_write()

clap_write()関数も修正します。まずは下記を探す。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ 拍手書き込み
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function clap_write() {
	global $PARAM;

そしたらまたglobal $PARAM;の上に追加します。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ 拍手書き込み
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function clap_write() {
	global $configLoader;
	$configLoader = new ConfigLoader(DATADIR . CONFIGJSON, DATADIR . SYSTEMJSON);
	$clapConfig = $configLoader->getConfig('clapConfig');
	$system = $configLoader->getSystem();
	global $PARAM;

で、$GLOBALSの箇所を修正していきます。

	// アクセス制限
	foreach ($GLOBALS['system']['denyHosts'] as $host) {
		if ($host === '') continue;
		$denyhost = preg_replace("/\./", "\\.", $host);
		$denyhost = preg_replace("/\*/", ".*", $denyhost);
		if (preg_match("/$denyhost/i", $ushost)) {
			error(array('status' => '_DENYNG_', 'errormsg' => 'アクセスが許可されていません'));
		}
	}

下記に変更。

	// アクセス制限
	if (!empty($system['denyHosts']) && is_array($system['denyHosts'])) {
	    foreach ($system['denyHosts'] as $host) {
	        if ($host === '') continue;
	        $denyhost = preg_replace("/\./", "\\.", $host);
	        $denyhost = preg_replace("/\*/", ".*", $denyhost);
	        if (preg_match("/$denyhost/i", $ushost)) {
	            error(array('status' => '_DENYNG_', 'errormsg' => 'アクセスが許可されていません'));
	        }
	    }
	}
$CLAPCONFIG = array_merge($GLOBALS['clapConfig'], $CLAPDATA['config']);

上記箇所を下記に変更。

$CLAPCONFIG = array_merge($clapConfig, $CLAPDATA['config']);
	// ユーザー個別拍手数
	$ckchain = get_cookie($_clapid, 0);
	if ($GLOBALS['system']['cookieCTRL'] && $CLAPCONFIG['chain'] > 0 && $ckchain >= $CLAPCONFIG['chain']) {
		error(array('status' => '_CLAPPING_OVER_', 'errormsg' => '拍手数が上限を超えています'), false);
	}
	$userclapcnt = $ckchain + 1;

上記箇所を下記に変更。

	// ユーザー個別拍手数
	$ckchain = get_cookie($_clapid, 0);
	if ($system['cookieCTRL'] && $CLAPCONFIG['chain'] > 0 && $ckchain >= $CLAPCONFIG['chain']) {
		error(array('status' => '_CLAPPING_OVER_', 'errormsg' => '拍手数が上限を超えています'), false);
	}
	$userclapcnt = $ckchain + 1;
				// ホストチェックによる連続拍手制限
				if ($GLOBALS['system']['hostCTRL'] && $CLAPCONFIG['chain'] > 0 && $chain > $CLAPCONFIG['chain']) {
					file_unlock($lfh); // ファイルロック解除
					error(array('status' => '_CLAPPING_OVER_', 'errormsg' => '拍手数が上限を超えています'), false);
				}

上記箇所を下記に変更。

				// ホストチェックによる連続拍手制限
				if ($system['hostCTRL'] && $CLAPCONFIG['chain'] > 0 && $chain > $CLAPCONFIG['chain']) {
					file_unlock($lfh); // ファイルロック解除
					error(array('status' => '_CLAPPING_OVER_', 'errormsg' => '拍手数が上限を超えています'), false);
				}
if (empty($CLAPDATA['url']) && $GLOBALS['system']['getReferer']) $CLAPDATA['url'] = getenv('HTTP_REFERER');

上記箇所を下記に変更。

if (empty($CLAPDATA['url']) && $system['getReferer']) $CLAPDATA['url'] = getenv('HTTP_REFERER');
		// 新規ファイルから書き込み
		$CLAPDATA = array(
			'clapcnt' => 1,
			'evalcnt' => 0,
			'evalttl' => 0,
			'evalmean' => '0.0',
			'label' => $PARAM['label'],
			'url' => ($GLOBALS['system']['getReferer']) ? getenv('HTTP_REFERER') : '',
			'config' => array(
				'on' => array(),
			),
		);

上記箇所を下記に変更。

		// 新規ファイルから書き込み
		$CLAPDATA = array(
			'clapcnt' => 1,
			'evalcnt' => 0,
			'evalttl' => 0,
			'evalmean' => '0.0',
			'label' => $PARAM['label'],
			'url' => ($system['getReferer']) ? getenv('HTTP_REFERER') : '',
			'config' => array(
				'on' => array(),
			),
		);
	// クッキーセット
	if ($GLOBALS['system']['cookieCTRL'] && ! is_ajax()) {
		$chainset = get_cookie($_clapid, 0) + 1;
		$timeout = time() + 60 * 60 * 24 * 30;
		setcookie($_clapid, $chainset, $timeout, '/', getenv('SERVER_NAME'));
	}

上記箇所を下記に変更。

	// クッキーセット
	if ($system['cookieCTRL'] && ! is_ajax()) {
		$chainset = get_cookie($_clapid, 0) + 1;
		$timeout = time() + 60 * 60 * 24 * 30;
		setcookie($_clapid, $chainset, $timeout, '/', getenv('SERVER_NAME'));
	}

view()

いよいよ拍手ボタン表示まわりですね。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ 拍手ボタン表示
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function view() {
	global $PARAM;

上記箇所を下記に変更。

function view() {
	global $configLoader;
	$configLoader = new ConfigLoader(DATADIR . CONFIGJSON, DATADIR . SYSTEMJSON);
	$clapConfig = $configLoader->getConfig('clapConfig');
	$system = $configLoader->getSystem();

	global $PARAM;
	// デフォルト
	$clapdef = array(
		'clapcnt' => 0,
		'evalcnt' => 0,
		'evalttl' => 0,
		'evalmean' => '0.0',
		'label' => '',
		'url' => '',
		'config' => array(
			'on' => array(),
		) + $GLOBALS['clapConfig'],
	);

上記箇所を下記に変更。

	// デフォルト
	$clapdef = array(
		'clapcnt' => 0,
		'evalcnt' => 0,
		'evalttl' => 0,
		'evalmean' => '0.0',
		'label' => '',
		'url' => '',
		'config' => array(
			'on' => array(),
		) + $clapConfig,
	);
$CLAPDATA['config'] = array_merge($GLOBALS['clapConfig'], $CLAPDATA['config']);

上記箇所を下記に変更。

$CLAPDATA['config'] = array_merge($clapConfig, $CLAPDATA['config']);

admin.phpの修正

めちゃくちゃ多い。mwhg.php以上に多い。
admin.phpでは$GLOBALSになっている箇所を修正と、基本拍手設定ページとシステム設定ページで保存したデータをそれぞれconfig.jsonとsystem.jsonに格納していくことになるので、その修正になります。多いぞ!

require_once('./common.php');

common.phpを読み込んでる行の下に、下記を追加。

global $configLoader;
$configLoader = new ConfigLoader(DATADIR . CONFIGJSON, DATADIR . SYSTEMJSON);
global $clapConfig;
$clapConfig = $configLoader->getClapConfig();
function getClapConfig() {
	global $clapConfig;
	return $clapConfig;
}

login()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ログイン
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function login() {
	$password = get_post('password');
	if ($password !== MSKEY) {
		$_SESSION['error'] = 'パスワードが間違っています';
	} else {
		session_regenerate();
		$_SESSION['password'] = $password;
	}
	location($GLOBALS['script']);
}

上記を下記に変更。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ログイン
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function login() {
	global $configLoader;
	$scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');

	$password = get_post('password');
	if ($password !== MSKEY) {
		$_SESSION['error'] = 'パスワードが間違っています';
	} else {
		session_regenerate();
		$_SESSION['password'] = $password;
	}
	location($scriptAction);
}

ここの修正がうまくいくと、ログインページが表示されるかと思います。

logout()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ログアウト
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function logout() {
	$sessname = get_cookie(session_name());
	$_SESSION = array();
	if ( ! empty($sessname)) setcookie(session_name(), '', time()-42000, '/');
	// if (get_cookie('alk') != null) setcookie('alk', '', time()-42000, '/');
	session_destroy();
	location($GLOBALS['script']);
}

上記を下記に変更。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ログアウト
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function logout() {
	global $configLoader;
	$scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');
	
	$sessname = get_cookie(session_name());
	$_SESSION = array();
	if ( ! empty($sessname)) setcookie(session_name(), '', time()-42000, '/');
	// if (get_cookie('alk') != null) setcookie('alk', '', time()-42000, '/');
	session_destroy();
	location($scriptAction);
}

ここの修正がうまくいくと、ログアウトされたあと、ログインページにリダイレクトされるかと思います。

top()

ログイン後のページです。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ トップページ
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function top() {
	$_SESSION['msgonly'] = get_query('msgonly', get_session('msgonly', 'off'));
	$_SESSION['viewtype'] = get_query('viewtype', get_session('viewtype', 'timeline'));
	$_SESSION['viewlabel'] = get_query('viewlabel', get_session('viewlabel', 'view'));
	$_SESSION['viewhost'] = get_query('viewhost', get_session('viewhost', 'view'));

上記を下記に変更。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ トップページ
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function top() {
	global $configLoader;
	$scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');

	$_SESSION['msgonly'] = get_query('msgonly', get_session('msgonly', 'off'));
	$_SESSION['viewtype'] = get_query('viewtype', get_session('viewtype', 'timeline'));
	$_SESSION['viewlabel'] = get_query('viewlabel', get_session('viewlabel', 'view'));
	$_SESSION['viewhost'] = get_query('viewhost', get_session('viewhost', 'view'));
<a href="'. $GLOBALS['script']. '?'. $_SERVER['QUERY_STRING']. '&viewtype=timeline" class="btn btn-default btn-sm'. (($_SESSION['viewtype'] === 'timeline') ? ' active' : ''). '">タイムライン</a>
<a href="'. $GLOBALS['script']. '?'. $_SERVER['QUERY_STRING']. '&viewtype=list" class="btn btn-default btn-sm'. (($_SESSION['viewtype'] === 'list') ? ' active' : ''). '">リスト</a>

上記を下記に変更。

<a href="'. $scriptAction. '?'. $_SERVER['QUERY_STRING']. '&viewtype=timeline" class="btn btn-default btn-sm'. (($_SESSION['viewtype'] === 'timeline') ? ' active' : ''). '">タイムライン</a>
<a href="'. $scriptAction. '?'. $_SERVER['QUERY_STRING']. '&viewtype=list" class="btn btn-default btn-sm'. (($_SESSION['viewtype'] === 'list') ? ' active' : ''). '">リスト</a>
<a href="'. $GLOBALS['script']. '?'. date('&\y\e\a\r=Y&\m\o\n\t\h=n&\d\a\y=d', strtotime(date('Y-m-d', $stttime).' -1 month')).'" title="back month" class="btn btn-default btn-xs"><i class="glyphicon glyphicon-chevron-left"></i></a>
<a class="btn btn-default btn-xs disabled">'. date('Y年n月', $stttime). '</a>
<a href="'. $GLOBALS['script']. '?'. date('&\y\e\a\r=Y&\m\o\n\t\h=n&\d\a\y=d', strtotime(date('Y-m-d', $stttime). ' +1 month')).'" title="next month" class="btn btn-default btn-xs"><i class="glyphicon glyphicon-chevron-right"></i></a>

上記を下記に変更。

<a href="'. $scriptAction. '?'. date('&\y\e\a\r=Y&\m\o\n\t\h=n&\d\a\y=d', strtotime(date('Y-m-d', $stttime).' -1 month')).'" title="back month" class="btn btn-default btn-xs"><i class="glyphicon glyphicon-chevron-left"></i></a>
<a class="btn btn-default btn-xs disabled">'. date('Y年n月', $stttime). '</a>
<a href="'. $scriptAction. '?'. date('&\y\e\a\r=Y&\m\o\n\t\h=n&\d\a\y=d', strtotime(date('Y-m-d', $stttime). ' +1 month')).'" title="next month" class="btn btn-default btn-xs"><i class="glyphicon glyphicon-chevron-right"></i></a>
if (file_exists($dfile)) {
	// 拍手があった日
	echo '<a href="'.$GLOBALS['script']. '?year='.$year.'&month='.$month.'&day='.$i.'" class="wrap">'.$i.'</a></td>';
} else {
	echo '<span class="wrap">'.$i.'</span></td>';
}

上記を下記に変更。

if (file_exists($dfile)) {
	// 拍手があった日
	echo '<a href="'.$scriptAction. '?year='.$year.'&month='.$month.'&day='.$i.'" class="wrap">'.$i.'</a></td>';
} else {
	echo '<span class="wrap">'.$i.'</span></td>';
}
<a href="'. $GLOBALS['script']. '?specify=month">一ヶ月</a>/<a
href="'. $GLOBALS['script']. '?specify=week">一週</a>/<a
href="'. $GLOBALS['script']. '?specify=yesterday">昨日</a>/<a
href="'. $GLOBALS['script']. '?">今日</a>
<br />
<hr />
<form action="'. $GLOBALS['script']. '" id="datesel">

上記を下記に変更。

<a href="'. $scriptAction. '?specify=month">一ヶ月</a>/<a
href="'. $scriptAction. '?specify=week">一週</a>/<a
href="'. $scriptAction. '?specify=yesterday">昨日</a>/<a
href="'. $scriptAction. '?">今日</a>
<br />
<hr />
<form action="'. $scriptAction. '" id="datesel">
<div class="checkbox">
	<label><input type="checkbox" onclick="location.href=\''. $GLOBALS['script']. '?'. $_SERVER['QUERY_STRING']. '&msgonly='. (($_SESSION['msgonly'] === 'on') ? 'hidden\'" checked="checked"' : 'on\'"'). '> メッセージ付きの拍手のみ表示する</label>
</div>
<div class="checkbox">
	<label><input type="checkbox" onclick="location.href=\''. $GLOBALS['script']. '?'. $_SERVER['QUERY_STRING']. '&viewlabel='. (($_SESSION['viewlabel'] === 'view') ? 'hidden\'" checked="checked"' : 'view\'"'). '> ラベルを表示する</label>
</div>
<div class="checkbox">
	<label><input type="checkbox" onclick="location.href=\''. $GLOBALS['script']. '?'. $_SERVER['QUERY_STRING']. '&viewhost='. (($_SESSION['viewhost'] === 'view') ? 'hidden\'" checked="checked"' : 'view\'"'). '> ホスト名を表示する</label>
</div>

上記を下記に変更。

<div class="checkbox">
	<label><input type="checkbox" onclick="location.href=\''. $scriptAction. '?'. $_SERVER['QUERY_STRING']. '&msgonly='. (($_SESSION['msgonly'] === 'on') ? 'hidden\'" checked="checked"' : 'on\'"'). '> メッセージ付きの拍手のみ表示する</label>
</div>
<div class="checkbox">
	<label><input type="checkbox" onclick="location.href=\''. $scriptAction. '?'. $_SERVER['QUERY_STRING']. '&viewlabel='. (($_SESSION['viewlabel'] === 'view') ? 'hidden\'" checked="checked"' : 'view\'"'). '> ラベルを表示する</label>
</div>
<div class="checkbox">
	<label><input type="checkbox" onclick="location.href=\''. $scriptAction. '?'. $_SERVER['QUERY_STRING']. '&viewhost='. (($_SESSION['viewhost'] === 'view') ? 'hidden\'" checked="checked"' : 'view\'"'). '> ホスト名を表示する</label>
</div>

これでトップページの左側にでてたエラーが修正されるんじゃないかな~。

datetotal($stttime, $endtime)

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ 日付別拍手
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function datetotal($stttime, $endtime) {
	$url = $GLOBALS['script']. '?'. $_SERVER['QUERY_STRING'];

上記を下記に変更。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ 日付別拍手
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function datetotal($stttime, $endtime) {
	global $configLoader;
	$scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');

	$url = $scriptAction. '?'. $_SERVER['QUERY_STRING'];

clapid()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ID一覧
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function clapid() {
	$cachefile = DATADIR. 'all_id.json';

上記を下記に変更。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ID一覧
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function clapid() {
	global $configLoader;
	$scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');
	$clapConfig = $configLoader->getConfig('clapConfig');

	$cachefile = DATADIR. 'all_id.json';
location($GLOBALS['script']. '?act=clapid');

上記を下記に変更。

location($scriptAction. '?act=clapid');

※これ数か所あるので、スクロールしていく途中で見つけたら幾度修正してください。

$CONFIG = array_merge($GLOBALS['clapConfig'], $DATA['config']);

上記を下記に変更。

$CONFIG = array_merge($clapConfig, $DATA['config']);
<form action="{$GLOBALS['script']}?act=clapid&cmd={$cmd}" method="post" id="tool-form" class="form-horizontal">

上記を下記に変更。

<form action="{$scriptAction}?act=clapid&cmd={$cmd}" method="post" id="tool-form" class="form-horizontal">

id_confg_form($id, $CON)

// ▼ 拍手ボタン設定フォーム(ajax)
function id_confg_form($id, $CON) {
	$CON = array_merge($GLOBALS['clapConfig'], $CON);

	// 設定有効チェックボックス
	$CONCHECK = array();
	foreach (array_keys($GLOBALS['clapConfig']) as $key) {
		$CONCHECK[$key] = '<span class="input-group-addon"><input type="checkbox" name="on_'. $key. '" value="true"';
		if (isset($CON['on'][$key]) && $CON['on'][$key] === true) $CONCHECK[$key] .= ' checked="checked"';
		$CONCHECK[$key] .= '></span>';
	}

上記を下記に変更。

// ▼ 拍手ボタン設定フォーム(ajax)
function id_confg_form($id, $CON) {
	global $configLoader;

	// PHP変数を事前に処理
	$scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');

	$clapConfig = $configLoader->getConfig('clapConfig');

	$CON = array_merge($clapConfig, $CON);

	// 設定有効チェックボックス
	$CONCHECK = array();
	foreach (array_keys($clapConfig) as $key) {
		$CONCHECK[$key] = '<span class="input-group-addon"><input type="checkbox" name="on_'. $key. '" value="true"';
		if (isset($CON['on'][$key]) && $CON['on'][$key] === true) $CONCHECK[$key] .= ' checked="checked"';
		$CONCHECK[$key] .= '></span>';
	}
<form action="'. $GLOBALS['script']. '?act=clapid&cmd=config" method="post" id="tool-form" class="form-horizontal">

上記を下記に変更。

<form action="'. $scriptAction. '?act=clapid&cmd=config" method="post" id="tool-form" class="form-horizontal">

ここまでadmin.phpのファイルを上から順に修正していってるんですけど、基本拍手設定とシステム設定はちょっと量が多いので、一旦飛ばします。

import()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ インポート
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function import() {
	// IDdatファイル
	$idfiles = wrapglob(DATADIR. IDDIR. '*.dat');

上記を下記に変更。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ インポート
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function import() {
	global $configLoader;
	$scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');

	// IDdatファイル
	$idfiles = wrapglob(DATADIR. IDDIR. '*.dat');
location($GLOBALS['script']. '?act=import');

上記を下記に変更。

location($scriptAction. '?act=import');
<form action="'. $GLOBALS['script']. '?act=import" method="post" id="configform">

上記を下記に変更。

<form action="'. $scriptAction. '?act=import" method="post" id="configform">

インポート機能は試してないので動くかわからないんですけど多分動くんじゃないかな…。動かなかったらすみません。

html_header()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ドキュメントヘッダー
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function html_header() {
	header('Content-Type: text/html; charset: utf-8');
	$def = new define_parse();
	echo <<< _HTML_

上記を下記に変更。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ドキュメントヘッダー
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function html_header() {
    header('Content-Type: text/html; charset: utf-8');
    $def = new define_parse(); 
    $cssDir = $def->get('CSSDIR');
    $bootstrapCss = $def->get('BOOTSTRAPCSS');
    $datePickerCss = $def->get('DATEPICKERCSS');
    $morrisCss = $def->get('MORRISCSS');
    $dataTableCss = $def->get('DATATABLECSS');
    $adminCss = $def->get('ADMINCSS');
    $jsDir = $def->get('JSDIR');
    $jqueryJs = $def->get('JQUERYJS');
    $reqHealJs = $def->get('REQHEALJS');
    $bootstrapJs = $def->get('BOOTSTRAPJS');
    $datePickerJs = $def->get('DATEPICKERJS');
    $datePickerJaJs = $def->get('DATEPICKERJAJS');
    $morrisJs = $def->get('MORRISJS');
    $validateJs = $def->get('VALIDATEJS');
    $dataTableJs = $def->get('DATATABLEJS');
    $dataTableBsJs = $def->get('DATATABLEBSJS');
    $scriptJs = $def->get('SCRIPTJS');
    $adminJs = $def->get('ADMINJS');

    echo <<< _HTML_

なんかゴリ押ししてる。(笑)スマートな方法があったら教えてください。
define_parseクラスのインスタンスを作成

	<link type="text/css" rel="stylesheet" href="{$def->get('CSSDIR')}{$def->get('BOOTSTRAPCSS')}" />
	<link type="text/css" rel="stylesheet" href="{$def->get('CSSDIR')}{$def->get('DATEPICKERCSS')}" />
	<link type="text/css" rel="stylesheet" href="{$def->get('CSSDIR')}{$def->get('MORRISCSS')}" />
	<link type="text/css" rel="stylesheet" href="{$def->get('CSSDIR')}{$def->get('DATATABLECSS')}" />
	<link type="text/css" rel="stylesheet" href="{$def->get('CSSDIR')}{$def->get('ADMINCSS')}" />
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('JQUERYJS')}"></script>
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('REQHEALJS')}"></script>
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('BOOTSTRAPJS')}"></script>
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('DATEPICKERJS')}"></script>
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('DATEPICKERJAJS')}"></script>
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('MORRISJS')}"></script>
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('VALIDATEJS')}"></script>
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('DATATABLEJS')}"></script>
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('DATATABLEBSJS')}"></script>
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('SCRIPTJS')}"></script>
	<script type="text/javascript" src="{$def->get('JSDIR')}{$def->get('ADMINJS')}"></script>

上記を下記に変更。

    <link type="text/css" rel="stylesheet" href="{$cssDir}{$bootstrapCss}" />
    <link type="text/css" rel="stylesheet" href="{$cssDir}{$datePickerCss}" />
    <link type="text/css" rel="stylesheet" href="{$cssDir}{$morrisCss}" />
    <link type="text/css" rel="stylesheet" href="{$cssDir}{$dataTableCss}" />
    <link type="text/css" rel="stylesheet" href="{$cssDir}{$adminCss}" />
    <script type="text/javascript" src="{$jsDir}{$jqueryJs}"></script>
    <script type="text/javascript" src="{$jsDir}{$reqHealJs}"></script>
    <script type="text/javascript" src="{$jsDir}{$bootstrapJs}"></script>
    <script type="text/javascript" src="{$jsDir}{$datePickerJs}"></script>
    <script type="text/javascript" src="{$jsDir}{$datePickerJaJs}"></script>
    <script type="text/javascript" src="{$jsDir}{$morrisJs}"></script>
    <script type="text/javascript" src="{$jsDir}{$validateJs}"></script>
    <script type="text/javascript" src="{$jsDir}{$dataTableJs}"></script>
    <script type="text/javascript" src="{$jsDir}{$dataTableBsJs}"></script>
    <script type="text/javascript" src="{$jsDir}{$scriptJs}"></script>
    <script type="text/javascript" src="{$jsDir}{$adminJs}"></script>

content_header()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ コンテンツヘッダー
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function content_header() {
	$act = get_query('act');

上記を下記に変更。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ コンテンツヘッダー
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function content_header() {    
	global $configLoader;
	// PHP変数を事前に処理
	$scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');
	$act = get_query('act');

それから、$GLOBALS['script']っていう箇所を全部$scriptActionに変更する。ここは同じなので略。

login_form()

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ログイン
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function login_form() {
	$error = get_session('error');

上記を下記に変更。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ログイン
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function login_form() {
	global $configLoader;
	$scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');

	$error = get_session('error');
<form action="{$GLOBALS['script']}?" method="post">

上記を下記に変更。

<form action="{$scriptAction}?" method="post">

これでだいたいの修正が終わったかと思われます。あとは基本拍手設定ページとシステム設定ページの修正をします。

基本拍手設定ページとシステム設定ページについて簡単に話すと、基本拍手設定ページの初期データはmwhg/data/config.jsonにあります。
初期データを基本拍手設定ページで読みこむ→WEB拍手ボタンの設定をする→保存したデータはconfig.jsonのclapConfigの初期データを上書きし、上書きしたデータを表示して…。という感じになります。

システム設定ページもやってることは同じですがsystem.json内に初期データがあります。
また、config.jsonとsystem.jsonは似たような動きをしていますが、config.jsonには基本拍手設定で保存したデータの他にsystemやpathといったデータも保存されており、ここがsystem.jsonとはちょっと違います。

clapconfig()

まず// ▼ ここから全部差し替え ~ // ▲ ここまで全部差し替えの間のプログラムを下記に変更してください。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ 基本拍手設定
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function clapconfig() {
// ▼ ここから全部差し替え
    global $configLoader;
    $scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');
    $clapConfig = $configLoader->getClapConfig();
    $scriptPath = $configLoader->getScript();

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $CON = [];
        foreach ($_POST as $name => $value) {
            if ($name === 'mode') continue;

            $CON[$name] = (in_array($value, ['true', 'false'], true)) ?
                ($value === 'true') : decode($value);

            if ($name === 'tkb') {
                $CON[$name] = array_map('trim', explode("<br />", $CON[$name]));
            }
        }

        $configLoader->setClapConfig($CON);

        $lfh = file_lock();
        if (!$lfh) {
            $_SESSION['error'] = '現在、他のプロセスが設定ファイルを使用しています。後ほど再試行してください。';
            header('Location: ' . $scriptPath . '?act=clapconfig');
            exit;
        }

        try {
            $configLoader->saveConfigToFile(DATADIR . CONFIGJSON);
        } catch (Exception $e) {
            file_unlock($lfh);
            $_SESSION['error'] = '設定の保存に失敗しました: ' . $e->getMessage();
            header('Location: ' . $scriptPath . '?act=clapconfig');
            exit;
        }

        file_unlock($lfh);

        $_SESSION['done'] = '設定を保存しました';
        header('Location: ' . $scriptPath . '?act=clapconfig');
        exit;
    }
// ▲ ここまで全部差し替え
    html_header();
    content_header();
<form action="'. $GLOBALS['script']. '?act=clapconfig" method="post" id="configform" class="form-horizontal">

上記を下記に変更します。

<form action="'. $scriptAction. '?act=clapconfig" method="post" id="configform" class="form-horizontal">

以下同様に$GLOBALSを修正していきます。修正後のコードだけ表示します。

<select name="label" class="form-control" id="label">
	'. select_option(
	array('true' => '有効', 'false' => '無効'),
	$clapConfig['label'] ?? '' // label が存在しない場合は空文字を使用
	) . '
</select>
<input type="text" name="chain" value="'. ($clapConfig['chain'] ?? '') . '" class="form-control" id="chain" />
<select name="numViewType" class="form-control" id="numViewType">
	'. select_option(
		array(
			'none' => '非表示', 
			'total' => '合計数', 
			'myclap' => '自分の拍手数', 
			'total_myclap' => '合計数+自分の拍手数'
		),
		$clapConfig['numViewType'] ?? '' // numViewType が存在しない場合は空文字を使用
	) . '
</select>
<select name="flat" class="form-control" id="flat">
	'. select_option(
		array(
			'true' => 'フラット', 
			'false' => 'グラデーション'
		),
		$clapConfig['flat'] ?? '' // flat が存在しない場合は空文字を使用
	) . '
</select>
<select name="btnColor" class="form-control" id="btnColor">
	'. select_option(
		array(
			'default' => '白', 
			'primary' => '青', 
			'info' => '水色', 
			'success' => '緑', 
			'warning' => '黄', 
			'danger' => '赤'
		),
		$clapConfig['btnColor'] ?? '' // btnColor が存在しない場合は空文字を使用
	) . '
</select>
<select name="btnType" class="form-control" id="btnType">
	'. select_option(
		array(
			'normal' => 'ノーマル', 
			'arrow' => '吹き出し付き'
		),
	$clapConfig['btnType'] ?? '' // btnType が存在しない場合は空文字を使用
	) . '
</select>

<input type="text" name="btnTitle" value="'. ($clapConfig['btnTitle'] ?? '') . '" class="form-control" id="btnTitle" />
<input type="text" name="btnText" value="'. ($clapConfig['btnText'] ?? '') . '" class="form-control" id="btnText" />
<textarea name="thanksClapMessage" class="form-control" id="thanksClapMessage" rows="5">'. preg_replace("/<br \/>/", "\n", $clapConfig['thanksClapMessage'] ?? '') . '</textarea>
<input type="checkbox" name="inputName" value="true"'. checkbox_checked($clapConfig['inputName'] ?? 'false') . '>
<input type="checkbox" name="inputEval" value="true"'. checkbox_checked($clapConfig['inputEval'] ?? 'false') . '>
<input type="checkbox" name="inputTkb" value="true"'. checkbox_checked($clapConfig['inputTkb'] ?? 'false') . '>
<input type="checkbox" name="inputMsg" value="true"'. checkbox_checked($clapConfig['inputMsg'] ?? 'false') . '>
<textarea name="tkb" class="form-control" id="tkb" rows="5">'. implode("\n", $clapConfig['tkb'] ?? []) . '</textarea>

tkbってTeiKeiBunのことか…!って今ようやく把握した(笑)てっきり以下略。

systemconfig()

システム設定も同様に修正していきます。数が多いので頑張りましょう。

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ システム設定
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ▼ ここから全部差し替え
function systemconfig() {
    global $configLoader;
    $scriptAction = htmlspecialchars($configLoader->getScript(), ENT_QUOTES, 'UTF-8');
    $systemConfig = $configLoader->getSystem();

	if ($_SERVER['REQUEST_METHOD'] === 'POST') {
	    // POSTデータから設定を取得

		$systemConfig = [];
		foreach ($_POST as $name => $value) {
		    if ($name === 'mode') continue;

		    // 空白とインデントを削除するために、各行の前後の空白を削除
		    $value = trim($value);
		    
		    // 改行コードを統一
		    $value = str_replace("\r\n", "\n", $value);

		    if ($name === 'denyHosts') {
		        // 改行で分割し、空行や余分な空白を除去して配列に格納
			    $lines = array_map('trim', explode("\n", $value));
			    $lines = array_filter($lines, 'strlen'); // 空行を除去
			    $systemConfig[$name] = $lines;
		    } else {
		        $systemConfig[$name] = (in_array($value, ['true', 'false'])) ? 
		            ($value === 'true' ? true : false) : $value;
		    }
		}

	    // ファイルロック実行
	    $lfh = file_lock() or die('Busy!');

	    try {
	        // システム設定ファイル書き込み
	        $configLoader->setSystem($systemConfig); // POSTデータから取得した設定を渡す
	        $configLoader->saveSystem(DATADIR . SYSTEMJSON); // ファイルパスを引数として渡す
	    } catch (Exception $e) {
	        error_log('Error saving system config: ' . $e->getMessage());
	    } finally {
	        // ファイルロック解除
	        file_unlock($lfh);
	    }

	    // 完了
	    $_SESSION['done'] = '設定を保存しました';
	    location($scriptAction . '?act=systemconfig');
	}

// ▲ ここまで全部差し替え
	html_header();
	content_header();

あとは$GLOBALSの修正をします。以降も修正後の載せていくので、適宜修正してください。

<form action="'. $scriptAction. '?act=systemconfig" method="post" id="configform" class="form-horizontal">
<input type="text" name="mailAddress" value="'. ($systemConfig['mailAddress'] ?? '') .'" class="form-control" id="mailAddress" />
<input type="checkbox" name="mailFlgName" value="true"'. checkbox_checked($configLoader->getSystem('mailFlgName')) . '>
<input type="checkbox" name="mailFlgEval" value="true"'. checkbox_checked($configLoader->getSystem('mailFlgEval')) . '>
<input type="checkbox" name="mailFlgTkb" value="true"'. checkbox_checked($configLoader->getSystem('mailFlgTkb')) . '>
<input type="checkbox" name="mailFlgMsg" value="true"'. checkbox_checked($configLoader->getSystem('mailFlgMsg')) . '>
<select name="getReferer" class="form-control" id="getReferer">
	'. select_option(array('true' => '有効', 'false' => '無効'), $configLoader->getSystem('getReferer')) . '
</select>
<select name="cookieCTRL" class="form-control" id="cookieCTRL">
	'. select_option(array('true' => '有効', 'false' => '無効'), $configLoader->getSystem('cookieCTRL')) . '
</select>
<select name="hostCTRL" class="form-control" id="hostCTRL">
	'. select_option(array('true' => '有効', 'false' => '無効'), $configLoader->getSystem('hostCTRL')) . '
</select>

アクセス制限のテキストエリアに空白やインデントが入る

ごめんなんかわからんのだけど何故か保存するたびにアクセス制限のテキストエリアに空白やインデントが入る。
でもうまく修正できずそのままになってるので、修正したよ!って方は教えてください。助かります。

<textarea name="denyHosts" class="form-control" id="denyHosts" rows="5">'
    . htmlspecialchars(implode("\n", (array) $configLoader->getSystem('denyHosts')), ENT_QUOTES, 'UTF-8') . '
</textarea>

ここの表示が悪いのかな…?

終わり

今回の修正でWEB拍手ボタンの表示、メッセージ送信、メール通知、管理画面での拍手データ表示などの操作はできるようになったんじゃないか…ナ…!?
修正したスキンをアップロードし、まいるどWEB拍手ぐれーと設定方法を参照しながら設置し、なおかつプログラムを修正してもボタンが設置されていなかったら
1.ブラウザのキャッシュのせい
2.てがろぐのスキンが最新じゃない(てがろぐの管理画面の設定などを保存してCGIを更新しスキンを最新のものにする)(もしくは別のスキンに変更しボタンを設置した場合の動作を見てみてもいいかも)
3.JSファイルの設置場所、またはバッティング(jqueryをすでに使っていたり、lightboxなど他のプログラムと相性が悪かったり、等)
4.まいるどWEB拍手ぐれーとの修正がなんかおかしい
のいずれかではないかと思われます。
スキンの影響か、jQueryまたはjsスクリプトの影響か、まいるどWEB拍手グレートのプログラムの問題か、その他か…など、こまかく問題を切り分けながらの調査が必要です。

・ブラウザに表示されるエラーをよく調べる
・プログラム内に不要なゴミがないか、または誤って必要なものを削除していないか
・config.jsonやsystem.jsonのデータは適切に保存されているか
・js/jquery.mwhg.js内のURLの変更はしているか

または私が必要な記述を書き忘れているか…(この記事は適時修正します)
PHP8でも動くように、と今回修正したけどPHP7で動くかはわからないしな…。多分大丈夫じゃないかと思うけど…。わからん…。
誰かのお役にたてれば幸いです。

なお、このブログの拍手はまいるどWEB拍手ぐれーとではありませんが、
今回の記事がお役にたちましたらぽちっと押していただけると励みになります。

  • この記事を書いた人

ゆず

■忘れないように自分の覚書と、誰かも困っているかもしれないので参考になればいいなくらいの軽い備忘録です。
■サイト運営費のためGoogleAdsenseをいれています。
giftee / ko-fi / mail

-tegalog