From 3260c6c4f895354572071e1e21daf576a01d9dfb Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Mon, 8 May 2017 13:30:36 +0100
Subject: [PATCH] Issue #2851293 by dagmar, alexpott, Munavijayalakshmi,
 jibran, Lendude, dawehner, catch: dblog is using the wrong views field,
 filter and relationships definitions

---
 .../config/schema/dblog.views.schema.yml      |   4 +
 core/modules/dblog/dblog.install              |  66 +++
 core/modules/dblog/dblog.module               |  72 +++
 core/modules/dblog/dblog.views.inc            |  13 +-
 .../src/Plugin/views/filter/DblogTypes.php    |  24 +
 .../DblogFiltersAndFieldsUpgradeTest.php      |  77 +++
 .../tests/fixtures/update/dblog-2851293.php   |  19 +
 .../test_views/views.view.dblog_2851293.yml   | 148 +++++
 .../views.view.dblog_integration_test.yml     | 505 ++++++++++++++++++
 .../src/Kernel/Views/ViewsIntegrationTest.php | 185 +++++--
 10 files changed, 1067 insertions(+), 46 deletions(-)
 create mode 100644 core/modules/dblog/src/Plugin/views/filter/DblogTypes.php
 create mode 100644 core/modules/dblog/src/Tests/Update/DblogFiltersAndFieldsUpgradeTest.php
 create mode 100644 core/modules/dblog/tests/fixtures/update/dblog-2851293.php
 create mode 100644 core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.dblog_2851293.yml
 create mode 100644 core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.dblog_integration_test.yml

diff --git a/core/modules/dblog/config/schema/dblog.views.schema.yml b/core/modules/dblog/config/schema/dblog.views.schema.yml
index e504364e0ef9..a2e09af3856a 100644
--- a/core/modules/dblog/config/schema/dblog.views.schema.yml
+++ b/core/modules/dblog/config/schema/dblog.views.schema.yml
@@ -11,3 +11,7 @@ views.field.dblog_message:
 views.field.dblog_operations:
   type: views_field
   label: 'Operation link markup'
+
+views.filter.dblog_types:
+  type: 'views.filter.in_operator'
+  label: 'Types'
diff --git a/core/modules/dblog/dblog.install b/core/modules/dblog/dblog.install
index f226ed04d9c9..8da830b310e5 100644
--- a/core/modules/dblog/dblog.install
+++ b/core/modules/dblog/dblog.install
@@ -90,3 +90,69 @@ function dblog_schema() {
 
   return $schema;
 }
