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; | |
| } | |
| } |