Skip to content
Snippets Groups Projects

Make dblog entities

Merge request reports

Members who can merge are allowed to add commits.
Approval is optional
Code Quality is loading
Test summary results are being parsed
Merge blocked: 1 check failed
Merge conflicts must be resolved.

Merge details

  • The source branch is 1374 commits behind the target branch.
  • 1 commit will be added to 11.x.
  • Source branch will not be deleted.

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
60 60 * The form builder service.
61 61 */
62 62 public function __construct(Connection $database, ModuleHandlerInterface $module_handler, DateFormatterInterface $date_formatter, FormBuilderInterface $form_builder) {
63 @trigger_error(__CLASS__ . ' is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. Use the \Drupal\dblog\DblogEntryListBuilder class instead. See https://www.drupal.org/node/3236383', E_USER_DEPRECATED);
  • 41 }
    42
    43 /**
    44 * Shows the most frequent log messages of a given event type.
    45 *
    46 * Messages are not truncated on this page because events detailed herein do
    47 * not have links to a detailed view.
    48 *
    49 * @param string $type
    50 * Type of database log events to display (e.g., 'search').
    51 *
    52 * @return array
    53 * A build array in the format expected by
    54 * \Drupal\Core\Render\RendererInterface::render().
    55 */
    56 public function list(string $type) {
  • 44 * internal = TRUE,
    45 * entity_keys = {
    46 * "id" = "wid",
    47 * },
    48 * links = {
    49 * "canonical" = "/admin/reports/dblog/event/{dblog}",
    50 * "collection" = "/admin/reports/dblog",
    51 * }
    52 * )
    53 */
    54 final class DblogEntry extends ContentEntityBase implements DblogEntryInterface {
    55
    56 /**
    57 * {@inheritdoc}
    58 */
    59 public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
  • 5 use Drupal\Core\Access\AccessResult;
    6 use Drupal\Core\Entity\EntityAccessControlHandler;
    7 use Drupal\Core\Entity\EntityInterface;
    8 use Drupal\Core\Session\AccountInterface;
    9
    10 /**
    11 * Defines the access control handler for the dblog entry entity type.
    12 *
    13 * @see \Drupal\dblog\Entity\DblogEntry
    14 */
    15 class DblogEntryAccessControllerHandler extends EntityAccessControlHandler {
    16
    17 /**
    18 * {@inheritdoc}
    19 */
    20 protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
    • Suggested change
      20 protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
      20 protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account): AccessResultInterface {
    • Please register or sign in to reply
  • 12 *
    13 * @see \Drupal\dblog\Entity\DblogEntry
    14 */
    15 class DblogEntryAccessControllerHandler extends EntityAccessControlHandler {
    16
    17 /**
    18 * {@inheritdoc}
    19 */
    20 protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
    21 return AccessResult::allowedIfHasPermission($account, 'access site reports');
    22 }
    23
    24 /**
    25 * {@inheritdoc}
    26 */
    27 public function createAccess($entity_bundle = NULL, ?AccountInterface $account = NULL, array $context = [], $return_as_object = FALSE) {
    • Suggested change
      27 public function createAccess($entity_bundle = NULL, ?AccountInterface $account = NULL, array $context = [], $return_as_object = FALSE) {
      27 public function createAccess($entity_bundle = NULL, ?AccountInterface $account = NULL, array $context = [], $return_as_object = FALSE): AccessResultInterface {
    • Please register or sign in to reply
  • 63 * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
    64 * The entity type definition.
    65 * @param \Drupal\Core\Entity\EntityStorageInterface $storage
    66 * The entity storage class.
    67 * @param \Symfony\Component\HttpFoundation\Request $current_request
    68 * The current request.
    69 * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
    70 * The date formatter service.
    71 * @param \Drupal\dblog\DblogFormatterInterface $dblog_formatter
    72 * The dblog formatter service.
    73 * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
    74 * The form builder.
    75 * @param \Drupal\Core\Entity\EntityStorageInterface $user_storage
    76 * The user storage service.
    77 */
    78 public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, Request $current_request, DateFormatterInterface $date_formatter, DblogFormatterInterface $dblog_formatter, FormBuilderInterface $form_builder, EntityStorageInterface $user_storage) {
  • 121 if ($this->currentRequest->query->has('order')) {
    122 // Allow the entity query to sort using the table header.
    123 $header = $this->buildHeader();
    124 $query->tableSort($header);
    125 }
    126 else {
    127 $query->sort('wid', 'DESC');
    128 }
    129
    130 return $query->execute();
    131 }
    132
    133 /**
    134 * {@inheritdoc}
    135 */
    136 public function buildHeader() {
  • 91 public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
    92 return new static(
    93 $entity_type,
    94 $container->get('entity_type.manager')->getStorage($entity_type->id()),
    95 $container->get('request_stack')->getCurrentRequest(),
    96 $container->get('date.formatter'),
    97 $container->get('dblog.formatter'),
    98 $container->get('form_builder'),
    99 $container->get('entity_type.manager')->getStorage('user'),
    100 );
    101 }
    102
    103 /**
    104 * {@inheritdoc}
    105 */
    106 protected function getEntityIds() {
  • 159 ],
    160 'uid' => [
    161 'data' => $this->t('User'),
    162 'class' => [RESPONSIVE_PRIORITY_MEDIUM],
    163 'specifier' => 'uid',
    164 'field' => 'uid',
    165 ],
    166 ];
    167
    168 return $header + parent::buildHeader();
    169 }
    170
    171 /**
    172 * {@inheritdoc}
    173 */
    174 public function buildRow(EntityInterface $entity) {
  • 51 */
    52 protected $dblogFormatter;
    53
    54 /**
    55 * Constructs a new dblog entry view builder.
    56 *
    57 * @param \Drupal\Core\Render\RendererInterface $renderer
    58 * The renderer service.
    59 * @param \Drupal\Core\Entity\EntityStorageInterface $user_storage
    60 * The user storage service.
    61 * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter
    62 * The date formatter service.
    63 * @param \Drupal\dblog\DblogFormatterInterface $dblog_formatter
    64 * The dblog formatter service.
    65 */
    66 public function __construct(RendererInterface $renderer, EntityStorageInterface $user_storage, DateFormatterInterface $date_formatter, DblogFormatterInterface $dblog_formatter) {
  • 160 public function getCacheTags() {
    161 // Intentionally empty.
    162 return [];
    163 }
    164
    165 /**
    166 * Creates a Link object if the provided URI is valid.
    167 *
    168 * @param string|null $uri
    169 * The uri string to convert into link if valid.
    170 *
    171 * @return \Drupal\Core\Link|string|null
    172 * Return a Link object if the uri can be converted as a link. In case of
    173 * empty uri or invalid, fallback to the provided $uri.
    174 */
    175 protected function createLink($uri) {
  • 15
    16 /**
    17 * {@inheritdoc}
    18 */
    19 protected function setDatabaseDumpFiles() {
    20 $this->databaseDumpFiles = [
    21 __DIR__ . '/../../../../../system/tests/fixtures/update/drupal-10.3.0.filled.standard.php.gz',
    22 ];
    23 }
    24
    25 /**
    26 * Tests that dblog view row style is updated properly.
    27 *
    28 * @group legacy
    29 */
    30 public function testSeverityUpdate() {
  • 4
    5 namespace Drupal\Tests\dblog\Functional\Update;
    6
    7 use Drupal\FunctionalTests\Update\UpdatePathTestBase;
    8
    9 /**
    10 * Tests the upgrade path for modifying dblog row styles.
    11 *
    12 * @group Update
    13 */
    14 class DblogViewSeverityUpdateTest extends UpdatePathTestBase {
    15
    16 /**
    17 * {@inheritdoc}
    18 */
    19 protected function setDatabaseDumpFiles() {
  • 25 protected static $modules = ['dblog', 'system', 'user'];
    26
    27 /**
    28 * {@inheritdoc}
    29 */
    30 protected function setUp(): void {
    31 parent::setUp();
    32
    33 $this->installSchema('dblog', ['watchdog']);
    34 $this->installConfig(['system']);
    35 }
    36
    37 /**
    38 * Tests creation of log entries.
    39 */
    40 public function testCreate() {
  • 63
    64 $this->assertEquals('', $log->getReferer());
    65
    66 $this->assertEquals('127.0.0.1', $log->getHostname());
    67
    68 $this->assertEquals(1632269259, $log->getTimestamp());
    69
    70 $this->expectException(EntityStorageException::class);
    71 $this->expectExceptionMessage('Use dblog.logger service to create log entities.');
    72 $log->save();
    73 }
    74
    75 /**
    76 * Tests loading a log entry.
    77 */
    78 public function testLoad() {
  • 75 /**
    76 * Tests loading a log entry.
    77 */
    78 public function testLoad() {
    79 $this->generateLogEntries(1);
    80 $log = DblogEntry::load(1);
    81
    82 $this->assertEquals(1, $log->id());
    83 $this->assertEquals('Dblog test log message Entry #0', $log->get('message')->getString());
    84 $this->assertEquals(RfcLogLevel::NOTICE, $log->getSeverity());
    85 }
    86
    87 /**
    88 * Tests deletion of log entries.
    89 */
    90 public function testDelete() {
  • 85 }
    86
    87 /**
    88 * Tests deletion of log entries.
    89 */
    90 public function testDelete() {
    91 $this->generateLogEntries(1);
    92 $log = DblogEntry::load(1);
    93 $log->delete();
    94 $this->assertNull(DblogEntry::load(1));
    95 }
    96
    97 /**
    98 * Tests that the log entries cannot be updated once created.
    99 */
    100 public function testUpdate() {
  • 98 * Tests that the log entries cannot be updated once created.
    99 */
    100 public function testUpdate() {
    101 $this->generateLogEntries(1);
    102 $log = DblogEntry::load(1);
    103
    104 $this->expectException(EntityStorageException::class);
    105 $this->expectExceptionMessage('Dblog entries are read only entities. Saving them once created is not allowed.');
    106
    107 $log->save();
    108 }
    109
    110 /**
    111 * Tests common dblog fields.
    112 */
    113 public function testHasField() {
  • 123 'referer',
    124 'hostname',
    125 'timestamp',
    126 ];
    127 $log = DblogEntry::create();
    128 foreach ($fields as $field_name) {
    129 $this->assertTrue($log->hasField($field_name));
    130 }
    131
    132 $this->assertFalse($log->hasField('field_message'));
    133 }
    134
    135 /**
    136 * Tests field definitions.
    137 */
    138 public function testFieldDefinition() {
  • 176 'message' => '<script>Test</script>',
    177 'variables' => serialize([]),
    178 ]);
    179 $this->assertEquals($log->getFormattedMessage($dblog_formatter), 'Test');
    180
    181 $log = DblogEntry::create([
    182 'message' => 'Testing @module module',
    183 'variables' => serialize(['@module' => 'dblog']),
    184 ]);
    185 $this->assertEquals($log->getFormattedMessage($dblog_formatter), 'Testing dblog module');
    186 }
    187
    188 /**
    189 * Tests validate methods.
    190 */
    191 public function testValidate() {
  • 10
    11 /**
    12 * Test the dblog entries storage.
    13 *
    14 * @group dblog
    15 */
    16 class DbLogEntryStorageTest extends KernelTestBase {
    17
    18 use FakeLogEntries;
    19
    20 /**
    21 * The dblog storage.
    22 *
    23 * @var \Drupal\dblog\DblogEntryStorageInterface
    24 */
    25 protected $storage;
  • 17
    18 use FakeLogEntries;
    19
    20 /**
    21 * The dblog storage.
    22 *
    23 * @var \Drupal\dblog\DblogEntryStorageInterface
    24 */
    25 protected $storage;
    26
    27 /**
    28 * The dblog formatter service.
    29 *
    30 * @var \Drupal\dblog\DblogFormatterInterface
    31 */
    32 protected $dblogFormatter;
  • 39 /**
    40 * {@inheritdoc}
    41 */
    42 protected function setUp(): void {
    43 parent::setUp();
    44
    45 $this->installSchema('dblog', ['watchdog']);
    46 $this->installConfig(['system']);
    47 $this->storage = \Drupal::entityTypeManager()->getStorage('dblog');
    48 $this->dblogFormatter = \Drupal::service('dblog.formatter');
    49 }
    50
    51 /**
    52 * Tests createInstance method.
    53 */
    54 public function testCreateInstance() {
  • 47 $this->storage = \Drupal::entityTypeManager()->getStorage('dblog');
    48 $this->dblogFormatter = \Drupal::service('dblog.formatter');
    49 }
    50
    51 /**
    52 * Tests createInstance method.
    53 */
    54 public function testCreateInstance() {
    55 $this->assertEquals('dblog', $this->storage->getEntityTypeId());
    56 $this->assertEquals('Dblog entry', $this->storage->getEntityType()->getLabel());
    57 }
    58
    59 /**
    60 * Tests deleteAll and hasData methods.
    61 */
    62 public function testDeleteAll() {
  • 69 $this->assertFalse($this->storage->hasData());
    70
    71 $this->generateLogEntries(5);
    72 // Delete all but the first log entry.
    73 $this->storage->deleteAll(1);
    74 $this->assertTrue($this->storage->hasData());
    75 $this->assertCount(1, $this->storage->loadMultiple());
    76
    77 $this->expectException(\InvalidArgumentException::class);
    78 $this->storage->deleteAll(-1);
    79 }
    80
    81 /**
    82 * Tests messageType method.
    83 */
    84 public function testMessageTypes() {
  • 84 public function testMessageTypes() {
    85 $this->assertEquals([], $this->storage->messageTypes());
    86 $this->generateLogEntries(5);
    87 $this->assertEquals(['custom' => 'custom'], $this->storage->messageTypes());
    88
    89 $this->generateLogEntries(1, ['channel' => 'system']);
    90 $this->assertEquals([
    91 'custom' => 'custom',
    92 'system' => 'system',
    93 ], $this->storage->messageTypes());
    94 }
    95
    96 /**
    97 * Tests loadMultiple method.
    98 */
    99 public function testLoadMultiple() {
  • 118 $c = array_pop($logs);
    119 $b = array_pop($logs);
    120
    121 // Logs can be loaded in a particular order as well.
    122 $this->assertEquals('Dblog test log message Entry #1', $b->getFormattedMessage($this->dblogFormatter));
    123 $this->assertEquals('Dblog test log message Entry #0', $c->getFormattedMessage($this->dblogFormatter));
    124 $this->assertEquals('Dblog test log message Entry #2', $a->getFormattedMessage($this->dblogFormatter));
    125
    126 $logs = $this->storage->loadMultiple([$a->id(), $a->id(), $a->id()]);
    127 $this->assertCount(1, $logs, 'Duplicated logs id are loaded once');
    128 }
    129
    130 /**
    131 * Tests load and loadUnchanged methods.
    132 */
    133 public function testLoad() {
  • 134 $this->generateLogEntries(3);
    135 $logs = $this->storage->loadMultiple();
    136
    137 $third = array_pop($logs);
    138 $second = array_pop($logs);
    139 $first = array_pop($logs);
    140
    141 $this->assertEquals($second, $this->storage->load($second->id()));
    142 $this->assertNull($this->storage->load(100));
    143 $this->assertEquals($second, $this->storage->loadUnchanged($second->id()));
    144 }
    145
    146 /**
    147 * Tests loadByProperties method.
    148 */
    149 public function testLoadByProperties() {
  • 164 $logs = $this->storage->loadByProperties([
    165 'type' => 'php',
    166 'severity' => RfcLogLevel::WARNING,
    167 ]);
    168 $this->assertCount(0, $logs);
    169
    170 $logs = $this->storage->loadByProperties([
    171 'type' => ['php', 'page not found'],
    172 ]);
    173 $this->assertCount(3, $logs);
    174 }
    175
    176 /**
    177 * Tests hasData method.
    178 */
    179 public function testHasData() {
  • 173 $this->assertCount(3, $logs);
    174 }
    175
    176 /**
    177 * Tests hasData method.
    178 */
    179 public function testHasData() {
    180 $this->assertFalse($this->storage->hasData());
    181 $this->generateLogEntries(1);
    182 $this->assertTrue($this->storage->hasData());
    183 }
    184
    185 /**
    186 * Tests aggregated query and get query methods.
    187 */
    188 public function testAggregateCount() {
  • 186 * Tests aggregated query and get query methods.
    187 */
    188 public function testAggregateCount() {
    189 $this->generateLogEntries(2);
    190
    191 $result = (int) $this->storage->getQuery()->count()->accessCheck(FALSE)->execute();
    192 $this->assertEquals(2, $result);
    193
    194 $result = (int) $this->storage->getAggregateQuery()->count()->accessCheck(FALSE)->execute();
    195 $this->assertEquals(2, $result);
    196 }
    197
    198 /**
    199 * Tests mostFrequentLogEntries method.
    200 */
    201 public function testMostFrequentLogs() {
  • 209 }
    210 }
    211 $this->generateLogEntries(3, ['channel' => 'access denied']);
    212
    213 $most_frequent = $this->storage->mostFrequentLogEntries('page not found');
    214 $this->assertCount(2, $most_frequent, 'There are 2 aggregated log entries for type: page not found');
    215 $this->assertEquals(5, $most_frequent[0]['count']);
    216 $this->assertEquals('/other', $most_frequent[0]['entry']->getFormattedMessage($this->dblogFormatter), 'Most frequent page not found log entry is: /other');
    217 $this->assertEquals(2, $most_frequent[1]['count']);
    218 $this->assertEquals('/something_else', $most_frequent[1]['entry']->getFormattedMessage($this->dblogFormatter));
    219 }
    220
    221 /**
    222 * Tests loadMostRecent method.
    223 */
    224 public function testLoadMostRecent() {
  • 19 19 * - options: Array of options for the select list for the filter.
    20 20 */
    21 21 function dblog_filters() {
    22 @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.0.0 and is removed from drupal:12.0.0. See https://www.drupal.org/node/3236383', E_USER_DEPRECATED);
  • 99 104 function dblog_update_last_removed() {
    100 105 return 10101;
    101 106 }
    107
    108 /**
    109 * Install the 'dblog entry' entity type.
    110 */
    111 function dblog_update_11000() {
  • 122 'base_table' => 'watchdog',
    123 'entity_keys' => [
    124 'id' => 'wid',
    125 ],
    126 ]);
    127 $field_storage_definitions = DblogEntry::baseFieldDefinitions($entity_type);
    128 $entity_definition_update_manager->installFieldableEntityType($entity_type, $field_storage_definitions);
    129
    130 return t('The "Dblog entry" entity type has been installed.');
    131 }
    132 }
    133
    134 /**
    135 * Changes class used by dblog to indicate severity icons.
    136 */
    137 function dblog_update_11001() {
  • 92 76 * List of uniquely defined database log message types.
    93 77 */
    94 78 function _dblog_get_message_types() {
    95 return \Drupal::database()->query('SELECT DISTINCT([type]) FROM {watchdog} ORDER BY [type]')
    96 ->fetchAllKeyed(0, 0);
    79 @trigger_error(__FUNCTION__ . '() is deprecated in drupal:11.0.0 and is removed from drupal:12.0.0. See https://www.drupal.org/node/3236383', E_USER_DEPRECATED);
  • 118 102 $view->element['#attached']['library'][] = 'dblog/drupal.dblog';
    119 103 }
    120 104 }
    105
    106 /**
    107 * Implements hook_module_preuninstall().
    108 */
    109 function dblog_module_preuninstall($module) {
    Please register or sign in to reply
    Loading