From 7f90ee63ab5023792fb8f3753111a06d7ac2ef8e Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Thu, 9 Apr 2015 12:29:20 +0100
Subject: [PATCH] Issue #2456709 by dawehner, rteijeiro: File views handlers
 need to be replaced with entity-aware formatters

---
 .../file/config/optional/views.view.files.yml |  86 +++++++--
 .../file/config/schema/file.schema.yml        |  31 ++++
 .../file/config/schema/file.views.schema.yml  |   4 -
 core/modules/file/src/FileViewsData.php       |  20 +-
 .../BaseFieldFileFormatterBase.php            |  94 ++++++++++
 .../FieldFormatter/DefaultFileFormatter.php   |  51 ++++++
 .../FieldFormatter/FileExtensionFormatter.php |  80 ++++++++
 .../Plugin/Field/FieldFormatter/FileSize.php  |  47 +++++
 .../Field/FieldFormatter/FileUriFormatter.php |  70 +++++++
 .../FieldFormatter/FilemimeFormatter.php      |  76 ++++++++
 .../file/src/Plugin/views/field/Extension.php |  69 -------
 .../file/src/Plugin/views/field/FileMime.php  |  53 ------
 .../file/src/Plugin/views/field/Status.php    |  30 ---
 .../file/src/Plugin/views/field/Uri.php       |  47 -----
 .../file/src/Plugin/views/wizard/File.php     |   4 +-
 .../Formatter/FileEntityFormatterTest.php     | 173 ++++++++++++++++++
 .../Tests/Views/ExtensionViewsFieldTest.php   |  71 +++----
 .../Tests/Views/FileViewsFieldAccessTest.php  |  14 +-
 .../views.view.file_extension_view.yml        |  41 ++---
 19 files changed, 768 insertions(+), 293 deletions(-)
 create mode 100644 core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php
 create mode 100644 core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php
 create mode 100644 core/modules/file/src/Plugin/Field/FieldFormatter/FileExtensionFormatter.php
 create mode 100644 core/modules/file/src/Plugin/Field/FieldFormatter/FileSize.php
 create mode 100644 core/modules/file/src/Plugin/Field/FieldFormatter/FileUriFormatter.php
 create mode 100644 core/modules/file/src/Plugin/Field/FieldFormatter/FilemimeFormatter.php
 delete mode 100644 core/modules/file/src/Plugin/views/field/Extension.php
 delete mode 100644 core/modules/file/src/Plugin/views/field/FileMime.php
 delete mode 100644 core/modules/file/src/Plugin/views/field/Status.php
 delete mode 100644 core/modules/file/src/Plugin/views/field/Uri.php
 create mode 100644 core/modules/file/src/Tests/Formatter/FileEntityFormatterTest.php

diff --git a/core/modules/file/config/optional/views.view.files.yml b/core/modules/file/config/optional/views.view.files.yml
index 526d9fdd4257..23bfd821e54a 100644
--- a/core/modules/file/config/optional/views.view.files.yml
+++ b/core/modules/file/config/optional/views.view.files.yml
@@ -159,7 +159,6 @@ display:
             html: false
           hide_empty: false
           empty_zero: false
-          link_to_file: false
           relationship: none
           group_type: group
           admin_label: ''
@@ -175,30 +174,45 @@ display:
           element_default_classes: true
           empty: ''
           hide_alter_empty: true
-          plugin_id: file
+          plugin_id: field
           entity_type: file
           entity_field: fid
         filename:
           id: filename
           table: file_managed
           field: filename
+          relationship: none
+          group_type: group
+          admin_label: ''
+          label: Name
+          exclude: false
           alter:
             alter_text: false
+            text: ''
             make_link: false
+            path: ''
             absolute: false
-            trim: 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: false
             ellipsis: false
+            more_link: false
+            more_link_text: ''
+            more_link_path: ''
             strip_tags: false
+            trim: false
+            preserve_tags: ''
             html: false
-          hide_empty: false
-          empty_zero: false
-          link_to_file: true
-          relationship: none
-          group_type: group
-          admin_label: ''
-          label: Name
-          exclude: false
           element_type: ''
           element_class: ''
           element_label_type: ''
@@ -208,8 +222,22 @@ display:
           element_wrapper_class: ''
           element_default_classes: true
           empty: ''
+          hide_empty: false
+          empty_zero: false
           hide_alter_empty: true
-          plugin_id: file
+          click_sort_column: value
+          type: file_link
+          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: 0
+          plugin_id: field
           entity_type: file
           entity_field: filename
         filemime:
@@ -260,9 +288,8 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          link_to_file: false
-          filemime_image: false
-          plugin_id: file_filemime
+          type: file_filemime
+          plugin_id: field
           entity_type: file
           entity_field: filemime
         filesize:
@@ -313,8 +340,8 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          file_size_display: formatted
-          plugin_id: file_size
+          type: file_size
+          plugin_id: field
           entity_type: file
           entity_field: filesize
         status:
