Add emoji support to newsletter body [MAILPOET-1009]

This commit is contained in:
stoletniy
2017-08-28 19:07:17 +03:00
parent 544bf0ddfd
commit b9bdc86fd9
6 changed files with 169 additions and 2 deletions

View File

@ -48,6 +48,11 @@ class Menu {
if(self::isOnMailPoetAdminPage()) {
do_action('mailpoet_conflict_resolver_styles');
do_action('mailpoet_conflict_resolver_scripts');
if($_REQUEST['page'] === 'mailpoet-newsletter-editor') {
// Disable WP emojis to not interfere with the newsletter editor emoji handling
$this->disableWPEmojis();
}
}
$main_page_slug = 'mailpoet-newsletters';
@ -278,6 +283,11 @@ class Menu {
);
}
function disableWPEmojis() {
remove_action('admin_print_scripts', 'print_emoji_detection_script');
remove_action('admin_print_styles', 'print_emoji_styles');
}
function welcome() {
if((bool)(defined('DOING_AJAX') && DOING_AJAX)) return;

View File

@ -4,6 +4,7 @@ use Carbon\Carbon;
use MailPoet\Newsletter\Renderer\Renderer;
use MailPoet\Util\Helpers;
use MailPoet\Util\Security;
use MailPoet\WP\Emoji;
if(!defined('ABSPATH')) exit;
@ -794,6 +795,10 @@ class Newsletter extends Model {
$newsletter = self::findOne((int)$data['id']);
}
if(!empty($data['body'])) {
$data['body'] = Emoji::encodeForUTF8Column(self::$_table, 'body', $data['body']);
}
if($newsletter === false) {
$newsletter = self::create();

View File

@ -1,6 +1,8 @@
<?php
namespace MailPoet\Models;
use MailPoet\WP\Emoji;
if(!defined('ABSPATH')) exit;
class SendingQueue extends Model {
@ -55,7 +57,10 @@ class SendingQueue extends Model {
$this->set('subscribers', serialize($this->subscribers));
}
if(!is_serialized($this->newsletter_rendered_body) && !is_null($this->newsletter_rendered_body)) {
$this->set('newsletter_rendered_body', serialize($this->newsletter_rendered_body));
$this->set(
'newsletter_rendered_body',
serialize($this->encodeEmojisInBody($this->newsletter_rendered_body))
);
}
// set the default priority to medium
if(!$this->priority) {
@ -81,12 +86,34 @@ class SendingQueue extends Model {
function getNewsletterRenderedBody($type = false) {
$rendered_newsletter = (!is_serialized($this->newsletter_rendered_body)) ?
$this->newsletter_rendered_body :
unserialize($this->newsletter_rendered_body);
$this->decodeEmojisInBody(unserialize($this->newsletter_rendered_body));
return ($type && !empty($rendered_newsletter[$type])) ?
$rendered_newsletter[$type] :
$rendered_newsletter;
}
function encodeEmojisInBody($newsletter_rendered_body) {
if(is_array($newsletter_rendered_body)) {
foreach($newsletter_rendered_body as $key => $value) {
$newsletter_rendered_body[$key] = Emoji::encodeForUTF8Column(
self::$_table,
'newsletter_rendered_body',
$value
);
}
}
return $newsletter_rendered_body;
}
function decodeEmojisInBody($newsletter_rendered_body) {
if(is_array($newsletter_rendered_body)) {
foreach($newsletter_rendered_body as $key => $value) {
$newsletter_rendered_body[$key] = Emoji::decodeEntities($value);
}
}
return $newsletter_rendered_body;
}
function isSubscriberProcessed($subscriber_id) {
$subscribers = $this->getSubscribers();
return in_array($subscriber_id, $subscribers['processed']);

32
lib/WP/Emoji.php Normal file
View File

@ -0,0 +1,32 @@
<?php
namespace MailPoet\WP;
class Emoji {
static function encodeForUTF8Column($table, $field, $value) {
global $wpdb;
$charset = $wpdb->get_col_charset($table, $field);
if($charset === 'utf8') {
$value = wp_encode_emoji($value);
}
return $value;
}
static function decodeEntities($content) {
// Based on wp_staticize_emoji()
// Loosely match the Emoji Unicode range.
$regex = '/(&#x[2-3][0-9a-f]{3};|&#x1f[1-6][0-9a-f]{2};)/';
$matches = array();
if(preg_match_all($regex, $content, $matches)) {
if(!empty($matches[1])) {
foreach($matches[1] as $emoji) {
$entity = html_entity_decode($emoji, ENT_HTML5, 'UTF-8');
$content = str_replace($emoji, $entity, $content);
}
}
}
return $content;
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace MailPoet\Test\Models;
use AspectMock\Test as Mock;
use MailPoet\Models\SendingQueue;
class SendingQueueTest extends \MailPoetTest {
function _before() {
$this->queue = SendingQueue::create();
$this->queue->save();
$this->rendered_body = array(
'html' => 'some html',
'text' => 'some text'
);
}
function testItCanEncodeEmojisInBody() {
$mock = Mock::double('MailPoet\WP\Emoji', [
'encodeForUTF8Column' => function($params) {
return $params;
}
]);
$this->queue->encodeEmojisInBody($this->rendered_body);
$mock->verifyInvokedMultipleTimes('encodeForUTF8Column', 2);
}
function testItCanDecodeEmojisInBody() {
$mock = Mock::double('MailPoet\WP\Emoji', [
'decodeEntities' => function($params) {
return $params;
}
]);
$this->queue->decodeEmojisInBody($this->rendered_body);
$mock->verifyInvokedMultipleTimes('decodeEntities', 2);
}
function _after() {
Mock::clean();
\ORM::raw_execute('TRUNCATE ' . SendingQueue::$_table);
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace MailPoet\Test\WP;
use MailPoet\Config\Env;
use MailPoet\WP\Emoji;
class EmojiTest extends \MailPoetTest {
function _before() {
$this->data_encoded = "Emojis: &#x1f603;&#x1f635;&#x1f4aa;, not emojis: &#046;&#0142;";
$this->data_decoded = "Emojis: 😃😵💪, not emojis: &#046;&#0142;";
$this->column = 'dummycol';
}
function testItCanEncodeForUTF8Column() {
$table = Env::$db_prefix . 'dummytable_utf8';
$this->createTable($table, 'utf8');
$result = Emoji::encodeForUTF8Column($table, $this->column, $this->data_decoded);
expect($result)->equals($this->data_encoded);
$this->dropTable($table);
}
function testItDoesNotEncodeForUTF8MB4Column() {
$table = Env::$db_prefix . 'dummytable_utf8mb4';
$this->createTable($table, 'utf8mb4');
$result = Emoji::encodeForUTF8Column($table, $this->column, $this->data_decoded);
expect($result)->equals($this->data_decoded);
$this->dropTable($table);
}
function testItCanDecodeEntities() {
$result = Emoji::decodeEntities($this->data_encoded);
expect($result)->equals($this->data_decoded);
}
private function createTable($table, $charset) {
\ORM::raw_execute(
'CREATE TABLE IF NOT EXISTS ' . $table
. ' (' . $this->column . ' TEXT) '
. 'DEFAULT CHARSET=' . $charset . ';'
);
}
private function dropTable($table) {
\ORM::raw_execute('DROP TABLE IF EXISTS ' . $table);
}
}