27

I'd love to be able to hide meta boxes using screen options, instead of removing them or restricting them to user roles, the goal is to just "uncheck" the meta box for the user.

I see how this would be tricky since any code that would make a DB change for a user wouldn't be allowed to run every time they hit the page because it would just reset. But smarter people than I code the core, so maybe there's a way. And if there is, I'm dying to know.

Any ideas?

2
  • Per username you would have to create your own plugin of sorts that populates all users with a checkbox next to their name and hooks into a filter for showing meta boxes, or multiple meta boxes.
    – Wyck
    Commented Apr 22, 2011 at 4:07
  • By default you mean they should be applied once when new user is created, correct?
    – Rarst
    Commented Apr 22, 2011 at 11:43

4 Answers 4

25

You are referring to the metaboxes on the admin post screen right?

For that you don't need a plugin, just drop the following into your functions.php file.

// add_action('user_register', 'set_user_metaboxes');
add_action('admin_init', 'set_user_metaboxes');
function set_user_metaboxes($user_id=NULL) {

    // These are the metakeys we will need to update
    $meta_key['order'] = 'meta-box-order_post';
    $meta_key['hidden'] = 'metaboxhidden_post';

    // So this can be used without hooking into user_register
    if ( ! $user_id)
        $user_id = get_current_user_id(); 

    // Set the default order if it has not been set yet
    if ( ! get_user_meta( $user_id, $meta_key['order'], true) ) {
        $meta_value = array(
            'side' => 'submitdiv,formatdiv,categorydiv,postimagediv',
            'normal' => 'postexcerpt,tagsdiv-post_tag,postcustom,commentstatusdiv,commentsdiv,trackbacksdiv,slugdiv,authordiv,revisionsdiv',
            'advanced' => '',
        );
        update_user_meta( $user_id, $meta_key['order'], $meta_value );
    }

    // Set the default hiddens if it has not been set yet
    if ( ! get_user_meta( $user_id, $meta_key['hidden'], true) ) {
        $meta_value = array('postcustom','trackbacksdiv','commentstatusdiv','commentsdiv','slugdiv','authordiv','revisionsdiv');
        update_user_meta( $user_id, $meta_key['hidden'], $meta_value );
    }
}

Basically what is happening is that for the currently logged in user, you are changing some saved meta_values in the wp_usermeta table.

There are two ways to use this function, you can either hook into 'user_register' or you can hook into 'admin_init'.

The advantage of using 'user_register' is that this function will only fire when a new user is registered (thus lower overhead). However it will not work for users that already exist.

If you want it to work for users that already exist, then hook into 'admin_init'. The disadvantage of course is that now this function fires every time a user goes to the admin page.

7
  • 16
    This is not a theme job and doesn’t belong into a functions.php.
    – fuxia
    Commented Jun 14, 2011 at 13:05
  • 7
    @toscho I don't really agree with that. Naturally you could put this into a plugin but if for instance you are building a theme for yourself or perhaps for a client that has no need to see certain boxes then why add the additional management overhead that comes with including this into a plugin. By dropping it into the functions.php file you ensure that the experience for the theme is consistent without having to make sure a plugin is installed and activated.
    – drebabels
    Commented Jun 29, 2011 at 12:32
  • 11
    There is no overhead by using a plugin. That’s a myth which has to die instantly. Plus, your usage restriction was not part of the question. Your answer is read by thousands of novices. You’ll help them with the best code you can write, not with something that kinda works in some specific situations. :)
    – fuxia
    Commented Jun 29, 2011 at 17:15
  • +1 Good answer - sometimes you do want to set these explicitly. It's a good base, and of course this code can be modified easily to be called when necessary (adding a new user, for example), so that you really are setting the "default" options and not forcing options on users who change them. I will be adding this code to my theme's functions.php file because the default options are for a specific project, which is represented / housed by the theme that I'm developing.
    – cwd
    Commented Nov 3, 2011 at 14:54
  • 2
    A couple months after this Answer was written, filters where added to core making this answer obsolete. Commented Mar 1, 2013 at 17:05
