We use Views 2 to create an automated address book of all our site members. Members, however, must be able to specify what private information they want to appear in the address book - and we want to use Profile Privacy for that.

When using Views 2 to create the address book - ie. a lists of users - Views seems to be unable to see the privacy settings for different fields, as set by Profile Privacy - which is a great, great pity.

Would there be any way for Profile Privacy to work with Views - or for Views to be aware of the field settings of Profile Privacy?

Many thanks in advance for your fantastic work - it's very much appreciated.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

icouto’s picture

Please note, that I've posted this request in the Profile Privacy queue, rather than in the Views queue, because of the following warning that appears when we try to create a new ticket in Views:

If you only read one of these submission guidelines, read this one. (Then please read the rest) If your problem deals exclusively with fields or filters provided by another module (CCK, Image, VotingAPI are common) please post the issue under the queue for that module first; all modules are responsible for telling Views about their own fields. It's possible Views IS at fault, but the module maintainers are the best people to make that determination, and they can kick the issue into the Views queue with an explanation of what's wrong if that is the case.

Once again, many thanks in advance for any and all help! :-)

quicksketch’s picture

Thanks, this is definitely a better place to post. Great job reading guidelines! Merlinofchaos would be proud :)

Regarding the issue, this should technically be possible with Privacy Profile, however I'm barely maintaining the module, so it's likely that any additions will need to be provided through a patch (which I'd be glad to apply). Unfortunately I don't have the time to invest in this particular problem.

gausarts’s picture

subscribing, thanks

milos1234’s picture

subscribe.... big time

finfin82’s picture

Status: Active » Needs work

Hi,
i solved this problem by adding the following views_query_alter hook to profile privacy.
i allready extended my profile privacy to work with user relationships so it could be, that you have to fit the PROFILE_PRIVACY_BUDDIES <-- etc defines to your needs

maybe this could be useful for somebody,
cheers finfin

btw: the user_relationship implementation will be commited as well, if i find the time to tidy up my code ;-)
this will see the first views arg as user-id ... mayb this information is better grabbed form anywhere else
i guess there is an error in reasoning in this case :-) the $view->args[0] should be the userid of the actual resulted user.... so forget about this solution ;-(

may be this will push someone in the right direction

/**
 * hook_views_query_alter implementation
 * @global object $user
 * @param object $view
 * @param object $query
 */
function profile_privacy_views_query_alter(&$view,&$query)
{
    global $user;
    
    $hide_field = array();
    foreach($query->table_queue as $tablekey=>$table)
    {
        if($view->args[0]==$user->uid||$user->uid==1)//skip if we are the user, or user is superadmin
            continue;
        if(eregi('profile_values',$tablekey))//we have a profile_value alias here
        {
            $fieldname = str_replace('profile_values_', "", $tablekey);
            
            //check the privacy-setting for this user and fieldname
            $privacy = profile_privacy_get_user_field_privacy($view->args[0], $fieldname);
            if($privacy)
            {
                if($privacy==PROFILE_PRIVACY_BUDDIES)//privacy-kind friends
                {
                    //check if related users are friends
                    if(user_relationships_api_socnet_is_related($user->uid, $view->args[0]))
                    {
                        //dont hide
                    }
                    else
                    {
                        $hide_field[] = $tablekey;
                    }
                }
                elseif($privacy==PROFILE_PRIVACY_PRIVATE)
                {
                    //hide generally
                    $hide_field[] = $tablekey;
                }
            }
        }
        
    }
    if(!empty($hide_field))
    {
        foreach ($hide_field as $tablealias)
        {
            //unset those fields, so they wouldnt exist in result
            unset($view->query->fields[$tablealias.'_value']);

        }
    }
    /*
    else
        //nothing
     *
     */
}
finfin82’s picture

I tried to solve the problem with another approach.
I tried to use the preprocess_views_view_field function

function phptemplate_preprocess_views_view_field(&$vars)
{
  global $user;
  $hide_field = array();
  foreach($vars['row'] as $key=>$row_val)
  {
      if($key=='uid'||$key=='users_user_relationships_uid')
        $userid=$row_val;
        
      if(eregi('profile_values_',$key))//profilfeld?
      {
            
            $fieldname = str_replace(array('profile_values_','_value'), "", $key);
            #echo 'fname:'.$fieldname.'<br>';
            #echo 'userid:'.$userid.'<br>';
            $privacy = profile_privacy_get_user_field_privacy($userid, $fieldname);
            #echo 'privacy:'.$privacy.'<br>';
            if(!empty($privacy))
            {
                if($privacy==PROFILE_PRIVACY_BUDDIES)
                {
                    //checken ob ich freund von args[0] bin
                    if(user_relationships_api_socnet_is_related($user->uid, $userid)||$user->uid===$userid)
                    {
                        //feld nicht verstecken
                    }
                    else
                    {
                        #$hide_field[$tablekey][] = "'".$query->table_queue[$tablekey]['join']->definition['extra'][0]['value']."'";
                        $hide_field[] = $key;
                    }
                }
                if($privacy==PROFILE_PRIVACY_PRIVATE)
                {
                    #echo "verstecke: ".$key.'<br>';
                    //generell verstecken
                    #$hide_field[$tablekey][] = "'".$query->table_queue[$tablekey]['join']->definition['extra'][0]['value']."'";
                    $hide_field[] = $key;
                }
            }//end if privacy
      }//end if profile field
      //echo $key.':'.$row_val.'<br>';
  }//end foreach
  
  foreach($hide_field as $field2hide)
  {
      #echo "verstecke: $field2hide mit dem wert:  ".$vars['row']->$field2hide.'<br>';
      unset($vars['row']->$field2hide);
      $vars['row']->$field2hide="";
  }

  
  $vars['output'] = $vars['field']->render($vars['row']);
  #var_dump($vars['field']);
}

but although i unset or empty the content of $vars['row']->$field2hide it's shown in the view-result on page,
so how do i unset a fields content, that it's no longer shown in result.

maybe merlinofcaos can help here?
cheers finfin

kentr’s picture

I know little about views, so please forgive my ignorance.

Could this be better solved with a profile "relationship" for views that automatically detects the privacy of an individual field and hides it at the query level?

ardi1983’s picture

I found a solution to this problem in the template that views supplies , using a function of profile_privacy module that return 1 in case of private and 0 in case of public field, the function is: profile_privacy_get_user_field_privacy($uid, $field_name), i take the user from the url... hope I can help someone :D :D :D

<?php
$user_load=user_load(array('uid' => arg(1)));

 foreach ($fields as $id => $field): 

      $handler=$field->handler;
      $temp=explode("_",$handler->options['table']);

 if (!profile_privacy_get_user_field_privacy($user_load->uid,$temp[2]."_".$temp[3])): 
 if (!empty($field->separator)): 
print $field->separator; 
endif; ?>
  <<?php print $field->inline_html;?> class="views-field-<?php print $field->class; ?>">
    <?php if ($field->label): ?>
      <label class="views-label-<?php print $field->class; ?>">
        <?php print $field->label; ?>:
      </label>
    <?php endif; ?> 
      <<?php print $field->element_type; ?> class="field-content"><?php print $field->content ?></<?php print $field->element_type; ?>>
  </<?php print $field->inline_html; ?>>
<?php endif; endforeach; ?>
kentr’s picture

Assigned: Unassigned » kentr

I'm pretty close to getting a patch for this.

kentr’s picture

Here's a beta patch. I got confused with Profile Privacy's access restrictions, so I ended up starting from scratch on the access specs.

This patch could be a separate module if necessary. Please indicate whether this is likely to be added to Profile Privacy, and if not I'll post it as a separate module.

 

Access specifications:

  • For PROFILE_PUBLIC_LISTING fields, default to public.
    (Profile module's specification: "content shown on profile page and on member list pages.")
  • For PROFILE_PUBLIC fields, default to private.
    (Profile module's specification: "content shown on profile page but not used on member list pages.")
  • For PROFILE_PRIVATE fields, default to private.
    (Profile module's specification: "content only available to privileged users.")
  • Users can override any of the above for their individual profiles.

    This means that for the purposes of Views, PROFILE_PUBLIC and PROFILE_PRIVATE are treated the same.

  • For PROFILE_HIDDEN fields, field is not displayed at all in the view unless the viewer has 'administer users' privileges. This is helpful for having one view that serves both admins and regular users.
    (Profile module's specification: "only accessible by administrators, modules and themes.")

    This behavior can be overridden as described below.

Additional features:

  • Each field now has two additional options in the Views configuration:
    • Replacement text for private fields.
    • Admin-override for PROFILE_HIDDEN fields.  If this option is checked for the field, the field will display in the view regardless. This option is only available to users with 'administer users' priviliges.

      Users cannot further override this setting because they cannot set Profile Privacy options on these fields on the Profile edit page. In the event that the field was formerly a status other than PROFILE_HIDDEN, there may be residual per-user Profile Privacy settings for the field.  If so, those settings are ignored.

      This feature is useful for Profile fields that you want displayed but kept non-editable by the users.
  • Private fields are wrapped with <span class="private"></span>.

Known issues:

  • There may be a "security hole" with the PROFILE_HIDDEN override config:  The form element for overriding only appears to certain users, but nothing was changed in the form validation.  It's possible that a user with 'administer views' privileges could hack a simulated form submission change the setting.  Since the user still must have 'administer views' priviliges to do so, I consider this a low risk issue.
  • The wrapper markup for private fields is hard-coded and possibly not overridable at the theme level.
  • The wrapper markup for private fields appears even if "Hide if empty" is set for the field.  I consider this a high priority for bandwith and theming reasons.
  • This hasn't been tested against the views data export modules, so the hard-coded markup might cause issues there as well. I will need to test against data export modules soon. UPDATE: It's working with the http://drupal.org/project/views_bonus CVS export.
coltrane’s picture

Status: Needs work » Needs review

This is great, I haven't reviewed yet but hope to soon. I've been neglecting this module :(

ac’s picture

Patch is working well for me so far. Will report any issues I find.

ac’s picture

So far this is working perfectly. Anyone else tested? Too premature to mark RTBC?

The only issue that I have (which was listed as known by the author) is "The wrapper markup for private fields appears even if "Hide if empty" is set for the field. I consider this a high priority for bandwith and theming reasons."

I assume this is because "Private fields are wrapped with " but I may be wrong.

kentr’s picture

The only issue that I have (which was listed as known by the author) is "The wrapper markup for private fields appears even if "Hide if empty" is set for the field. I consider this a high priority for bandwith and theming reasons."

I assume this is because "Private fields are wrapped with " but I may be wrong.

Yes. I've been unable to dig into the views system enough to find a better solution. Feel free to patch the patch ;-).

The code you're looking for is in the render() methods of each of the custom views handlers. It could be as simple as adding an "if not empty..." condition.

Ideally, the HTML would be moved to a theme function or template. Just haven't figured that part out yet.

But I also request that we don't let that be an obstacle to getting the patch committed.

coltrane’s picture

Status: Needs review » Needs work

Right on, patch applies and works great. The wrapping HTML won't keep this patch from getting in. Thank you kentr for writing this and ac et al for testing.

I noticed some issues with replacement user-supplied text that should be handled. It's all the handlers like below.

+++ views/handlers/profile_privacy_views_handler_field_profile_date.inc	(revision 736)
@@ -0,0 +1,40 @@
+  function render($values) {
+    if (_profile_privacy_views_field_access($values->uid, $this->definition['profile_privacy_field_name'], $this)) {
+      return parent::render($values);
+    }
+    else {
+      return '<span class="private">' . t($this->options['profile_privacy_replacement_text']) . '</span>';
+    }
+  }

If you want to allow for translating, that's fine, but this does not escape the replacement text. Use check_plain() or variable substitution (@text) instead. Unless there's a Views-specific way to handle this.

+++ views/handlers/profile_privacy_views_handler_field.inc	(revision 736)
@@ -0,0 +1,40 @@
+      return '<span class="private">' . t($this->options['profile_privacy_replacement_text']) . '</span>x';

And here. Also, what's with the ending 'x'?

The form element for overriding only appears to certain users, but nothing was changed in the form validation. It's possible that a user with 'administer views' privileges could hack a simulated form submission change the setting.

@kentr, are you implying someone could POST to the Views edit form with the value set for overriding hidden field display? FAPI protects against most form semantic hacks and I believe it would in this case if the form element wasn't in the FAPI build array the POST processing won't accept it.

kentr’s picture

If you want to allow for translating, that's fine, but this does not escape the replacement text. Use check_plain() or variable substitution (@text) instead. Unless there's a Views-specific way to handle this.

When you say 'escaped', do you mean stripped of HTML? Does it need to be? I was assuming that whoever is editing the view will have high-enough privileges that they're not a XSS risk, and HTML might be desired in the replacement text, but if you want it stripped, that's OK with me.

After further reviewing t(), I think that part is unnecessary. I incorrectly thought t() was the general language translation function.

Also, what's with the ending 'x'?

Oversight. Will remove.

@kentr, are you implying someone could POST to the Views edit form with the value set for overriding hidden field display? FAPI protects against most form semantic hacks and I believe it would in this case if the form element wasn't in the FAPI build array the POST processing won't accept it.

Yes, that was my concern. Glad to know that it's probably not an issue.

coltrane’s picture

I meant escaped but HTML stripping would work as well. Someone with the permission to administer views may not have other administration permissions and they could place script code in the replacement text that could allow them to gain higher permissions on the site. HTML is ok in the replacement text, but we should use filter_xss() or filter_xss_admin() then so script tags aren't allowed.

kentr’s picture

It may be a while before I can make these changes, so if someone else is able to, please do so.

Let us know, so we don't duplicate efforts.

M_Z’s picture

Status: Needs work » Needs review
FileSize
19.93 KB

@coltrane and kentr:

I attached a modified patch:
- removed the "x" in one of the 7 Views field handlers
- in all 7 Views field handlers: replaced t(...) by filter_xss_admin(...) - translation of the replace text is handled by Views (because 'translatable' => TRUE is set in options definitions - I tested translation behaviour with my multilanguage Drupal installation and everything works fine)
- in all 7 Views field handlers: replaced else { by elseif (drupal_strlen($this->options['profile_privacy_replacement_text'])) { to skip <span>...</span> output for empty replacement text

I also tested the "old" patch and it worked very well - but I am not sure, if I should change status to RTBC after modifying the patch.

By the way: I had some problems in applying the patch - I had to move the profile_privacy.views.inc and the complete handlers directory in a manually created "views" directory.

Looking forward to see this patch in next release!

Greets,
Martin

seaneffel’s picture

Status: Needs review » Reviewed & tested by the community

Ping. Hoping there was some movement on this. I have an interesting use case for this module in Drupal 6. Let me know how I can help.

bryancasler’s picture

subscribe

M_Z’s picture

@seaneffel:
Because you are asking "Let me know how I can help."...
Have you tried my #19 patch? Changing the issue status without reporting, if the patch works fine for you is a little bit strange.

@animelion:
Instead of subscribing it would be nice if you could tell us if you tried my #19 patch. Thanks in advance.

bryancasler’s picture

I have not, I subscribed to remind myself to try this module later when I have time

seaneffel’s picture

Probably the change in status was a fat finger error.

I've applied the patch in #10 and #19 and I get no results. From what I can gather in the whole thread, its just a patch that will allow Views to respect the privacy settings of the Profile fields, and neither of these patches do that for me. I've got a fresh installation of Views 6.x-2.12 and Profile Policy 6.x-1.2 on Drupal 6.20, and built a nice straightforward view. See this screenshot:

http://drupal.org/files/issues/screenshot1_0_35.png

In the screenshot you can see that none of the profile fields are marked as public, and you can see that while the profile page hides the fields, Views does not.

http://drupal.org/files/issues/screenshot2_0_35.png

Could this be that incremental changes to Views over the last eight months has broken the patches you submitted?

seaneffel’s picture

Status: Reviewed & tested by the community » Needs work
FileSize
220.46 KB
135.76 KB

Sorry... stupid file names.

seaneffel’s picture

Cross referencing this other issue that deals with Views and privacy of Profiles, just in case it's pertinent:

http://drupal.org/node/816992

M_Z’s picture

@seaneffel:

Please try to view your view with a user different from your superuser 1!
(To be more precise: By design of the views field handlers user_access('administer users') leads to show all profile fields without regarding profile privacy settings.)

If it doen't work please post a screenshot of a profile field (in edit mode) and a screenshot with field settings in Views for one profile field.

I can say again, that my patch #19 works fine for me.

seaneffel’s picture

Sure, I'll try again with another user that is not uid 1. But I don't think that is the issue. The view pulls profile fields from user 1 but the it displays them to anonymous user session. That's in the screenshot.

I would think that when user 1 hides profile fields then anonymous users shouldn't be able to see the fields. Am I right?

I'll be back with more screenies later today.

seaneffel’s picture

Confirming that patch #19 is not delivering for me. Check the screenshots, they are pretty straight forward.

Shot #3: Shows the privacy config of one of the fields, the High School field. It is a private field that allows users to override the privacy settings. That appears to be configured correctly. I got the same results when the field was set to a default of public, too.

Shot #4: Shows how uid 3 configured his High School field as not public but the College field is public. The top right shows how the anonymous session cannot see the High School field of uid 3 when looking at the profile page. However, the bottom right shows how the same anonymous session can see all fields when the fields are presented through a view.

Shot #5: Just for diligence, here is a screenie of the view from shot #4 so you can see how it was configured.

All in all, I can report that the patch in #19 is not working for me unless there is some missing step that I have missed. Could there be more steps I've missed in configuring the view?

seaneffel’s picture

FileSize
122.82 KB
189.72 KB
127.88 KB

Freaking attachments is not working on d.o. Here they are again...

M_Z’s picture

FileSize
17.31 KB

Thanks for your answer.

1. Could you post screenshots where we can see the configuration of your 2 profile fields from screenshot no. 5 (picture5.png).

2. I try to add a zipped version of my current profile_privacy directory, so you could try to diff my folder with yours to report any differences here.

seaneffel’s picture

1. I'm sure my fields are configured properly in my example, and I posted the config of my one profile field in screenshot 3 above. But...

2. Your zipped module works for me. After applying this patch, my file structure doesn't match yours. All the new .inc handler files that the patch generated did not get filed into the privacy_policy/views/handlers directory but when manually moving the files into the right place I get the behavior I need. Your zipped files is also missing the screenshots directory from the original module. The short is, it wasn't as simple as applying the patch.

I'm no whiz at making patches but if this patch could structure the files correctly then it would be ready to roll.

seaneffel’s picture

FileSize
208.31 KB

Just for reference, this is what my module looks like after applying your #19 patch. No deeper directories. Screenshot directory is present, too.

M_Z’s picture

@seaneffel:

As I wrote in #19 I had some problems in appying #10 patch (and I thought the reason could be using git instead of cvs).
I modified my improvements directly in the old patch.

Because moving files to the right place (like described by seaneffel in #18) should be an easy task for the maintainer of this module, I suggest that #19 solves this issue and seaneffel should change status to rtbc and assign the issue to coltrane (the maintainer).

By the way: I removed the screenshots directory because in my opinion these files shouldn't exist there, because they aren't used in the module. (at least up to now - see http://drupal.org/node/751656)

seaneffel’s picture

Assigned: kentr » Unassigned
Status: Needs work » Reviewed & tested by the community

Ok then.

Patch 19 works fine after moving the resulting files to the right directories. Maintainer can decide on what to do with the screenshots. Consider this RTBC.

I am unable to change the assignment but I'm hoping coltrane can commit this so I can put the patched module to use right away.

MacaroniDuck’s picture

subscribe

cor3huis’s picture

Title: Compatibility with Views » Module incompatible with Views
Category: feature » bug
cor3huis’s picture

Priority: Normal » Major

As far as I can see the improvements all work. A 6.x v1.x Dev release with all this patches merged and included would be very welcomed. Work toward a stable 1.3 could commence and then the improvements ported to the D7 Dev version.

cpliakas’s picture

I repurposed this patch and committed at #1268114: Views integration. The original patch worked well, although it did cause some performance issues. Added some static caching to the downstream project in order to reduce the amount of access checks performed by the _profile_privacy_views_field_access() function.

cpliakas’s picture

Version: 6.x-1.2 » 6.x-2.x-dev
Status: Reviewed & tested by the community » Fixed

Moving to the 6.x-2.x branch. Committed at 21f7146.

Status: Fixed » Closed (fixed)

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