@@ -365,7 +392,12 @@ display:
           hide_empty: false
           empty_zero: false
           hide_alter_empty: true
-          plugin_id: file_status
+          type: boolean
+          settings:
+            format: custom
+            format_custom_false: 'Temporary'
+            format_custom_true: 'Permanent'
+          plugin_id: field
           entity_type: file
           entity_field: status
         created:
@@ -679,6 +711,12 @@ display:
       arguments: {  }
       group_by: true
       show_admin_links: true
+      display_extenders: {  }
+    cache_metadata:
+      contexts:
+        - languages
+        - url
+      cacheable: false
   page_1:
     display_plugin: page
     id: page_1
@@ -706,6 +744,12 @@ display:
           group_type: group
           admin_label: 'File usage'
           required: false
+      display_extenders: {  }
+    cache_metadata:
+      contexts:
+        - languages
+        - url
+      cacheable: false
   page_2:
     display_plugin: page
     id: page_2
@@ -1054,3 +1098,9 @@ display:
           group_type: group
           admin_label: 'File usage'
           required: true
+      display_extenders: {  }
+    cache_metadata:
+      contexts:
+        - languages
+        - url
+      cacheable: false
diff --git a/core/modules/file/config/schema/file.schema.yml b/core/modules/file/config/schema/file.schema.yml
index e5892e57d417..b9f8918f6331 100644
--- a/core/modules/file/config/schema/file.schema.yml
+++ b/core/modules/file/config/schema/file.schema.yml
@@ -90,3 +90,34 @@ field.widget.settings.file_generic:
     progress_indicator:
       type: string
       label: 'Progress indicator'
+
+field_formatter_settings_base_file:
+  type: mapping
+  mapping:
+    link_to_file:
+      type: boolean
+      label: 'Link to file'
+
+field.formatter.settings.file_link:
+  type: field_formatter_settings_base_file
+
+field.formatter.settings.file_uri:
+  type: field_formatter_settings_base_file
+  mapping:
+    file_download_path:
+      type: boolean
+      label: 'Display download path'
+
+field.formatter.settings.file_filemime:
+  type: field_formatter_settings_base_file
+  mapping:
+    filemime_image:
+      type: boolean
+      label: 'Display the filemime as icon'
+
+field.formatter.settings.file_extension:
+  type: field_formatter_settings_base_file
+  mapping:
+    extension_detect_tar:
+      type: boolean
+      label: 'Detect tar'
diff --git a/core/modules/file/config/schema/file.views.schema.yml b/core/modules/file/config/schema/file.views.schema.yml
index 2f63384037b9..e04b5d730974 100644
--- a/core/modules/file/config/schema/file.views.schema.yml
+++ b/core/modules/file/config/schema/file.views.schema.yml
@@ -29,10 +29,6 @@ views.field.file_filemime:
       type: boolean
       label: 'Display an icon representing the file type, instead of the MIME text (such as "image/jpeg")'
 
-views.field.file_status:
-  type: views_field
-  label: 'File status'
-
 views.field.file_uri:
   type: views.field.file
   label: 'File URI'
