dblog.admin.inc

Same filename in other branches
  1. 9 core/modules/dblog/dblog.admin.inc
  2. 8.9.x core/modules/dblog/dblog.admin.inc
  3. 10 core/modules/dblog/dblog.admin.inc
  4. 11.x core/modules/dblog/dblog.admin.inc

Administrative page callbacks for the Database Logging module.

File

modules/dblog/dblog.admin.inc

View source
<?php


/**
 * @file
 * Administrative page callbacks for the Database Logging module.
 */

/**
 * Page callback: Displays a listing of database log messages.
 *
 * Messages are truncated at 56 chars. Full-length messages can be viewed on the
 * message details page.
 *
 * @see dblog_clear_log_form()
 * @see dblog_event()
 * @see dblog_filter_form()
 * @see dblog_menu()
 *
 * @ingroup logging_severity_levels
 */
function dblog_overview() {
    $filter = dblog_build_filter_query();
    $rows = array();
    $classes = array(
        WATCHDOG_DEBUG => 'dblog-debug',
        WATCHDOG_INFO => 'dblog-info',
        WATCHDOG_NOTICE => 'dblog-notice',
        WATCHDOG_WARNING => 'dblog-warning',
        WATCHDOG_ERROR => 'dblog-error',
        WATCHDOG_CRITICAL => 'dblog-critical',
        WATCHDOG_ALERT => 'dblog-alert',
        WATCHDOG_EMERGENCY => 'dblog-emerg',
    );
    $build['dblog_filter_form'] = drupal_get_form('dblog_filter_form');
    $build['dblog_clear_log_form'] = drupal_get_form('dblog_clear_log_form');
    $header = array(
        '',
        // Icon column.
array(
            'data' => t('Type'),
            'field' => 'w.type',
        ),
        array(
            'data' => t('Date'),
            'field' => 'w.wid',
            'sort' => 'desc',
        ),
        t('Message'),
        array(
            'data' => t('User'),
            'field' => 'u.name',
        ),
        array(
            'data' => t('Operations'),
        ),
    );
    $query = db_select('watchdog', 'w')->extend('PagerDefault')
        ->extend('TableSort');
    $query->leftJoin('users', 'u', 'w.uid = u.uid');
    $query->fields('w', array(
        'wid',
        'uid',
        'severity',
        'type',
        'timestamp',
        'message',
        'variables',
        'link',
    ))
        ->addField('u', 'name');
    if (!empty($filter['where'])) {
        $query->where($filter['where'], $filter['args']);
    }
    $result = $query->limit(50)
        ->orderByHeader($header)
        ->execute();
    foreach ($result as $dblog) {
        $rows[] = array(
            'data' => array(
                // Cells
array(
                    'class' => 'icon',
                ),
                t($dblog->type),
                format_date($dblog->timestamp, 'short'),
                theme('dblog_message', array(
                    'event' => $dblog,
                    'link' => TRUE,
                )),
                theme('username', array(
                    'account' => $dblog,
                )),
                filter_xss($dblog->link),
            ),
            // Attributes for tr
'class' => array(
                drupal_html_class('dblog-' . $dblog->type),
                $classes[$dblog->severity],
            ),
        );
    }
    $build['dblog_table'] = array(
        '#theme' => 'table',
        '#header' => $header,
        '#rows' => $rows,
        '#attributes' => array(
            'id' => 'admin-dblog',
        ),
        '#empty' => t('No log messages available.'),
    );
    $build['dblog_pager'] = array(
        '#theme' => 'pager',
    );
    return $build;
}

/**
 * Page callback: Shows the most frequent log messages of a given event type.
 *
 * Messages are not truncated on this page because events detailed herein do not
 * have links to a detailed view.
 *
 * @param string $type
 *   Type of database log events to display (e.g., 'search').
 *
 * @return array
 *   A build array in the format expected by drupal_render().
 *
 * @see dblog_menu()
 */
function dblog_top($type) {
    $header = array(
        array(
            'data' => t('Count'),
            'field' => 'count',
            'sort' => 'desc',
        ),
        array(
            'data' => t('Message'),
            'field' => 'message',
        ),
    );
    $count_query = db_select('watchdog');
    $count_query->addExpression('COUNT(DISTINCT(message))');
    $count_query->condition('type', $type);
    $query = db_select('watchdog', 'w')->extend('PagerDefault')
        ->extend('TableSort');
    $query->addExpression('COUNT(wid)', 'count');
    $query = $query->fields('w', array(
        'message',
        'variables',
    ))
        ->condition('w.type', $type)
        ->groupBy('message')
        ->groupBy('variables')
        ->limit(30)
        ->orderByHeader($header);
    $query->setCountQuery($count_query);
    $result = $query->execute();
    $rows = array();
    foreach ($result as $dblog) {
        $rows[] = array(
            $dblog->count,
            theme('dblog_message', array(
                'event' => $dblog,
            )),
        );
    }
    $build['dblog_top_table'] = array(
        '#theme' => 'table',
        '#header' => $header,
        '#rows' => $rows,
        '#empty' => t('No log messages available.'),
    );
    $build['dblog_top_pager'] = array(
        '#theme' => 'pager',
    );
    return $build;
}

