1<?php 2/** 3 * Copyright 2004-2017 Horde LLC (http://www.horde.org/) 4 * 5 * See the enclosed file COPYING for license information (GPL). If you 6 * did not receive this file, see http://www.horde.org/licenses/gpl. 7 * 8 * @category Horde 9 * @copyright 2004-2017 Horde LLC 10 * @license http://www.horde.org/licenses/gpl GPL 11 * @package IMP 12 */ 13 14/** 15 * Message thread display. 16 * Usable in both basic and dynamic views. 17 * 18 * @author Michael Slusarz <slusarz@horde.org> 19 * @category Horde 20 * @copyright 2004-2017 Horde LLC 21 * @license http://www.horde.org/licenses/gpl GPL 22 * @package IMP 23 */ 24class IMP_Basic_Thread extends IMP_Basic_Base 25{ 26 /** 27 */ 28 protected function _init() 29 { 30 global $injector, $notification, $page_output, $registry, $session; 31 32 $imp_mailbox = $this->indices->mailbox->list_ob; 33 34 switch ($mode = $this->vars->get('mode', 'thread')) { 35 case 'thread': 36 /* THREAD MODE: Make sure we have a valid index. */ 37 list($m, $u) = $this->indices->getSingle(); 38 $imp_indices = $imp_mailbox->getFullThread($u, $m); 39 break; 40 41 default: 42 /* MSGVIEW MODE: Make sure we have a valid list of messages. */ 43 $imp_indices = $this->indices; 44 break; 45 } 46 47 if (!count($imp_indices)) { 48 $notification->push(_("Could not load message."), 'horde.error'); 49 $this->indices->mailbox->url('mailbox')->redirect(); 50 } 51 52 /* Run through action handlers. */ 53 switch ($this->vars->actionID) { 54 case 'add_address': 55 try { 56 $contact_link = $injector->getInstance('IMP_Contacts')->addAddress($this->vars->address, $this->vars->name); 57 $notification->push(sprintf(_("Entry \"%s\" was successfully added to the address book"), $contact_link), 'horde.success', array('content.raw')); 58 } catch (Horde_Exception $e) { 59 $notification->push($e); 60 } 61 break; 62 } 63 64 $msgs = $tree = array(); 65 $subject = ''; 66 $page_label = $this->indices->mailbox->label; 67 68 $imp_ui = $injector->getInstance('IMP_Message_Ui'); 69 70 $query = new Horde_Imap_Client_Fetch_Query(); 71 $query->envelope(); 72 73 /* Force images to show in HTML data. */ 74 $injector->getInstance('IMP_Images')->alwaysShow = true; 75 76 $multiple = (count($imp_indices) > 1); 77 78 foreach ($imp_indices as $ob) { 79 $imp_imap = $ob->mbox->imp_imap; 80 $fetch_res = $imp_imap->fetch($ob->mbox, $query, array( 81 'ids' => $imp_imap->getIdsOb($ob->uids) 82 )); 83 84 foreach ($ob->uids as $idx) { 85 $envelope = $fetch_res[$idx]->getEnvelope(); 86 87 /* Get the body of the message. */ 88 $curr_msg = $curr_tree = array(); 89 $contents = $injector->getInstance('IMP_Factory_Contents')->create($ob->mbox->getIndicesOb($idx)); 90 $mime_id = $contents->findBody(); 91 if ($contents->canDisplay($mime_id, IMP_Contents::RENDER_INLINE)) { 92 $ret = $contents->renderMIMEPart($mime_id, IMP_Contents::RENDER_INLINE); 93 $ret = reset($ret); 94 $curr_msg['body'] = $ret['data']; 95 96 if (!empty($ret['js'])) { 97 $page_output->addInlineScript($ret['js'], true); 98 } 99 } else { 100 $curr_msg['body'] = '<em>' . _("There is no text that can be displayed inline.") . '</em>'; 101 } 102 $curr_msg['idx'] = $idx; 103 104 /* Get headers for the message. */ 105 $curr_msg['date'] = $imp_ui->getLocalTime($envelope->date); 106 107 if ($this->indices->mailbox->special_outgoing) { 108 $curr_msg['addr_to'] = true; 109 $curr_msg['addr'] = _("To:") . ' ' . $imp_ui->buildAddressLinks($envelope->to, Horde::selfUrlParams()); 110 $addr = _("To:") . ' ' . htmlspecialchars($envelope->to[0]->label, ENT_COMPAT, 'UTF-8'); 111 } else { 112 $from = $envelope->from; 113 $curr_msg['addr_to'] = false; 114 $curr_msg['addr'] = $imp_ui->buildAddressLinks($from, Horde::selfUrlParams()); 115 $addr = htmlspecialchars($from[0]->label, ENT_COMPAT, 'UTF-8'); 116 } 117 118 $subject_header = htmlspecialchars($envelope->subject, ENT_COMPAT, 'UTF-8'); 119 120 switch ($mode) { 121 case 'thread': 122 if (empty($subject)) { 123 $subject = preg_replace('/^re:\s*/i', '', $subject_header); 124 } 125 $curr_msg['link'] = $multiple 126 ? Horde::widget(array('url' => '#display', 'title' => _("Thread List"), 'nocheck' => true)) 127 : ''; 128 $curr_tree['subject'] = $imp_mailbox->getThreadOb($imp_mailbox->getArrayIndex($fetch_res[$idx]->getUid(), $ob->mbox) + 1)->img; 129 break; 130 131 default: 132 $curr_msg['link'] = Horde::widget(array('url' => '#display', 'title' => _("Back to Multiple Message View Index"), 'nocheck' => true)); 133 $curr_tree['subject'] = ''; 134 break; 135 } 136 137 switch ($registry->getView()) { 138 case $registry::VIEW_BASIC: 139 $curr_msg['link'] .= ' | ' . Horde::widget(array('url' => $this->indices->mailbox->url('message', $idx), 'title' => _("Go to Message"), 'nocheck' => true)) . 140 ' | ' . Horde::widget(array('url' => $this->indices->mailbox->url('mailbox')->add(array('start' => $imp_mailbox->getArrayIndex($idx))), 'title' => sprintf(_("Bac_k to %s"), $page_label))); 141 break; 142 } 143 144 $curr_tree['subject'] .= Horde::link('#i' . $idx) . Horde_String::truncate($subject_header, 60) . '</a> (' . $addr . ')'; 145 146 $msgs[] = $curr_msg; 147 $tree[] = $curr_tree; 148 } 149 } 150 151 /* Flag messages as seen. */ 152 $injector->getInstance('IMP_Message')->flag(array( 153 'add' => array(Horde_Imap_Client::FLAG_SEEN) 154 ), $imp_indices); 155 156 $view = new Horde_View(array( 157 'templatePath' => IMP_TEMPLATES . '/thread' 158 )); 159 160 if ($mode == 'thread') { 161 $view->subject = $subject; 162 $view->thread = true; 163 164 switch ($registry->getView()) { 165 case $registry::VIEW_BASIC: 166 $uid_list = $imp_indices[strval($this->indices->mailbox)]; 167 $delete_link = $this->indices->mailbox->url('mailbox')->add(array( 168 'actionID' => 'delete_messages', 169 'indices' => strval($imp_indices), 170 'token' => $session->getToken(), 171 'start' => $imp_mailbox->getArrayIndex(end($uid_list)) 172 )); 173 $view->delete = Horde::link($delete_link, _("Delete Thread"), null, null, null, null, null, array('id' => 'threaddelete')); 174 $page_output->addInlineScript(array( 175 '$("threaddelete").observe("click", function(e) { if (!window.confirm(' . json_encode(_("Are you sure you want to delete all messages in this thread?")) . ')) { e.stop(); } })' 176 ), true); 177 break; 178 } 179 } else { 180 $view->subject = sprintf(_("%d Messages"), count($msgs)); 181 } 182 $view->messages = $msgs; 183 $view->tree = $tree; 184 185 $page_output->addScriptFile('stripe.js', 'horde'); 186 $page_output->addScriptFile('toggle_quotes.js', 'horde'); 187 $page_output->noDnsPrefetch(); 188 189 $this->output = $view->render('thread'); 190 191 switch ($registry->getView()) { 192 case $registry::VIEW_DYNAMIC: 193 $page_output->topbar = $page_output->sidebar = false; 194 $this->header_params = array( 195 'html_id' => 'htmlAllowScroll' 196 ); 197 break; 198 } 199 200 $this->title = ($mode == 'thread') 201 ? _("Thread View") 202 : _("Multiple Message View"); 203 } 204 205 /** 206 */ 207 public function status() 208 { 209 global $registry; 210 211 return ($registry->getView() == $registry::VIEW_DYNAMIC) 212 ? '' 213 : parent::status(); 214 } 215 216 /** 217 */ 218 static public function url(array $opts = array()) 219 { 220 return Horde::url('basic.php') 221 ->add('page', 'thread') 222 ->unique() 223 ->setRaw(!empty($opts['full'])); 224 } 225 226} 227