Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 241 |
DbLogController | |
0.00% |
0 / 1 |
|
0.00% |
0 / 8 |
702 | |
0.00% |
0 / 241 |
create | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 7 |
|||
__construct | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 6 |
|||
getLogLevelClassMap | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 11 |
|||
overview | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 87 |
|||
eventDetails | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 57 |
|||
buildFilterQuery | |
0.00% |
0 / 1 |
42 | |
0.00% |
0 / 22 |
|||
formatMessage | |
0.00% |
0 / 1 |
20 | |
0.00% |
0 / 13 |
|||
topLogMessages | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 38 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\dblog\Controller\DbLogController. | |
*/ | |
namespace Drupal\dblog\Controller; | |
use Drupal\Component\Utility\Html; | |
use Drupal\Component\Utility\Unicode; | |
use Drupal\Core\Controller\ControllerBase; | |
use Drupal\Core\Database\Connection; | |
use Drupal\Core\Datetime\DateFormatterInterface; | |
use Drupal\Core\Extension\ModuleHandlerInterface; | |
use Drupal\Core\Form\FormBuilderInterface; | |
use Drupal\Core\Logger\RfcLogLevel; | |
use Drupal\Core\Url; | |
use Drupal\user\Entity\User; | |
use Symfony\Component\DependencyInjection\ContainerInterface; | |
/** | |
* Returns responses for dblog routes. | |
*/ | |
class DbLogController extends ControllerBase { | |
/** | |
* The database service. | |
* | |
* @var \Drupal\Core\Database\Connection | |
*/ | |
protected $database; | |
/** | |
* The module handler service. | |
* | |
* @var \Drupal\Core\Extension\ModuleHandlerInterface | |
*/ | |
protected $moduleHandler; | |
/** | |
* The date formatter service. | |
* | |
* @var \Drupal\Core\Datetime\DateFormatterInterface | |
*/ | |
protected $dateFormatter; | |
/** | |
* The form builder service. | |
* | |
* @var \Drupal\Core\Form\FormBuilderInterface | |
*/ | |
protected $formBuilder; | |
/** | |
* The user storage. | |
* | |
* @var \Drupal\user\UserStorageInterface | |
*/ | |
protected $userStorage; | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function create(ContainerInterface $container) { | |
return new static( | |
$container->get('database'), | |
$container->get('module_handler'), | |
$container->get('date.formatter'), | |
$container->get('form_builder') | |
); | |
} | |
/** | |
* Constructs a DbLogController object. | |
* | |
* @param \Drupal\Core\Database\Connection $database | |
* A database connection. | |
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler | |
* A module handler. | |
* @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter | |
* The date formatter service. | |
* @param \Drupal\Core\Form\FormBuilderInterface $form_builder | |
* The form builder service. | |
*/ | |
public function __construct(Connection $database, ModuleHandlerInterface $module_handler, DateFormatterInterface $date_formatter, FormBuilderInterface $form_builder) { | |
$this->database = $database; | |
$this->moduleHandler = $module_handler; | |
$this->dateFormatter = $date_formatter; | |
$this->formBuilder = $form_builder; | |
$this->userStorage = $this->entityManager()->getStorage('user'); | |
} | |
/** | |
* Gets an array of log level classes. | |
* | |
* @return array | |
* An array of log level classes. | |
*/ | |
public static function getLogLevelClassMap() { | |
return array( | |
RfcLogLevel::DEBUG => 'dblog-debug', | |
RfcLogLevel::INFO => 'dblog-info', | |
RfcLogLevel::NOTICE => 'dblog-notice', | |
RfcLogLevel::WARNING => 'dblog-warning', | |
RfcLogLevel::ERROR => 'dblog-error', | |
RfcLogLevel::CRITICAL => 'dblog-critical', | |
RfcLogLevel::ALERT => 'dblog-alert', | |
RfcLogLevel::EMERGENCY => 'dblog-emergency', | |
); | |
} | |
/** | |
* Displays a listing of database log messages. | |
* | |
* Messages are truncated at 56 chars. | |
* Full-length messages can be viewed on the message details page. | |
* | |
* @return array | |
* A render array as expected by drupal_render(). | |
* | |
* @see dblog_clear_log_form() | |
* @see dblog_event() | |
*/ | |
public function overview() { | |
$filter = $this->buildFilterQuery(); | |
$rows = array(); | |
$classes = static::getLogLevelClassMap(); | |
$this->moduleHandler->loadInclude('dblog', 'admin.inc'); | |
$build['dblog_filter_form'] = $this->formBuilder->getForm('Drupal\dblog\Form\DblogFilterForm'); | |
$build['dblog_clear_log_form'] = $this->formBuilder->getForm('Drupal\dblog\Form\DblogClearLogForm'); | |
$header = array( | |
// Icon column. | |
'', | |
array( | |
'data' => $this->t('Type'), | |
'field' => 'w.type', | |
'class' => array(RESPONSIVE_PRIORITY_MEDIUM)), | |
array( | |
'data' => $this->t('Date'), | |
'field' => 'w.wid', | |
'sort' => 'desc', | |
'class' => array(RESPONSIVE_PRIORITY_LOW)), | |
$this->t('Message'), | |
array( | |
'data' => $this->t('User'), | |
'field' => 'ufd.name', | |
'class' => array(RESPONSIVE_PRIORITY_MEDIUM)), | |
array( | |
'data' => $this->t('Operations'), | |
'class' => array(RESPONSIVE_PRIORITY_LOW)), | |
); | |
$query = $this->database->select('watchdog', 'w') | |
->extend('\Drupal\Core\Database\Query\PagerSelectExtender') | |
->extend('\Drupal\Core\Database\Query\TableSortExtender'); | |
$query->fields('w', array( | |
'wid', | |
'uid', | |
'severity', | |
'type', | |
'timestamp', | |
'message', | |
'variables', | |
'link', | |
)); | |
$query->leftJoin('users_field_data', 'ufd', 'w.uid = ufd.uid'); | |
if (!empty($filter['where'])) { | |
$query->where($filter['where'], $filter['args']); | |
} | |
$result = $query | |
->limit(50) | |
->orderByHeader($header) | |
->execute(); | |
foreach ($result as $dblog) { | |
$message = $this->formatMessage($dblog); | |
if ($message && isset($dblog->wid)) { | |
$title = Unicode::truncate(Html::decodeEntities(strip_tags($message)), 256, TRUE, TRUE); | |
$log_text = Unicode::truncate($title, 56, TRUE, TRUE); | |
// The link generator will escape any unsafe HTML entities in the final | |
// text. | |
$message = $this->l($log_text, new Url('dblog.event', array('event_id' => $dblog->wid), array( | |
'attributes' => array( | |
// Provide a title for the link for useful hover hints. The | |
// Attribute object will escape any unsafe HTML entities in the | |
// final text. | |
'title' => $title, | |
), | |
))); | |
} | |
$username = array( | |
'#theme' => 'username', | |
'#account' => $this->userStorage->load($dblog->uid), | |
); | |
$rows[] = array( | |
'data' => array( | |
// Cells. | |
array('class' => array('icon')), | |
$this->t($dblog->type), | |
$this->dateFormatter->format($dblog->timestamp, 'short'), | |
$message, | |
array('data' => $username), | |
array('data' => array('#markup' => $dblog->link)), | |
), | |
// Attributes for table row. | |
'class' => array(Html::getClass('dblog-' . $dblog->type), $classes[$dblog->severity]), | |
); | |
} | |
$build['dblog_table'] = array( | |
'#type' => 'table', | |
'#header' => $header, | |
'#rows' => $rows, | |
'#attributes' => array('id' => 'admin-dblog', 'class' => array('admin-dblog')), | |
'#empty' => $this->t('No log messages available.'), | |
'#attached' => array( | |
'library' => array('dblog/drupal.dblog'), | |
), | |
); | |
$build['dblog_pager'] = array('#type' => 'pager'); | |
return $build; | |
} | |
/** | |
* Displays details about a specific database log message. | |
* | |
* @param int $event_id | |
* Unique ID of the database log message. | |
* | |
* @return array | |
* If the ID is located in the Database Logging table, a build array in the | |
* format expected by drupal_render(); | |
* | |
*/ | |
public function eventDetails($event_id) { | |
$build = array(); | |
if ($dblog = $this->database->query('SELECT w.*, u.uid FROM {watchdog} w LEFT JOIN {users} u ON u.uid = w.uid WHERE w.wid = :id', array(':id' => $event_id))->fetchObject()) { | |
$severity = RfcLogLevel::getLevels(); | |
$message = $this->formatMessage($dblog); | |
$username = array( | |
'#theme' => 'username', | |
'#account' => $dblog->uid ? $this->userStorage->load($dblog->uid) : User::getAnonymousUser(), | |
); | |
$rows = array( | |
array( | |
array('data' => $this->t('Type'), 'header' => TRUE), | |
$this->t($dblog->type), | |
), | |
array( | |
array('data' => $this->t('Date'), 'header' => TRUE), | |
$this->dateFormatter->format($dblog->timestamp, 'long'), | |
), | |
array( | |
array('data' => $this->t('User'), 'header' => TRUE), | |
array('data' => $username), | |
), | |
array( | |
array('data' => $this->t('Location'), 'header' => TRUE), | |
$this->l($dblog->location, $dblog->location ? Url::fromUri($dblog->location) : Url::fromRoute('<none>')), | |
), | |
array( | |
array('data' => $this->t('Referrer'), 'header' => TRUE), | |
$this->l($dblog->referer, $dblog->referer ? Url::fromUri($dblog->referer) : Url::fromRoute('<none>')), | |
), | |
array( | |
array('data' => $this->t('Message'), 'header' => TRUE), | |
$message, | |
), | |
array( | |
array('data' => $this->t('Severity'), 'header' => TRUE), | |
$severity[$dblog->severity], | |
), | |
array( | |
array('data' => $this->t('Hostname'), 'header' => TRUE), | |
$dblog->hostname, | |
), | |
array( | |
array('data' => $this->t('Operations'), 'header' => TRUE), | |
array('data' => array('#markup' => $dblog->link)), | |
), | |
); | |
$build['dblog_table'] = array( | |
'#type' => 'table', | |
'#rows' => $rows, | |
'#attributes' => array('class' => array('dblog-event')), | |
'#attached' => array( | |
'library' => array('dblog/drupal.dblog'), | |
), | |
); | |
} | |
return $build; | |
} | |
/** | |
* Builds a query for database log administration filters based on session. | |
* | |
* @return array | |
* An associative array with keys 'where' and 'args'. | |
*/ | |
protected function buildFilterQuery() { | |
if (empty($_SESSION['dblog_overview_filter'])) { | |
return; | |
} | |
$this->moduleHandler->loadInclude('dblog', 'admin.inc'); | |
$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, | |
); | |
} | |
/** | |
* Formats a database log message. | |
* | |
* @param object $row | |
* The record from the watchdog table. The object properties are: wid, uid, | |
* severity, type, timestamp, message, variables, link, name. | |
* | |
* @return string|false | |
* The formatted log message or FALSE if the message or variables properties | |
* are not set. | |
*/ | |
public function formatMessage($row) { | |
// Check for required properties. | |
if (isset($row->message) && isset($row->variables)) { | |
// Messages without variables or user specified text. | |
if ($row->variables === 'N;') { | |
$message = $row->message; | |
} | |
// Message to translate with injected variables. | |
else { | |
$message = $this->t($row->message, unserialize($row->variables)); | |
} | |
} | |
else { | |
$message = FALSE; | |
} | |
return $message; | |
} | |
/** | |
* 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. | |
* | |
* Use one of the above *Report() methods. | |
* | |
* @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(). | |
*/ | |
public function topLogMessages($type) { | |
$header = array( | |
array('data' => $this->t('Count'), 'field' => 'count', 'sort' => 'desc'), | |
array('data' => $this->t('Message'), 'field' => 'message'), | |
); | |
$count_query = $this->database->select('watchdog'); | |
$count_query->addExpression('COUNT(DISTINCT(message))'); | |
$count_query->condition('type', $type); | |
$query = $this->database->select('watchdog', 'w') | |
->extend('\Drupal\Core\Database\Query\PagerSelectExtender') | |
->extend('\Drupal\Core\Database\Query\TableSortExtender'); | |
$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) { | |
if ($message = $this->formatMessage($dblog)) { | |
$rows[] = array($dblog->count, $message); | |
} | |
} | |
$build['dblog_top_table'] = array( | |
'#type' => 'table', | |
'#header' => $header, | |
'#rows' => $rows, | |
'#empty' => $this->t('No log messages available.'), | |
'#attached' => array( | |
'library' => array('dblog/drupal.dblog'), | |
), | |
); | |
$build['dblog_top_pager'] = array('#type' => 'pager'); | |
return $build; | |
} | |
} |