Extending Administration Views for fun and profit

The Administration Views module is a significant improvement out of the box for content editors, providing a starting point for building a much more useful content administration tool. Because it provides a set of Views displays, it’s easy to extend.  However, if you’re trying to export your views using Features you’ll run into the problem of having two default views trying to use the same machine name, so Features can’t export or import a modified admin menu view overtop of the one provided in Admin Views.  

The first solution is to export the modified view and blast the old one using hook_views_default_views_alter().

function example_views_default_views_alter(&$views){
  if (array_key_exists('admin_views_node', $views)) {
    $view = new view;
    ...the rest of your exported view goes here
  }
}

That’s great, as long as you don’t mind rebuilding and reexporting the view if Admin Views gets an update and changes something.  If you only want to modify the parts you care about and preserve the rest of Admin Views (or another module is extending it as well and you don’t want to miss that), you can also modify the array in line.  Either compare a dpm of the modified display to the default or export both and do a diff.

diff old_view.export new_view.export > changes.diff

This gives you the changes and you can drop those into the hook.

function example_views_default_views_alter(&$views){
  if (array_key_exists('admin_views_node', $views)) {
    /* Field: Content: Example */
    $views['admin_views_node']->display['default']->display_options['fields']['field_example']['id'] = 'field_example';
    $views['admin_views_node']->display['default']->display_options['fields']['field_example<']['table'] = 'field_data_field_example';
    $views['admin_views_node']->display['default']->display_options['fields']['field_example']['field'] = 'field_example';
    $views['admin_views_node']->display['default']->display_options['fields']['field_example']['label'] = 'Example Field';
    $views['admin_views_node']->display['default']->display_options['fields']['field_example']['element_label_colon'] = FALSE;
  }
}

The hook_views_default_views_alter() function provides easy access to modifying the default view, but by default it just appends any added fields, filters or actions to the end of the list.  If you don’t want your added field showing up at the end, you’ll need to add an array_merge that takes a given key into account.  To make that mostly generic, add the following function to your custom module:

/**
 * Helper function to insert an array element after a specified key, where
 * a theming call uses the order of a keyed array for display.
 */

function example_view_array_merge($source, $addition, $position) {
  foreach($source as $key => $value){
    $replaced[$key] = $value;
    if($key == $position) {
      $replaced = array_merge($replaced , $addition);
    }
  }
  return $replaced;
}

To make things a little more readable during customization, as compared to a succinct export, I clean the array up a bit, then call our merge function.

function example_views_default_views_alter(&$views){
  if (array_key_exists('admin_views_node', $views)){
    // table column declaration for Example field
    $addition = array(
      'field_example' => array(
        'id' => 'field_example',
        'table' => 'field_data_field_example',
        'field' => 'field_example',
        'label' => 'Example Field',
        'element_label_colon' => FALSE,
      ),
    );
    
    $views['admin_views_node']->display['default']->display_options['fields'] = example_view_array_merge($views['admin_views_node']->display['default']->display_options['fields'], $addition, 'changed');
  }
}

Assuming you’ve already declared it with the info array, that adds your new column after the “last changed date” column, rather than as the last column in the table.