Add emoji support to newsletter body [MAILPOET-1009]
This commit is contained in:
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
32
lib/WP/Emoji.php
Normal 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};|[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;
|
||||
}
|
||||
}
|
42
tests/unit/Models/SendingQueueTest.php
Normal file
42
tests/unit/Models/SendingQueueTest.php
Normal 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);
|
||||
}
|
||||
}
|
51
tests/unit/WP/EmojiTest.php
Normal file
51
tests/unit/WP/EmojiTest.php
Normal 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: 😃😵💪, not emojis: .Ž";
|
||||
$this->data_decoded = "Emojis: 😃😵💪, not emojis: .Ž";
|
||||
|
||||
$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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user