Snippet: Wordpress Admin - Tidy Dashboard Widgets By Role

Recently I worked on a Wordpress site where I wanted to be able to customise the dashboard for different user roles. Wordpress has the default roles of administrators, editors, authors, contributors and subscribers. It's not too much to assume you might not want to show your editors or authors all the details of your blog posts etc and placing these short code snippets into your theme's functions.php file will allow you to do just that.

Clearing up

Lets get rid of the incoming links widget for authors and editors and then clean up some of the other boxes for everyone:
function tidy_dashboard()
{
  global $wp_meta_boxes, $current_user;
  
  // remove incoming links info for authors or editors
  if(in_array('author', $current_user->roles) || in_array('editor', $current_user->roles))
  {
    unset($wp_meta_boxes['dashboard']['normal ']['core']['dashboard_incoming_links']);
  }
    
  // remove the plugins info and news feeds for everyone
  unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_plugins']);
  unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_primary']);
  unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_secondary']);
  
}
//add our function to the dashboard setup hook
add_action('wp_dashboard_setup', 'tidy_dashboard');

Here's a full list of how to unset each of the current default dashboard widgets:

//Right Now - Comments, Posts, Pages at a glance
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_right_now']);
//Recent Comments
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_recent_comments']);
//Incoming Links
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_incoming_links']);
//Plugins - Popular, New and Recently updated Wordpress Plugins
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_plugins']);

//Wordpress Development Blog Feed
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_primary']);
//Other Wordpress News Feed
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_secondary']);
//Quick Press Form
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_quick_press']);
//Recent Drafts List
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_recent_drafts']);

Add your own - Private pages menu

Perhaps rather than the default information, you have other items you'd like to be on the dashboard for authors or editors etc? I often add a dashboard widget to list private pages. Here's how:
// function to display widget
function display_dashboard_widget() 
{
  //define arguments for WP_Query()
  $qargs = array(
    'post_type'=>'page',
    'post_status'=>'private'
  );
  // perform the query
  $q = new WP_Query();
  $q->query($qargs);

  // setup the content with a list
  $widget_content = '<ul>';
  
  // execute the WP loop
  while ($q->have_posts()) : $q->the_post(); 
    $widget_content .= '<li><a href="'.get_permalink() .'" rel="bookmark">'. get_the_title() .'</a></li>';
  endwhile;
  
  $widget_content .= '</ul>';
  
  // return the content you want displayed
  return $widget_content;
} 

//function to setup widget
function add_dashboard_widgets() 
{
  // create a dashboard widget called "private_page_menu_dashboard_widget" with the title "Private Pages Menu" and call our display function to draw it
  wp_add_dashboard_widget('private_page_menu_dashboard_widget', 'Private Pages Menu', 'display_dashboard_widget' );
} 

// finally we have to hook our function into the dashboard setup using add_action
add_action('wp_dashboard_setup', 'add_dashboard_widgets');

The only problem with wp_add_dashboard_widget is that it doesn't allow you to define where on the dashboard the widget is placed. Instead it just places the box at the bottom of the left hand side in the ['normal']['core'] array.

I want my private page menu to display at the top on the right hand side of the dashboard, so I am going to add a few more lines to add_dashboard_widgets() to shuffle the boxes around the way I want them. This will be overridden by user settings if the boxes are dragged around, but insures that my authors and editors see the box in an obvious position when they first login.

function add_dashboard_widgets() 
{
  // don't forget the global to get all dashboard widgets
  global $wp_meta_boxes;
 
  // create a dashboard widget called "private_page_menu_dashboard_widget" with the title "Private Pages Menu" and call our display function to draw it
  wp_add_dashboard_widget('private_page_menu_dashboard_widget', 'Private Pages Menu', 'display_dashboard_widget' );

  // reorder the boxes - first save the left and right columns into variables
  $left_dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
  $right_dashboard = $wp_meta_boxes['dashboard']['side']['core'];

  // take a copy of the new widget from the left column 
  $my_widget = array('private_page_menu_dashboard_widget' => $left_dashboard['private_page_menu_dashboard_widget']);
  
  // remove the new widget from the left column
  unset($left_dashboard['private_page_menu_dashboard_widget']);

  // use array_merge so that the new widget is pushed on to the beginning of the right column's array  
  $right_dashboard = array_merge($my_widget, $right_dashboard);

  // finally replace the left and right columns with the new reordered versions
  $wp_meta_boxes['dashboard']['normal']['core'] = $left_dashboard;	
  $wp_meta_boxes['dashboard']['side']['core'] = $right_dashboard;
}

I hope you find these tricks as useful as I do!

Resources

A Note on Snippets: When customising a CMS such as Wordpress it is often the simplest pieces of code which are the hardest to either find or remember. These snippets are placed here for my own reference and will hopefully be useful to others. If you find them useful or have any suggestions, please let me know.