EntityReferenceFormatterBase contains the logic about collecting the entities to display, including non-existing entities and autocreated entities.

FileFormatterBase currently duplicates that logic. #2403873: FileFormatterBase does not retain unsaved entities (files) fixed a bug there, but a better fix would be that FileFormatterBase extends EntityReferenceFormatterBase.

Also, this fixes some nasty bugs since currently file/image formatters:
- (major) do not follow the correct translation behavior that was added for ER fields in #2346315: Translated entity references not rendered in the entity display language
- (critical) do no check entity access

Regarding access check, discussion has shown (#32 / #35) that:
- it actually makes no sense and would just add useless overhead to check file access with core's default FileAccessControlHandler, given its internal logic
- but, if a different access handler with different logic was switched in, then not running file access would be a security hole.

Thus, what the patch fixes is the ability for the file access controller to opt-in for "have file formatters run me" if their logic require it, by implementing FileAccessFormatterControlHandlerInterface (empty marker interface)

CommentFileSizeAuthor
#77 file-formatter-you-stinky-orphan-2405469.77.patch28.39 KBlarowlan
#77 interdiff.txt3.16 KBlarowlan
#66 interdiff.txt6.92 KBamateescu
#66 2405469-splobjectstorage.patch25.91 KBamateescu
#64 2405469-FileFormatterBase_ERFormatterBase-64.patch25.21 KBBerdir
#56 interdiff.txt1.5 KByched
#56 2405469-FileFormatterBase_ERFormatterBase-53.patch27.28 KByched
#52 interdiff.txt1.74 KByched
#52 2405469-FileFormatterBase_ERFormatterBase-52.patch26.57 KByched
#49 interdiff.txt590 bytesyched
#49 2405469-FileFormatterBase_ERFormatterBase-49.patch26.49 KByched
#47 interdiff.txt843 bytesgoogletorp
#46 interdiff.txt0 bytesgoogletorp
#46 2405469-FileFormatterBase_ERFormatterBase-46.patch26.41 KBgoogletorp
#45 interdiff.txt7.43 KByched
#45 2405469-FileFormatterBase_ERFormatterBase-44.patch26.42 KByched
#42 2405469-FileFormatterBase_ERFormatterBase-42.patch23.2 KBgoogletorp
#39 interdiff.txt7.13 KByched
#39 2405469-FileFormatterBase_ERFormatterBase-39.patch24.27 KByched
#30 interdiff.txt10.05 KByched
#30 2405469-FileFormatterBase_ERFormatterBase-30.patch22.21 KByched
#28 interdiff.txt4.61 KByched
#28 2405469-FileFormatterBase_ERFormatterBase-28.patch15.91 KByched
#23 2405469-FileFormatterBase_ERFormatterBase-23.patch16.05 KByched
#10 interdiff.txt743 bytesyched
#10 2405469-FileFormatterBase_ERFormatterBase-10.patch15.2 KByched
#8 interdiff.txt539 bytesyched
#8 2405469-FileFormatterBase_ERFormatterBase-8.patch15.08 KByched
#5 interdiff.txt664 bytesyched
#5 2405469-FileFormatterBase_ERFormatterBase-5.patch15.06 KByched
#2 2405469-FileFormatterBase_ERFormatterBase-2.patch14.75 KByched
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

yched’s picture

For that, EntityReferenceFormatterBase should be in Core rather than in entity_ref module.
Thus, postponed on #2404021: entity_reference formatters should be in Core

yched’s picture

Status: Postponed » Needs review
FileSize
14.75 KB

#2404021: entity_reference formatters should be in Core is in.

Initial attempt - this lets us simplify / unify quite some code down all file / image formatters.

Still @todo - would be really nice if this let us get rid of "the default image has a side effect of modifying the $items in the $entity that gets rendered". Mulling on that.

yched’s picture

Category: Task » Bug report
Issue summary: View changes

Also, this actually fixes a bug: currently file/image formatters do not follow the correct translation behavior that was added for ER fields in #2346315: Translated entity references not rendered in the entity display language

yched’s picture

Priority: Normal » Major
yched’s picture

#2 will fail on 'default_image'. This should fix it.

The last submitted patch, 2: 2405469-FileFormatterBase_ERFormatterBase-2.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 5: 2405469-FileFormatterBase_ERFormatterBase-5.patch, failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
15.08 KB
539 bytes

Headdesk of the month.

Status: Needs review » Needs work

The last submitted patch, 8: 2405469-FileFormatterBase_ERFormatterBase-8.patch, failed testing.

yched’s picture

Issue summary: View changes
Priority: Major » Critical
Status: Needs work » Needs review
FileSize
15.2 KB
743 bytes

Fails in ToolbarAdminMenuTest look like an unrelated bot fluke, test is green locally

Fails in ImageFieldDefaultImagesTest were because basing on ERFormatterBase means we now check entity access, and that seems to fail for the default image used in that test.

For now, working around this by forcing the "fake" 'access' property in the runtime-added item for the default image. Will need more thought, and #2374019: Cleanup the use of custom item properties in EntityReferenceFormatterBase intends to get rid of that property anyway.

But the fact that file/image formatters currently do not check entity access would make this critical ?

jibran’s picture

  1. --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceFormatterBase.php
    +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceFormatterBase.php
    

    Damn this change will affect DER.

  2. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceFormatterBase.php
    @@ -95,4 +86,17 @@ public function prepareView(array $entities_items) {
    +  protected function getIdsToLoad(array $entities_items) {
    

    function doc missing.

yched’s picture

@jibran : Sure, docs still missing, and there are @todos. This is still a WIP :-)

How would DER be affected ?

jibran’s picture

Sure, docs still missing, and there are @todos. This is still a WIP :-)

I was just being helpful please ignore my reviews when you are still working on issues. :)

