Owing to a long development period, and several changes of the core development team, we have a lot of leftover Views that are no longer being used. However, with pages upon pages of them and quite a large site, it isn't always immediately apparent which Views are still needed and which aren't.
Here is a very small module I quickly threw together yesterday to track when Views are called/rendered and generate a report at /admin/views_audit. I doubt that there is enough general need for this to put it in contrib, but someone out there might get some use of it.
It should be just as happy running on 4.7 as 5.
Keep in mind that this will add one additional DB query per View access, so it isn't the sort of thing you would want to enable and forget about on a production server. Rather, you'd want to turn it on for about a week or so to collect the data. Myself, I only have it enabled on our development server.
Full tarball with module, install file, and info file is here, module code is pasted below. (The formatting may look a little off because of linewrap and such)
<?php
function views_audit_menu($may_cache) {
if ($may_cache) {
$items[] = array('path' => 'admin/views_audit',
'title' => t('Views Audit'),
'callback' => 'views_audit_admin_page',
'access' => user_access('administer views'),
'type' => MENU_CALLBACK,
);
}
return $items;
}
function views_audit_views_pre_query($view) {
// this function will be called for each view
$sql = "INSERT INTO {views_audit} (vid, timestamp)
VALUES (%d, %d)
ON DUPLICATE KEY UPDATE timestamp = %d;";
$result = db_query($sql, $view->vid, time(), time());
}
function views_audit_admin_page() {
$output = '';
if (isset($_REQUEST['days'])) {
$days_stamp = $_REQUEST['days'] * 86400;
}
else {
$days_stamp = 0;
}
// 4.7 and 5 have different drupal_get_form behaviour, so compensate
if (strncmp(VERSION, '5', 1) == 0)
$output .= drupal_get_form('views_audit_admin_form');
else
$output .= drupal_get_form('views_audit_admin_form', views_audit_admin_form());
$header = array(
array('data' => t('View ID'),
'field' => 'vid',
),
array('data' => t('View Name'),
'field' => 'name',
),
array('data' => t('Last Updated'),
'field' => 'changed',
),
array('data' => t('Last Accessed'),
'sort' => 'desc',
'field' => 'timestamp',
)
);
$sql = "SELECT v.vid, a.timestamp, v.changed, v.name
FROM {view_view} v
LEFT OUTER JOIN {views_audit} a
ON v.vid = a.vid";
$result = db_query($sql . tablesort_sql($header));
while ($sql_row = db_fetch_object($result)) {
if (empty($sql_row->timestamp)) {
$timestamp = $sql_row->timestamp = "no record";
}
else {
$timestamp = format_date($sql_row->timestamp, 'small') .
' (' . round( (time() - $sql_row->timestamp)/86400 ) .
' ' . t('days ago') . ')';
}
$updated = format_date($sql_row->changed, 'small') .
' (' . round( (time() - $sql_row->changed)/86400 ) .
' ' . t('days ago') . ')';
// the Views admin paths are different in 4.7 and 5, so build the appropriate
// destination path
if (strncmp(VERSION, '5', 1) == 0)
$destination = 'admin/build/views/' . $sql_row->name . '/edit';
else
$destination = 'admin/views/edit/' . $sql_row->vid;
$table_row = array($sql_row->vid,
l($sql_row->name, $destination),
$updated,
$timestamp,
);
if ( ($sql_row->timestamp <= time() - $days_stamp) ||
($sql_row->timestamp == 'no record') ) {
$rows[] = $table_row;
}
}
$output .= theme('table', $header, $rows);
return $output;
}
function views_audit_admin_form() {
$form['days'] = array(
'#type' => 'select',
'#title' => t('Show Views which have not been used in at least the following number of days'),
'#default_value' => $_REQUEST['days'],
'#options' => drupal_map_assoc(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 60, 120, 240, 365)),
'#required' => FALSE,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'filter',
);
return $form;
}
function views_audit_admin_form_submit($form_id, $form_values) {
drupal_goto('admin/views_audit', 'days='.$form_values['days']);
}
?>





+1 on putting this in contrib! Thanks for sharing in any case.