Hello,

I was wondering if someone might have a solution to this problem. I've been plugging away at this for hours trying to figure out how to make this work.

I have a scenario where i have created two profile types, and each user will have two profiles. One profile stores contact information (address, city, etc) and this information through the permissions is able to be edited by the user. The second profile is information that is related to a user's membership, so things like membership ID, year joined, etc. This information is such that it can be viewed by the user, but not edited. I have created a role called 'membership admin' and they can go in and see and edit this information.

So far so good.. Profiles work as expected.

however, when trying to use views to create a profile table view and to look at the information from both profiles - per user - i cant seem to get it to show just one line containing info from both profiles. What i get is two lines per user, one with the fields from each individual profile.

So for example, id like the table to show:

Bob - 123 anystreet - anytown - 2005 - #4344 (so you see, info on the same line, but from two different profiles)

I tried creating a user view and using relationships to profiles, and creating a profiles view and create a relationship to users.

Any way i try it, i cant get around the two line output.

Maybe this is an issue in Views? Entity?

Thank you kindly.

Tom

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

joachim’s picture

Category: task » bug
Status: Active » Closed (duplicate)

> I tried creating a user view and using relationships to profiles, and creating a profiles view and create a relationship to users.

I didn't think both those relationships were available!

Anyway, the problem is that you need the user -> profile relationship to be able to restrict by profile type. Which requires some work in our views support, which is here #986430: Improve the views integration.

u8915055’s picture

Hi there joachim,

Thank you for your response. Yes, it seems the relationships part works. So far, i've tried the following:

user view with relationships to both profile and profile-type
profiles view with relationship to both profile-type and users
profile-type view with relationship to profile (no user relationship available in this one)

They all seem to work. I can grab all variables and include them in the view as necessary.

The big problem is that when it comes to users and profiles, each line is displayed per unique profile entry, not per user. So for example, if i've defined the following:

Profile1
- field : nickname

Profile2
- field : age

Then i fill out both of these profiles for a given user, say UID=3

Then when i try to create a view for users and show one line with both details, i get two lines, one per profile per user.

Effectively things need to be sort of grouped per UID and merged. I dont think there would be an opportunity for duplicate fields across multiple profiles by the way the fields are actually stored in the database (naming wise).

Anyway, just curious is to maybe it something im not doing right, or is it a views issue, or maybe entity issue.

Thank you very much for your response.
Tom

joachim’s picture

Yes, I understand the problem -- the solution is what I described in my earlier comment.

joachim’s picture

Title: Creating view with data from multiple profiles associated with same user » Views integration: create a user -> profile relationship that limits by profile type
Status: Closed (duplicate) » Active

... actually, let's work on that here as the other issue needs splitting up.

joachim’s picture

Status: Active » Needs work
FileSize
2.92 KB

Here's a patch that gets us most of the way -- the only thing that needs doing is the querying part (and writing a few bits of doxygen...)

Don't know when I'll have more time in the next week or two, so perhaps someone else can take this forward?

joachim’s picture

I did a bit more on this; we're blocked by this bug in Views: #1118100: JOIN 'extra' fails with multiple value.

joachim’s picture

Version: 7.x-1.0-beta2 » 7.x-1.x-dev
Component: Miscellaneous » Code
Status: Needs work » Needs review
FileSize
4.27 KB

Here's the patch; though the patch from the Views issue needs applying too.

u8915055’s picture

Hello joachim,

Thank you very much for the update on this. I really appreciate the work. If my coding skills were more up to date, i would help you write some of this.. Im just learning the Drupal system with hopes of being able to contribute code in future at some point.

I looked at the views patch, at least .3 of the patch and your .2 of the profile2 and ill give these a try and see where we get to.

THank you again joachim,
Tom

BazzeFTW’s picture

joachim, I tried your patch but when trying to add a relationship I get the following error:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AND _users.type IN 'teacher', '0' INNER JOIN drupal_users_roles users_roles ON u' at line 1

And in the list of relationships it says "User: Error: missing title".

joachim’s picture

Thanks for giving it a spin -- you need to also patch Views; see link above.

BazzeFTW’s picture

Hmm... After applying that patch as well i get additional error messages (well, notices actually):

    Notice: Undefined index: field i views_handler_relationship->option_definition() (rad 63 av /***/drupal-7.0/sites/all/modules/views/handlers/views_handler_relationship.inc).
    Notice: Undefined index: field i views_handler_relationship->option_definition() (rad 63 av /***/drupal-7.0/sites/all/modules/views/handlers/views_handler_relationship.inc).
    Notice: Undefined index: title i views_handler->ui_name() (rad 234 av /***/drupal-7.0/sites/all/modules/views/includes/handlers.inc).
joachim’s picture

Did you clear your Views cache?

BazzeFTW’s picture