/**
 * Page callback: Displays details about a specific database log message.
 *
 * @param int $id
 *   Unique ID of the database log message.
 *
 * @return array|string
 *   If the ID is located in the Database Logging table, a build array in the
 *   format expected by drupal_render(); otherwise, an empty string.
 *
 * @see dblog_menu()
 */
function dblog_event($id) {
    $severity = watchdog_severity_levels();
    $result = db_query('SELECT w.*, u.name, u.uid FROM {watchdog} w INNER JOIN {users} u ON w.uid = u.uid WHERE w.wid = :id', array(
        ':id' => $id,
    ))->fetchObject();
    if ($dblog = $result) {
        $rows = array(
            array(
                array(
                    'data' => t('Type'),
                    'header' => TRUE,
                ),
                t($dblog->type),
            ),
            array(
                array(
                    'data' => t('Date'),
                    'header' => TRUE,
                ),
                format_date($dblog->timestamp, 'long'),
            ),
            array(
                array(
                    'data' => t('User'),
                    'header' => TRUE,
                ),
                theme('username', array(
                    'account' => $dblog,
                )),
            ),
            array(
                array(
                    'data' => t('Location'),
                    'header' => TRUE,
                ),
                l($dblog->location, $dblog->location),
            ),
            array(
                array(
                    'data' => t('Referrer'),
                    'header' => TRUE,
                ),
                l($dblog->referer, $dblog->referer),
            ),
            array(
                array(
                    'data' => t('Message'),
                    'header' => TRUE,
                ),
                theme('dblog_message', array(
                    'event' => $dblog,
                )),
            ),
            array(
                array(
                    'data' => t('Severity'),
                    'header' => TRUE,
                ),
                $severity[$dblog->severity],
            ),
            array(
                array(
                    'data' => t('Hostname'),
                    'header' => TRUE,
                ),
                check_plain($dblog->hostname),
            ),
            array(
                array(
                    'data' => t('Operations'),
                    'header' => TRUE,
                ),
                $dblog->link,
            ),
        );
        $build['dblog_table'] = array(
            '#theme' => 'table',
            '#rows' => $rows,
            '#attributes' => array(
                'class' => array(
                    'dblog-event',
                ),
            ),
        );
        return $build;
    }
    else {
        return '';
    }
}

/**
 * Builds a query for database log administration filters based on session.
 *
 * @return array
 *   An associative array with keys 'where' and 'args'.
 */
function dblog_build_filter_query() {
    if (empty($_SESSION['dblog_overview_filter'])) {
        return;
    }
    $filters = dblog_filters();
    // Build query
    $where = $args = array();
    foreach ($_SESSION['dblog_overview_filter'] as $key => $filter) {
        $filter_where = array();
        foreach ($filter as $value) {
            $filter_where[] = $filters[$key]['where'];
            $args[] = $value;
        }
        if (!empty($filter_where)) {
            $where[] = '(' . implode(' OR ', $filter_where) . ')';
        }
    }
    $where = !empty($where) ? implode(' AND ', $where) : '';
    return array(
        'where' => $where,
        'args' => $args,
    );
}

/**
 * Creates a list of database log administration filters that can be applied.
 *
 * @return array
 *   Associative array of filters. The top-level keys are used as the form
 *   element names for the filters, and the values are arrays with the following
 *   elements:
 *   - title: Title of the filter.
 *   - where: The filter condition.
 *   - options: Array of options for the select list for the filter.
 */
function dblog_filters() {
    $filters = array();
    foreach (_dblog_get_message_types() as $type) {
        $types[$type] = t($type);
    }
    if (!empty($types)) {
        $filters['type'] = array(
            'title' => t('Type'),
            'where' => "w.type = ?",
            'options' => $types,
        );
    }
    $filters['severity'] = array(
        'title' => t('Severity'),
        'where' => 'w.severity = ?',
        'options' => watchdog_severity_levels(),
    );
    return $filters;
}

/**
 * Returns HTML for a log message.
 *
 * @param array $variables
 *   An associative array containing:
 *   - event: An object with at least the message and variables properties.
 *   - link: (optional) Format message as link, event->wid is required.
 *
 * @ingroup themeable
 */
