Problem/Motivation

If an Entity Reference field references one bundle, the checkbox "Create referenced entities if they don't already exist" is checked, and an "Autocomplete" widget is chosen, then users can create new entities for that bundle by simply typing in a new label into the text field. However if more then one bundle is referenced, then no entities are added.

Proposed resolution

Move the auto_create setting into EntityReferenceAutocompleteWidget widget settings because the widget should be in business of doing "auto-create".

In widget settings, let the site builder choose a target bundle where the auto-created entities to be stored when the entity reference field is configured to use more than one bundle as destination and auto-creation of entities is enabled.

Remaining tasks

None.

User interface changes

On the field config page: /admin/structure/types/manage/article/fields/{entity}.{bundle}.{field}

Only one vocabulary as destination

Two vocabularies as destination but no auto-creation

Two vocabularies as destination with auto-creation

JavaScript disabled

API changes

Remove auto_create setting from selection handler settings. Two new widget settings: auto_create and auto_create_bundle for EntityReferenceAutocompleteWidget widgets.

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue category Bug because it breaks a functionality: entity auto-creation.
Issue priority Major because the entity auto-creation doesn't work when multiple bundles are selected as target
Disruption Disruption handled by hook_update_N() implementation.
CommentFileSizeAuthor
#167 interdiff.txt4.81 KBamateescu
#167 2412569-167.patch30.94 KBamateescu
#156 interdiff.txt3.69 KBamateescu
#156 2412569-156.patch30.99 KBamateescu
#150 interdiff.txt843 bytesamateescu
#150 2412569-150.patch30.99 KBamateescu
#148 interdiff.txt8.24 KBamateescu
#148 2412569-148.patch30.99 KBamateescu
#144 allow_setting_the-2412569-144.patch22.75 KBjibran
#140 interdiff.txt966 bytesamateescu
#140 2412569-140.patch22.75 KBamateescu
#133 2412569-133.patch22.73 KBamateescu
#128 2412569-128.patch22.73 KBamateescu
#126 2412569-126.patch22.82 KBamateescu
#123 2412569-123.patch22.81 KByched
#114 interdiff.txt3.77 KBamateescu
#114 2412569-114-plus-1978714.patch41.73 KBamateescu
#114 2412569-114-do-not-test.patch22.81 KBamateescu
#111 interdiff.txt1.75 KBamateescu
#111 2412569-111-plus-1978714.patch42.14 KBamateescu
#111 2412569-111-do-not-test.patch21.82 KBamateescu
#107 2412569-plus-1978714.patch41.58 KBamateescu
#107 2412569-107-do-not-test.patch21.26 KBamateescu
#91 interdiff.txt670 bytesclaudiu.cristea
#91 2412569-91.patch59.47 KBclaudiu.cristea
#88 interdiff.txt5.28 KBclaudiu.cristea
#88 2412569-88.patch59.94 KBclaudiu.cristea
#86 2412569-86.patch57.49 KBclaudiu.cristea
#86 interdiff.txt870 bytesclaudiu.cristea
#84 2412569-84.patch57.4 KBclaudiu.cristea
#80 target_bundle_for-2412569-80.patch57.31 KBclaudiu.cristea
#80 interdiff.txt34.08 KBclaudiu.cristea
#79 interdiff.txt5.53 KBclaudiu.cristea
#79 target_bundle_for-2412569-79.patch53.45 KBclaudiu.cristea
#77 interdiff.txt7.15 KBclaudiu.cristea
#77 target_bundle_for-2412569-77.patch53.75 KBclaudiu.cristea
#75 interdiff.txt7.64 KBclaudiu.cristea
#75 target_bundle_for-2412569-75.patch51.67 KBclaudiu.cristea
#73 interdiff.txt21.09 KBclaudiu.cristea
#73 target_bundle_for-2412569-73.patch45.28 KBclaudiu.cristea
#71 many-bundels.png155.5 KBclaudiu.cristea
#71 one-bundle.png181.91 KBclaudiu.cristea
#70 interdiff.txt29.62 KBclaudiu.cristea
#70 target_bundle_for-2412569-70.patch24.2 KBclaudiu.cristea
#66 interdiff.txt15.17 KBclaudiu.cristea
#66 target_bundle_for-2412569-66.patch27.15 KBclaudiu.cristea
#59 interdiff.txt8.52 KBclaudiu.cristea
#59 target_bundle_for-2412569-59.patch24.1 KBclaudiu.cristea
#51 interdiff.txt3.32 KBclaudiu.cristea
#51 target_bundle_for-2412569-51.patch23.19 KBclaudiu.cristea
#49 interdiff.txt3.44 KBclaudiu.cristea
#49 target_bundle_for-2412569-49.patch22.35 KBclaudiu.cristea
#39 target_bundle_for-2412569-39.patch19.54 KBsiva_epari
#34 interdiff.txt14.87 KBclaudiu.cristea
#34 target_bundle_for-2412569-34.patch25.4 KBclaudiu.cristea
#31 interdiff.txt1.62 KBamateescu
#31 2412569-31.patch19.7 KBamateescu
#30 interdiff.txt600 bytesamateescu
#30 2412569-30.patch18.09 KBamateescu
#24 interdiff.txt5.97 KBclaudiu.cristea
#24 target_bundle_for-2412569-24.patch18.09 KBclaudiu.cristea
#19 interdiff.txt1.13 KBclaudiu.cristea
#19 target_bundle_for-2412569-19.patch17.42 KBclaudiu.cristea
#17 target_vocabulary_for-2412569-17.patch17.54 KBclaudiu.cristea
#17 interdiff.txt6.1 KBclaudiu.cristea
#15 interdiff.txt5.93 KBclaudiu.cristea
#15 target_vocabulary_for-2412569-15.patch17.38 KBclaudiu.cristea
#14 interdiff.txt2.06 KBclaudiu.cristea
#14 target_vocabulary_for-2412569-14.patch16.6 KBclaudiu.cristea
#12 interdiff.txt577 bytesamateescu
#12 2412569-12.patch16.58 KBamateescu
#10 2412569-10.patch16.02 KBamateescu
#9 target_vocabulary_for-2412569-9.patch16.74 KBclaudiu.cristea
#9 interdiff.txt3.52 KBclaudiu.cristea
#7 target_vocabulary_for-2412569-7.patch16.6 KBclaudiu.cristea
#7 interdiff.txt4.14 KBclaudiu.cristea
#5 no_js.png77.48 KBclaudiu.cristea
#5 two_vocabularies_with_auto_create.png110.22 KBclaudiu.cristea
#5 two_vocabularies.png45.11 KBclaudiu.cristea
#5 one_vocabulary.png44.82 KBclaudiu.cristea
#5 entity_reference_field-2412569-5.patch16.68 KBclaudiu.cristea

Comments

ifrik’s picture

jibran’s picture

amateescu’s picture

Yup, that issue had nothing to do with this bug.

jhedstrom’s picture

Issue tags: +Needs tests
claudiu.cristea’s picture

Title: Entity reference field does not add taxonomy terms when 2 vocabularies are referenced » Target vocabulary for auto-created taxonomy terms on entity reference with many destination vocabularies
Issue summary: View changes
Status: Active » Needs review
StatusFileSize
new16.68 KB
new44.82 KB
new45.11 KB
new110.22 KB
new77.48 KB

Patch.

Please credit @amateescu because he guided me in this issue.

amateescu’s picture

Issue tags: -Needs tests

