「PHP」タグアーカイブ

PHP7.0からPHP7.2に変更したらSyntax Highlighter ComPressでエラー発生

PHPの最新化のためにPHP7.0からPHP7.2へ変更しました。
7.2にするとプラグインでエラーが出るという話がありましたが、利用しているプラグインであるSyntax Highlighter ComPressで以下のエラーが発生しました。

Deprecated: Function create_function() is deprecated in /wp-content/plugins/syntax-highlighter-compress/syntax-highlighter-compress.php on line 418

調べてみるとPHP7.2ではcreate_function()という関数が使えなくなっているようです。
早速エラーが出ている個所を修正します。

変更前

/**
 * Actions
 */
add_action('plugins_loaded', create_function( '', 'global $wp_shc; $wp_shc = new wp_shc();' ) );

変更後

/**
 * Actions
 */
add_action('plugins_loaded', function() {global $wp_shc; $wp_shc = new wp_shc();} );

これでエラーはでなくなりました。

カテゴリー別全投稿タイトル一覧の固定ページを追加

全記事のタイトルを見ることができるサイトマップみたいなものが欲しかったのですが、単にタイトルを全部並べただけでは非常に見難い。
希望を満たせるものがないか少し探してみましたが、作った方が早いんじゃないかと思い作りました。
今回はタグではなくカテゴリーを使った投稿タイトル一覧にしました。

動きとしては、まず親カテゴリーを取得し、親カテゴリーに属している投稿のタイトル一覧を作成します。
但し親カテゴリーの子カテゴリーに属していた場合は一覧に含みません。
更に親カテゴリの下には属する子カテゴリを表示し、その子カテゴリに属する投稿のタイトル一覧を作成します。
(今回は対象の子カテゴリーは親カテゴリーの1階層下までとしました)
文章で書くと分かりにくいですが、私の固定ページを見て頂ければ直ぐに分かるかと思います。
コンテンツ一覧

まずwp-content/themes/all_contents.phpというファイルを作成して以下の内容を記述して保存します。

	.all_contents_sub_category {
		padding-left: 1em;
	}

<?php
// 親カテゴリーを取得
$top_categories = get_categories(array('parent' => 0, 'orderby' => 'term_order'));
// 親カテゴリー分ループ
foreach($top_categories as $top_category) :
	// 親カテゴリーのリンク作成 ?>
	<?php endforeach; ?>
<?php endforeach; ?>

これだけでは固定ページから呼び出せませんので、テーマのfunction.phpに以下の内容を追記します。

/*
* コンテンツ一覧のphpファイルを読み込むショートコード
*/
function include_all_contents_php( $atts ){
	ob_start();
	get_template_part('../all_contents'); // ../all_contents.phpを読みこみ
	return ob_get_clean();
}
add_shortcode( 'include_all_contents', 'include_all_contents_php' );

これはショートコードと呼ばれる方法で、PHPを投稿や固定ページから呼び出せるようにするものです。
投稿や固定ページには基本的にPHPを記述することはできませんが、このショートコードを利用することで簡単に呼び出せるようになります。

あとは固定ページで[include_all_contents]と書けば呼び出せます。
※そのまま書いてしまうと呼び出されてしまうため、上では[]を全角文字で書いてますので半角に置き換えてください。

尚、「Category Order and Taxonomy Terms Order」プラグインを使用してカテゴリーを並び替えている場合は、その並び替えた順番でカテゴリーが生成されます。

Syntax Highlighter ComPressでエラー

blog上でのコード表示用にSyntaxHighlighterを利用していました。
WPに乗り換えるにあたって直接header.phpにJavaScriptの呼び出しを記述するのではなく、プラグインを利用することにしました。
Syntax Highlighter ComPress バージョン 3.0.83.3を利用しましたが、問題点が2点出ました。
まず1点目は縦スクロールが必要ない場面でも縦スクロールが出ることです。
これはwp-content/plugins/syntax-highlighter-compress/styles/shCoreDefault.cssを変更することで解消されました。

変更前

.syntaxhighlighter {
  width: 100% !important;
  margin: 1em 0 1em 0 !important;
  position: relative !important;
  overflow: auto !important;
  font-size: 1em !important;
}

変更後

