今回の WordPress バグですが、
またまた、カスタムヘッダーを利用する際のバグ紹介です。
( 解説に使用している WordPress ソースコードは WordPress 3.9 です )
【バグ確認バージョン】
WordPress 3.9
【前提条件】
add_theme_support 関数の第一パラメータに ‘custom-header’ を指定して
カスタムヘッダーを利用する指定をする際、
明示的にデフォルトヘッダーを指定していない
【現象】
管理画面[外観 - カスタマイズ] にて下記 Warning が発生
チラッと出て、他のレイヤーの下に隠れるので、気づかない方もいるかも・・・
/[WordPressディレクトリ]/wp-admin/custom-header.php on line 1248
Warning: array_merge(): Argument #2 is not an array in
/[WordPressディレクトリ]/wp-admin/custom-header.php on line 1268
【解消方法】
register_default_headers 関数にて、
明示的にデフォルトヘッダーを配列として登録する
管理画面からヘッダー画像を変更したり、ブログタイトルや
紹介文の文字色を変更できるようにさせるためには、
add_theme_support 関数の
第一パラメータに ‘custom-header’ を、
第二パラメータにデフォルトの挙動を指定する連想配列を与え、
カスタムヘッダーのサポートを有効にします。
/* カスタムヘッダー パラメータを指定して追加 */
add_theme_support('custom-header', array(
'default-image' => get_template_directory_uri() . '/images/header_photo-green.jpg', // デフォルトヘッダー画像
'random-default' => false, // ヘッダー画像をランダム表示するか
'width' => 986, // ヘッダー画像幅
'height' => 150, // ヘッダー画像高
'flex-width' => false, // 画像幅をフレキシブルにするか ・・・true:指定サイズに関係なくトリミング可能 / false:指定サイズに準拠した割合でのみトリミング可能
'flex-height' => false, // 画像高をフレキシブルにするか ・・・true:指定サイズに関係なくトリミング可能 / false:指定サイズに準拠した割合でのみトリミング可能
'default-text-color' => '464646', // ヘッダーテキスト文字色
'header-text' => true, // ヘッダーテキストの表示制御可否
'uploads' => true, // ヘッダー画像アップロード可否
'wp-head-callback' => 'header_style', // ユーザ画面ヘッダーで、管理画面でのカスタマイズスタイルを適用するためのコールバック
'admin-head-callback' => 'admin_header_style', // 管理画面で、[外観 - カスタマイズ]をプレビューするためのコールバック
'admin-preview-callback' => 'admin_header_preview' // 管理画面で、[外観 - ヘッダー]をプレビューするためのコールバック
));
上記のように、‘default-image’ を指定しているにも関わらず、
「 管理画面[外観 - ヘッダー] 」 を表示すると、
/wp-admin/custom-header.php の get_default_header_images 関数にて、
Warning が発生します。
PHP のエラー表示で Warning を表示しない設定にしていたり、
表示していても、画面表示上はチラッと出て他のレイヤーの下に
隠れてしまうので、気づいていない方もいるかもしれません。
なぜこんなことになるのでしょう?
public function get_default_header_images() {
$this->process_default_headers();
// Get the default image if there is one.
$default = get_theme_support( 'custom-header', 'default-image' );
if ( ! $default ) { // If not,
return $this->default_headers; // easy peasy.
}
$default = sprintf( $default, get_template_directory_uri(), get_stylesheet_directory_uri() );
$already_has_default = false;
foreach ( $this->default_headers as $k => $h ) {
if ( $h['url'] === $default ) {
$already_has_default = true;
break;
}
}
if ( $already_has_default ) {
return $this->default_headers;
}
// If the one true image isn't included in the default set, prepend it.
$header_images = array();
$header_images['default'] = array(
'url' => $default,
'thumbnail_url' => $default,
'description' => 'Default'
);
// The rest of the set comes after.
$header_images = array_merge( $header_images, $this->default_headers );
return $header_images;
}
実際に Warning を吐いているのは、1248行目と1268行目です。
「Invalid argument supplied for foreach() in ・・・ on line 1248」
「array_merge(): Argument #2 is not an array in ・・・ on line 1268」
メッセージから、いずれも配列操作に関する argument の
Warning であることが分かります。
ここで操作している配列は、$this->default_headers です。
では、$this->default_headers はどこで初期化されているのでしょう?
$this は自身のクラスインスタンスを示す疑似変数ですので、
default_headers で custom-header.php を検索してみます。
ぬ?
ないではありませんか! 初期化するコードが!
/** * Holds default headers. * * @var array * @since 3.0.0 * @access private */ var $default_headers;
43行目に変数の宣言はありますが、配列としての宣言ではありません。
では、どこで代入があるのでしょう?
/**
* Process the default headers
*
* @since 3.0.0
*/
function process_default_headers() {
global $_wp_default_headers;
if ( !empty($this->headers) )
return;
if ( !isset($_wp_default_headers) )
return;
if ( is_array( $this->default_headers ) ) {
return;
}
$this->default_headers = $_wp_default_headers;
$template_directory_uri = get_template_directory_uri();
$stylesheet_directory_uri = get_stylesheet_directory_uri();
foreach ( array_keys($this->default_headers) as $header ) {
$this->default_headers[$header]['url'] = sprintf( $this->default_headers[$header]['url'], $template_directory_uri, $stylesheet_directory_uri );
$this->default_headers[$header]['thumbnail_url'] = sprintf( $this->default_headers[$header]['thumbnail_url'], $template_directory_uri, $stylesheet_directory_uri );
}
}
261行目で $_wp_default_headers を代入しています。
しかし、$_wp_default_headers は249行目で global 宣言されています。
なんてこった・・・
このソース (custom-header.php) だけで完結しねぇ・・・ orz
で、結局、$_wp_default_headers も他のソースでも初期化されているふうはなく、
配列として明示的に指定してやることをやってそうな関数は、
theme.php の register_default_headers 関数。
/**
* Register a selection of default headers to be displayed by the custom header admin UI.
*
* @since 3.0.0
*
* @param array $headers Array of headers keyed by a string id. The ids point to arrays containing 'url', 'thumbnail_url', and 'description' keys.
*/
function register_default_headers( $headers ) {
global $_wp_default_headers;
$_wp_default_headers = array_merge( (array) $_wp_default_headers, (array) $headers );
}
よって、解消方法としては、この (register_default_headers) 関数を使って、
明示的に、デフォルトヘッダ画像を(配列として)エントリしてやればよさそうです。
register_default_headers(array( 'photo-green' => array( 'url' => '%s/images/header_photo-green.jpg', // ヘッダー画像のアドレス 'thumbnail_url' => '%s/images/thum_photo-green.jpg', // ヘッダー画像のサムネイルのアドレス 'description' => '木漏れ日' // ヘッダー画像の説明や日本語名など(省略可) ), 'photo-sky' => array( 'url' => '%s/images/header_photo-sky.jpg', 'thumbnail_url' => '%s/images/thum_photo-sky.jpg', 'description' => '青空' ), 'photo-tunnel' => array( 'url' => '%s/images/header_photo-tunnel.jpg', 'thumbnail_url' => '%s/images/thum_photo-tunnel.jpg', 'description' => 'トンネル' ), 'texture-green' => array( 'url' => '%s/images/header_texture-green.jpg', 'thumbnail_url' => '%s/images/thum_texture-green.jpg', 'description' => '緑のプリント基盤' ), 'texture-blue' => array( 'url' => '%s/images/header_texture-blue.jpg', 'thumbnail_url' => '%s/images/thum_texture-blue.jpg', 'description' => '青い蜂の巣' ), 'texture-yellow' => array( 'url' => '%s/images/header_texture-yellow.jpg', 'thumbnail_url' => '%s/images/thum_texture-yellow.jpg', 'description' => '黄色いビームライン' ) ));
register_default_headers 関数へ食わせるパラメータは、
必ずしも複数のデフォルト画像を用意する必要はありませんが、
連想配列の多次元配列として与えてやる必要があります。
(上記、7行目から31行目はなくても大丈夫ということ)
なんだかなぁ・・・
どうなんだろう、このバグ・・・雑だなぁ
私が発見したときには未だ解決してませんでしたけど、
日本語版でも英語版でもフォーラムで話題に挙がったみたいですね。
このバグ・・・
> WordPress フォーラム 日本語:エラー ヘッダー画像関連?
> php problems with responsive on WordPress 3.9



SmartStyle