function theme_dblog_message($variables) {
    $output = '';
    $event = $variables['event'];
    // Check for required properties.
    if (isset($event->message) && isset($event->variables)) {
        $event_variables = @unserialize($event->variables);
        // Messages without variables or user specified text.
        if ($event_variables === NULL) {
            $output = $event->message;
        }
        elseif (!is_array($event_variables)) {
            $output = t('Log data is corrupted and cannot be unserialized: @message', array(
                '@message' => $event->message,
            ));
        }
        else {
            $output = t($event->message, $event_variables);
        }
        // If the output is expected to be a link, strip all the tags and
        // special characters by using filter_xss() without any allowed tags.
        // If not, use filter_xss_admin() to allow some tags.
        if ($variables['link'] && isset($event->wid)) {
            // Truncate message to 56 chars after stripping all the tags.
            $output = truncate_utf8(filter_xss($output, array()), 56, TRUE, TRUE);
            $output = l($output, 'admin/reports/event/' . $event->wid, array(
                'html' => TRUE,
            ));
        }
        else {
            // Prevent XSS in log detail pages.
            $output = filter_xss_admin($output);
        }
    }
    return $output;
}

/**
 * Form constructor for the database logging filter form.
 *
 * @see dblog_filter_form_validate()
 * @see dblog_filter_form_submit()
 * @see dblog_overview()
 *
 * @ingroup forms
 */
function dblog_filter_form($form) {
    $filters = dblog_filters();
    $form['filters'] = array(
        '#type' => 'fieldset',
        '#title' => t('Filter log messages'),
        '#collapsible' => TRUE,
        '#collapsed' => empty($_SESSION['dblog_overview_filter']),
    );
    foreach ($filters as $key => $filter) {
        $form['filters']['status'][$key] = array(
            '#title' => $filter['title'],
            '#type' => 'select',
            '#multiple' => TRUE,
            '#size' => 8,
            '#options' => $filter['options'],
        );
        if (!empty($_SESSION['dblog_overview_filter'][$key])) {
            $form['filters']['status'][$key]['#default_value'] = $_SESSION['dblog_overview_filter'][$key];
        }
    }
    $form['filters']['actions'] = array(
        '#type' => 'actions',
        '#attributes' => array(
            'class' => array(
                'container-inline',
            ),
        ),
    );
    $form['filters']['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Filter'),
    );
    if (!empty($_SESSION['dblog_overview_filter'])) {
        $form['filters']['actions']['reset'] = array(
            '#type' => 'submit',
            '#value' => t('Reset'),
        );
    }
    return $form;
}

/**
 * Form validation handler for dblog_filter_form().
 *
 * @see dblog_filter_form_submit()
 */
function dblog_filter_form_validate($form, &$form_state) {
    if ($form_state['values']['op'] == t('Filter') && empty($form_state['values']['type']) && empty($form_state['values']['severity'])) {
        form_set_error('type', t('You must select something to filter by.'));
    }
}

/**
 * Form submission handler for dblog_filter_form().
 *
 * @see dblog_filter_form_validate()
 */
function dblog_filter_form_submit($form, &$form_state) {
    $op = $form_state['values']['op'];
    $filters = dblog_filters();
    switch ($op) {
        case t('Filter'):
            foreach ($filters as $name => $filter) {
                if (isset($form_state['values'][$name])) {
                    $_SESSION['dblog_overview_filter'][$name] = $form_state['values'][$name];
                }
            }
            break;
        case t('Reset'):
            $_SESSION['dblog_overview_filter'] = array();
            break;
    }
    return 'admin/reports/dblog';
}

/**
 * Form constructor for the form that clears out the log.
 *
 * @see dblog_clear_log_submit()
 * @ingroup forms
 */
function dblog_clear_log_form($form) {
    $form['dblog_clear'] = array(
        '#type' => 'fieldset',
        '#title' => t('Clear log messages'),
        '#description' => t('This will permanently remove the log messages from the database.'),
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
    );
    $form['dblog_clear']['clear'] = array(
        '#type' => 'submit',
        '#value' => t('Clear log messages'),
        '#submit' => array(
            'dblog_clear_log_submit',
        ),
    );
    return $form;
}

/**
 * Form submission handler for dblog_clear_log_form().
 */
function dblog_clear_log_submit() {
    $_SESSION['dblog_overview_filter'] = array();
    db_truncate('watchdog')->execute();
    drupal_set_message(t('Database log cleared.'));
}

Functions

Title Deprecated Summary
dblog_build_filter_query Builds a query for database log administration filters based on session.
dblog_clear_log_form Form constructor for the form that clears out the log.
dblog_clear_log_submit Form submission handler for dblog_clear_log_form().
dblog_event Page callback: Displays details about a specific database log message.
dblog_filters Creates a list of database log administration filters that can be applied.
dblog_filter_form Form constructor for the database logging filter form.
dblog_filter_form_submit Form submission handler for dblog_filter_form().
dblog_filter_form_validate Form validation handler for dblog_filter_form().
dblog_overview Page callback: Displays a listing of database log messages.
dblog_top Page callback: Shows the most frequent log messages of a given event type.
theme_dblog_message Returns HTML for a log message.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.