.syntaxhighlighter {
  width: 100% !important;
  margin: 1em 0 1em 0 !important;
  position: relative !important;
  font-size: 1em !important;
  overflow-x: auto !important;
  overflow-y: hidden !important;
  padding: 1px !important;
}

次に管理画面に以下の警告が出るようになりました。

Notice: has_cap がバージョン 2.0.0 から非推奨になった引数付きで呼び出されました。ユーザーレベルの使用は推奨されていません。代わりに権限を使ってください。

検索したところ以下のページを見つけました。
「Notice: has_cap の使用は…」はプラグインを確認する
※既にリンク先のサイトはなくなっているようです。

要は数字ではなく文字列で権限を指定しろということらしいです。
で、Syntax Highlighter ComPressで該当する箇所はwp-content/plugins/syntax-highlighter-compress/syntax-highlighter-compress.php内のadd_submenu_page関数でした。
add_submenu_pageの75行目を以下のように修正したら無事警告も出なくなりました。

変更前

add_submenu_page('options-general.php', __('Syntax Highlighter ComPress Options', 'SHC'), $menutitle, 8, basename(__FILE__), 'shc_options_subpanel');

変更後

add_submenu_page('options-general.php', __('Syntax Highlighter ComPress Options', 'SHC'), $menutitle, 'administrator', basename(__FILE__), 'shc_options_subpanel');

WordPressにカウンターを設置(同じIPはカウントしない)

blognplusからWordPressへ移行した際に良いカウンターがなかったので自作しました。
自作と言っても元はblogplusのモジュール用に作られた「カルカン(お手軽カウンター)」をWordPress用に改造したものです。
作者様に改造品の掲載許可を頂きたかったのですが、既にHPも閉鎖されているようで連絡が取れず…
もし作者様がこのブログを見られましたら許可・非許可のコメントを頂ければ幸いです。

「カルカン(お手軽カウンター)」で出来ることは以下の3つです。
1.トータルのカウント数を表示
2.当日のカウント数を表示
3.昨日のカウント数を表示
全てのカウント数で同じ日の同じIPからのアクセスは、何度アクセスしても1回としてカウントされます。
いわゆる「延べ数」なPVとは違い、実際の訪問者数が分かります。
(BOTかどうかまでは分かりませんが)
尚、7行目のIPアドレス保存件数しかIPを保存しないので、人気のあるサイトは数を大目にしないと直ぐに同じIPでもカウントアップしてしまいます。

使い方は簡単で以下のソースコードをテーマのfunction.phpに追記するだけで、ウィジェットとして使用することが可能となります。

/*
* カウンターウィジェット
*/
// 保存ファイル名
define('WIDGET_COUNTER_FILE', WP_CONTENT_DIR."/widget_counter_file");
// IPアドレス保存件数
define('WIDGET_COUNTER_REMOTE', 30);
class Counter_Widget extends WP_Widget {
	/* コンストラクタ */
	function __construct() {
		parent::__construct(
			false,
			$name = 'カウンター',
			array( 'description' => 'IP重複なしのカウンターです', )
		);
	}
	
	/* 管理画面のウィジェット設定用コード */
	function form($instance) {
	?>

	<?php
	}

	/* 管理画面のウィジェット設定を変更した時の処理 */
	function update($new_instance, $old_instance) {
		$instance = $old_instance;
		$instance['title'] = strip_tags($new_instance['title']);
		return $instance;
	}

	/* ウィジェットを配置した時の表示用コード */
	function widget($args, $instance) {
		extract( $args );
		
		// カウント取得
		$counter = $this->widgetCounterGetCount('default');
		$out_count = '';
		$out_count .= "合計: ".$counter['total']."\n";
		$out_count .= "今日: ".$counter['today']."\n";
		$out_count .= "昨日: ".$counter['yesterday']."\n";

		if($instance['title'] != ''){
			$title = apply_filters('widget_title', $instance['title']);
		}
		echo $before_widget;
		if( $title ){
			echo $before_title . $title . $after_title;
		}
		echo $out_count;
		echo $after_widget;
	}
	
	/* 日付を取得-----------------------------------------------------------------*/
	function widgetCounterGetDate($format, $timestamp = NULL) {
		$format = preg_replace('/(?<!\\\)T/', preg_replace('/(.)/', '\\\$1', 'JST'), $format);

		$time = 9 * 3600 + (($timestamp !== NULL) ? $timestamp : time() - date('Z'));

		return date($format, $time);
	}

