カスタムフィールドを追加するプラグインなどを使用して、記事の編集画面の使い勝手をよくしていくと、編集画面にメタボックスがたくさん並びます。
メタボックスはドラッグアンドドロップでユーザーごとに好きな位置に動かせるのですが、これがお仕事のサイトだったりすると、マニュアル作成時に問題になったりします。
「マニュアルと同じところに入力欄がないんだけど!!」
しかも、表示位置の設定情報は簡単にクリアすることができません。
ということで、このユーザーごとの設定を効かせないようにすることはできないかなーと、コアファイルを覗いてみることにしました。
メタボックスを出力しているところは?
メタボックスを出力しているコードを特定するために、まずは編集画面のメタボックスを囲っているHTMLコードで、wp-adminディレクトリ内をgrepしてみます。
[kusanagi@minkapi wp-admin]$ grep -irn 'id="postbox-container-2"' * edit-form-advanced.php:699:<div id="postbox-container-2" class="postbox-container"> edit-form-comment.php:174:<div id="postbox-container-2" class="postbox-container"> edit-link-form.php:133:<div id="postbox-container-2" class="postbox-container"> includes/dashboard.php:220: <div id="postbox-container-2" class="postbox-container">
wp-admin/edit-form-advanced.phpの699行目に記載されているようなので、実際に中を見てみます。
<div id="postbox-container-2" class="postbox-container">
<?php
do_meta_boxes(null, 'normal', $post);
if ( 'page' == $post_type ) {
/**
* Fires after 'normal' context meta boxes have been output for the 'page' post type.
*
* @since 1.5.0
*
* @param WP_Post $post Post object.
*/
do_action( 'edit_page_form', $post );
}
else {
/**
* Fires after 'normal' context meta boxes have been output for all post types other than 'page'.
*
* @since 1.5.0
*
* @param WP_Post $post Post object.
*/
do_action( 'edit_form_advanced', $post );
}
do_meta_boxes(null, 'advanced', $post);
?>
</div>
do_meta_boxes()で出力しているみたい。
ということで、次はdo_meta_boxes()でgrep。
[kusanagi@minkapi wp-admin]$ grep -irn 'function do_meta_boxes' *
includes/template.php:995:function do_meta_boxes( $screen, $context, $object ) {
wp-admin/includes/template.phpの995行目の、do_meta_boxes()を見てみると…
function do_meta_boxes( $screen, $context, $object ) {
global $wp_meta_boxes;
static $already_sorted = false;
if ( empty( $screen ) )
$screen = get_current_screen();
elseif ( is_string( $screen ) )
$screen = convert_to_screen( $screen );
$page = $screen->id;
$hidden = get_hidden_meta_boxes( $screen );
printf('<div id="%s-sortables" class="meta-box-sortables">', htmlspecialchars($context));
// Grab the ones the user has manually sorted. Pull them out of their previous context/priority and into the one the user chose
if ( ! $already_sorted && $sorted = get_user_option( "meta-box-order_$page" ) ) {
foreach ( $sorted as $box_context => $ids ) {
foreach ( explode( ',', $ids ) as $id ) {
if ( $id && 'dashboard_browser_nag' !== $id ) {
add_meta_box( $id, null, null, $screen, $box_context, 'sorted' );
}
}
}
}
$already_sorted = true;
$i = 0;
if ( isset( $wp_meta_boxes[ $page ][ $context ] ) ) {
foreach ( array( 'high', 'sorted', 'core', 'default', 'low' ) as $priority ) {
if ( isset( $wp_meta_boxes[ $page ][ $context ][ $priority ]) ) {
foreach ( (array) $wp_meta_boxes[ $page ][ $context ][ $priority ] as $box ) {
if ( false == $box || ! $box['title'] )
continue;
$i++;
$hidden_class = in_array($box['id'], $hidden) ? ' hide-if-js' : '';
echo '<div id="' . $box['id'] . '" class="postbox ' . postbox_classes($box['id'], $page) . $hidden_class . '" ' . '>' . "\n";
if ( 'dashboard_browser_nag' != $box['id'] ) {
$widget_title = $box[ 'title' ];
if ( is_array( $box[ 'args' ] ) && isset( $box[ 'args' ][ '__widget_basename' ] ) ) {
$widget_title = $box[ 'args' ][ '__widget_basename' ];
// Do not pass this parameter to the user callback function.
unset( $box[ 'args' ][ '__widget_basename' ] );
}
echo '<button type="button" class="handlediv" aria-expanded="true">';
echo '<span class="screen-reader-text">' . sprintf( __( 'Toggle panel: %s' ), $widget_title ) . '</span>';
echo '<span class="toggle-indicator" aria-hidden="true"></span>';
echo '</button>';
}
echo "<h2 class='hndle'><span>{$box['title']}</span></h2>\n";
echo '<div class="inside">' . "\n";
call_user_func($box['callback'], $object, $box);
echo "</div>\n";
echo "</div>\n";
}
}
}
}
echo "</div>";
return $i;
}
1011行目から1019行目の間でソートしてる!
ソートを停止させよう
1011行目の、
if ( ! $already_sorted && $sorted = get_user_option( "meta-box-order_$page" ) ) {
の判定をtrueにすればいいのだけど、$already_sortedはfalseにするフックやらなんやらがないご様子。
ということで、get_user_option( “meta-box-order_$page” )をfalseにすることに。
get_user_option()をgrepして探してみます。
[kusanagi@minkapi wp-includes]$ grep -irn 'function get_user_option' *
user.php:451:function get_user_option( $option, $user = 0, $deprecated = '' ) {
wp-includes/user.phpの451行目を確認してみると…
function get_user_option( $option, $user = 0, $deprecated = '' ) {
global $wpdb;
if ( !empty( $deprecated ) )
_deprecated_argument( __FUNCTION__, '3.0.0' )
if ( empty( $user ) )
$user = get_current_user_id();
if ( ! $user = get_userdata( $user ) )
return false;
$prefix = $wpdb->get_blog_prefix();
if ( $user->has_prop( $prefix . $option ) ) // Blog specific
$result = $user->get( $prefix . $option );
elseif ( $user->has_prop( $option ) ) // User specific and cross-blog
$result = $user->get( $option );
else
$result = false;
/**
* Filters a specific user option value.
*
* The dynamic portion of the hook name, `$option`, refers to the user option name.
*
* @since 2.5.0
*
* @param mixed $result Value for the user's option.
* @param string $option Name of the option being retrieved.
* @param WP_User $user WP_User object of the user whose option is being retrieved.
*/
return apply_filters( "get_user_option_{$option}", $result, $option, $user );
}
apply_filters()を発見!!これでfalseにできるよー
※実際は$screenとかも遡って見てたりしましたが、もう$optionとかをvar_dump()してみちゃうほうが早い。
カスタムフィールドのユーザーごとの並び順設定を読み込まないようにした
下のコードで読み込みが停止できます。投稿タイプごとに設定が必要なので注意。
// カスタムフィールドのユーザーごとの並び順設定を読み込まないようにする add_filter( 'get_user_option_meta-box-order_post', '__return_false' ); // 投稿 add_filter( 'get_user_option_meta-box-order_page', '__return_false' ); // 固定ページ add_filter( 'get_user_option_meta-box-order_[post_type]', '__return_false' ); // カスタム投稿