+
+/**
+ * Use standard plugin for wid and uid fields. Use dblog_types for type filter.
+ */
+function dblog_update_8400() {
+  $config_factory = \Drupal::configFactory();
+
+  foreach ($config_factory->listAll('views.view.') as $view_config_name) {
+    $view = $config_factory->getEditable($view_config_name);
+    if ($view->get('base_table') != 'watchdog') {
+      continue;
+    }
+
+    $save = FALSE;
+    foreach ($view->get('display') as $display_name => $display) {
+      // Iterate through all the fields of watchdog views based tables.
+      if (isset($display['display_options']['fields'])) {
+        foreach ($display['display_options']['fields'] as $field_name => $field) {
+          // We are only interested in wid and uid fields from the watchdog
+          // table that still use the numeric id.
+          if (isset($field['table']) &&
+              $field['table'] === 'watchdog' &&
+              $field['plugin_id'] == 'numeric' &&
+              in_array($field['field'], ['wid', 'uid'])) {
+
+            $save = TRUE;
+            $new_value = $field;
+            $new_value['plugin_id'] = 'standard';
+
+            // Delete all the attributes related to numeric fields.
+            unset(
+              $new_value['set_precision'],
+              $new_value['precision'],
+              $new_value['decimal'],
+              $new_value['separator'],
+              $new_value['format_plural'],
+              $new_value['format_plural_string'],
+              $new_value['prefix'],
+              $new_value['suffix']
+            );
+            $view->set("display.$display_name.display_options.fields.$field_name", $new_value);
+          }
+        }
+      }
+
+      // Iterate all filters looking for type filters to update.
+      if (isset($display['display_options']['filters'])) {
+        foreach ($display['display_options']['filters'] as $filter_name => $filter) {
+          if (isset($filter['table']) &&
+              $filter['table'] === 'watchdog' &&
+              $filter['plugin_id'] == 'in_operator' &&
+              $filter['field'] == 'type') {
+
+            $save = TRUE;
+            $filter['plugin_id'] = 'dblog_types';
+            $view->set("display.$display_name.display_options.filters.$filter_name", $filter);
+          }
+        }
+      }
+    }
+
+    if ($save) {
+      $view->save();
+    }
+  }
+}
diff --git a/core/modules/dblog/dblog.module b/core/modules/dblog/dblog.module
index ed92d6c8f2a9..f33f74902fba 100644
--- a/core/modules/dblog/dblog.module
+++ b/core/modules/dblog/dblog.module
@@ -12,6 +12,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\StringTranslation\TranslatableMarkup;
+use Drupal\views\ViewEntityInterface;
 
 /**
  * Implements hook_help().
@@ -115,3 +116,74 @@ function dblog_form_system_logging_settings_alter(&$form, FormStateInterface $fo
 function dblog_logging_settings_submit($form, FormStateInterface $form_state) {
   \Drupal::configFactory()->getEditable('dblog.settings')->set('row_limit', $form_state->getValue('dblog_row_limit'))->save();
 }
+
+/**
+ * Implements hook_ENTITY_TYPE_presave() for views entities.
+ *
+ * This hook ensures there are no views based that are using a wrong plugin for
+ * wid and uid fields on views that use watchdog as base table.
+ *
+ * @deprecated in Drupal 8.4.x and will be removed before 9.0.0.
+ *
+ * @see https://www.drupal.org/node/2876378
+ */
+function dblog_view_presave(ViewEntityInterface $view) {
+  // Only interested in watchdog based views.
+  if ($view->get('base_table') != 'watchdog') {
+    return;
+  }
+
+  $displays = $view->get('display');
+  $update = FALSE;
+  foreach ($displays as $display_name => $display) {
+
+    // Iterate through all the fields of watchdog views based tables.
+    if (isset($display['display_options']['fields'])) {
+      foreach ($display['display_options']['fields'] as $field_name => $field) {
+        // We are only interested in wid and uid fields from the watchdog table
+        // that still use the numeric id.
+        if (isset($field['table']) &&
+            $field['table'] === 'watchdog' &&
+            $field['plugin_id'] == 'numeric' &&
+            in_array($field['field'], ['wid', 'uid'], TRUE)) {
+
+          $displays[$display_name]['display_options']['fields'][$field_name]['plugin_id'] = 'standard';
+
+          // Delete all the attributes related to numeric fields.
+          unset(
+            $displays[$display_name]['display_options']['fields'][$field_name]['set_precision'],
+            $displays[$display_name]['display_options']['fields'][$field_name]['precision'],
+            $displays[$display_name]['display_options']['fields'][$field_name]['decimal'],
+            $displays[$display_name]['display_options']['fields'][$field_name]['separator'],
+            $displays[$display_name]['display_options']['fields'][$field_name]['format_plural'],
+            $displays[$display_name]['display_options']['fields'][$field_name]['format_plural_string'],
+            $displays[$display_name]['display_options']['fields'][$field_name]['prefix'],
+            $displays[$display_name]['display_options']['fields'][$field_name]['suffix']
+          );
+
+          $update = TRUE;
+          @trigger_error("The numeric plugin for watchdog.$field_name field is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Must use standard plugin instead. See https://www.drupal.org/node/2876378.", E_USER_DEPRECATED);
+        }
+      }
+    }
+
+    // Iterate all filters looking for type filters to update.
+    if (isset($display['display_options']['filters'])) {
+      foreach ($display['display_options']['filters'] as $filter_name => $filter) {
+        if (isset($filter['table']) &&
+            $filter['table'] === 'watchdog' &&
+            $filter['plugin_id'] == 'in_operator' &&
+            $filter['field'] == 'type') {
+
+          $displays[$display_name]['display_options']['filters'][$filter_name]['plugin_id'] = 'dblog_types';
+          $update = TRUE;
+          @trigger_error("The in_operator plugin for watchdog.type filter is deprecated in Drupal 8.4.0 and will be removed before Drupal 9.0.0. Must use dblog_types plugin instead. See https://www.drupal.org/node/2876378.", E_USER_DEPRECATED);
+        }
+      }
+    }
+  }
+
+  if ($update) {
+    $view->set('display', $displays);
+  }
+}
diff --git a/core/modules/dblog/dblog.views.inc b/core/modules/dblog/dblog.views.inc
index 20ad9ceb290c..6ad9e68ce417 100644
--- a/core/modules/dblog/dblog.views.inc
+++ b/core/modules/dblog/dblog.views.inc
@@ -24,7 +24,7 @@ function dblog_views_data() {
     'title' => t('WID'),
     'help' => t('Unique watchdog event ID.'),
     'field' => [
-      'id' => 'numeric',
+      'id' => 'standard',
     ],
     'filter' => [
       'id' => 'numeric',
@@ -39,9 +39,9 @@ function dblog_views_data() {
 
   $data['watchdog']['uid'] = [
     'title' => t('UID'),
-    'help' => t('The user ID of the user on which the log entry was written..'),
+    'help' => t('The user ID of the user on which the log entry was written.'),
     'field' => [
-      'id' => 'numeric',
+      'id' => 'standard',
     ],
     'filter' => [
       'id' => 'numeric',
@@ -52,7 +52,7 @@ function dblog_views_data() {
     'relationship' => [
       'title' => t('User'),
       'help' => t('The user on which the log entry as written.'),
-      'base' => 'users',
+      'base' => 'users_field_data',
       'base field' => 'uid',
       'id' => 'standard',
     ],
@@ -68,8 +68,7 @@ function dblog_views_data() {
       'id' => 'string',
     ],
     'filter' => [
-      'id' => 'in_operator',
-      'options callback' => '_dblog_get_message_types',
+      'id' => 'dblog_types',
     ],
     'sort' => [
       'id' => 'standard',
@@ -120,7 +119,7 @@ function dblog_views_data() {
     ],
     'filter' => [
       'id' => 'in_operator',
-      'options callback' => 'Drupal\dblog\Controller\DbLogController::getLogLevelClassMap',
+      'options callback' => 'Drupal\Core\Logger\RfcLogLevel::getLevels',
     ],
     'sort' => [
       'id' => 'standard',
diff --git a/core/modules/dblog/src/Plugin/views/filter/DblogTypes.php b/core/modules/dblog/src/Plugin/views/filter/DblogTypes.php
new file mode 100644
index 000000000000..23ea736ea9ee
--- /dev/null
+++ b/core/modules/dblog/src/Plugin/views/filter/DblogTypes.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Drupal\dblog\Plugin\views\filter;
+
+use Drupal\views\Plugin\views\filter\InOperator;
+
+/**
+ * Exposes log types to views module.
+ *
+ * @ViewsFilter("dblog_types")
+ */
+class DblogTypes extends InOperator {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getValueOptions() {
+    if (!isset($this->valueOptions)) {
+      $this->valueOptions = _dblog_get_message_types();
+    }
+    return $this->valueOptions;
+  }
+
+}
diff --git a/core/modules/dblog/src/Tests/Update/DblogFiltersAndFieldsUpgradeTest.php b/core/modules/dblog/src/Tests/Update/DblogFiltersAndFieldsUpgradeTest.php
new file mode 100644
index 000000000000..d988d71e9da2
--- /dev/null
+++ b/core/modules/dblog/src/Tests/Update/DblogFiltersAndFieldsUpgradeTest.php
@@ -0,0 +1,77 @@
+<?php
+
+namespace Drupal\dblog\Tests\Update;
+
+use Drupal\system\Tests\Update\UpdatePathTestBase;
+use Drupal\views\Views;
+use Drupal\Core\Serialization\Yaml;
+
+/**
+ * Tests the upgrade path for views field and filter handlers.
+ *
+ * @see dblog_update_8400()
+ *
+ * @group Update
+ */
+class DblogFiltersAndFieldsUpgradeTest extends UpdatePathTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setDatabaseDumpFiles() {
+    $this->databaseDumpFiles = [
+      __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz',
+      __DIR__ . '/../../../tests/fixtures/update/dblog-2851293.php',
+    ];
+  }
+
+  /**
+   * Tests that field and filter handlers are updated properly.
+   */
+  public function testDblogUpgradePath() {
+
+    $this->runUpdates();
+
+    $view = Views::getView('dblog_2851293');
+    $data = $view->storage->toArray();
+    $fields = $data['display']['default']['display_options']['fields'];
+
+    // The 'wid' and 'uid' fields should use the standard plugin now.
+    $this->assertEqual('standard', $fields['wid']['plugin_id']);
+    $this->assertEqual('standard', $fields['uid']['plugin_id']);
+
+    $filters = $data['display']['default']['display_options']['filters'];
+    // The 'type' filter should use the dblog_types plugin now.
+    $this->assertEqual('dblog_types', $filters['type']['plugin_id']);
+
+    // Now that the view had been converted, try the same approach but using
+    // dblog_view_presave()
+    $config_factory = \Drupal::configFactory();
+    $config_view = $config_factory->getEditable('views.view.dblog_2851293');
+    $config_view->setData(Yaml::decode(file_get_contents('core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.dblog_2851293.yml')));
+    $config_view->save();
+
+    // Make sure we have a not upgraded view.
+    $view = Views::getView('dblog_2851293');
+    $data = $view->storage->toArray();
+    $fields = $data['display']['default']['display_options']['fields'];
+    $filters = $data['display']['default']['display_options']['filters'];
+
+    $this->assertEqual('numeric', $fields['wid']['plugin_id']);
+    $this->assertEqual('numeric', $fields['uid']['plugin_id']);
+    $this->assertEqual('in_operator', $filters['type']['plugin_id']);
+
+    // Now save the view. This trigger dblog_view_presave().
+    $view->save();
+
+    // Finally check the same convertion proccess ran.
+    $data = $view->storage->toArray();
+    $fields = $data['display']['default']['display_options']['fields'];
+    $filters = $data['display']['default']['display_options']['filters'];
+
+    $this->assertEqual('standard', $fields['wid']['plugin_id']);
+    $this->assertEqual('standard', $fields['uid']['plugin_id']);
+    $this->assertEqual('dblog_types', $filters['type']['plugin_id']);
+  }
+
+}
diff --git a/core/modules/dblog/tests/fixtures/update/dblog-2851293.php b/core/modules/dblog/tests/fixtures/update/dblog-2851293.php
new file mode 100644
index 000000000000..0a2603174867
--- /dev/null
+++ b/core/modules/dblog/tests/fixtures/update/dblog-2851293.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * @file
+ * Test fixture.
+ */
+
+use Drupal\Core\Database\Database;
+use Drupal\Core\Serialization\Yaml;
+
+$connection = Database::getConnection();
+
+$connection->insert('config')
+  ->fields([
+    'collection' => '',
+    'name' => 'views.view.dblog_2851293',
+    'data' => serialize(Yaml::decode(file_get_contents('core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.dblog_2851293.yml'))),
+  ])
+  ->execute();
diff --git a/core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.dblog_2851293.yml b/core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.dblog_2851293.yml
new file mode 100644
index 000000000000..470a1f0251f4
--- /dev/null
+++ b/core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.dblog_2851293.yml
@@ -0,0 +1,148 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - user
+id: dblog_2851293
+label: dblog_2851293
+module: views
+description: 'Base view to test upgrade from issue #2851293'
+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: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      pager:
+        type: some
+        options:
+          items_per_page: 10
+          offset: 0
+      style:
+        type: default
+        options:
+          grouping: {  }
+          row_class: ''
+          default_row_class: true
+          uses_fields: false
+      row:
+        type: fields
+        options:
+          inline: {  }
+          separator: ''
+          hide_empty: false
+          default_field_elements: true
+      fields:
+        wid:
+          table: watchdog
+          field: wid
+          id: wid
+          entity_type: null
+          entity_field: null
+          plugin_id: numeric
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          set_precision: false
+          precision: 0
+          decimal: .
+          separator: ','
+          format_plural: false
+          format_plural_string: "1\x03@count"
+          prefix: ''
+          suffix: ''
+        uid:
+          id: uid
+          table: watchdog
+          field: uid
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: ''
+          exclude: false
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          set_precision: false
+          precision: 0
+          decimal: .
+          separator: ','
+          format_plural: false
+          format_plural_string: "1\x03@count"
+          prefix: ''
+          suffix: ''
+          plugin_id: numeric
+      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
+            reduce: false
+          plugin_id: in_operator
+      sorts: {  }
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships: {  }
+      arguments: {  }
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_interface'
+        - user.permissions
+      tags: {  }
diff --git a/core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.dblog_integration_test.yml b/core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.dblog_integration_test.yml
new file mode 100644
index 000000000000..5e701ab08134
--- /dev/null
+++ b/core/modules/dblog/tests/modules/dblog_test_views/test_views/views.view.dblog_integration_test.yml
@@ -0,0 +1,505 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - dblog
+    - user
+id: dblog_integration_test
+label: dblog_integration_test
+module: views
+description: ''
+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: tag
+        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: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      pager:
+        type: mini
+        options:
+          items_per_page: 10
+          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: default
+      row:
+        type: fields
+      fields:
+        wid:
+          table: watchdog
+          field: wid
+          id: wid
+          entity_type: null
+          entity_field: null
+          plugin_id: standard
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: ''
+          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
+        message:
+          id: message
+          table: watchdog
+          field: message
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: ''
+          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: false
+          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
+        link:
+          id: link
+          table: watchdog
+          field: link
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: ''
+          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: false
+          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
+        severity:
+          id: severity
+          table: watchdog
+          field: severity
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: ''
+          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: false
+          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: ''
+          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: false
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_empty: false
+          empty_zero: false
+          hide_alter_empty: true
+          plugin_id: standard
+        name:
+          id: name
+          table: users_field_data
+          field: name
+          relationship: uid
+          group_type: group
+          admin_label: ''
+          label: ''
+          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: false
+          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
+      filters:
+        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 level'
+            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
+        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
+      sorts: {  }
+      title: dblog_integration_test
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships:
+        uid:
+          id: uid
+          table: watchdog
+          field: uid
+          relationship: none
+          group_type: group
+          admin_label: uid
+          required: false
+          plugin_id: standard
+      arguments: {  }
+      display_extenders: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - user.permissions
+      tags: {  }
+  page_1:
+    display_plugin: page
+    id: page_1
+    display_title: Page
+    position: 1
+    display_options:
+      display_extenders: {  }
+      path: dblog-integration-test
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - url
+        - url.query_args
+        - user.permissions
+      tags: {  }
diff --git a/core/modules/dblog/tests/src/Kernel/Views/ViewsIntegrationTest.php b/core/modules/dblog/tests/src/Kernel/Views/ViewsIntegrationTest.php
index 7b63394d52b8..67d693fb8bb3 100644
--- a/core/modules/dblog/tests/src/Kernel/Views/ViewsIntegrationTest.php
+++ b/core/modules/dblog/tests/src/Kernel/Views/ViewsIntegrationTest.php
@@ -18,41 +18,161 @@
 class ViewsIntegrationTest extends ViewsKernelTestBase {
 
   /**
-   * Views used by this test.
-   *
-   * @var array
+   * {@inheritdoc}
    */
-  public static $testViews = ['test_dblog'];
+  public static $testViews = ['test_dblog', 'dblog_integration_test'];
 
   /**
-   * Modules to enable.
-   *
-   * @var array
+   * {@inheritdoc}
    */
   public static $modules = ['dblog', 'dblog_test_views', 'user'];
 
+  /**
+   * {@inheritdoc}
+   */
+  protected $columnMap = ['watchdog_message' => 'message'];
+
   /**
    * {@inheritdoc}
    */
   protected function setUp($import_test_views = TRUE) {
     parent::setUp();
 
-    // Rebuild the router, otherwise we can't generate links.
-    $this->container->get('router.builder')->rebuild();
-
+    $this->installEntitySchema('user');
     $this->installSchema('dblog', ['watchdog']);
 
     ViewTestData::createTestViews(get_class($this), ['dblog_test_views']);
   }
 
   /**
-   * Tests the integration.
+   * Tests the messages escaping functionality.
+   */
+  public function testMessages() {
+
+    // Remove the watchdog entries added by the potential batch process.
+    $this->container->get('database')->truncate('watchdog')->execute();
+
+    $entries = $this->createLogEntries();
+
+    $view = Views::getView('test_dblog');
+    $this->executeView($view);
+    $view->initStyle();
+
+    foreach ($entries as $index => $entry) {
+      if (!isset($entry['variables'])) {
+        continue;
+      }
+      $this->assertEqual($view->style_plugin->getField($index, 'message'), SafeMarkup::format($entry['message'], $entry['variables']));
+      $link_field = $view->style_plugin->getField($index, 'link');
+      // The 3rd entry contains some unsafe markup that needs to get filtered.
+      if ($index == 2) {
+        // Make sure that unsafe link differs from the rendered link, so we know
+        // that some filtering actually happened.
+        $this->assertNotEqual($link_field, $entry['variables']['link']);
+      }
+      $this->assertEqual($link_field, Xss::filterAdmin($entry['variables']['link']));
+    }
+
+    // Disable replacing variables and check that the tokens aren't replaced.
+    $view->destroy();
+    $view->storage->invalidateCaches();
+    $view->initHandlers();
+    $this->executeView($view);
+    $view->initStyle();
+    $view->field['message']->options['replace_variables'] = FALSE;
+    foreach ($entries as $index => $entry) {
+      $this->assertEqual($view->style_plugin->getField($index, 'message'), $entry['message']);
+    }
+  }
+
+  /**
+   * Tests the relationship with the users_field_data table.
    */
-  public function testIntegration() {
+  public function testRelationship() {
+    $view = Views::getView('dblog_integration_test');
+    $view->setDisplay('page_1');
+    // The uid relationship should now join to the {users_field_data} table.
+    $tables = array_keys($view->getBaseTables());
+    $this->assertTrue(in_array('users_field_data', $tables));
+    $this->assertFalse(in_array('users', $tables));
+    $this->assertTrue(in_array('watchdog', $tables));
+  }
 
+  /**
+   * Test views can be filtered by severity and log type.
+   */
+  public function testFiltering() {
     // Remove the watchdog entries added by the potential batch process.
     $this->container->get('database')->truncate('watchdog')->execute();
+    $this->createLogEntries();
+
+    $view = Views::getView('dblog_integration_test');
+
+    $filters = [
+      'severity' => [
+        'id' => 'severity',
+        'table' => 'watchdog',
+        'field' => 'severity',
+        'relationship' => 'none',
+        'group_type' => 'group',
+        'admin_label' => '',
+        'operator' => 'in',
+        'value' => [
+          RfcLogLevel::WARNING,
+        ],
+        'group' => 1,
+        'exposed' => FALSE,
+        'plugin_id' => 'in_operator',
+      ],
+    ];
+
+    $view->setDisplay('page_1');
+    $view->displayHandlers->get('page_1')->overrideOption('filters', $filters);
+    $view->save();
+
+    $this->executeView($view);
+
+    $resultset = [['message' => 'Warning message']];
+    $this->assertIdenticalResultset($view, $resultset, $this->columnMap);
+
+    $view = Views::getView('dblog_integration_test');
+
+    $filters = [
+      'type' => [
+        'id' => 'type',
+        'table' => 'watchdog',
+        'field' => 'type',
+        'relationship' => 'none',
+        'group_type' => 'group',
+        'admin_label' => '',
+        'operator' => 'in',
+        'value' => [
+          'my-module' => 'my-module',
+        ],
+        'group' => '1',
+        'exposed' => FALSE,
+        'is_grouped' => FALSE,
+        'plugin_id' => 'dblog_types',
+      ],
+    ];
+
+    $view->setDisplay('page_1');
+    $view->displayHandlers->get('page_1')->overrideOption('filters', $filters);
+    $view->save();
+
+    $this->executeView($view);
+
+    $resultset = [['message' => 'My module message']];
+    $this->assertIdenticalResultset($view, $resultset, $this->columnMap);
+  }
 
+  /**
+   * Create a set of log entries.
+   *
+   * @return array
+   *   An array of data used to create the log entries.
+   */
+  protected function createLogEntries() {
     $entries = [];
     // Setup a watchdog entry without tokens.
     $entries[] = [
@@ -76,41 +196,28 @@ public function testIntegration() {
         'link' => '<a href="' . \Drupal::url('<front>') . '"><object>Link</object></a>',
       ],
     ];
+    // Setup a watchdog entry with severity WARNING.
+    $entries[] = [
+      'message' => 'Warning message',
+      'severity' => RfcLogLevel::WARNING,
+    ];
+    // Setup a watchdog entry with a different module.
+    $entries[] = [
+      'message' => 'My module message',
+      'severity' => RfcLogLevel::INFO,
+      'type' => 'my-module',
+    ];
+
     $logger_factory = $this->container->get('logger.factory');
     foreach ($entries as $entry) {
       $entry += [
         'type' => 'test-views',
         'severity' => RfcLogLevel::NOTICE,
+        'variables' => [],
       ];
       $logger_factory->get($entry['type'])->log($entry['severity'], $entry['message'], $entry['variables']);
     }
-
-    $view = Views::getView('test_dblog');
-    $this->executeView($view);
-    $view->initStyle();
-
-    foreach ($entries as $index => $entry) {
-      $this->assertEqual($view->style_plugin->getField($index, 'message'), SafeMarkup::format($entry['message'], $entry['variables']));
-      $link_field = $view->style_plugin->getField($index, 'link');
-      // The 3rd entry contains some unsafe markup that needs to get filtered.
-      if ($index == 2) {
-        // Make sure that unsafe link differs from the rendered link, so we know
-        // that some filtering actually happened.
-        $this->assertNotEqual($link_field, $entry['variables']['link']);
-      }
-      $this->assertEqual($link_field, Xss::filterAdmin($entry['variables']['link']));
-    }
-
-    // Disable replacing variables and check that the tokens aren't replaced.
-    $view->destroy();
-    $view->storage->invalidateCaches();
-    $view->initHandlers();
-    $this->executeView($view);
-    $view->initStyle();
-    $view->field['message']->options['replace_variables'] = FALSE;
-    foreach ($entries as $index => $entry) {
-      $this->assertEqual($view->style_plugin->getField($index, 'message'), $entry['message']);
-    }
+    return $entries;
   }
 
 }
-- 
GitLab