From: nagyad <joevagyok@gmail.com>
Date: Fri, 31 Jan 2020 08:36:50 +0100
Subject: [PATCH] Issue #2367235 by nagyad, axel.rutz, dawehner, Les Lim, harings_rob,
 webflo, lwalley, Arlina, m4olivei, sylus, frega, Jacine: Support entity
 revision references

---
 config/schema/inline_entity_form.schema.yml   |   6 +
 src/Element/InlineEntityForm.php              |  17 +-
 .../FieldWidget/InlineEntityFormBase.php      |  11 +
 .../FieldWidget/InlineEntityFormComplex.php   |   3 +-
 .../FieldWidget/InlineEntityFormSimple.php    |   3 +-
 ...ield_override.node.err_level_1.promote.yml |  21 ++
 ...ield_override.node.err_level_2.promote.yml |  21 ++
 ...ield_override.node.err_level_3.promote.yml |  21 ++
 ..._form_display.node.err_level_1.default.yml |  62 +++++
 ..._form_display.node.err_level_2.default.yml |  38 +++
 ..._form_display.node.err_level_3.default.yml |  23 ++
 ..._view_display.node.err_level_1.default.yml |  34 +++
 ...y_view_display.node.err_level_1.teaser.yml |  16 ++
 ..._view_display.node.err_level_2.default.yml |  25 ++
 ...y_view_display.node.err_level_2.teaser.yml |  16 ++
 ..._view_display.node.err_level_3.default.yml |  15 +
 ...y_view_display.node.err_level_3.teaser.yml |  16 ++
 ...level_1.field_level_2_entity_no_bundle.yml |  27 ++
 ...d.node.err_level_1.field_level_2_items.yml |  29 ++
 ...d.node.err_level_2.field_level_3_items.yml |  29 ++
 ...ge.node.field_level_2_entity_no_bundle.yml |  21 ++
 ...field.storage.node.field_level_2_items.yml |  19 ++
 ...field.storage.node.field_level_3_items.yml |  19 ++
 .../config/optional/node.type.err_level_1.yml |   9 +
 .../config/optional/node.type.err_level_2.yml |   9 +
 .../config/optional/node.type.err_level_3.yml |   9 +
 .../ComplexWidgetRevisionsTest.php            | 258 ++++++++++++++++++
 27 files changed, 773 insertions(+), 4 deletions(-)
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_1.promote.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_2.promote.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_3.promote.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_1.default.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_2.default.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_3.default.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.default.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.teaser.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.default.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.teaser.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.default.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.teaser.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_entity_no_bundle.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_items.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_2.field_level_3_items.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_entity_no_bundle.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_items.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_3_items.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/node.type.err_level_1.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/node.type.err_level_2.yml
 create mode 100644 tests/modules/inline_entity_form_test/config/optional/node.type.err_level_3.yml
 create mode 100644 tests/src/FunctionalJavascript/ComplexWidgetRevisionsTest.php

diff --git a/config/schema/inline_entity_form.schema.yml b/config/schema/inline_entity_form.schema.yml
index aef7d46..801e132 100644
--- a/config/schema/inline_entity_form.schema.yml
+++ b/config/schema/inline_entity_form.schema.yml
@@ -31,6 +31,9 @@ field.widget.settings.inline_entity_form_simple:
     collapsed:
       type: boolean
       label: "Collapsed by default"
+    revision:
+      type: boolean
+      label: "Create new revision"
 
 field.widget.settings.inline_entity_form_complex:
   type: mapping
@@ -66,3 +69,6 @@ field.widget.settings.inline_entity_form_complex:
     collapsed:
       type: boolean
       label: "Collapsed by default"
+    revision:
+      type: boolean
+      label: "Create new revision"
diff --git a/src/Element/InlineEntityForm.php b/src/Element/InlineEntityForm.php
index 0fbe233..7de4012 100644
--- a/src/Element/InlineEntityForm.php
+++ b/src/Element/InlineEntityForm.php
@@ -3,8 +3,8 @@
 namespace Drupal\inline_entity_form\Element;
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\RevisionLogInterface;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Render\Element;
 use Drupal\Core\Render\Element\RenderElement;
 use Drupal\inline_entity_form\ElementSubmit;
 use Drupal\inline_entity_form\TranslationHelper;
