Problem/Motivation
There is an issue if you have an entity browser inside an inline entity form.
- Reference from article to media entity gallery with complex inline entity form widget
- These gallery entity has a reference to media entity image with entity browser widget
- After creating a gallery and selecting some images, we press save gallery
- Then edit gallery and the selected images are gone
- The article was not saved in this use-case
The attached patch, fixes this issue
| Comment | File | Size | Author |
|---|---|---|---|
| #47 | interdiff.txt | 2.4 KB | slashrsm |
| #47 | 2764889_47.patch | 32 KB | slashrsm |
| #46 | 2764889_44.patch | 31.97 KB | slashrsm |
| #41 | interdiff-2764889-37-41.txt | 4.83 KB | mtodor |
| #41 | 2764889-41.patch | 31.95 KB | mtodor |
Comments
Comment #2
chr.fritschComment #3
slashrsm commentedCould we do just !empty()?
Can you explain a bit why this patch fixes it? It is not obvious and I'd like to fully understand what is going on before committing.
Comment #4
chr.fritschWhen Drupal\entity_browser\Plugin\Field\FieldWidget\EntityReference:formElement() is executed during switching from IEF preview to edit mode, $form_state->has(['entity_browser_widget', $this->getFormStateKey($items)]) returns true but its empty, but in the $items everything is fine.
But maybe the issue occurs before, so that the storage should not be empty.
Comment #5
slashrsm commentedI'd say we simplify the condition a bit. Should be equivalent.
I tested few pretty edge-casey scenarios and it seems that widget still works OK in other cases too.
We should definitely have tests for this. @Denchev is working on basic Javascript test. When that lands it will be easier to extend it with coverage for cases like this one.
I suggest to commit this and add tests later.
Comment #6
mtodor commentedThis problem is not just with adding new entities, it's also with editing of selection. If you already have created media with few entities selected and you want to edit selection and remove entity. When you click update media and edit again - old selection will be displayed.
I have attached module with configuration, that can be used to reproduce it.
Modules needed: Entity Browser + EB Examples + EB IEF, Inline Entity Form, Entity, Media Entity
+ Test module I have attached (test_ief_remove).
Steps to reproduce:
1. Create new "Test IEF Remove" content
2. Set title -> Click "Add new Test File Media" -> set name for media
3. Click "Select entities" -> upload few files or use existing
4. Click "Create Test File Media" -> "Save and Publish"
5. Make edit of that saved content
6. Click "Edit" to edit Test File Media
7. Remove any entity for existing list
8. Click "Update Test File Media"
9. Click again "Edit" to edit Test File Media
=> Old preselection will be populated.
If content would be "Saved and Published" -> selection would properly saved.
I have investigated a bit and looks that problem is with not correct saved state in $form_state after Remove action.
If someone have idea where to look further, I would appreciate that?
Comment #7
mtodor commentedI have investigated further what makes inconsistent form state -> and I have ended in IEF module.
So what is going on (in "short"): for example when remove button is pressed without IEF
Other case: for example when remove button is pressed within IEF
I have changed that IEF doesn't return #process callback but actually just to execute it and provide result directly. In that case form state will be properly saved (cached). Also build flow is more similar to normal build flow.
I have provided patch for Inline Entity Form module, maybe it's easier for someone to see code instead of "short" explanation. I'm not sure is that right way to go? And what are other options to solve issue?
Comment #8
berdirJust a reroll of #5 so I can test it.
Comment #9
berdirNote: Turns out that the paragraph problems that I had in alpha7 are already fixed in 8.x-1.x-dev, which explains why I couldn't reproduce with that version.
Given that, not sure if this is needed and how to reproduce this problem exactly.
@mtodor: If you think there is a bug in IEF, I suggest you open a new issue there and reference this.
Comment #10
bojanz commentedDoesn't sound logical that #process would cause any $form_state issues. If there's an IEF bug somewhere, it's not due to #process.
Comment #11
mtodor commentedAdded test to represent problem. It still doesn't cover cases when Entity Browser with preselection is used (multi step).
Tests that should be added:
Comment #17
slashrsm commentedAdded test dependency ^.
Comment #23
slashrsm commentedReroll.
Comment #29
mtodor commentedHere is solution proposal with using of "target_id" input element as source of selection if it's available.
I have also added additional tests (test class is also checked with Selenium):
Additional info for new test module: I have added jQuery library for drag/drop simulation, because we need it for testing of reordering. Library is taken from: https://github.com/jquery/jquery-simulate
What would be nice to do is:
Comment #31
mtodor commentedAdjusted test to work properly with faster execution.
Comment #33
samuel.mortensonAn alternative to adding the jquery.simulate library would be to just simulate the event we're hoping to trigger. In #2421427: Improve the UX of Quick Editing single-valued image fields I do this with the following code:
This specific test was mocking a "dropped file" event, which is likely more complicated than mocking a DOM element being dragged somewhere.
Comment #34
mtodor commented@samuel.mortenson: I'll take a look at your solution. I'm always up to get rid of additional dependencies. I guess that for this test tricky part will be to find correct drop event coordinates (x, y).
Comment #35
slashrsm commentedUse snake case. From coding standards.
snake_case is used in this file.
Also
getUserInput()returns raw and potentially unsecure values.getValues()should be used instead.I am not sure if we're allowed to add this into the repository since it is not GPL. We should check and be very careful with that.
Another reason to try to avoid it.
Comment #36
dawehnerWorking on addressing the feedback. I'm quite sure that you can simulate dragging much nicer.
Comment #37
dawehnerMh, I tried to use the following code, but sadly this somehow looses content. If you are honest, this bugfix for itself, doesn't need to test the drag&drop functionality, right?
Comment #38
samuel.mortensonI believe that JS testing is required to reproduce the bug (as reported, at least), but you should be able to submit the form with arbitrary weights without drag and drop. *Fingers crossed*
Comment #39
mtodor commentedI'll take look to simulate DD.
I think that problem with native driver dragTo method is that you can't specify position and that's what we need in this case, because drop element should be container of draggable elements.
And tests for reorder are here, because better test coverage for entity browser and that's what we should improve.
Comment #40
dawehnerNo question this totally makes sense, but this issue is about a different bugfix, to be honest. Creating an issue is easy and we do it not often enough.
Comment #41
mtodor commentedUnfortunately solution with
getValues()doesn't work, it doesn't contain values required to determine selected elements, so I have usedgetUserInput().And I have added solution for drag->drop, it's not nice, but it should work fine (also tested with Selenium and PhantomJS).
Comment #42
dawehnerNice work!
Comment #43
chr.fritschThis patch is part of Thunder since weeks. We haven't noticed any issues with that. Would be nice to get this committed.
Comment #46
slashrsm commentedReroll.
Comment #47
slashrsm commentedA bit of a clean-up/code optimization. I am not super happy with the solution as it looks a bit hacky. Also, the fact that we need to use raw user input probably shows that we're doing something wrong.
However, I don't have any better suggestions right now. Patch clearly fixes the problem and adds a bunch of new tests. This should allow us to refactor in the future. I opened #2825890: Refactor and clean EntityReferenceBrowserWidget::formElementEntities() for that.
Great work @mtodor!!
Comment #49
slashrsm commentedComment #50
dawehnerNice, thank you @slashrsm!
Comment #52
oknateI'm going to revisit this issue, as it looks to be causing a regression in the EntityReferenceBrowserWidget when used without inline entity form:
#3046416: Remove button conflict wrong triggering element
It seems that updating the form on rebuild causes the remove button to not be recognized, so Drupal FAPI grabs a random button leading to some surprising and hilarious consequences.