diff --git a/core/modules/file/src/FileViewsData.php b/core/modules/file/src/FileViewsData.php
index fdd8fc62b9bb..7acbabc5d163 100644
--- a/core/modules/file/src/FileViewsData.php
+++ b/core/modules/file/src/FileViewsData.php
@@ -25,7 +25,6 @@ public function getViewsData() {
     $data['file_managed']['table']['base']['defaults']['field'] = 'filename';
     $data['file_managed']['table']['wizard_id'] = 'file_managed';
 
-    $data['file_managed']['fid']['field']['id'] ='file';
     $data['file_managed']['fid']['argument'] = array(
       'id' => 'file_fid',
       // The field to display in the summary.
@@ -42,25 +41,30 @@ public function getViewsData() {
       'label' => t('File usage'),
     );
 
-    $data['file_managed']['filename']['field']['id'] = 'file';
+    $data['file_managed']['uri']['field']['default_formatter'] = 'file_uri';
 
-    $data['file_managed']['uri']['field']['id'] = 'file_uri';
-
-    $data['file_managed']['filemime']['field']['id'] = 'file_filemime';
+    $data['file_managed']['filemime']['field']['default_formatter'] = 'file_filemime';
 
     $data['file_managed']['extension'] = array(
       'title' => t('Extension'),
       'help' => t('The extension of the file.'),
       'real field' => 'filename',
       'field' => array(
-        'id' => 'file_extension',
+        'entity_type' => 'file',
+        'field_name' => 'filename',
+        'default_formatter' => 'file_extension',
+        'id' => 'field',
         'click sortable' => FALSE,
        ),
     );
 
-    $data['file_managed']['filesize']['field']['id'] = 'file_size';
+    $data['file_managed']['filesize']['field']['default_formatter'] = 'file_size';
 
-    $data['file_managed']['status']['field']['id'] = 'file_status';
+    $data['file_managed']['status']['field']['default_formatter_settings'] = [
+      'format' => 'custom',
+      'format_custom_false' => $this->t('Temporary'),
+      'format_custom_true' => t('Permanent'),
+    ];
     $data['file_managed']['status']['filter']['id'] = 'file_status';
 
     $data['file_managed']['uid']['relationship']['title'] = t('User who uploaded');
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php b/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php
new file mode 100644
index 000000000000..865471200a9e
--- /dev/null
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\file\Plugin\Field\FieldFormatter\BaseFieldFileFormatterBase.
+ */
+
+namespace Drupal\file\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemInterface;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\FormatterBase;
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
+
+/**
+ * Base class for file formatters, which allow to link to the file download URL.
+ */
+abstract class BaseFieldFileFormatterBase extends FormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    $settings['link_to_file'] = FALSE;
+
+    return $settings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $form = parent::settingsForm($form, $form_state);
+
+    $form['link_to_file'] = [
+      '#title' => $this->t('Link this field to the file download URL'),
+      '#type' => 'checkbox',
+      '#default_value' => $this->getSetting('link_to_file'),
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items) {
+    $elements = [];
+
+    $url = NULL;
+    // Add support to link to the entity itself.
+    if ($this->getSetting('link_to_file')) {
+      $url = file_create_url($items->getEntity()->uri->value);
+    }
+
+    foreach ($items as $delta => $item) {
+      $string = $this->viewValue($item);
+
+      if ($url) {
+        $elements[$delta] = [
+          '#type' => 'link',
+          '#title' => $string,
+          '#url' => Url::fromUri($url),
+        ];
+      }
+      else {
+        $elements[$delta] = is_array($string) ? $string : ['#markup' => $string];
+      }
+    }
+
+    return $elements;
+  }
+
+  /**
+   * Generate the output appropriate for one field item.
+   *
+   * @param \Drupal\Core\Field\FieldItemInterface $item
+   *   One field item.
+   *
+   * @return mixed
+   *   The textual output generated.
+   */
+  abstract protected function viewValue(FieldItemInterface $item);
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function isApplicable(FieldDefinitionInterface $field_definition) {
+    return $field_definition->getTargetEntityTypeId() === 'file';
+  }
+
+}
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php
new file mode 100644
index 000000000000..18375aa329cb
--- /dev/null
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\file\Plugin\Field\FieldFormatter\DefaultFileFormatter.
+ */
+
+namespace Drupal\file\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FieldItemInterface;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Formatter for a text field on a file entity that links the field to the file.
+ *
+ * @FieldFormatter(
+ *   id = "file_link",
+ *   label = @Translation("File link"),
+ *   field_types = {
+ *     "string"
+ *   }
+ * )
+ */
+class DefaultFileFormatter extends BaseFieldFileFormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    $settings = parent::defaultSettings();
+    $settings['link_to_file'] = TRUE;
+
+    return $settings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    // We don't call the parent in order to bypass the link to file form.
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function viewValue(FieldItemInterface $item) {
+    return $item->value;
+  }
+
+}
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/FileExtensionFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/FileExtensionFormatter.php
new file mode 100644
index 000000000000..626582e114ea
--- /dev/null
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileExtensionFormatter.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\file\Plugin\Field\FieldFormatter\FileExtensionFormatter.
+ */
+
+namespace Drupal\file\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemInterface;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Formatter to render a filename as file extension.
+ *
+ * @FieldFormatter(
+ *   id = "file_extension",
+ *   label = @Translation("File extension"),
+ *   field_types = {
+ *     "string"
+ *   }
+ * )
+ */
+class FileExtensionFormatter extends BaseFieldFileFormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    $settings = parent::defaultSettings();
+
+    $settings['extension_detect_tar'] = FALSE;
+    return $settings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $form = parent::settingsForm($form, $form_state);
+    $form['extension_detect_tar'] = array(
+      '#type' => 'checkbox',
+      '#title' => $this->t('Include tar in extension'),
+      '#description' => $this->t("If the part of the filename just before the extension is '.tar', include this in the extension output."),
+      '#default_value' => $this->getSetting('extension_detect_tar'),
+    );
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function viewValue(FieldItemInterface $item) {
+    $filename = $item->value;
+    if (!$this->getSetting('extension_detect_tar')) {
+      return pathinfo($filename, PATHINFO_EXTENSION);
+    }
+    else {
+      $file_parts = explode('.', basename($filename));
+      if (count($file_parts) > 1) {
+        $extension = array_pop($file_parts);
+        $last_part_in_name = array_pop($file_parts);
+        if ($last_part_in_name === 'tar') {
+          $extension = 'tar.' . $extension;
+        }
+        return $extension;
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function isApplicable(FieldDefinitionInterface $field_definition) {
+    // Just show this file extension formatter on the filename field.
+    return parent::isApplicable($field_definition) && $field_definition->getName() === 'filename';
+  }
+
+}
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/FileSize.php b/core/modules/file/src/Plugin/Field/FieldFormatter/FileSize.php
new file mode 100644
index 000000000000..27973da720a9
--- /dev/null
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileSize.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\file\Plugin\Field\FieldFormatter\FileSize.
+ */
+
+namespace Drupal\file\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\FormatterBase;
+
+/**
+ * Formatter that shows the file size in a human readable way.
+ *
+ * @FieldFormatter(
+ *   id = "file_size",
+ *   label = @Translation("File size"),
+ *   field_types = {
+ *     "integer"
+ *   }
+ * )
+ */
+class FileSize extends FormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function isApplicable(FieldDefinitionInterface $field_definition) {
+    return parent::isApplicable($field_definition) && $field_definition->getName() === 'filesize';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items) {
+    $elements = [];
+
+    foreach ($items as $delta => $item) {
+      $elements[$delta] = ['#markup' => format_size($item->value)];
+    }
+
+    return $elements;
+  }
+
+}
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/FileUriFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/FileUriFormatter.php
new file mode 100644
index 000000000000..0a2a855bcdfa
--- /dev/null
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileUriFormatter.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\file\Plugin\Field\FieldFormatter\FileUriFormatter.
+ */
+
+namespace Drupal\file\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemInterface;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Formatter to render the file URI to its download path.
+ *
+ * @FieldFormatter(
+ *   id = "file_uri",
+ *   label = @Translation("File URI"),
+ *   field_types = {
+ *     "uri"
+ *   }
+ * )
+ */
+class FileUriFormatter extends BaseFieldFileFormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    $settings = parent::defaultSettings();
+
+    $settings['file_download_path'] = FALSE;
+    return $settings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $form = parent::settingsForm($form, $form_state);
+
+    $form['file_download_path'] = [
+      '#title' => $this->t('Display the file download URI'),
+      '#type' => 'checkbox',
+      '#default_value' => $this->getSetting('file_download_path'),
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function viewValue(FieldItemInterface $item) {
+    $value = $item->value;
+    if ($this->getSetting('file_download_path')) {
+      $value = file_create_url($value);
+    }
+    return $value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function isApplicable(FieldDefinitionInterface $field_definition) {
+    return parent::isApplicable($field_definition) && $field_definition->getName() === 'uri';
+  }
+
+}
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/FilemimeFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/FilemimeFormatter.php
new file mode 100644
index 000000000000..5e2925117570
--- /dev/null
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FilemimeFormatter.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\file\Plugin\Field\FieldFormatter\FilemimeFormatter.
+ */
+
+namespace Drupal\file\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Field\FieldItemInterface;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Formatter to render the file mime type, with an optional icon.
+ *
+ * @FieldFormatter(
+ *   id = "file_filemime",
+ *   label = @Translation("File mime"),
+ *   field_types = {
+ *     "string"
+ *   }
+ * )
+ */
+class FilemimeFormatter extends BaseFieldFileFormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function isApplicable(FieldDefinitionInterface $field_definition) {
+    return parent::isApplicable($field_definition) && $field_definition->getName() === 'filemime';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    $settings = parent::defaultSettings();
+
+    $settings['filemime_image'] = FALSE;
+
+    return $settings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, FormStateInterface $form_state) {
+    $form = parent::settingsForm($form, $form_state);
+
+    $form['filemime_image'] = array(
+      '#title' => $this->t('Display an icon'),
+      '#description' => $this->t('The icon is representing the file type, instead of the MIME text (such as "image/jpeg")'),
+      '#type' => 'checkbox',
+      '#default_value' => $this->getSetting('filemime_image'),
+    );
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function viewValue(FieldItemInterface $item) {
+    $value = $item->value;
+    if ($this->getSetting('filemime_image') && $value) {
+      $file_icon = [
+        '#theme' => 'image__file_icon',
+        '#file' => $item->getEntity(),
+      ];
+      return $file_icon;
+    }
+    return $value;
+  }
+
+}
diff --git a/core/modules/file/src/Plugin/views/field/Extension.php b/core/modules/file/src/Plugin/views/field/Extension.php
deleted file mode 100644
index 1b0bd738bdd2..000000000000
--- a/core/modules/file/src/Plugin/views/field/Extension.php
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of views_handler_field_file_extension.
- */
-
-namespace Drupal\file\Plugin\views\field;
-
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\views\Plugin\views\field\FieldPluginBase;
-use Drupal\views\ResultRow;
-
-/**
- * Returns a pure file extension of the file, for example 'module'.
- *
- * @ingroup views_field_handlers
- *
- * @ViewsField("file_extension")
- */
-class Extension extends FieldPluginBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function defineOptions() {
-    $options = parent::defineOptions();
-    $options['extension_detect_tar'] = array('default' => FALSE);
-    return $options;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
-    parent::buildOptionsForm($form, $form_state);
-    $form['extension_detect_tar'] = array(
-      '#type' => 'checkbox',
-      '#title' => $this->t('Detect if tar is part of the extension'),
-      '#description' => $this->t("See if the previous extension is '.tar' and if so, add that, so we see 'tar.gz' or 'tar.bz2' instead of just 'gz'."),
-      '#default_value' => $this->options['extension_detect_tar'],
-    );
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function render(ResultRow $values) {
-    $value = $this->getValue($values);
-    if (!$this->options['extension_detect_tar']) {
-      if (preg_match('/\.([^\.]+)$/', $value, $match)) {
-        return $this->sanitizeValue($match[1]);
-      }
-    }
-    else {
-      $file_parts = explode('.', basename($value));
-      // If there is an extension.
-      if (count($file_parts) > 1) {
-        $extension = array_pop($file_parts);
-        $last_part_in_name = array_pop($file_parts);
-        if ($last_part_in_name === 'tar') {
-          $extension = 'tar.' . $extension;
-        }
-        return $this->sanitizeValue($extension);
-      }
-    }
-  }
-
-}
diff --git a/core/modules/file/src/Plugin/views/field/FileMime.php b/core/modules/file/src/Plugin/views/field/FileMime.php
deleted file mode 100644
index 4652f177dbb4..000000000000
--- a/core/modules/file/src/Plugin/views/field/FileMime.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\file\Plugin\views\field\FileMime.
- */
-
-namespace Drupal\file\Plugin\views\field;
-
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\views\ResultRow;
-
-/**
- * Field handler to add rendering MIME type images as an option on the filemime field.
- *
- * @ingroup views_field_handlers
- *
- * @ViewsField("file_filemime")
- */
-class FileMime extends File {
-
-  protected function defineOptions() {
-    $options = parent::defineOptions();
-    $options['filemime_image'] = array('default' => FALSE);
-    return $options;
-  }
-
-  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
-    $form['filemime_image'] = array(
-      '#title' => $this->t('Display an icon representing the file type, instead of the MIME text (such as "image/jpeg")'),
-      '#type' => 'checkbox',
-      '#default_value' => !empty($this->options['filemime_image']),
-    );
-    parent::buildOptionsForm($form, $form_state);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function render(ResultRow $values) {
-    $data = $values->{$this->field_alias};
-    if (!empty($this->options['filemime_image']) && $data !== NULL && $data !== '') {
-      $file_icon = array(
-        '#theme' => 'image__file_icon',
-        '#file' => $values->_entity,
-      );
-      $data = drupal_render($file_icon);
-    }
-
-    return $this->renderLink($data, $values);
-  }
-
-}
diff --git a/core/modules/file/src/Plugin/views/field/Status.php b/core/modules/file/src/Plugin/views/field/Status.php
deleted file mode 100644
index a18209982821..000000000000
--- a/core/modules/file/src/Plugin/views/field/Status.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\file\Plugin\views\field\Status.
- */
-
-namespace Drupal\file\Plugin\views\field;
-
-use Drupal\views\Plugin\views\field\FieldPluginBase;
-use Drupal\views\ResultRow;
-
-/**
- * Field handler to translate a node type into its readable form.
- *
- * @ingroup views_field_handlers
- *
- * @ViewsField("file_status")
- */
-class Status extends FieldPluginBase {
-
-  /**
-   * {@inheritdoc}
-   */
-  public function render(ResultRow $values) {
-    $value = $this->getValue($values);
-    return _views_file_status($value);
-  }
-
-}
diff --git a/core/modules/file/src/Plugin/views/field/Uri.php b/core/modules/file/src/Plugin/views/field/Uri.php
deleted file mode 100644
index 1df8c25a40a1..000000000000
--- a/core/modules/file/src/Plugin/views/field/Uri.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\file\Plugin\views\field\Uri.
- */
-
-namespace Drupal\file\Plugin\views\field;
-
-use Drupal\Core\Form\FormStateInterface;
-use Drupal\views\ResultRow;
-
-/**
- * Field handler to add rendering file paths as file URLs instead of as internal file URIs.
- *
- * @ViewsField("file_uri")
- */
-class Uri extends File {
-
-  protected function defineOptions() {
-    $options = parent::defineOptions();
-    $options['file_download_path'] = array('default' => FALSE);
-    return $options;
-  }
-
-  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
-    $form['file_download_path'] = array(
-      '#title' => $this->t('Display download path instead of file storage URI'),
-      '#description' => $this->t('This will provide the full download URL rather than the internal filestream address.'),
-      '#type' => 'checkbox',
-      '#default_value' => !empty($this->options['file_download_path']),
-    );
-    parent::buildOptionsForm($form, $form_state);
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function render(ResultRow $values) {
-    $data = $values->{$this->field_alias};
-    if (!empty($this->options['file_download_path']) && $data !== NULL && $data !== '') {
-      $data = file_create_url($data);
-    }
-    return $this->renderLink($data, $values);
-  }
-
-}
diff --git a/core/modules/file/src/Plugin/views/wizard/File.php b/core/modules/file/src/Plugin/views/wizard/File.php
index 36f57ac15c96..5b64f8445319 100644
--- a/core/modules/file/src/Plugin/views/wizard/File.php
+++ b/core/modules/file/src/Plugin/views/wizard/File.php
@@ -54,8 +54,8 @@ protected function defaultDisplayOptions() {
     $display_options['fields']['filename']['alter']['html'] = 0;
     $display_options['fields']['filename']['hide_empty'] = 0;
     $display_options['fields']['filename']['empty_zero'] = 0;
-    $display_options['fields']['filename']['link_to_file'] = 1;
-    $display_options['fields']['filename']['plugin_id'] = 'file';
+    $display_options['fields']['filename']['plugin_id'] = 'field';
+    $display_options['fields']['filename']['type'] = 'file_link';
 
     return $display_options;
   }
diff --git a/core/modules/file/src/Tests/Formatter/FileEntityFormatterTest.php b/core/modules/file/src/Tests/Formatter/FileEntityFormatterTest.php
new file mode 100644
index 000000000000..1c9a275f77fe
--- /dev/null
+++ b/core/modules/file/src/Tests/Formatter/FileEntityFormatterTest.php
@@ -0,0 +1,173 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\file\Tests\Formatter\FileEntityFormatterTest.
+ */
+
+namespace Drupal\file\Tests\Formatter;
+
+use Drupal\Core\Entity\Entity\EntityViewDisplay;
+use Drupal\Core\Url;
+use Drupal\file\Entity\File;
+use Drupal\simpletest\KernelTestBase;
+
+/**
+ * Tests the default file formatter.
+ *
+ * @group field
+ */
+class FileEntityFormatterTest extends KernelTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = ['file', 'user'];
+
+  /**
+   * The files.
+   *
+   * @var array
+   */
+  protected $files;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installEntitySchema('file');
+
+    $this->files = [];
+    file_put_contents('public://file.png', str_repeat('t', 10));
+    $file = File::create([
+      'uri' => 'public://file.png',
+      'filename' => 'file.png',
+    ]);
+    $file->save();
+    $this->files[] = $file;
+
+    file_put_contents('public://file.tar', str_repeat('t', 200));
+    $file = File::create([
+      'uri' => 'public://file.tar',
+      'filename' => 'file.tar',
+    ]);
+    $file->save();
+    $this->files[] = $file;
+
+    file_put_contents('public://file.tar.gz', str_repeat('t', 40000));
+    $file = File::create([
+      'uri' => 'public://file.tar.gz',
+      'filename' => 'file.tar.gz',
+    ]);
+    $file->save();
+    $this->files[] = $file;
+
+    file_put_contents('public://file', str_repeat('t', 8000000));
+    $file = File::create([
+      'uri' => 'public://file',
+      'filename' => 'file',
+    ]);
+    $file->save();
+    $this->files[] = $file;
+  }
+
+  /**
+   * Tests the file_link field formatter.
+   */
+  public function testFormatterFileLink() {
+    $entity_display = EntityViewDisplay::create([
+      'targetEntityType' => 'file',
+      'bundle' => 'file',
+    ]);
+    $entity_display->setComponent('filename', ['type' => 'file_link']);
+
+    $build = $entity_display->buildMultiple($this->files)[0]['filename'][0];
+    $this->assertEqual('file.png', $build['#title']);
+    $this->assertEqual(Url::fromUri(file_create_url('public://file.png')), $build['#url']);
+  }
+
+  /**
+   * Tests the file_link field formatter.
+   */
+  public function testFormatterFileUri() {
+    $entity_display = EntityViewDisplay::create([
+      'targetEntityType' => 'file',
+      'bundle' => 'file',
+    ]);
+    $entity_display->setComponent('uri', ['type' => 'file_uri']);
+
+    $build = $entity_display->buildMultiple($this->files)[0]['uri'][0];
+    $this->assertEqual('public://file.png', $build['#markup']);
+
+    $entity_display->setComponent('uri', ['type' => 'file_uri', 'settings' => ['file_download_path' => TRUE]]);
+    $build = $entity_display->buildMultiple($this->files)[0]['uri'][0];
+    $this->assertEqual(file_create_url('public://file.png'), $build['#markup']);
+
+    $entity_display->setComponent('uri', ['type' => 'file_uri', 'settings' => ['file_download_path' => TRUE, 'link_to_file' => TRUE]]);
+    $build = $entity_display->buildMultiple($this->files)[0]['uri'][0];
+    $this->assertEqual(file_create_url('public://file.png'), $build['#title']);
+    $this->assertEqual(Url::fromUri(file_create_url('public://file.png')), $build['#url']);
+  }
+
+  /**
+   * Tests the file_extension field formatter.
+   */
+  public function testFormatterFileExtension() {
+    $entity_display = EntityViewDisplay::create([
+      'targetEntityType' => 'file',
+      'bundle' => 'file',
+    ]);
+    $entity_display->setComponent('filename', ['type' => 'file_extension']);
+
+    $expected = ['png', 'tar', 'gz', ''];
+    foreach (array_values($this->files) as $i => $file) {
+      $build = $entity_display->build($file);
+      $this->assertEqual($expected[$i], $build['filename'][0]['#markup']);
+    }
+
+    $entity_display->setComponent('filename', ['type' => 'file_extension', 'settings' => ['extension_detect_tar' => TRUE]]);
+
+    $expected = ['png', 'tar', 'tar.gz', ''];
+    foreach (array_values($this->files) as $i => $file) {
+      $build = $entity_display->build($file);
+      $this->assertEqual($expected[$i], $build['filename'][0]['#markup']);
+    }
+  }
+
+  /**
+   * Tests the file_extension field formatter.
+   */
+  public function testFormatterFileMime() {
+    $entity_display = EntityViewDisplay::create([
+      'targetEntityType' => 'file',
+      'bundle' => 'file',
+    ]);
+    $entity_display->setComponent('filemime', ['type' => 'file_filemime', 'settings' => ['filemime_image' => TRUE]]);
+
+    foreach (array_values($this->files) as $i => $file) {
+      $build = $entity_display->build($file);
+      $this->assertEqual('image__file_icon', $build['filemime'][0]['#theme']);
+      $this->assertEqual(spl_object_hash($file), spl_object_hash($build['filemime'][0]['#file']));
+    }
+  }
+
+  /**
+   * Tests the file_size field formatter.
+   */
+  public function testFormatterFileSize() {
+    $entity_display = EntityViewDisplay::create([
+      'targetEntityType' => 'file',
+      'bundle' => 'file',
+    ]);
+    $entity_display->setComponent('filesize', ['type' => 'file_size']);
+
+    $expected = ['10 bytes', '200 bytes', '39.06 KB', '7.63 MB'];
+    foreach (array_values($this->files) as $i => $file) {
+      $build = $entity_display->build($file);
+      $this->assertEqual($expected[$i], $build['filesize'][0]['#markup']);
+    }
+  }
+
+}
diff --git a/core/modules/file/src/Tests/Views/ExtensionViewsFieldTest.php b/core/modules/file/src/Tests/Views/ExtensionViewsFieldTest.php
index 7a01bc7d931e..75623f4e5a6d 100644
--- a/core/modules/file/src/Tests/Views/ExtensionViewsFieldTest.php
+++ b/core/modules/file/src/Tests/Views/ExtensionViewsFieldTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\file\Tests\Views;
 
