Index: src/wp-includes/user-functions.php
===================================================================
--- src/wp-includes/user-functions.php	(revision 34691)
+++ src/wp-includes/user-functions.php	(working copy)
@@ -500,38 +500,58 @@
  */
 function get_blogs_of_user( $user_id, $all = false ) {
 	global $wpdb;
+	static $blogs = array();
 
 	$user_id = (int) $user_id;
 
 	// Logged out users can't have blogs
-	if ( empty( $user_id ) )
+	if ( empty( $user_id ) ) {
 		return array();
+	}
 
+	/**
+	 * Filter a user's blogs array before it is retrieved.
+	 *
+	 * @since 4.4
+	 *
+	 * @param array $blogs[ $user_id ] An array of blog objects belonging to the user. Default null.
+	 * @param int   $user_id           User ID.
+	 * @param bool  $all               Whether the returned blogs array should contain all
+	 *                                 blogs, including those marked 'deleted', 'archived',
+	 *                                 or 'spam'. Default false.
+	 */
+	$blogs[ $user_id ] = apply_filters( 'pre_get_blogs_of_user', null, $user_id, $all );
+
+	if ( is_array( $blogs[ $user_id ] ) ) {
+		return $blogs[ $user_id ];
+	}
+
 	$keys = get_user_meta( $user_id );
-	if ( empty( $keys ) )
+	if ( empty( $keys ) ) {
 		return array();
+	}
 
 	if ( ! is_multisite() ) {
 		$blog_id = get_current_blog_id();
-		$blogs = array( $blog_id => new stdClass );
-		$blogs[ $blog_id ]->userblog_id = $blog_id;
-		$blogs[ $blog_id ]->blogname = get_option('blogname');
-		$blogs[ $blog_id ]->domain = '';
-		$blogs[ $blog_id ]->path = '';
-		$blogs[ $blog_id ]->site_id = 1;
-		$blogs[ $blog_id ]->siteurl = get_option('siteurl');
-		$blogs[ $blog_id ]->archived = 0;
-		$blogs[ $blog_id ]->spam = 0;
-		$blogs[ $blog_id ]->deleted = 0;
-		return $blogs;
+		$blogs[ $user_id ] = array( $blog_id => new stdClass );
+		$blogs[ $user_id ][ $blog_id ]->userblog_id = $blog_id;
+		$blogs[ $user_id ][ $blog_id ]->blogname = get_option('blogname');
+		$blogs[ $user_id ][ $blog_id ]->domain = '';
+		$blogs[ $user_id ][ $blog_id ]->path = '';
+		$blogs[ $user_id ][ $blog_id ]->site_id = 1;
+		$blogs[ $user_id ][ $blog_id ]->siteurl = get_option('siteurl');
+		$blogs[ $user_id ][ $blog_id ]->archived = 0;
+		$blogs[ $user_id ][ $blog_id ]->spam = 0;
+		$blogs[ $user_id ][ $blog_id ]->deleted = 0;
+		return $blogs[ $user_id ];
 	}
 
-	$blogs = array();
+	$blogs[ $user_id ] = array();
 
 	if ( isset( $keys[ $wpdb->base_prefix . 'capabilities' ] ) && defined( 'MULTISITE' ) ) {
 		$blog = get_blog_details( 1 );
 		if ( $blog && isset( $blog->domain ) && ( $all || ( ! $blog->archived && ! $blog->spam && ! $blog->deleted ) ) ) {
-			$blogs[ 1 ] = (object) array(
+			$blogs[ $user_id ][ 1 ] = (object) array(
 				'userblog_id' => 1,
 				'blogname'    => $blog->blogname,
 				'domain'      => $blog->domain,
@@ -561,7 +581,7 @@
 		$blog_id = (int) $blog_id;
 		$blog = get_blog_details( $blog_id );
 		if ( $blog && isset( $blog->domain ) && ( $all || ( ! $blog->archived && ! $blog->spam && ! $blog->deleted ) ) ) {
-			$blogs[ $blog_id ] = (object) array(
+			$blogs[ $user_id ][ $blog_id ] = (object) array(
 				'userblog_id' => $blog_id,
 				'blogname'    => $blog->blogname,
 				'domain'      => $blog->domain,
@@ -581,12 +601,13 @@
 	 *
 	 * @since MU
 	 *
-	 * @param array $blogs   An array of blog objects belonging to the user.
-	 * @param int   $user_id User ID.
-	 * @param bool  $all     Whether the returned blogs array should contain all blogs, including
-	 *                       those marked 'deleted', 'archived', or 'spam'. Default false.
+	 * @param array $blogs[ $user_id ] An array of blog objects belonging to the user.
+	 * @param int   $user_id           User ID.
+	 * @param bool  $all               Whether the returned blogs array should contain all
+	 *                                 blogs, including those marked 'deleted', 'archived',
+	 *                                 or 'spam'. Default false.
 	 */
-	return apply_filters( 'get_blogs_of_user', $blogs, $user_id, $all );
+	return apply_filters( 'get_blogs_of_user', $blogs[ $user_id ], $user_id, $all );
 }
 
 /**
Index: tests/phpunit/tests/user/multisite.php
===================================================================
--- tests/phpunit/tests/user/multisite.php	(revision 34691)
+++ tests/phpunit/tests/user/multisite.php	(working copy)
@@ -106,6 +106,11 @@
 		// Passing false (the default) as the second parameter should retrieve only good sites.
 		$blog_ids_of_user = array_keys( get_blogs_of_user( $user1_id, false ) );
 		$this->assertEquals( $blog_ids, $blog_ids_of_user );
+
+		add_filter( 'pre_get_blogs_of_user', '__return_empty_array' );
+		$blogs_of_user = get_blogs_of_user( $user1_id, false );
+
+		$this->assertTrue( is_array( $blog_ids ) && empty( $blog_ids ) );
 	}
 
 	/**
