WordPress 4.3 アップデートで画面が真っ白 WP-Ban プラグインには要注意!

2015年8月19日、 WordPress バージョン 4.3 “Billie” が公開されました。

なんでもジャズミュージシャンの Billie Holiday から命名されているそうですが、その”Billie”もとい 4.3 にアップデートをすると画面が真っ白になる不具合が発生しています。特に WP-Ban プラグイン が入っている場合は要注意!!です。WP-Ban のバージョンにより確実に真っ白画面になります。

バージョンによる動作状況

WordPress 4.2.4, 4.3 と WP-Ban 1.65, 1.66 バージョンによる動作状況を以下のマトリクスで示します。
WordPress 4.3 + WP-Ban 1.65 の組み合わせでは確実に真っ白画面になります。
また WordPress 4.2.4 以下 + WP-Ban 1.66 の組み合わせでは WP-Ban プラグインを有効化できません。

WP-Ban
バージョン 1.65 1.66
WordPress 4.2.4 以下 正常 有効化不可
4.3 真っ白画面 正常

原因

真っ白画面 (WordPress 4.3 + WP-Ban 1.65)

WordPress 4.3 で general-template.php に get_language_attributes() 関数が追加されました。この get_language_attributes() という名前の関数は、すでに以前から同名の関数が WP-Ban に実装されており 1.65 まで存在していました。
したがって WordPress 4.3 + WP-Ban 1.65 の組み合わせの場合、以下のような関数の二重定義エラーとなり、画面が真っ白になります。

関数の二重定義エラー

[cc] Fatal error: Cannot redeclare get_language_attributes() (previously declared in /wp-includes/general-template.php:2624)
in /wp-content/plugins/wp-ban/wp-ban.php on line 249
[/cc]

WordPress 4.3 – general-template.php

/**
 * Gets the language attributes for the html tag.
 *
 * Builds up a set of html attributes containing the text direction and language
 * information for the page.
 *
 * @since 4.3.0
 *
 * @param string $doctype Optional. The type of html document. Accepts 'xhtml' or 'html'. Default 'html'.
 */
function get_language_attributes( $doctype = 'html' ) {
	$attributes = array();

	if ( function_exists( 'is_rtl' ) && is_rtl() )
		$attributes[] = 'dir="rtl"';

	if ( $lang = get_bloginfo('language') ) {
		if ( get_option('html_type') == 'text/html' || $doctype == 'html' )
			$attributes[] = "lang=\"$lang\"";

		if ( get_option('html_type') != 'text/html' || $doctype == 'xhtml' )
			$attributes[] = "xml:lang=\"$lang\"";
	}

	$output = implode(' ', $attributes);

	/**
	 * Filter the language attributes for display in the html tag.
	 *
	 * @since 2.5.0
	 * @since 4.3.0 Added the `$doctype` parameter.
	 *
	 * @param string $output A space-separated list of language attributes.
	 * @param string $doctype The type of html document (xhtml|html).
	 */
	return apply_filters( 'language_attributes', $output, $doctype );
}
この get_language_attributes() 関数は、 WordPress 4.2.4 までは、ほぼ language_attributes() という関数名でした。ですので正確にはリネーム(リファクタリング)ですかね。なお language_attributes() 関数のコメントには以下の記載があります。
/**
 * Displays the language attributes for the html tag.
 *
 * Builds up a set of html attributes containing the text direction and language
 * information for the page.
 *
 * @since 2.1.0
 * @since 4.3.0 Converted into a wrapper for get_language_attributes().
 *
 * @param string $doctype Optional. The type of html document. Accepts 'xhtml' or 'html'. Default 'html'.
 */
function language_attributes( $doctype = 'html' ) {
	echo get_language_attributes( $doctype );
}

WP-Ban 1.65 – wp-ban.php

### Function: Returns page's language attributes depends on WordPress language
function get_language_attributes($doctype = 'html') {
	ob_start();
	language_attributes();
	$language_attributes = ob_get_contents();
	ob_end_clean();
	return $language_attributes;
}

WP-Ban 有効化不可 (WordPress 4.2.4 以下 + WP-Ban 1.66)

一方 WordPress 4.2.4 以下の場合、WP-Ban 1.66 では get_language_attributes() 関数が削除されたため、関数がない旨の未定義エラーで WP-Ban プラグインを有効化できません。

関数未定義エラー

[cc] 重大なエラーを引き起こしたため、プラグインを有効化できませんでした。

Fatal error: Call to undefined function get_language_attributes() in /wp-content/plugins/wp-ban/wp-ban.php on line 287
[/cc]

対応策

