Problem/Motivation

On #2393339: [META] Make sure Views base fields are using Field API for formatting, and do not lose functionality, we are updating all base entity fields in entity views data so that they are using Field API for formatting rather than using generic Views handlers.

This issue is about various custom handlers from the File module:
- 'file', used in file_managed.fid, file_managed.filename
- 'file_uri', used in file_managed.uri
- 'file_filemime', used in file_managed.filemime
- 'file_extension', used in file_managed.extension
- 'file_size', used in file_managed.filesize
- 'file_status', used in file_managed.status

Proposed resolution

Change these fields to use the Field API formatter 'field' instead of the custom formatters. Should also be able to remove the custom formatters from the code base completely.

If there is missing functionality in the Field API formatters, file separate issue(s) to add that back in (especially if it would delay this patch), and add them to the meta-parent issue: #2393339: [META] Make sure Views base fields are using Field API for formatting, and do not lose functionality

Remaining tasks

Make a patch.

User interface changes

None.

API changes

Not really.

Comments

cosmicdreams’s picture

This sounds very interesting, and a lot of work. Is #2456713: Custom taxonomy field views handler needs to be replaced with generic Field API handler a good example of what needs to be done for File to get it into compliance?

dawehner’s picture

I'll give it a try.

dawehner’s picture

Status: Active » Needs review
StatusFileSize
new21.33 KB

Let's see, how much fails.

jibran’s picture

Issue tags: +Field API

I think we need @yched input here.

jibran’s picture

Issue tags: +Needs tests

We also need tests for all the new formatters.

Status: Needs review » Needs work

The last submitted patch, 3: 2456709-3.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new23.92 KB
new3.41 KB

@jibran
Sure, no question.

Here is some work on config schema first.

Status: Needs review » Needs work

The last submitted patch, 7: 2456709-7.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new30.27 KB
new6.35 KB

Fixing just the test for now.

Status: Needs review » Needs work

The last submitted patch, 9: 2456709-9.patch, failed testing.

amateescu’s picture

  1. +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php
    @@ -0,0 +1,84 @@
    +abstract class BaseFieldFileFormatterBase extends FormatterBase {
    

    The name of this class is a bit unfortunate, I don't think it's tied only to base fields, is it?

  2. +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php
    @@ -0,0 +1,50 @@
    +class DefaultFileFormatter extends BaseFieldFileFormatterBase {
    
    +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileExtensionFormatter.php
    @@ -0,0 +1,83 @@
    +class FileExtensionFormatter extends BaseFieldFileFormatterBase {
    
    +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileSize.php
    @@ -0,0 +1,47 @@
    +class FileSize extends FormatterBase {
    
    +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileUriFormatter.php
    @@ -0,0 +1,59 @@
    +class FileUriFormatter extends BaseFieldFileFormatterBase {
    
    +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FilemimeFormatter.php
    @@ -0,0 +1,75 @@
    +class FilemimeFormatter extends BaseFieldFileFormatterBase {
    

    Wouldn't it be easier to just provide something like "FileInformationFormatter" with settings to display all of these things?

  3. +++ b/core/modules/file/src/Tests/Formatter/DefaultFileFormatterTest.php
    @@ -0,0 +1,18 @@
    +class DefaultFileFormatterTest extends KernelTestBase {
    +}
    

    I think the test are failing because of this test class with no test*() methods.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new33.97 KB
new5.48 KB

Thank you for your review!!

Wouldn't it be easier to just provide something like "FileInformationFormatter" with settings to display all of these things?

Did you had a look at the code and see what they actually provide, its so dramatically different.

I think the test are failing because of this test class with no test*() methods.

Yeah right, I was not able to motivate to write some, if we aren't even sure whether we want the formatter structure like that.

dawehner’s picture

Issue tags: -Needs tests

Alright, we have tests now.

jhodgdon’s picture

Status: Needs review » Needs work

Took a look at the latest patch... some thoughts:

a) It's modifying core/modules/file/config/optional/views.view.files.yml -- not sure how well the pages/blocks that view handles are tested, so we should probably look at them in a manual test before marking this patch RTBC. Didn't do that yet...

b) Similarly, we should probably manually test the code changes by making a File-based view with the patch, manually, and make sure the fields all work the way we'd expect, in the Add dialogs, Settings, and output. Didn't do that yet...

c) core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php -- class has no class doc block.

d) In the settings form on that class:

+    $form['link_to_file'] = [
+      '#title' => $this->t('Link this field to download the file'),
+      '#description' => $this->t("Enable to override this field's links."),
+      '#type' => 'checkbox',
+      '#default_value' => $this->getSetting('link_to_file'),
+    ];

Can we fix the field title/description? These don't make much sense to me. How about:
- Link this field to the file download URL
- I think get rid of the description. Our UI text says only to put in a description if absolutely necessary, and I don't think this adds anything comprehensible/useful to the title? If it does it needs to be reworded because I have no idea what it means: what links are being overridden?

e) In the viewElements on that same class:

+  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),
+        ];
+      }

