'Show available message types and severity levels. A prompt will ask for a choice to show watchdog messages.', 'drupal dependencies' => array('dblog'), 'outputformat' => array( 'default' => 'table', 'pipe-format' => 'var_export', 'field-labels' => array('wid' => 'ID', 'type' => 'Type', 'message' => 'Message', 'severity' => 'Severity', 'location' => 'Location', 'hostname' => 'Hostname', 'date' => 'Date', 'username' => 'Username'), 'fields-default' => array('wid', 'date', 'type', 'severity', 'message'), 'column-widths' => array('type' => 8, 'severity' => 8), 'output-data-type' => 'format-table', ), 'aliases' => array('wd-list'), ); $items['watchdog-show'] = array( 'description' => 'Show watchdog messages.', 'drupal dependencies' => array('dblog'), 'arguments' => array( 'wid' => 'Optional id of a watchdog message to show in detail. If not provided, a listing of most recent 10 messages will be displayed. Alternatively if a string is provided, watchdog messages will be filtered by it.', ), 'options' => array( 'count' => 'The number of messages to show. Defaults to 10.', 'severity' => 'Restrict to messages of a given severity level.', 'type' => 'Restrict to messages of a given type.', 'tail' => 'Continuously show new watchdog messages until interrupted.', 'sleep-delay' => 'To be used in conjunction with --tail. This is the number of seconds to wait between each poll to the database. Delay is 1 second by default.', 'extended' => 'Return extended information about each message.', ), 'examples' => array( 'drush watchdog-show' => 'Show a listing of most recent 10 messages.', 'drush watchdog-show 64' => 'Show in detail message with id 64.', 'drush watchdog-show "cron run succesful"' => 'Show a listing of most recent 10 messages containing the string "cron run succesful".', 'drush watchdog-show --count=46' => 'Show a listing of most recent 46 messages.', 'drush watchdog-show --severity=notice' => 'Show a listing of most recent 10 messages with a severity of notice.', 'drush watchdog-show --type=php' => 'Show a listing of most recent 10 messages of type php.', 'drush watchdog-show --tail --extended' => 'Show a listing of most recent 10 messages with extended information about each one and continue showing messages as they are registered in the watchdog.', 'drush watchdog-show --tail --sleep-delay=2' => 'Do a tail of the watchdog with a delay of two seconds between each poll to the database.', ), 'outputformat' => array( 'default' => 'table', 'pipe-format' => 'var_export', 'field-labels' => array('wid' => 'ID', 'type' => 'Type', 'message' => 'Message', 'severity' => 'Severity', 'location' => 'Location', 'hostname' => 'Hostname', 'date' => 'Date', 'username' => 'Username'), 'fields-default' => array('wid', 'date', 'type', 'severity', 'message'), 'column-widths' => array('type' => 8, 'severity' => 8), 'output-data-type' => 'format-table', ), 'aliases' => array('wd-show', 'ws'), ); $items['watchdog-delete'] = array( 'description' => 'Delete watchdog messages.', 'drupal dependencies' => array('dblog'), 'options' => array( 'severity' => 'Delete messages of a given severity level.', 'type' => 'Delete messages of a given type.', ), 'examples' => array( 'drush watchdog-delete all' => 'Delete all messages.', 'drush watchdog-delete 64' => 'Delete messages with id 64.', 'drush watchdog-delete "cron run succesful"' => 'Delete messages containing the string "cron run succesful".', 'drush watchdog-delete --severity=notice' => 'Delete all messages with a severity of notice.', 'drush watchdog-delete --type=cron' => 'Delete all messages of type cron.', ), 'aliases' => array('wd-del', 'wd-delete'), ); return $items; } /** * Command callback. */ function drush_core_watchdog_list() { drush_include_engine('drupal', 'environment'); $options['-- types --'] = dt('== message types =='); $types = drush_watchdog_message_types(); foreach ($types as $key => $type) { $options[$key] = $type; } $options['-- levels --'] = dt('== severity levels =='); $severities = drush_watchdog_severity_levels(); foreach ($severities as $key => $value) { $options[$key] = "$value($key)"; } $option = drush_choice($options, dt('Select a message type or severity level.')); if ($option === FALSE) { return drush_user_abort(); } if (isset($types[$option])) { drush_set_option('type', $types[$option]); } else { drush_set_option('severity', $option - $ntypes); } return drush_core_watchdog_show_many(); } /** * Command callback. */ function drush_core_watchdog_show($arg = NULL) { drush_include_engine('drupal', 'environment'); if (is_numeric($arg)) { return drush_core_watchdog_show_one($arg); } else { return drush_core_watchdog_show_many($arg); } } /** * Print a watchdog message. * * @param $wid * The id of the message to show. */ function drush_core_watchdog_show_one($wid) { drush_set_default_outputformat('key-value-list', array('fields-default' => array('wid', 'type', 'message', 'severity', 'date'),)); $rsc = drush_db_select('watchdog', '*', 'wid = :wid', array(':wid' => $wid), 0, 1); $result = drush_db_fetch_object($rsc); if (!$result) { return drush_set_error(dt('Watchdog message #!wid not found.', array('!wid' => $wid))); } $result = core_watchdog_format_result($result, TRUE); return array($result->wid => (array)$result); } /** * Print a table of watchdog messages. * * @param $filter * String to filter the message's text by. */ function drush_core_watchdog_show_many($filter = NULL) { $count = drush_get_option('count', 10); $type = drush_get_option('type'); $severity = drush_get_option('severity'); $tail = drush_get_option('tail', FALSE); $extended = drush_get_option('extended', FALSE); $where = core_watchdog_query($type, $severity, $filter); if ($where === FALSE) { return drush_log(dt('Aborting.')); } $rsc = drush_db_select('watchdog', '*', $where['where'], $where['args'], 0, $count, 'wid', 'DESC'); if ($rsc === FALSE) { return drush_log(dt('Aborting.')); } $table = array(); while ($result = drush_db_fetch_object($rsc)) { $row = core_watchdog_format_result($result, $extended); $table[$row->wid] = (array)$row; } if (empty($table) && !$tail) { drush_log(dt('No log messages available.'), LogLevel::OK); return array(); } else { drush_log(dt('Most recent !count watchdog log messages:', array('!count' => $count))); } if ($tail) { $field_list = array('wid' => 'ID', 'date' => 'Date', 'severity' => 'Severity', 'type' => 'Type', 'message' => 'Message'); $table = array_reverse($table); $table_rows = drush_rows_of_key_value_to_array_table($table, $field_list, array()); $tbl = drush_print_table($table_rows, TRUE); // Reuse the table object to display each line generated while in tail mode. // To make it possible some hacking is done on the object: // remove the header and reset the rows on each iteration. $tbl->_headers = NULL; // Obtain the last wid. If the table has no rows, start at 0. if (count($table_rows) > 1) { $last = array_pop($table_rows); $last_wid = $last[0]; } else { $last_wid = 0; } // Adapt the where snippet. if ($where['where'] != '') { $where['where'] .= ' AND '; } $where['where'] .= 'wid > :wid'; // sleep-delay $sleep_delay = drush_get_option('sleep-delay', 1); while (TRUE) { $where['args'][':wid'] = $last_wid; $table = array(); // Reset table rows. $tbl->_data = array(); $rsc = drush_db_select('watchdog', '*', $where['where'], $where['args'], NULL, NULL, 'wid', 'ASC'); while ($result = drush_db_fetch_object($rsc)) { $row = core_watchdog_format_result($result, $extended); $table[] = array($row->wid, $row->date, $row->severity, $row->type, $row->message); #$tbl->addRow(array($row->wid, $row->date, $row->severity, $row->type, $row->message)); $last_wid = $row->wid; } $tbl->addData($table); print $tbl->_buildTable(); sleep($sleep_delay); } } return $table; } /** * Format a watchdog database row. * * @param $result * Array. A database result object. * @param $extended * Boolean. Return extended message details. * @return * Array. The result object with some attributes themed. */ function core_watchdog_format_result($result, $extended = FALSE) { // Severity. $severities = drush_watchdog_severity_levels(); $result->severity = $severities[$result->severity]; // Date. $result->date = format_date($result->timestamp, 'custom', 'd/M H:i'); unset($result->timestamp); // Message. $variables = $result->variables; if (is_string($variables)) { $variables = unserialize($variables); } if (is_array($variables)) { $result->message = strtr($result->message, $variables); } unset($result->variables); $message_length = 188; // Print all the data available if ($extended) { // Possible empty values. if (empty($result->link)) { unset($result->link); } if (empty($result->referer)) { unset($result->referer); } // Username. if ($account = user_load($result->uid)) { $result->username = $account->name; } else { $result->username = dt('Anonymous'); } unset($result->uid); $message_length = PHP_INT_MAX; } if (drush_drupal_major_version() >= 8) { $result->message = Unicode::truncate(strip_tags(Html::decodeEntities($result->message)), $message_length, FALSE, FALSE); } else { $result->message = truncate_utf8(strip_tags(decode_entities($result->message)), $message_length, FALSE, FALSE); } return $result; } /** * Command callback. * * @param $arg * The id of the message to delete or 'all'. */ function drush_core_watchdog_delete($arg = NULL) { drush_include_engine('drupal', 'environment'); if ($arg == 'all') { drush_print(dt('All watchdog messages will be deleted.')); if (!drush_confirm(dt('Do you really want to continue?'))) { return drush_user_abort(); } drush_db_delete('watchdog'); drush_log(dt('All watchdog messages have been deleted.'), LogLevel::OK); } else if (is_numeric($arg)) { drush_print(dt('Watchdog message #!wid will be deleted.', array('!wid' => $arg))); if(!drush_confirm(dt('Do you really want to continue?'))) { return drush_user_abort(); } $affected_rows = drush_db_delete('watchdog', 'wid=:wid', array(':wid' => $arg)); if ($affected_rows == 1) { drush_log(dt('Watchdog message #!wid has been deleted.', array('!wid' => $arg)), LogLevel::OK); } else { return drush_set_error(dt('Watchdog message #!wid does not exist.', array('!wid' => $arg))); } } else { $type = drush_get_option('type'); $severity = drush_get_option('severity'); if ((!isset($arg))&&(!isset($type))&&(!isset($severity))) { return drush_set_error(dt('No options provided.')); } $where = core_watchdog_query($type, $severity, $arg, 'OR'); if ($where === FALSE) { // Drush set error was already called by core_watchdog_query return FALSE; } drush_print(dt('All messages with !where will be deleted.', array('!where' => preg_replace("/message LIKE %$arg%/", "message body containing '$arg'" , strtr($where['where'], $where['args']))))); if(!drush_confirm(dt('Do you really want to continue?'))) { return drush_user_abort(); } $affected_rows = drush_db_delete('watchdog', $where['where'], $where['args']); drush_log(dt('!affected_rows watchdog messages have been deleted.', array('!affected_rows' => $affected_rows)), LogLevel::OK); } } /** * Build a WHERE snippet based on given parameters. * * @param $type * String. Valid watchdog type. * @param $severity * Int or String for a valid watchdog severity message. * @param $filter * String. Value to filter watchdog messages by. * @param $criteria * ('AND', 'OR'). Criteria for the WHERE snippet. * @return * False or array with structure ('where' => string, 'args' => array()) */ function core_watchdog_query($type = NULL, $severity = NULL, $filter = NULL, $criteria = 'AND') { $args = array(); $conditions = array(); if ($type) { $types = drush_watchdog_message_types(); if (array_search($type, $types) === FALSE) { $msg = "Unrecognized message type: !type.\nRecognized types are: !types."; return drush_set_error('WATCHDOG_UNRECOGNIZED_TYPE', dt($msg, array('!type' => $type, '!types' => implode(', ', $types)))); } $conditions[] = "type = :type"; $args[':type'] = $type; } if (isset($severity)) { $severities = drush_watchdog_severity_levels(); if (isset($severities[$severity])) { $level = $severity; } elseif (($key = array_search($severity, $severities)) !== FALSE) { $level = $key; } else { $level = FALSE; } if ($level === FALSE) { foreach ($severities as $key => $value) { $levels[] = "$value($key)"; } $msg = "Unknown severity level: !severity.\nValid severity levels are: !levels."; return drush_set_error(dt($msg, array('!severity' => $severity, '!levels' => implode(', ', $levels)))); } $conditions[] = 'severity = :severity'; $args[':severity'] = $level; } if ($filter) { $conditions[] = "message LIKE :filter"; $args[':filter'] = '%'.$filter.'%'; } $where = implode(" $criteria ", $conditions); return array('where' => $where, 'args' => $args); }