カスタムフィールドを追加するプラグインなどを使用して、記事の編集画面の使い勝手をよくしていくと、編集画面にメタボックスがたくさん並びます。
メタボックスはドラッグアンドドロップでユーザーごとに好きな位置に動かせるのですが、これがお仕事のサイトだったりすると、マニュアル作成時に問題になったりします。
「マニュアルと同じところに入力欄がないんだけど!!」
しかも、表示位置の設定情報は簡単にクリアすることができません。
ということで、このユーザーごとの設定を効かせないようにすることはできないかなーと、コアファイルを覗いてみることにしました。
メタボックスを出力しているところは?
メタボックスを出力しているコードを特定するために、まずは編集画面のメタボックスを囲っている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' ); // カスタム投稿