Ning Developer Network

Derrick Or

Adding Visibility Options to Your Member Profile Pages

Source Code Access Required Yes
Skills Required PHP

Intro

By default, member profile pages can be viewed by anyone who has access to the network. This tutorial will show you how to implement additional functionality that gives your members the ability to set visibility options on their profile pages.  After completing the changes discussed in this tutorial, your network's members will have the ability to make their profile pages public, private, or only visible to their friends.

Instructions

Before we can begin, login to your network's file system using WebDav.

First, we'll begin by adding profile page settings to your network's privacy setting page. To do this, we'll need to modify 3 files.  The user model, the profile controller, and the privacy settings template files. 

  1. Open the user model file located at: widgets/index/models/User.php
    • We'll be adding an additional field to the user object on the network.  The new field will be used to keep track of member's profile page preferences.
    • The new field will be NULL by default and can hold one of three string values (all, friends, me)
    • In User.php search for the string "xn-ignore-start".  You should see a comment that looks something like: 
      /** xn-ignore-start 2365cb7691764f05894c2de6698b7da0 **/
    • Directly above this line, add the following code:
          /**
      * Whether to display the person's profile page
      *
      * @var XN_Attribute::STRING optional
      * @rule choice 1,1
      * @since 3.2
      */
      public $profileVisibility;
      public $profileVisibility_choices = array('all', 'friends', 'me');
    • This code lets your network know that User objects can contain a field called "profileVisibility" that holds one of three string values. 
    • Once you're done making your changes, save the file. 
  2. Open the privacy settings template file located at: widgets/profiles/templates/profile/privacySettings.php
    • This file is used to render the privacy settings page. We need to modify this page so that members can choose visibility options for their profile pages. We'll be adding a set of radio buttons at the top of this page that let members choose one of three visibility options.
    • In the tempate file, locate the existing radio buttons. Add the following code before all the existing radio buttons:
      <fieldset>
      <div class="normal">Who can view your profile page? </div>
      <ul class="options" <%= error_if($this,'profileVisibility') %>>
      <li><label><%= $this->form->radio('profileVisibility','all','class="radio"') %>Anyone</label></li>
      <li><label><%= $this->form->radio('profileVisibility','friends','class="radio"') %>Friends Only</label></li>
      <li><label><%= $this->form->radio('profileVisibility','me','class="radio"') %>Just Me</label></li>
      </ul>
      </fieldset>
    • When you're done making your changes, be sure to save your file.  Your template file should look  something like the following:
      <?php xg_header('profile', $title = xg_text('PRIVACY'), $this->_user); ?>
      <?php
      $enabledModules = XG_ModuleHelper::getEnabledModules();
      function error_if($ob,$field) {
      return isset($ob->errors[$field]) ? 'class="error"' : '';
      } ?>
      <div id="xg_body">
      <div class="xg_colgroup">
      <div class="xg_3col first-child">
      <h1><%= xg_html('MY_SETTINGS') %></h1>
      <form id="settings_form" action="<%= $this->_buildUrl('profile', 'privacySettings') %>" method="post">
      <%= XG_SecurityHelper::csrfTokenHiddenInput() %>
      <div class="xg_module">
      <div class="xg_module_body pad">
      <?php $this->renderPartial('fragment_settingsNavigation', '_shared', array('selected' => 'privacy')); ?>
      <div class="right page_ticker_content">
      <fieldset class="nolegend">
      <h3><%= xnhtmlentities($title) %></h3>
      <?php
      if ($_GET['saved']) { ?>
      <dl class='success msg' id='settings_form_notify'>
      <dd><p><%= xg_html('YOUR_SETTINGS_HAVE_BEEN_SAVED'); %></p></dd>
      </dl>
      <?php
      } else if (count($this->errors)) { ?>
      <dl class="errordesc msg" id="settings_form_notify">
      <dt><%= xg_html('PLEASE_CORRECT_THE_FOLLOWING') %></dt>
      <dd><ol>
      <?php foreach ($this->errors as $error) { ?>
      <li><%= $error %></li>
      <?php } ?>
      </ol></dd>
      </dl>
      <?php
      } ?>
      <fieldset>
      <div class="normal">Who can view your profile page? </div>
      <ul class="options" <%= error_if($this,'profileVisibility') %>>
      <li><label><%= $this->form->radio('profileVisibility','all','class="radio"') %>Anyone</label></li>
      <li><label><%= $this->form->radio('profileVisibility','friends','class="radio"') %>Friends Only</label></li>
      <li><label><%= $this->form->radio('profileVisibility','me','class="radio"') %>Just Me</label></li>
      </ul>
      <p><small><%= xg_html('YOU_CAN_OVERRIDE_WHEN_YOU_ADD') %></small></p>
      </fieldset>
      <fieldset>
      <div class="normal"><%= strip_tags(str_replace('>', '> ', xg_html('WHO_CAN_VIEW_YOUR_PHOTOS_VIDEOS'))) %> </div>
      <ul class="options" <%= error_if($this,'defaultVisibility') %>>
      <li><label><%= $this->form->radio('defaultVisibility','all','class="radio"') %><%= xg_html('ANYONE') %></label></li>
      <li><label><%= $this->form->radio('defaultVisibility','friends','class="radio"') %><%= xg_html('JUST_MY_FRIENDS') %></label></li>
      <li><label><%= $this->form->radio('defaultVisibility','me','class="radio"') %><%= xg_html('JUST_ME') %></label></li>
      </ul>
      <p><small><%= xg_html('YOU_CAN_OVERRIDE_WHEN_YOU_ADD') %></small></p>
      </fieldset>
      <fieldset>
      <div class="normal"><%= strip_tags(str_replace('>', '> ', xg_html('WHO_CAN_COMMENT_ON_PHOTOS_VIDEOS'))) %></div>
      <ul class="options" <%= error_if($this,'addCommentPermissions') %>>
      <li><label><%= $this->form->radio('addCommentPermission','all','class="radio"') %><%= xg_html('ANYONE') %></label></li>
      <li><label><%= $this->form->radio('addCommentPermission','friends','class="radio"') %><%= xg_html('JUST_MY_FRIENDS') %></label></li>
      <li><label><%= $this->form->radio('addCommentPermission','me','class="radio"') %><%= xg_html('JUST_ME') %></label></li>
      </ul>
      </fieldset>
      <fieldset>
      <div class="normal"><%= strip_tags(str_replace('>', '> ', xg_html('MODERATE_COMMENTS_ON_BLOG'))) %></div>
      <ul class="options" <%= error_if($this,$this->moderationAttributeName) %>>
      <li><label><%= $this->form->radio($this->moderationAttributeName,'Y','class="radio"') %><%= xg_html('YES_LET_ME_APPROVE') %></label></li>
      <li><label><%= $this->form->radio($this->moderationAttributeName,'N','class="radio"') %><%= xg_html('NO_PUBLISH_COMMENTS') %></label></li>
      </ul>
      </fieldset>
      <fieldset>
      <div class="normal"><%= strip_tags(str_replace('>', '> ', xg_html('MODERATE_COMMENTS_ON_COMMENTWALL'))) %></div>
      <ul class="options" <%= error_if($this,$this->commentWallModerationAttributeName) %>>
      <li><label><%= $this->form->radio($this->commentWallModerationAttributeName,'Y','class="radio"') %><%= xg_html('YES_LET_ME_APPROVE') %></label></li>
      <li><label><%= $this->form->radio($this->commentWallModerationAttributeName,'N','class="radio"') %><%= xg_html('NO_PUBLISH_COMMENTS') %></label></li>
      </ul>
      </fieldset>
      <?php if ($enabledModules['events']) {?>
      <fieldset>
      <div class="normal"><%= strip_tags(str_replace('>', '> ', xg_html('WHO_CAN_VIEW_EVENTS'))) %></div>
      <ul class="options" <%= error_if($this,'viewEventsPermission') %>>
      <li><label><%= $this->form->radio('viewEventsPermission','all','class="radio"') %><%= xg_html('ANYONE') %></label></li>
      <li><label><%= $this->form->radio('viewEventsPermission','friends','class="radio"') %><%= xg_html('JUST_MY_FRIENDS') %></label></li>
      <li><label><%= $this->form->radio('viewEventsPermission','me','class="radio"') %><%= xg_html('JUST_ME') %></label></li>
      </ul>
      </fieldset>
      <?php }?>
      <?php if (XG_App::everythingIsVisible()) { ?>
      <fieldset>
      <div class="normal"><%= strip_tags(str_replace('>', '> ', xg_html('NOTIFY_BLOG_PING_SERVICES'))) %></div>
      <ul class="options" id="blog_ping_options">
      <li><label><%= $this->form->checkbox('blogPingPermission','Y','class="checkbox"') %><%= xg_html('YES_NOTIFY_BLOG_SERVICES','href="http://pingomatic.com" target="_new"')%></label></li>
      </ul>
      </fieldset>
      <?php } ?>
      <?php
      XG_App::includeFileOnce('/lib/XG_ModuleHelper.php');
      if($enabledModules['activity']) { ?>
      <fieldset>
      <div class="normal"><%= strip_tags(str_replace('>', '> ', xg_html('WHICH_OF_YOUR_ACTIONS_DISPLAY_ACTIVITY'))) %></div>
      <ul class="options" id="activity_options">
      <li><label><%= $this->form->checkbox('activityNewContent','Y','class="checkbox"') %><%= xg_html('NEW_CONTENT_I_ADD')%></label></li>
      <li><label><%= $this->form->checkbox('activityNewComment','Y','class="checkbox"') %><%= xg_html('NEW_COMMENTS_I_ADD')%></label></li>
      <li><label><%= $this->form->checkbox('activityFriendships','Y','class="checkbox"') %><%= xg_html('NEW_FRIENDS')%></label></li>
      <li><label><%= $this->form->checkbox('activityProfileUpdate','Y','class="checkbox"') %><%= xg_html('WHEN_I_UPDATE_MY_PROFILE')%></label></li>
      <?php if ($enabledModules['events']) {?>
      <li><label><%= $this->form->checkbox('activityEvents','Y','class="checkbox"') %><%= xg_html('MY_EVENTS_AND_RSVP')%></label></li>
      <?php }?>
      </ul>
      <p><small><%= xg_html('THE_LATEST_ACTIVITY_WILL_NEVER')%></small></p>
      </fieldset>
      <?php
      } ?>
      <p class="buttongroup"><input type="submit" class="button left" value="<%= xg_html('SAVE') %>" /></p>
      </fieldset>
      </div>
      </div>
      </div><!--/.xg_module-->
      </form>
      </div>
      <div class="xg_1col last-child">
      <?php xg_sidebar($this); ?>
      </div><!--/xg_1col-->
      </div><!--/xg_colgroup-->
      </div><!--/#xg_body-->
      <?php xg_footer(); ?>
  3. Open the profile controller file located at: widgets/profiles/controllers/ProfileController.php
    • This file contains all the functions and logic used by the template page you edited in the previous step. We'll need to update this file to handle the additional visibility options we added to the privacy settings template file.
    • In the controller file, locate the function "action_privacySettings".
    • At the bottom of this function before the privacy form is rendered, add the following line of code:
      $defaults['profileVisibility'] = $user->my->profileVisibility;
    • When you're done, the function "action_privacySettings" should look like:
          public function action_privacySettings() {
      XG_SecurityHelper::redirectIfNotMember(null, true);
      $this->moderationAttributeName = XG_App::widgetAttributeName(W_Cache::getWidget('profiles'), 'moderateBlogComments');
      $this->commentWallModerationAttributeName = XG_App::widgetAttributeName(W_Cache::getWidget('profiles'), 'moderateChatters');

      if ($_SERVER['REQUEST_METHOD'] == 'POST') {
      // Make sure the submitted data is sane
      $this->errors = array();
      $errorCatalog = array('defaultVisibility' => xg_html('PICK_VALID_DEFAULT_VISIBILITY'),
      'addCommentPermission' => xg_html('PICK_VALID_WHO_CAN_COMMENT'),
      $this->moderationAttributeName => xg_html('PICK_VALID_BLOG_COMMENT_MODERATION'),
      $this->commentWallModerationAttributeName => xg_html('PICK_VALID_COMMENTWALL_COMMENT_MODERATION'),
      );

      foreach (array('defaultVisibility','addCommentPermission') as $f) {
      if (isset($_POST[$f]) && (! in_array($_POST[$f], array('all','friends','me')))) {
      $this->errors[$f] = $errorCatalog[$f];
      }
      }
      if (isset($_POST[$this->moderationAttributeName]) && (! in_array($_POST[$this->moderationAttributeName], array('Y','N')))) {
      $this->errors[$this->moderationAttributeName] = $errorCatalog[$this->moderationAttributeName];
      }
      if (isset($_POST[$this->commentWallModerationAttributeName]) && (! in_array($_POST[$this->commentWallModerationAttributeName], array('Y','N')))) {
      $this->errors[$this->commentWallModerationAttributeName] = $errorCatalog[$this->commentWallModerationAttributeName];
      }

      if (count($this->errors) == 0) {
      $this->forwardTo('privacySettingsSave', 'profile', array(true));
      return;
      }
      }
      $user = User::load($this->_user);

      foreach (array('defaultVisibility','addCommentPermission','blogPingPermission', 'viewEventsPermission',
      $this->moderationAttributeName, $this->commentWallModerationAttributeName) as $f){
      $defaults[$f] = $user->my->{$f};
      }
      if (!$defaults['viewEventsPermission']) {
      $defaults['viewEventsPermission'] = 'all';
      }
      foreach (array('activityNewContent', 'activityNewComment', 'activityProfileUpdate','activityEvents','activityFriendships') as $f) {
      $defaults[$f] = ($user->my->{$f} != 'N')?'Y':'N';
      }

      $defaults['profileVisibility'] = $user->my->profileVisibility;

      $this->form = new XNC_Form($defaults);
      $this->app = XN_Application::load();
      }
    • Next, we'll need to locate and modify the function "action_privacySettingsSave"
    • At the bottom of this function, right before the "save()" method is called on the User object, add the following line of code:
      $user->my->profileVisibility = $_POST['profileVisibility'];
    • When you're done making the change, your "action_privacySettingsSave" function should look like:
          public function action_privacySettingsSave($fromSettings = false) {
      XG_SecurityHelper::redirectIfNotMember();
      if (! $fromSettings) {
      $this->redirectTo('privacySettings');
      return;
      }
      $this->moderationAttributeName = XG_App::widgetAttributeName(W_Cache::getWidget('profiles'), 'moderateBlogComments');
      $this->commentWallModerationAttributeName = XG_App::widgetAttributeName(W_Cache::getWidget('profiles'), 'moderateChatters');
      $user = User::load($this->_user);
      foreach (array('defaultVisibility','addCommentPermission',$this->moderationAttributeName, $this->commentWallModerationAttributeName) as $f) {
      if (isset($_POST[$f])) { $user->my->{$f} = $_POST[$f]; }
      }
      foreach (array('activityNewContent','activityNewComment','activityProfileUpdate','blogPingPermission','activityFriendships') as $f) {
      $user->my->{$f} = (isset($_POST[$f]) && mb_strlen($_POST[$f])) ? $_POST[$f] : 'N';
      }

      XG_App::includeFileOnce('/lib/XG_ModuleHelper.php');
      $enabledModules = XG_ModuleHelper::getEnabledModules();
      if ($enabledModules['events']) {
      $user->my->viewEventsPermission = $_POST['viewEventsPermission'];
      $user->my->activityEvents = $_POST['activityEvents'] ? 'Y' : 'N';
      }

      $user->my->profileVisibility = $_POST['profileVisibility'];

      $user->save();

      // Invalidate pages (such as the blog post detail page) that depend on user settings

      $this->redirectTo('privacySettings', 'profile', array('saved' => 1));
      }
    • Be sure to save the changes to your controller file.
  4. Open the profile display template file located at: widgets/profiles/templates/profile/show.php
    • This file is in charge of rendering different member profile pages. We'll be adding logic to this template file that checks to see if a particular profile page should be displayed in the browser based on the profile owner's visibility settings, relationship with the current user, etc.
    • Add the following code above the existing contents of the template file:
      <?php
      //get the profile page visibility preferences and userid for the owner of the profile page
      $query =XN_Query::create('content')
      ->filter( 'type', 'eic', 'User')
      ->filter('id','=', $this->pageOwner);
      $page_owner = $query->uniqueResult();
      $profileVisibility = $page_owner->my->profileVisibility;
      $profileUserId = $page_owner->title;

      //get the userid for the current user
      $currentUser = User::load($this->_user);
      $currentUserId = $currentUser->title;

      //check to see if current user is friends with the person who owns the profile page
      $isFriend=false;
      if($currentUserId != NULL)
      {
      $query = XN_Query::create('Contact')
      ->filter('owner', '=', $currentUserId)
      ->filter('contact', '=', $profileUserId);
      $relationshipObject = $query->uniqueResult();
      $userRelationship = $relationshipObject->relationship;
      if($userRelationship == 'friend'){ $isFriend=true; }

      //if($relationshipObject != NULL)
      //{
      //$output_string = $relationshipObject -> debugHtml ( );
      //echo"$currentUserId <br> $output_string ";
      //}
      }
      ?>

      <?php
      //Decide what to do on this page based on the information collected above
      if($profileVisibility == 'all' || $profileVisibility == NULL || $profileUserId == $currentUserId || ($profileVisibility == 'friends' && $isFriend == true)):
      ?>
    • Add the following code below the existing contents of the template file
      <?php elseif($profileVisibility == 'friends' && $isFriend == false):?>
      <script>
      alert('Sorry, you must be friends with this member to see their profile page');
      history.back();
      </script>

      <?php else: ?>
      <script>
      alert('Sorry, this member\'s profile page is private');
      history.back();
      </script>
      <?php endif; ?>
    • Your template file should look like the following:
      <?php
      //get the profile page visibility preferences and userid for the owner of the profile page
      $query =XN_Query::create('content')
      ->filter( 'type', 'eic', 'User')
      ->filter('id','=', $this->pageOwner);
      $page_owner = $query->uniqueResult();
      $profileVisibility = $page_owner->my->profileVisibility;
      $profileUserId = $page_owner->title;

      //get the userid for the current user
      $currentUser = User::load($this->_user);
      $currentUserId = $currentUser->title;

      //check to see if current user is friends with the person who owns the profile page
      $isFriend=false;
      if($currentUserId != NULL)
      {
      $query = XN_Query::create('Contact')
      ->filter('owner', '=', $currentUserId)
      ->filter('contact', '=', $profileUserId);
      $relationshipObject = $query->uniqueResult();
      $userRelationship = $relationshipObject->relationship;
      if($userRelationship == 'friend'){ $isFriend=true; }

      //if($relationshipObject != NULL)
      //{
      //$output_string = $relationshipObject -> debugHtml ( );
      //echo"$currentUserId <br> $output_string ";
      //}
      }
      ?>

      <?php
      //Decide what to do on this page based on the information collected above
      if($profileVisibility == 'all' || $profileVisibility == NULL || $profileUserId == $currentUserId || ($profileVisibility == 'friends' && $isFriend == true)):
      ?>
      <?php
      xg_header(($this->userIsOwner ? 'profile' : 'members'),$this->pageTitle,$this->pageOwner, array('includeActionBarCss' => true, 'metaDescription' => $this->metaDescription));
      XG_App::ningLoaderRequire('xg.index.actionicons', 'xg.shared.util');
      ?>
      <div id="xg_body">
      <?php XG_LayoutHelper::renderLayout($this->xgLayout, $this); ?>
      </div><!--/#xg_body-->
      <?php xg_footer(); ?>

      <?php elseif($profileVisibility == 'friends' && $isFriend == false):?>
      <script>
      alert('Sorry, you must be friends with this member to see their profile page');
      history.back();
      </script>

      <?php else: ?>
      <script>
      alert('Sorry, this member\'s profile page is private');
      history.back();
      </script>
      <?php endif; ?>
    • Be sure to save the changes to your file.
  5. Congratulations, the new profile visibility options are now ready for testing and use on your network!

Last updated by Devin Oct 2.

We're Hiring

We are looking for talented and passionate individuals to join our growing team.

Visit our engineering jobs and see if Ning is right for you.

© 2008   Created by Ning Developer Admin

Badges  |  Report an Issue  |  Privacy  |  Terms of Service