solrlog-1.0.1/src/Controller/ViewLogController.php
src/Controller/ViewLogController.php
<?php
namespace Drupal\solrlog\Controller;
use Drupal\Component\Render\FormattableMarkup;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Component\Utility\Xss;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Link;
use Drupal\Core\Logger\RfcLogLevel;
use Drupal\Core\Url;
use Drupal\solrlog\SolariumTrait;
use Drupal\user\Entity\User;
use Drupal\user\UserStorageInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Returns responses for solrlog routes.
*/
class ViewLogController extends ControllerBase {
use SolariumTrait;
/**
* The date formatter service.
*
* @var \Drupal\Core\Datetime\DateFormatterInterface
*/
protected DateFormatterInterface $dateFormatter;
/**
* The user storage.
*
* @var \Drupal\user\UserStorageInterface
*/
protected UserStorageInterface $userStorage;
/**
* Constructs a ViewLogController object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager.
* @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(
EntityTypeManagerInterface $entityTypeManager,
ModuleHandlerInterface $module_handler,
DateFormatterInterface $date_formatter,
FormBuilderInterface $form_builder,
) {
$this->entityTypeManager = $entityTypeManager;
$this->moduleHandler = $module_handler;
$this->dateFormatter = $date_formatter;
$this->formBuilder = $form_builder;
$this->userStorage = $this->entityTypeManager->getStorage('user');
}
/**
* Page callback.
*
* This callback is always overriden by views.view.solrlog.
*
* @return array
* Render array
*/
public function overview() {
return [];
}
/**
* Gets an array of log level classes.
*
* @return array
* An array of log level classes.
*/
public static function getLogLevelClassMap() {
return [
RfcLogLevel::DEBUG => 'debug',
RfcLogLevel::INFO => 'info',
RfcLogLevel::NOTICE => 'notice',
RfcLogLevel::WARNING => 'warning',
RfcLogLevel::ERROR => 'error',
RfcLogLevel::CRITICAL => 'critical',
RfcLogLevel::ALERT => 'alert',
RfcLogLevel::EMERGENCY => 'emergency',
];
}
/**
* 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\Core\Render\RendererInterface::render().
*
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
* If no event found for the given ID.
*/
public function eventDetails(int $event_id) {
$connector = $this->getConnector();
if (empty($connector)) {
throw new NotFoundHttpException();
}
$query = $connector->getSelectQuery();
$query->setQuery('id:' . $event_id);
$result = $connector->createSearchResult($query, $connector->search($query));
$data = $query->getResponseParser()->parse($result);
if (empty($data['numfound'])) {
throw new NotFoundHttpException();
}
$document = $data['documents'][0]->getFields();
$severity = RfcLogLevel::getLevels();
$message = $this->formatMessage($document);
$username = [
'#theme' => 'username',
'#account' => $document['itm_uid'][0] ?
$this->userStorage->load($document['itm_uid'][0]) : User::getAnonymousUser(),
];
$rows = [
[
['data' => $this->t('Type'), 'header' => TRUE],
$document[self::$logFieldMappings['type']],
],
[
['data' => $this->t('Date'), 'header' => TRUE],
$document['timestamp'],
],
[
['data' => $this->t('User'), 'header' => TRUE],
['data' => $username],
],
[
['data' => $this->t('Location'), 'header' => TRUE],
$this->createLink($document[self::$logFieldMappings['location']]),
],
[
['data' => $this->t('Referrer'), 'header' => TRUE],
$this->createLink($document[self::$logFieldMappings['referer']]),
],
[
['data' => $this->t('Message'), 'header' => TRUE],
$message,
],
[
['data' => $this->t('Severity'), 'header' => TRUE],
$severity[$document[self::$logFieldMappings['severity']]],
],
[
['data' => $this->t('Hostname'), 'header' => TRUE],
$document[self::$logFieldMappings['hostname']],
],
];
if (isset($dblog->backtrace)) {
$rows[] = [
['data' => $this->t('Backtrace'), 'header' => TRUE],
$dblog->backtrace,
];
}
$build['dblog_table'] = [
'#type' => 'table',
'#rows' => $rows,
'#attributes' => ['class' => ['solrlog-event']],
];
return $build;
}
/**
* Formats a Solr log message.
*
* @param object $row
* The Solr document. The object properties are: wid, uid,
* severity, type, timestamp, message, variables, link, name.
*
* If the variables contain a @backtrace_string placeholder which is not
* used in the message, the formatted backtrace will be assigned to a new
* backtrace property on the row object which can be displayed separately.
*
* @return string|\Drupal\Core\StringTranslation\TranslatableMarkup|false
* The formatted log message or FALSE if the message or variables properties
* are not set.
*/
public function formatMessage($row) {
// Check for required properties.
$variables = $row[self::$logFieldMappings['variables']] ?? NULL;
if (isset($variables)) {
$variables = json_decode(current($variables), TRUE);
}
$message = $row[self::$logFieldMappings['message']] ?? NULL;
if (is_array($message)) {
$message = current($message);
}
if ($variables === NULL) {
$message = Xss::filterAdmin($row->message);
}
elseif (!is_array($variables)) {
$message = $this->t('Log data is corrupted and cannot be unserialized: @message', ['@message' => Xss::filterAdmin($row->message)]);
}
if (isset($variables['@backtrace_string'])) {
$variables['@backtrace_string'] = new FormattableMarkup(
'<pre class="backtrace">@backtrace_string</pre>', $variables
);
// Save a reference so the backtrace can be displayed separately.
if (!str_contains($message, '@backtrace_string')) {
$row['backtrace'] = $variables['@backtrace_string'];
}
}
return $this->t(Xss::filterAdmin($message), $variables);
}
/**
* Creates a Link object if the provided URI is valid.
*
* @param string|null $uri
* The uri string to convert into link if valid.
*
* @return \Drupal\Core\Link|string|null
* Return a Link object if the uri can be converted as a link. In case of
* empty uri or invalid, fallback to the provided $uri.
*/
protected function createLink($uri) {
if ($uri !== NULL && UrlHelper::isValid($uri, TRUE)) {
return new Link($uri, Url::fromUri($uri));
}
return $uri;
}
}
