mirror of
https://github.com/roundcube/roundcubemail.git
synced 2026-03-02 14:24:00 +01:00
167 lines
5.5 KiB
PHP
167 lines
5.5 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Emoticons.
|
|
*
|
|
* 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 https://roundcube.net
|
|
*/
|
|
class emoticons extends rcube_plugin
|
|
{
|
|
public $task = 'mail|settings|utils';
|
|
|
|
/**
|
|
* Plugin initialization.
|
|
*/
|
|
#[Override]
|
|
public function init()
|
|
{
|
|
$rcube = rcmail::get_instance();
|
|
|
|
$this->add_hook('message_part_after', [$this, 'message_part_after']);
|
|
$this->add_hook('html_editor', [$this, 'html_editor']);
|
|
|
|
if ($rcube->task == 'settings') {
|
|
$this->add_hook('preferences_list', [$this, 'preferences_list']);
|
|
$this->add_hook('preferences_save', [$this, 'preferences_save']);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 'message_part_after' hook handler to replace common
|
|
* plain text emoticons with emoji
|
|
*/
|
|
public function message_part_after($args)
|
|
{
|
|
if ($args['type'] == 'plain') {
|
|
$this->load_config();
|
|
|
|
$rcube = rcmail::get_instance();
|
|
if (!$rcube->config->get('emoticons_display', false)) {
|
|
return $args;
|
|
}
|
|
|
|
$args['body'] = self::text2icons($args['body']);
|
|
}
|
|
|
|
return $args;
|
|
}
|
|
|
|
/**
|
|
* 'html_editor' hook handler, where we enable emoticons in TinyMCE
|
|
*/
|
|
public function html_editor($args)
|
|
{
|
|
$rcube = rcmail::get_instance();
|
|
|
|
$this->load_config();
|
|
|
|
if ($rcube->config->get('emoticons_compose', true)) {
|
|
$args['extra_plugins'][] = 'emoticons';
|
|
$args['extra_buttons'][] = 'emoticons';
|
|
}
|
|
|
|
return $args;
|
|
}
|
|
|
|
/**
|
|
* 'preferences_list' hook handler
|
|
*/
|
|
public function preferences_list($args)
|
|
{
|
|
$rcube = rcmail::get_instance();
|
|
$dont_override = $rcube->config->get('dont_override', []);
|
|
|
|
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(['name' => '_' . $field_id, 'id' => $field_id, 'value' => 1]);
|
|
|
|
$args['blocks']['main']['options']['emoticons_display'] = [
|
|
'title' => html::label($field_id, $this->gettext('emoticonsdisplay')),
|
|
'content' => $checkbox->show(intval($rcube->config->get('emoticons_display', false))),
|
|
];
|
|
} elseif ($args['section'] == 'compose' && !in_array('emoticons_compose', $dont_override)) {
|
|
$this->load_config();
|
|
$this->add_texts('localization');
|
|
|
|
$field_id = 'emoticons_compose';
|
|
$checkbox = new html_checkbox(['name' => '_' . $field_id, 'id' => $field_id, 'value' => 1]);
|
|
|
|
$args['blocks']['main']['options']['emoticons_compose'] = [
|
|
'title' => html::label($field_id, $this->gettext('emoticonscompose')),
|
|
'content' => $checkbox->show(intval($rcube->config->get('emoticons_compose', true))),
|
|
];
|
|
}
|
|
|
|
return $args;
|
|
}
|
|
|
|
/**
|
|
* 'preferences_save' hook handler
|
|
*/
|
|
public function preferences_save($args)
|
|
{
|
|
if ($args['section'] == 'mailview') {
|
|
$args['prefs']['emoticons_display'] = (bool) rcube_utils::get_input_value('_emoticons_display', rcube_utils::INPUT_POST);
|
|
} elseif ($args['section'] == 'compose') {
|
|
$args['prefs']['emoticons_compose'] = (bool) 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 = [
|
|
'/(?<!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(['title' => $title], "&#x{$ico};");
|
|
}
|
|
}
|