上記マトリクスから対応策を考えますと、以下の2点になるかと思います。

  • WordPress 4.3 にアップデートする場合は、アッデート前にまず先に WP-Ban プラグインを 1.66 にアップデートしておいてから WordPress 4.3 にアップデートする。
  • WordPress 4.2.4 以下の場合は WP-Ban プラグインは 1.65 のままにしておき、1.66 へはアップデートしない。

真っ白画面になってしまった場合 (WordPress 4.3 + WP-Ban 1.65)

WP-Ban 1.65 のまま、WordPress 4.3 にアップデートしてしまった場合は真っ白画面になり、ダッシュボードなどの管理画面にもアクセスできません。したがって別途 FTP, SFTP, SSH やファイルマネージャーなど WordPress 非依存のツールが必要になります。方法は主に以下の2通りになります。
あらかじめ、https://downloads.wordpress.org/plugin/wp-ban.1.66.zip をダウンロードし解凍しておきます。

WP-Ban 1.66 の wp-ban.php ファイルをアップロードする方法

  1. wp-ban.php ファイルのリネーム
    WP-Ban 1.65 の /wp-content/plugins/wp-ban/wp-ban.php が真っ白画面になる原因のファイルですので、 FTP, SFTP, SSH やファイルマネージャーなど WordPress 非依存のツールを使い wp-ban.php を適宜 wp-ban.php.bak などの名前にリネームします。これで真っ白画面は解消されます。

  2. WP-Ban 1.66 の wp-ban.php ファイルのアップロード
    解凍した WP-Ban 1.66 の wp-ban.php を /wp-content/plugins/wp-ban/ ディレクトリにアップロードします。

WP-Ban プラグインの削除&インストールする方法

  1. WP-Ban 1.65 プラグインの削除
    FTP, SFTP, SSH やファイルマネージャーなど WordPress 非依存のツールを使い、プラグインのディレクトリ(/wp-content/plugins/)に入り、wp-ban ディレクトリごと削除します。これで真っ白画面は解消されます。

  2. WP-Ban 1.66 プラグインのインストール
    解凍した WP-Ban 1.66 の wp-ban フォルダをすべてアップロードし手動でインストールするか、ダッシュボードのプラグインから新規追加で「プラグインのアップロード」にて wp-ban.1.66.zip ファイルを選択しインストールします。
    もしくはダッシュボードのプラグインから新規追加で WP-Ban プラグインを検索し再インストールでもよいです。なお設定はデータベースにありますので消えることはありません。

WP-Ban有効化不可の場合 (WordPress 4.2.4 以下 + WP-Ban 1.66)

WordPress 4.2.4 以下で、WP-Ban 1.66 にアップデートしてしまった場合、有効化できませんがダッシュボードなどの管理画面へのアクセスはすべて可能ですので、いわゆる WP-Ban プラグインのダウンデートを行います。方法は主に以下の2通りになります。
あらかじめ、https://downloads.wordpress.org/plugin/wp-ban.1.65.zip をダウンロードし解凍しておきます。

WP-Ban 1.65 の wp-ban.php ファイルをアップロードする方法

  1. wp-ban.php ファイルのリネーム
    WP-Ban 1.66 の /wp-content/plugins/wp-ban/wp-ban.php が有効化不可になる原因のファイルですので、FTP, SFTP, SSH やファイルマネージャー(WordPress依存可)などのツールを使い wp-ban.php を適宜 wp-ban.php.bak などの名前にリネームします。

  2. WP-Ban 1.65 の wp-ban.php ファイルのアップロード
    解凍した WP-Ban 1.65 の wp-ban.php を /wp-content/plugins/wp-ban/ ディレクトリにアップロードします。

WP-Ban プラグインの削除&インストールする方法

  1. WP-Ban 1.66 プラグインの削除
    ダッシュボードのプラグインからバージョンが 1.66 の WP-Ban プラグインを一旦削除します。この場合、WP-Ban プラグインをアンインストールしますので設定は消えてしまいます。設定を消したくない場合は、別途 FTP, SFTP, SSH やファイルマネージャー(WordPress依存可)などのツールを使い プラグインのディレクトリ(/wp-content/plugins/)に入り、wp-ban ディレクトリごと削除します。

  2. WP-Ban 1.65 プラグインのインストール
    解凍した WP-Ban 1.65 の wp-ban フォルダをすべてアップロードし手動でインストールするか、ダッシュボードのプラグインから新規追加で「プラグインのアップロード」にて wp-ban.1.65.zip ファイルを選択しインストールします。

おわりに