Great work on the patch and the screenshots, thanks a lot @claudiu.cristea! I just found a few small things to complain about:

  1. +++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php
    @@ -129,9 +129,6 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    -      elseif ($entity_type_id == 'taxonomy_term') {
    -        $target_bundles_title = $this->t('Vocabularies');
    -      }
    
    +++ b/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
    @@ -39,14 +39,51 @@ public function entityQueryAlter(SelectInterface $query) {
    +    $form['target_bundles']['#title'] = $this->t('Vocabularies');
    

    Let's remove these changes and let #2452957: Remove node & taxonomy term hardcoding of bundle names in SelectionBase deal with them.

  2. +++ b/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php
    @@ -216,17 +217,64 @@ public function testAvailableFormatters() {
    +    // Create a new filed pointing to the first vocabulary.
    

    filed -> field :)

  3. +++ b/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
    @@ -39,14 +39,51 @@ public function entityQueryAlter(SelectInterface $query) {
    +    $form['target_bundles_update'] = [
    ...
    +    ];
    

    We should use the array() syntax here because it looks a bit weird when all the code around it is not converted to the [] syntax.

claudiu.cristea’s picture

StatusFileSize
new4.14 KB
new16.6 KB

I preferred to convert the rest of arrays in [] format because it doesn't increase the foot print too much.

amateescu’s picture

Sure, converting the rest of them to the [] syntax is also fine. I reviewed the patch once more and found a few other things to fix. Sorry for not catching them in the first review, I was just on my out of the room :/

  1. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
    @@ -146,21 +146,23 @@ public function massageFormValues(array $values, array $form, FormStateInterface
    +   * @throws \InvalidArgumentException
    

    We need to put some information about when that exception is thrown, in this case we can copy some parts of the comment just above it. Something like: "Thrown when the 'auto_create' and 'auto_create_bundle' settings are inconsistent."

  2. +++ b/core/modules/entity_reference/config/schema/entity_reference.schema.yml
    @@ -36,6 +36,9 @@ entity_reference.default.handler_settings:
    +      label: 'Vocabulary where auto-created taxonomy terms are stored.'
    

    Even though we expose this setting only on taxonomy term references for now, the setting is still generic so it should mention 'Bundle' instead of 'Vocabulary' -> "Bundle where auto-created entities are stored."

  3. +++ b/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php
    @@ -216,17 +217,64 @@ public function testAvailableFormatters() {
    +    // Expect that there's no 'auto_create_bundle' select.
    

    Really minor: 'select' -> 'selected' :)

  4. +++ b/core/modules/entity_reference/src/Tests/EntityReferenceAdminTest.php
    @@ -216,17 +217,64 @@ public function testAvailableFormatters() {
    +    // Check the second vocabulary as target.
    

    How about "Enable the second vocabulary as a target bundle."?

claudiu.cristea’s picture

StatusFileSize
new3.52 KB
new16.74 KB

Thank you for review.

amateescu’s picture

Status: Needs review » Reviewed & tested by the community
StatusFileSize
new16.02 KB

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 10: 2412569-10.patch, failed testing.

amateescu’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new16.58 KB
new577 bytes

That reroll was missing the schema addition, fixed it.

yched’s picture

+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
@@ -146,21 +146,25 @@ public function massageFormValues(array $values, array $form, FormStateInterface
+      // Otherwise use the target vocabulary stored in selection handler
+      // settings.
+      elseif (!$bundle = $this->getSelectionHandlerSetting('auto_create_bundle')) {
+        // If no bundle has been set as auto create target vocabulary means that
+        // there is an inconsistency in entity reference field settings.
+        throw new \InvalidArgumentException("Reference auto-create is enabled on multiple target vocabularies but 'auto_create_bundle' is not set.");

Seems wrong to talk about "vocabularies" in the generic ERAutocompleteWidget ?

+++ b/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
@@ -40,14 +40,50 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
+    $form['auto_create_bundle'] = [

Wondering: what's the reason why it is only TermSelection that can provide a UI for that otherwise generic (described in the generic entity_reference_selection config schema and used by the generic AutocompleteWidget) setting ?

claudiu.cristea’s picture

StatusFileSize
new16.6 KB
new2.06 KB

@yched,

Wondering: what's the reason why it is only TermSelection that can provide a UI for that otherwise generic (described in the generic entity_reference_selection config schema and used by the generic AutocompleteWidget) setting ?

I fully agree and I can move that in the generic level but I found this line (see the @todo) in TermSelection.php and I thought that maybe there are other reasons for limiting only to taxonomy term.

    // @todo: Currently allow auto-create only on taxonomy terms.
    $form['auto_create'] = [
      '#type' => 'checkbox',
      ...

Maybe @amateescu knows better why?

claudiu.cristea’s picture

StatusFileSize
new17.38 KB
new5.93 KB

@yched, @amateescu,

I expanded the auto-creation to all target entities. At least the manually testing was OK, let's see the bot.

Any comments on expanding the auto-creation capability to all types?

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 15: target_vocabulary_for-2412569-15.patch, failed testing.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new6.1 KB
new17.54 KB

Sorry! Interdiff still against #14 and comment from #15.

claudiu.cristea’s picture

Title: Target vocabulary for auto-created taxonomy terms on entity reference with many destination vocabularies » Target bundle for auto-created entity references with multiple target bundles

Change the title accordingly.

claudiu.cristea’s picture

StatusFileSize
new17.42 KB
new1.13 KB

Small fix in setting a default.

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

The only reason for restricting the 'autocreate' feature to taxonomy terms in the UI is that entity API was not in a very good shape at the time (read: mostly broken), so we wanted to have as few things that could break as possible :)

Expanding it to all entity types now seems like a good idea to me as well.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
@@ -146,21 +146,23 @@ public function massageFormValues(array $values, array $form, FormStateInterface
+        // If no bundle has been set as auto create target means that there is
+        // an inconsistency in entity reference field settings.
+        throw new \InvalidArgumentException("Reference auto-create is enabled on multiple target bundles but 'auto_create_bundle' is not set.");

This is not tested. Originally I though that would never occur. But I think it can so let's test it.

yched’s picture

Last nitpick while we're in there :

+++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php
@@ -201,13 +214,37 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
+  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
+    $form_state->unsetValue(['field', 'settings', 'handler_settings', 'target_bundles_update']);
+  }

Havinga validate callback that just ditches some of the submitted values looks a bit surprising. I'm sure there's a reason, but it might be worth a comment ?

amateescu’s picture

The reason is that we don't that value to end up in config :P

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new18.09 KB
new5.97 KB

Added/changed:

  • Test required in #21.
  • Comment required in #22.
  • Make use of already existing \Drupal\entity_reference\Tests\EntityReferenceTestTrait.
  • Renamed the 2 tests to be more generic. Dropped the reference to taxonomy in test name and comments.
jibran’s picture

  1. +++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php
    @@ -201,13 +214,39 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    +      $form['auto_create_bundle'] = array(
    

    This key is confusing i thought it means we are auto creating bundles, why would we do that? So maybe bundle_of_auto_create.

amateescu’s picture

If we're going to change that, I would prefer bundle_for_auto_create, but I also think the current name is fine :) Other opinions? :)

claudiu.cristea’s picture

@jibran, It might be confusing if you read it as a phrase but it's not in the logic of field config settings. In fact the key name is bundle but is namespaced with auto_create_* because is someting that belongs to that setting. Without auto_create ON the setting doesn't make sense. By this naming I wanted to tell that auto_create_bundle is dependant on auto_create. Read it as The bundle where we save when auto creating. I was tempted to add a auto_create_settings as array having a simple bundle key exactly as handler and handler_settings is doing. But that would bring an unnecessary level if nesting.

@amateescu, I addressed all points raised by @yched and @alexpott. If we can live with the new setting naming let's RTBC this :)

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

Agreed, let's do that.

yched’s picture

No strong opinion on the setting name. I see how the current name could be misleading, not sure it's worth losing the 'auto_create_' prefix pattern. So, the current works for me.

Minor :

+++ b/core/config/schema/core.data_types.schema.yml
@@ -776,6 +776,9 @@ entity_reference_selection:
+    auto_create_bundle:
+      type: string
+      label: 'Bundle where auto-created entities are stored.'

A bit approximative; striclty speaking, bundles are not storage locations. "Bundle assigned to the auto-created entities" ?

Can be fixed anytime in a quick followup if needed, so keeping at RTBC

amateescu’s picture

StatusFileSize
new18.09 KB
new600 bytes

Thanks, @yched! Let's avoid a "needs work" cycle for that :)

amateescu’s picture

StatusFileSize
new19.7 KB
new1.62 KB

@xjm pointed out in #1847596-267: Remove Taxonomy term reference field in favor of Entity reference that taxonomy_help() says:

You will also need to enable the Create referenced entities if they don't already exist option, and restrict the field to one vocabulary.

but the last part of the sentence is not true anymore after this patch, so we need to update it. I vote for simply removing that part because the UI is pretty straightforward in letting users know that they need to choose the target bundle in which to place auto-created entities.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

We could also change the config structure to

auto_create_entity:
  enabled: TRUE
  bundle: bundle_id

Which, in my opinion, is much clearer. However this is more of an API break. Setting to needs review to get feedback on this suggestion.

And wow is the entity reference field UI confusing. If you select "Taxonomy term" you don't get to choose the autocreate settings... you just get to limit it to a particular bundle. You have to choose "Other..." to be able to set this. Is there an issue to address this?

amateescu’s picture

I don't have any preference on the current config structure vs. the one proposed in #32. The nice thing about the current patch is that it's only an API addition though.

And wow is the entity reference field UI confusing. If you select "Taxonomy term" you don't get to choose the autocreate settings... you just get to limit it to a particular bundle. You have to choose "Other..." to be able to set this. Is there an issue to address this?

Yes, #1847596: Remove Taxonomy term reference field in favor of Entity reference will fix that :)

claudiu.cristea’s picture

StatusFileSize
new25.4 KB
new14.87 KB

I'm fine with this.

amateescu’s picture

I'm not sure about this... the interdiff looks mostly ok but I still think it's not really worth the API break, so I'm +1 to #31 and just "fine.. if everyone else wants it that much" on #34 :)

yched’s picture

Same as #35 :-)

alexpott’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

Okay as I wrote in #32 - we should discuss it. I agree that not breaking the API is probably the way to go here. Unfortunately this patch needs a reroll. So lets reroll #31.

Also we need to add a dependency on the bundle if it is a config entity.

alexpott’s picture

Re the dependency part of #37 - what happens atm if a bundle is deleted and it is used for auto create?

siva_epari’s picture

StatusFileSize
new19.54 KB

Patch from #31 rerolled.

amateescu’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll

Testing the patch first.

claudiu.cristea’s picture

amateescu’s picture

Also we need to add a dependency on the bundle if it is a config entity.

I opened #2458337: Add missing config dependencies for the entity reference field type to tackle all the missing dependencies.

Re #38: We can handle that in #1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted.

claudiu.cristea’s picture

@amateescu, I don't see the reason for 2 issues handling the same thing: sync field config settings when target bundles are removed/renamed.

amateescu’s picture

@claudiu.cristea, you might want to read #42 again, I'm talking about two different things there :P

alexpott’s picture

I'm not sure I agree with #42 - this issue is adding a new bundle containing field. Let's not fix a bug and create more known bugs at the same time.

amateescu’s picture

@alexpott, the known bugs are already there, we need to add dependencies on:

- the target bundles
- the target entity type
- the sort field
- the filter (roles) field for users

This one is just one more to add to the list and I think it will be easier if we handle all of then in one issue/patch.

amateescu’s picture

Status: Needs review » Needs work

Discussed in IRC with @alexpott and we agreed that we should fix the dependency problem here.

Basically, we need to implement some self-healing in EntityReferenceItem::onDependencyRemoval() by completely disabling 'auto_create' if the bundle specified in 'auto_create_bundle' is deleted.

amateescu’s picture

@claudiu.cristea, let me explain #44 a bit more:

The difference between #1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted and #2458337: Add missing config dependencies for the entity reference field type is that the first issue is about updating the field definition (i.e. its settings) when a bundle is renamed or deleted, while the second one is about adding all the missing config dependencies (i.e. not just bundles) and probably implement some self-healing like we'll be adding here.

If you think the difference is too subtle to split in two separate issues, I'm fine with merging them in #1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new22.35 KB
new3.44 KB
amateescu’s picture

+++ b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php
@@ -237,4 +235,34 @@ public static function getPreconfiguredOptions() {
+    if (!empty($handler_settings['auto_create_bundle'])) {
+      $field_definition->settings['handler_settings']['auto_create'] = FALSE;
+      unset($field_definition->settings['handler_settings']['auto_create_bundle']);
+      $changed = TRUE;
+    }

We need to check if our 'auto_create_bundle' is in the $dependencies array, not just delete the setting unconditionally :)

claudiu.cristea’s picture

StatusFileSize
new23.19 KB
new3.32 KB

Voilà!

amateescu’s picture

+++ b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php
@@ -258,9 +258,13 @@ public static function onDependencyRemoval(FieldDefinitionInterface $field_defin
+      $target_type = \Drupal::entityManager()->getDefinition($field_definition->getFieldStorageDefinition()->getSetting('target_type'));
+      $bundle = entity_load($target_type->getBundleEntityType(), $handler_settings['auto_create_bundle']);

We also need to check if the target entity types uses config entities for its bundles, because that's not always the case.

Also, getBundleEntityType() currently returns a bogus 'bundle' value by default instead of NULL, so we should probably postpone this on #2346857: Set default property bundle_entity_type in EntityType to NULL in order to not introduce even more special casing for the crappy current return value.

claudiu.cristea’s picture

Status: Needs review » Postponed
jibran’s picture

claudiu.cristea’s picture

Wait, wait... this needs some additional work not just a reroll.

The last submitted patch, 51: target_bundle_for-2412569-51.patch, failed testing.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new24.1 KB
new8.52 KB

@amateescu, added the check requested in #52.

amateescu’s picture

Status: Needs review » Needs work
  1. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
    @@ -144,21 +144,23 @@ public function massageFormValues(array $values, array $form, FormStateInterface
    +   *   Thrown when there's no 'auto_create_bundle' set but the entity reference
    +   *   is configured to store new entities in multiple bundles.
    

    The entity reference field cannot be configured to store new entities in multiple bundles, it can just reference entities from multiple bundles.

    How about: Thrown when the field allows references from multiple target bundles, 'auto_create' is enabled and 'auto_create_bundle' is not set.

  2. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
    @@ -144,21 +144,23 @@ public function massageFormValues(array $values, array $form, FormStateInterface
    +        throw new \InvalidArgumentException("Reference auto-create is enabled on multiple target bundles but 'auto_create_bundle' is not set.");
    

    This exception message is not really friendly as it assumes that the user knows how ER stores its settings internally.

    How about something like:

    The 'Create referenced entities if they don\'t already exist' option is enabled but a specific destination bundle is not set. You should re-visit and fix the settings of the $field_name field.

    Of course, $field_name needs to be replaced with the actual field name :)

  3. +++ b/core/modules/entity_reference/src/ConfigurableEntityReferenceItem.php
    @@ -230,4 +231,48 @@ public static function getPreconfiguredOptions() {
    +        if ($bundle && isset($dependencies[$bundle->getConfigDependencyKey()][$bundle->getConfigDependencyName()])) {
    +          unset($handler_settings['auto_create_bundle']);
    +          $handler_settings['auto_create'] = FALSE;
    +          $field_definition->setSetting('handler_settings', $handler_settings);
    +          $changed = TRUE;
    +        }
    

    The isset() check is not correct, it should be an in_array() check instead.

    Also, we can provide a better fallback in the case when the bundle specified in 'auto_create_bundle' was removed and the field now allows only one target bundle, we can default to that.

  4. +++ b/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
    @@ -38,7 +38,6 @@ public function entityQueryAlter(SelectInterface $query) {
         // @todo: Currently allow auto-create only on taxonomy terms.
         $form['auto_create'] = array(
    

    Since we moved the 'auto_create' form element in the parent class, we should remove it from the Term-specific one.

  5. +++ b/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
    @@ -63,7 +61,7 @@ public function getReferenceableEntities($match = NULL, $match_operator = 'CONTA
    -    $options = array();
    +    $options = [];
    

    Unrelated change.

  6. +++ b/core/modules/taxonomy/taxonomy.module
    @@ -52,7 +52,7 @@ function taxonomy_help($route_name, RouteMatchInterface $route_match) {
           $output .= '<dt>' . t('Adding new terms during content creation') . '</dt>';
    -      $output .= '<dd>' . t('Allowing users to add new terms gradually builds a vocabulary as content is added and edited. Users can add new terms if either of the two <em>Autocomplete</em> widgets is chosen for the Taxonomy term reference field in the <em>Manage form display</em> page for the field. You will also need to enable the <em>Create referenced entities if they don\'t already exist</em> option, and restrict the field to one vocabulary.') . '</dd>';
    +      $output .= '<dd>' . t('Allowing users to add new terms gradually builds a vocabulary as content is added and edited. Users can add new terms if the <em>Autocomplete term widget (tagging)</em> is chosen for a <em>Taxonomy Term reference</em> field, or if either of the two <em>Autocomplete</em> widgets is chosen for an <em>Entity reference</em> field. In this case you need to enable the <em>Create referenced entity</em> option.') . '</dd>';
    

    This change should be reverted as well, the current text is more accurate :)

claudiu.cristea’s picture

@amateescu, thank you!

Thinking more on this. We must resolve also the cleanup of the handler settings target_bundles here, not in #1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted. We'll leave only the renaming for #1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted.

Let me know what you think.

amateescu’s picture

Not sure about that, this patch is well contained and fixes a bug on its own.

The last submitted patch, 59: target_bundle_for-2412569-59.patch, failed testing.

yched’s picture

Coming to think of it, it seems 'auto_create_bundle' should be a setting of the autocomplete widget ?

API-wise, an ER field supports assigning an unsaved (but otherwise *fully formed*) $entity in $item->entity, and saving it along as the field is saved. No need for an 'auto_create_bundle' for that, the $entity has a bundle.

It's only the autocomplete widget that, on top of that, lets you create an $entity to reference out of a mere label string, and thus needs to know which bundle to assign it. Another widget (there are some in contrib D7 IIRC) could additionally show a dropdown to let you pick the bundle of the newly created entiy, and wouldn't need an 'auto_create_bundle'.

In fact, strictly speaking, what the ER field type supports is "auto-save", it's the autocomplete widget that does "auto-create".

Thoughts ?

amateescu’s picture

@yched, the line of thought in #64 is correct. So you would prefer if we move both the existing 'auto_create' and the new 'auto_create_bundle' settings to the widget(s) in this patch?

Edit: also, we'd need to check if that would be a usability regression :/

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new27.15 KB
new15.17 KB

#60.1, 2, 4, 5, 6: Done.

#60.3: This requirement is hard to implement without #61 because I need to count the target bundles. So, they both belong to this piece of code and we should treat them in the same move.

EDIT: I fully agree with you that somehow this is not part of this issue but...

EDIT2:

The isset() check is not correct, it should be an in_array() check instead.

I checked this twice, in_array() doesn't work here. I wrote a test for dependency stuff that should prove :)

yched’s picture

So you would prefer if we move both the existing 'auto_create' and the new 'auto_create_bundle' settings to the widget(s) in this patch?

Hm, right, they go hand in hand (logically, and in the UI through #states).

Well, I guess #64 could also be said about 'auto_create', it's the autocomplete widget that can be configured to auto-create or not ? (I mean, that mimicks the properties of the underlying entity_autocomplete FAPI #type, right ?)

I might be missing something, but I doubt there are actual uses of 'auto_create' as part of the selection plugin, I can't really see how that affects the selection process ?

amateescu’s picture

I mean, that mimicks the properties of the underlying entity_autocomplete FAPI #type, right ?

Yup.

I might be missing something, but I doubt there are actual uses of 'auto_create' as part of the selection plugin, I can't really see how that affects the selection process ?

Also true, 'auto_create' is a selection plugin setting only for historical reasons.

yched’s picture

Edit: also, we'd need to check if that would be a usability regression :/

Well, IMO simplifying the "ER field" config form by removing a setting that only makes sense for a specific widget (that isn't even the default ER widget - hm, BTW, ERItem specifies no default widget ?) [edit: ok, scratch that, e_r.module does make it the default ER widget], and putting in the config screen for that widget only if you select it, is a usability win ;-)

claudiu.cristea’s picture

Based on #67.

Known issue:

Unfortunately WidgetInterface doesn't implement onDependencyRemoval() so we must hook_entity_bundle_delete() and so, we're back in to the ER field finder from #1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted. And that cannot be worked now because #2337191: Split up EntityManager into many services is not in. Also all these ER settings update have to implement hook_entity_bundle_delete/rename() but entity_reference.module will go away in #2429191: Deprecate entity_reference.module and move its functionality to core. So...

So, I opened #2553169: Dispatch bundle CRUD events to be able to handle all these synchronizations directly in core. Even I agree with #45, my proposal is to not handle now the settings update. Right now this is already broken because "target_bundles" are not updated. We can fix this when:

  1. We have the bundle CRUD events dispatcher. (#2553169: Dispatch bundle CRUD events)
  2. A utility method to retrieve fields targeting to a specific entity/bundle (#1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted)

Opinions?

claudiu.cristea’s picture

Issue summary: View changes
StatusFileSize
new181.91 KB
new155.5 KB

Updating issue summary.

Also, I found that we need an update path for auto_create, from handler settings to widget settings.

Status: Needs review » Needs work

The last submitted patch, 70: target_bundle_for-2412569-70.patch, failed testing.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new45.28 KB
new21.09 KB

Added update path for settings in system_update_8004(). I avoided the ER module because sooner or latter will be removed.

yched’s picture

we're back in to the ER field finder from #1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted

Not sure I follow. The new 'auto_create_bundle' is a widget, so what would need an update is the widget settings (i.e the EntityFormDisplay), not the ER field ?
I agree that, since ER currently doesn't update its 'target_bundles' either, it could be OK to leave the 'auto_create_bundle' widget setting dangling as well, and fix both in the same issue if that's easier, but I don't really see

Regarding bundle deletion : well, if the 'auto_create_bundle' setting refers to a bundle, I guess it means the containing config entity (EntityFormDisplay) should have a dependency on that bundle and that bundle shouldn't be removable ?

[...] system_update_8004(). I avoided the ER module because sooner or latter will be removed

Well, it's Core that defines both the selection plugins and the autocomplete widget, so putting the update in e_r wouldn't make sense anyway ;-)

claudiu.cristea’s picture

StatusFileSize
new51.67 KB
new7.64 KB

@yched, thank you! I was a little bit confused about the relation between form display and widgets. Now it makes sense.

Comments:

  1. Reconsidering #60.3. I'm not sure anymore that we have to assure that fallback. First, the fallback works only when there are two target bundles and one is deleted. This will be inconsistent with the other cases when, for example there are 3 or more bundles and you delete one. In that case auto_create_bundle will be set to NULL and auto creation disabled. An I think this is correct because... (Second), we cannot make an assumption on how the site builder wants to set that field. IMO, we should be consistent here across all the cases. Maybe simply registering a warning log entry telling: "Bundle 'tags' was deleted and the auto-creation for fields
    has been disabled. Reconfigure each field..." (a good message to be find). Opinions?
  2. It seems to me that having both, auto_create and auto_create_bundle, is bit redundant. We can consider auto_create_bundle == NULL as "disabled auto-creation"? I that case we need to treat target entities without bundle (like user) but I don't think that it would be too difficult. What about this?
  3. The new test (\Drupal\system\Tests\Field\EntityReferenceSettingsTest) is temporary built on the old KernelTestBase because of #2553661: KernelTestBase fails to set up FileCache. When the bug will be fixed I'll convert the test.

EDIT: And I think that system_update_8004() deserves a test...

Status: Needs review » Needs work

The last submitted patch, 75: target_bundle_for-2412569-75.patch, failed testing.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new53.75 KB
new7.15 KB

Added the test for system_update_8004().

Status: Needs review » Needs work

The last submitted patch, 77: target_bundle_for-2412569-77.patch, failed testing.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new53.45 KB
new5.53 KB

Here we go.

claudiu.cristea’s picture

StatusFileSize
new34.08 KB
new57.31 KB

Here's patch with a version based on #75.2: Removing the redundancy of having both auto_create_bundle and auto_create.

Pros:

  1. Removes the next possible inconsistency: The field accepts >1 target bundles AND auto_create is TRUE AND auto_create_bundle is NULL.
  2. More compact widget settings.

Cons:

Right now, in this patch, there's a small loss of UX by not having that checkbox that makes the interface more meaningful to the user. I can fix that by adding a checkbox with states only to show hide the bundles select element if we go with this solution.

So, @yched, @amateescu, what is your opinion? Should we go with this approach or continue with #79?

jibran’s picture

Ok if I have an autocreate entity autocomplete element in a custom form how can I mention bundle settings there? Because of this I think this helper method should live in \Drupal\Core\Entity\Element\EntityAutocomplete as a static method to which we can pass target_type and auto_create_bundle setting. What do you think about it?

jibran’s picture

And moving this to widget is a good call ++ on that. Some what related widget setting issue for DER is #2381993: Allow view mode or formatter to be selected per item in the widget.

claudiu.cristea’s picture

if I have an autocreate entity autocomplete element in a custom form how can I mention bundle settings there? Because of this I think this helper method should live in \Drupal\Core\Entity\Element\EntityAutocomplete as a static method to which we can pass target_type and auto_create_bundle setting

@jibran, I'm not sure I understand your question. After quick looking in the code, I guess you'll need to add something like this:

$form['foo‘] = [
  '#type' => 'entity_autocomplete',
  '#target_type' => 'taxonomy_term',
  '#selection_handler' => 'default',
  '#selection_settings' => [
    'target_bundles' => [
      'tags' => 'tags',
      'whatever' => 'whatever',
    ],
  ],
  '#validate_reference' => FALSE,
  '#maxlength' => 1024,
  '#default_value' => NULL,
  '#size' => 50,
  '#placeholder' => $this->t('Type something...'),
  '#autocreate' => [
    'bundle' => 'whatever',
    'uid' => \Drupal::currentUser()->id(),
  ],
];

EDIT: Fixed the #autocreate key.

claudiu.cristea’s picture

StatusFileSize
new57.4 KB

Reroll of #80.

Status: Needs review » Needs work

The last submitted patch, 84: 2412569-84.patch, failed testing.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new870 bytes
new57.49 KB

Fixed update test.

Status: Needs review » Needs work

The last submitted patch, 86: 2412569-86.patch, failed testing.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new59.94 KB
new5.28 KB
claudiu.cristea’s picture

Priority: Normal » Major
Issue summary: View changes

This is major because the entity auto-creation doesn't work when multiple bundles are selected as target. Added beta evaluation.

Status: Needs review » Needs work

The last submitted patch, 88: 2412569-88.patch, failed testing.

claudiu.cristea’s picture

Status: Needs work » Needs review
StatusFileSize
new59.47 KB
new670 bytes
jibran’s picture

+++ b/core/lib/Drupal/Core/Entity/Entity/EntityFormDisplay.php
@@ -336,4 +336,78 @@ public function getPluginCollections() {
+    foreach ($this->getEntityReferenceAutocompleteComponents() as $field_name => $bundle) {
...
+  protected function getEntityReferenceAutocompleteComponents() {

This function doesn't belong to this class.

claudiu.cristea’s picture

@jibran,

Yes, it seems so. But if we'll look closer, we can see that it's just a helper for calculateDependencies() and onDependencyRemoval(), providing a very customized return structure, not usable in other places. And calculateDependencies() and onDependencyRemoval() are part of EntityFormDisplay interface. Moving that helper to other class it would not make too much sense. I tried only to reuse code.

yched’s picture

Having specific code in EntityFormDisplay about ER fields and EntityReferenceAutocompleteWidget does sound like a no-go :-/

This widget happens to have a dependency based on what's present in one of its settings, it should be the widget that exposes that.
On the next widget (or formatter) that has such a case, we don't want to keep adding more specific code in EntityDisplays - and contrib won't be able to do such a thing anyway.

Meaning, EntityDisplayBase::calculateDependencies() should call each widget / formatter and ask for its dependencies - it's weird, I thought we had something like that in place, but apparently we don't.

As was discussed earlier I think, we might argue leaving that for a separate issue, since we already have problems with ER-related settings not updating when a bundle name changes ?

claudiu.cristea’s picture

EntityDisplayBase::calculateDependencies() should call each widget / formatter and ask for its dependencies - it's weird, I thought we had something like that in place, but apparently we don't.

We can fix this here by iterating through all components and collect dependencies from widgets. Or, better open a new issue just for that to cover also formatters?

As was discussed earlier I think, we might argue leaving that for a separate issue, since we already have problems with ER-related settings not updating when a bundle name changes ?

I wanted that earlier but @alexpott disagreed in #45. If we go with a new issue for collecting dependencies for widgets/formatters then maybe we can postpone this till fixing that.

yched’s picture

Ouch. Then yes, I guess a new issue postponing this one is the way to go :-/

jibran’s picture

Thanks @yched for the clarity.

claudiu.cristea’s picture

Status: Needs review » Postponed
claudiu.cristea’s picture

Issue tags: +ER check for RC

Tagging.

claudiu.cristea’s picture

Assigned: Unassigned » yched

Discussed with @yched and @amateescu at Drupalcon Barcelona to check with core committers if moving the auto_create from filed to widget is feasible in 8.0.x. Assigning to @yched to get a resolution on that.

yched’s picture

Me and @amateescu discussed this with @alexpott in Barcelona.

@alexpott agrees that moving the setting to the widget is cleaner and makes more sense, and would be acceptable with an update hook if we can get it ready before RC.

However, discussing further with @amateescu, we hit another question with that approach :
The bundle stored in the widget setting needs to be one of the bundles referenceable by the field.
Then, what do we do when someone modifies the field settings and removes the "bundle used for autocreate by the widget" from the list of possible target bundles ?

- We could add a FAPI #validate in the settings form defined by SelectionBase::buildConfigurationForm() so that any bundle currently used for autocreate by any widget in any form mode, cannot be removed from the list of target bundles. @alexpott seemed to agree with that approach.
- Or, keeping the 'autocreate_bundle' setting in the field setting makes it easier to make sure that it never gets inconsistent...

jibran’s picture

Or, keeping the 'autocreate_bundle' setting in the field setting makes it easier to make sure that it never gets inconsistent...

This seems much better and simple imo.

yched’s picture

Assigned: yched » Unassigned

Coming from #2064191-47: Fix the 'target_bundle' field setting - 'target_bundles' are not validated when entity_reference is enabled :

ViewsSelector is inherently incompatible with auto-save. You cannot validate that an $entity that isn't in the database yet will match a given View

Meaning, we should not offer to "autocreate" if the selection handler is ViewsSelector...
Which is another argument for "it's simpler to keep autocreate settings in the same UI than the selection handler". So, fine, let's do that :-)

yched’s picture

Status: Postponed » Active

Meaning it can also be unpostponed

claudiu.cristea’s picture

I don't get it. Will be on field or widget?

yched’s picture

Sorry, that wasn't clear.

I meant :
[autocreate should not be offered with ViewsSelection handler] is another argument for "it's simpler to keep autocreate settings in the field settings, where the selection settings also are".

So, yeah, let's go with field settings I guess.

amateescu’s picture

Status: Active » Needs review
StatusFileSize
new21.26 KB
new41.58 KB

Nice that we finally have consensus on where to store the setting :) Here's #66, rerolled, cleaned up a little and also applied on top of #1978714-86: Entity reference doesn't update its field settings when referenced entity bundles are deleted because both issues need the same code to handle the 'target_bundles' config dependency.

Status: Needs review » Needs work

The last submitted patch, 107: 2412569-plus-1978714.patch, failed testing.

jibran’s picture

Issue tags: +Needs change record

IMO we should add a change record for this. Patch looks good let's fix the fails.

The last submitted patch, 107: 2412569-plus-1978714.patch, failed testing.

amateescu’s picture

Status: Needs work » Needs review
Issue tags: -Needs change record
StatusFileSize
new21.82 KB
new42.14 KB
new1.75 KB

Let's :) I don't think a CR is needed for this patch.

jibran’s picture

Yay!!! green. Looks perfect to me. @yched please nitpick the patch. :D Other then that and parent issue this is ready.

yched’s picture

  1. +++ b/core/modules/entity_reference/entity_reference.module
    @@ -211,3 +210,49 @@ function entity_reference_query_entity_reference_alter(AlterableInterface $query
    +        // have to log a warning message because the field will not function
    

    Nit : we're logging a critical, not a warning :-)

  2. +++ b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
    @@ -96,6 +96,14 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    +  public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
    +    // Don't call the parent validation handler because we don't have any
    +    // 'target_bundles' setting.
    +  }
    

    It's really unfortunate that SelectionBase is both a base class and an actual selection plugin with "by bundle" logic that subclasses willing to use the base class then need to undo.

    That means any change in the "by bundle" handler, like the one here, can break any other Selection class.

    Probably not for this issue to change, though :-/

    Also : as mentioned in #2577963: Let entity_ref Selection handlers be in charge of the field validation, ViewsSelector is in fact incompatible with auocreate, since we cannot validate that a newly created entity that is not in the db yet is going to match a given View. Not sure if that means there is additional UI adjustments needed (do not provide the option for ViewsSelection), and if we want to do them here, just saying :-)

  3. +++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php
    @@ -136,6 +137,18 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    +      $form['target_bundles_update'] = array(
    +        '#type' => 'submit',
    +        '#value' => $this->t('Update bundles'),
    +        '#limit_validation_errors' => array(),
    +        '#attributes' => array(
    +          'class' => array('js-hide'),
    +        ),
    +        '#submit' => array('entity_reference_settings_ajax_submit'),
    

    I'm not seeing anywhere this button is actually used ? Or is there some automagical ajax wiring with the 'target_bundles' select I have forgotten about ?

  4. +++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/SelectionBase.php
    @@ -204,6 +217,28 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    +    $form['auto_create'] = array(
    +      '#type' => 'checkbox',
    +      '#title' => $this->t("Create referenced entities if they don't already exist"),
    +      '#default_value' => $selection_handler_settings['auto_create'],
    +    );
    

    Aw - we didn't have any UI controlling that so far ?

  5. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
    @@ -388,6 +397,16 @@ public static function onDependencyRemoval(FieldDefinitionInterface $field_defin
    +      if (!empty($handler_settings['auto_create']) && count($handler_settings['target_bundles']) === 1) {
    +        $handler_settings['auto_create_bundle'] = key($handler_settings['target_bundles']);
    +      }
    

    If the bundle used for auto_create disappears, do we really want to silently switch a a random other bundle ?

amateescu’s picture

StatusFileSize
new22.81 KB
new41.73 KB
new3.77 KB

Thanks for reviewing!

  1. That's actually part of #1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted, but we might as well fix it here :)
  2. SelectionBase is not really a base class, it's just poorly named :/ It should be renamed to DefaultSelection, but it's kinda late for that now.
  3. That button is shown when you have JS disabled.
  4. We did, but only in the taxonomy term selection handler.
  5. Hmm, right, we probably don't want that setting to change without any user input. Fixed.
yched’s picture

#114.1 : yeah sorry, I started reviewing the "full" patch before I realized it contained the patch for the other issue :-)

#114.2

SelectionBase is not really a base class, it's just poorly named

Well, ViewsSelection does use it as a base class, and then needs to undo the logic in a couple places. Do you think having a real base class and renalming the current SelectionBase to DefaultSelection would break a lot of things ? I guess contrib modules that started adding selection adjustments for their own entity types ?

If not possible, then I guess we could at least make ViewsSelection stop extending it ? But right, probably not for this issue...

Looks ready then - but postponed on #1978714: Entity reference doesn't update its field settings when referenced entity bundles are deleted, right ?

amateescu’s picture

Status: Needs review » Postponed

Yes, I should've been more in favor of the trait in #2482705-12: ViewsSelection::validateAutocompleteInput is not implemented, which is the recent issue that made ViewsSelection extend SelectionBase :/ We can definitely open a new issue to clean it up, since it seems that ViewsSelection has to undo more and more things from SelectionBase..

yched’s picture

@amateescu : right, so this is only about reusing SelectionBase::validateAutocompleteInput() ?
Since that code is only called by Element\EntityAutocomplete::validateEntityAutocomplete(), and seems to only contain some generic logic to bridge between Selection::getReferenceableEntities() and the form autocomplete format, maybe it could also be moved directly into EntityAutocomplete::validateEntityAutocomplete() ?

i.e EntityAutocomplete calls Selection::getReferenceableEntities(), which contains the real "selection logic", and then simply massages the results for its own "autocomplete" needs ? SelectionInterface then doesn't have any method about the specific use case of autocomplete ?

yched’s picture

The last submitted patch, 111: 2412569-111-plus-1978714.patch, failed testing.

Status: Postponed » Needs work

The last submitted patch, 114: 2412569-114-plus-1978714.patch, failed testing.

jibran’s picture

yched’s picture

Assigned: Unassigned » yched
Status: Postponed » Needs work
yched’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new22.81 KB

Reroll was the 2412569-114-do-not-test.patch from #114, with some fuzz.

yched’s picture

Side note : I virtually RTBCed the 2412569-114-plus-1978714.patch in #115, so I feel I'm fine RTBCing the standalone patch @amateescu had prepared :-)

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

Needs reroll.

amateescu’s picture

Assigned: yched » Unassigned
Status: Needs work » Reviewed & tested by the community
StatusFileSize
new22.82 KB

Rerolled.

jibran’s picture

+1 for RTBC

PS: As much as all these ER fixes are awesome and I'm happy that we are almost done with it before RC deadline but DER is extremely broken now :P and I don't know where to start :D

amateescu’s picture

claudiu.cristea’s picture

Issue summary: View changes

Restored screenshots corresponding to the RTBC solution.

claudiu.cristea’s picture

Issue summary: View changes
catch’s picture

Issue tags: +rc target triage, +minor version target

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 128: 2412569-128.patch, failed testing.

amateescu’s picture

Status: Needs work » Reviewed & tested by the community
StatusFileSize
new22.73 KB

Rerolled.

alexpott’s picture

Title: Target bundle for auto-created entity references with multiple target bundles » Disable auto-create entity references with multiple target bundles
Status: Reviewed & tested by the community » Needs work
Issue tags: -rc target triage +rc target

Discussed this with @xjm, @catch, and @effulgentsia, and we agreed to make this an RC target but we're not convinced by the solution. We think that we should do the minimal fix which is to remove the auto create option if there are multiple bundles.

xjm’s picture

I think the minimal fix described in #134 would also be patch-release safe, though the current patch would not be.

claudiu.cristea’s picture

@xjm, sorry but I cannot understand why a patch that doesn't exist yet is "safe" while the current one, which was heavily commented, reviewed, amended and RTBC-ed is not :)

ifrik’s picture

I've reviewed patch #133 from a sitebuilder's perspective, and - with JavaScript enabled - it works as desired.

But without JavaScript, the two buttons "Change handler" and "Update bundles" are rather confusing.
1) I don't think we use "bundles" in other places in UI text, so it probably should be reworded.

2) When I tick an additional vocabulary, and then click on "Update bundles" the page gets reloaded and the vocabulary is unticked again. Is that intended behaviour? Or if not, what is that button for?

catch’s picture

Version: 8.0.x-dev » 8.1.x-dev
Status: Needs work » Needs review

@claudiu.cristea - because the current patch makes changes to configuration schema, which is something we'd try to do only in minor releases.

Having said that, I think we should have another look at the current patch here for 8.1.x (I haven't yet) - and if it's OK for a minor release, commit to 8.1.x. Then we can revisit what to do about 8.0.x for this issue, if anything, afterwards.

ifrik’s picture

Since I reported the issue, the behaviour has changed. Previously, no term was created at all, if several vocabularies where chosen.
Now, the term is created in the first vocabulary on the list, so it's not lost.

But this first vocabulary is then set as destination for any other of such entity reference field.

If I set up one entity reference fields, using vocabulary 1 and vocabulary 2, the destination is the vocabulary on the top of the list (Vocabulary 1). If I then create another entity reference field, using vocabulary 3 and 4 for another content type, then the destination is still set as vocabulary 1.
Users then can't save the content of this second content type, because the term cannot be created.

The patch in #133 fixes this problem as well.

amateescu’s picture

StatusFileSize
new22.75 KB
new966 bytes

Rerolled for 8.1.x and fixed the two problems mentioned in #137 1) and 2).

amateescu’s picture

Title: Disable auto-create entity references with multiple target bundles » Allow setting the auto-create bundle on entity reference fields with multiple target bundles

And a new title for what should go into 8.1.x.

claudiu.cristea’s picture

Status: Needs review » Reviewed & tested by the community

I'm setting this back to RTBC per #123.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 140: 2412569-140.patch, failed testing.

jibran’s picture

Status: Needs work » Reviewed & tested by the community
Issue tags: -ER check for RC, -rc target
StatusFileSize
new22.75 KB

Here is a reroll.

alexpott’s picture

+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
@@ -144,21 +144,27 @@ public function massageFormValues(array $values, array $form, FormStateInterface
+      elseif (!$bundle = $this->getSelectionHandlerSetting('auto_create_bundle')) {
+        // If no bundle has been set as auto create target means that there is
+        // an inconsistency in entity reference field settings.
+        throw new \InvalidArgumentException(sprintf(
+          "Create referenced entities if they don't already exist option is enabled but a specific destination bundle is not set. You should re-visit and fix the settings of the '%s' (%s) field.",
+          $this->fieldDefinition->getLabel(),
+          $this->fieldDefinition->getName()
+        ));
       }

Doesn't this mean we need an upgrade path to set the auto create bundle to the first available to replicate the old functionality?

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

Setting to needs review for #145

claudiu.cristea’s picture

Status: Needs review » Needs work
Issue tags: +Needs upgrade path, +Needs upgrade path tests

Yes, definitely.

amateescu’s picture

Status: Needs work » Needs review
Issue tags: -minor version target, -Needs upgrade path, -Needs upgrade path tests
StatusFileSize
new30.99 KB
new8.24 KB

This should do it.

jibran’s picture

I have to fix this in DER as well. Let me ping @larowlan for review.

  1. +++ b/core/modules/field/field.install
    @@ -68,3 +68,39 @@ function field_update_8002() {
    +    if ($class == EntityReferenceItem::class || is_subclass_of($class, EntityReferenceItem::class)) {
    

    DER is a sub class but it's settings are not stored this way.

  2. +++ b/core/modules/field/field.install
    @@ -68,3 +68,39 @@ function field_update_8002() {
    +      $handler_settings = $field->get('settings.handler_settings');
    ...
    +      if (isset($handler_settings['auto_create']) && $handler_settings['auto_create']) {
    

    $handler_settings can be NULL (in case of DER) so it should have to be a part of if condition.

amateescu’s picture

StatusFileSize
new30.99 KB
new843 bytes

Does this address your concern?

jibran’s picture

Yup thanks.

claudiu.cristea’s picture

I think this looks great and can be RTBCed. But I cannot do it because I've contributed to the solution and the code (I only did it when it was a docs diff, in #142). Anybody for a final review? Maybe @jibran or @yched?

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Yup sure.

lokapujya’s picture

Status: Reviewed & tested by the community » Needs work

1-4 not a big deal, but should at least take a look at #5

  1. +++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php
    @@ -122,6 +122,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    @@ -139,6 +140,18 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    
    @@ -139,6 +140,18 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    @@ -207,6 +220,28 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    

    the changes in these functions can use the new [] instead of array().

  2. +++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php
    @@ -139,6 +140,18 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    +          'class' => array('js-hide'),
    
    +++ b/core/modules/field/field.install
    @@ -68,3 +68,39 @@ function field_update_8002() {
    +  // Iterate on all fields.
    

    Iterate all fields.

  3. +++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceAutoCreateTest.php
    @@ -134,4 +139,103 @@ public function testAutoCreate() {
    +   * Tests if a entity reference field having multiple target bundles is storing
    

    an entity reference

  4. +++ b/core/modules/field/tests/fixtures/update/drupal-8.views_entity_reference_plugins-2429191.php
    @@ -26,8 +26,14 @@
    +$field_ref_views_select_2429191 = Yaml::decode(file_get_contents(__DIR__ . '/field.storage.node.field_ref_views_select_2429191.yml'));
    +
    +// Configuration for an entity_reference field storage using the auto-create
    +// feature.
    +$field_ref_autocreate_2412569 = Yaml::decode(file_get_contents(__DIR__ . '/field.storage.node.field_ref_autocreate_2412569.yml'));
    

    Unnecessary long variable name. Should we remove the issue id form the variable name?

  5. +++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php
    @@ -139,6 +140,18 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    +        '#limit_validation_errors' => array(),
    

    Why adding limit_validation_errors? Seems like it could cause the target bundles field to skip validation. Not sure if this is really a problem? But try deselecting all terms and saving.

lokapujya’s picture

More on #5:Once you save the entity reference field without a target bundle selected, then the "Create referenced entities if they don't already exist" checkbox does not hide the "Store new Items" dropdown (even after selecting 2 bundles.)

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new30.99 KB
new3.69 KB

#154.1, .2 and .3: Fixed.

#154.4: I think it's better to keep the issue id there for clarity and future updates to that file/code.

#154.5: and #155 I can not reproduce the wrong behavior, when I de-select all target bundles and try to submit the form I get the proper validation error ("Content types field is required.").

lokapujya’s picture

#154.5: I agree that the form gives the proper validation error. The problem is that the form still saves. If you refresh the page, you will see that target bundles remain deselected. I guess I'm expecting it to work like the label and not submit. Couldn't find any other examples of required checkboxes in Core, so maybe that's just the way it works.

#155 seems to be an issue with states.js, perhaps should be a new issue. The checkbox works correctly when javascript is not aggregated.
I actually discovered the problem by:
1. use a content type as the reference type. Initially, no target bundles are selected.
2. select the target bundles: page and article - store new items select shows up, even though we haven't done step 3 yet.
3. click "Create referenced entities if they don't already exist"
4. click "Create referenced entities if they don't already exist" again - store new items doesn't hide
Then, I noticed this only happens when there are initially no target bundles selected. But that should never happen anyway for taxonomy term because it's supposed to be required.

lokapujya’s picture

Status: Needs review » Reviewed & tested by the community

Thanks for fixing 1-3. I created a new related issue #2656546 for the problem described in #157.

droplet’s picture

Status: Reviewed & tested by the community » Needs review

I followed steps in #2656546: javascript form states don't work and got PHP errors:

The website encountered an unexpected error. Please try again later.

** revert the patch and works.

droplet’s picture

InvalidArgumentException: Missing required #autocreate['bundle'] parameter. in Drupal\Core\Entity\Element\EntityAutocomplete::processEntityAutocomplete() (line 112 of core\lib\Drupal\Core\Entity\Element\EntityAutocomplete.php).
call_user_func_array(Array, Array)
Drupal\Core\Form\FormBuilder->doBuildForm('field_config_edit_form', Array, Object)
Drupal\Core\Form\FormBuilder->doBuildForm('field_config_edit_form', Array, Object)
Drupal\Core\Form\FormBuilder->doBuildForm('field_config_edit_form', Array, Object)
Drupal\Core\Form\FormBuilder->doBuildForm('field_config_edit_form', Array, Object)
Drupal\Core\Form\FormBuilder->doBuildForm('field_config_edit_form', Array, Object)
Drupal\Core\Form\FormBuilder->processForm('field_config_edit_form', Array, Object)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
call_user_func_array(Object, Array)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1)
Stack\StackedHttpKernel->handle(Object, 1, 1)
Drupal\Core\DrupalKernel->handle(Object)
lokapujya’s picture

On which step did you get the error? I know there is a javascript UI issue, but I didn't see that PHP error.

droplet’s picture

1. add `content` reference
2. select Type of item to reference : Content type
3. Save save save
4. edit field
5. click "Create referenced entities if they don't already exist"
6. save save
7. edit again -> HIT error

claudiu.cristea’s picture

@droplet, did you run the update script?

droplet’s picture

Status: Needs review » Reviewed & tested by the community

ah right. back to prev state.

I didn't test JS part yet but if that introduced from this patch, I think we should fix them together.

catch’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php
    @@ -221,6 +256,10 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form
    +    $form_state->unsetValue(['settings', 'handler_settings', 'target_bundles_update']);
    

    It'd be nice if there was a way to flag this in the form definition. Reminds me a bit of $user->data having to do it manually. Not for here though, but wondering whether we have the same trouble elsewhere.

  2. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
    @@ -473,10 +475,19 @@ public static function onDependencyRemoval(FieldDefinitionInterface $field_defin
    +              $auto_create_bundle = !empty($handler_settings['auto_create_bundle']) ? $handler_settings['auto_create_bundle'] : FALSE;
    +              if ($auto_create_bundle && $auto_create_bundle == $bundle->id()) {
    +                $handler_settings['auto_create'] = NULL;
    +                $handler_settings['auto_create_bundle'] = NULL;
    +              }
    

    What if we go from two bundles down to one? Could we not leave auto-create on but remove the bundle setting?

    Or we might want to log this similar to below either way?

  3. +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
    @@ -144,21 +144,27 @@ public function massageFormValues(array $values, array $form, FormStateInterface
    +        throw new \InvalidArgumentException(sprintf(
    

    I'm not convinced about showing the exception on the widget. This could mean that regular site visitors get fatal errors (and I don't yet see a warning being shown on the field UI page with this patch, so only on entity forms which is not where you can fix this). Feels more like we should disable either the autocreate, or the field entirely, + trigger_error()?

  4. +++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceAutoCreateTest.php
    @@ -134,4 +139,103 @@ public function testAutoCreate() {
    +    // Test the case when the field config settings are inconsistent.
    +    unset($handler_settings['auto_create_bundle']);
    +    $field_config->setSetting('handler_settings', $handler_settings);
    +    $field_config->save();
    +
    +    // If we use $this->drupalGet() we cannot catch the exception because the
    +    // form builder runs in other PHP space. Instead we are only building the
    +    // form in order to check if the exception is thrown.
    +    try {
    +      /** @var \Drupal\Core\Form\FormBuilderInterface $form_builder */
    +      $form_builder = $this->container->get('entity.form_builder');
    +      $form_builder->getForm(Node::load(1));
    +      $this->fail("Missed 'auto_create_bundle' should throw \\InvalidArgumentException but it didn't.");
    +    }
    +    catch (\InvalidArgumentException $e) {
    +      $this->assertIdentical(
    +        $e->getMessage(),
    +        sprintf(
    +          "Create referenced entities if they don't already exist option is enabled but a specific destination bundle is not set. You should re-visit and fix the settings of the '%s' (%s) field.",
    +          $field_config->getLabel(),
    +          $field_config->getName()
    +        )
    +      );
    +    }
    +  }
    

    This shows the problem with the exception even more.

    Saving the field with the wrong configuration doesn't show an exception, viewing the entity form does.

    I'd rather see a config listener that throws the exception so you can never get into this situation in the first place, then if we think there are cases where something could go wrong (race condition with the update function not having been run yet?) trigger_error() in the UI.

amateescu’s picture

I don't think we can rely on a config listener for this situation because that won't run for base field updates.

How about just disabling the auto-create functionality + logging a critical watchdog message in the widget instead of throwing an exception, just like we do in the "last available target bundle was deleted" case? That way, regular site visitors will be able to use the field (partially, at least) and site admins should see the problem pretty soon, given its critical status.

amateescu’s picture

Status: Needs work » Needs review
StatusFileSize
new30.94 KB
new4.81 KB

Ok, this should do it.

What if we go from two bundles down to one? Could we not leave auto-create on but remove the bundle setting?

If the referenced entity type has more than one bundle at any point in time, we should not make any assumptions on which bundle we can use for auto-create because that could have security implications, so it's safer to just disable the feature.

amateescu’s picture

Status: Needs review » Reviewed & tested by the community

The small feedback from @catch has been addressed, so setting back to RTBC.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

  • catch committed a547ae6 on 8.2.x
    Issue #2412569 by claudiu.cristea, amateescu, yched, jibran, epari.siva...
catch’s picture

Version: 8.2.x-dev » 8.1.x-dev
Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.2.x and cherry-picked to 8.1.x. Thanks!

Added review credit post-commit.

catch’s picture

Adding review credit.

Status: Fixed » Closed (fixed)

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

jibran’s picture

Issue tags: +Needs followup
+++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceAutoCreateTest.php
@@ -136,4 +140,94 @@ public function testAutoCreate() {
+    // @todo Re-enable this test when WebTestBase::curlHeaderCallback() provides
+    //   a way to catch and assert user-triggered errors.
...
+    // Test the case when the field config settings are inconsistent.
+    //unset($handler_settings['auto_create_bundle']);
+    //$field_config->setSetting('handler_settings', $handler_settings);
+    //$field_config->save();
+    //
+    //$this->drupalGet('node/add/' . $this->referencingType);
+    //$error_message = sprintf(
+    //  "Create referenced entities if they don't already exist option is enabled but a specific destination bundle is not set. You should re-visit and fix the settings of the '%s' (%s) field.",
+    //  $field_config->getLabel(),
+    //  $field_config->getName()
+    //);
+    //$this->assertErrorLogged($error_message);

We need a followup for this.