Mercurial > hg > rc1
view plugins/thunderbird_labels/thunderbird_labels.php @ 29:ea061c743982
localise title and label exactly once each :-)
author | Charlie Root |
---|---|
date | Sun, 28 Jan 2018 13:44:10 -0500 |
parents | e097905863b9 |
children | b2d0a9781472 |
line wrap: on
line source
<?php /** * Thunderbird Labels Plugin for Roundcube Webmail * * Plugin to show the 5 Message Labels Thunderbird Email-Client provides for IMAP * * @version $Revision$ * @author Michael Kefeder * @url http://code.google.com/p/rcmail-thunderbird-labels/ */ class thunderbird_labels extends rcube_plugin { public $task = 'mail|settings'; private $rc; private $map; function init() { $this->rc = rcmail::get_instance(); $this->load_config(); $this->add_texts('localization/', false); $this->setCustomLabels(); if ($this->rc->task == 'mail') { # -- disable plugin when printing message if ($this->rc->action == 'print') return; if (!$this->rc->config->get('tb_label_enable')) // disable plugin according to prefs return; // how many labels? $max_id = $this->rc->config->get('tb_max_label'); // pass 'tb_max_label', 'tb_label_enable_shortcuts' // and 'tb_label_style' prefs to JS $this->rc->output->set_env('tb_max_label', $max_id); $this->rc->output->set_env('tb_label_enable_shortcuts', $this->rc->config->get('tb_label_enable_shortcuts')); $this->rc->output->set_env('tb_label_style', $this->rc->config->get('tb_label_style')); $this->include_script('tb_label.js'); $this->add_hook('messages_list', array($this, 'read_flags')); $this->add_hook('message_load', array($this, 'read_single_flags')); $this->add_hook('template_object_messageheaders', array($this, 'color_headers')); $this->add_hook('render_page', array($this, 'tblabelpopup')); $this->include_stylesheet($this->local_skin_path() . '/tb_label.css'); $this->name = get_class($this); # -- additional TB flags $this->add_tb_flags = array(); for ($i = 1; $i <= $max_id; $i++) { $this->add_tb_flags['LABEL'.$i]='$Label'.$i; } $this->message_tb_labels = array(); # This builds the toolbar button, but # it's also used by the ctxtmenu initialisation # contextmenu.js:rcube_context_menu to build # the context menu, and that somehow # ends up with display: none??? # Bother, missed it, it's before this.container.show # Afeter ul.appendnd -- inside menu.show on 307 # 567? Yes -- that's calling 'hide', but overriding # doesn't fix :-( #rcube::write_log('lab','add_button'); $this->add_button( array( #'command' => 'plugin.thunderbird_labels.rcm_tb_label_submenu', 'name' => 'tblabellink', 'id' => 'tblabelpopuplink', 'domain' => $this->ID, 'type' => 'link', 'class' => 'button tblabel', 'label' => 'tb_label_button_label', 'title' => 'tb_label_button_title', 'onclick' => "UI.toggle_popup('tblabelpopup',event);return false", 'aria-haspopup' => true, 'aria-expanded' => false, 'aria-owns' => 'plugin.thunderbird_labels.rcm_tb_label_submenu-menu' #'classact' => 'listbutton add', ), 'toolbar' ); // JS function "set_flags" => PHP function "set_flags" $this->register_action('plugin.thunderbird_labels.set_flags', array($this, 'set_flags')); if (method_exists($this, 'require_plugin') && in_array('contextmenu', $this->rc->config->get('plugins')) && $this->require_plugin('contextmenu') && $this->rc->config->get('tb_label_enable_contextmenu')) { if ($this->rc->action == 'list') $this->add_hook('render_mailboxlist', array($this, 'show_tb_label_contextmenu')); #rcube::write_log('lab','ctxt: '.$this->rc->action); } else { #rcube::write_log('lab','no ctxt'); } } elseif ($this->rc->task == 'settings') { $this->include_stylesheet($this->local_skin_path() . '/tb_label.css'); $this->add_hook('preferences_list', array($this, 'prefs_list')); $this->add_hook('preferences_sections_list', array($this, 'prefs_section')); $this->add_hook('preferences_save', array($this, 'prefs_save')); } } private function setCustomLabels() { $c = $this->rc->config->get('tb_label_custom_labels'); if (empty($c)) { // if no user specific labels, use localized strings by default $max_id = $this->rc->config->get('tb_max_label'); $parmLabs = array(); $tb_flag_text = array(); for ($i = 0; $i <= $max_id; $i++) { $lab=$this->getText('label'.$i); $isParm=($lab[-1]=='1'); $lab=substr($lab,0,strlen($lab)-1); $tb_flag_text[$i] = $lab; if ($isParm) { $parmLabs[$i]=strtolower($lab); } } $this->rc->config->set('tb_label_custom_labels', $tb_flag_text); $this->rc->config->set('tb_label_parm_labels', $parmLabs); } // pass label strings to JS $this->rc->output->set_env('tb_label_custom_labels', $this->rc->config->get('tb_label_custom_labels')); $this->rc->output->set_env('tb_label_parm_labels', $this->rc->config->get('tb_label_parm_labels')); } // create a section for the tb-labels Settings public function prefs_section($args) { $args['list']['thunderbird_labels'] = array( 'id' => 'thunderbird_labels', 'section' => rcube::Q($this->gettext('tb_label_options')) ); return $args; } // display thunderbird-labels prefs in Roundcube Settings public function prefs_list($args) { if ($args['section'] != 'thunderbird_labels') return $args; $this->load_config(); $dont_override = (array) $this->rc->config->get('dont_override', array()); $args['blocks']['tb_label'] = array(); $args['blocks']['tb_label']['name'] = $this->gettext('tb_label_options'); $key = 'tb_label_enable'; if (!in_array($key, $dont_override)) { $input = new html_checkbox(array( 'name' => $key, 'id' => $key, 'value' => 1 )); $content = $input->show($this->rc->config->get($key)); $args['blocks']['tb_label']['options'][$key] = array( 'title' => $this->gettext('tb_label_enable_option'), 'content' => $content ); } $key = 'tb_label_enable_shortcuts'; if (!in_array($key, $dont_override)) { $input = new html_checkbox(array( 'name' => $key, 'id' => $key, 'value' => 1 )); $content = $input->show($this->rc->config->get($key)); $args['blocks']['tb_label']['options'][$key] = array( 'title' => $this->gettext('tb_label_enable_shortcuts_option'), 'content' => $content ); } $key = 'tb_label_style'; if (!in_array($key, $dont_override)) { $select = new html_select(array( 'name' => $key, 'id' => $key )); $select->add(array($this->gettext('thunderbird'), $this->gettext('bullets')), array('thunderbird', 'bullets')); $content = $select->show($this->rc->config->get($key)); $args['blocks']['tb_label']['options'][$key] = array( 'title' => $this->gettext('tb_label_style_option'), 'content' => $content ); } $key = 'tb_label_custom_labels'; if (!in_array($key, $dont_override) && $this->rc->config->get('tb_label_modify_labels')) { $old = $this->rc->config->get($key); $oldParms = $this->rc->config->get('tb_label_parm_labels'); $max_id = $this->rc->config->get('tb_max_label'); for($i=1; $i<=$max_id; $i++) { $oldVal = $old[$i]; $oparm=$oldParms[$i]?1:0; $input = new html_inputfield(array( 'name' => $key.$i, 'id' => $key.$i, 'type' => 'text', 'autocomplete' => 'off', 'value' => $oldVal)); $parmBox = new html_checkbox(array( 'name' => $key.$i.'parm', 'id' => $key.$i.'parm', 'value' => 1)); $args['blocks']['tb_label']['options'][$key.$i] = array( 'title' => $this->gettext('tb_label_label')." ".$i, 'content' => $input->show()." ".$parmBox->show($oparm) ); } } return $args; } // save prefs after modified in UI public function prefs_save($args) { #rcube::write_log('lab','saving: '.print_r($args,true)); if ($args['section'] != 'thunderbird_labels') return $args; $this->load_config(); $dont_override = (array) $this->rc->config->get('dont_override', array()); if (!in_array('tb_label_enable', $dont_override)) $args['prefs']['tb_label_enable'] = rcube_utils::get_input_value('tb_label_enable', rcube_utils::INPUT_POST) ? true : false; if (!in_array('tb_label_enable_shortcuts', $dont_override)) $args['prefs']['tb_label_enable_shortcuts'] = rcube_utils::get_input_value('tb_label_enable_shortcuts', rcube_utils::INPUT_POST) ? true : false; if (!in_array('tb_label_style', $dont_override)) $args['prefs']['tb_label_style'] = rcube_utils::get_input_value('tb_label_style', rcube_utils::INPUT_POST); if (!in_array('tb_label_custom_labels', $dont_override) && $this->rc->config->get('tb_label_modify_labels')) { $max_id = $this->rc->config->get('tb_max_label'); $tb_lab_prefs = array(); $tb_parm_prefs = array(); $tb_lab_prefs[0] = $this->gettext('label0'); for ($i = 1; $i <= $max_id; $i++) { $tb_lab_prefs[$i] = rcube_utils::get_input_value('tb_label_custom_labels'.$i, rcube_utils::INPUT_POST); if (rcube_utils::get_input_value('tb_label_custom_labels'.$i.'parm', rcube_utils::INPUT_POST)) { $tb_parm_prefs[$i] = strtolower($tb_lab_prefs[$i]); } } $args['prefs']['tb_label_custom_labels'] = $tb_lab_prefs; $args['prefs']['tb_label_parm_labels'] = $tb_parm_prefs; } return $args; } public function show_tb_label_contextmenu($args) # never called? { #$this->api->output->add_label('copymessage.copyingmessage'); $li = html::tag('li', array('class' => 'submenu'), '<span>'.rcube::Q($this->gettext('tb_label_contextmenu_title')).'</span>' . $this->_gen_label_submenu($args, 'tb_label_ctxm_submenu')); $out .= html::tag('ul', array('id' => 'tb_label_ctxm_mainmenu'), $li); #rcube::write_log('lab',"stblc $out"); $this->api->output->add_footer(html::div(array('style' => 'display: none;'), $out)); } private function _gen_label_submenu($args, $id) # never called? { $out = ''; $custom_labels = $this->rc->config->get('tb_label_custom_labels'); $max_id = $this->rc->config->get('tb_max_label'); for ($i = 0; $i <= $max_id; $i++) { $separator = ($i == 0)? ' separator_below' :''; $out .= '<li class="label'.$i.$separator. ' ctxm_tb_label"><a href="#ctxm_tb_label" class="active" onclick="rcmail_ctxm_label_set('.$i.')"><span>'. $i.' '.$custom_labels[$i]. '</span></a></li>'; } $out = html::tag('ul', array('class' => 'popupmenu toolbarmenu folders', 'id' => $id), $out); return $out; } public function read_single_flags($args) { #rcube::write_log($this->name, print_r(($args['object']), true)); if (!isset($args['object'])) { return; } if (is_array($args['object']->headers->flags)) { $this->message_tb_labels = array(); foreach ($args['object']->headers->flags as $flagname => $flagvalue) { $flag = is_numeric("$flagvalue")? $flagname:$flagvalue;// for compatibility with < 0.5.4 $flag = strtolower($flag); if (preg_match('/^\$?label/', $flag)) { $flag_no = preg_replace('/^\$?label/', '', $flag); #rcube::write_log($this->name, "Single message Flag: ".$flag." Flag_no:".$flag_no); $this->message_tb_labels[] = (int)$flag_no; } } } # -- no return value for this hook } /** * Writes labelnumbers for single message display * Coloring of Message header table happens via Javascript */ public function color_headers($p) { #rcube::write_log($this->name, print_r($p, true)); # -- always write array, even when empty $p['content'] .= '<script type="text/javascript"> var tb_labels_for_message = ['.join(',', $this->message_tb_labels).']; </script>'; return $p; } public function read_flags($args) { // add color information for all messages // dont loop over all messages if we dont have any highlights or no msgs if (!isset($args['messages']) or !is_array($args['messages'])) { return $args; } // loop over all messages and add $LabelX info to the extra_flags $mbox = $this->rc->output->get_env('mailbox') ?: $this->rc->storage->get_folder(); #rcube::write_log($this->name, "mbox: $mbox"); foreach($args['messages'] as $message) { $message->list_flags['extra_flags']['tb_labels'] = array(); # always set extra_flags, needed for javascript later! $message->list_flags['extra_flags']['tb_lparms'] = array(); $keyPos = array_search($_SESSION['sort_col'],$this->rc->config->get('tb_label_parm_labels')); #rcube::write_log($this->name,"sort? $keyPos ".$_SESSION['sort_order']." ".print_r($this->rc->config->get('tb_label_parm_labels'),true)); if (is_array($message->flags)) foreach ($message->flags as $flagname => $flagvalue) { $flag = is_numeric("$flagvalue")? $flagname:$flagvalue;// for compatibility with < 0.5.4 $flag = strtolower($flag); if (preg_match('/^\$?label/', $flag)) { $flag_no = preg_replace('/^\$?label/', '', $flag); #rcube::write_log($this->name, "Flag:".$flag." Flag_no:".$flag_no); if ($ppos = strpos($flag_no,'_') > -1) { // We have a flag parameter value... $pn=(int)substr($flag_no,0,$ppos); $pv=substr($flag_no,$ppos+1); $message->list_flags['extra_flags']['tb_lparms'][]=array( 'number' => $pn, 'parm' => $pv); if ($keyPos && $message->depth==0) { $message->sortKey=array_map('intval',preg_split('#[/-]#',$pv)); } } else { $message->list_flags['extra_flags']['tb_labels'][] = (int)$flag_no; } } } } if ($keyPos) { $rev = $_SESSION['sort_order']=='DESC'; $datesSort = function($a, $b) use ($rev) { if ($ak=$a->sortKey) { if ($bk=$b->sortKey) { // each key is sd sm ed em if ($ak[1]<$bk[1]) return $rev?1:-1; if ($ak[1]>$bk[1]) return $rev?-1:1; // start month is the same if ($ak[0]<$bk[0]) return $rev?1:-1; if ($ak[0]>$bk[0]) return $rev?-1:1; // start date is the same if ($ak[3]<$bk[3]) return $rev?1:-1; if ($ak[3]>$bk[3]) return $rev?-1:1; // end month is the same if ($ak[2]<$bk[2]) return $rev?1:-1; if ($ak[2]>$bk[2]) return $rev?-1:1; // both dates are the same return 0; } else { return $rev?1:-1; } } else if ($b->sortKey) { return $rev?-1:1; } else { return 0; } }; if ($this->rc->config->get('message_threading')[$mbox]) { // The threading information is contained in three fields: // depth, parent_uid and uid // I _think_ if you gave every depth0 message its dates as key // every depth>0 [already sorted by date, see list.inc:71] // Then first sort all the depth0 messages into a new array // then iterate over them, pull all depth1 with shared parent // insert after parent // repeat at depth 1, etc. $sm = array(); // sorted result accumulates here $rm = array(); // unprocessed remnant foreach ($args['messages'] as $m) { if ($m->depth===0) { $sm[]=$m; } else { $rm[]=$m; } } #rcube::write_log($this->name,"ts0: |".$rm[0]->depth."| |".($rm[0]->depth===0)."|"); usort($sm,$datesSort); $depth=0; $foundSome=true; while ($foundSome) { #rcube::write_log($this->name,"ts: $depth ".count($sm).' '.count($rm)); $foundSome=false; $tsm = array(); $trm = array(); foreach ($sm as $m) { $tsm[]=$m; if ($m->depth===$depth) { $puid = $m->uid; foreach ($rm as $c) { if ($c->parent_uid===$puid) { $tsm[]=$c; $foundSome=true; } else { $trm[]=$c; } } $rm = $trm; $trm = array(); } } $sm = $tsm; $depth+=1; } $args['messages']=$sm; } else { usort($args['messages'],$datesSort); } } return($args); } // set flags in IMAP server function set_flags() { #rcube::write_log($this->name, "set: ".print_r($_GET, true)); $imap = $this->rc->imap; $cbox = rcube_utils::get_input_value('_cur', rcube_utils::INPUT_GET); $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GET); $toggle_label = rcube_utils::get_input_value('_toggle_label', rcube_utils::INPUT_GET); $flag_uids = rcube_utils::get_input_value('_flag_uids', rcube_utils::INPUT_GET); $flag_uids = explode(',', $flag_uids); $unflag_uids = rcube_utils::get_input_value('_unflag_uids', rcube_utils::INPUT_GET); $unflag_uids = explode(',', $unflag_uids); $imap->conn->flags = array_merge($imap->conn->flags, $this->add_tb_flags); #rcube::write_log($this->name, print_r($flag_uids, true)); #rcube::write_log($this->name, print_r($unflag_uids, true)); if (!is_array($unflag_uids) || !is_array($flag_uids)) return false; $imap->set_flag($flag_uids, $toggle_label, $mbox); // belt and braces if (count($unflag_uids)>0) { $flaggedMsgs = $imap->list_flags($mbox,$unflag_uids); #rcube::write_log($this->name,'oldFlags: '.print_r($flaggedMsgs,true)); $fullFlags=array(); foreach ($flaggedMsgs as $uid => $flags) { foreach ($flags as $flag => $x) { $pos=strpos(strtolower($flag),$toggle_label); #rcube::write_log($this->name,"flag?: $flag $toggle_label $pos"); if ($pos>-1 && $pos<2 && !in_array($flag,$fullFlags)) { $fullFlags[]=$flag; } } } if (count($fullFlags)==0) { #rcube::write_log('errors',"no full flags for $toggle_label in ".print_r($flaggedMsgs,true)); $imap->set_flag($unflag_uids, "UN$toggle_label", $mbox); } else { foreach ($fullFlags as $flag) { #rcube::write_log($this->name,"UNsetting $flag in $mbox for ".join(',',$unflag_uids)); $imap->set_flag($unflag_uids, "UN$flag", $mbox); } } } $this->api->output->send(); } function tblabelpopup() { $custom_labels = $this->rc->config->get('tb_label_custom_labels'); $max_id = $this->rc->config->get('tb_max_label'); $out = '<div id="tblabelpopup" class="popupmenu"> <ul class="toolbarmenu">'; for ($i = 0; $i <= $max_id; $i++) { $separator = ($i == 0)? ' separator_below' :''; $out .= '<li class="label'.$i.$separator.'"><a href="#" id="tblabel'.$i.'" class="active">'.$i.' '.$custom_labels[$i].'</a></li>'; } $out .= '</ul> </div>'; $this->rc->output->add_gui_object('tblabelpopup_obj', 'tblabelpopup'); #rcube::write_log('lab',"tblp $out"); $this->rc->output->add_footer($out); } }