Problem/Motivation
Coming from #2721349: Nested inline entities must be saved in "inside-out" order, i noted that we make quite a throughout the code to track iIEF entities in $form_state, to finally save them in \Drupal\inline_entity_form\WidgetSubmit::doSubmit. I suppose all that came from D7.
Otoh, looking into \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem, in D8, it can well do the job for us in preSave:
/**
* Determines whether the item holds an unsaved entity.
*
* This is notably used for "autocreate" widgets, and more generally to
* support referencing freshly created entities (they will get saved
* automatically as the hosting entity gets saved).
*
* @return bool
* TRUE if the item holds an unsaved entity.
*/
public function hasNewEntity() {
return !$this->isEmpty() && $this->target_id === NULL && $this->entity->isNew();
}
public function preSave() {
if ($this->hasNewEntity()) {
// Save the entity if it has not already been saved by some other code.
if ($this->entity->isNew()) {
$this->entity->save();
}
// Make sure the parent knows we are updating this property so it can
// react properly.
$this->target_id = $this->entity->id();
}
if (!$this->isEmpty() && $this->target_id === NULL) {
$this->target_id = $this->entity->id();
}
}
Proposed resolution
Remove our $entity->save() logic and let the field do the job. Benefits:
- Largely reduced complexity on our side.
- Works also for special EntityReferenceItem implementations
Update: This works in principle, but only for new entities.
Remaining tasks
- Figure out how to fix the above.
User interface changes
API changes
Data model changes
Issue fork inline_entity_form-3189205
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
geek-merlinComment #3
geek-merlinInteresting:
- In patch #2966933-11: Complex widget doesn't yield automatic pathauto aliases, the WidgetSubmit::doSubmit $entity->save() logic is disabled for pathauto-needing entities, which is reported to fix that issue, but does not break IEF.
I wonder what happens if we remove that $entity->save completely.
Comment #5
geek-merlinRemoved our saving logic.
Some entity saving tests seem to still work, while others fail.
For example, ComplexSimpleWidgetTest.testSimpleInComplex creates some nodes and passes.
Interesting.
Checking some failing tests, the pattern may be that creating entities works, while updating fails.
Comment #6
geek-merlinOK, now i grok that core logic:
- It saves unsaved entities without ID. According to above test results, this really obsoletes our $form_state storage for creating new entities.
- It does not save changed entities with ID. Until maybe core does this one day, we'd have to do this ourselves :-/. Not sure how easy that is, compared to the current approach.
Comment #7
aaronbaumanfixed typo in title
Comment #8
geek-merlinOK, so to sum up. i tried what can be done with FieldType/TypedData, but no low hanging success. Still thinking, as this would imho be gold standard.
(If referenced entities are auto-saved just before the entity itself, this is proof that saving always happens in the right order.)
Comment #9
geek-merlinComment #10
geek-merlinWe'd need that upstream.
Comment #11
geek-merlinThe current approach uses hook_entity_presave to emulate field item autosave.
Some tests are failing, so this may or may not work out.
Comment #12
geek-merlinComment #14
Pooja Ganjage commentedComment #15
geek-merlinThis turned out much mor complicated than thought, so the other approaches had been preferrable for now.
I still believe that this should be the way to go at some point in the future.