Problem/Motivation

This was originally discussed in #2349371: Display selection can be confusing. Idea for this issue comes from comment #25 in that issue.

For usability reasons we'd like to treat view modes more like standalone display plugins instead of configuration variables on a single one.

From the original discussion:

I think we should present a single <select>.

I think we can do that because:

Typical Entity Embed Display plugins: Rendered entity, Entity ID, Label
Typical view modes: Teaser, Full …
Hence, we can merge them into a single list, like so:

- "Label"
- "Teaser"
- "Full"
- "ID"

Proposed resolution

Create derivative of the "Rendered entity" display for each view mode. This will make view modes equivalent to any other display plugin and implicitly define view mode that needs to be used.

We need to make sure that each individual plugin appears only related to entity types it belongs to. We should also make sure that existing embeds still work (by keeping the storage untouched, by leaving general "Rendered entity" plugin or by providing BC layer).

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

slashrsm created an issue. See original summary.

Berdir’s picture

That sounds interesting I think. Also makes it very easy to configured allowed embed view modes per button. More custom code that we could kill in our site ;)

One thing to think about is backwards compatibility. I think the existing, non-derived formatter should be kept or existing content would break. but you don't want to expose both to users by default, that would be even more confusing.

Maybe a setting to switch between the two modes? Then existing sites could have an update function to use the old one and new ones could default to using the derivates?

yoroy’s picture

Issue tags: +Needs screenshots
Dave Reid’s picture

Interesting, but this is something I'd love to see possibly improved in core and re-using field formatters instead of diverging from that reusability.

thenchev’s picture

Assigned: Unassigned » thenchev
Status: Active » Needs review
FileSize
5.89 KB
57.87 KB

Initial patch. Still need to work on backwards compatibility from berdirs suggestion.
ee

Status: Needs review » Needs work

The last submitted patch, 5: treat_each_view_mode_in-2736741-5.patch, failed testing.

thenchev’s picture

Status: Needs work » Needs review
FileSize
10.17 KB
8.82 KB

Fixed test fails and expanded test coverage.

slashrsm’s picture

