<!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][7570] trunk: Remove BuddyPress's restriction spaces in user_login</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/7570">7570</a></dd>
<dt>Author</dt> <dd>boonebgorges</dd>
<dt>Date</dt> <dd>2013-11-14 15:43:43 +0000 (Thu, 14 Nov 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Remove BuddyPress's restriction spaces in user_login

BuddyPress has historically enforced a no-spaces rule on user_login during
user registration. Originally this was rooted in WPMU's own peculiar character
restrictions, and when the MU requirement was dropped, the same restrictions
were carried over to WordPress Single.

However, these restrictions have caused various problems. BP enforced the "no
spaces" rule during registration by simply swapping out spaces with hyphens and
not telling users. This caused immense confusion. Moreover, the restriction
caused problems when bypassing BP's native user registration, as when
integrating with an external authentication service; these external usernames
*can* sometimes have spaces, and certain areas of BuddyPress were not equipped
to deal with them.

This changeset removes the no-spaces restriction from BuddyPress, and hands
off user_login validation to WordPress Multisite when possible (meaning that on
MS, spaces will still not be allowed during native registration). It also
makes the necessary adjustments throughout BuddyPress to ensure that spaces
in user_login will not break related functionality. On a normal setup, BP (and
WP) only use user_login for authentication, but several changes were necessary
to account for "username compatibility mode", where the user_login is displayed
publicly:

- Refactor the way that activity @-mentions work in username compatibility
  mode. We now have functions for converting user IDs to "mentionname" (and vice
  versa) which will produce @-mention-safe versions of user_nicename or
  user_login, as appropriate.
- Use proper URL encoding when building and parsing URLs that contain usernames
  when compatibility mode is enabled.
- Fix private messaging autocomplete to work with spaces.

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

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

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkbpactivitybpactivityfunctionsphp">trunk/bp-activity/bp-activity-functions.php</a></li>
<li><a href="#trunkbpactivitybpactivitytemplatephp">trunk/bp-activity/bp-activity-template.php</a></li>
<li><a href="#trunkbpmembersbpmembersfunctionsphp">trunk/bp-members/bp-members-functions.php</a></li>
<li><a href="#trunkbpmessagesbpmessagesfunctionsphp">trunk/bp-messages/bp-messages-functions.php</a></li>
<li><a href="#trunkbptemplatesbplegacybuddypressmemberssinglememberheaderphp">trunk/bp-templates/bp-legacy/buddypress/members/single/member-header.php</a></li>
<li><a href="#trunkbptemplatesbplegacybuddypressfunctionsphp">trunk/bp-templates/bp-legacy/buddypress-functions.php</a></li>
<li><a href="#trunkbpthemesbpdefault_incajaxphp">trunk/bp-themes/bp-default/_inc/ajax.php</a></li>
<li><a href="#trunkbpthemesbpdefaultmemberssinglememberheaderphp">trunk/bp-themes/bp-default/members/single/member-header.php</a></li>
<li><a href="#trunkteststestcasesactivityfunctionsphp">trunk/tests/testcases/activity/functions.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkbpactivitybpactivityfunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-activity/bp-activity-functions.php (7569 => 7570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-activity/bp-activity-functions.php      2013-11-13 02:47:20 UTC (rev 7569)
+++ trunk/bp-activity/bp-activity-functions.php 2013-11-14 15:43:43 UTC (rev 7570)
</span><span class="lines">@@ -72,11 +72,7 @@
</span><span class="cx"> 
</span><span class="cx">  // We've found some mentions! Check to see if users exist
</span><span class="cx">  foreach( (array) $usernames as $key => $username ) {
</span><del>-               if ( bp_is_username_compatibility_mode() ) {
-                       $user_id = username_exists( $username );
-               } else {
-                       $user_id = bp_core_get_userid_from_nicename( $username );
-               }
</del><ins>+                $user_id = bp_activity_get_userid_from_mentionname( $username );
</ins><span class="cx"> 
</span><span class="cx">          // user ID exists, so let's add it to our array
</span><span class="cx">          if ( ! empty( $user_id ) ) {
</span><span class="lines">@@ -247,6 +243,69 @@
</span><span class="cx">  return $return;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/**
+ * Determine a user's "mentionname", the name used for that user in @-mentions.
+ *
+ * @since BuddyPress (1.9.0)
+ *
+ * @return string User name appropriate for @-mentions.
+ */
+function bp_activity_get_user_mentionname( $user_id ) {
+       $mentionname = '';
+
+       $userdata = bp_core_get_core_userdata( $user_id );
+
+       if ( $userdata ) {
+               if ( bp_is_username_compatibility_mode() ) {
+                       $mentionname = str_replace( ' ', '-', $userdata->user_login );
+               } else {
+                       $mentionname = $userdata->user_nicename;
+               }
+       }
+
+       return $mentionname;
+}
+
+/**
+ * Get a user ID from a "mentionname", the name used for a user in @-mentions.
+ *
+ * @since BuddyPress (1.9.0)
+ *
+ * @return int|bool ID of the user, if one is found. Otherwise false.
+ */
+function bp_activity_get_userid_from_mentionname( $mentionname ) {
+       $user_id = false;
+
+       // In username compatibility mode, hyphens are ambiguous between
+       // actual hyphens and converted spaces.
+       //
+       // @todo There is the potential for username clashes between 'foo bar'
+       // and 'foo-bar' in compatibility mode. Come up with a system for
+       // unique mentionnames.
+       if ( bp_is_username_compatibility_mode() ) {
+               // First, try the raw username
+               $userdata = get_user_by( 'login', $mentionname );
+
+               // Doing a direct query to use proper regex. Necessary to
+               // account for hyphens + spaces in the same user_login.
+               if ( empty( $userdata ) || ! is_a( $userdata, 'WP_User' ) ) {
+                       global $wpdb;
+                       $regex   = esc_sql( str_replace( '-', '[ \-]', $mentionname ) );
+                       $user_id = $wpdb->get_var( "SELECT ID FROM {$wpdb->users} WHERE user_login REGEXP '{$regex}'" );
+               } else {
+                       $user_id = $userdata->ID;
+               }
+
+       // When username compatibility mode is disabled, the mentionname is
+       // the same as the nicename
+       } else {
+               $user_id = bp_core_get_userid_from_nicename( $mentionname );
+       }
+
+
+       return $user_id;
+}
+
</ins><span class="cx"> /** Actions ******************************************************************/
</span><span class="cx"> 
</span><span class="cx"> /**
</span></span></pre></div>
<a id="trunkbpactivitybpactivitytemplatephp"></a>
<div class="modfile"><h4>Modified: trunk/bp-activity/bp-activity-template.php (7569 => 7570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-activity/bp-activity-template.php       2013-11-13 02:47:20 UTC (rev 7569)
+++ trunk/bp-activity/bp-activity-template.php  2013-11-14 15:43:43 UTC (rev 7570)
</span><span class="lines">@@ -583,7 +583,7 @@
</span><span class="cx">                                  }
</span><span class="cx"> 
</span><span class="cx">                                  // Start search at @ symbol and stop search at closing tag delimiter.
</span><del>-                                       $search_terms     = '@' . bp_core_get_username( $user_id ) . '<';
</del><ins>+                                        $search_terms     = '@' . bp_activity_get_user_mentionname( $user_id ) . '<';
</ins><span class="cx">                                   $display_comments = 'stream';
</span><span class="cx">                                  $user_id = 0;
</span><span class="cx">                                  break;
</span><span class="lines">@@ -2718,9 +2718,10 @@
</span><span class="cx">          if ( ! is_user_logged_in() || ! bp_is_user() || bp_is_my_profile() )
</span><span class="cx">                  return false;
</span><span class="cx"> 
</span><del>-               return apply_filters( 'bp_get_send_public_message_link', wp_nonce_url( bp_get_activity_directory_permalink() . '?r=' . bp_get_displayed_user_username() ) );
</del><ins>+                return apply_filters( 'bp_get_send_public_message_link', wp_nonce_url( bp_get_activity_directory_permalink() . '?r=' . bp_get_displayed_user_mentionname() ) );
</ins><span class="cx">   }
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> /**
</span><span class="cx">  * Output the mentioned user display name.
</span><span class="cx">  *
</span><span class="lines">@@ -2919,6 +2920,24 @@
</span><span class="cx">          return $user_ids;
</span><span class="cx">  }
</span><span class="cx"> 
</span><ins>+/**
+ * Output the mentionname for the displayed user.
+ *
+ * @since BuddyPress (1.9.0)
+ */
+function bp_displayed_user_mentionname() {
+       echo bp_get_displayed_user_mentionname();
+}
+       /**
+        * Get the mentionname for the displayed user.
+        *
+        * @since BuddyPress (1.9.0)
+        *
+        * @return string Mentionname for the displayed user, if available.
+        */
+       function bp_get_displayed_user_mentionname() {
+               return apply_filters( 'bp_get_displayed_user_mentionname', bp_activity_get_user_mentionname( bp_displayed_user_id() ) );
+       }
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Echo a list of all registered activity types for use in dropdowns or checkbox lists.
</span></span></pre></div>
<a id="trunkbpmembersbpmembersfunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-members/bp-members-functions.php (7569 => 7570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-members/bp-members-functions.php        2013-11-13 02:47:20 UTC (rev 7569)
+++ trunk/bp-members/bp-members-functions.php   2013-11-14 15:43:43 UTC (rev 7570)
</span><span class="lines">@@ -269,11 +269,6 @@
</span><span class="cx">          $update_cache = false;
</span><span class="cx">  }
</span><span class="cx"> 
</span><del>-       // Check $username for empty spaces and default to nicename if found
-       if ( strstr( $username, ' ' ) ) {
-               $username = bp_members_get_user_nicename( $user_id );
-       }
-
</del><span class="cx">   // Add this to cache
</span><span class="cx">  if ( ( true === $update_cache ) && !empty( $username ) ) {
</span><span class="cx">          wp_cache_set( 'bp_user_username_' . $user_id, $username, 'bp' );
</span><span class="lines">@@ -946,21 +941,6 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Strips spaces from usernames that are created using add_user() and wp_insert_user()
- *
- * @package BuddyPress Core
- */
-function bp_core_strip_username_spaces( $username ) {
-       // Don't alter the user_login of existing users, as it causes user_nicename problems.
-       // See http://trac.buddypress.org/ticket/2642
-       if ( username_exists( $username ) && ( !bp_is_username_compatibility_mode() ) )
-               return $username;
-
-       return str_replace( ' ', '-', $username );
-}
-add_action( 'pre_user_login', 'bp_core_strip_username_spaces' );
-
-/**
</del><span class="cx">  * When a user logs in, check if they have been marked as a spammer. If yes then simply
</span><span class="cx">  * redirect them to the home page and stop them from logging in.
</span><span class="cx">  *
</span><span class="lines">@@ -1172,68 +1152,77 @@
</span><span class="cx">  */
</span><span class="cx"> function bp_core_validate_user_signup( $user_name, $user_email ) {
</span><span class="cx"> 
</span><del>-       $errors = new WP_Error();
-
-       // Apply any user_login filters added by BP or other plugins before validating
-       $user_name = apply_filters( 'pre_user_login', $user_name );
-
-       if ( empty( $user_name ) )
-               $errors->add( 'user_name', __( 'Please enter a username', 'buddypress' ) );
-
</del><span class="cx">   // Make sure illegal names include BuddyPress slugs and values
</span><span class="cx">  bp_core_flush_illegal_names();
</span><span class="cx"> 
</span><del>-       $illegal_names = get_site_option( 'illegal_names' );
</del><ins>+        // WordPress Multisite has its own validation. Use it, so that we
+       // properly mirror restrictions on username, etc.
+       if ( function_exists( 'wpmu_validate_user_signup' ) ) {
+               $result = wpmu_validate_user_signup( $user_name, $user_email );
</ins><span class="cx"> 
</span><del>-       if ( in_array( $user_name, (array) $illegal_names ) )
-               $errors->add( 'user_name', __( 'That username is not allowed', 'buddypress' ) );
</del><ins>+        // When not running Multisite, we perform our own validation. What
+       // follows reproduces much of the logic of wpmu_validate_user_signup(),
+       // minus the multisite-specific restrictions on user_login
+       } else {
+               $errors = new WP_Error();
</ins><span class="cx"> 
</span><del>-       if ( ! validate_username( $user_name ) ) {
-               // Check for capital letters when on multisite.
-               //
-               // If so, throw a different error message.
-               // @see #5175
-               if ( is_multisite() ) {
-                       $match = array();
-                       preg_match( '/[A-Z]/', $user_name, $match );
</del><ins>+                // Apply any user_login filters added by BP or other plugins before validating
+               $user_name = apply_filters( 'pre_user_login', $user_name );
</ins><span class="cx"> 
</span><del>-                       if ( ! empty( $match ) ) {
-                               $errors->add( 'user_name', __( 'Username must be in lowercase characters', 'buddypress' ) );
-                       }
</del><ins>+                // User name can't be empty
+               if ( empty( $user_name ) ) {
+                       $errors->add( 'user_name', __( 'Please enter a username', 'buddypress' ) );
+               }
</ins><span class="cx"> 
</span><del>-               } else {
</del><ins>+                // user name can't be on the blacklist
+               $illegal_names = get_site_option( 'illegal_names' );
+               if ( in_array( $user_name, (array) $illegal_names ) ) {
+                       $errors->add( 'user_name', __( 'That username is not allowed', 'buddypress' ) );
+               }
+
+               // User name must pass WP's validity check
+               if ( ! validate_username( $user_name ) ) {
</ins><span class="cx">                   $errors->add( 'user_name', __( 'Usernames can contain only letters, numbers, ., -, and @', 'buddypress' ) );
</span><span class="cx">          }
</span><del>-       }
</del><span class="cx"> 
</span><del>-       if( strlen( $user_name ) < 4 )
-               $errors->add( 'user_name',  __( 'Username must be at least 4 characters', 'buddypress' ) );
</del><ins>+                // Minimum of 4 characters
+               if ( strlen( $user_name ) < 4 ) {
+                       $errors->add( 'user_name',  __( 'Username must be at least 4 characters', 'buddypress' ) );
+               }
</ins><span class="cx"> 
</span><del>-       if ( strpos( ' ' . $user_name, '_' ) != false )
-               $errors->add( 'user_name', __( 'Sorry, usernames may not contain the character "_"!', 'buddypress' ) );
</del><ins>+                // No underscores. @todo Why not?
+               if ( false !== strpos( ' ' . $user_name, '_' ) ) {
+                       $errors->add( 'user_name', __( 'Sorry, usernames may not contain the character "_"!', 'buddypress' ) );
+               }
</ins><span class="cx"> 
</span><del>-       // Is the user_name all numeric?
-       $match = array();
-       preg_match( '/[0-9]*/', $user_name, $match );
</del><ins>+                // No usernames that are all numeric. @todo Why?
+               $match = array();
+               preg_match( '/[0-9]*/', $user_name, $match );
+               if ( $match[0] == $user_name ) {
+                       $errors->add( 'user_name', __( 'Sorry, usernames must have letters too!', 'buddypress' ) );
+               }
</ins><span class="cx"> 
</span><del>-       if ( $match[0] == $user_name )
-               $errors->add( 'user_name', __( 'Sorry, usernames must have letters too!', 'buddypress' ) );
</del><ins>+                // Check if the username has been used already.
+               if ( username_exists( $user_name ) ) {
+                       $errors->add( 'user_name', __( 'Sorry, that username already exists!', 'buddypress' ) );
+               }
</ins><span class="cx"> 
</span><del>-       // Check if the username has been used already.
-       if ( username_exists( $user_name ) )
-               $errors->add( 'user_name', __( 'Sorry, that username already exists!', 'buddypress' ) );
</del><ins>+                // Validate the email address and process the validation results into
+               // error messages
+               $validate_email = bp_core_validate_email_address( $user_email );
+               bp_core_add_validation_error_messages( $errors, $validate_email );
</ins><span class="cx"> 
</span><del>-       // Validate the email address and process the validation results into
-       // error messages
-       $validate_email = bp_core_validate_email_address( $user_email );
-       bp_core_add_validation_error_messages( $errors, $validate_email );
</del><ins>+                // Assemble the return array
+               $result = array(
+                       'user_name'  => $user_name,
+                       'user_email' => $user_email,
+                       'errors'     => $errors,
+               );
</ins><span class="cx"> 
</span><del>-       // Assemble the return array
-       $result = array( 'user_name' => $user_name, 'user_email' => $user_email, 'errors' => $errors );
</del><ins>+                // Apply WPMU legacy filter
+               $result = apply_filters( 'wpmu_validate_user_signup', $result );
+       }
</ins><span class="cx"> 
</span><del>-       // Apply WPMU legacy filter
-       $result = apply_filters( 'wpmu_validate_user_signup', $result );
-
</del><span class="cx">   return apply_filters( 'bp_core_validate_user_signup', $result );
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkbpmessagesbpmessagesfunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-messages/bp-messages-functions.php (7569 => 7570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-messages/bp-messages-functions.php      2013-11-13 02:47:20 UTC (rev 7569)
+++ trunk/bp-messages/bp-messages-functions.php 2013-11-14 15:43:43 UTC (rev 7570)
</span><span class="lines">@@ -77,7 +77,7 @@
</span><span class="cx">                  // check user_login / nicename columns first
</span><span class="cx">                  // @see http://buddypress.trac.wordpress.org/ticket/5151
</span><span class="cx">                  if ( bp_is_username_compatibility_mode() ) {
</span><del>-                               $recipient_id = bp_core_get_userid( $recipient );
</del><ins>+                                $recipient_id = bp_core_get_userid( urldecode( $recipient ) );
</ins><span class="cx">                   } else {
</span><span class="cx">                          $recipient_id = bp_core_get_userid_from_nicename( $recipient );
</span><span class="cx">                  }
</span></span></pre></div>
<a id="trunkbptemplatesbplegacybuddypressmemberssinglememberheaderphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-templates/bp-legacy/buddypress/members/single/member-header.php (7569 => 7570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-templates/bp-legacy/buddypress/members/single/member-header.php 2013-11-13 02:47:20 UTC (rev 7569)
+++ trunk/bp-templates/bp-legacy/buddypress/members/single/member-header.php    2013-11-14 15:43:43 UTC (rev 7570)
</span><span class="lines">@@ -22,7 +22,7 @@
</span><span class="cx"> <div id="item-header-content">
</span><span class="cx"> 
</span><span class="cx">  <?php if ( bp_is_active( 'activity' ) && bp_activity_do_mentions() ) : ?>
</span><del>-               <h2 class="user-nicename">@<?php bp_displayed_user_username(); ?></h2>
</del><ins>+                <h2 class="user-nicename">@<?php bp_displayed_user_mentionname(); ?></h2>
</ins><span class="cx">   <?php endif; ?>
</span><span class="cx"> 
</span><span class="cx">  <span class="activity"><?php bp_last_activity( bp_displayed_user_id() ); ?></span>
</span></span></pre></div>
<a id="trunkbptemplatesbplegacybuddypressfunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-templates/bp-legacy/buddypress-functions.php (7569 => 7570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-templates/bp-legacy/buddypress-functions.php    2013-11-13 02:47:20 UTC (rev 7569)
+++ trunk/bp-templates/bp-legacy/buddypress-functions.php       2013-11-14 15:43:43 UTC (rev 7570)
</span><span class="lines">@@ -1335,7 +1335,9 @@
</span><span class="cx">                  }
</span><span class="cx"> 
</span><span class="cx">                  if ( bp_is_username_compatibility_mode() ) {
</span><del>-                               $username = $ud->user_login;
</del><ins>+                                // Sanitize for spaces. Use urlencode() rather
+                               // than rawurlencode() because %20 breaks JS
+                               $username = urlencode( $ud->user_login );
</ins><span class="cx">                   } else {
</span><span class="cx">                          $username = $ud->user_nicename;
</span><span class="cx">                  }
</span></span></pre></div>
<a id="trunkbpthemesbpdefault_incajaxphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-themes/bp-default/_inc/ajax.php (7569 => 7570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-themes/bp-default/_inc/ajax.php 2013-11-13 02:47:20 UTC (rev 7569)
+++ trunk/bp-themes/bp-default/_inc/ajax.php    2013-11-14 15:43:43 UTC (rev 7570)
</span><span class="lines">@@ -982,7 +982,8 @@
</span><span class="cx">                  }
</span><span class="cx"> 
</span><span class="cx">                  if ( bp_is_username_compatibility_mode() ) {
</span><del>-                               $username = $ud->user_login;
</del><ins>+                                // Sanitize for spaces
+                               $username = urlencode( $ud->user_login );
</ins><span class="cx">                   } else {
</span><span class="cx">                          $username = $ud->user_nicename;
</span><span class="cx">                  }
</span></span></pre></div>
<a id="trunkbpthemesbpdefaultmemberssinglememberheaderphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-themes/bp-default/members/single/member-header.php (7569 => 7570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-themes/bp-default/members/single/member-header.php      2013-11-13 02:47:20 UTC (rev 7569)
+++ trunk/bp-themes/bp-default/members/single/member-header.php 2013-11-14 15:43:43 UTC (rev 7570)
</span><span class="lines">@@ -26,7 +26,7 @@
</span><span class="cx">  </h2>
</span><span class="cx"> 
</span><span class="cx">  <?php if ( bp_is_active( 'activity' ) && bp_activity_do_mentions() ) : ?>
</span><del>-               <span class="user-nicename">@<?php bp_displayed_user_username(); ?></span>
</del><ins>+                <span class="user-nicename">@<?php bp_displayed_user_mentionname(); ?></span>
</ins><span class="cx">   <?php endif; ?>
</span><span class="cx"> 
</span><span class="cx">  <span class="activity"><?php bp_last_activity( bp_displayed_user_id() ); ?></span>
</span></span></pre></div>
<a id="trunkteststestcasesactivityfunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/tests/testcases/activity/functions.php (7569 => 7570)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/testcases/activity/functions.php     2013-11-13 02:47:20 UTC (rev 7569)
+++ trunk/tests/testcases/activity/functions.php        2013-11-14 15:43:43 UTC (rev 7570)
</span><span class="lines">@@ -100,4 +100,96 @@
</span><span class="cx">          bp_activity_update_meta( $a, 'linebreak_test', $meta_value );
</span><span class="cx">          $this->assertEquals( $meta_value, bp_activity_get_meta( $a, 'linebreak_test' ) );
</span><span class="cx">  }
</span><ins>+
+       /**
+        * @group bp_activity_get_user_mentionname
+        */
+       public function test_bp_activity_get_user_mentionname_compatibilitymode_off() {
+               add_filter( 'bp_is_username_compatibility_mode', '__return_false' );
+
+               $u = $this->create_user( array(
+                       'user_login' => 'foo bar baz',
+                       'user_nicename' => 'foo-bar-baz',
+               ) );
+
+               $this->assertEquals( 'foo-bar-baz', bp_activity_get_user_mentionname( $u ) );
+
+               remove_filter( 'bp_is_username_compatibility_mode', '__return_false' );
+       }
+
+       /**
+        * @group bp_activity_get_user_mentionname
+        */
+       public function test_bp_activity_get_user_mentionname_compatibilitymode_on() {
+               add_filter( 'bp_is_username_compatibility_mode', '__return_true' );
+
+               $u1 = $this->create_user( array(
+                       'user_login' => 'foo bar baz',
+                       'user_nicename' => 'foo-bar-baz',
+               ) );
+
+               $u2 = $this->create_user( array(
+                       'user_login' => 'foo.bar.baz',
+                       'user_nicename' => 'foo-bar-baz',
+               ) );
+
+               $this->assertEquals( 'foo-bar-baz', bp_activity_get_user_mentionname( $u1 ) );
+               $this->assertEquals( 'foo.bar.baz', bp_activity_get_user_mentionname( $u2 ) );
+
+               remove_filter( 'bp_is_username_compatibility_mode', '__return_true' );
+       }
+
+       /**
+        * @group bp_activity_get_userid_from_mentionname
+        */
+       public function test_bp_activity_get_userid_from_mentionname_compatibilitymode_off() {
+               add_filter( 'bp_is_username_compatibility_mode', '__return_false' );
+
+               $u = $this->create_user( array(
+                       'user_login' => 'foo bar baz',
+                       'user_nicename' => 'foo-bar-baz',
+               ) );
+
+               $this->assertEquals( $u, bp_activity_get_userid_from_mentionname( 'foo-bar-baz' ) );
+
+               remove_filter( 'bp_is_username_compatibility_mode', '__return_false' );
+       }
+
+       /**
+        * @group bp_activity_get_userid_from_mentionname
+        */
+       public function test_bp_activity_get_userid_from_mentionname_compatibilitymode_on() {
+               add_filter( 'bp_is_username_compatibility_mode', '__return_true' );
+
+               // all spaces are hyphens
+               $u1 = $this->create_user( array(
+                       'user_login' => 'foo bar baz',
+                       'user_nicename' => 'foobarbaz',
+               ) );
+
+               // no spaces are hyphens
+               $u2 = $this->create_user( array(
+                       'user_login' => 'foo-bar-baz-1',
+                       'user_nicename' => 'foobarbaz-1',
+               ) );
+
+               // some spaces are hyphens
+               $u3 = $this->create_user( array(
+                       'user_login' => 'foo bar-baz 2',
+                       'user_nicename' => 'foobarbaz-2',
+               ) );
+
+               $u4 = $this->create_user( array(
+                       'user_login' => 'foo.bar.baz',
+                       'user_nicename' => 'foo-bar-baz',
+               ) );
+
+               $this->assertEquals( $u1, bp_activity_get_userid_from_mentionname( 'foo-bar-baz' ) );
+               $this->assertEquals( $u2, bp_activity_get_userid_from_mentionname( 'foo-bar-baz-1' ) );
+               $this->assertEquals( $u3, bp_activity_get_userid_from_mentionname( 'foo-bar-baz-2' ) );
+               $this->assertEquals( $u4, bp_activity_get_userid_from_mentionname( 'foo.bar.baz' ) );
+
+               remove_filter( 'bp_is_username_compatibility_mode', '__return_true' );
+       }
+
</ins><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>