<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[BuddyPress][8610] trunk/src: Untangle some load order and mutual dependency issues between component loaders</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://buddypress.trac.wordpress.org/changeset/8610">8610</a></dd>
<dt>Author</dt> <dd>boonebgorges</dd>
<dt>Date</dt> <dd>2014-07-12 03:01:27 +0000 (Sat, 12 Jul 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Untangle some load order and mutual dependency issues between component loaders

BuddyPress's components are dependent upon each other in numerous ways. All
components depend in one way or another on bp-core. Many components reference
bp-members functions and globals. References to bp-xprofile can be found in
a number of components. And so on. We have managed to make these dependencies
work on a case-by-case basis, though the system becomes less stable as it
becomes more complex. The fact that all components are loaded at
bp_setup_components introduces the possibliity of numerous race conditions that
may not cause problems on vanilla installations of BuddyPress, but can cause
fatal errors when trying to customize in various ways.

As part of an ongoing project to disentangle and regularize these dependencies
(see eg <a href="http://buddypress.trac.wordpress.org/ticket/5750">#5750</a>), this changeset introduces a few enhancements that make the
dependencies between components more predictable, more serialized, and more
stable.

- In bp-members and bp-groups, move canonical_stack determination out of the
  main setup_globals() method and into its own setup_canonical_stack() method.
  This new method runs after all components have had a chance to run
  setup_globals(). As a result, the components are able to reference each other
  safely when determining default and fallback components for redirects (for
  example, the members component has access to the activity component's slug
  and other global data when determining whether
  example.com/members/boone/activity/ should resolve to example.com/members/boone/)
- In bp-members, use only WP core data to set up the loggedin_user and
  displayed_user global objects. Previously, these objects were configured by
  referenced to xprofile, which required that xprofile be loaded before members.
  Now, users' display names are first loaded from wp_users, and are overridden
  by the xprofile component via filter, only after xprofile has fully
  initialized.
- In bp-xprofile, move the Settings > Profile navigation setup routine out of
  the main setup_nav() task. bp-xprofile loads early, before bp-settings has
  had a chance to set up its top-level navigation. As a result, bp-xprofile
  must wait until the bp_settings_setup_nav action to add its Profile subnav
  item.
- Fine-tune the component load order. bp-core, which acts more like a library
  of common functionality than like a traditional component, is moved from
  bp_setup_components:10 to bp_loaded:0. This ensures that it is available to
  all other components. bp-xprofile, which must load after bp-members but at
  the same time is closely coupled to it, is moved to bp_setup_components:2,
  just after bp-members.

These changes are enough to make it possible to move forward on dependent
tickets; see, for example, <a href="http://buddypress.trac.wordpress.org/ticket/5407">#5407</a>. It's likely that significant entanglement
and load-order issues remain. We'll continue to fix them as they arise, by
making load order more explicit, and by breaking the component bootstrap
process into increasingly discrete chunks.

Fixes <a href="http://buddypress.trac.wordpress.org/ticket/5436">#5436</a>

Props boonebgorges, r-a-y</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcbpcorebpcoreactionsphp">trunk/src/bp-core/bp-core-actions.php</a></li>
<li><a href="#trunksrcbpcorebpcorecomponentphp">trunk/src/bp-core/bp-core-component.php</a></li>
<li><a href="#trunksrcbpcorebpcoredependencyphp">trunk/src/bp-core/bp-core-dependency.php</a></li>
<li><a href="#trunksrcbpcorebpcoreloaderphp">trunk/src/bp-core/bp-core-loader.php</a></li>
<li><a href="#trunksrcbpgroupsbpgroupsloaderphp">trunk/src/bp-groups/bp-groups-loader.php</a></li>
<li><a href="#trunksrcbpmembersbpmembersloaderphp">trunk/src/bp-members/bp-members-loader.php</a></li>
<li><a href="#trunksrcbpxprofilebpxprofilefunctionsphp">trunk/src/bp-xprofile/bp-xprofile-functions.php</a></li>
<li><a href="#trunksrcbpxprofilebpxprofileloaderphp">trunk/src/bp-xprofile/bp-xprofile-loader.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcbpcorebpcoreactionsphp"></a>
<div class="modfile"><h4>Modified: trunk/src/bp-core/bp-core-actions.php (8609 => 8610)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/bp-core/bp-core-actions.php    2014-07-12 01:59:03 UTC (rev 8609)
+++ trunk/src/bp-core/bp-core-actions.php       2014-07-12 03:01:27 UTC (rev 8610)
</span><span class="lines">@@ -66,6 +66,7 @@
</span><span class="cx">  */
</span><span class="cx"> add_action( 'bp_init', 'bp_core_set_uri_globals',    2  );
</span><span class="cx"> add_action( 'bp_init', 'bp_setup_globals',           4  );
</span><ins>+add_action( 'bp_init', 'bp_setup_canonical_stack',   5  );
</ins><span class="cx"> add_action( 'bp_init', 'bp_setup_nav',               6  );
</span><span class="cx"> add_action( 'bp_init', 'bp_setup_title',             8  );
</span><span class="cx"> add_action( 'bp_init', 'bp_core_load_admin_bar_css', 12 );
</span></span></pre></div>
<a id="trunksrcbpcorebpcorecomponentphp"></a>
<div class="modfile"><h4>Modified: trunk/src/bp-core/bp-core-component.php (8609 => 8610)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/bp-core/bp-core-component.php  2014-07-12 01:59:03 UTC (rev 8609)
+++ trunk/src/bp-core/bp-core-component.php     2014-07-12 03:01:27 UTC (rev 8610)
</span><span class="lines">@@ -337,6 +337,9 @@
</span><span class="cx">          // Setup globals
</span><span class="cx">          add_action( 'bp_setup_globals',          array( $this, 'setup_globals'          ), 10 );
</span><span class="cx"> 
</span><ins>+               // Set up canonical stack
+               add_action( 'bp_setup_canonical_stack',  array( $this, 'setup_canonical_stack'  ), 10 );
+
</ins><span class="cx">           // Include required files. Called early to ensure that BP core
</span><span class="cx">          // components are loaded before plugins that hook their loader functions
</span><span class="cx">          // to bp_include with the default priority of 10. This is for backwards
</span><span class="lines">@@ -379,6 +382,13 @@
</span><span class="cx">  }
</span><span class="cx"> 
</span><span class="cx">  /**
</span><ins>+        * Set up the canonical URL stack for this component.
+        *
+        * @since BuddyPress (2.1.0)
+        */
+       public function setup_canonical_stack() {}
+
+       /**
</ins><span class="cx">    * Set up component navigation.
</span><span class="cx">   *
</span><span class="cx">   * @see bp_core_new_nav_item() For a description of the $main_nav
</span></span></pre></div>
<a id="trunksrcbpcorebpcoredependencyphp"></a>
<div class="modfile"><h4>Modified: trunk/src/bp-core/bp-core-dependency.php (8609 => 8610)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/bp-core/bp-core-dependency.php 2014-07-12 01:59:03 UTC (rev 8609)
+++ trunk/src/bp-core/bp-core-dependency.php    2014-07-12 03:01:27 UTC (rev 8610)
</span><span class="lines">@@ -32,6 +32,13 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Fire the 'bp_setup_canonical_stack' action, where plugins should set up their canonical URL.
+ */
+function bp_setup_canonical_stack() {
+       do_action( 'bp_setup_canonical_stack' );
+}
+
+/**
</ins><span class="cx">  * Fire the 'bp_setup_globals' action, where plugins should initialize global settings.
</span><span class="cx">  */
</span><span class="cx"> function bp_setup_globals() {
</span></span></pre></div>
<a id="trunksrcbpcorebpcoreloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/src/bp-core/bp-core-loader.php (8609 => 8610)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/bp-core/bp-core-loader.php     2014-07-12 01:59:03 UTC (rev 8609)
+++ trunk/src/bp-core/bp-core-loader.php        2014-07-12 03:01:27 UTC (rev 8610)
</span><span class="lines">@@ -263,4 +263,4 @@
</span><span class="cx"> function bp_setup_core() {
</span><span class="cx">  buddypress()->core = new BP_Core();
</span><span class="cx"> }
</span><del>-add_action( 'bp_setup_components', 'bp_setup_core', 2 );
</del><ins>+add_action( 'bp_loaded', 'bp_setup_core', 0 );
</ins></span></pre></div>
<a id="trunksrcbpgroupsbpgroupsloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/src/bp-groups/bp-groups-loader.php (8609 => 8610)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/bp-groups/bp-groups-loader.php 2014-07-12 01:59:03 UTC (rev 8609)
+++ trunk/src/bp-groups/bp-groups-loader.php    2014-07-12 03:01:27 UTC (rev 8610)
</span><span class="lines">@@ -240,34 +240,6 @@
</span><span class="cx">                  return;
</span><span class="cx">          }
</span><span class="cx"> 
</span><del>-               if ( bp_is_groups_component() && !empty( $this->current_group ) ) {
-
-                       $this->default_extension = apply_filters( 'bp_groups_default_extension', defined( 'BP_GROUPS_DEFAULT_EXTENSION' ) ? BP_GROUPS_DEFAULT_EXTENSION : 'home' );
-
-                       if ( !bp_current_action() ) {
-                               $bp->current_action = $this->default_extension;
-                       }
-
-                       // Prepare for a redirect to the canonical URL
-                       $bp->canonical_stack['base_url'] = bp_get_group_permalink( $this->current_group );
-
-                       if ( bp_current_action() ) {
-                               $bp->canonical_stack['action'] = bp_current_action();
-                       }
-
-                       if ( !empty( $bp->action_variables ) ) {
-                               $bp->canonical_stack['action_variables'] = bp_action_variables();
-                       }
-
-                       // When viewing the default extension, the canonical URL should not have
-                       // that extension's slug, unless more has been tacked onto the URL via
-                       // action variables
-                       if ( bp_is_current_action( $this->default_extension ) && empty( $bp->action_variables ) )  {
-                               unset( $bp->canonical_stack['action'] );
-                       }
-
-               }
-
</del><span class="cx">           // Preconfigured group creation steps
</span><span class="cx">          $this->group_creation_steps = apply_filters( 'groups_create_group_steps', array(
</span><span class="cx">                  'group-details'  => array(
</span><span class="lines">@@ -308,6 +280,46 @@
</span><span class="cx">  }
</span><span class="cx"> 
</span><span class="cx">  /**
</span><ins>+        * Set up canonical stack for this component.
+        *
+        * @since BuddyPress (2.1.0)
+        */
+       public function setup_canonical_stack() {
+               if ( ! bp_is_groups_component() ) {
+                       return;
+               }
+
+               if ( empty( $this->current_group ) ) {
+                       return;
+               }
+
+
+               $this->default_extension = apply_filters( 'bp_groups_default_extension', defined( 'BP_GROUPS_DEFAULT_EXTENSION' ) ? BP_GROUPS_DEFAULT_EXTENSION : 'home' );
+
+               if ( !bp_current_action() ) {
+                       buddypress()->current_action = $this->default_extension;
+               }
+
+               // Prepare for a redirect to the canonical URL
+               buddypress()->canonical_stack['base_url'] = bp_get_group_permalink( $this->current_group );
+
+               if ( bp_current_action() ) {
+                       buddypress()->canonical_stack['action'] = bp_current_action();
+               }
+
+               if ( !empty( buddypress()->action_variables ) ) {
+                       buddypress()->canonical_stack['action_variables'] = bp_action_variables();
+               }
+
+               // When viewing the default extension, the canonical URL should not have
+               // that extension's slug, unless more has been tacked onto the URL via
+               // action variables
+               if ( bp_is_current_action( $this->default_extension ) && empty( buddypress()->action_variables ) )  {
+                       unset( buddypress()->canonical_stack['action'] );
+               }
+       }
+
+       /**
</ins><span class="cx">    * Set up navigation.
</span><span class="cx">   *
</span><span class="cx">   * @global BuddyPress $bp The one true BuddyPress instance
</span></span></pre></div>
<a id="trunksrcbpmembersbpmembersloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/src/bp-members/bp-members-loader.php (8609 => 8610)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/bp-members/bp-members-loader.php       2014-07-12 01:59:03 UTC (rev 8609)
+++ trunk/src/bp-members/bp-members-loader.php  2014-07-12 03:01:27 UTC (rev 8610)
</span><span class="lines">@@ -96,8 +96,11 @@
</span><span class="cx"> 
</span><span class="cx">          /** Logged in user ****************************************************/
</span><span class="cx"> 
</span><ins>+               // The core userdata of the user who is currently logged in.
+               $bp->loggedin_user->userdata       = bp_core_get_core_userdata( bp_loggedin_user_id() );
+
</ins><span class="cx">           // Fetch the full name for the logged in user
</span><del>-               $bp->loggedin_user->fullname       = bp_core_get_user_displayname( bp_loggedin_user_id() );
</del><ins>+                $bp->loggedin_user->fullname       = isset( $bp->loggedin_user->userdata->display_name ) ? $bp->loggedin_user->userdata->display_name : '';
</ins><span class="cx"> 
</span><span class="cx">          // Hits the DB on single WP installs so get this separately
</span><span class="cx">          $bp->loggedin_user->is_super_admin = $bp->loggedin_user->is_site_admin = is_super_admin( bp_loggedin_user_id() );
</span><span class="lines">@@ -105,20 +108,17 @@
</span><span class="cx">          // The domain for the user currently logged in. eg: http://domain.com/members/andy
</span><span class="cx">          $bp->loggedin_user->domain         = bp_core_get_user_domain( bp_loggedin_user_id() );
</span><span class="cx"> 
</span><del>-               // The core userdata of the user who is currently logged in.
-               $bp->loggedin_user->userdata       = bp_core_get_core_userdata( bp_loggedin_user_id() );
-
</del><span class="cx">           /** Displayed user ****************************************************/
</span><span class="cx"> 
</span><del>-               // The domain for the user currently being displayed
-               $bp->displayed_user->domain   = bp_core_get_user_domain( bp_displayed_user_id() );
-
</del><span class="cx">           // The core userdata of the user who is currently being displayed
</span><span class="cx">          $bp->displayed_user->userdata = bp_core_get_core_userdata( bp_displayed_user_id() );
</span><span class="cx"> 
</span><span class="cx">          // Fetch the full name displayed user
</span><del>-               $bp->displayed_user->fullname = bp_core_get_user_displayname( bp_displayed_user_id() );
</del><ins>+                $bp->displayed_user->fullname = isset( $bp->displayed_user->userdata->fullname ) ? $bp->displayed_user->userdata->fullname : '';
</ins><span class="cx"> 
</span><ins>+               // The domain for the user currently being displayed
+               $bp->displayed_user->domain   = bp_core_get_user_domain( bp_displayed_user_id() );
+
</ins><span class="cx">           /** Signup ************************************************************/
</span><span class="cx"> 
</span><span class="cx">          $bp->signup = new stdClass;
</span><span class="lines">@@ -130,7 +130,16 @@
</span><span class="cx">                  $bp->profile->slug = 'profile';
</span><span class="cx">                  $bp->profile->id   = 'profile';
</span><span class="cx">          }
</span><ins>+       }
</ins><span class="cx"> 
</span><ins>+       /**
+        * Set up canonical stack for this component.
+        *
+        * @since BuddyPress (2.1.0)
+        */
+       public function setup_canonical_stack() {
+               $bp = buddypress();
+
</ins><span class="cx">           /** Default Profile Component *****************************************/
</span><span class="cx"> 
</span><span class="cx">          if ( defined( 'BP_DEFAULT_COMPONENT' ) && BP_DEFAULT_COMPONENT ) {
</span></span></pre></div>
<a id="trunksrcbpxprofilebpxprofilefunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/src/bp-xprofile/bp-xprofile-functions.php (8609 => 8610)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/bp-xprofile/bp-xprofile-functions.php  2014-07-12 01:59:03 UTC (rev 8609)
+++ trunk/src/bp-xprofile/bp-xprofile-functions.php     2014-07-12 03:01:27 UTC (rev 8610)
</span><span class="lines">@@ -497,6 +497,35 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Replace the displayed and logged-in userss fullnames with the xprofile name, if required.
+ *
+ * The Members component uses the logged-in user's display_name to set the
+ * value of buddypress()->loggedin_user->fullname. However, in cases where
+ * profile sync is disabled, display_name may diverge from the xprofile
+ * fullname field value, and the xprofile field should take precedence.
+ *
+ * Runs at bp_setup_globals:100 to ensure that all components have loaded their
+ * globals before attempting any overrides.
+ *
+ * @since BuddyPress (2.0.0)
+ */
+function xprofile_override_user_fullnames() {
+       // If sync is enabled, the two names will match. No need to continue.
+       if ( ! bp_disable_profile_sync() ) {
+               return;
+       }
+
+       if ( bp_loggedin_user_id() ) {
+               buddypress()->loggedin_user->fullname = bp_core_get_user_displayname( bp_loggedin_user_id() );
+       }
+
+       if ( bp_displayed_user_id() ) {
+               buddypress()->displayed_user->fullname = bp_core_get_user_displayname( bp_displayed_user_id() );
+       }
+}
+add_action( 'bp_setup_globals', 'xprofile_override_user_fullnames', 100 );
+
+/**
</ins><span class="cx">  * Setup the avatar upload directory for a user.
</span><span class="cx">  *
</span><span class="cx">  * @package BuddyPress Core
</span></span></pre></div>
<a id="trunksrcbpxprofilebpxprofileloaderphp"></a>
<div class="modfile"><h4>Modified: trunk/src/bp-xprofile/bp-xprofile-loader.php (8609 => 8610)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/bp-xprofile/bp-xprofile-loader.php     2014-07-12 01:59:03 UTC (rev 8609)
+++ trunk/src/bp-xprofile/bp-xprofile-loader.php        2014-07-12 03:01:27 UTC (rev 8610)
</span><span class="lines">@@ -218,25 +218,47 @@
</span><span class="cx">                  );
</span><span class="cx">          }
</span><span class="cx"> 
</span><del>-               // Privacy Settings
-               if ( bp_is_active( 'settings' ) ) {
</del><ins>+                // The Settings > Profile nav item can only be set up after
+               // the Settings component has run its own nav routine
+               add_action( 'bp_settings_setup_nav', array( $this, 'setup_settings_nav' ) );
</ins><span class="cx"> 
</span><del>-                       // Get the settings slug
-                       $settings_slug = bp_get_settings_slug();
</del><ins>+                parent::setup_nav( $main_nav, $sub_nav );
+       }
</ins><span class="cx"> 
</span><del>-                       // Add the sub-navigation
-                       $sub_nav[] = array(
-                               'name'            => __( 'Profile', 'buddypress' ),
-                               'slug'            => 'profile',
-                               'parent_url'      => trailingslashit( $user_domain . $settings_slug ),
-                               'parent_slug'     => $settings_slug,
-                               'screen_function' => 'bp_xprofile_screen_settings',
-                               'position'        => 30,
-                               'user_has_access' => bp_core_can_edit_settings()
-                       );
</del><ins>+        /**
+        * Set up the Settings > Profile nav item.
+        *
+        * Loaded in a separate method because the Settings component may not
+        * be loaded in time for BP_XProfile_Component::setup_nav().
+        *
+        * @since BuddyPress (2.1.0)
+        */
+       public function setup_settings_nav() {
+               if ( ! bp_is_active( 'settings' ) ) {
+                       return;
</ins><span class="cx">           }
</span><span class="cx"> 
</span><del>-               parent::setup_nav( $main_nav, $sub_nav );
</del><ins>+                // Determine user to use
+               if ( bp_displayed_user_domain() ) {
+                       $user_domain = bp_displayed_user_domain();
+               } elseif ( bp_loggedin_user_domain() ) {
+                       $user_domain = bp_loggedin_user_domain();
+               } else {
+                       return;
+               }
+
+               // Get the settings slug
+               $settings_slug = bp_get_settings_slug();
+
+               bp_core_new_subnav_item( array(
+                       'name'            => __( 'Profile', 'buddypress' ),
+                       'slug'            => 'profile',
+                       'parent_url'      => trailingslashit( $user_domain . $settings_slug ),
+                       'parent_slug'     => $settings_slug,
+                       'screen_function' => 'bp_xprofile_screen_settings',
+                       'position'        => 30,
+                       'user_has_access' => bp_core_can_edit_settings()
+               ) );
</ins><span class="cx">   }
</span><span class="cx"> 
</span><span class="cx">  /**
</span><span class="lines">@@ -354,4 +376,4 @@
</span><span class="cx">  if ( !isset( $bp->profile->id ) )
</span><span class="cx">          $bp->profile = new BP_XProfile_Component();
</span><span class="cx"> }
</span><del>-add_action( 'bp_setup_components', 'bp_setup_xprofile', 6 );
</del><ins>+add_action( 'bp_setup_components', 'bp_setup_xprofile', 2 );
</ins></span></pre>
</div>
</div>

</body>
</html>