Problem/Motivation

While a user's profiles can be added to User entity, there is no way to specify the view mode.

Steps to reproduce:

  1. Create a view mode for profiles by hand: /admin/structure/display-modes/view/add/profile
  2. Create a profile entity type on /admin/people/profiles
  3. Configure profile fields on /admin/config/people/profiles/manage/[profile_machine_name]/fields.
  4. Configure the view mode display of those fields on /admin/config/people/profiles/manage/[profile_machine_name]/display.
  5. Add the Profile type's pseudo-reference field to the User entity on /admin/config/people/accounts/display and attempt to configure it to render the appropriate profile fields by selecting the view mode to use.

Expected behavior:

User should be able to specify the view mode used to embed the profile on User account.

What actually happened:

There are no options to select the view mode.

Proposed resolution

The profile field on the User entity field management form is missing the settings/widget configurator, because the Profile field is not a real field but a pseudo-field, (see https://www.webomelette.com/creating-pseudo-fields-drupal-8).

These fields do not provide any widget display because Field API cannot figure out which data type the field represents and all the rendering is made programmatically via #2629956: Profile type rendering on user view should be done as extra fields. However, the community reported other limitations:

Matt Glaman implemented one approach using computed fields to solve issue #2654980-39: Storing the active profile(s) in a field regarding the transparent recognition of these fields within entity queries on comment #39 that actually solves this issue.

There were also other relevant approaches on Issue #2654980 which were tested by @citlacom however only Matt Glaman's patch from #39 solves this issue (even though it does not solve the original problem from that issue).

We have confirmed that applying the patch from comment #39 of #2654980-39: Storing the active profile(s) in a field allows us to configure the rendered entity widget with the Profile's Teaser view mode, however it caused a regression in user migrations. So we've adapted the patch from that ticket, and moved it here to add a fix for the migration regression and added testing.

Remaining tasks

Write patch
Validate & test patch

User interface changes

Users will be able to modify the Profile pseudo-field widget settings on the User entity's "Manage Display" tab.

API changes

N/A

Data model changes

N/A,

Original issue description by jwilson3

Thanks for this module Matt!

This is the one entity type in my site that supports Fields API, Field Groups, and the new Drupal 8 field layout, but doesn't support display modes. /admin/structure/display-modes/view lists possible view modes for all my entities except for Profiles, and the /admin/config/people/profiles/manage/{profile_type}/display page is missing the "Custom display settings" collapsed fieldset.

Similarly, if I have a profile reference field configured on a node, the only view mode that comes up in dropdown of the field's display settings for "Rendered entity" is "Default".

Comments

jwilson3 created an issue. See original summary.

jwilson3’s picture

Issue summary: View changes
jwilson3’s picture

Issue summary: View changes
jwilson3’s picture

Status: Active » Closed (works as designed)
StatusFileSize
new139.4 KB
new149.16 KB

This was a huge brain fart on my part. I missed the fact that

A) profiles don't have any default view modes by design, and then
B) I didn't even think to check under the "+ Add view mode" button on the page, to see if I could actually create one from scratch.

Sure enough. Profiles can have view modes. Face, meet palm.

Closing this as works as designed with tail between legs.

jwilson3’s picture

Title: Display modes for Profiles » Display modes for embedding Profiles on User Accounts
Status: Closed (works as designed) » Active

Embedding a profile into any other entity, like a Node, via an entity reference field, works fine, as you're given the standard dropdown to select the display type and then if you choose "rendered entity" to select a view mode for the profile entity in the field display ui.

However, I'm reopening this issue and refining the title to describe the problem more accurately, because it this view mode stuff is in fact still a problem when embedding the Profile onto the User entity/page. You're not given any view modes to select from.

jwilson3’s picture

StatusFileSize
new92.12 KB

@citlacom found the root cause of the issue here configuring the widget and view mode for Profile field on the User entity.