Yes I did! When trying to access the view you get the "drupal has encountered an error"-screen and the following errors occur:

    Notice: Undefined index: field i views_handler_relationship->option_definition() (rad 63 av /***/drupal-7.0/sites/all/modules/views/handlers/views_handler_relationship.inc).
    Notice: Undefined index: field i views_handler_relationship->option_definition() (rad 63 av /***/drupal-7.0/sites/all/modules/views/handlers/views_handler_relationship.inc).
    Notice: Undefined index: base i profile2_handler_relationship_user_profile->query() (rad 45 av /***/drupal-7.0/sites/all/modules/profile2/views/profile2_handler_relationship_user_profile.inc).
    Notice: Undefined index: table i profile2_handler_relationship_user_profile->query() (rad 46 av /***/drupal-7.0/sites/all/modules/profile2/views/profile2_handler_relationship_user_profile.inc).
    Notice: Undefined index: base i profile2_handler_relationship_user_profile->query() (rad 51 av /***/drupal-7.0/sites/all/modules/profile2/views/profile2_handler_relationship_user_profile.inc).
    Notice: Undefined index: base i profile2_handler_relationship_user_profile->query() (rad 85 av /***/drupal-7.0/sites/all/modules/profile2/views/profile2_handler_relationship_user_profile.inc).
    PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AND _users.type IN ( 'teacher', '0' ) INNER JOIN drupal_users_roles users_roles ' at line 1: SELECT COUNT(*) AS expression FROM (SELECT 1 AS expression FROM {users} users LEFT JOIN {} _users ON users.profile = _users. AND _users.type IN ( :views_join_condition_0, :views_join_condition_1 ) INNER JOIN {users_roles} users_roles ON users.uid = users_roles.uid WHERE (( (users.status <> :db_condition_placeholder_0) AND (users_roles.rid = :db_condition_placeholder_1) ))) subquery; Array ( [:db_condition_placeholder_0] => 0 [:db_condition_placeholder_1] => 4 [:views_join_condition_0] => teacher [:views_join_condition_1] => 0 ) i views_plugin_pager->execute_count_query() (rad 140 av /***/drupal-7.0/sites/all/modules/views/plugins/views_plugin_pager.inc).
joachim’s picture

Did you edit your view to select a profile type in the relationship?

BazzeFTW’s picture

Yes I did. I've created a view based on Users and added the relationship, and as I mentioned earlier when adding the relationship it is named "User: Error: missing title".

joachim’s picture

Weird. I had this working perfectly on my setup.

I'm on holiday from this Saturday so I won't have any more time to look at this for a while -- over to anyone else who wants to work on this :)

> LEFT JOIN {} _users

That looks very suspicious. Have you got the very latest versions (ie git pulled) of Entity, Profile, and Views?

Jerome F’s picture

I tried creating a user view and using relationships to profiles

Configure Relationship: Broken/missing handler

The handler for this item is broken or missing and cannot be used. If a module provided the handler and was disabled, re-enabling the module may restore it. Otherwise, you should probably delete this item.

I use last git of views and profiles 2 and applied both patches.

EDIT : this is not true anymore with the patches applied I can create an User: Profile relationship

Jerome F’s picture

I tried the other way around : creating a profiles view and create a relationship to users

Here the handler exists and I can retreive user data. First problem I see with this is the one described by u8915055 the duplicate entries due to the multiple user profiles :

1) So I added the profile type relation Profile: Type
2) and then I have new filter criterias available like (Profile type) Profile type: Machine-readable name

This way I can get rid of duplicates based on profile type.
It leaves me with the struggle to pull some fields from profile type A and some fields from profile type B together in the same view for each user.
Maybe something I can do with views field view if I can't do it an other way, I'm going to play that.

Jerome F’s picture

I just want to share that in a profile view once you've added the Profile: User relationship, using this relationship, you can add an other relationship : User: Profile in which you can select which profile type you want to use.

EDIT: now that User: Profile relationships work it's useless. I can go for the user view solution, thanks to joachim's comment there I went some steps further:
http://drupal.org/node/1119130#comment-4351078

joachim’s picture

@Jerome F: I don't understand where you're going wrong with these patches. They remove the need for the filter. To make what you want, you would create:

- a user view
- add a relationship to profile, limited to profile type A
- add some fields on this relationship (so fields from type A)
- repeat for other profile types

Jerome F’s picture

Status: Needs review » Reviewed & tested by the community

@joachim: sorry I forgot to update in this issue the problems in #17 to #19 are solved, just the way you described it in #20.

So I'm changing the status of the present issue to reviewed and tested by the community, as the relationships work fine.

The problems I still had in views belong to other issues, when I wrote #17 to #19 I was still confused by these issues: I had duplicate entries for users, but that's an other issue I described in: http://drupal.org/node/1135744 I had duplicate entries in the profile table in the database.

I also had problems with views taxonomy term fields exposed filters widgets, and it turns out it's a i18n_taxonomy issue http://drupal.org/node/1135798 - not related to Profile2 in any way.

joachim’s picture

Thanks for the review!

We're still blocked by #1118100: JOIN 'extra' fails with multiple value, as soon as that goes into Views we can commit this.

joachim’s picture

In light of fago's comment here -- http://drupal.org/node/1111936#comment-4416486 -- I'm wondering whether the implementation of this needs to be rethought.

@fago: what do you think?

fago’s picture

