From a63f14ec4045e82f47b237663bcf09939a0eadc5 Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Sat, 29 Aug 2015 01:52:57 -0400
Subject: [PATCH] Emoticons-related code refactoring

---
 plugins/emoticons/emoticons.php |  208 +++++++++++++++++++++++++++++++++++++++------------
 1 files changed, 158 insertions(+), 50 deletions(-)

diff --git a/plugins/emoticons/emoticons.php b/plugins/emoticons/emoticons.php
index f3f987a..cb90b6f 100644
--- a/plugins/emoticons/emoticons.php
+++ b/plugins/emoticons/emoticons.php
@@ -1,9 +1,10 @@
 <?php
 
 /**
- * Display Emoticons
+ * Emoticons
  *
- * Sample plugin to replace emoticons in plain text message body with real icons
+ * Plugin to replace emoticons in plain text message body with real icons.
+ * Also it enables emoticons in HTML compose editor. Both features are optional.
  *
  * @version @package_version@
  * @license GNU GPLv3+
@@ -13,66 +14,173 @@
  */
 class emoticons extends rcube_plugin
 {
-    public $task = 'mail';
+    public $task = 'mail|settings|utils';
 
+
+    /**
+     * Plugin initilization.
+     */
     function init()
     {
-        $this->add_hook('message_part_after', array($this, 'replace'));
+        $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') {
+            $this->add_hook('preferences_list', array($this, 'preferences_list'));
+            $this->add_hook('preferences_save', array($this, 'preferences_save'));
+        }
     }
 
-    function replace($args)
+    /**
+     * 'message_part_after' hook handler to replace common plain text emoticons
+     * with emoticon images (<img>)
+     */
+    function message_part_after($args)
     {
-        // This is a lookbehind assertion which will exclude html entities
-        // E.g. situation when ";)" in "&quot;)" 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/'   => $this->img_tag('smiley-laughing.gif',    ':D'    ),
-            '/:-D/'             => $this->img_tag('smiley-laughing.gif',    ':-D'   ),
-            '/:\(/'             => $this->img_tag('smiley-frown.gif',       ':('    ),
-            '/:-\(/'            => $this->img_tag('smiley-frown.gif',       ':-('   ),
-            '/'.$entity.';\)/'  => $this->img_tag('smiley-wink.gif',        ';)'    ),
-            '/'.$entity.';-\)/' => $this->img_tag('smiley-wink.gif',        ';-)'   ),
-            '/8\)/'             => $this->img_tag('smiley-cool.gif',        '8)'    ),
-            '/8-\)/'            => $this->img_tag('smiley-cool.gif',        '8-)'   ),
-            '/(?<!mailto):O/i'  => $this->img_tag('smiley-surprised.gif',   ':O'    ),
-            '/(?<!mailto):-O/i' => $this->img_tag('smiley-surprised.gif',   ':-O'   ),
-            '/(?<!mailto):P/i'  => $this->img_tag('smiley-tongue-out.gif',  ':P'    ),
-            '/(?<!mailto):-P/i' => $this->img_tag('smiley-tongue-out.gif',  ':-P'   ),
-            '/(?<!mailto):@/i'  => $this->img_tag('smiley-yell.gif',        ':@'    ),
-            '/(?<!mailto):-@/i' => $this->img_tag('smiley-yell.gif',        ':-@'   ),
-            '/O:\)/i'           => $this->img_tag('smiley-innocent.gif',    'O:)'   ),
-            '/O:-\)/i'          => $this->img_tag('smiley-innocent.gif',    'O:-)'  ),
-            '/(?<!O):\)/'       => $this->img_tag('smiley-smile.gif',       ':)'    ),
-            '/(?<!O):-\)/'      => $this->img_tag('smiley-smile.gif',       ':-)'   ),
-            '/(?<!mailto):\$/'  => $this->img_tag('smiley-embarassed.gif',  ':$'    ),
-            '/(?<!mailto):-\$/' => $this->img_tag('smiley-embarassed.gif',  ':-$'   ),
-            '/(?<!mailto):\*/i'  => $this->img_tag('smiley-kiss.gif',       ':*'    ),
-            '/(?<!mailto):-\*/i' => $this->img_tag('smiley-kiss.gif',       ':-*'   ),
-            '/(?<!mailto):S/i'  => $this->img_tag('smiley-undecided.gif',   ':S'    ),
-            '/(?<!mailto):-S/i' => $this->img_tag('smiley-undecided.gif',   ':-S'   ),
-        );
-
         if ($args['type'] == 'plain') {
-            $args['body'] = preg_replace(
-                array_keys($map), array_values($map), $args['body']);
+            $this->load_config();
+
+            $rcube = rcube::get_instance();
+            if (!$rcube->config->get('emoticons_display', false)) {
+                return $args;
+            }
+
+            require_once __DIR__ . '/emoticons_engine.php';
+
+            $args['body'] = emoticons_engine::text2icons($args['body']);
         }
 
         return $args;
     }
 
-    private function img_tag($ico, $title)
+    /**
+     * 'message_outgoing_body' hook handler to replace image emoticons from TinyMCE
+     * editor with image attachments.
+     */
+    function message_outgoing_body($args)
     {
-        $path = './program/js/tinymce/plugins/emoticons/img/';
-        return html::img(array('src' => $path.$ico, 'title' => $title));
+        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 similiar 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']);
+        }
+
+        return $args;
+    }
+
+    /**
+     * 'html_editor' hook handler, where we enable emoticons in TinyMCE
+     */
+    function html_editor($args)
+    {
+        $rcube = rcube::get_instance();
+
+        $this->load_config();
+
+        if (!$rcube->config->get('emoticons_compose', true)) {
+            $args['disabled_plugins'][] = 'emoticons';
+            $args['disabled_buttons'][] = 'emoticons';
+        }
+
+        return $args;
+    }
+
+    /**
+     * 'preferences_list' hook handler
+     */
+    function preferences_list($args)
+    {
+        $rcube         = rcube::get_instance();
+        $dont_override = $rcube->config->get('dont_override', array());
+
+        if ($args['section'] == 'mailview' && !in_array('emoticons_display', $dont_override)) {
+            $this->load_config();
+            $this->add_texts('localization');
+
+            $field_id = 'emoticons_display';
+            $checkbox = new html_checkbox(array('name' => '_' . $field_id, 'id' => $field_id, 'value' => 1));
+
+            $args['blocks']['main']['options']['emoticons_display'] = array(
+                    'title'   => $this->gettext('emoticonsdisplay'),
+                    'content' => $checkbox->show(intval($rcube->config->get('emoticons_display', false)))
+            );
+        }
+        else if ($args['section'] == 'compose' && !in_array('emoticons_compose', $dont_override)) {
+            $this->load_config();
+            $this->add_texts('localization');
+
+            $field_id = 'emoticons_compose';
+            $checkbox = new html_checkbox(array('name' => '_' . $field_id, 'id' => $field_id, 'value' => 1));
+
+            $args['blocks']['main']['options']['emoticons_compose'] = array(
+                    'title'   => $this->gettext('emoticonscompose'),
+                    'content' => $checkbox->show(intval($rcube->config->get('emoticons_compose', true)))
+            );
+        }
+
+        return $args;
+    }
+
+    /**
+     * 'preferences_save' hook handler
+     */
+    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;
+        }
+        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;
+        }
+
+        return $args;
     }
 }

--
Gitblit v1.9.1