Issue tags: +D8Media
  1. +++ b/src/EntityEmbedDisplay/FieldFormatterEntityEmbedDisplayBase.php
    @@ -116,11 +111,18 @@ abstract class FieldFormatterEntityEmbedDisplayBase extends EntityEmbedDisplayBa
       /**
    +   * Returns the field formatter id.
    +   */
    +  public function getFieldFormatterId() {
    +    return $this->getDerivativeId();
    +  }
    

    Should add @return statement. Let's use this function on other places where getDerivativeId() is used at the moment. For consistency and to make sure overrides are always respected.

    I think that this last part actually introduces bugs at the moment. Button configuration form will throw a fatal if you limit the list of display plugins that can be used.

  2. +++ b/src/Plugin/Derivative/ViewModeDeriver.php
    @@ -0,0 +1,59 @@
    +   * The entity type manager.
    ...
    +   * Constructs new FieldFormatterEntityEmbedDisplayBase.
    
    +++ b/src/Plugin/entity_embed/EntityEmbedDisplay/ViewModeFieldFormatter.php
    @@ -0,0 +1,82 @@
    + * Entity Embed Display reusing entity reference field formatters.
    
    +++ b/src/Tests/ViewModeFieldFormatterTest.php
    @@ -0,0 +1,55 @@
    + * Tests the view mode field formatters provided by entity_embed.
    ...
    +   * Tests view mode field formatters.
    ...
    +   * Tests filter using view mode Entity Embed Display plugins.
    

    This comments are not correct in one way or another. Review and fix them.

    Usually when we refer to "field formatter" we think "Entity Embed Display". Let's use that.

  3. +++ b/src/Plugin/Derivative/ViewModeDeriver.php
    @@ -0,0 +1,59 @@
    +    foreach ($this->entityDisplayRepository->getAllViewModes() as $entity_type => $view_modes) {
    

    $entity_type is not used.

  4. +++ b/src/Plugin/entity_embed/EntityEmbedDisplay/ViewModeFieldFormatter.php
    @@ -0,0 +1,82 @@
    + *   label = @Translation("View Mode Field Formatter"),
    

    "Field formatter" part is strange here. It can simply be "View mode".

  5. +++ b/src/Plugin/entity_embed/EntityEmbedDisplay/ViewModeFieldFormatter.php
    @@ -0,0 +1,82 @@
    +class ViewModeFieldFormatter extends FieldFormatterEntityEmbedDisplayBase {
    ...
    +  public function getFieldDefinition() {
    +    if (!isset($this->fieldDefinition)) {
    +      $this->fieldDefinition = parent::getFieldDefinition();
    +      $this->fieldDefinition->setSetting('target_type', $this->getEntityTypeFromContext());
    +    }
    +    return $this->fieldDefinition;
    +  }
    ...
    +  /**
    +   * {@inheritdoc}
    +   */
    +  public function getFieldValue() {
    +    return ['target_id' => $this->getContextValue('entity')->id()];
    +  }
    

    If we extend EntityReferenceFieldFormatter instead of FieldFormatterEntityEmbedDisplayBase we're able to get rid of this two functions entirely.

  6. +++ b/src/Plugin/entity_embed/EntityEmbedDisplay/ViewModeFieldFormatter.php
    @@ -0,0 +1,82 @@
    +    // Remove the configuration from entity_reference_entity_view. The view mode
    +    // is already set in getFieldFormatter.
    +    return [];
    

    This comment reads a bit strange. Maybe something like "Configuration form is not needed as the view mode is defined implicitly."

  7. Readme file could use an update with this change.
  8. Would be nice to have before and after screenshots.
slashrsm’s picture

Status: Needs review » Needs work
thenchev’s picture

Status: Needs work » Needs review
FileSize
7.59 KB
10.57 KB
43.08 KB

Should address the feedback above.
123

slashrsm’s picture

Status: Needs review » Needs work

Patch looks good to me. However, we need to handle BC. As @Berdir suggested we should probably create two "modes". In new mode we will make only view mode plugins available while in old mode that will be the case for Rendered entity display.

We can do this through configuration: add default config that will enable new mode and add an update hook that will enable old mode for existing sites.

Hiding should be done on UI level. All plugins should be created, but only the ones that are "active" in a given mode should be displayed in UI (button config and embed dialog). We could probably add a parameter to the plugin annotation that could be used to control display.

Please add screenshots to the issue summary.

thenchev’s picture

Status: Needs work » Needs review
FileSize
12.28 KB
19.74 KB
17.94 KB
13.36 KB

This should address BC. Not sure how to test the update hook?
after update:
old
new installation:
new

Berdir’s picture

Status: Needs review » Needs work

Looks good, just details

  1. +++ b/entity_embed.install
    @@ -43,3 +43,11 @@ function entity_embed_update_8001() {
    + */
    +function entity_embed_update_8002() {
    +  $config = \Drupal::service('config.factory')->getEditable('entity_embed.settings');
    +  $config->set('rendered_entity_mode', TRUE)->save();
    +}
    

    Can be done in a single chain, should be formatted correctyl:

    \Drupal::configFactory()
    ->getEditable()
    ->set()
    ->save()

  2. +++ b/src/Annotation/EntityEmbedDisplay.php
    @@ -53,4 +53,11 @@ class EntityEmbedDisplay extends Plugin {
    +   * Shows plugin in the UI if this is TRUE.
    +   *
    +   * @var bool
    +   */
    +  public $expose_in_ui = TRUE;
    

    The @FieldType plugin type simply uses no_ui for this flag.

  3. +++ b/src/EntityEmbedDisplay/EntityEmbedDisplayManager.php
    @@ -111,6 +127,7 @@ class EntityEmbedDisplayManager extends DefaultPluginManager {
        */
       public function getDefinitionOptionsForEntityType($entity_type) {
         $definitions = $this->getDefinitionsForContexts(array('entity_type' => $entity_type));
    +    $definitions = $this->filterExposedDefinitions($definitions);
    

    this method doesn't seem to document that it now filters.

    Given the name, that might not be obvious?

  4. +++ b/src/Plugin/Derivative/FieldFormatterDeriver.php
    @@ -58,9 +70,13 @@ class FieldFormatterDeriver extends DeriverBase implements ContainerDeriverInter
         }
    +    $mode = $this->configFactory->get('entity_embed.settings')->get('rendered_entity_mode');
         foreach ($this->formatterManager->getOptions($base_plugin_definition['field_type']) as $formatter => $label) {
           $this->derivatives[$formatter] = $base_plugin_definition;
           $this->derivatives[$formatter]['label'] = $label;
    +      if ($formatter == 'entity_reference_entity_view' && $mode == FALSE) {
    +        $this->derivatives[$formatter]['expose_in_ui'] = FALSE;
    +      }
    

    this could use a comment.

thenchev’s picture

Status: Needs work » Needs review
FileSize
7.33 KB
23.49 KB

Addressed feedback, also added test for the update hook. Its green on localhost lest see what the testbot says.

slashrsm’s picture

Status: Needs review » Needs work
Issue tags: -Needs screenshots
  1. +++ b/README.md
    @@ -49,18 +49,18 @@ Entity Embed can be installed via the
    +* If the entity you select is a node entity, for **Display as** you can choose one of the following options:
    

    Break the line to not exceed 80 chars.

  2. +++ b/src/EntityEmbedDisplay/EntityEmbedDisplayManager.php
    @@ -95,13 +93,32 @@ class EntityEmbedDisplayManager extends DefaultPluginManager {
    +  public function filterExposedDefinitions(array $definitions) {
    +    return array_filter($definitions, function($definition) {
    +      return isset($definition['no_ui']) && $definition['no_ui'] == FALSE;
    

    Should this be protected?

    We could simplify the condition with empty($definition['no_ui'])

  3. +++ b/src/Tests/EntityEmbedUpdateHookTest.php
    @@ -0,0 +1,43 @@
    +   * Tests hook_post_update_NAME().
    

    This comment is not accurate.

thenchev’s picture

This should cover #15

Status: Needs review » Needs work

The last submitted patch, 16: treat_each_view_mode_in-2736741-16.patch, failed testing.

thenchev’s picture

Status: Needs work » Needs review
FileSize
23.55 KB

Sorry, this should be ok now.

slashrsm’s picture

Status: Needs review » Fixed

Two nit-piks before committing:

diff --git a/README.md b/README.md
index 9a260f0..7c008ae 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ Entity Embed can be installed via the
 * Click on the 'E' button in the text editor.
 * Enter part of the title of the entity you're looking for and select
   one of the search results.
-* If the entity you select is a node entity, for **Display as** you can choose 
+* If the entity you select is a node entity, for **Display as** you can choose
   one of the following options:
   * Entity ID
   * Label
diff --git a/src/Plugin/Derivative/ViewModeDeriver.php b/src/Plugin/Derivative/ViewModeDeriver.php
index 76cfd82..d3870d3 100644
--- a/src/Plugin/Derivative/ViewModeDeriver.php
+++ b/src/Plugin/Derivative/ViewModeDeriver.php
@@ -64,7 +64,7 @@ class ViewModeDeriver extends DeriverBase implements ContainerDeriverInterface {
         $this->derivatives[$definition['id']]['label'] = new TranslatableMarkup($definition['label']);
         $this->derivatives[$definition['id']]['view_mode'] = $view_mode;
         $this->derivatives[$definition['id']]['entity_types'] = $definition['targetEntityType'];
-        $this->derivatives[$definition['id']]['no_ui'] = $mode ? TRUE : FALSE;
+        $this->derivatives[$definition['id']]['no_ui'] = $mode;
       }
     }
     return $this->derivatives;

Committed. Thanks!

  • slashrsm committed 3757436 on 8.x-1.x authored by Denchev
    Issue #2736741 by Denchev: Treat each view mode in "Rendered entity"...
Dave Reid’s picture

Status: Fixed » Needs review

I really really think this should have had some UX feedback or review before commit.

slashrsm’s picture

Can you tell more? What are your concerns? Is there any UX expert that wasn't involved into this or parent issue looking at this? Can we rather do it as a follow-up (setting this to "Needs review" without explaining what the plan is doesn't really mean anything)?

Dave Reid’s picture

My concerns are:
* Diverging from re-using field formatters as they exist, same as I said in #4.
* No actual UX feedback on this change (can we hop in the UX community meeting for this, before proceeding further?)

slashrsm’s picture

Status: Needs review » Fixed

Diverging from re-using field formatters as they exist, same as I said in #4.

We didn't diverge from that. We are still using field formatter to do that. It is just presented differently. Nothing changed behind the scenes.

* No actual UX feedback on this change (can we hop in the UX community meeting for this, before proceeding further?)

Definitely. Let's open a follow-up issue and continue there. EE could use a general UX review and suggestions for improvements in that area.

Status: Fixed » Closed (fixed)

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

volkerk’s picture

Status: Closed (fixed) » Needs work

With this new behaviour contact_form entities can no longer be embedded, because rendered entity setting is not available anymore. These are configuration entites with a ViewBuilder provided by contact_storage module, using rendered_entity_mode=TRUE works fine, also using core entity_reference field still works. Maybe configuration entities should be treated differently, or can there be anything done in contact_storage module?

Berdir’s picture

Status: Needs work » Closed (fixed)

Please open a new issue for this. Sounds like we need some kind of special case, although I'd expect there's a default view mode for those as well.

marcoscano’s picture