	/* カウンターの値の取得及びカウントアップ-------------------------------------*/
	function widgetCounterGetCount($page) {
		$ipMax				= (WIDGET_COUNTER_REMOTE<1) ? 1 : WIDGET_COUNTER_REMOTE;
		
		$default = array(
			'total'		=> 0,
			'date'		=> $this->widgetCounterGetDate('Y/m/d'),
			'today'		=> 0,
			'yesterday'	=> 0
		);
		
		$counters			= array();
		$couterns[$page]	= $default;
		
		for ($i=0; $i<$ipMax; $i++) {
			$default["ip$i"] = '';
		}
		
		$file = WIDGET_COUNTER_FILE.'.'.$page.'.dat';
		
		$modify = FALSE;	//更新フラグ
		
		if (! $fp = @fopen($file, file_exists($file) ? 'r+' : 'w+')) return $default;
		set_file_buffer($fp, 0);
		flock($fp, LOCK_EX);
		rewind($fp);
		foreach ($default as $key=>$val) {
			//データ取得
			$counters[$page][$key] = rtrim(fgets($fp, 256));
			if (feof($fp)) break;
		}
		if ($counters[$page]['date'] != $default['date']) {
			// 新しい日付
			$modify = TRUE;
			$yesterday = ($counters[$page]['date'] == $this->widgetCounterGetDate('Y/m/d', (time() - date('Z') - 3600 * 24)));
			for ($i=$ipMax-1; $i>0; $i--) {
				$counters[$page]["ip$i"] = '';
			}
			$counters[$page]['ip0']       = $_SERVER['REMOTE_ADDR'];
			$counters[$page]['date']      = $default['date'];
			$counters[$page]['yesterday'] = $yesterday ? $counters[$page]['today'] : 0;
			$counters[$page]['today']     = 1;
			$counters[$page]['total']++;
			
		} else {
			$newer = TRUE;
			for ($i=0; $i<$ipMax; $i++) {
				if ($counters[$page]["ip$i"] == $_SERVER['REMOTE_ADDR']) {
					$newer = FALSE;
					break;
				}
			}
			if ($newer) {
				// カウントアップ
				$modify = TRUE;
				for ($i=$ipMax-1; $i>0; $i--) {
					$j = $i-1;
					$counters[$page]["ip$i"] = $counters[$page]["ip$j"];
				}
				$counters[$page]['ip0'] = $_SERVER['REMOTE_ADDR'];
				$counters[$page]['today']++;
				$counters[$page]['total']++;
			}
		}
		
		// 更新されていた場合
		if ($modify) {
			rewind($fp);
			ftruncate($fp, 0);
			foreach (array_keys($default) as $key)
				fputs($fp, $counters[$page][$key] . "\n");
		}
		
		flock($fp, LOCK_UN);
		fclose($fp);

		return $counters[$page];
	}
}
/* カウンターウィジェットを使えるように登録 */
register_widget('Counter_Widget');

上記コードをfunction.phpに登録すると、テーマのカスタマイズのウィジェットで選択して使用可能となります。

カウンタの数はデータベースではなくファイルに保存されます。
ファイルの保存場所は「wp-content」の直下でファイル名は「widget_counter_file.default.dat」です。
テーマを変更しても変更したテーマのfunction.phpに上記コードを書けば、カウンター数の内容を引き継ぐことが出来ます。

設置後初回だけはファイルが存在せずにエラーが出るかもしれませんが、自動でファイルが作成されますので2回目以降はエラーにならないはずです。
wp-contentの下にファイルが出来ていない場合は、ディレクトリに正しく権限が付与されていない可能性があります。
(プラグインのインストールが失敗するケースなどと同じ理由です)
基本は正しく権限を与えてもらうべきですが、手動でwidget_counter_file.default.datを作成して全権限を与えるというお勧めできない方法もあるにはあります。

また、見られても特に困るファイルではないと思いますが、念のために「wp-content」の直下に.htaccessを置いて以下の記述をしておくとwidget_counter_file.default.datへのアクセスが不可となります。
(アクセスしようとしても403エラーが返るようになります)

<Files widget_counter_file.default.dat>
    Deny from all
</Files>