From b1e2ed55d6b2635af837a59c0559ff2317cb0a58 Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole Date: Thu, 22 Jun 2017 11:47:52 +0100 Subject: [PATCH] Issue #2015149 by dagmar, Jo Fitzgerald, hanoii, pritish.kumar, Pol, Lendude, damiankloip, nicolas.rafaelli, alansaviolobo, Psikik, mondrake, yoroy, dawehner, alexpott, catch, jibran: Replace dblog recent log entries with a view --- .../config/optional/views.view.watchdog.yml | 709 ++++++++++++++++++ core/modules/dblog/dblog.module | 10 + core/modules/dblog/dblog.post_update.php | 35 + .../DblogRecentLogsUsingViewsUpdateTest.php | 40 + .../dblog/tests/src/Functional/DbLogTest.php | 30 +- .../tests/src/Functional/DbLogViewsTest.php | 70 ++ .../src/Functional/d6/MigrateUpgrade6Test.php | 2 +- .../src/Functional/d7/MigrateUpgrade7Test.php | 2 +- 8 files changed, 893 insertions(+), 5 deletions(-) create mode 100644 core/modules/dblog/config/optional/views.view.watchdog.yml create mode 100644 core/modules/dblog/dblog.post_update.php create mode 100644 core/modules/dblog/src/Tests/Update/DblogRecentLogsUsingViewsUpdateTest.php create mode 100644 core/modules/dblog/tests/src/Functional/DbLogViewsTest.php diff --git a/core/modules/dblog/config/optional/views.view.watchdog.yml b/core/modules/dblog/config/optional/views.view.watchdog.yml new file mode 100644 index 00000000000..a805ca59889 --- /dev/null +++ b/core/modules/dblog/config/optional/views.view.watchdog.yml @@ -0,0 +1,709 @@ +langcode: en +status: true +dependencies: + module: + - dblog + - user +id: watchdog +label: Watchdog +module: views +description: 'Recent log messages' +tag: '' +base_table: watchdog +base_field: wid +core: 8.x +display: + default: + display_plugin: default + id: default + display_title: Master + position: 0 + display_options: + access: + type: perm + options: + perm: 'access site reports' + cache: + type: none + options: { } + query: + type: views_query + options: + disable_sql_rewrite: false + distinct: false + replica: false + query_comment: '' + query_tags: { } + exposed_form: + type: basic + options: + submit_button: Filter + reset_button: true + reset_button_label: Reset + exposed_sorts_label: 'Sort by' + expose_sort_order: false + sort_asc_label: Asc + sort_desc_label: Desc + pager: + type: mini + options: + items_per_page: 50 + offset: 0 + id: 0 + total_pages: null + expose: + items_per_page: false + items_per_page_label: 'Items per page' + items_per_page_options: '5, 10, 25, 50' + items_per_page_options_all: false + items_per_page_options_all_label: '- All -' + offset: false + offset_label: Offset + tags: + previous: ‹‹ + next: ›› + style: + type: table + options: + grouping: { } + row_class: '{{ type }} {{ severity }}' + default_row_class: true + override: true + sticky: false + caption: '' + summary: '' + description: '' + columns: + nothing: nothing + wid: wid + severity: severity + type: type + timestamp: timestamp + message: message + name: name + link: link + info: + nothing: + sortable: false + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: priority-medium + wid: + sortable: false + default_sort_order: desc + align: '' + separator: '' + empty_column: false + responsive: priority-low + severity: + sortable: false + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: priority-low + type: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: priority-medium + timestamp: + sortable: true + default_sort_order: desc + align: '' + separator: '' + empty_column: false + responsive: priority-low + message: + sortable: false + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: '' + name: + sortable: true + default_sort_order: asc + align: '' + separator: '' + empty_column: false + responsive: priority-medium + link: + align: '' + separator: '' + empty_column: false + responsive: priority-low + default: wid + empty_table: false + row: + type: fields + fields: + nothing: + id: nothing + table: views + field: nothing + relationship: none + group_type: group + admin_label: Icon + label: '' + exclude: false + alter: + alter_text: true + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: icon + element_label_type: '' + element_label_class: '' + element_label_colon: false + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: false + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: false + plugin_id: custom + wid: + id: wid + table: watchdog + field: wid + relationship: none + group_type: group + admin_label: '' + label: WID + exclude: true + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + plugin_id: standard + severity: + id: severity + table: watchdog + field: severity + relationship: none + group_type: group + admin_label: '' + label: Severity + exclude: true + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + machine_name: false + plugin_id: machine_name + type: + id: type + table: watchdog + field: type + relationship: none + group_type: group + admin_label: '' + label: Type + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + plugin_id: standard + timestamp: + id: timestamp + table: watchdog + field: timestamp + relationship: none + group_type: group + admin_label: '' + label: Date + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + date_format: short + custom_date_format: '' + timezone: '' + plugin_id: date + message: + id: message + table: watchdog + field: message + relationship: none + group_type: group + admin_label: '' + label: Message + exclude: false + alter: + alter_text: false + text: '' + make_link: true + path: 'admin/reports/dblog/event/{{ wid }}' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '{{ message }}' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 56 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: true + trim: true + preserve_tags: '' + html: true + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + replace_variables: true + plugin_id: dblog_message + name: + id: name + table: users_field_data + field: name + relationship: uid + group_type: group + admin_label: '' + label: User + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + click_sort_column: value + type: user_name + settings: + link_to_entity: true + group_column: value + group_columns: { } + group_rows: true + delta_limit: 0 + delta_offset: 0 + delta_reversed: false + delta_first_last: false + multi_type: separator + separator: ', ' + field_api_classes: false + entity_type: user + entity_field: name + plugin_id: field + link: + id: link + table: watchdog + field: link + relationship: none + group_type: group + admin_label: '' + label: Operations + exclude: false + alter: + alter_text: false + text: '' + make_link: false + path: '' + absolute: false + external: false + replace_spaces: false + path_case: none + trim_whitespace: false + alt: '' + rel: '' + link_class: '' + prefix: '' + suffix: '' + target: '' + nl2br: false + max_length: 0 + word_boundary: true + ellipsis: true + more_link: false + more_link_text: '' + more_link_path: '' + strip_tags: false + trim: false + preserve_tags: '' + html: false + element_type: '' + element_class: '' + element_label_type: '' + element_label_class: '' + element_label_colon: true + element_wrapper_type: '' + element_wrapper_class: '' + element_default_classes: true + empty: '' + hide_empty: false + empty_zero: false + hide_alter_empty: true + plugin_id: dblog_operations + filters: + type: + id: type + table: watchdog + field: type + relationship: none + group_type: group + admin_label: '' + operator: in + value: { } + group: 1 + exposed: true + expose: + operator_id: type_op + label: Type + description: '' + use_operator: false + operator: type_op + identifier: type + required: false + remember: false + multiple: true + remember_roles: + authenticated: authenticated + anonymous: '0' + administrator: '0' + reduce: false + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + plugin_id: dblog_types + severity: + id: severity + table: watchdog + field: severity + relationship: none + group_type: group + admin_label: '' + operator: in + value: { } + group: 1 + exposed: true + expose: + operator_id: severity_op + label: Severity + description: '' + use_operator: false + operator: severity_op + identifier: severity + required: false + remember: false + multiple: true + remember_roles: + authenticated: authenticated + anonymous: '0' + administrator: '0' + reduce: false + is_grouped: false + group_info: + label: '' + description: '' + identifier: '' + optional: true + widget: select + multiple: false + remember: false + default_group: All + default_group_multiple: { } + group_items: { } + plugin_id: in_operator + sorts: + wid: + id: wid + table: watchdog + field: wid + relationship: none + group_type: group + admin_label: '' + order: DESC + exposed: false + expose: + label: '' + plugin_id: standard + title: 'Recent log messages' + header: { } + footer: { } + empty: + area: + id: area + table: views + field: area + relationship: none + group_type: group + admin_label: '' + empty: true + tokenize: false + content: + value: 'No log messages available.' + format: basic_html + plugin_id: text + relationships: + uid: + id: uid + table: watchdog + field: uid + relationship: none + group_type: group + admin_label: User + required: false + plugin_id: standard + arguments: { } + display_extenders: { } + filter_groups: + operator: AND + groups: + 1: AND + css_class: admin-dblog + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - user.permissions + tags: { } + page: + display_plugin: page + id: page + display_title: Page + position: 1 + display_options: + display_extenders: { } + path: admin/reports/dblog + cache_metadata: + max-age: 0 + contexts: + - 'languages:language_content' + - 'languages:language_interface' + - url + - url.query_args + - user.permissions + tags: { } diff --git a/core/modules/dblog/dblog.module b/core/modules/dblog/dblog.module index f33f74902fb..700ceeaa6bd 100644 --- a/core/modules/dblog/dblog.module +++ b/core/modules/dblog/dblog.module @@ -13,6 +13,7 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\views\ViewEntityInterface; +use Drupal\views\ViewExecutable; /** * Implements hook_help(). @@ -187,3 +188,12 @@ function dblog_view_presave(ViewEntityInterface $view) { $view->set('display', $displays); } } + +/** + * Implements hook_views_pre_render(). + */ +function dblog_views_pre_render(ViewExecutable $view) { + if (isset($view) && ($view->storage->get('base_table') == 'watchdog')) { + $view->element['#attached']['library'][] = 'dblog/drupal.dblog'; + } +} diff --git a/core/modules/dblog/dblog.post_update.php b/core/modules/dblog/dblog.post_update.php new file mode 100644 index 00000000000..6021ec6b526 --- /dev/null +++ b/core/modules/dblog/dblog.post_update.php @@ -0,0 +1,35 @@ +moduleExists('views')) { + if (!View::load('watchdog')) { + // Save the watchdog view to config. + $module_handler = \Drupal::moduleHandler(); + $optional_install_path = $module_handler->getModule('dblog')->getPath() . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY; + $storage = new FileStorage($optional_install_path); + + \Drupal::entityTypeManager() + ->getStorage('view') + ->create($storage->read('views.view.watchdog')) + ->save(); + + return t('The watchdog view has been created.'); + } + + return t("The watchdog view already exists and was not replaced. To replace the 'Recent log messages' with a view, rename the watchdog view and uninstall and install the 'Database Log' module"); + } +} diff --git a/core/modules/dblog/src/Tests/Update/DblogRecentLogsUsingViewsUpdateTest.php b/core/modules/dblog/src/Tests/Update/DblogRecentLogsUsingViewsUpdateTest.php new file mode 100644 index 00000000000..4ea6d49f9b8 --- /dev/null +++ b/core/modules/dblog/src/Tests/Update/DblogRecentLogsUsingViewsUpdateTest.php @@ -0,0 +1,40 @@ +databaseDumpFiles = [ + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz', + ]; + } + + /** + * Ensures that update hook is run for dblog module. + */ + public function testUpdate() { + // Make sure the watchog view doesn't exist before the updates. + $view = \Drupal::entityTypeManager()->getStorage('view')->load('watchdog'); + $this->assertNull($view); + + $this->runUpdates(); + + // Ensure the watchdog view is present after run updates. + $view = \Drupal::entityTypeManager()->getStorage('view')->load('watchdog'); + $displays = $view->get('display'); + + $this->assertIdentical($displays['page']['display_options']['path'], 'admin/reports/dblog', 'Recent logs message view exists.'); + } + +} diff --git a/core/modules/dblog/tests/src/Functional/DbLogTest.php b/core/modules/dblog/tests/src/Functional/DbLogTest.php index bddc80712b5..5b82282d6aa 100644 --- a/core/modules/dblog/tests/src/Functional/DbLogTest.php +++ b/core/modules/dblog/tests/src/Functional/DbLogTest.php @@ -248,10 +248,10 @@ class DbLogTest extends BrowserTestBase { */ protected function filterLogsEntries($type = NULL, $severity = NULL) { $edit = []; - if (!is_null($type)) { + if (isset($type)) { $edit['type[]'] = $type; } - if (!is_null($severity)) { + if (isset($severity)) { $edit['severity[]'] = $severity; } $this->drupalPostForm(NULL, $edit, t('Filter')); @@ -278,6 +278,12 @@ class DbLogTest extends BrowserTestBase { $this->assertText(t('Recent log messages'), 'DBLog report was displayed'); } + $this->drupalGet('admin/reports/dblog/confirm'); + $this->assertResponse($response); + if ($response == 200) { + $this->assertText(t('Are you sure you want to delete the recent logs?'), 'DBLog clear logs form was displayed'); + } + // View the database log page-not-found report page. $this->drupalGet('admin/reports/page-not-found'); $this->assertResponse($response); @@ -799,7 +805,7 @@ class DbLogTest extends BrowserTestBase { $this->drupalGet('admin/reports/dblog'); $this->assertResponse(200); // Make sure HTML tags are filtered out. - $this->assertRaw('title="alert('foo');Lorem ipsum dolor sit amet, consectetur adipiscing & elit. Entry #0"><script>alert('foo');</script>Lorem ipsum dolor sit…'); + $this->assertRaw('title="alert('foo');Lorem'); $this->assertNoRaw(""); // Make sure HTML tags are filtered out in admin/reports/dblog/event/ too. @@ -810,4 +816,22 @@ class DbLogTest extends BrowserTestBase { $this->assertRaw("alert('foo'); Lorem ipsum"); } + /** + * Test sorting for entries with the same timestamp. + */ + public function testSameTimestampEntries() { + $this->drupalLogin($this->adminUser); + + $this->generateLogEntries(1, ['timestamp' => 1498062000, 'type' => 'same_time', 'message' => 'First']); + $this->generateLogEntries(1, ['timestamp' => 1498062000, 'type' => 'same_time', 'message' => 'Second']); + $this->generateLogEntries(1, ['timestamp' => 1498062000, 'type' => 'same_time', 'message' => 'Third']); + + $this->drupalGet('admin/reports/dblog'); + + $entries = $this->getLogEntries(); + $this->assertEquals($entries[0]['message'], 'Third Entry #0'); + $this->assertEquals($entries[1]['message'], 'Second Entry #0'); + $this->assertEquals($entries[2]['message'], 'First Entry #0'); + } + } diff --git a/core/modules/dblog/tests/src/Functional/DbLogViewsTest.php b/core/modules/dblog/tests/src/Functional/DbLogViewsTest.php new file mode 100644 index 00000000000..d04d9ba1542 --- /dev/null +++ b/core/modules/dblog/tests/src/Functional/DbLogViewsTest.php @@ -0,0 +1,70 @@ +xpath('.//table[contains(@class, "views-view-table")]/tbody/tr'); + } + + /** + * {@inheritdoc} + */ + protected function filterLogsEntries($type = NULL, $severity = NULL) { + $query = []; + if (isset($type)) { + $query['type[]'] = $type; + } + if (isset($severity)) { + $query['severity[]'] = $severity; + } + + $this->drupalGet('admin/reports/dblog', ['query' => $query]); + } + + /** + * {@inheritdoc} + */ + public function testDBLogAddAndClear() { + // Is necesary to create the basic_html format because if absent after + // delete the logs, a new log entry is created indicating that basic_html + // format do not exists. + $basic_html_format = FilterFormat::create([ + 'format' => 'basic_html', + 'name' => 'Basic HTML', + 'filters' => [ + 'filter_html' => [ + 'status' => 1, + 'settings' => [ + 'allowed_html' => '


', + ], + ], + ], + ]); + $basic_html_format->save(); + + parent::testDBLogAddAndClear(); + } + +} diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php index 0578675c054..5299f38e24a 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d6/MigrateUpgrade6Test.php @@ -65,7 +65,7 @@ class MigrateUpgrade6Test extends MigrateUpgradeTestBase { 'user' => 7, 'user_role' => 6, 'menu_link_content' => 4, - 'view' => 14, + 'view' => 15, 'date_format' => 11, 'entity_form_display' => 19, 'entity_form_mode' => 1, diff --git a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php index 6bb46a9fecf..1d412191ab8 100644 --- a/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/d7/MigrateUpgrade7Test.php @@ -66,7 +66,7 @@ class MigrateUpgrade7Test extends MigrateUpgradeTestBase { 'user' => 4, 'user_role' => 3, 'menu_link_content' => 7, - 'view' => 14, + 'view' => 15, 'date_format' => 11, 'entity_form_display' => 18, 'entity_form_mode' => 1,