Status: Reviewed & tested by the community » Closed (won't fix)

hm, I don't think we need profile2 specific views integration for this. You can already add the relationship + a filter on the profile type machine-name then, no?

We might want to
* add an options-list for that
* allow using the filter directly on the profile2-type db column

But this are things we should be able to improve in the entity API generically, so let's do so. If this doesn't work out, we can still go this way.

joachim’s picture

> You can already add the relationship + a filter on the profile type machine-name then, no?

Will that let you have several relationships, each to a different profile type?

fago’s picture

yep, that's possible. I just gave it a test and you can already configure it now. See my attached view.

But I agree, that the relationship-option makes sense too. I guess we can do that generically in the entity API views integration too though.

$view = new view;
$view->name = 'profiletest';
$view->description = 'test';
$view->tag = 'test';
$view->base_table = 'profile';
$view->human_name = 'profiletest';
$view->core = 7;
$view->api_version = '3.0-alpha1';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Defaults */
$handler = $view->new_display('default', 'Defaults', 'default');
$handler->display->display_options['access']['type'] = 'role';
$handler->display->display_options['access']['role'] = array(
  1 => '1',
  2 => '2',
);
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['style_plugin'] = 'table';
$handler->display->display_options['style_options']['columns'] = array(
  'pid' => 'pid',
  'id' => 'id',
  'label' => 'label',
  'module' => 'module',
  'weight' => 'weight',
  'type' => 'type',
);
$handler->display->display_options['style_options']['default'] = '-1';
$handler->display->display_options['style_options']['info'] = array(
  'pid' => array(
    'sortable' => 1,
    'default_sort_order' => 'asc',
    'align' => '',
    'separator' => '',
  ),
  'id' => array(
    'sortable' => 1,
    'default_sort_order' => 'asc',
    'align' => '',
    'separator' => '',
  ),
  'label' => array(
    'sortable' => 1,
    'default_sort_order' => 'asc',
    'align' => '',
    'separator' => '',
  ),
  'module' => array(
    'sortable' => 1,
    'default_sort_order' => 'asc',
    'align' => '',
    'separator' => '',
  ),
  'weight' => array(
    'sortable' => 1,
    'default_sort_order' => 'asc',
    'align' => '',
    'separator' => '',
  ),
  'type' => array(
    'sortable' => 1,
    'default_sort_order' => 'asc',
    'align' => '',
    'separator' => '',
  ),
);
$handler->display->display_options['style_options']['override'] = 1;
$handler->display->display_options['style_options']['sticky'] = 0;
/* Relationship: Profile: Type */
$handler->display->display_options['relationships']['type']['id'] = 'type';
$handler->display->display_options['relationships']['type']['table'] = 'profile';
$handler->display->display_options['relationships']['type']['field'] = 'type';
$handler->display->display_options['relationships']['type']['required'] = 0;
/* Relationship: Profile: User */
$handler->display->display_options['relationships']['user']['id'] = 'user';
$handler->display->display_options['relationships']['user']['table'] = 'profile';
$handler->display->display_options['relationships']['user']['field'] = 'user';
$handler->display->display_options['relationships']['user']['required'] = 0;
/* Field: Profile: Profile ID */
$handler->display->display_options['fields']['pid']['id'] = 'pid';
$handler->display->display_options['fields']['pid']['table'] = 'profile';
$handler->display->display_options['fields']['pid']['field'] = 'pid';
$handler->display->display_options['fields']['pid']['alter']['alter_text'] = 0;
$handler->display->display_options['fields']['pid']['alter']['make_link'] = 0;
$handler->display->display_options['fields']['pid']['alter']['absolute'] = 0;
$handler->display->display_options['fields']['pid']['alter']['trim'] = 0;
$handler->display->display_options['fields']['pid']['alter']['nl2br'] = 0;
$handler->display->display_options['fields']['pid']['alter']['word_boundary'] = 1;
$handler->display->display_options['fields']['pid']['alter']['ellipsis'] = 1;
$handler->display->display_options['fields']['pid']['alter']['strip_tags'] = 0;
$handler->display->display_options['fields']['pid']['alter']['html'] = 0;
$handler->display->display_options['fields']['pid']['element_label_colon'] = 1;
$handler->display->display_options['fields']['pid']['element_default_classes'] = 1;
$handler->display->display_options['fields']['pid']['hide_empty'] = 0;
$handler->display->display_options['fields']['pid']['empty_zero'] = 0;
$handler->display->display_options['fields']['pid']['format_plural'] = 0;
/* Field: Profile type: Internal, numeric profile type ID */
$handler->display->display_options['fields']['id']['id'] = 'id';
$handler->display->display_options['fields']['id']['table'] = 'profile_type';
$handler->display->display_options['fields']['id']['field'] = 'id';
$handler->display->display_options['fields']['id']['relationship'] = 'type';
/* Field: Profile type: Label */
$handler->display->display_options['fields']['label']['id'] = 'label';
$handler->display->display_options['fields']['label']['table'] = 'profile_type';
$handler->display->display_options['fields']['label']['field'] = 'label';
$handler->display->display_options['fields']['label']['relationship'] = 'type';
$handler->display->display_options['fields']['label']['alter']['alter_text'] = 0;
$handler->display->display_options['fields']['label']['alter']['make_link'] = 0;
$handler->display->display_options['fields']['label']['alter']['absolute'] = 0;
$handler->display->display_options['fields']['label']['alter']['trim'] = 0;
$handler->display->display_options['fields']['label']['alter']['nl2br'] = 0;
$handler->display->display_options['fields']['label']['alter']['word_boundary'] = 1;
$handler->display->display_options['fields']['label']['alter']['ellipsis'] = 1;
$handler->display->display_options['fields']['label']['alter']['strip_tags'] = 0;
$handler->display->display_options['fields']['label']['alter']['html'] = 0;
$handler->display->display_options['fields']['label']['element_label_colon'] = 1;
$handler->display->display_options['fields']['label']['element_default_classes'] = 1;
$handler->display->display_options['fields']['label']['hide_empty'] = 0;
$handler->display->display_options['fields']['label']['empty_zero'] = 0;
/* Field: Profile type: Module */
$handler->display->display_options['fields']['module']['id'] = 'module';
$handler->display->display_options['fields']['module']['table'] = 'profile_type';
$handler->display->display_options['fields']['module']['field'] = 'module';
/* Field: Profile type: Weight */
$handler->display->display_options['fields']['weight']['id'] = 'weight';
$handler->display->display_options['fields']['weight']['table'] = 'profile_type';
$handler->display->display_options['fields']['weight']['field'] = 'weight';
/* Field: Profile type: Machine-readable name */
$handler->display->display_options['fields']['type']['id'] = 'type';
$handler->display->display_options['fields']['type']['table'] = 'profile_type';
$handler->display->display_options['fields']['type']['field'] = 'type';
$handler->display->display_options['fields']['type']['relationship'] = 'type';
$handler->display->display_options['fields']['type']['alter']['alter_text'] = 0;
$handler->display->display_options['fields']['type']['alter']['make_link'] = 0;
$handler->display->display_options['fields']['type']['alter']['absolute'] = 0;
$handler->display->display_options['fields']['type']['alter']['trim'] = 0;
$handler->display->display_options['fields']['type']['alter']['nl2br'] = 0;
$handler->display->display_options['fields']['type']['alter']['word_boundary'] = 1;
$handler->display->display_options['fields']['type']['alter']['ellipsis'] = 1;
$handler->display->display_options['fields']['type']['alter']['strip_tags'] = 0;
$handler->display->display_options['fields']['type']['alter']['html'] = 0;
$handler->display->display_options['fields']['type']['element_label_colon'] = 1;
$handler->display->display_options['fields']['type']['element_default_classes'] = 1;
$handler->display->display_options['fields']['type']['hide_empty'] = 0;
$handler->display->display_options['fields']['type']['empty_zero'] = 0;
/* Field: User: E-mail */
$handler->display->display_options['fields']['mail']['id'] = 'mail';
$handler->display->display_options['fields']['mail']['table'] = 'users';
$handler->display->display_options['fields']['mail']['field'] = 'mail';
$handler->display->display_options['fields']['mail']['relationship'] = 'user';
$handler->display->display_options['fields']['mail']['alter']['alter_text'] = 0;
$handler->display->display_options['fields']['mail']['alter']['make_link'] = 0;
$handler->display->display_options['fields']['mail']['alter']['absolute'] = 0;
$handler->display->display_options['fields']['mail']['alter']['trim'] = 0;
$handler->display->display_options['fields']['mail']['alter']['nl2br'] = 0;
$handler->display->display_options['fields']['mail']['alter']['word_boundary'] = 1;
$handler->display->display_options['fields']['mail']['alter']['ellipsis'] = 1;
$handler->display->display_options['fields']['mail']['alter']['strip_tags'] = 0;
$handler->display->display_options['fields']['mail']['alter']['html'] = 0;
$handler->display->display_options['fields']['mail']['element_label_colon'] = 1;
$handler->display->display_options['fields']['mail']['element_default_classes'] = 1;
$handler->display->display_options['fields']['mail']['hide_empty'] = 0;
$handler->display->display_options['fields']['mail']['empty_zero'] = 0;
/* Field: User: Name */
$handler->display->display_options['fields']['name']['id'] = 'name';
$handler->display->display_options['fields']['name']['table'] = 'users';
$handler->display->display_options['fields']['name']['field'] = 'name';
$handler->display->display_options['fields']['name']['relationship'] = 'user';
$handler->display->display_options['fields']['name']['alter']['alter_text'] = 0;
$handler->display->display_options['fields']['name']['alter']['make_link'] = 0;
$handler->display->display_options['fields']['name']['alter']['absolute'] = 0;
$handler->display->display_options['fields']['name']['alter']['trim'] = 0;
$handler->display->display_options['fields']['name']['alter']['nl2br'] = 0;
$handler->display->display_options['fields']['name']['alter']['word_boundary'] = 1;
$handler->display->display_options['fields']['name']['alter']['ellipsis'] = 1;
$handler->display->display_options['fields']['name']['alter']['strip_tags'] = 0;
$handler->display->display_options['fields']['name']['alter']['html'] = 0;
$handler->display->display_options['fields']['name']['element_label_colon'] = 1;
$handler->display->display_options['fields']['name']['element_default_classes'] = 1;
$handler->display->display_options['fields']['name']['hide_empty'] = 0;
$handler->display->display_options['fields']['name']['empty_zero'] = 0;
$handler->display->display_options['fields']['name']['link_to_user'] = 1;
$handler->display->display_options['fields']['name']['overwrite_anonymous'] = 0;
/* Field: Profile type: Status */
$handler->display->display_options['fields']['status']['id'] = 'status';
$handler->display->display_options['fields']['status']['table'] = 'profile_type';
$handler->display->display_options['fields']['status']['field'] = 'status';
$handler->display->display_options['fields']['status']['relationship'] = 'type';
$handler->display->display_options['fields']['status']['alter']['alter_text'] = 0;
$handler->display->display_options['fields']['status']['alter']['make_link'] = 0;
$handler->display->display_options['fields']['status']['alter']['absolute'] = 0;
$handler->display->display_options['fields']['status']['alter']['trim'] = 0;
$handler->display->display_options['fields']['status']['alter']['nl2br'] = 0;
$handler->display->display_options['fields']['status']['alter']['word_boundary'] = 1;
$handler->display->display_options['fields']['status']['alter']['ellipsis'] = 1;
$handler->display->display_options['fields']['status']['alter']['strip_tags'] = 0;
$handler->display->display_options['fields']['status']['alter']['html'] = 0;
$handler->display->display_options['fields']['status']['element_label_colon'] = 1;
$handler->display->display_options['fields']['status']['element_default_classes'] = 1;
$handler->display->display_options['fields']['status']['hide_empty'] = 0;
$handler->display->display_options['fields']['status']['empty_zero'] = 0;
$handler->display->display_options['fields']['status']['format_plural'] = 0;
/* Field: Fields: test */
$handler->display->display_options['fields']['entity_id']['id'] = 'entity_id';
$handler->display->display_options['fields']['entity_id']['table'] = 'field_data_field_text';
$handler->display->display_options['fields']['entity_id']['field'] = 'field_text';
$handler->display->display_options['fields']['entity_id']['label'] = 'field_text';
$handler->display->display_options['fields']['entity_id']['alter']['alter_text'] = 0;
$handler->display->display_options['fields']['entity_id']['alter']['make_link'] = 0;
$handler->display->display_options['fields']['entity_id']['alter']['absolute'] = 0;
$handler->display->display_options['fields']['entity_id']['alter']['trim'] = 0;
$handler->display->display_options['fields']['entity_id']['alter']['nl2br'] = 0;
$handler->display->display_options['fields']['entity_id']['alter']['word_boundary'] = 1;
$handler->display->display_options['fields']['entity_id']['alter']['ellipsis'] = 1;
$handler->display->display_options['fields']['entity_id']['alter']['strip_tags'] = 0;
$handler->display->display_options['fields']['entity_id']['alter']['html'] = 0;
$handler->display->display_options['fields']['entity_id']['element_label_colon'] = 1;
$handler->display->display_options['fields']['entity_id']['element_default_classes'] = 1;
$handler->display->display_options['fields']['entity_id']['hide_empty'] = 0;
$handler->display->display_options['fields']['entity_id']['empty_zero'] = 0;
/* Filter criterion: Profile type: Machine-readable name */
$handler->display->display_options['filters']['type']['id'] = 'type';
$handler->display->display_options['filters']['type']['table'] = 'profile_type';
$handler->display->display_options['filters']['type']['field'] = 'type';
$handler->display->display_options['filters']['type']['relationship'] = 'type';
$handler->display->display_options['filters']['type']['exposed'] = TRUE;
$handler->display->display_options['filters']['type']['expose']['operator_id'] = 'type_op';
$handler->display->display_options['filters']['type']['expose']['label'] = 'Profile type';
$handler->display->display_options['filters']['type']['expose']['operator'] = 'type_op';
$handler->display->display_options['filters']['type']['expose']['identifier'] = 'type';
$handler->display->display_options['filters']['type']['expose']['required'] = FALSE;
$handler->display->display_options['filters']['type']['expose']['multiple'] = FALSE;

/* Display: Page */
$handler = $view->new_display('page', 'Page', 'page_1');
$handler->display->display_options['path'] = 'profile-view';
$handler->display->display_options['menu']['type'] = 'normal';
$handler->display->display_options['menu']['title'] = 'Profiles';
$handler->display->display_options['menu']['weight'] = '0';
$handler->display->display_options['menu']['name'] = 'main-menu';
$translatables['profiletest'] = array(
  t('Defaults'),
  t('more'),
  t('Apply'),
  t('Reset'),
  t('Sort by'),
  t('Asc'),
  t('Desc'),
  t('Items per page'),
  t('- All -'),
  t('Offset'),
  t('Profile type'),
  t('User'),
  t('Profile ID'),
  t('.'),
  t(','),
  t('Internal, numeric profile type ID'),
  t('Label'),
  t('Module'),
  t('Weight'),
  t('Machine-readable name'),
  t('E-mail'),
  t('Name'),
  t('Status'),
  t('field_text'),
  t('Page'),
);
Jerome F’s picture

So why is this still won't fis if the relationship-option makes sense, I don't get it? The patch here did work with the views patch in #1118100 and the result was good.

I guess the answer is in:

I guess we can do that generically in the entity API views integration too

but this is beyond the scope of my knowledge in Drupal.

For the moment, I keep my views running with these patches and I'm prepared to change these views when your alternative will be ready.

fago’s picture

Jerome F’s picture

#1118100: JOIN 'extra' fails with multiple value has been commited

bochen87’s picture

Status: Closed (won't fix) » Reviewed & tested by the community

The patch in #7 works very well and should be commited to the latest dev version. The reson why to use this patch instead of the workaround with Profile relationship + filter is:
If you have certain profile types, that are optional, then all the users that did not fill out the optional profile, will be filtered out by the where clause. But if you do this in the Join, then you can leave them in the result by doing the regular filter and making an or with the profile to be empty. This way, you could also add optional profiles.

fago’s picture

Status: Reviewed & tested by the community » Needs work

If you have certain profile types, that are optional, then all the users that did not fill out the optional profile, will be filtered out by the where clause. But if you do this in the Join, then you can leave them in the result by doing the regular filter and making an or with the profile to be empty. This way, you could also add optional profiles.

That's an argument.

Let's do it in the entity API for all relations to entities having a bundle though.

geshido’s picture

subscribe

joachim’s picture

I don't think we can do all of this in EntityAPI:

+++ b/views/profile2.views.inc
@@ -0,0 +1,15 @@
+  // Use our relationship handler for user->profile to give limiting options.
+  $data['users']['profile']['relationship']['handler'] = 'profile2_handler_relationship_user_profile';

We can't do this part in EntityAPI -- only each entity knows how it relates to others.

+++ b/views/profile2_handler_relationship_user_profile.inc
@@ -0,0 +1,87 @@
+    foreach (profile2_get_types() as $type => $info) {
+      $options[$type] = $info->label;
+    }

What's the EntityAPI equivalent of this bit?

I reckon we can move the relationship handler to EntityAPI, but it's have to be each entity's hook_views_data_alter() that makes use of that to define relationships to other entities.

fago’s picture

>We can't do this part in EntityAPI -- only each entity knows how it relates to others.
Well, the entity API knows about the bundle relationship and this is exactly what we need here. If the entity for which we are adding a relationship has a known bundle entity, provide the option.

>What's the EntityAPI equivalent of this bit?
Using entity_label(). Also, there is already EntityDefaultMetadataController::bundleOptionsList() which handles the same case by getting it from entity-info.

dalanz’s picture

subscribe

kthull’s picture

It looks like some people in the thread consider this resolved. I don't see how. Specifically regarding #18 and #20 and #26, I am still getting a separate result per profile type, so in my case I get two rows per user. I've read through this several times last night and even a fresh look today trying various views from either a user, profile or profile type base table and I'm getting nowhere.

Even importing the view from #26, I still get two rows of results per user.

Is there any way combine fields from profileA and profileB into one views row?

EDIT: Applied patch from #7 and still get a separate result per profile type and I'm running the latest (as of two days ago) devs for both views and profile2.

joachim’s picture

Hmm actually, just spotted another problem doing this in entityAPI.

We want a user->profile relationship. That means we define a field on the users base table. Which means we need to do it in hook_views_data_alter().

Obviously, the controller class we create in entity_views_data() can figure out what it needs to say about the users table, but how do we hang on to that information until hook_views_data_alter() is invoked?

(@kthull: nope, this isn't resolved. More work is needed, but it's quite a complex issue.)

joachim’s picture

Title: Views integration: create a user -> profile relationship that limits by profile type » Views integration: create an entity-entity relationship that limits by entity type if applicable
Project: Profile 2 » Entity API
Component: Code » Code - misc
Category: bug » feature
Status: Needs work » Needs review
FileSize
9.44 KB

Moving to Entity API. And I guess it's a feature request here -- even though this missing functionality is a bug in Profile2 ;)

Here's a patch. Try creating a relationship from users to profile2 to see how it works :)

The logic for when we use the type-limiting handler is:

- going to a single-bundled entity, eg user: use regular relationship
- going to a bundled entity, BUT coming from the entity that is the bundle, eg profile type -> profile: use a regular relationship, as limiting by type here is meaningless
- anything else that has a multi-bundled entity on the right: use the new type-limiting relationship

For this, I've had to add a property 'single-bundled' to the entity info.

crifi’s picture

joachim’s picture

Nope. It adds a better relationship handler to both forward and reverse relationships.

crifi’s picture

Okay, thanks joachim for the clarification.

fago’s picture

Status: Needs review » Needs work

oh, great - thanks for working on that. I've done a first review:

+++ b/entity.api.php
@@ -33,6 +33,9 @@
+ * - single-bundled: Whether the entity has more than one bundle, or is capable
+ *   of having more than one. Eg, 'user' is single-bundled; 'node' is not, even
+ *   if there is currently only one node type defined.

There is an easy way to derive that information already: check whether there is a bundle key given under entity keys ( just check whether it's not empty).

+++ b/views/entity.views.inc
@@ -147,25 +147,30 @@ class EntityDefaultViewsController {
+        'entity type' => $this->type,

You should be able to read this out of the base-table already?
E.g. see the views_handler_field_entity in Views.

+++ b/views/entity.views.inc
@@ -302,6 +307,40 @@ class EntityDefaultViewsController {
+    // If the right side of the relationship join has multiple bundles, then we
+    // use our relationship handler that allows the relationship to be limited
+    // by bundle.

I guess this comment should be moved to the else part.

+++ b/views/handlers/entity_handler_relationship_limit_type.inc
@@ -0,0 +1,100 @@
+ * or more entity types.

It limits the join to a specific bundle of an entity type. (Yes, in our case that are entities too, but using bundle here should make clearer of what we are talking here.)

+++ b/views/handlers/entity_handler_relationship_limit_type.inc
@@ -0,0 +1,100 @@
+    $form['entity_type'] = array(
...
+      '#description' => t('Restrict this relationship to one or more @entity types. Selecting more than one type may produce duplicate rows.', array(

The same way, I think we should call this bundle/bundles instead of entity-type(s).

joachim’s picture

> You should be able to read this out of the base-table already?
E.g. see the views_handler_field_entity in Views.

I didn't think so -- eg with profile2, we have profile / profile2. I looked in the data the view handler has at that point, and it's not there.

> The same way, I think we should call this bundle/bundles instead of entity-type(s).

That's UI text -- in the UI we say 'types' surely?

fago’s picture

It must be there, see EntityDefaultViewsController::views_data():

      $data[$table]['table']['base'] = array(
        'field' => $this->info['entity keys']['id'],
        'title' => drupal_ucfirst($this->info['label']),
        // @todo: Support an entity info description key or such?
        'help' => '',
        'entity type' => $this->type,
      );
That's UI text -- in the UI we say 'types' surely?

Makes sense. So what about using the bundle-entity-type-label in the UI + "bundle" as options key?

joachim’s picture

But when you're adding a relationship, your relationship handler doesn't have the data for the base table you're joining to. I suppose I could go pull it out of the whole big views data stuff...

fago’s picture

it recently got fixed in Views to be located at the table not on the base table level. We'll have to adapt to that location in the entity api too - see #1270982: only base-tables can be assigned to entity types

joachim’s picture

> single-bundled

Yup, that's a much easier test. I've used it directly, though on second thoughts I think the 'single-bundled' flag on entities could prove useful to other modules for developers who don't manage to figure out the sniffing technique... what do you think?

> You should be able to read this out of the base-table already?

Yup, done.

> I guess this comment should be moved to the else part.

Moved the comments. Though I'm never entirely sure where makes more sense for if/else comments. I like a comment above to if() to explain what is being tested.

> So what about using the bundle-entity-type-label in the UI + "bundle" as options key?

Not sure what you mean there. Is there callback that given 'node' says 'type' and given 'term' says 'vocabulary'?

Do you want the string 'type' replaced with 'bundle' in the name of the class & other parts of the code?

rlmumford’s picture

Was going review this but it didn't apply - entity api dev version as of today.
entity.views.inc patch does not apply

joachim’s picture

Here's a patch rerolled against latest from git, with the changes mentioned in #47. Still needs some work based on fago's comment, but a review of functionality would be great.

rlmumford’s picture

Functionality seems to be good.

If this is now a standard thing for entities it would be good for the Add field dialogue to show Entity:Bundle:Field rather than just Entity:Bundle

joachim’s picture

@fago: Could you take a look at my comments in 47 please? I've addressed everything in your review except points I'm not clear on.

fago’s picture

Yup, that's a much easier test. I've used it directly, though on second thoughts I think the 'single-bundled' flag on entities could prove useful to other modules for developers who don't manage to figure out the sniffing technique... what do you think?

Yep, but the information is still there and defined by core- so we should not add another duplicating key. Making the existing information simpler should be a core issue.

Moved the comments. Though I'm never entirely sure where makes more sense for if/else comments. I like a comment above to if() to explain what is being tested.

Imho the comment should be at the place of the code that is commented. When reading your patch, I was confuse because it says it is using another handler but goes with the views default handler.

It's fine to just have a comment before the else block.

if ( foo ) {
 do
}
// Comment why else bar.
else {
  bar
}
Not sure what you mean there. Is there callback that given 'node' says 'type' and given 'term' says 'vocabulary'?

Yes, in case of enttiy.module bundles yep. We have a key which says 'bundle of' in entity-info, thus profile-type is the 'bundle-of' profile.

joachim’s picture

> Yes, in case of enttiy.module bundles yep. We have a key which says 'bundle of' in entity-info, thus profile-type is the 'bundle-of' profile.

But that is not the way round we need here.

Given 'profile2', how do I get 'profile-type'? Or rather, how do I get a nice user-facing string that says 'type'?

What I need is this mapping from entity machine name to human label for the bundle name:

'term' => 'vocabulary'
'node' => 'type',
'profile2' => 'type'

In the meantime, here is a reroll to account for recent changes in the module.

fago’s picture

You'll have to loop over all entity-types to find the right one. Still, it won't work that way for terms <-> vocabularies as those don't use that key. It's an entity.module specific one, but that should be fine as the generated views integration is for entities provided with the entity.module too.

joachim’s picture

> You'll have to loop over all entity-types to find the right one.

Isn't that a bit expensive?
Is this something entity API could add to the info it has cached?

fago’s picture

> You'll have to loop over all entity-types to find the right one.

Nope, that's not a big deal. It's more ugly than expensive. Also, it's done during UI configuration only.

>Is this something entity API could add to the info it has cached?
I don't like duplicating the info in hook-entity-info as it would confuse people which one they have to provide.

joachim’s picture

The string I get is 'Profile type'. I need to make that plural for the UI -- we seem to be missing 'plural label' on profile module's entity info?

Also, in the case where there is no entity type with a 'bundle of' key, we need a fallback. That should be 'Foobar type' IMO, as 'bundle' is a term that is unseen in the Drupal UI -- it's only in code.

In which case, we need a string that's either:

- Restrict this relationship to one or more @entity_type_label
- Restrict this relationship to one or more @entity types

which is getting really messy.

fago’s picture

The string I get is 'Profile type'. I need to make that plural for the UI -- we seem to be missing 'plural label' on profile module's entity info?

Oh, yes we need to add that. I'd default to just appending a 's'.

Also, in the case where there is no entity type with a 'bundle of' key, we need a fallback.

If we don't have that, we don't know the database table, do we? I guess we should restrict the handler only to entity types that have that relation/key.

joachim’s picture

> Oh, yes we need to add that. I'd default to just appending a 's'.

That's not going to allow translations...

joachim’s picture

Status: Needs work » Needs review
FileSize
8.71 KB

I think this will work.

I'll file a patch to add the missing plural label to profile 2, but that won't hold this up as it has a fallback to use 'type'.

fago’s picture

Thanks, I took a stab on that and re-worked it.

* Restricted it to 'bundle of' relations only. Others might won't work correctly anyway as the bundle-key might not have a respective query column, as for term-vocabs. We want it for 'bundle of' relations, let's do it for them.
* Use 'bundle types' as views settings key and simplified the form generation code.
* Simplified class-detection logic.
* Renamed handler and file to fit the "entity_views" namespace. we'll fix the other views integration too.

Patch works for me. -> attached.

joachim’s picture

Status: Needs review » Needs work
+      // If there is bundle entity for the given entity-type allow filtering
...
+      // the relation by bundle. Exception: If joined from the bundle entity
...
+      // we do not need to filter by bundle entity any more.
...
+      if (!empty($info['bundle of']) && $info['bundle of'] == $entity_type && $type != $left_type) {
...
+        return 'entity_views_handler_relationship_by_bundle';
...
+      }

You're the maintainer so it's down to how you find code easier to understand, but I can't follow complex if statements like this one at all, not even when I read the comments.

Also I don't understand the return inside the foreach loop.

+++ b/views/entity.views.inc
@@ -309,6 +309,26 @@ class EntityDefaultViewsController {
+      // If there is bundle entity for the given entity-type allow filtering
+      // the relation by bundle. Exception: If joined from the bundle entity
+      // we do not need to filter by bundle entity any more.
+      if (!empty($info['bundle of']) && $info['bundle of'] == $entity_type && $type != $left_type) {
+        return 'entity_views_handler_relationship_by_bundle';

You're the maintainer so it's down to how you find code easier to read. But even reading the comment, this sort of complex if statement is greek to me :(

+++ b/views/handlers/entity_views_handler_relationship_by_bundle.inc
@@ -0,0 +1,116 @@
+    $plural_label = isset($entity_bundle_info['plural label']) ? $entity_bundle_info['plural label'] : $entity_bundle_info['label'] . 's';

Translators will really not like this.

+    $plural_label = isset($entity_bundle_info['plural label']) ? $entity_bundle_info['plural label'] : $entity_bundle_info['label'] . 's';

This really will have translators up in arms.

fago’s picture

Status: Needs work » Needs review

Translators will really not like this.

Yep, it's just the default value in case nothing else is provided. If modules provide the plural label everything is fine. We could just show the single label in that case too though. What do you think is the better option?

You're the maintainer so it's down to how you find code easier to understand, but I can't follow complex if statements like this one at all, not even when I read the comments.
Also I don't understand the return inside the foreach loop.

What's wrong with the return in the foreach loop? It's like break, but just returning immediately.

@if: hm, the comment should explain it. a) we are looking for bundle of == $entity type and b) it may not equal the left-type: "Exception: If joined from the bundle entity we do not need to filter by bundle entity any more"

Maybe you could suggest an improved if statement? Or we just split it up in two nested ifs with two separate comments?

joachim’s picture

> What's wrong with the return in the foreach loop? It's like break, but just returning immediately.

Yeah but for the first thing that's found in entity_get_info(). Won't that always be 'comment'?

fago’s picture

>Yeah but for the first thing that's found in entity_get_info(). Won't that always be 'comment'?
Nope - it's looking for the entity which is the bundle of the passed entity.

Is it clearer that way?

fago’s picture

including the include...

fago’s picture

Status: Needs review » Fixed

I hope so - if not let's fix it in a follow-up. Committed.

joachim’s picture

@Fago: I think it's down to personal preference. You have a code style which I tend to find fairly dense, with complex expressions and statements. I prefer to lay things out in smaller chunks. You're the maintainer here, it's your choice :)

mh86’s picture

Status: Fixed » Needs review
FileSize
1.31 KB

The relationship handler doesn't work if no bundle type is selected (then '0' is used as bundle type). Furthermore, 'type' is used as field for the bundle key, which definitely isn't true for all entity types.
Attached patch fixes both issues.

fago’s picture

Status: Needs review » Fixed

thanks, committed.

ltiong’s picture

Still unable to solve the issue in the original post: getting duplicate Users in View when using Profile2.

I've just done a clean install with (modules available as of 11/11/2011):
drupal-7.9
ctools-7.x-1.0-rc1
entity-7.x-1.0-rc1
profile2-7.x-1.1
views-7.x-3.0-rc1

1. clean install of D7 & modules;
2. created (2) Profile2 types: Main & Education;
3. created Fields for Profile2 types;
4. created (2) Users and added Profile2 data;
5. created View (Show:User) and added User:Profile as relationship (checked boxes corresponding w/ Profile2 types);
6. i get duplicate user entries -- one corresponding to each Profile2 type.

What am I doing wrong?

ltiong’s picture

Nvm..got it working. While creating the View (step 5 above):

5.1 create View (Show:User)
5.2 add relationship, (User:Profile); give the Identifier a unique name ie 'MainProfile'; select a single checkbox for 'Profile type', in my case 'Main profile';
5.3 add another relationship, (User:Profile); give the Identifier a unique name ie 'EducationProfile'; select the other checkbox for 'Profile type', in my case 'Education profile';
5.4 add Fields to view; select Profile2 field items; use Relationship dropdown in 'Configure field' to associate w/ correct relationship;

joachim’s picture

Bingo -- you need one relationship per profile type you want in the view :)

Might be a good idea to add this to a docs section on using Views with Profile2?

Status: Fixed » Closed (fixed)

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

sreekanth1201’s picture

Assigned: Unassigned » sreekanth1201
Priority: Normal » Critical
Status: Closed (fixed) » Active

Hi am adding a module entity relationship..am getting an error like below

Describe arbitrary relationships between entities
Required by: Entity Relationships UI (disabled), Entity Relationships Views (disabled)

even i enabled them.I want to giv a relation between the content types.can any one suggest a good tutorial using this module..

Thanks

crifi’s picture

Assigned: sreekanth1201 » Unassigned
Priority: Critical » Normal
Status: Active » Closed (fixed)

Please do not hijack closed issues. You can open a new support issue instead.

rhlb91’s picture

thank u guys ,it really worked for me what i want ...
thanks a lot

kristiaanvandeneynde’s picture

Issue summary: View changes
Status: Closed (fixed) » Needs review
FileSize
1.13 KB

The latest commit in this issue incorrectly uses "bundle keys" instead of "entity keys".
I've attached a patch that fixes this.

Long version:

$info['entity keys']['bundle'] = 'the property on the entity itself that stores the machine name of its bundle entity';
$info['bundle keys']['bundle'] = 'the property on the bundle entity that stores its machine name';

So for instance for the Group project, a Group entity references its Group Type through the 'type' property. A Group Type, however, stores its machine name in its 'name' property. So for a Group entity, the relevant entity info would look like this:

$info['entity keys']['bundle'] = 'type';
$info['bundle keys']['bundle'] = 'name';

Seeing as a Group entity does not have a 'name' property, the handler created in this issue throws an error until fixed with the attached patch.

joachim’s picture

For an issue that's been closed for this long, it's really better to file a new issue...

(Good catch though!)

klausi’s picture

Status: Needs review » Reviewed & tested by the community

Indeed a good catch. You will only encounter this with entity types that use a different name for the type on the type object. For example node and profile2 use "type" on the entity and on the entity type class, so they are not affected. Message and I assume OG use "type" on the entity and "name" on the entity type, and that's where it breaks.

Example symptom in message module: #2275091: Unknown column 'message_users.name'.

So this looks RTBC to me.

kristiaanvandeneynde’s picture

Status: Reviewed & tested by the community » Closed (fixed)

The new issue for this one is here: #2309697: Fix variable mistake in entity_views_handler_relationship_by_bundle
Forgot to mark this one as "Closed (fixed)" again (added a child issue).

nehapandya55’s picture

Thanks ltiong #72 worked for me.