The problem is that the profile field that is missing the settings/widget config was not a real field but a pseudo-field, (see https://www.webomelette.com/creating-pseudo-fields-drupal-8).

These fields do not provide any widget display because Field API cannot figure out which data type the field represents and all the rendering is made programmatically via #2629956: Profile type rendering on user view should be done as extra fields. However, the community reported other limitations:

Matt Glaman implemented an alternative approach using computed fields, (see https://www.drupal.org/docs/8/api/entity-api/dynamicvirtual-field-values...) on comment #39 of #2654980-39: Storing the active profile(s) in a field.

There were also other approaches on Issue #2654980 that were relevant to the problem here. @citlacom tested these and found that Matt Glaman's patch solves this issue even though it does not solve the original problem from that issue, regarding the transparent recognition of this fields within the entity queries.

We have confirmed that applying the patch from comment #39 of #2654980-39: Storing the active profile(s) in a field allows us to configure the rendered entity widget with the Profile's Teaser view mode:

I'm open to suggestions about how to move this issue forward. Obviously, we'd love to see that patch get included, but don't have enough insight onto whether that would cause regressions in other places, or if it would be save to move that patch to this issue so it could get included anyway.

@mglaman, what do you think?

citlacom’s picture

Using the original patch from Matt https://www.drupal.org/files/issues/storing_the_active-2654980-39_0.patch we have experimented problems when importing users via migrations, users that are processed for creation via migration trigger the following call at ProfileEntityFieldItemList.php:

$profile_storage->loadMultipleByUser($user, $this->getSetting('profile_type'), TRUE)

As the user is not yet saved the $user do not have an assigned uid so when the load query is executed the following condition uid is empty:

return $this->loadByProperties([
      'uid' => $account->id(),
      'type' => $profile_type,
      'status' => $active,
    ]);

This causes the exception: Query condition 'profile.uid IN ()' cannot be empty. (core/lib/Drupal/Core/Database/Query/Condition.php).

In order to solve the problem the loadMultipleByUser should execute only when the current user is not anonymous, the fix is added to the attached patch.

citlacom’s picture

Needed to re-roll the patch to apply cleanly on 8.x-1.x and generated the interdiff from 2654980-39 to 2946670-7 that is the fix for the error: Query condition 'profile.uid IN ()' cannot be empty. (core/lib/Drupal/Core/Database/Query/Condition.php).

citlacom’s picture

Changed approach to check if user profiles should be loaded for an user, needed to use id() instead of isAnonymous() entity method due was still experimenting the query condition error on profile module functional tests. This new patch should resolve those problems.

citlacom’s picture

Restored the views.view.profiles.yml view config file that was initially removed in Matt's patch but that was required to properly display profiles list when user have more than one profile at userProfileForm:

      // Render the active profiles.
      $build['active_profiles'] = [
        '#type' => 'view',
        '#name' => 'profiles',
        '#display_id' => 'profile_type_listing',
        '#arguments' => [$user->id(), $profile_type->id(), 1],
        '#embed' => TRUE,
        '#title' => $this->t('Active @type', ['@type' => $profile_type->label()]),
        '#pre_render' => [
          ['\Drupal\views\Element\View', 'preRenderViewElement'],
          'profile_views_add_title_pre_render',
        ],
      ];

Additionally I extended some tests to include configuration of the profile field on user entity to show in the default display mode. Attached an interdiff of the changes compared with Matt's initial patch.

citlacom’s picture

StatusFileSize
new13.63 KB

Correct interdiff from last patch.

citlacom’s picture

Added a testProfileFieldOnUserDisplayConfig() to check that profile field configuration at User entity display mode allow to customize the render configuration. Updated the interdiff with the last version.

citlacom’s picture

Status: Active » Needs review
Issue tags: +profile, +display fields

All tests are passed so now need help from other developers to review and confirm that all is working as expected and hopefully @mglaman can review and commit the final patch. :)

zenimagine’s picture

The rendered entity of the profile works, but in /admin/structure/display-modes/view there are no profile display modes

jwilson3’s picture

Issue summary: View changes

@zen imagine you have to create the display/view modes for Profile entity types manually on /admin/structure/display-modes/view/add/profile. I'm not entirely sure if it makes sense for us to create one out-of-the-box or not, but that could be a followup issue to this one.

I've updated the issue summary to clarify this.

zenimagine’s picture

@jwilson3

I know how to create a view mode.

The problem is that the profile view modes that it's created, are not listed on /admin/structure/display-modes/view

I have another problem. If I add the code {{ content.profile_personnel }} to the user's twig, the profile is not displayed.

zenimagine’s picture

The profile is displayed if I do not create a twig.

If I create a twig of the user display, the profile does not work.

Can you confirm ?

zenimagine’s picture

StatusFileSize
new44.7 KB

With this configuration, there is no identifier in the url :

{#
/**
 * @file
 * Default theme implementation to present all user data.
 *
 * This template is used when viewing a registered user's page,
 * e.g., example.com/user/123. 123 being the user's ID.
 *
 * Available variables:
 * - content: A list of content items. Use 'content' to print all content, or
 *   print a subset such as 'content.field_example'. Fields attached to a user
 *   such as 'user_picture' are available as 'content.user_picture'.
 * - attributes: HTML attributes for the container element.
 * - user: A Drupal User entity.
 *
 * @see template_preprocess_user()
 *
 * @ingroup themeable
 */
#}
<article{{ attributes.addClass('user--comment') }}>

  <div class="row">

    {{ content.user_picture }}
    {{ user.label }}
    {{ content.profile_personnel }}

    <div class="bs-field-link">
      <a href="/profile/{{ content.profile_personnel }}" title="{{ user.label }}"></a>
    </div>

  </div>

</article>
jwilson3’s picture

@zenimagine: This isn't really the right place for this, but please debug your Twig.

In my case, with field layout module enabled, I get this variable:

{{ content._field_layout.content.staff_profile_profiles }}

our profile type is called "staff_profile". Given that your profile appears to be named personnel, I could wager a guess that the profile should be available at either:

{{ content.personnel_profiles }}

or

{{ content._field_layout.content.personnel_profiles }}

You can use this snippet of code to figure out what sub-components are available for you to use from there:

<pre>
{% for i in content|keys %}
content.{{ i }}
{% for j in content[i]|keys %}
content.{{ i }}.{{ j }}
{% for k in content[i][j]|keys %}
content.{{ i }}.{{ j }}.{{ k }}
{% endfor %}
{% endfor %}
{% endfor %}
</pre>

Good luck.

If you're still having trouble, please open a separate support request on a separate issue and link it here so we can keep this thread limited to the original issue at hand.

jwilson3’s picture

StatusFileSize
new129.76 KB

@zenimagine:

The problem is that the profile view modes that it's created, are not listed on /admin/structure/display-modes/view

I'm not seeing this issue:

zenimagine’s picture

@jwilson3 I cleaned the cache and I do not see anything :-(

jwilson3’s picture

Issue summary: View changes
jwilson3’s picture

Issue summary: View changes
jwilson3’s picture

Issue summary: View changes
zenimagine’s picture

StatusFileSize
new166.45 KB

@jwilson3

#20 It works, but impossible to create a link to the profile (see screenshot).

<article{{ attributes.addClass('user--comment') }}>

  <div class="row">

  <a href="/profile/{{ content.personnel_profiles }}" title="{{ user.label }}">

    {{ content.user_picture }}
    {{ user.label }}
    {{ content.personnel_profiles }}

  </a>

  </div>

</article>

Before applying the patch, the {{ content.profile_personnel }} code worked

jwilson3’s picture

Issue summary: View changes
jwilson3’s picture

Creating a link to the profile is not the primary purpose of this issue. This issue is to embed the profile into the User page.

drupgirl’s picture

This is working as expected. Thank you all for your work.

yasmeensalah’s picture

I needed the patch on the rc1 version so i rerolled it to work with it.

geek-merlin’s picture

Status: Needs review » Closed (duplicate)

I'd say once the broader #2750059: Move the profile "registration" form to a field widget is fixed, anyone can leverage core's form display configuration to move and disable any profile or profile field.

super_romeo’s picture

Status: Closed (duplicate) » Needs review
StatusFileSize
new8.55 KB
new1.73 KB

1. I think it is different issue. #2750059: Profile fields to appear on manage form display for account settings is about manage form (!) display and this issue is about manage display.

2. I've fix the patch.
While creating user with:

$user = User::create([...]);

I have warning:

Automatically creating the first item for computed fields is deprecated in Drupal 8.5.x and will be removed before Drupal 9.0.0. Use \Drupal\Core\TypedData\ComputedItemListTrait instead.

Change record: ComputedItemListTrait has been added to standardize the behavior of computed fields

martijn de wit’s picture

tested screenshot
Used patch and field widget display settings appearing as expected.
Tested it with several different view modes as rendered entity.

git: dev commit "716e81dd0328bab469bf1574351c0de373d1ae9a [716e81d]"

+1 RTbC

martijn de wit’s picture

Status: Needs review » Reviewed & tested by the community

Also can be applied to "5400cebed4afe4271095f003d754e0361aba5822 [5400ceb]"

mglaman’s picture

@Martijn de Wit thanks for the screenshots! Helped test this before commit. I will be reviewing.

martijn de wit’s picture

StatusFileSize
new93.58 KB

Don't know where my screenshot did go.. uploaded it again...

mglaman’s picture

Assigned: Unassigned » mglaman

Finally sitting down so we can commit this :)

mglaman’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/src/Plugin/Field/ProfileEntityFieldItemList.php
@@ -0,0 +1,47 @@
+    // Ignore anonymous and user accounts not saved yet.
+    if ($user->id() === NULL) {
+      return [];
+    }

Anonymous user's do not have a uid of null, it is 0.

Fixing some phpcs. Will post patch with an interdiff.

mglaman’s picture

Status: Needs work » Needs review
StatusFileSize
new9.63 KB
new2.63 KB

Here is an updated patch to address #38. The problem I see is this: what about already configured extra display fields? Do we need some kind of upgrade path or just a change record so users know to reconfigure their profile displays on users?

The extra field used to be keyed ['profile_' . $bundle->id()] and now it is [$profile_type->id() . '_profiles']

mglaman’s picture

Client work and DrupalCon derailed my effort to finish this up. Since no one has replied, I am going to give it a quick test. I will probably post another patch that puts the field keys back to the way they originally were.

mglaman’s picture

StatusFileSize
new2.94 KB
new17.29 KB

Okay, I experimented with my thoughts in #40. When reusing the same keys, the following error shows up for already configured profile extra fields: Notice: Undefined index: type in Drupal\field_ui\Form\EntityDisplayFormBase->buildFieldRow() (line 367 of core/modules/field_ui/src/Form/EntityDisplayFormBase.php).

I'm going to open a change record that states end users embedding profiles on user pages will need a quick reconfigure.

Here's a new patch which removes an unused function that hacked in the View title, and the view display that used to be used.

mglaman’s picture

Status: Needs review » Needs work

The last submitted patch, 41: 2946670-41.patch, failed testing. View results

mglaman’s picture

+++ b/config/install/views.view.profiles.yml
@@ -310,70 +309,3 @@ display:
-  user_view:

+++ b/profile.module
@@ -255,25 +255,6 @@ function profile_form_user_register_form_submit(array &$form, FormStateInterface
-function profile_views_add_title_pre_render($element) {
-  /** @var \Drupal\views\ViewExecutable $view */
-  if (isset($element['#title'])) {
-    $view = $element['view_build']['#view'];
-    if (!empty($view->result)) {
-      $view->setTitle($element['#title']);
-    }
-  }

Bah, this was still needed for ProfileController::userProfileForm

mglaman’s picture

Assigned: mglaman » Unassigned
Status: Needs work » Needs review
StatusFileSize
new9.63 KB

Okay, #41 just was a bad idea. Here is #39 again. If green, merge ahoy!

  • mglaman committed 6c6702a on 8.x-1.x authored by super_romeo
    Issue #2946670 by citlacom, mglaman, super_romeo, yasmeensalah, jwilson3...
mglaman’s picture

Status: Needs review » Fixed

🎉Thanks everyone, committed.

bojanz’s picture

Title: Display modes for embedding Profiles on User Accounts » Add computed {$profile_type}_profiles fields to users, use them to render profile data on the user profile

Better title :)

Published the change record, but we'll want to flesh it out a bit too.

andyg5000’s picture

Just had the need for this when building a Search API index. Thanks y'all #partytimeexcellent

Status: Fixed » Closed (fixed)

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