How would DER be affected ?

Doesn't matter this is a note to self. :) I am trying to keep up with iq. We are overriding EntityReferenceFormatterBase::prepareView() in DynamicEntityReferenceFormatterTrait

amateescu’s picture

+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php
@@ -19,9 +19,14 @@
+    // @todo : is there any way we could do this without modifying $items in the
+    // $entity as a side effect ?
+    // We could move loading the $file to getEntitiesToView(), but we also need
+    // to pass the fake $item created below.

We can override ERFormatterBase::getEntitiesToView() and manually append the fake $item/$file to the returned array, no?

+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatterBase.php
@@ -40,6 +45,9 @@ public function prepareView(array $entities_items) {
+            // @todo Temporary - ImageFieldDefaultImagesTest fails without it. Figure this out.
+            'access' => TRUE,
Fails in ImageFieldDefaultImagesTest were because basing on ERFormatterBase means we now check entity access, and that seems to fail for the default image used in that test.

For now, working around this by forcing the "fake" 'access' property in the runtime-added item for the default image. Will need more thought, and #2374019: Cleanup the use of custom item properties in EntityReferenceFormatterBase intends to get rid of that property anyway.

#2374019: Cleanup the use of custom item properties in EntityReferenceFormatterBase will indeed remove 'access' but I think we currently agree that 'originalEntity' needs to stay (even with a different name) and the presence of this property (originalEntity) will also mean that the $item in question was checked for access.. I think.

yched’s picture

We can override ERFormatterBase::getEntitiesToView() and manually append the fake $item/$file to the returned array, no?

Yup, that would be the idea. I started that in a local branch based on this patch. Not sure yet if I'll include it in the next iteration or keep it for a followup.

IMO it makes a lot of sense for the "fallback image" : the "entities to view" are derived from the $items, but do not modify the $items.

The issue is that getEntitiesToView() is fine for ER formatters, because an ERItem only contains an entity (a target_id).
But File and Image items contain other stuff ('alt', 'title'...), so the formatters use the entity but also the item that references the entity.

In the current patch, they do :

foreach ($this->getEntitiesToView() as $delta => $entity) {
  $item = $items[$delta];
  // Do stuff with $entity and the $item that refers to it.
}

In the case of the "fallback image", we can add it as an entity in getEntitiesToView(), but the formatter will also need the associated "fake item", that we don't want to add in $items.

In my local branch, I worked around that by having ImageFormatterBase::getEntitiesToView() add $entity->_referringItem in all the returned entities. That way the formatters can call getEntitiesToView() and have both the entity and the item. Not completely ideal, but I can't think of a better solution atm.

And then I'm wondering whether it would make sense to move that $entity->_referringItem thing all the way up in ERFormatterBase::getEntitiesToView().

amateescu’s picture

The issue is that getEntitiesToView() is fine for ER formatters, because an ERItem only contains an entity (a target_id).
But File and Image items contain other stuff ('alt', 'title'...), so the formatters use the entity but also the item that references the entity.

That's a very good point. So we actually need something like getItemsToView() if we want to be able to use it for file/image fields too. I think it's valid to do that refactoring in this issue, but maybe postponed on #2374019: Cleanup the use of custom item properties in EntityReferenceFormatterBase?

yched’s picture

getItemsToView() : why not, not too sure yet. I considered that option as well, but:

- I wasn't completely a fan of

public function viewElements($items) {
  $items = $this->getItemsToView($items);
  ...
}

:-)

