Make WordPress Core


Ignore:
Timestamp:
03/11/2015 10:48:16 PM (11 years ago)
Author:
pento
Message:

Add emoji support, with Twemoji fallback.

Replace exisiting smilies with equivalent emoji, or with shiny new smiley images where no emoji existed.

Props batmoo, joen and mkaz for the original plugin upon which this is based.

Props pento, iseulde, kraftbj and peterwilsoncc for making the internet's dreams come true.

See #31242

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/formatting.php

    r31678 r31733  
    20382038        $smiley = trim( reset( $matches ) );
    20392039        $img = $wpsmiliestrans[ $smiley ];
     2040
     2041        $matches = array();
     2042        $ext = preg_match( '/\.([^.]+)$/', $img, $matches ) ? strtolower( $matches[1] ) : false;
     2043        $image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' );
     2044
     2045        // Don't convert smilies that aren't images - they're probably emoji.
     2046        if ( ! in_array( $ext, $image_exts ) ) {
     2047                return $img;
     2048        }
    20402049
    20412050        /**
     
    40164025        return $spaces;
    40174026}
     4027
     4028/**
     4029 * Print the important emoji-related styles.
     4030 *
     4031 * @since 4.2.0
     4032 */
     4033function print_emoji_styles() {
     4034?>
     4035<style type="text/css">
     4036img.wp-smiley,
     4037img.emoji {
     4038        border: none !important;
     4039        box-shadow: none !important;
     4040        height: 1em !important;
     4041        width: 1em !important;
     4042        margin: 0 .05em 0 .1em !important;
     4043        vertical-align: -0.1em !important;
     4044        background: none !important;
     4045        padding: 0 !important;
     4046}
     4047</style>
     4048<?php
     4049}
     4050
     4051/**
     4052 * Convert any 4 byte emoji in a string to their equivalent HTML entity.
     4053 * Currently, only Unicode 7 emoji are supported. Unicode 8 emoji will be added
     4054 * when the spec in finalised, along with the new skin-tone modifiers.
     4055 *
     4056 * This allows us to store emoji in a DB using the utf8 character set.
     4057 *
     4058 * @since 4.2.0
     4059 *
     4060 * @param string $content The content to encode.
     4061 * @return string The encoded content.
     4062 */
     4063function wp_encode_emoji( $content ) {
     4064        if ( function_exists( 'mb_convert_encoding' ) ) {
     4065                $regex = '/(
     4066                     \x23\xE2\x83\xA3               # Digits
     4067                     [\x30-\x39]\xE2\x83\xA3
     4068                   | \xF0\x9F[\x85-\x88][\xA6-\xBF] # Enclosed characters
     4069                   | \xF0\x9F[\x8C-\x97][\x80-\xBF] # Misc
     4070                   | \xF0\x9F\x98[\x80-\xBF]        # Smilies
     4071                   | \xF0\x9F\x99[\x80-\x8F]
     4072                   | \xF0\x9F\x9A[\x80-\xBF]        # Transport and map symbols
     4073                   | \xF0\x9F\x99[\x80-\x85]
     4074                )/x';
     4075
     4076                $matches = array();
     4077                if ( preg_match_all( $regex, $content, $matches ) ) {
     4078                        if ( ! empty( $matches[1] ) ) {
     4079                                foreach( $matches[1] as $emoji ) {
     4080                                        /*
     4081                                         * UTF-32's hex encoding is the same as HTML's hex encoding.
     4082                                         * So, by converting the emoji from UTF-8 to UTF-32, we magically
     4083                                         * get the correct hex encoding.
     4084                                         */
     4085                                        $unpacked = unpack( 'H*', mb_convert_encoding( $emoji, 'UTF-32', 'UTF-8' ) );
     4086                                        if ( isset( $unpacked[1] ) ) {
     4087                                                $entity = '&#x' . trim( $unpacked[1], '0' ) . ';';
     4088                                                $content = str_replace( $emoji, $entity, $content );
     4089                                        }
     4090                                }
     4091                        }
     4092                }
     4093        }
     4094
     4095        return $content;
     4096}
     4097
     4098/**
     4099 * Convert emoji to a static <img> link.
     4100 *
     4101 * @since 4.2.0
     4102 *
     4103 * @param string $content The content to encode.
     4104 * @return string The encoded content.
     4105 */
     4106function wp_staticize_emoji( $content ) {
     4107        $content = wp_encode_emoji( $content );
     4108
     4109        if ( ! class_exists( 'DOMDocument' ) ) {
     4110                return $content;
     4111        }
     4112
     4113        /** This filter is documented in wp-includes/script-loader.php */
     4114        $cdn_url = apply_filters( 'emoji_url', '//s0.wp.com/wp-content/mu-plugins/emoji/twemoji/72x72/' );
     4115        /** This filter is documented in wp-includes/script-loader.php */
     4116        $ext = apply_filters( 'emoji_ext', '.png' );
     4117
     4118        $html = '<!DOCTYPE html><html><head></head><body>' . $content . '</body></html>';
     4119
     4120        $document = new DOMDocument;
     4121        if ( ! $document->loadHTML( $html ) ) {
     4122                return $content;
     4123        }
     4124
     4125        $xpath = new DOMXPath( $document );
     4126        $textnodes = $xpath->query( '//text()' );
     4127
     4128        foreach( $textnodes as $node ) {
     4129                $originalText = $text = wp_encode_emoji( $node->nodeValue );
     4130
     4131                $matches = array();
     4132                if ( preg_match_all( '/(&#x1f1(e[6-9a-f]|f[0-9a-f]);){2}/', $text, $matches ) ) {
     4133                        if ( ! empty( $matches[0] ) ) {
     4134                                foreach ( $matches[0] as $flag ) {
     4135                                        $chars = str_replace( array( '&#x', ';'), '', $flag );
     4136
     4137                                        list( $char1, $char2 ) = str_split( $chars, 5 );
     4138                                        $entity = '<img src="https:' . $cdn_url . $char1 . '-' . $char2 . $ext . '" class="wp-smiley" style="height: 1em;" />';
     4139
     4140                                        $text = str_replace( $flag, $entity, $text );
     4141                                }
     4142                        }
     4143                }
     4144
     4145                // Loosely match the Emoji Unicode range.
     4146                $regex = '/(&#x[2-3][0-9a-f]{3};|&#x1f[1-6][0-9a-f]{2};)/';
     4147
     4148                $matches = array();
     4149                if ( preg_match_all( $regex, $text, $matches ) ) {
     4150                        if ( ! empty( $matches[1] ) ) {
     4151                                foreach ( $matches[1] as $emoji ) {
     4152                                        $char = str_replace( array( '&#x', ';'), '', $emoji );
     4153                                        $entity = '<img src="https:' . $cdn_url . $char . $ext . '" class="wp-smiley" style="height: 1em;" />';
     4154
     4155                                        $text = str_replace( $emoji, $entity, $text );
     4156                                }
     4157                        }
     4158                }
     4159
     4160                if ( $originalText !== $text ) {
     4161                        $content = str_replace( $originalText, $text, $content );
     4162                }
     4163        }
     4164
     4165        return $content;
     4166}
     4167
     4168/**
     4169 * Convert emoji in emails into static images.
     4170 *
     4171 * @param array $mail The email data array.
     4172 *
     4173 * @return array The email data array, with emoji in the message staticized.
     4174 */
     4175function mail_emoji( $mail ) {
     4176        $mail['message'] = wp_staticize_emoji( $mail['message'], true );
     4177        return $mail;
     4178}
Note: See TracChangeset for help on using the changeset viewer.