@@ -45,6 +45,8 @@ class InlineEntityForm extends RenderElement {
       '#default_value' => NULL,
       // The form mode used to display the entity form.
       '#form_mode' => 'default',
+      // Will create a new revision if set to TRUE.
+      '#revision' => FALSE,
       // Will save entity on submit if set to TRUE.
       '#save_entity' => TRUE,
       // 'add', 'edit' or 'duplicate'.
@@ -97,6 +99,7 @@ class InlineEntityForm extends RenderElement {
       throw new \InvalidArgumentException('The inline_entity_form #default_value property must be an entity object.');
     }
 
+    $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_form['#entity_type']);
     if (empty($entity_form['#ief_id'])) {
       $entity_form['#ief_id'] = \Drupal::service('uuid')->generate();
     }
@@ -106,7 +109,6 @@ class InlineEntityForm extends RenderElement {
     }
     else {
       // This is an add operation, create a new entity.
-      $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_form['#entity_type']);
       $storage = \Drupal::entityTypeManager()->getStorage($entity_form['#entity_type']);
       $values = [];
       if ($langcode_key = $entity_type->getKey('langcode')) {
@@ -132,6 +134,17 @@ class InlineEntityForm extends RenderElement {
     $entity_form['#entity'] = TranslationHelper::prepareEntity($entity_form['#entity'], $form_state);
     $entity_form['#translating'] = TranslationHelper::isTranslating($form_state) && $entity_form['#entity']->isTranslatable();
 
+    // Handle revisioning if the entity supports it.
+    if ($entity_type->isRevisionable() && $entity_form['#revision']) {
+      $entity_form['#entity']->setNewRevision($entity_form['#revision']);
+
+      // @see \Drupal\Core\Entity\ContentEntityForm::buildEntity
+      if ($entity_form['#entity'] instanceof RevisionLogInterface) {
+        $entity_form['#entity']->setRevisionUserId(\Drupal::currentUser()->id());
+        $entity_form['#entity']->setRevisionCreationTime(\Drupal::time()->getRequestTime());
+      }
+    }
+
     $inline_form_handler = static::getInlineFormHandler($entity_form['#entity_type']);
     $entity_form = $inline_form_handler->entityForm($entity_form, $form_state);
     // The form element can't rely on inline_entity_form_form_alter() calling
diff --git a/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php b/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php
index 5598be4..fc55971 100644
--- a/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php
+++ b/src/Plugin/Field/FieldWidget/InlineEntityFormBase.php
@@ -190,6 +190,7 @@ abstract class InlineEntityFormBase extends WidgetBase implements ContainerFacto
   public static function defaultSettings() {
     return [
       'form_mode' => 'default',
+      'revision' => FALSE,
       'override_labels' => FALSE,
       'label_singular' => '',
       'label_plural' => '',
@@ -212,6 +213,11 @@ abstract class InlineEntityFormBase extends WidgetBase implements ContainerFacto
       '#options' => $this->entityDisplayRepository->getFormModeOptions($entity_type_id),
       '#required' => TRUE,
     ];
+    $element['revision'] = [
+      '#type' => 'checkbox',
+      '#title' => $this->t('Create new revision'),
+      '#default_value' => $this->getSetting('revision'),
+    ];
     $element['override_labels'] = [
       '#type' => 'checkbox',
       '#title' => $this->t('Override labels'),
@@ -278,6 +284,10 @@ abstract class InlineEntityFormBase extends WidgetBase implements ContainerFacto
       $summary[] = $this->t('Default labels are used.');
     }
 
+    if ($this->getSetting('revision')) {
+      $summary[] = $this->t('Create new revision');
+    }
+
     if ($this->getSetting('collapsible')) {
       $summary[] = $this->t($this->getSetting('collapsed') ? 'Collapsible, collapsed by default' : 'Collapsible');
     }
@@ -395,6 +405,7 @@ abstract class InlineEntityFormBase extends WidgetBase implements ContainerFacto
       '#default_value' => $entity,
       '#op' => $operation,
       '#form_mode' => $this->getSetting('form_mode'),
+      '#revision' => $this->getSetting('revision'),
       '#save_entity' => FALSE,
       '#ief_row_delta' => $delta,
       // Used by Field API and controller methods to find the relevant
diff --git a/src/Plugin/Field/FieldWidget/InlineEntityFormComplex.php b/src/Plugin/Field/FieldWidget/InlineEntityFormComplex.php
index 6b073da..913a1a9 100644
--- a/src/Plugin/Field/FieldWidget/InlineEntityFormComplex.php
+++ b/src/Plugin/Field/FieldWidget/InlineEntityFormComplex.php
@@ -25,7 +25,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
  *   id = "inline_entity_form_complex",
  *   label = @Translation("Inline entity form - Complex"),
  *   field_types = {
- *     "entity_reference"
+ *     "entity_reference",
+ *     "entity_reference_revisions",
  *   },
  *   multiple_values = true
  * )
diff --git a/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php b/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
index cc19ae8..a654660 100644
--- a/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
+++ b/src/Plugin/Field/FieldWidget/InlineEntityFormSimple.php
@@ -18,7 +18,8 @@ use Drupal\inline_entity_form\TranslationHelper;
  *   id = "inline_entity_form_simple",
  *   label = @Translation("Inline entity form - Simple"),
  *   field_types = {
- *     "entity_reference"
+ *     "entity_reference",
+ *     "entity_reference_revisions",
  *   },
  *   multiple_values = false
  * )
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_1.promote.yml b/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_1.promote.yml
new file mode 100644
index 0000000..4ddf2df
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_1.promote.yml
@@ -0,0 +1,21 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - node.type.err_level_1
+id: node.err_level_1.promote
+field_name: promote
+entity_type: node
+bundle: err_level_1
+label: 'Promoted to front page'
+description: ''
+required: false
+translatable: true
+default_value:
+  -
+    value: 0
+default_value_callback: ''
+settings:
+  on_label: 'On'
+  off_label: 'Off'
+field_type: boolean
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_2.promote.yml b/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_2.promote.yml
new file mode 100644
index 0000000..cb90dff
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_2.promote.yml
@@ -0,0 +1,21 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - node.type.err_level_2
+id: node.err_level_2.promote
+field_name: promote
+entity_type: node
+bundle: err_level_2
+label: 'Promoted to front page'
+description: ''
+required: false
+translatable: true
+default_value:
+  -
+    value: 0
+default_value_callback: ''
+settings:
+  on_label: 'On'
+  off_label: 'Off'
+field_type: boolean
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_3.promote.yml b/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_3.promote.yml
new file mode 100644
index 0000000..39c23b6
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.base_field_override.node.err_level_3.promote.yml
@@ -0,0 +1,21 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - node.type.err_level_3
+id: node.err_level_3.promote
+field_name: promote
+entity_type: node
+bundle: err_level_3
+label: 'Promoted to front page'
+description: ''
+required: false
+translatable: true
+default_value:
+  -
+    value: 0
+default_value_callback: ''
+settings:
+  on_label: 'On'
+  off_label: 'Off'
+field_type: boolean
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_1.default.yml b/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_1.default.yml
new file mode 100644
index 0000000..3228408
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_1.default.yml
@@ -0,0 +1,62 @@
+langcode: en
+status: true
+dependencies:
+  config:
+    - field.field.node.err_level_1.field_level_2_entity_no_bundle
+    - field.field.node.err_level_1.field_level_2_items
+    - node.type.err_level_1
+  module:
+    - inline_entity_form
+id: node.err_level_1.default
+targetEntityType: node
+bundle: err_level_1
+mode: default
+content:
+  field_level_2_entity_no_bundle:
+    weight: 32
+    settings:
+      form_mode: compact
+      revision: true
+      label_singular: ''
+      label_plural: ''
+      allow_new: true
+      match_operator: CONTAINS
+      override_labels: false
+      collapsible: false
+      collapsed: false
+      allow_existing: false
+      allow_duplicate: false
+    third_party_settings: {  }
+    type: inline_entity_form_complex
+    region: content
+  field_level_2_items:
+    weight: 31
+    settings:
+      match_operator: CONTAINS
+      form_mode: default
+      override_labels: false
+      label_singular: ''
+      label_plural: ''
+      allow_new: true
+      allow_existing: false
+      revision: true
+      collapsible: false
+      collapsed: false
+      allow_duplicate: false
+    third_party_settings: {  }
+    type: inline_entity_form_complex
+    region: content
+  title:
+    type: string_textfield
+    weight: -5
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+    region: content
+hidden:
+  created: true
+  path: true
+  promote: true
+  sticky: true
+  uid: true
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_2.default.yml b/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_2.default.yml
new file mode 100644
index 0000000..849b2b4
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_2.default.yml
@@ -0,0 +1,38 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - field.field.node.err_level_2.field_level_3_items
+    - node.type.err_level_2
+  module:
+    - inline_entity_form
+id: node.err_level_2.default
+targetEntityType: node
+bundle: err_level_2
+mode: default
+content:
+  field_level_3_items:
+    weight: 1
+    settings:
+      match_operator: CONTAINS
+      form_mode: default
+      override_labels: false
+      label_singular: ''
+      label_plural: ''
+      allow_new: true
+      allow_existing: false
+    third_party_settings: {  }
+    type: inline_entity_form_complex
+  title:
+    type: string_textfield
+    weight: 0
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+hidden:
+  created: true
+  path: true
+  promote: true
+  sticky: true
+  uid: true
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_3.default.yml b/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_3.default.yml
new file mode 100644
index 0000000..7d94d96
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.entity_form_display.node.err_level_3.default.yml
@@ -0,0 +1,23 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - node.type.err_level_3
+id: node.err_level_3.default
+targetEntityType: node
+bundle: err_level_3
+mode: default
+content:
+  title:
+    type: string_textfield
+    weight: -5
+    settings:
+      size: 60
+      placeholder: ''
+    third_party_settings: {  }
+hidden:
+  created: true
+  path: true
+  promote: true
+  sticky: true
+  uid: true
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.default.yml b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.default.yml
new file mode 100644
index 0000000..b3de56d
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.default.yml
@@ -0,0 +1,34 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - field.field.node.err_level_1.field_level_2_items
+    - node.type.err_level_1
+  module:
+    - entity_reference_revisions
+    - user
+id: node.err_level_1.default
+targetEntityType: node
+bundle: err_level_1
+mode: default
+content:
+  field_level_2_entity_no_bundle:
+    weight: 102
+    label: above
+    settings:
+      view_mode: default
+      link: ''
+    third_party_settings: {  }
+    type: entity_reference_revisions_entity_view
+    region: content
+  field_level_2_items:
+    weight: 101
+    label: above
+    settings:
+      view_mode: default
+      link: ''
+    third_party_settings: {  }
+    type: entity_reference_revisions_entity_view
+  links:
+    weight: 100
+hidden: {  }
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.teaser.yml b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.teaser.yml
new file mode 100644
index 0000000..ea334e8
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_1.teaser.yml
@@ -0,0 +1,16 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - core.entity_view_mode.node.teaser
+    - node.type.err_level_1
+  module:
+    - user
+id: node.err_level_1.teaser
+targetEntityType: node
+bundle: err_level_1
+mode: teaser
+content:
+  links:
+    weight: 100
+hidden: {  }
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.default.yml b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.default.yml
new file mode 100644
index 0000000..7a2e001
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.default.yml
@@ -0,0 +1,25 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - field.field.node.err_level_2.field_level_3_items
+    - node.type.err_level_2
+  module:
+    - entity_reference_revisions
+    - user
+id: node.err_level_2.default
+targetEntityType: node
+bundle: err_level_2
+mode: default
+content:
+  field_level_3_items:
+    weight: 101
+    label: above
+    settings:
+      view_mode: default
+      link: ''
+    third_party_settings: {  }
+    type: entity_reference_revisions_entity_view
+  links:
+    weight: 100
+hidden: {  }
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.teaser.yml b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.teaser.yml
new file mode 100644
index 0000000..8ccdf15
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_2.teaser.yml
@@ -0,0 +1,16 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - core.entity_view_mode.node.teaser
+    - node.type.err_level_2
+  module:
+    - user
+id: node.err_level_2.teaser
+targetEntityType: node
+bundle: err_level_2
+mode: teaser
+content:
+  links:
+    weight: 100
+hidden: {  }
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.default.yml b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.default.yml
new file mode 100644
index 0000000..d3de6a5
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.default.yml
@@ -0,0 +1,15 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - node.type.err_level_3
+  module:
+    - user
+id: node.err_level_3.default
+targetEntityType: node
+bundle: err_level_3
+mode: default
+content:
+  links:
+    weight: 100
+hidden: {  }
diff --git a/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.teaser.yml b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.teaser.yml
new file mode 100644
index 0000000..c119fd3
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/core.entity_view_display.node.err_level_3.teaser.yml
@@ -0,0 +1,16 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - core.entity_view_mode.node.teaser
+    - node.type.err_level_3
+  module:
+    - user
+id: node.err_level_3.teaser
+targetEntityType: node
+bundle: err_level_3
+mode: teaser
+content:
+  links:
+    weight: 100
+hidden: {  }
diff --git a/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_entity_no_bundle.yml b/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_entity_no_bundle.yml
new file mode 100644
index 0000000..5906fff
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_entity_no_bundle.yml
@@ -0,0 +1,27 @@
+uuid: 616ca481-7579-4873-aee6-6aaf74375d7b
+langcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_level_2_entity_no_bundle
+    - node.type.err_level_1
+  module:
+    - entity_reference_revisions
+id: node.err_level_1.field_level_2_entity_no_bundle
+field_name: field_level_2_entity_no_bundle
+entity_type: node
+bundle: err_level_1
+label: 'Test entity no bundle'
+description: ''
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: 'default:entity_test_no_bundle'
+  handler_settings:
+    target_bundles: null
+    sort:
+      field: _none
+    auto_create: false
+field_type: entity_reference_revisions
diff --git a/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_items.yml b/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_items.yml
new file mode 100644
index 0000000..025d09c
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_1.field_level_2_items.yml
@@ -0,0 +1,29 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_level_2_items
+    - node.type.err_level_1
+    - node.type.err_level_2
+  module:
+    - entity_reference_revisions
+id: node.err_level_1.field_level_2_items
+field_name: field_level_2_items
+entity_type: node
+bundle: err_level_1
+label: 'Level 2 Items'
+description: ''
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: 'default:node'
+  handler_settings:
+    target_bundles:
+      err_level_2: err_level_2
+    sort:
+      field: _none
+    auto_create: false
+    auto_create_bundle: ''
+field_type: entity_reference_revisions
diff --git a/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_2.field_level_3_items.yml b/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_2.field_level_3_items.yml
new file mode 100644
index 0000000..e285cec
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/field.field.node.err_level_2.field_level_3_items.yml
@@ -0,0 +1,29 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_level_3_items
+    - node.type.err_level_2
+    - node.type.err_level_3
+  module:
+    - entity_reference_revisions
+id: node.err_level_2.field_level_3_items
+field_name: field_level_3_items
+entity_type: node
+bundle: err_level_2
+label: 'Level 3 Items'
+description: ''
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: 'default:node'
+  handler_settings:
+    target_bundles:
+      err_level_3: err_level_3
+    sort:
+      field: _none
+    auto_create: false
+    auto_create_bundle: ''
+field_type: entity_reference_revisions
diff --git a/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_entity_no_bundle.yml b/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_entity_no_bundle.yml
new file mode 100644
index 0000000..bb09a02
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_entity_no_bundle.yml
@@ -0,0 +1,21 @@
+uuid: 2111cc32-c893-4518-864a-74aed74266c7
+langcode: en
+status: true
+dependencies:
+  module:
+    - entity_reference_revisions
+    - entity_test
+    - node
+id: node.field_level_2_entity_no_bundle
+field_name: field_level_2_entity_no_bundle
+entity_type: node
+type: entity_reference_revisions
+settings:
+  target_type: entity_test_no_bundle
+module: entity_reference_revisions
+locked: false
+cardinality: 1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false
diff --git a/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_items.yml b/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_items.yml
new file mode 100644
index 0000000..1070cc3
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_2_items.yml
@@ -0,0 +1,19 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  module:
+    - entity_reference_revisions
+    - node
+id: node.field_level_2_items
+field_name: field_level_2_items
+entity_type: node
+type: entity_reference_revisions
+settings:
+  target_type: node
+module: entity_reference_revisions
+locked: false
+cardinality: -1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false
diff --git a/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_3_items.yml b/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_3_items.yml
new file mode 100644
index 0000000..757c48a
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/field.storage.node.field_level_3_items.yml
@@ -0,0 +1,19 @@
+trimIefIdParentslangcode: en
+status: true
+dependencies:
+  module:
+    - entity_reference_revisions
+    - node
+id: node.field_level_3_items
+field_name: field_level_3_items
+entity_type: node
+type: entity_reference_revisions
+settings:
+  target_type: node
+module: entity_reference_revisions
+locked: false
+cardinality: -1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false
diff --git a/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_1.yml b/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_1.yml
new file mode 100644
index 0000000..4865eb9
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_1.yml
@@ -0,0 +1,9 @@
+trimIefIdParentslangcode: en
+status: true
+name: 'Entity Reference Revisions (Level 1)'
+type: err_level_1
+description: 'Top level content type with an entity_reference_revisions field type to another content type.'
+help: ''
+new_revision: true
+preview_mode: 1
+display_submitted: false
diff --git a/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_2.yml b/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_2.yml
new file mode 100644
index 0000000..289dc9d
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_2.yml
@@ -0,0 +1,9 @@
+trimIefIdParentslangcode: en
+status: true
+name: 'Entity Reference Revisions (Level 2)'
+type: err_level_2
+description: 'Second level content type with an entity_reference_revisions field type to another content type.'
+help: ''
+new_revision: true
+preview_mode: 1
+display_submitted: false
diff --git a/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_3.yml b/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_3.yml
new file mode 100644
index 0000000..b22f916
--- /dev/null
+++ b/tests/modules/inline_entity_form_test/config/optional/node.type.err_level_3.yml
@@ -0,0 +1,9 @@
+trimIefIdParentslangcode: en
+status: true
+name: 'Entity Reference Revisions (Level 3)'
+type: err_level_3
+description: 'Third level content type.'
+help: ''
+new_revision: true
+preview_mode: 1
+display_submitted: false
diff --git a/tests/src/FunctionalJavascript/ComplexWidgetRevisionsTest.php b/tests/src/FunctionalJavascript/ComplexWidgetRevisionsTest.php
new file mode 100644
index 0000000..c54752d
--- /dev/null
+++ b/tests/src/FunctionalJavascript/ComplexWidgetRevisionsTest.php
@@ -0,0 +1,258 @@
+<?php
+
+namespace Drupal\inline_entity_form\Tests;
+
+use Drupal\Tests\inline_entity_form\FunctionalJavascript\InlineEntityFormTestBase;
+
+/**
+ * IEF complex entity reference revisions tests.
+ *
+ * @group inline_entity_form
+ */
+class ComplexWidgetRevisionsTest extends InlineEntityFormTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'field',
+    'field_ui',
+    'entity_test',
+    'entity_reference_revisions',
+    'inline_entity_form_test',
+  ];
+
+  /**
+   * URL to add new content.
+   *
+   * @var string
+   */
+  protected $formContentAddUrl;
+
+  /**
+   * Prepares environment for testing.
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->user = $this->createUser([
+      'administer entity_test__without_bundle content',
+      'administer entity_test content',
+      'administer content types',
+      'create err_level_1 content',
+      'edit any err_level_1 content',
+      'delete any err_level_1 content',
+      'create err_level_2 content',
+      'edit any err_level_2 content',
+      'delete any err_level_2 content',
+      'create err_level_3 content',
+      'edit any err_level_3 content',
+      'delete any err_level_3 content',
+      'view own unpublished content',
+    ]);
+    $this->drupalLogin($this->user);
+
+    $this->formContentAddUrl = 'node/add/err_level_1';
+  }
+
+  /**
+   * Tests saving entity reference revisions' field types at depth.
+   */
+  public function testRevisionsAtDepth() {
+    $this->drupalGet($this->formContentAddUrl);
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+
+    // Open up level 2 and 3 IEF forms.
+    $this->assertNotEmpty($lvl_2_add_new_node_button = $assert_session->elementExists('css', 'input[data-drupal-selector="edit-field-level-2-items-actions-ief-add"]'));
+    $lvl_2_add_new_node_button->press();
+    $this->assertNotEmpty($lvl_3_add_new_node_button = $assert_session->waitForElement('css', 'input[data-drupal-selector="edit-field-level-2-items-form-inline-entity-form-field-level-3-items-actions-ief-add"]'));
+    $lvl_3_add_new_node_button->press();
+
+    // Fill in and save level 3 IEF form.
+    $lvl_3_title_field = 'field_level_2_items[form][inline_entity_form][field_level_3_items][form][inline_entity_form][title][0][value]';
+    $lvl_3_create_node_button = 'input[data-drupal-selector="edit-field-level-2-items-form-inline-entity-form-field-level-3-items-form-inline-entity-form-actions-ief-add-save"]';
+    $this->assertNotEmpty($assert_session->waitForField($lvl_3_title_field));
+    $assert_session->fieldExists($lvl_3_title_field)->setValue('Level 3');
+    $assert_session->elementExists('css', $lvl_3_create_node_button)->press();
+    $lvl_3_edit_button = 'input[data-drupal-selector="edit-field-level-2-items-form-inline-entity-form-field-level-3-items-entities-0-actions-ief-entity-edit"]';
+    $this->assertNotEmpty($assert_session->waitForElement('css', $lvl_3_edit_button));
+
+    // Fill in and save level 2 IEF form.
+    $lvl_2_title_field = 'field_level_2_items[form][inline_entity_form][title][0][value]';
+    $lvl_2_create_node_button = 'input[data-drupal-selector="edit-field-level-2-items-form-inline-entity-form-actions-ief-add-save"]';
+    $assert_session->fieldExists($lvl_2_title_field)->setValue('Level 2');
+    $assert_session->elementExists('css', $lvl_2_create_node_button)->press();
+    $lvl_2_edit_button = 'input[data-drupal-selector="edit-field-level-2-items-entities-0-actions-ief-entity-edit"]';
+    $this->assertNotEmpty($assert_session->waitForElement('css', $lvl_2_edit_button));
+
+    // Save the top level entity.
+    $page->fillField('title[0][value]', 'Level 1');
+    $page->pressButton('Save');
+
+    // Re-edit the created node to test for revisions.
+    $node = $this->drupalGetNodeByTitle('Level 1');
+    $this->drupalGet('node/' . $node->id() . '/edit');
+
+    // Open up level 2 and 3 IEF forms.
+    $this->assertNotEmpty($lvl_2_edit_node_button = $assert_session->elementExists('css', $lvl_2_edit_button));
+    $lvl_2_edit_node_button->press();
+    $lvl_3_edit_button = 'input[data-drupal-selector="edit-field-level-2-items-form-inline-entity-form-entities-0-form-field-level-3-items-entities-0-actions-ief-entity-edit"]';
+    $this->assertNotEmpty($lvl_3_edit_node_button = $assert_session->waitForElement('css', $lvl_3_edit_button));
+    $lvl_3_edit_node_button->press();
+
+    // Change level 3 IEF node title.
+    $lvl_3_title_field = 'field_level_2_items[form][inline_entity_form][entities][0][form][field_level_3_items][form][inline_entity_form][entities][0][form][title][0][value]';
+    $this->assertNotEmpty($assert_session->waitForField($lvl_3_title_field));
+    $assert_session->fieldExists($lvl_3_title_field)->setValue('Level 3.1');
+    $lvl_3_update_node_button = 'input[data-drupal-selector="edit-field-level-2-items-form-inline-entity-form-entities-0-form-field-level-3-items-form-inline-entity-form-entities-0-form-actions-ief-edit-save"]';
+    $assert_session->elementExists('css', $lvl_3_update_node_button)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('css', $lvl_3_edit_button));
+
+    // Change level 2 IEF node title.
+    $lvl_2_title_field = 'field_level_2_items[form][inline_entity_form][entities][0][form][title][0][value]';
+    $assert_session->fieldExists($lvl_2_title_field)->setValue('Level 2.1');
+    $lvl_2_update_node_button = 'input[data-drupal-selector="edit-field-level-2-items-form-inline-entity-form-entities-0-form-actions-ief-edit-save"]';
+    $assert_session->elementExists('css', $lvl_2_update_node_button)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('css', $lvl_2_edit_button));
+
+    // Save the top level entity.
+    $page->fillField('title[0][value]', 'Level 1.1');
+    $page->pressButton('Save');
+
+    // Assert that the entities are correctly saved.
+    $assert_session->pageTextContains('Level 1.1 has been updated.');
+    $assert_session->pageTextContains('Level 2.1');
+    $assert_session->pageTextContains('Level 3.1');
+
+    // Load the current revision id of the Level 2 node.
+    $node_level_2 = $this->drupalGetNodeByTitle('Level 2.1');
+    $node_level_2_vid = $node_level_2->getLoadedRevisionId();
+
+    // Load the current revision id of the Level 3 node.
+    $node_level_3 = $this->drupalGetNodeByTitle('Level 3.1');
+    $node_level_3_vid = $node_level_3->getLoadedRevisionId();
+
+    // Re-edit the created node to test for revisions.
+    $this->drupalGet('node/' . $node->id() . '/edit');
+
+    // Open up level 2 and 3 IEF forms.
+    $this->assertNotEmpty($lvl_2_edit_node_button = $assert_session->elementExists('css', $lvl_2_edit_button));
+    $lvl_2_edit_node_button->press();
+    $this->assertNotEmpty($lvl_3_edit_node_button = $assert_session->waitForElement('css', $lvl_3_edit_button));
+    $lvl_3_edit_node_button->press();
+
+    // Change level 3 IEF node title.
+    $this->assertNotEmpty($assert_session->waitForField($lvl_3_title_field));
+    $assert_session->fieldExists($lvl_3_title_field)->setValue('Level 3.2');
+    $assert_session->elementExists('css', $lvl_3_update_node_button)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('css', $lvl_3_edit_button));
+
+    // Change level 2 IEF node title.
+    $assert_session->fieldExists($lvl_2_title_field)->setValue('Level 2.2');
+    $assert_session->elementExists('css', $lvl_2_update_node_button)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('css', $lvl_2_edit_button));;
+
+    // Save the top level entity.
+    $page->fillField('title[0][value]', 'Level 1.2');
+    $page->pressButton('Save');
+
+    // Assert that the entities are correctly saved.
+    $assert_session->pageTextContains('Level 1.2 has been updated.');
+    $assert_session->pageTextContains('Level 2.2');
+    $assert_session->pageTextContains('Level 3.2');
+
+    // Clear node cache.
+    $this->container->get('entity_type.manager')
+      ->getStorage('node')
+      ->resetCache();
+
+    // Load the current revision id of the Level 2 node.
+    $node_level_2 = $this->drupalGetNodeByTitle('Level 2.2');
+    $node_level_2_vid_new = $node_level_2->getLoadedRevisionId();
+
+    // Assert that a new revision created.
+    $this->assertNotEqual($node_level_2_vid, $node_level_2_vid_new);
+
+    // Load the current revision id of the Level 3 node.
+    $node_level_3 = $this->drupalGetNodeByTitle('Level 3.2');
+    $node_level_3_vid_new = $node_level_3->getLoadedRevisionId();
+
+    // Assert that no new revision created.
+    $this->assertEqual($node_level_3_vid, $node_level_3_vid_new);
+  }
+
+  /**
+   * Tests saving entity revision with test entity that has no bundle.
+   */
+  public function testRevisionsWithTestEntityNoBundle() {
+    $this->drupalGet($this->formContentAddUrl);
+    $page = $this->getSession()->getPage();
+    $assert_session = $this->assertSession();
+
+    // Open up test entity with no bundle IEF form.
+    $this->assertNotEmpty($add_new_no_bundle_node_button = $assert_session->elementExists('css', 'input[data-drupal-selector="edit-field-level-2-entity-no-bundle-actions-ief-add"]'));
+    $add_new_no_bundle_node_button->press();
+    $no_bundle_create_node_button = 'input[data-drupal-selector="edit-field-level-2-entity-no-bundle-form-inline-entity-form-actions-ief-add-save"]';
+    $this->assertNotEmpty($assert_session->waitForElement('css', $no_bundle_create_node_button));
+
+    // Save level 2 test entity without bundle IEF form.
+    $no_bundle_title_field = 'field_level_2_entity_no_bundle[form][inline_entity_form][name][0][value]';
+    $assert_session->fieldExists($no_bundle_title_field)->setValue('Level 2 entity without bundle');
+    $assert_session->elementExists('css', $no_bundle_create_node_button)->press();
+    $no_bundle_node_edit_button = 'input[data-drupal-selector="edit-field-level-2-entity-no-bundle-entities-0-actions-ief-entity-edit"]';
+    $this->assertNotEmpty($assert_session->waitForElement('css', $no_bundle_node_edit_button));
+
+    // Save the top level entity.
+    $page->fillField('title[0][value]', 'Level 1');
+    $page->pressButton('Save');
+
+    // Assert that the entities are correctly saved.
+    $assert_session->pageTextContains('Level 1 has been created.');
+    $assert_session->pageTextContains('Level 2 entity without bundle');
+
+    // Load the new revision id of the entity.
+    $entity_no_bundle = $this->container->get('entity_type.manager')
+      ->getStorage('entity_test_no_bundle')
+      ->loadByProperties(['name' => 'Level 2 entity without bundle']);
+    $entity = reset($entity_no_bundle);
+    $entity_no_bundle_vid = $entity->getLoadedRevisionId();
+
+    // Re-edit the created node to test for revisions.
+    $node = $this->drupalGetNodeByTitle('Level 1');
+    $this->drupalGet('node/' . $node->id() . '/edit');
+
+    // Open up test entity with no bundle IEF form for editing.
+    $assert_session->elementExists('css', $no_bundle_node_edit_button)->press();
+    $no_bundle_update_node_button = 'input[data-drupal-selector="edit-field-level-2-entity-no-bundle-form-inline-entity-form-entities-0-form-actions-ief-edit-save"]';
+    $this->assertNotEmpty($assert_session->waitForElement('css', $no_bundle_update_node_button));
+
+    // Change test entity with no bundle title.
+    $assert_session->fieldExists('field_level_2_entity_no_bundle[form][inline_entity_form][entities][0][form][name][0][value]')->setValue('Level 2.1 entity without bundle');
+    $assert_session->elementExists('css', $no_bundle_update_node_button)->press();
+    $this->assertNotEmpty($assert_session->waitForElement('css', $no_bundle_node_edit_button));
+
+    // Save the top level entity.
+    $page->fillField('title[0][value]', 'Level 1.1');
+    $page->pressButton('Save');
+
+    // Assert that the entities are correctly saved.
+    $assert_session->pageTextContains('Level 1.1 has been updated.');
+    $assert_session->pageTextContains('Level 2.1 entity without bundle');
+
+    // Reload the new revision id of the entity.
+    $this->container->get('entity_type.manager')
+      ->getStorage('entity_test_no_bundle')
+      ->resetCache();
+    $entity_no_bundle = $this->container->get('entity_type.manager')
+      ->getStorage('entity_test_no_bundle')
+      ->load($entity->id());
+    $entity_no_bundle_vid_new = $entity_no_bundle->getLoadedRevisionId();
+
+    // Assert that new revision was created.
+    $this->assertNotEqual($entity_no_bundle_vid, $entity_no_bundle_vid_new);
+  }
+
+}
-- 
2.20.1