- In relation to #2374019: Cleanup the use of custom item properties in EntityReferenceFormatterBase : if formatters go back to working with $items / $item (those returned by getItemsToView()), we can't expect them to work with $item->originalEntity or whatever other custom property name contains the "right" entity. They should do $this->entity as usual. Hence my last patch in that issue over there, which should make that point a non-issue.

- More importantly : would we also move ERFormatterBase and the ER formatters from getEntitiesToView() to getItemsToView() ?
Feels weird to have ER formatters use getEntitiesToView() and tell field/image formatters "yeah, there is a getEntitiesToView(), but it's not for you, you guys have getItemsToView() instead" ?

amateescu’s picture

Ugh, yes, getItemsToView() might be an unfortunate name.

- More importantly : would we also move ERFormatterBase and the ER formatters from getEntitiesToView() to getItemsToView() ?

Definitely, we have to try and get all of them at the same level on semantics.

larowlan’s picture

+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceFormatterBase.php
@@ -95,4 +86,17 @@ public function prepareView(array $entities_items) {
+        if ($item->target_id !== NULL) {

Should we be checking $item->hasNewEntity() here too?

yched’s picture

@larowlan - good question, that puzzled me too. But this is what HEAD does atm, the patch just moves this code around.

larowlan’s picture

Issue tags: +Critical Office Hours

Tagging for manual testing in office hours and possibly reviews depending on taker

jibran’s picture

Status: Needs review » Needs work

This is NW as per #13 #14 #15 and if we can commit #2374019: Cleanup the use of custom item properties in EntityReferenceFormatterBase it would help here that is RTBC. That is not a blocker so I can't change the priority there.

yched’s picture

Status: Needs work » Needs review
FileSize
16.05 KB

For now, just a reroll after #2374019: Cleanup the use of custom item properties in EntityReferenceFormatterBase.

Shows that the split between prepareView() and getIdsToLoad() in ERFormatterBase is not ideal. Left a @todo, will address in a later patch.

Status: Needs review » Needs work

The last submitted patch, 23: 2405469-FileFormatterBase_ERFormatterBase-23.patch, failed testing.

yched’s picture

Of course, like mentioned in #10, this fails now that we can't hack the $entity_ref_item->acces property of the "default image" anymore :-p. Will look into fixing access checks in those tests at last.

catch’s picture

Issue tags: +Security, +D8 upgrade path
effulgentsia’s picture

Issue tags: +Triaged D8 critical

Confirmed the criticality of this (due to the access checking part) with the branch maintainers, so tagging.

yched’s picture

Status: Needs work » Needs review
FileSize
15.91 KB
4.61 KB

Puts the iteration back into prepareView(), as mentioned in #23.

This will still fail because of #25 (access check on the fallback image), that's the next target.
Still running the bot to check there were no other regressions.

Status: Needs review » Needs work

The last submitted patch, 28: 2405469-FileFormatterBase_ERFormatterBase-28.patch, failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
22.21 KB
10.05 KB

Work in progress for #15 - #17, here's what I have.
Will post more explanations in a later comment :-)

Status: Needs review » Needs work

The last submitted patch, 30: 2405469-FileFormatterBase_ERFormatterBase-30.patch, failed testing.

yched’s picture

So, funny things :

- we cannot check entity access on the fallback image (HEAD currently doesn't, but latest patch does), since core's FileAccessControlHandler grants access based on whether there exists an entity the user can access that referes to the file. But the principle of the fallback image is that it can totally happen that no entity actually refers to it.

- given the above on how FileAccessControlHandler works, it seems a bit absurd (and costly) to have image/file formatters check access on file/image entities before displaying them ? If we are displaying the field, it means the user should have view access to the parent entity, and having FileAccessControlHandler re-do that there exists such an entity is useless (and also, might break on preview I guess, since the entity that refers to the file might not be created in the db yet ?)

- but the reasoning above is only valid for the current FileAccessControlHandler - what if a different access handler is swapped in for files ?

larowlan’s picture

Right, that is problematic. Something like file_entity would definitely swap something in.

Perhaps we can get the access handler class and see if it is FileAccessControlHandler, and if so skip the access check - if it's not - we can call ->access()?

yched’s picture

Yes, I was thinking of something like that too.

Drawback is that we'd hardcode behavior on a specific access handler class. If you swap a similar but just slightly different class (say, a subclass that changes a minor behavior, or changes behavior for grants other than 'view'), you're out of luck.

Maybe the file access handlers should have a method for "call me in file/image formatters" ? :-/

larowlan’s picture

Something like this?

FileAccessControlHandlerInterface extends EntityAccessControlHandlerInterface {
  /**
   * Determines if formatters should check access to a file before rendering.
   *
   * By default core's file-access controls depend on view access to the entity
   * containing the file/image field. If the user can view the entity to which
   * the field is attached, then they can view the file also. Rather than hard-code
   * this assumption, File access control handler must implement this method
   * to notify file formatters if additional access checking is required.
   *
   * @return bool
   *    TRUE if formatters need to check access before rendering.
   */
  public function formatterAccess();
}

I think that makes sense

yched’s picture

Curious to know what @fago and @Berdir think about it, but this looks fine by me.

Will see how to integrate that behavior in the generic ERFormatterBase::getEntitiesToView()

catch’s picture

Or just an extra (empty) interface rather than adding the method?

FileAccessFormatterControlHandlerInterface
yched’s picture

Yup, better.

yched’s picture

Status: Needs work » Needs review
FileSize
24.27 KB
7.13 KB

Done as per #33 and #37 :
FileFormatterBase only checks access if the file access control handler implements FileAccessFormatterControlHandlerInterface, which the default file handler does not.

I tried to add understandable explanations in that newly added FileAccessFormatterControlHandlerInterface, suggestions welcome on how to make it less verbose - or how to phrase a first line that makes sense *and* doesn't go over 80 chars :-p

This seems to make the image tests pass again, let's see if this broke something else.

(patch also adjusts a couple vars names, and uses the _referringItem pattern consistenly in all file / image formatters - more on that when we're green)

jibran’s picture

I know this patch is WIP I am just adding remarks so that you can fix them before next reroll :)

  1. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceFormatterBase.php
    @@ -106,4 +106,11 @@ protected function needsEntityLoad(EntityReferenceItem $item) {
    +  protected function needsAccessCheck(EntityReferenceItem $item) {
    

    Can we use interface here? Else i have to override this for DER.

  2. +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileFormatterBase.php
    @@ -22,4 +22,11 @@ protected function needsEntityLoad(EntityReferenceItem $item) {
    +  protected function needsAccessCheck(EntityReferenceItem $item) {
    

    {@inheritdoc} missing.

  3. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceFormatterBase.php
    @@ -39,8 +40,13 @@ protected function getEntitiesToView(FieldItemListInterface $items) {
    +          // @todo if the assigned $value happens to be a TypedData, ContentEntityBase::__set()
    +          // force-assigns $value->getValue(). It should only do so on "official fields",
    

    more then 80 chars.

  4. +++ b/core/modules/responsive_image/src/Plugin/Field/FieldFormatter/ResponsiveImageFormatter.php
    @@ -232,10 +239,10 @@ public function viewElements(FieldItemListInterface $items) {
    +        $url = Url::fromUri(file_create_url($file->getFileUri()));
    

    We can use FileInterface::url() here.

googletorp’s picture

Other than what is mentioned above

+  /**
+   * @todo
+   */
+  protected function needsEntityLoad(EntityReferenceItem $item) {
+    return !$item->hasNewEntity();
+  }
+
+  /**
+   * @todo
+   */
+  protected function needsAccessCheck(EntityReferenceItem $item) {
+    return TRUE;
+  }

Documentation of these methods should be added

googletorp’s picture

Solved the comment issues, since it was easy pickings.

yched’s picture

@googletorp: The patch is still in progress, I was waiting for it to settle before filling in the docs. Thanks for stepping in - when uploading a new patch on an issue, it is really recommended to post an interdiff alongside, so that people can check you changes, and the patch author can integrate them in its local branch :-)

Will process @jibran's remarks in a later post.

mikey_p’s picture

Status: Needs review » Needs work

Latest patch is missing FileAccessFormatterControlHandlerInterface.php

yched’s picture

Status: Needs work » Needs review
FileSize
26.42 KB
7.43 KB

@mikey_p: yep, I added it back (manually added @googletorp's changes on top of my own branch)

This attempts to fix ContentEntityBase::__set() messing with TypedData objects added as non-field properties. Will post that as a separate patch if green.

Also adjusts the docs added in #42 a bit.

googletorp’s picture

@yched thanks for the info, I don't do much work on core.

I processed the last remark from jibran using File::url to generate the url, instead of file_create_url (this is what File::url does anyways).

googletorp’s picture

FileSize
843 bytes

Something failed in creating the interdiff, so adding it here.

yched’s picture

Assigned: Unassigned » yched

@googletorp, @jibran : That change is correct in itself, but is not related to this task here, this is existing code that the patch just moves around. Plus, ImageFormatter has the same code, and should be updated as well..

--> I'll revert #46 in the next patch I roll, please open a separate issue for this.

@jibran:

+  protected function needsAccessCheck(EntityReferenceItem $item) {

Can we use interface here? Else i have to override this for DER.

Problem is, we don't have an EntityReferenceItemInterface atm. Arguably we should, since EntityReferenceItem adds a specific public hasNewEntity() method. Care to open an issue for that ?

yched’s picture

Opened #2426509: ContentEntityBase::__set() messes with values that happen to be TypedData for the bug in ContentEntityBase::__set() that prevents $entity->_referringItem = $item.
Patch here still contains the fix for now, added a link.

Reverts #46, interdiff is with #45.

Wim Leers’s picture

Status: Needs review » Needs work

Only nits. This looks ready to me :)

  1. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceFormatterBase.php
    @@ -94,4 +96,30 @@ public function prepareView(array $entities_items) {
    +   * @param EntityReferenceItem $item
    ...
    +   * @param EntityReferenceItem $item
    

    Needs fully qualified classnames.

  2. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/EntityReferenceFormatterBase.php
    @@ -94,4 +96,30 @@ public function prepareView(array $entities_items) {
    +  protected function needsEntityLoad(EntityReferenceItem $item) {
    +    return !$item->hasNewEntity();
    +  }
    

    So much better :)

  3. +++ b/core/modules/file/src/FileAccessFormatterControlHandlerInterface.php
    @@ -0,0 +1,30 @@
    + * it might be needed if a different access control handler with different logic
    

    s/with/when/

  4. +++ b/core/modules/file/src/FileAccessFormatterControlHandlerInterface.php
    @@ -0,0 +1,30 @@
    + * files opts in by impleminting this interface.
    

    s/impleminting/implementing/

  5. +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileFormatterBase.php
    @@ -7,40 +7,29 @@
    +    return is_subclass_of($access_handler_class, '\Drupal\file\FileAccessFormatterControlHandlerInterface');
    

    Why not instanceof?

yched’s picture

Thanks @Wim, will address those asap. Also, I still need to explain a bit why I went with the $entity->_referringItem approach, but it's too late tonight.

Note that this is blocked on #2426509: ContentEntityBase::__set() messes with values that happen to be TypedData though.

yched’s picture

Status: Needs work » Needs review
FileSize
26.57 KB
1.74 KB

re @Wim #50 :

1. Fixed
2. :-)
3. I don't get this point, the sentence looks correct to me, and the proposed replacement doesn't :-)
"[that check] might be needed if a different access control handler with (= that has a) different logic is swapped in", no ?
4. Lol, "implemint" sounds delicious, but well, fixed :-p
5. Because we're checking "is $class_name as subclass of $other_class_name", instanceof doesn't work for that

amateescu’s picture

I'm very curious about that _referringItem stuff :)

jibran’s picture

Wim Leers’s picture

Title: FileFormatterBase should extend EntityReferenceFormatterBase » [PP-1] FileFormatterBase should extend EntityReferenceFormatterBase

Point 3 = Wimfail. I misread — sorry :)

RTBC as soon as:

  1. the blocker lands
  2. the _referringItem stuff is doc'd :)
yched’s picture

Enhanced docs a bit.

googletorp’s picture

Great work yched, all looks good to me.

amateescu’s picture

I'll try to take a thorough look at this tonight.

yched’s picture

So, about the $entity->_referringtems approach :

Sorry for making this such a mistery, just had a couple busy days with little quality time in front of my keyboard. Well, also took me a little while to actually remember the reason :-p, but it's actually pretty simple :

getEntitiesToView() is about providing an API to ERFormatter::viewElements() implementations for "just give me the entities I should display, *and* the corresponding items that reference them". That API takes care of checking access and putting the entities in the right language, so that it is not left for each formatter to figure out (with large chances of implementing it wrong or not at all).

Now, if that API primarily returned field items instead of entities (i.e if it was getItemsToView() instead of getEntitiesToView()):
- the formatters implementations would access the referenced entity with the regular "$item->entity", which doesn't give you the entity in the correct language (and we don't want to modify $item->entity to contain the entity in the right language, because we don't want to modify the containing entity being rendered - viewing an entity shouldn't modify that entity as a side effect)
- filtering out items for access check means we'd have to clone the FieldItemList (again, we don't want to modify the containing entity being displayed), which would be a slight perf impact.

So, we stick to returning an array of entities for display, and on each entity you can access the item that referenced it - that's $entity->_referringItem :-)

yched’s picture

Side note : an alternative could be to use SplObjectStorage to return an "array" with FieldItem object as keys and Entity objects as values, letting consumers do foreach ($this->getEntitiesToView() as $item => $entity)

Not sure it's worth the extra CPU cost - also, we don't use SplObjectStorage that much, it could look unfamiliar / surprising.

amateescu’s picture

Thanks @yched for the detailed description of this $entity->_referringtems approach. I agree that we can't make it prettier without SplObjectStorage, but I'm not sure there is any extra CPU cost involved to it, after all we're still building an array in getEntitiesToView().

So let's get this in to fix the critical and open a followup to investigate the alternative approach :)

One last thing though, should we add a test for the security part of this patch?

yched’s picture

Reading http://technosophos.com/2009/05/29/set-objects-php-arrays-vs-splobjectst..., it seems there is no perf impact regarding SplObjectStorage - they're even supposed to be faster :-). Given our use case here (most likely under 100 items), it would probably not make a difference anyway.

The difference betwen the two approaches is then:
- exposing SplObjectStorage in a relatively high-level API (entity ref formatters), not really a typical pattern in Drupal so far
- the SplObjectStorage approach loses track of the delta, you need to get it from the $item, using the (totally unintuitive) getName() method from TypedData (which, for FieldItems in a FieldItemList, happens to be the delta) :

// Current approach:
foreach ($this->getEntitiestoView() as $delta => $entity) {
  $item = $entity->_referringItem;
  $element[$delta] = [... $entity / $item ... ];
}

// SplObjectStorage approach:
foreach ($this->getEntitiestoView() as $item => $entity) {
  $delta = $item->getName();
  $element[$delta] = [... $entity / $item ... ];
}

This kind of sucks, because not all formatters actually need the $item, but they all need the $delta :-)

So yeah, I can't say I'm married to it, but I'm still inclined towards the _referringItem approach at this point.

jibran’s picture

Title: [PP-1] FileFormatterBase should extend EntityReferenceFormatterBase » FileFormatterBase should extend EntityReferenceFormatterBase
Status: Needs review » Needs work
Issue tags: +Needs reroll
Berdir’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
25.21 KB

Here's a reroll without the changes in ContentEntityBase.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

It is RTBC as per #55

/me goes to roll a fix for DER. :)

amateescu’s picture

If anyone is curious, this is how the patch might look like with the SplObjectStorage approach. Not saying that we should go with it, I just wanted to try it out.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 66: 2405469-splobjectstorage.patch, failed testing.

amateescu’s picture

Status: Needs work » Reviewed & tested by the community

Apparently it doesn't work very well, so the patch in #64 is RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/file/src/FileAccessFormatterControlHandlerInterface.php
@@ -0,0 +1,30 @@
+interface FileAccessFormatterControlHandlerInterface extends EntityAccessControlHandlerInterface { }

+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/FileFormatterBase.php
@@ -7,40 +7,29 @@
+  protected function needsAccessCheck(EntityReferenceItem $item) {
+    // Only check access if the current file access control handler explicitly
+    // opts in by implementing FileAccessFormatterControlHandlerInterface.
+    $access_handler_class = $item->entity->getEntityType()->getHandlerClass('access');
+    return is_subclass_of($access_handler_class, '\Drupal\file\FileAccessFormatterControlHandlerInterface');
   }

Since there is not an implementation of FileAccessFormatterControlHandlerInterface this code is untested. Plus we're obviously not running access checks on files still then - which the summary claims this fixes.

yched’s picture

Issue summary: View changes
Issue tags: +needs test

@alexpott:

Plus we're obviously not running access checks on files still then - which the summary claims this fixes

Yes, this was decided in #32 / #35 :
- it actually makes no sense and would just add useless overhead to check file access with core's default FileAccessControlHandler, given its internal logic
- *but*, if a different access handler with different logic was switched in, then not running file access would be a security hole.
Thus, what the patch fixes is the ability for the file access controller to opt-in for "have file formatters run me" if their logic requires it.

(added that to the IS)

Will need to think of how to test this with a dummy file access handler class.

yched’s picture

Also - we would likely need to move TaxonomyFormatterBase to EntityReferenceFormatterBase as well :-/.

It looks like it currently handles translation and access checks correctly, so that wouldn't be a bug fix, just a maintainability enhancement by avoiding one-off duplicate logic. Opened #2433513: [PP-1] TaxonomyFormatterBase should extend EntityReferenceFormatterBase

yched’s picture

Issue summary: View changes
Wim Leers’s picture

Issue tags: -needs test +Needs tests
amateescu’s picture

- *but*, if a different access handler with different logic was switched in, then not running file access would be a security hole.

Isn't the custom access handler responsible for not regressing in security from the default one provided by core?

yched’s picture

@amateescu : for the custom access handler to be responsible for anything, it needs to be called in the first place ;-)

The logic we're facing is :
- We don't want FileFormatters to run the default file access controller (FileAccessControlHandler), because for the specific logic in FileAccessControlHandler that would super costly and useless anyway
- But we want FileFormatters to be able to call the file access controller if it's *not* FileAccessControlHandler

So:
- It's the responsibility of the file access controller to specify that it wants to be called by FileFormatters (by implementing FileAccessFormatterControlHandlerInterface)
- It's the responsibility of FileFormatters to comply and actually call the access controller if it did the above :-)

larowlan’s picture

Assigned: yched » larowlan

/me starts on a test, will assign back later - sorry for hijacking

larowlan’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
3.16 KB
28.39 KB

Added tests

larowlan’s picture

Assigned: larowlan » yched

back to @yched

yched’s picture

Assigned: yched » Unassigned
Status: Needs review » Reviewed & tested by the community

Thanks a lot @larowlan ! Sorry, hard to carve out time in front of my IDE lately :-/

Thus, setting back to RTBC ?

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 ef0cb6e and pushed to 8.0.x. Thanks!

  • alexpott committed ef0cb6e on 8.0.x
    Issue #2405469 by yched, googletorp, amateescu, larowlan, Berdir:...

Status: Fixed » Closed (fixed)

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