diff options
author | Aleksander Machniak <alec@alec.pl> | 2020-07-11 19:46:17 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-11 19:46:17 +0300 |
commit | cd3cad6aae1163dbe2af837d227d88c491c5c6a3 (patch) | |
tree | 25bca3836018b035c3f37807ab46ebba534f3d63 /plugins/emoticons | |
parent | 36bf280a97d983553d90da00ea5d51ccb912e54b (diff) |
TinyMCE 5 (#7403)
Diffstat (limited to 'plugins/emoticons')
-rw-r--r-- | plugins/emoticons/composer.json | 2 | ||||
-rw-r--r-- | plugins/emoticons/emoticons.php | 128 | ||||
-rw-r--r-- | plugins/emoticons/emoticons_engine.php | 152 | ||||
-rw-r--r-- | plugins/emoticons/localization/en_US.inc | 2 | ||||
-rw-r--r-- | plugins/emoticons/tests/EmoticonsEngine.php | 48 |
5 files changed, 56 insertions, 276 deletions
diff --git a/plugins/emoticons/composer.json b/plugins/emoticons/composer.json index 30dd3928e..fa0f41ea5 100644 --- a/plugins/emoticons/composer.json +++ b/plugins/emoticons/composer.json @@ -3,7 +3,7 @@ "type": "roundcube-plugin", "description": "Plugin that adds emoticons support.", "license": "GPLv3+", - "version": "2.0", + "version": "3.0", "authors": [ { "name": "Thomas Bruederli", diff --git a/plugins/emoticons/emoticons.php b/plugins/emoticons/emoticons.php index 4eefed873..bc76017eb 100644 --- a/plugins/emoticons/emoticons.php +++ b/plugins/emoticons/emoticons.php @@ -1,15 +1,15 @@ <?php /** - * Emoticons + * Emoticons. * - * Plugin to replace emoticons in plain text message body with real icons. + * Plugin to replace emoticons in plain text message body with real emoji. * Also it enables emoticons in HTML compose editor. Both features are optional. * * @license GNU GPLv3+ * @author Thomas Bruederli * @author Aleksander Machniak - * @website http://roundcube.net + * @website https://roundcube.net */ class emoticons extends rcube_plugin { @@ -24,8 +24,6 @@ class emoticons extends rcube_plugin $rcube = rcube::get_instance(); $this->add_hook('message_part_after', array($this, 'message_part_after')); - $this->add_hook('message_outgoing_body', array($this, 'message_outgoing_body')); - $this->add_hook('html2text', array($this, 'html2text')); $this->add_hook('html_editor', array($this, 'html_editor')); if ($rcube->task == 'settings') { @@ -35,8 +33,8 @@ class emoticons extends rcube_plugin } /** - * 'message_part_after' hook handler to replace common plain text emoticons - * with emoticon images (<img>) + * 'message_part_after' hook handler to replace common + * plain text emoticons with emoji */ function message_part_after($args) { @@ -48,65 +46,7 @@ class emoticons extends rcube_plugin return $args; } - require_once __DIR__ . '/emoticons_engine.php'; - - $args['body'] = emoticons_engine::text2icons($args['body']); - } - - return $args; - } - - /** - * 'message_outgoing_body' hook handler to replace image emoticons from TinyMCE - * editor with image attachments. - */ - function message_outgoing_body($args) - { - if ($args['type'] == 'html') { - $this->load_config(); - - $rcube = rcube::get_instance(); - if (!$rcube->config->get('emoticons_compose', true)) { - return $args; - } - - require_once __DIR__ . '/emoticons_engine.php'; - - // look for "emoticon" images from TinyMCE and change their src paths to - // be file paths on the server instead of URL paths. - $images = emoticons_engine::replace($args['body']); - - // add these images as attachments to the MIME message - foreach ($images as $img_name => $img_file) { - $args['message']->addHTMLImage($img_file, 'image/gif', '', true, $img_name); - } - } - - return $args; - } - - /** - * 'html2text' hook handler to replace image emoticons from TinyMCE - * editor with plain text emoticons. - * - * This is executed on html2text action, i.e. when switching from HTML to text - * in compose window (or similar place). Also when generating alternative - * text/plain part. - */ - function html2text($args) - { - $rcube = rcube::get_instance(); - - if ($rcube->action == 'html2text' || $rcube->action == 'send') { - $this->load_config(); - - if (!$rcube->config->get('emoticons_compose', true)) { - return $args; - } - - require_once __DIR__ . '/emoticons_engine.php'; - - $args['body'] = emoticons_engine::icons2text($args['body']); + $args['body'] = self::text2icons($args['body']); } return $args; @@ -170,16 +110,58 @@ class emoticons extends rcube_plugin */ function preferences_save($args) { - $rcube = rcube::get_instance(); - $dont_override = $rcube->config->get('dont_override', array()); - - if ($args['section'] == 'mailview' && !in_array('emoticons_display', $dont_override)) { - $args['prefs']['emoticons_display'] = rcube_utils::get_input_value('_emoticons_display', rcube_utils::INPUT_POST) ? true : false; + if ($args['section'] == 'mailview') { + $args['prefs']['emoticons_display'] = !empty(rcube_utils::get_input_value('_emoticons_display', rcube_utils::INPUT_POST)); } - else if ($args['section'] == 'compose' && !in_array('emoticons_compose', $dont_override)) { - $args['prefs']['emoticons_compose'] = rcube_utils::get_input_value('_emoticons_compose', rcube_utils::INPUT_POST) ? true : false; + else if ($args['section'] == 'compose') { + $args['prefs']['emoticons_compose'] = !empty(rcube_utils::get_input_value('_emoticons_compose', rcube_utils::INPUT_POST)); } return $args; } + + /** + * Replace common plain text emoticons with emoji + * + * @param string $text Text + * + * @return string Converted text + */ + protected static function text2icons($text) + { + // This is a lookbehind assertion which will exclude html entities + // E.g. situation when ";)" in "")" shouldn't be replaced by the icon + // It's so long because of assertion format restrictions + $entity = '(?<!&' + . '[a-zA-Z0-9]{2}' . '|' . '#[0-9]{2}' . '|' + . '[a-zA-Z0-9]{3}' . '|' . '#[0-9]{3}' . '|' + . '[a-zA-Z0-9]{4}' . '|' . '#[0-9]{4}' . '|' + . '[a-zA-Z0-9]{5}' . '|' + . '[a-zA-Z0-9]{6}' . '|' + . '[a-zA-Z0-9]{7}' + . ')'; + + // map of emoticon replacements + $map = array( + '/(?<!mailto):-?D/' => self::ico_tag('1f603', ':D' ), // laugh + '/:-?\(/' => self::ico_tag('1f626', ':(' ), // frown + '/'.$entity.';-?\)/' => self::ico_tag('1f609', ';)' ), // wink + '/8-?\)/' => self::ico_tag('1f60e', '8)' ), // cool + '/(?<!mailto):-?O/i' => self::ico_tag('1f62e', ':O' ), // surprised + '/(?<!mailto):-?P/i' => self::ico_tag('1f61b', ':P' ), // tongue out + '/(?<!mailto):-?@/i' => self::ico_tag('1f631', ':-@' ), // yell + '/O:-?\)/i' => self::ico_tag('1f607', 'O:-)' ), // innocent + '/(?<!O):-?\)/' => self::ico_tag('1f60a', ':-)' ), // smile + '/(?<!mailto):-?\$/' => self::ico_tag('1f633', ':-$' ), // embarrassed + '/(?<!mailto):-?\*/i' => self::ico_tag('1f48b', ':-*' ), // kiss + '/(?<!mailto):-?S/i' => self::ico_tag('1f615', ':-S' ), // undecided + ); + + return preg_replace(array_keys($map), array_values($map), $text); + } + + protected static function ico_tag($ico, $title) + { + return html::span(array('title' => $title), "&#x{$ico};"); + } } diff --git a/plugins/emoticons/emoticons_engine.php b/plugins/emoticons/emoticons_engine.php deleted file mode 100644 index 4d534cdc1..000000000 --- a/plugins/emoticons/emoticons_engine.php +++ /dev/null @@ -1,152 +0,0 @@ -<?php - -/** - * @license GNU GPLv3+ - * @author Thomas Bruederli - * @author Aleksander Machniak - */ -class emoticons_engine -{ - const IMG_PATH = 'program/js/tinymce/plugins/emoticons/img/'; - - /** - * Replaces TinyMCE's emoticon images with plain-text representation - * - * @param string $html HTML content - * - * @return string HTML content - */ - public static function icons2text($html) - { - $emoticons = array( - '8-)' => 'smiley-cool', - ':-#' => 'smiley-foot-in-mouth', - ':-*' => 'smiley-kiss', - ':-X' => 'smiley-sealed', - ':-P' => 'smiley-tongue-out', - ':-@' => 'smiley-yell', - ":'(" => 'smiley-cry', - ':-(' => 'smiley-frown', - ':-D' => 'smiley-laughing', - ':-)' => 'smiley-smile', - ':-S' => 'smiley-undecided', - ':-$' => 'smiley-embarassed', - 'O:-)' => 'smiley-innocent', - ':-|' => 'smiley-money-mouth', - ':-O' => 'smiley-surprised', - ';-)' => 'smiley-wink', - ); - - foreach ($emoticons as $idx => $file) { - // <img title="Cry" src="http://.../program/js/tinymce/plugins/emoticons/img/smiley-cry.gif" border="0" alt="Cry" /> - $file = preg_quote(self::IMG_PATH . $file . '.gif', '/'); - $search[] = '/<img (title="[a-z ]+" )?src="[^"]+' . $file . '"[^>]+\/>/i'; - $replace[] = $idx; - } - - return preg_replace($search, $replace, $html); - } - - /** - * Replace common plain text emoticons with empticon <img> tags - * - * @param string $text Text - * - * @return string Converted text - */ - public static function text2icons($text) - { - // This is a lookbehind assertion which will exclude html entities - // E.g. situation when ";)" in "")" shouldn't be replaced by the icon - // It's so long because of assertion format restrictions - $entity = '(?<!&' - . '[a-zA-Z0-9]{2}' . '|' . '#[0-9]{2}' . '|' - . '[a-zA-Z0-9]{3}' . '|' . '#[0-9]{3}' . '|' - . '[a-zA-Z0-9]{4}' . '|' . '#[0-9]{4}' . '|' - . '[a-zA-Z0-9]{5}' . '|' - . '[a-zA-Z0-9]{6}' . '|' - . '[a-zA-Z0-9]{7}' - . ')'; - - // map of emoticon replacements - $map = array( - '/(?<!mailto):D/' => self::img_tag('smiley-laughing.gif', ':D' ), - '/:-D/' => self::img_tag('smiley-laughing.gif', ':-D' ), - '/:\(/' => self::img_tag('smiley-frown.gif', ':(' ), - '/:-\(/' => self::img_tag('smiley-frown.gif', ':-(' ), - '/'.$entity.';\)/' => self::img_tag('smiley-wink.gif', ';)' ), - '/'.$entity.';-\)/' => self::img_tag('smiley-wink.gif', ';-)' ), - '/8\)/' => self::img_tag('smiley-cool.gif', '8)' ), - '/8-\)/' => self::img_tag('smiley-cool.gif', '8-)' ), - '/(?<!mailto):O/i' => self::img_tag('smiley-surprised.gif', ':O' ), - '/(?<!mailto):-O/i' => self::img_tag('smiley-surprised.gif', ':-O' ), - '/(?<!mailto):P/i' => self::img_tag('smiley-tongue-out.gif', ':P' ), - '/(?<!mailto):-P/i' => self::img_tag('smiley-tongue-out.gif', ':-P' ), - '/(?<!mailto):@/i' => self::img_tag('smiley-yell.gif', ':@' ), - '/(?<!mailto):-@/i' => self::img_tag('smiley-yell.gif', ':-@' ), - '/O:\)/i' => self::img_tag('smiley-innocent.gif', 'O:)' ), - '/O:-\)/i' => self::img_tag('smiley-innocent.gif', 'O:-)' ), - '/(?<!O):\)/' => self::img_tag('smiley-smile.gif', ':)' ), - '/(?<!O):-\)/' => self::img_tag('smiley-smile.gif', ':-)' ), - '/(?<!mailto):\$/' => self::img_tag('smiley-embarassed.gif', ':$' ), - '/(?<!mailto):-\$/' => self::img_tag('smiley-embarassed.gif', ':-$' ), - '/(?<!mailto):\*/i' => self::img_tag('smiley-kiss.gif', ':*' ), - '/(?<!mailto):-\*/i' => self::img_tag('smiley-kiss.gif', ':-*' ), - '/(?<!mailto):S/i' => self::img_tag('smiley-undecided.gif', ':S' ), - '/(?<!mailto):-S/i' => self::img_tag('smiley-undecided.gif', ':-S' ), - ); - - return preg_replace(array_keys($map), array_values($map), $text); - } - - protected static function img_tag($ico, $title) - { - return html::img(array('src' => './' . self::IMG_PATH . $ico, 'title' => $title)); - } - - /** - * Replace emoticon icons <img> 'src' attribute, so it can - * be replaced with real file by Mail_Mime. - * - * @param string &$html HTML content - * - * @return array List of image files - */ - public static function replace(&$html) - { - // Replace this: - // <img src="http[s]://.../tinymce/plugins/emoticons/img/smiley-cool.gif" ... /> - // with this: - // <img src="/path/on/server/.../tinymce/plugins/emoticons/img/smiley-cool.gif" ... /> - - $rcube = rcube::get_instance(); - $assets_dir = $rcube->config->get('assets_dir'); - $path = unslashify($assets_dir ?: INSTALL_PATH) . '/' . self::IMG_PATH; - $offset = 0; - $images = array(); - - // remove any null-byte characters before parsing - $html = preg_replace('/\x00/', '', $html); - - if (preg_match_all('# src=[\'"]([^\'"]+)#', $html, $matches, PREG_OFFSET_CAPTURE)) { - foreach ($matches[1] as $m) { - // find emoticon image tags - if (preg_match('#'. self::IMG_PATH . '(.*)$#', $m[0], $imatches)) { - $image_name = $imatches[1]; - - // sanitize image name so resulting attachment doesn't leave images dir - $image_name = preg_replace('/[^a-zA-Z0-9_\.\-]/i', '', $image_name); - $image_file = $path . $image_name; - - // Add the same image only once - $images[$image_name] = $image_file; - - $html = substr_replace($html, $image_file, $m[1] + $offset, strlen($m[0])); - $offset += strlen($image_file) - strlen($m[0]); - } - } - } - - return $images; - } -} diff --git a/plugins/emoticons/localization/en_US.inc b/plugins/emoticons/localization/en_US.inc index c1ab1dab8..c1f65d566 100644 --- a/plugins/emoticons/localization/en_US.inc +++ b/plugins/emoticons/localization/en_US.inc @@ -17,5 +17,3 @@ $labels = array(); $labels['emoticonsdisplay'] = 'Display emoticons in plain text messages'; $labels['emoticonscompose'] = 'Enable emoticons'; - -?> diff --git a/plugins/emoticons/tests/EmoticonsEngine.php b/plugins/emoticons/tests/EmoticonsEngine.php deleted file mode 100644 index 58ad0668c..000000000 --- a/plugins/emoticons/tests/EmoticonsEngine.php +++ /dev/null @@ -1,48 +0,0 @@ -<?php - -class EmoticonsEngine extends PHPUnit\Framework\TestCase -{ - - function setUp() - { - include_once __DIR__ . '/../emoticons_engine.php'; - } - - /** - * text2icons() method tests - */ - function test_text2icons() - { - $map = array( - ':D' => array('smiley-laughing.gif', ':D' ), - ':-D' => array('smiley-laughing.gif', ':-D' ), - ':(' => array('smiley-frown.gif', ':(' ), - ':-(' => array('smiley-frown.gif', ':-(' ), - '8)' => array('smiley-cool.gif', '8)' ), - '8-)' => array('smiley-cool.gif', '8-)' ), - ':O' => array('smiley-surprised.gif', ':O' ), - ':-O' => array('smiley-surprised.gif', ':-O' ), - ':P' => array('smiley-tongue-out.gif', ':P' ), - ':-P' => array('smiley-tongue-out.gif', ':-P' ), - ':@' => array('smiley-yell.gif', ':@' ), - ':-@' => array('smiley-yell.gif', ':-@' ), - 'O:)' => array('smiley-innocent.gif', 'O:)' ), - 'O:-)' => array('smiley-innocent.gif', 'O:-)' ), - ':)' => array('smiley-smile.gif', ':)' ), - ':-)' => array('smiley-smile.gif', ':-)' ), - ':$' => array('smiley-embarassed.gif', ':$' ), - ':-$' => array('smiley-embarassed.gif', ':-$' ), - ':*' => array('smiley-kiss.gif', ':*' ), - ':-*' => array('smiley-kiss.gif', ':-*' ), - ':S' => array('smiley-undecided.gif', ':S' ), - ':-S' => array('smiley-undecided.gif', ':-S' ), - ); - - foreach ($map as $body => $expected) { - $result = emoticons_engine::text2icons($body); - - $this->assertRegExp('/' . preg_quote($expected[0], '/') . '/', $result); - $this->assertRegExp('/title="' . preg_quote($expected[1], '/') . '"/', $result); - } - } -} |