Index: src/wp-admin/includes/post.php
===================================================================
--- src/wp-admin/includes/post.php	(revision 31259)
+++ src/wp-admin/includes/post.php	(working copy)
@@ -325,6 +325,10 @@
 
 		foreach( $fields as $field ) {
 			if ( isset( $post_data[ $field ] ) ) {
+				$charset = $wpdb->get_col_charset( $wpdb->posts, $field );
+				if ( 'utf8' === $charset ) {
+					$post_data[ $field ] = wp_encode_emoji( $post_data[ $field ] );
+				}
 				$post_data[ $field ] = $wpdb->strip_invalid_text_for_column( $wpdb->posts, $field, $post_data[ $field ] );
 			}
 		}
Index: src/wp-includes/formatting.php
===================================================================
--- src/wp-includes/formatting.php	(revision 31259)
+++ src/wp-includes/formatting.php	(working copy)
@@ -3318,6 +3318,10 @@
 
 		case 'blogdescription':
 		case 'blogname':
+			$charset = $wpdb->get_col_charset( $wpdb->options, 'option_value' );
+			if ( 'utf8' === $charset ) {
+				$value = wp_encode_emoji( $value );
+			}
 			$value = $wpdb->strip_invalid_text_for_column( $wpdb->options, 'option_value', $value );
 			$value = wp_kses_post( $value );
 			$value = esc_html( $value );
@@ -4015,3 +4019,41 @@
 
 	return $spaces;
 }
+
+/**
+ * Convert any 4 byte emoji in a string to their equivalent HTML entitiy.
+ *
+ * This allows us to store emoji in a DB using the utf8 character set.
+ *
+ * @since 4.2.0
+ * @param  string $content The content to encode
+ * @return string The encoded content
+ */
+function wp_encode_emoji( $content ) {
+	if ( function_exists( 'mb_convert_encoding' ) ) {
+		$regex = '/(
+			  \x23\xE2\x83\xA3               # Digits
+			  [\x30-\x39]\xE2\x83\xA3
+			| \xF0\x9F[\x85-\x88][\xB0-\xBF] # Enclosed characters
+			| \xF0\x9F[\x8C-\x97][\x80-\xBF] # Misc
+			| \xF0\x9F\x98[\x80-\xBF]        # Smilies
+			| \xF0\x9F\x99[\x80-\x8F]
+			| \xF0\x9F\x9A[\x80-\xBF]        # Transport and map symbols
+			| \xF0\x9F\x99[\x80-\x85]
+		)/x';
+		$matches = array();
+		if ( preg_match_all( $regex, $content, $matches ) ) {
+			if ( ! empty( $matches[1] ) ) {
+				foreach( $matches[1] as $emoji ) {
+					$unpacked = unpack( 'H*', mb_convert_encoding( $emoji, 'UTF-32', 'UTF-8' ) );
+					if ( isset( $unpacked[1] ) ) {
+						$entity = '&#x' . trim( $unpacked[1], '0' ) . ';';
+						$content = str_replace( $emoji, $entity, $content );
+					}
+				}
+			}
+		}
+	}
+
+	return $content;
+}
\ No newline at end of file
Index: tests/phpunit/tests/formatting/Emoji.php
===================================================================
--- tests/phpunit/tests/formatting/Emoji.php	(revision 0)
+++ tests/phpunit/tests/formatting/Emoji.php	(working copy)
@@ -0,0 +1,20 @@
+<?php
+
+/**
+ * @group formatting
+ * @group emoji
+ */
+class Tests_Formatting_Emoji extends WP_UnitTestCase {
+	public function test_emoji_encoding() {
+		$content = "foo\xf0\x9f\x98\x89bar";
+		$expected = "foo&#x1f609;bar";
+		$encoded = wp_encode_emoji( $content );
+		$this->assertEquals( $expected, $encoded );
+	}
+
+	public function test_non_emoji_encoding() {
+		$content = "foo\xe5\x85\xb1bar";
+		$encoded = wp_encode_emoji( $content );
+		$this->assertEquals( $content, $encoded );
+	}
+}

Property changes on: tests/phpunit/tests/formatting/Emoji.php
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