+use Drupal\file\Entity\File;
 use Drupal\views\Views;
 use Drupal\views\Tests\ViewUnitTestBase;
 use Drupal\views\Tests\ViewTestData;
@@ -36,30 +37,32 @@ class ExtensionViewsFieldTest extends ViewUnitTestBase {
   protected function setUp() {
     parent::setUp();
     ViewTestData::createTestViews(get_class($this), array('file_test_views'));
-  }
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function dataSet() {
-    $data = parent::dataSet();
-    $data[0]['name'] = 'file.png';
-    $data[1]['name'] = 'file.tar';
-    $data[2]['name'] = 'file.tar.gz';
-    $data[3]['name'] = 'file';
-
-    return $data;
-  }
+    $this->installEntitySchema('file');
 
-  /**
-   * {@inheritdoc}
-   */
-  protected function viewsData() {
-    $data = parent::viewsData();
-    $data['views_test_data']['name']['field']['id'] = 'file_extension';
-    $data['views_test_data']['name']['real field'] = 'name';
+    file_put_contents('public://file.png', '');
+    File::create([
+      'uri' => 'public://file.png',
+      'filename' => 'file.png',
+    ])->save();
+
+    file_put_contents('public://file.tar', '');
+    File::create([
+      'uri' => 'public://file.tar',
+      'filename' => 'file.tar',
+    ])->save();
 
-    return $data;
+    file_put_contents('public://file.tar.gz', '');
+    File::create([
+      'uri' => 'public://file.tar.gz',
+      'filename' => 'file.tar.gz',
+    ])->save();
+
+    file_put_contents('public://file', '');
+    File::create([
+      'uri' => 'public://file',
+      'filename' => 'file',
+    ])->save();
   }
 
   /**
@@ -68,20 +71,26 @@ protected function viewsData() {
   public function testFileExtensionTarOption() {
     $view = Views::getView('file_extension_view');
     $view->setDisplay();
-
     $this->executeView($view);
 
     // Test without the tar option.
-    $this->assertEqual($view->field['name']->advancedRender($view->result[0]), 'png');
-    $this->assertEqual($view->field['name']->advancedRender($view->result[1]), 'tar');
-    $this->assertEqual($view->field['name']->advancedRender($view->result[2]), 'gz');
-    $this->assertEqual($view->field['name']->advancedRender($view->result[3]), '');
+    $this->assertEqual($view->field['extension']->advancedRender($view->result[0]), 'png');
+    $this->assertEqual($view->field['extension']->advancedRender($view->result[1]), 'tar');
+    $this->assertEqual($view->field['extension']->advancedRender($view->result[2]), 'gz');
+    $this->assertEqual($view->field['extension']->advancedRender($view->result[3]), '');
     // Test with the tar option.
-    $view->field['name']->options['extension_detect_tar'] = TRUE;
-    $this->assertEqual($view->field['name']->advancedRender($view->result[0]), 'png');
-    $this->assertEqual($view->field['name']->advancedRender($view->result[1]), 'tar');
-    $this->assertEqual($view->field['name']->advancedRender($view->result[2]), 'tar.gz');
-    $this->assertEqual($view->field['name']->advancedRender($view->result[3]), '');
+
+    $view = Views::getView('file_extension_view');
+    $view->setDisplay();
+    $view->initHandlers();
+
+    $view->field['extension']->options['settings']['extension_detect_tar'] = TRUE;
+    $this->executeView($view);
+
+    $this->assertEqual($view->field['extension']->advancedRender($view->result[0]), 'png');
+    $this->assertEqual($view->field['extension']->advancedRender($view->result[1]), 'tar');
+    $this->assertEqual($view->field['extension']->advancedRender($view->result[2]), 'tar.gz');
+    $this->assertEqual($view->field['extension']->advancedRender($view->result[3]), '');
   }
 
 }
diff --git a/core/modules/file/src/Tests/Views/FileViewsFieldAccessTest.php b/core/modules/file/src/Tests/Views/FileViewsFieldAccessTest.php
index b448e0e2868f..74baac34e7f5 100644
--- a/core/modules/file/src/Tests/Views/FileViewsFieldAccessTest.php
+++ b/core/modules/file/src/Tests/Views/FileViewsFieldAccessTest.php
@@ -9,8 +9,6 @@
 
 use Drupal\file\Entity\File;
 use Drupal\language\Entity\ConfigurableLanguage;
-use Drupal\node\Entity\Node;
-use Drupal\node\Entity\NodeType;
 use Drupal\user\Entity\User;
 use Drupal\views\Tests\Handler\FieldFieldAccessTestBase;
 
@@ -61,15 +59,15 @@ public function testFileFields() {
 
     // @todo Expand the test coverage in https://www.drupal.org/node/2464635
 
-    // $this->assertFieldAccess('file', 'fid', $file->id());
+    $this->assertFieldAccess('file', 'fid', $file->id());
     // $this->assertFieldAccess('file', 'uuid', $file->uuid());
     $this->assertFieldAccess('file', 'langcode', $file->language()->getName());
     $this->assertFieldAccess('file', 'uid', 'test user');
-    // $this->assertFieldAccess('file', 'filename', $file->getFilename());
-    // $this->assertFieldAccess('file', 'uri', $file->getFileUri());
-    // $this->assertFieldAccess('file', 'filemime', $file->filemime->value);
-    // $this->assertFieldAccess('file', 'size', '4 Bytes');
-    // $this->assertFieldAccess('file', 'status', 'On');
+    $this->assertFieldAccess('file', 'filename', $file->getFilename());
+    $this->assertFieldAccess('file', 'uri', $file->getFileUri());
+    $this->assertFieldAccess('file', 'filemime', $file->filemime->value);
+    $this->assertFieldAccess('file', 'filesize', '4 bytes');
+    $this->assertFieldAccess('file', 'status', t('Permanent'));
     // $this->assertFieldAccess('file', 'created', \Drupal::service('date.formatter')->format(123456));
     // $this->assertFieldAccess('file', 'changed', \Drupal::service('date.formatter')->format(REQUEST_TIME));
   }
diff --git a/core/modules/file/tests/modules/file_test_views/test_views/views.view.file_extension_view.yml b/core/modules/file/tests/modules/file_test_views/test_views/views.view.file_extension_view.yml
index a8351f71bcdb..f870fb3df84d 100644
--- a/core/modules/file/tests/modules/file_test_views/test_views/views.view.file_extension_view.yml
+++ b/core/modules/file/tests/modules/file_test_views/test_views/views.view.file_extension_view.yml
@@ -6,8 +6,8 @@ label: 'Test view for file extension views field handler'
 module: views
 description: ''
 tag: ''
-base_table: views_test_data
-base_field: nid
+base_table: file_managed
+base_field: fid
 core: '8'
 display:
   default:
@@ -17,36 +17,31 @@ display:
         pager: false
         sorts: false
       fields:
-        age:
-          field: age
-          id: age
+        fid:
+          field: fid
+          id: fid
           relationship: none
-          table: views_test_data
-          plugin_id: numeric
-        id:
-          field: id
-          id: id
+          table: file_managed
+          plugin_id: field
+        extension:
+          field: extension
+          id: extension
           relationship: none
-          table: views_test_data
-          plugin_id: numeric
-        name:
-          field: name
-          id: file_extension
-          relationship: none
-          table: views_test_data
-          plugin_id: string
+          table: file_managed
+          plugin_id: field
+          type: file_extension
       pager:
         options:
           offset: 0
         type: none
       sorts:
-        id:
-          field: id
-          id: id
+        fid:
+          field: fid
+          id: fid
           order: ASC
           relationship: none
-          table: views_test_data
-          plugin_id: numeric
+          table: file_managed
+          plugin_id: standard
     display_plugin: default
     display_title: Master
     id: default
-- 
GitLab