Um... is this right? $items is an array of field items, right? So ... how is there only one entity URL? You have a multi-valued field and you're making the same link for all of them??!? That cannot possibly be right?

f)

++ b/core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\file\Plugin\Field\FieldFormatter\DefaultFileFormatter.
+ */
...
+/**
+ * Formatter to render a field to its file itself
+ *

This is not an OK class description... What is this? "render a field to its file itself"?!? No idea what it is supposed to be. Also needs to end in .

g)

+ *   label = @Translation("File link"),
+ *   field_types = {
+ *     "string"
+ *   }
+ * )
+ */
+class DefaultFileFormatter extends BaseFieldFileFormatterBase {

Oh, so it's actually the "File link" formatter? Does it need a better name? Anyway if the label here is correct, probably the class docs should say:
Provides a formatter for a text field on a file entity that links the field to the file.

If that's too long, take out the "Provides a" part.

h) Settings form in FileExtensionFormatter:

+      '#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'."),

I don't think this is clear... Let's change this to:
- Include tar in extension
- If the part of the filename just before the extension is '.tar', include this in the extension output.

i) Code in FileExtensionFormatter... kind of messy and unclear, why not use pathinfo() PHP function instead of custom regular expressions? Also the code comment "If there is an extension." is not a sentence.

j) FileSize formatter -- class description line needs to end in . and I think it would be better as something more like:
"Formatter for the filesize field on the File entity." Come to think of it, back to FileExtensionFormatter, maybe it should be "Formatter that shows the extension on the filename field for a File entity." Similar for the other formatters.

k) Shouldn't all these formatters do a check in isApplicable() to make sure the fields are on a File entity?

l) File URI formatter:

+ *   label = @Translation("File uri"),

Needs to be "File URI".

m) Same class, settingsForm is missing the inheritdoc block

n) In that class again:

+      '#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.'),

What does that description mean? Would anyone not a Drupal developer have any idea what the "internal filestream address" is?

o) On the Mime type formatter:

+      '#title' => $this->t('Display an icon representing the file type, instead of the MIME text (such as "image/jpeg")'),

That is kind of long, maybe split into title/description?

p) Same formatter:

+    if ($this->getSetting('filemime_image') && $value) {
+      $file_icon = [
+        '#theme' => 'image__file_icon',
+        '#file' => $item->getEntity(),
+      ];

Hm. So if you set up to use the mime image, you are deriving that image from the entire File entity, not the mime type field? That's interesting...

q) core/modules/file/src/Tests/Formatter/FileEntityFormatterTest.php - most methods lack docblocks

Whew!

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new34.55 KB
new8.24 KB

Thank you for your intensive review!

c) core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php -- class has no class doc block.

Made it to exactly 80 chars.

Can we fix the field title/description? These don't make much sense to me. How about:

Sure ... to be clear, I just copied them over from where, where especially the description might make more sense in the first place.

Link this field to the file download URL

That is absolutely an improvement.

Um... is this right? $items is an array of field items, right? So ... how is there only one entity URL? You have a multi-valued field and you're making the same link for all of them??!? That cannot possibly be right?

... Field formatters are always written against FieldItemList ... as this is what $entity->bar always contains, no matter whether its a base field or its a configured field, with actually multiple entries.
Please have a look at any other formatter in core. ... $items is always coming from one $entity.

i) Code in FileExtensionFormatter... kind of messy and unclear, why not use pathinfo() PHP function instead of custom regular expressions? Also the code comment "If there is an extension." is not a sentence.

Well, its all existing code ... too bad

"Formatter for the filesize field on the File entity."

Alright

k) Shouldn't all these formatters do a check in isApplicable() to make sure the fields are on a File entity?

Well, I guess we have to ... Its just a bit sad that we can't make the formatters easily reusable.

What does that description mean? Would anyone not a Drupal developer have any idea what the "internal filestream address" is?

Well, I just removed it, we seem to not want to explain users details, too bad.

That is kind of long, maybe split into title/description?

Did that, thank you.

Hm. So if you set up to use the mime image, you are deriving that image from the entire File entity, not the mime type field? That's interesting...

Well, it should be derived though from the filemime at the end ...

q) core/modules/file/src/Tests/Formatter/FileEntityFormatterTest.php - most methods lack docblocks

Right, because I think adding docblocks here would not add value, but rather discourage people from finding good test method names ...

Whew!

Seriously, use dreditor, it makes life so much easier ...

Status: Needs review » Needs work

The last submitted patch, 15: 2456709-15.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new37.18 KB
new6.6 KB

So we do have test coverage for that view, yeah!

effulgentsia’s picture

Issue tags: +Critical Office Hours

Per #2393339-57: [META] Make sure Views base fields are using Field API for formatting, and do not lose functionality, tagging for critical office hours, but if there's a reason to not have this particular child issue in that list, please untag it.