今回は、以前からプラグイン側にある関数と同名の関数を WordPress 本体側が 4.3 で実装(追加)してしまったのが原因でした。まあ WordPress 本体開発者からすればプラグイン側の関数名など眼中にないのかもしれませんが、そこは grep などで調査し、本体側に追加する関数に同名の関数がプラグイン側に存在した場合は、すみやかにプラグイン開発者側に周知するなり知らせるのがマナーかと思います。プラグイン開発者軽視、本体開発者側の傲慢もそこにはあるのかもしれません。

本体開発者からすれば「WordPress 4.3 リリース前に『プラグイン開発者はプレビュー期間で動作確認しておいてくれよ!』という時間は十分取った」とかいう後付け理由はすぐに思い浮かぶのですが、技術屋視点からしますと、結局被害を被るのは WordPress ユーザで、現に重大な不具合が起きているわけですから、本体への関数追加は充分に調査し慎重に行うべきであると思います。

一方、今回は、WP-Ban プラグイン開発者側にも大いに問題があると思います。WordPress 4.3 で真っ白画面になる不具合が、本体側起因と言えども、1.65 ⇒ 1.66 への対応で wp-ban.php の get_language_attributes() 関数をごっそり削除してしまうというヘタレ対応をしてしまいました。これでは下位互換が保てません。
WordPress 4.3 への WP-Ban 開発者の対応として、バッティングする get_language_attributes() 同名関数を「If you can’t beat them, join them.(長いものに巻かれよ)」ではないですがプラグイン側が折れて名前変更するとか、バージョンチェック処理を入れるとか、方法はいくつかあると思います。

例えば WP-Ban 1.66 で以下のような対応が必要であったと思います。1.67 でなにかしら対応してくれること祈ります。

function_exists() 関数で定義済かを事前確認する

function_exists() 関数で get_language_attributes() 関数がすでに定義済かどうか事前に確認し下位互換を保持する。
if ( !function_exists('get_language_attributes') ) {
	function get_language_attributes($doctype = 'html') {
		ob_start();
		language_attributes();
		$language_attributes = ob_get_contents();
		ob_end_clean();
		return $language_attributes;
	}
}

呼び出し元の関数を get_language_attributes() から language_attributes() に変更する

1.66 と同様に WP-Ban 側の get_language_attributes() は削除し、代わりに呼び出し元の get_language_attributes() を WordPress 4.3 にも 4.2.4 以下にも存在する language_attributes() 関数に変更し下位互換を保持する。(これが一番無難かも)
	'<html xmlns="http://www.w3.org/1999/xhtml" '.language_attributes().'>'."\n".
				default_template = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" <?php echo str_replace('"', '\"', language_attributes()); ?>>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=<?php echo get_option('blog_charset'); ?>\" />\n<title>%SITE_NAME% - %SITE_URL%</title>\n</head>\n<body>\n<div id=\"wp-ban-container\">\n<p style=\"text-align: center; font-weight: bold;\"><?php _e('You Are Banned.', 'wp-ban'); ?></p>\n</div>\n</body>\n</html>";

WordPress 4.3 本当に “Billie” 敬意を表してるんでしょうか。こんなんでは “Billie” が泣いてますよね! Billie is Crying!


2015/08/25 追記
普段は PHP 使いではないので WordPress ってこんなに簡単にFatal(真っ白)で落ちるのかって思う反面、Plugin Framework というアーキテクチャの観点からすると、 WordPress 本体がプラグインをロードするロジックで、関数の二重定義ぐらい 本体側でチェックしてよねって思ってしまうのは私だけではないはず。この機能さえあれば、例え今回のような関数の二重定義があったとしても、プラグインは動作不可にはなっても WordPress 本体が落ちてしまい、ダッシュボードなどの管理画面にすらたどり着けないという致命的なエラーは起こらないはずです。
いまさら感いっぱいの「整形ルール」などの実装より、このような信頼性を高める機能改善のほうがよっぽどプライオリティが高い気がします。

Windows 10 クリーンインストールする

2015/07/29付で、Windows 10 のインストールプログラムが提供開始されました。Windows 7SP1/8.1 から無償でアップグレードができ、またクリーンインストールにはWindows 10 のプロダクトキーが必要とのこと。