18

There is default_hidden_meta_boxes filter in get_hidden_meta_boxes() that allows to modify which are not shown as long as user hadn't modified his preferences in screen options.

0
8

I have code comments about three solutions already posted, but also a general comment

They present a suboptimal choice: either override the user's Screen Options checkbox choice; or respect it but have your code ignored if the user has ever changed the checkboxes, even for other meta_boxes, or before your code was in WP. Seems the respectful choice is only useful if all your users are new. The best solution would be to set a custom user option to determine if your specific meta_box defaults have been changed by the user, and respect that. No, I haven't written that code! Should be easy... :)

The three solutions posted:

1. WraithKenny's hidden_meta_boxes solution is the one that overrides the user_option. Note it covers all post types ('post', 'page', 'link', 'attachment', and any custom post types). That's fine unless you want it to be specific. You specified the post_type's in your add_meta_box() calls. You can try to match those, or just wing it since the ones that don't match will be ignored. If you want to know the post_type in the filter, you can use the extra screen parameter:

add_filter('hidden_meta_boxes', 'foo_hidden_meta_boxes', 10, 2);
function foo_hidden_meta_boxes($hidden, $screen) {
    $post_type= $screen->id;
    switch ($post_type) {
        // case 'post', 'page', 'link', 'attachment', and any custom post types
        // $hidden[]= 'foo_box_id';
        // /or/
        // $hidden= array_diff($hidden, array('foo_box_id'));
    }
    return $hidden;
}

2. As Rarst says, default_hidden_meta_boxes respects the user_option. As with hidden_meta_boxes, you can use the $screen parameter to distinguish post_types.

3. Drebabels's set_user_metaboxes() function also respects the user_option. Note it is hard-coded for the 'post' edit screen. To handle the 'page' edit screen, and other post_types, wrap the code in this loop:

function set_user_metaboxes($user_id=NULL) {
    $post_types= array( 'post', 'page', 'link', 'attachment' );
    // add any custom post types here:
    // $post_types[]= 'my_custom_post_type';
    foreach ($post_types as $post_type) {

       // These are the metakeys we will need to update
       $meta_key= array(
           'order' => "meta-box-order_$post_type",
           'hidden' => "metaboxhidden_$post_type",
       );

       // The rest is the same as drebabels's code,
       // with '*_user_meta()' changed to '*_user_option()'

       // So this can be used without hooking into user_register
       if ( ! $user_id)
           $user_id = get_current_user_id(); 

       // Set the default order if it has not been set yet
       if ( ! get_user_option( $meta_key['order'], $user_id ) ) {
           $meta_value = array(
               'side' => 'submitdiv,formatdiv,categorydiv,postimagediv',
               'normal' => 'postexcerpt,tagsdiv-post_tag,postcustom,commentstatusdiv,commentsdiv,trackbacksdiv,slugdiv,authordiv,revisionsdiv',
               'advanced' => '',
           );
           update_user_option( $user_id, $meta_key['order'], $meta_value, true );
       }

       // Set the default hiddens if it has not been set yet
       if ( ! get_user_option( $meta_key['hidden'], $user_id ) ) {
           $meta_value = array('postcustom','trackbacksdiv','commentstatusdiv','commentsdiv','slugdiv','authordiv','revisionsdiv');
           update_user_option( $user_id, $meta_key['hidden'], $meta_value, true );
       }
    }
 }

Yeah, get_user_meta should be get_user_option. For single-site it doesn't matter, and even for multi-site it probably doesn't. See wp-admin/includes/ajax-actions.php for why: update_user_option has the 'true' global parameter.

2
add_filter( 'hidden_meta_boxes', 'custom_hidden_meta_boxes' );
function custom_hidden_meta_boxes( $hidden ) {
    $hidden[] = 'your_metabox';
    return $hidden;
}

There is also hidden_meta_boxes filter that would "uncheck" the metabox (making it hidden) on every page load (but wouldn't have to update the database at all). If you just want it off for new users until they check the box themselves, use Rarst's answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.