larowlan’s picture

This is close too, just some minor cleanup and some questions around optimisations

  1. +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php
    @@ -0,0 +1,58 @@
    +  public function settingsForm(array $form, FormStateInterface $form_state) {
    

    This method can go?

  2. +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileExtensionFormatter.php
    @@ -0,0 +1,80 @@
    +    return $field_definition->getTargetEntityTypeId() === 'file' && $field_definition->getName() === 'filename';
    

    Is it worth moving the first half of this to the parent method? Seems to be common to all of the child classes. Then these lines would be:

    return parent::isApplicable($field_definition) && {the rest of the hunk}
    
  3. +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileSize.php
    @@ -0,0 +1,47 @@
    + * Formatter that shows the extension on the filename field for a File entity.
    

    c/p error - should say something about file size

  4. +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FilemimeFormatter.php
    @@ -0,0 +1,76 @@
    + * Formatter to render filemime as image.
    

    Seems that rendering image is optional? Perhaps Formatter to render the file mime type, with an optional icon?

  5. +++ b/core/modules/file/src/Tests/Formatter/FileEntityFormatterTest.php
    @@ -0,0 +1,140 @@
    +    $file->save();
    

    Any reason for the two file->save() calls (here and in all cases)

  6. +++ b/core/modules/file/src/Tests/Formatter/FileEntityFormatterTest.php
    @@ -0,0 +1,140 @@
    +  public function testFormatterFileLink() {
    ...
    +  public function testFormatterFileExtension() {
    ...
    +  public function testFormatterFileMime() {
    ...
    +  public function testFormatterFileSize() {
    

    Missing docblocks?

jibran’s picture

Status: Needs review » Needs work

NW cuz of #19

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new37.43 KB
new7.45 KB

Is it worth moving the first half of this to the parent method? Seems to be common to all of the child classes. Then these lines would be:

Well, if you think its really easier to read :)

Any reason for the two file->save() calls (here and in all cases)

impatience

Missing docblocks?

Meh

larowlan’s picture

Issue summary: View changes
Status: Needs review » Needs work
StatusFileSize
new68.22 KB
new25.45 KB
new12.7 KB

Manual testing - ended up with an Exception - see screenshot.

Also noticed that the boolean formatter doesn't seem to have #states support, although could be pre-existing issue there.

Attached is my test view from which the exception was thrown - created the view, added an article with a file attached.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new2.51 KB
new37.99 KB

Thank you for your manual test! I think we should

Manual testing - ended up with an Exception - see screenshot.

Long story short.

Fatal error, due to passing "0" as $settings. This is caused by the code in core/lib/Drupal/Core/Field/FormatterPluginManager.php:161
doing basically array_intersect_key($settings, NULL) + NULL === NULL. This is caused by a missing return value in \Drupal\file\Plugin\Field\FieldFormatter\FileUriFormatter::defaultSettings

Another problem was that the wrong field type was supported.

Let's expand the test coverage.

Attached is my test view from which the exception was thrown - created the view, added an article with a file attached.

Yeah, that is not a problem of that issue, but I was sure #1985406: #states not supported for elements in formatter settings being displayed on Views field handler form had fixed that.

Status: Needs review » Needs work

The last submitted patch, 23: 2456709-23.patch, failed testing.

dawehner’s picture

Status: Needs work » Needs review
StatusFileSize
new38.54 KB
new1.28 KB

Also tests has to be written in the right ways.

dawehner’s picture

StatusFileSize
new40.18 KB
new1.64 KB

Added the access test coverage

larowlan’s picture

Status: Needs review » Reviewed & tested by the community

Thanks

rteijeiro’s picture

StatusFileSize
new40.19 KB
new482 bytes

Just fixed a nitpick.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

This issue addresses a critical bug and is allowed per https://www.drupal.org/core/beta-changes. Committed d36e3de and pushed to 8.0.x. Thanks!

alexpott’s picture

This issue addresses a critical bug and is allowed per https://www.drupal.org/core/beta-changes. Committed 7f90ee6 and pushed to 8.0.x. Thanks!

diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php
index fb51e9f..18375aa 100644
--- a/core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/DefaultFileFormatter.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\file\Plugin\Field\FieldFormatter;
 
-use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemInterface;
 use Drupal\Core\Form\FormStateInterface;
 
diff --git a/core/modules/file/src/Tests/Views/FileViewsFieldAccessTest.php b/core/modules/file/src/Tests/Views/FileViewsFieldAccessTest.php
index e7593fc..74baac3 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;

Fixed some unused uses on commit.

  • alexpott committed 7f90ee6 on 8.0.x
    Issue #2456709 by dawehner, rteijeiro: File views handlers need to be...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

amateescu’s picture

Opened a small follow-up to remove some forgotten entries in the file module's config schema: #2479607: Remove obsolete schema entries from file.views.schema.yml