メディアの作成

  • MediaCreationToolによるメディア作成
    1. メディア作成ツール(MediaCreationTool)のダウンロード
      ISOなりのメディアがないと不安な旧人類ですので、まずは以下からメディア作成ツールをダウンロードします。
      http://www.microsoft.com/ja-jp/software-download/windows10
    2. メディアの作成
      ダウンロードしたMediaCreationTool.exe(64BitはMediaCreationToolx64.exe)を実行し、「他のPC用にインストールメディアを作成する」を選択し、「USBフラッシュドライブ(以後USBメモリ)」または「ISOファイル」のメディアを作成します。
      私はUSBメモリに「日本語」「Windows 10 Pro」「両方」で作成しました。はじめは「両方」ってなに?って思いましたが、これはブートする過程で「32bit」か「64bit」かの選択画面が表示されbit選択できます。1メディアで32/64bit両対応ということですね。「両方」の場合は6GB程度ありますので8GB以上のUSBメモリが必要です。
  • Windows 10 のディスク イメージ (ISO ファイル) のダウンロード
    1. ブラウザの User Agent を変更
      Firefox に User Agent Swicherアドオン を追加し、User Agent を「iPhone 3.0」に変更します。

    2. ISOファイルダウンロードサイトの表示
      以下のURLのISOダウンロードサイトにアクセスします。User Agentを変更しておかないと、上記AのMediaCreationToolサイトにリダイレクトされます。このA,Bの2サイトはURL末尾に「ISO」文字列の有無だけなのですが、User Agentにより排他リダイレクトされます。
      http://www.microsoft.com/ja-jp/software-download/windows10ISO
    3. ISOファイルのダウンロード
      「Windows10」「日本語」を選択しますと、32bit/64bitそれぞれのISOファイルをダウンロードできます。こちらのISOファイルはHome/Proエディション両方が含まれておりインストール時に選択可能です。またMSDNのISOファイルとSHA1ハッシュが一致し同一ファイルです。
      ■32bit
      ダウンロードファイル名 Win10_Japanese_x32.iso
      MSDNファイル名 ja_windows_10_multiple_editions_x86_dvd_6847020.iso
      SHA1 9F425A21873A8A5FB40B0F6B849EDA325A6A57FC
      ■64bit
      ダウンロードファイル名 Win10_Japanese_x64.iso
      MSDNファイル名 ja_windows_10_multiple_editions_x64_dvd_6847015.iso
      SHA1 7A0B55F969E513D366543F099B2BFAE4357E7A40

Windows 7SP1 から Windows 10 へのアップグレード

  1. Windows 7SP1 から Windows 10 へのアップグレード
    • MediaCreationTool による Windows 10 へのアップグレード
      Windows 7SP1 から MediaCreationTool.exe を実行し「このPCを今すぐアップグレードする」を選択し Windows 10 にアップグレードします。この場合オンラインでなければなりません。

    • メディアによる Windows 10 へのアップグレード
      Windows 7SP1 を起動した状態で、USBメモリやISOから「setup.exe」を実行しアップグレードします。
      オンラインの場合は「更新プログラムをダウンロードしてインストールする(推奨)」、オフラインの場合は「今はしない」を選択します。「今はしない」を選択しますと、メディアからアップグレードされます。
  2. Windows 10 ライセンス認証の確認
    ライセンス認証されるには、必ずオンラインでなければなりません。例えメディアからオフラインでアップグレードしてもオンラインにならないと、ライセンス認証が通りません。

  3. Windows 10 のプロダクトキーの確認
    ライセンス認証が確認できたら、regedit にてレジストリエディタを起動し、以下の場所のプロダクトキーを控えます。
    [cc] HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform\BackupProductKeyDefault
    [/cc] Windows 10 の Generic Key は概ね以下のプロダクトキーになるようです。
    http://peace.2ch.net/test/read.cgi/win/1438179165/706

Windows 10 のクリーンインストール

  1. Windows 10 のクリーンインストール
    USBメモリから起動し、Windows 10 をクリーンインストールします。

  2. プロダクトキーの入力
    インストール開始時に、プロダクトキーの入力を促されますまので、先ほど控えたプロダクトキーを入力します。スキップしてもオンラインであればクリーンインストール後、ライセンス認証されます。プロダクトキーはある意味エディションの選択に使用するのみです。

ライセンス認証

    Windows 7SP1 から Windows 10 へのアップグレードは、アップグレードが完了しオンラインでマイクロソフト側にハードウェアプロファイル情報(インストールID)が登録された時点でライセンス認証されます。一度登録されたハードウェアで以後クリーンインストールを行ったとしてもオンラインであればプロダクトキーなしでライセンス認証が通ります。オフライン場合は、クリーンインストールしてもインストールは完了しますがライセンス未認証の状態になります。
    今のところ、初めに「アップグレード修行」しておかないと、クリーンインストールでのライセンス認証は通らないということですね。

    MS側にHW情報が登録されるというなんともiOSっぽくなったのが、Windows 10 ですね。iOSからみますと、最終的にマイクロソフトは、Officeなどのアプリケーションもハードウェアと紐付けし、MS Store はたまた MS Play などから、ハードウェア個別のアプリケーションのインストールしか認めないようにしたいのかなと。